Forfatter |
Emne Søg Emne funktioner
|
anthonsen
Forum Begynder
Medlem: 21.Jun.2016
Status: Offline
Point: 12
|
Emne: Gem som i nyt format Sendt: 06.Jul.2016 kl. 11:06 |
Hej igen Jeg har følgende udfordring som jeg håber nogle kan hjælpe med: Jeg har en makro til at køre, og i slutningen af denne vil jeg gerne have den til at gemme en ny version af projektmappen. Det skal dog være i .xslx i stedet for .xslm, og når den er gemt, vil jeg gerne have åbnet .xslm udgaven igen. Hvis man derudover kan vælge navnet på den nye fil ud fra værdien i en bestemt celle vil jeg være lykkelig. På forhånd mange tak /Lasse
|
|
|
|
|
BQardi
Bronze bruger
Medlem: 11.Nov.2016
Land: Danmark
Status: Offline
Point: 100
|
Sendt: 13.Nov.2016 kl. 19:18 |
Bedre sent end aldrig
Dette stykke kode skulle gøre hvad du er ude efter:
Sub DinMakro() 'Din kode
'Sæt den rigtige reference til din celle ind her (fane-navn og celle-adresse): GemKopi Worksheets("Ark1").Range("A1").Value End Sub
Sub GemKopi(SaveName As String) Dim wbPath As String, ws As Worksheet, arr() As String ReDim arr(0 To (Worksheets.Count) - 1) wbPath = ThisWorkbook.Path If Not Right(wbPath, 1) = "\" Then wbPath = wbPath & "\" For Each ws In Worksheets arr(ws.Index - 1) = ws.Name Next ws Worksheets(arr).Copy Application.DisplayAlerts = False With ActiveWorkbook .SaveAs wbPath & SaveName & ".xlsx", xlOpenXMLWorkbook .Close False End With Application.DisplayAlerts = True ThisWorkbook.Activate End Sub
|
|
|
EXCELGAARD
Platin bruger
Medlem: 27.Dec.2012
Land: Denmark
Status: Offline
Point: 5419
|
Sendt: 13.Nov.2016 kl. 20:08 |
Næsten... Hva' nu, hvis filen indeholder diagrammer? Og, husk nu, at rydde op efter dig, når du er færdig
|
Husk, at trykke på [Tak], hvis du kan lide et indlæg. Husk, at trykke på [Accepteret Svar], hvis du kan bruge et løsningsforslag.
|
|
BQardi
Bronze bruger
Medlem: 11.Nov.2016
Land: Danmark
Status: Offline
Point: 100
|
Sendt: 13.Nov.2016 kl. 21:53 |
EXCELGAARD skrev:
Næsten... Hva' nu, hvis filen indeholder diagrammer? Og, husk nu, at rydde op efter dig, når du er færdig
|
Den havde jeg ikke tænkt over. Jeg er dog stadig i en indlærings proces vedrørende at være forudseende overfor eventuelle fejl Mht. diagrammerne, så kunne jeg ikke få dem til at "ligge" i samme rækkefølge som original-arket. Måske du har en løsning til det? Eller en anden løsning der er bedre/enklere? Jeg går i hvert fald lige i tænkeboks over den her. Den er lidt mere hardcore end jeg havde regnet med, eller også har jeg bare skyklapper på lige nu. Friske øjne i morgen kan måske gøre livet enklere
Hvad mener du med "at rydde op efter dig"? Jeg har da børstet krummerne væk fra tastaturet efter min ostemad...
Sub DinMakro() 'Din kode
'Sæt den rigtige reference til din celle ind her (fane-navn og celle-adresse): GemKopi Worksheets("Sheet1").Range("A1").Value End Sub
Sub GemKopi(SaveName As String) Dim wbPath As String, ws As Worksheet, ch As Chart, arr() As String Dim counter As Long, wsCount As Long, chCount As Long wbPath = ThisWorkbook.Path If Not Right(wbPath, 1) = "\" Then wbPath = wbPath & "\" counter = 0 wsCount = Worksheets.Count ReDim arr(0 To wsCount - 1) For Each ws In Worksheets arr(counter) = ws.Name counter = counter + 1 Next ws Worksheets(arr).Copy counter = 0 With ThisWorkbook chCount = .Charts.Count If Not chCount = 0 Then ReDim arr(0 To chCount - 1) For Each ch In .Charts arr(counter) = ch.Name counter = counter + 1 Next ch .Charts.Copy ActiveWorkbook.Worksheets(1) End If End With Application.DisplayAlerts = False With ActiveWorkbook .SaveAs wbPath & SaveName & ".xlsx", xlOpenXMLWorkbook .Close False End With Application.DisplayAlerts = True ThisWorkbook.Activate End Sub
|
|
|
BQardi
Bronze bruger
Medlem: 11.Nov.2016
Land: Danmark
Status: Offline
Point: 100
|
Sendt: 13.Nov.2016 kl. 22:08 |
Hold nu op!!!
Selvfølgelig kunne det gøres meget simplere:
Sub DinMakro() 'Din kode
'Sæt den rigtige reference til din celle ind her (fane-navn og celle-adresse): GemKopien Worksheets("Sheet1").Range("A1").Value End Sub
Sub GemKopien(SaveName As String) Dim wbPath As String, wb As Workbook Application.ScreenUpdating = False wbPath = ThisWorkbook.Path If Not Right(wbPath, 1) = "\" Then wbPath = wbPath & "\" Application.DisplayAlerts = False ThisWorkbook.SaveCopyAs wbPath & SaveName Set wb = Workbooks.Open(wbPath & SaveName, xlUpdateLinksAlways) With wb .SaveAs wbPath & SaveName & ".xlsx", xlOpenXMLWorkbook .Close False End With Kill wbPath & SaveName Application.DisplayAlerts = True ThisWorkbook.Activate End Sub
|
|
|
anthonsen
Forum Begynder
Medlem: 21.Jun.2016
Status: Offline
Point: 12
|
Sendt: 14.Nov.2016 kl. 08:33 |
BQardi, det var lige præcis hvad jeg ledte efter. Tak for hjælpen
|
|
EXCELGAARD
Platin bruger
Medlem: 27.Dec.2012
Land: Denmark
Status: Offline
Point: 5419
|
Sendt: 14.Nov.2016 kl. 11:13 |
Med 'rydde op' mener jeg at nulstille dine object variabler og slette dine arrays...
Set WB = Nothing Set WS = Nothing Set CH = Nothing Erase Arr |
Jeg gør det altid til sidst i mine makroer, som du vil kunne se i samtlige af mine kode r på min hjemmeside: www.excelgaard.dk/ www.excelgaard.dk/
|
Husk, at trykke på [Tak], hvis du kan lide et indlæg. Husk, at trykke på [Accepteret Svar], hvis du kan bruge et løsningsforslag.
|
|
BQardi
Bronze bruger
Medlem: 11.Nov.2016
Land: Danmark
Status: Offline
Point: 100
|
Sendt: 14.Nov.2016 kl. 22:15 |
EXCELGAARD skrev:
Med 'rydde op' mener jeg at nulstille dine object variabler og slette dine arrays...
Set WB = Nothing Set WS = Nothing Set CH = Nothing Erase Arr | Jeg gør det altid til sidst i mine makroer, som du vil kunne se i samtlige af mine kode r på min hjemmeside: www.excelgaard.dk/ www.excelgaard.dk/
|
Jeg har næsten ikke lyst til at starte sådan en diskussion, men efter min mening burde det ikke være nødvendigt at "rydde op", da det mere eller mindre sker automatisk når variablerne går ud af "scope". VBA bruger en form for "reference tæller" der forøges når en variabel bliver tildelt en object reference. Når man f.eks. når enden af en Sub eller en Function bliver denne tæller nedskrevet med 1 og når man "rammer" 0 bliver disse variabler destrueret. Så i det stykke kode jeg gav er det faktisk ikke nødvendigt da tælleren aldrig når over 1 og dermed bliver destrueret så snart koden slutter. Man kan så diskutere hvorvidt man bør "rydde op" ved enden af koden. Det er selvfølgelig den sikre måde at håndtere sin kode, men jeg er af den mening at det er vigtigere at have forståelsen for hvornår man skal bruge det eller ej. Forstå mig ret, jeg kritiserer ikke din brug af at være på den sikre side eller betvivler om du har forståelse for dette, da jeg kan se at du er en solid "coder" og helt sikkert er bedre og mere erfaren end mig, men det er bare mit syn på det. Så det er ikke fordi jeg ikke er klar over at der skal "ryddes op", men fordi jeg ved at det ikke er nødvendigt i dette tilfælde. Eksempelvis kan man sige at i min kode skulle jeg umiddelbart efter dette:
Set wb = Workbooks.Open(wbPath & SaveName, xlUpdateLinksAlways) With wb .SaveAs wbPath & SaveName & ".xlsx", xlOpenXMLWorkbook .Close False End With
|
have destrueret wb med Set wb = Nothing, da variablen ikke skal bruges mere, men da den alligevel blev destrueret ved End Sub (tre kodelinjer længere nede), synes jeg at det var ubetydeligt at bruge en ekstra linje kode på det da jeg også har en tendens til at prøve at lave så kort kode som muligt (eller øver mig på det)... Hvis du er uenig vil jeg gerne høre din mening om dette... Vi lærer hele tiden og jeg er sulten efter visdom
|
|
EXCELGAARD
Platin bruger
Medlem: 27.Dec.2012
Land: Denmark
Status: Offline
Point: 5419
|
Sendt: 15.Nov.2016 kl. 17:11 |
Der er to tilfælde, hvor det er en god i de, at 'rydde' op: - Ved gentagen kald til samme makro inden for samme session, da du har ganske ret i, at objekt variablen bliver slettet, når variablen går ud af anvendelse (scope).
Men, sletter man ikke en objekt variabel specifikt bliver kun variablen slettet - variabel tælleren bliver ikke, og derfor kan man opleve, at ens makroer, der benytter objekt variabler bliver langsommere og langsommere.
- Hvis to objekt variabler bliver gensidigt afhængige af hinanden kan fortolkeren ikke af sig selv slette nogle af objekt variablerne.
Her er man nødt til manuelt, at 'bryde kæden', ved selv at nulstille objekt variablerne (med Set = Nothing).
Uanset, om en enkelt kort makro selv kan slette disse typer hukommelsestunge variabler, så er det en god ide altid, at gøre det, var de små makroer kan ende med at blive en del af et større projekt, og så er det 'træls' at projektet bliver sløvet ned pga. dette.
Så, altid rydde op efter sig, uanset om det i den specifikke situation er nødvendigt eller ej.
Og, jeg har været der - der, hvor 'de vises sten' var, at gøre kode så kort som muligt! Men, det er ikke længere et mål - det viste sig, at gå ud over en lang række principper, som jeg værdsætter mere, bl.a.: Forståelighed og læselighed af koden. Og, ikke mindst - forståelsen o g gennemskueligheden, når man kommer tilbage og skal rette sin kode igen efter et par år: "Hva' F*****, er det jeg har lavet der?!?" God overskuelig kode, med masser af kommentarer og forklaringer er vejen frem...
|
Husk, at trykke på [Tak], hvis du kan lide et indlæg. Husk, at trykke på [Accepteret Svar], hvis du kan bruge et løsningsforslag.
|
|
BQardi
Bronze bruger
Medlem: 11.Nov.2016
Land: Danmark
Status: Offline
Point: 100
|
Sendt: 17.Nov.2016 kl. 16:11 |
Men, sletter man ikke en objekt variabel specifikt bliver
kun variablen slettet - variabeltælleren bliver ikke |
Her er jeg ikke helt enig:
Variabel tælleren bliver ikke ”slettet”, den bliver nulstillet når du specifikt
destruerer en objekt variabel (Set = Nothing).
Når man når til slutningen af sin makro (End Sub, …) bliver
tælleren nedskrevet med 1 og har du kun angivet din objekt variabel én gang,
vil tælleren altså ramme nul og variablen destrueres.
I følgende scenarie:
Sub Eksempel() Dim x As Object ’Kode Set x = Nothing End Sub
|
vil VBA tjekke om variablerne er ”Nothing” ved ”End Sub” og genererer derfor
koden til at frigøre disse variabler. Så ”Set x = Nothing” svarer til at
duplikere denne kode, hvilket efter min mening er helt unødvendigt.
Hvis man tidligere i sin kode kan eliminere sine variabler
bør man selvfølgelig gøre det for at frigøre ressourcer.
Der hvor jeg taber tråden er når du siger ”husk nu, at rydde
op efter dig, når du er færdig”. Det tolker jeg som at du specifikt mener at
man SKAL gøre det i slutningen af sin kode og det er netop det der er min pointe,
man SKAL ikke, man KAN gøre det hvis man føler for det. Det er blot et
spørgsmål om præference som jeg nævnte tidligere.
|
|
EXCELGAARD
Platin bruger
Medlem: 27.Dec.2012
Land: Denmark
Status: Offline
Point: 5419
|
Sendt: 18.Nov.2016 kl. 20:00 |
Tror jeg vil undlade, at starte denne diskution - det er vist et religionsspørgsmål, og mod religion kæmper selv de klogeste forgæves - se bare, hvordan gamle forstokkede programmørere stædigt holder fast i 'Ungarnsk Notation' Men, uanset, hvad du vælger, at fokusere på, så slipper du aldrig uden om mit punkt nummer 2 - eller 'risikoen' for at en enkelt lille makro ender med at blive en del af et større projekt. Dog ændrer det ikke på, at uanset om du rydder op efter dig eller ej, så har du ganske godt fat i den lange ende. når det gælder programmering... ...keep up the good work
|
Husk, at trykke på [Tak], hvis du kan lide et indlæg. Husk, at trykke på [Accepteret Svar], hvis du kan bruge et løsningsforslag.
|
|