Sök…


Kvalificerade referenser

När du hänvisar till ett worksheet , ett range eller enskilda cells är det viktigt att referensen är fullständigt kvalificerad.

Till exempel:

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

Är inte helt kvalificerad: Cells referenserna har inte en arbetsbok och kalkylblad associerade med dem. Utan en uttrycklig referens hänvisar Cells till ActiveSheet standard. Så denna kod kommer att misslyckas (ger felaktiga resultat) om ett annat kalkylblad än Sheet1 är det aktuella ActiveSheet .

Det enklaste sättet att korrigera detta är att använda ett With uttalande enligt följande:

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

Alternativt kan du använda en kalkylvariabelvariabel. (Det här är troligtvis en föredragen metod om din kod behöver referera till flera kalkylblad, till exempel att kopiera data från ett ark till ett annat.)

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

Ett annat vanligt problem är att referera till kalkylarksamlingen utan att kvalificera arbetsboken. Till exempel:

Worksheets("Sheet1").Copy

Sheet1 är inte fullt kvalificerat och saknar en arbetsbok. Detta kan misslyckas om flera arbetsböcker hänvisas till i koden. Använd istället något av följande:

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

Undvik dock att använda följande:

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

På samma sätt för range , om inte uttryckligen kvalificerade, hänvisar range till det aktuella aktiva arket:

Range("a1")

Är det samma som:

ActiveSheet.Range("a1")

Radera rader eller kolumner i en slinga

Om du vill ta bort rader (eller kolumner) i en slinga bör du alltid slinga från början av slutet och flytta tillbaka i varje steg. Vid användning av koden:

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

Du kommer att sakna några rader. Till exempel, om koden raderar rad 3, sedan rad 4 blir rad 3. Men variabel i kommer att ändras till 4. Så, i detta fall koden kommer att missa en rad och kontrollera en annan, som inte var inom räckhåll tidigare.

Rätt kod skulle vara

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 vs. ThisWorkbook

ActiveWorkbook och ThisWorkbook ibland utbytbart av nya användare av VBA utan att helt förstå vilket objekt förhåller sig till, detta kan orsaka oönskat beteende vid körning. Båda dessa objekt tillhör applikationsobjektet


ActiveWorkbook objektet hänvisar till den arbetsbok som för närvarande är högst upp i Excel-applikationsobjektet vid körningstillfället. (t.ex. arbetsboken som du kan se och interagera med vid den punkt då det hänvisas till detta objekt)

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

ThisWorkbook objektet hänvisar till den arbetsbok som koden tillhör vid den tidpunkt då den körs.

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

Enstaka dokumentgränssnitt kontra flera dokumentgränssnitt

Var medveten om att Microsoft Excel 2013 (och senare) använder Single Document Interface (SDI) och att Excel 2010 (och nedan) använder Multiple Document Interfaces (MDI).

Detta innebär att för Excel 2013 (SDI) innehåller varje arbetsbok i en enda instans av Excel sitt eget band UI:

ange bildbeskrivning här

Omvänt för Excel 2010 använde varje arbetsbok i en enda instans av Excel ett vanligt band UI (MDI): ange bildbeskrivning här

Detta väcker några viktiga frågor om du vill migrera en VBA-kod (2010 <-> 2013) som interagerar med bandet.

En procedur måste skapas för att uppdatera UI-kontrollerna för band i samma tillstånd i alla arbetsböcker för Excel 2013 och Higher.

Anteckna det :

  1. Alla Excel-applikationsnivåfönster, händelser och egenskaper förblir opåverkade. ( Application.ActiveWindow , Application.Windows ...)
  2. I Excel 2013 och högre (SDI) fungerar nu alla fönstermetoder, händelser och egenskaper på arbetsbokenivån i det övre nivåfönstret. Det är möjligt att hämta handtaget i detta toppnivå med Application.Hwnd

För mer information, se källan till detta exempel: MSDN .

Detta orsakar också problem med användarformerna för modelllösa. Se Här för en lösning.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow