Zoeken…


In aanmerking komende referenties

Wanneer u verwijst naar een worksheet , een range of afzonderlijke cells , is het belangrijk om de referentie volledig te kwalificeren.

Bijvoorbeeld:

ThisWorkbook.Worksheets("Sheet1").Range(Cells(1, 2), Cells(2, 3)).Copy

Is niet volledig gekwalificeerd: aan de Cells is geen werkmap en werkblad gekoppeld. Zonder een expliciete verwijzing verwijst cellen standaard naar de ActiveSheet . Dus deze code zal mislukken (produceren onjuiste resultaten) als een ander werkblad dan Sheet1 het huidige ActiveSheet .

De eenvoudigste manier om dit te corrigeren is om de With instructie als volgt te gebruiken:

With ThisWorkbook.Worksheets("Sheet1")
    .Range(.Cells(1, 2), .Cells(2, 3)).Copy
End With

U kunt ook een werkbladvariabele gebruiken. (Dit is waarschijnlijk de voorkeursmethode als uw code naar meerdere werkbladen moet verwijzen, zoals het kopiëren van gegevens van het ene naar het andere blad.)

Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
ws1.Range(ws1.Cells(1, 2), ws1.Cells(2, 3)).Copy

Een ander veel voorkomend probleem is het verwijzen naar de verzameling werkbladen zonder de werkmap te kwalificeren. Bijvoorbeeld:

Worksheets("Sheet1").Copy

Het werkblad Sheet1 is niet volledig gekwalificeerd en heeft geen werkmap. Dit kan mislukken als naar meerdere werkmappen wordt verwezen in de code. Gebruik in plaats daarvan een van de volgende:

ThisWorkbook.Worksheets("Sheet1")       '<--ThisWorkbook refers to the workbook containing 
                                        'the running VBA code
Workbooks("Book1").Worksheets("Sheet1") '<--Where Book1 is the workbook containing Sheet1

Vermijd echter het volgende:

ActiveWorkbook.Worksheets("Sheet1")     '<--Valid, but if another workbook is activated
                                        'the reference will be changed

Hetzelfde geldt voor range objecten, zo niet expliciet gekwalificeerd, het range zal verwijzen naar de op dat moment actieve blad:

Range("a1")

Is hetzelfde als:

ActiveSheet.Range("a1")

Rijen of kolommen in een lus verwijderen

Als u rijen (of kolommen) in een lus wilt verwijderen, moet u altijd vanaf het einde van het bereik beginnen en in elke stap teruggaan. In geval van gebruik van de code:

Dim i As Long
With Workbooks("Book1").Worksheets("Sheet1")
    For i = 1 To 4
        If IsEmpty(.Cells(i, 1)) Then .Rows(i).Delete
    Next i
End With

U mist enkele rijen. Als de code bijvoorbeeld rij 3 verwijdert, wordt rij 4 rij 3. Echter, variabele i verandert in 4. Dus in dit geval zal de code een rij missen en een andere controleren, die eerder niet binnen bereik was.

De juiste code zou zijn

Dim i As Long
With Workbooks("Book1").Worksheets("Sheet1")
    For i = 4 To 1 Step -1
        If IsEmpty(.Cells(i, 1)) Then .Rows(i).Delete
    Next i
End With

ActiveWorkbook versus ThisWorkbook

ActiveWorkbook en ThisWorkbook soms door elkaar gebruikt door nieuwe gebruikers van VBA zonder volledig te begrijpen waar elk object betrekking op heeft, dit kan ongewenst gedrag tijdens de uitvoering veroorzaken. Beide objecten behoren tot het toepassingsobject


Het ActiveWorkbook object verwijst naar de werkmap die op het moment van uitvoering momenteel in de bovenste weergave van het Excel-toepassingsobject staat. (bijv. de werkmap die u kunt zien en waarmee u kunt communiceren op het moment waarop naar dit object wordt verwezen)

Sub ActiveWorkbookExample()

'// Let's assume that 'Other Workbook.xlsx' has "Bar" written in A1.

    ActiveWorkbook.ActiveSheet.Range("A1").Value = "Foo"
    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Foo"

    Workbooks.Open("C:\Users\BloggsJ\Other Workbook.xlsx")
    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Bar"

    Workbooks.Add 1
    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints nothing

End Sub

Het object ThisWorkbook verwijst naar de werkmap waartoe de code behoort op het moment dat deze wordt uitgevoerd.

Sub ThisWorkbookExample()

'// Let's assume to begin that this code is in the same workbook that is currently active

    ActiveWorkbook.Sheet1.Range("A1").Value = "Foo"
    Workbooks.Add 1
    ActiveWorkbook.ActiveSheet.Range("A1").Value = "Bar"

    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Bar"
    Debug.Print ThisWorkbook.Sheet1.Range("A1").Value '// Prints "Foo"

End Sub

Interface voor één document versus meerdere documentinterfaces

Houd er rekening mee dat Microsoft Excel 2013 (en hoger) Single Document Interface (SDI) gebruikt en dat Excel 2010 (en lager) Multiple Document Interfaces (MDI) gebruikt.

Dit betekent dat voor Excel 2013 (SDI) elke werkmap in een enkel exemplaar van Excel zijn eigen lint-UI bevat:

voer hier de afbeeldingsbeschrijving in

Omgekeerd voor Excel 2010 gebruikte elke werkmap in één exemplaar van Excel een gemeenschappelijke lint-UI (MDI): voer hier de afbeeldingsbeschrijving in

Dit roept een aantal belangrijke problemen op als u een VBA-code (2010 <-> 2013) wilt migreren die met het lint samenwerkt.

Er moet een procedure worden gemaakt om lint-UI-besturingselementen in alle werkmappen voor Excel 2013 en hoger in dezelfde status bij te werken.

Let daar op :

  1. Alle venstermethoden, gebeurtenissen en eigenschappen op Excel-toepassingsniveau blijven onaangetast. ( Application.ActiveWindow , Application.Windows ...)
  2. In Excel 2013 en hoger (SDI) werken alle venstermethoden, gebeurtenissen en eigenschappen op werkmapniveau nu op het bovenste niveau. Het is mogelijk om de toepassing van dit venster op het hoogste niveau op te halen met Application.Hwnd

Zie de bron van dit voorbeeld voor meer informatie: MSDN .

Dit veroorzaakt ook enige problemen met modelloze gebruikersformulieren. Zie hier voor een oplossing.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow