• Privacywetgeving
    Het is bij Helpmij.nl niet toegestaan om persoonsgegevens in een voorbeeld te plaatsen. Alle voorbeelden die persoonsgegevens bevatten zullen zonder opgaaf van reden verwijderd worden. In de vraag zal specifiek vermeld moeten worden dat het om fictieve namen gaat.

Macro samenvoeg

Status
Niet open voor verdere reacties.

Dappre

Gebruiker
Lid geworden
28 mei 2017
Berichten
102
Hi forumleden,

Middels de volgende code voeg ik diverse Excel bestanden tot 1 compleet.

Code:
Sub VoegExcelBestandenSamenIn1NieuwBlad()
' [TOPIC=848630///][NOHTML][rml][ Excel] Meerdere bestanden samenvoegen[/rml][/NOHTML][/TOPIC]
' deel 2

Dim wbSingleWorkbook As Excel.Workbook, wbFinalWorkbook As Excel.Workbook
Dim wsSingleSheet As Excel.Worksheet, wsFinalSheet As Excel.Worksheet
Dim strPath As String, strWorkbook(500) As String ' max 500 bestanden
Dim intCounter As Integer, n As Integer
Dim Answer As VbMsgBoxResult

    strPath = "c:\test\"        ' Map met .xlsx-bestanden
    intCounter = 1              ' teller
    strWorkbook(intCounter) = Dir(strPath & "*.xlsx")
     
    Do While strWorkbook(intCounter) <> ""
     
        intCounter = intCounter + 1
        strWorkbook(intCounter) = Dir
         
    Loop
     
    intCounter = intCounter - 1 ' want de laatste is leeg
    Set wbFinalWorkbook = Workbooks.Add
    Application.DisplayAlerts = False
     
    Do While wbFinalWorkbook.Sheets.Count > 1
     
        wbFinalWorkbook.Sheets(1).Delete
     
    Loop                        ' We hebben maar 1 blad nodig
     
    Application.DisplayAlerts = True
    Set wsFinalSheet = wbFinalWorkbook.Sheets(1)
         
    On Error GoTo Einde         ' Error trapping AAN
     
    For n = 1 To intCounter
     
        Set wbSingleWorkbook = Workbooks.Open(Filename:=strPath _
            & strWorkbook(n), ReadOnly:=True)
             
        For Each wsSingleSheet In wbSingleWorkbook.Sheets
             
            wsSingleSheet.UsedRange.Copy _
                Destination:=wsFinalSheet.Cells _
                (wsFinalSheet.Cells.SpecialCells _
                (xlCellTypeLastCell).Row + 1, 1)
             
        Next wsSingleSheet

        wbSingleWorkbook.Close
     
    Next n
     
    On Error GoTo 0             ' Error trapping UIT
     
Einde:

    Select Case Err.Number      ' Foutmelding 1004 is
                                ' hoogstwaarschijnlijk veroorzaakt
        Case 1004               ' door iets te plakken dat boven
                                ' de 65536 rijen uit zou komen
            Answer = MsgBox(Err.Description & Chr(13) & Chr(13) & _
                "Waarschijnlijk wordt dit bestand te groot..." & _
                Chr(13) & "Verder gaan op nieuw blad?", _
                vbCritical Or vbYesNo, "Error " & Err.Number & _
                ": " & Err.Description)
             
            If Answer = vbYes Then
             
                Set wsFinalSheet = wbFinalWorkbook.Sheets.Add
                Resume
                 
            End If
             
        Case 0                  ' Niks aan 't handje :-)
             
        Case Else               ' Overige foutmeldingen
         
            MsgBox Err.Description, _
                vbCritical Or vbOKOnly, "Error " & Err.Number & _
                " in bestand " & n
     
    End Select
     
    Set wbSingleWorkbook = Nothing
    Set wbFinalWorkbook = Nothing
    Set wsSingleSheet = Nothing
    Set wsFinalSheet = Nothing

End Sub

Echter krijg ik tijdens het toevoegen van data en het openen van de diverse .xlsx bestanden iedere keer bij het openen van ieder bestand de vraag om externe koppelingen bij te werken.
Is er een mogelijkheid om deze in de macro te verwerken om te kiezen voor NIET BIJWERKEN.

Verder wordt er ook een enkele keer gevraagd om een bepaalde waarde uit een ander bestand te halen. Ook deze melding wil ik graag skippen zodat hij netjes doorloopt.

Alvast bedankt.
 
a. Makkelijkste lijkt me, vanwege de scope die (zover ik uit je verhaal kan nagaan) precies goed is, bij het openen de UpdateLinks parameter op False te zetten.
Dus
Code:
Set wbSingleWorkbook = Workbooks.Open(Filename:=strPath _
            & strWorkbook(n), ReadOnly:=True)
te vervangen door
Code:
Set wbSingleWorkbook = Workbooks.Open(Filename:=strPath _
            & strWorkbook(n), [B][COLOR="#FF0000"]UpdateLinks:=False,[/COLOR][/B] ReadOnly:=True)
b. Met grotere scope, en dus kans op "meer krijgen dan je had gewenst" (dus a. blijft favoriet):
Code:
Application.AskToUpdateLinks = False
die je na het openen van het workbook z.s.m. weer op True kunt/moet zetten.

Tijs.
 
Laatst bewerkt:
Bedankt Thijs, wat bedoel je precies met scope? En waarom zou je meer krijgen?
 
Ik ben hier niet om basis-concepten uit te leggen, maar wat ik bedoel met scope (*) is (even inzoomend op a. en b. uit mijn vorige posting):
Bij keuze a. wordt het updaten van links alleen afgezet bij het specifieke werkboek dat op dat moment geopend wordt.
Kies je b. dan zet je het voor het hele huidige Excel venster uit (totdat je het weer aanzet, natuurlijk).

Hopelijk begrijp je nu waarom je met b. 'voorzichtiger' moet zijn dan met a., dus, zoals ik al aangaf, z.s.m. b. weer uitzetten, want vergeet je het, dan staat het updaten van links gedurende je hele Excel venster uit. Echter: a. doet precies wat je vraagt en ook alleen op de objecten waar jij wilt dat het op gebruikt wordt, namelijk in die ene macro, alleen het updaten van links uitgezet hebben tijdens het openen van de werkboeken die jij in je macro aangeeft. Vandaar dat de scope van a. precies goed is.

(*) van Dale woordenboek vertaalt Scope als:
1 bereik, gebied, omvang: that is beyond (of: outside) the scope of this book dat valt buiten het bestek van dit boek
2 ruimte, armslag, gelegenheid: this job gives you scope for your abilities deze baan geeft je de kans je talenten te ontplooien
In het kader van Excel zou ik de vertaling "bereik" het beste vinden, oftewel iets als: "wat wordt ermee beïnvloed", "hoe ver de gevolgen zich (kunnen) uitstrekken", "waar heeft het betrekking op", "waar het gevolgen voor heeft" etc.

Tijs.
 
Laatst bewerkt:
Graag gedaan. :) Ik neem aan dat je a. hebt ingevoerd in je VBA code en dat dat precies doet wat je vroeg.

Indien je vraag is opgelost, dan nog even deze vraag de status opgelost geven:
Ingelogd op het forum en deze vraag geopend, kun je 2 acties doen daaromtrent. Kies er 1 van:
a. Klik op "Zet status opgelost" op de donkerblauwe horizontale balk, bijna bovenaan deze webpagina [die met "Zet status opgelost", "Onderwerp opties" etc.]
b. Ook rechts onderaan je startposting (dus rechts onderaan posting #1) kun je de status op opgelost zetten.

Tijs.
 
Bedankt dnties,

Ik heb hem zojuist getest en wat blijkt is dat hij nog op zoek gaat naar een waarde via een externe bestand. Hij roept het de verkenner open om het bestand te selecteren.
Is er ook een mogelijkheid deze te skippen?

Ik heb gekozen voor optie A, bedankt.
 
Goed dat je dit vermeldt, ik was even vergeten dat je vraag (min of meer) tweeledig was. Je tweede vraag:
Verder wordt er ook een enkele keer gevraagd om een bepaalde waarde uit een ander bestand te halen. Ook deze melding wil ik graag skippen zodat hij netjes doorloopt.

Dat wordt lastiger, mogelijk opgelost door het volgende vóór het Workbooks.Open gedeelte te zetten:
Code:
Application.DisplayAlerts = False
en die daarna weer uit te zetten met
Code:
Application.DisplayAlerts = True

NB: Met deze instelling op False geldt (zie deze link)
Set this property to False to suppress prompts and alert messages while a macro is running; when a message requires a response, Microsoft Excel chooses the default response.
Dus stel dat je normaal gesproken 2 keuzes zou krijgen, Ja of Nee, en Ja is standaard/default, dan wordt er dus tijdens Application.DisplayAlerts = False het antwoord Ja gepresenteerd, terwijl je (interactief) mogelijk juist Nee als antwoord geeft.

Voor NL uitleg en een paar voorbeelden (de laatste onderdruk je al met UpdateLinks:=False): deze link
Geeft mij ook het idee dat Doorgaan (zoals vermeld in jouw schermafdruk in posting #8) door Excel wordt gekozen indien Application.DisplayAlerts = False, dus (toevallig) precies wat je wilt.

Tijs.
 
Laatst bewerkt:
waarom niet ?

Code:
Sub M_snb()
   application.displayalerts=false
   Application.AskToUpdateLinks = False
   ThisWorkbook.UpdateLinks = 2

   sn=split(createobject("wscript.shell").exec("cmd /c dir C:\test\*.xlsx /b/s").stdout.readall,vbcrlf)

   for j=0 to ubound(sn)-1
     sheets.add ,sheets(sheets.count),,sn(j)
   next
End Sub
 
Laatst bewerkt:
Code aanpassing van Tijs werkt prima. Echter weet ik niet hoe ik juist test of hij de workbook weer netjes op True gezet heeft. Andere kant is het geen probleem voor dit samenvoeg bestand om ik enkel harde data nodig heb zonder koppelingen.

De enige melding die ik nu nog krijg (aangezien de grote hoeveelheid data) is dat ik de keuze "Yes" moet geven om op een tweede blad te kopiëren.

Stel dat ik deze ook wil skippen en automatiseren zal ik waarschijnlijk dezelfde code moeten toepassen.
 
De scope (;)) van mijn code in a. van posting #2 is puur tijdens het openen. Er verandert niets in het bestand zelf en ook niet in de manier waarop je (een volgende keer) het bestand interactief of via macro opent, qua UpdateLinks activiteit.

Dit is echter anders als je code zó was geweest:

Code:
Set wbSingleWorkbook = Workbooks.Open(Filename:=strPath _
            & strWorkbook(n), UpdateLinks:=False)
wbSingleWorkbook.UpdateLinks = xlUpdateLinksNever

of
Code:
Set wbSingleWorkbook = Workbooks.Open(Filename:=strPath _
            & strWorkbook(n), UpdateLinks:=False)
wbSingleWorkbook.UpdateLinks = False
want dan is het een kenmerk van het geopende werkboekbestand geworden [mogelijk krijg je dan nog een vraag of je het workbook ook wilt opslaan ("wbSingleWorkbook.Close") vanwege de aanpassing, daar ben ik niet zeker van.]
Zie ook deze link, vooral het stukje code in het Example.

Ok, dan nog over die vraag over kopiëren: Er is geen optie in het Range.Copy commando (zie deze link) om meldingen uit te zetten, dus zul je het met het onderdrukken van de melding moeten doen. Nu kan ik zo snel niet (uit mijn hoofd) nagaan wat het standaardantwoord is, maar komt die overeen met wat jij anders (interactief) had aangeklikt/gekozen, dan kun je weer dat Application.DisplayAlerts = False verhaal (her-)gebruiken.
Werkt/helpt dat niet, dan kun je kijken wat er gebeurt als je meteen na de Range.Copy regel je het volgende invoegt:
Code:
Application.CutCopyMode = False
oftewel (o.a.) het wissen van wat er op het klembord staat alhoewel jouw Range.Copy commando geen gebruik maakt van het klembord. Dit dus echt even testen op nut.

Tijs.
 
Laatst bewerkt:
Beste forumleden,

Hoe kan het zo zijn dat deze macro niet alle (juiste xlsx) bestanden samenvoegt.
Alle meldingen staan op true waarbij ik ook geen foutmelding krijg.

Hij stopt op een gegeven moment met samenvoegen waarbij hij niet alle files heeft gepakt maar een enkele.

Wie weet hier een oplossing voor?
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan