Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Effektiv Databehandling | Arbeide med Excel-data
Excel VBA for Forretningsautomatisering

Effektiv Databehandling

Sveip for å vise menyen

Alt hittil har jobbet med én celle om gangen — greit for fem ordre, men smertefullt tregt for femti tusen. Løsningen er å slutte å behandle regnearket celle for celle, og i stedet flytte hele blokken inn i et array i minnet, jobbe med det der, og skrive det tilbake i én operasjon.

Lese et område inn i et array

Dim dataArr As Variant
dataArr = ws.Range("A2:I6").Value    ' one read, not 45 individual reads

dataArr er nå et 2D-array i minnet: dataArr(1,1) er ORD1001, dataArr(1,4) er "Laptop Stand", og så videre — VBA-arrays som leses fra et område er 1-baserte, ikke 0-baserte, noe som ofte fører til feil.

Behandle arrayet

Dette gjøres med vanlige løkker — men nå løkker du over minnet, som er tusenvis av ganger raskere enn å løkke over regnearket:

Dim i As Long
Dim recalculated As Double
 
For i = 1 To UBound(dataArr, 1)
    recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
    If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
        Debug.Print "Mismatch on row " & i & ": sheet says " & dataArr(i, 8) & _
                    ", recalculated " & Format(recalculated, "0.00")
    End If
Next i

Skrive arrayet tilbake

Igjen én enkelt operasjon:

ws.Range("A2:I6").Value = dataArr

Unngå Select og Activate

Opptaksmakroer bruker ofte disse (Range("A1").Select deretter Selection.Font.Bold = True), men de er unødvendige og trege — hver .Select tvinger Excel til å tegne skjermen på nytt. Referer direkte til området eller objektet i stedet:

' Avoid:
ws.Range("A1").Select
Selection.Font.Bold = True
 
' Prefer:
ws.Range("A1").Font.Bold = True

Ytelseshensyn

Disse blir viktige når datamengden overstiger noen hundre rader:

Application.ScreenUpdating = False   ' stop redrawing while the macro runs
Application.Calculation = xlCalculationManual   ' pause recalculation
Application.EnableEvents = False     ' suppress other macros triggering mid-run
 
' ... your fast array-based code here ...
 
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True

Gjenopprett alltid disse innstillingene til slutt — og pakk gjenopprettingen inn i feilhåndtering slik at et krasj underveis ikke etterlater Excel med skjermoppdatering avslått.

Gjennomgangseksempel: Order Integrity Checker

Dette kapittelet har bygget opp mot dette:

Option Explicit
 
Sub VerifyOrderTotals()
    Dim ws As Worksheet
    Dim dataArr As Variant
    Dim lastRow As Long
    Dim i As Long
    Dim recalculated As Double
    Dim issues As String
 
    Set ws = ThisWorkbook.Worksheets("Orders")
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
 
    Application.ScreenUpdating = False
 
    dataArr = ws.Range("A2:I" & lastRow).Value
    issues = ""
 
    For i = 1 To UBound(dataArr, 1)
        recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
        If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
            issues = issues & dataArr(i, 1) & ": sheet=" & dataArr(i, 8) & _
                      ", expected=" & Format(recalculated, "0.00") & vbNewLine
        End If
    Next i
 
    Application.ScreenUpdating = True
 
    If issues = "" Then
        MsgBox "All " & UBound(dataArr, 1) & " order totals check out."
    Else
        MsgBox "Discrepancies found:" & vbNewLine & issues
    End If
End Sub

Kjør dette mot eksempel-tabellen og det skal rapportere at alle fem summer er korrekte — prøv å endre Total for ORD1002 på arket til noe feil og kjør på nytt for å se varslingen.

Oppgave

  1. Kopier VerifyOrderTotals inn i arbeidsboken din og kjør den mot de fem eksempelordrene.
  2. Endre manuelt én ordres Total på arket (skriv inn et åpenbart feil tall) og kjør på nytt — bekreft at avviket rapporteres med riktig Order ID.
  3. Legg til ti nye rader med fiktive ordredata under rad 6, og bekreft at makroen fortsatt fungerer uten endringer i koden — dette viser fordelen med lastRow og array-behandling.
Hjelper
expand arrow

Valgfri hjelper hvis du heller vil generere de ti ekstra radene i kode i stedet for å skrive dem inn manuelt:

Sub AddTestOrders()
    Dim ws As Worksheet
    Dim i As Long
    Dim r As Long

    Set ws = ThisWorkbook.Worksheets("Orders")
    r = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1

    For i = 1 To 10
        ws.Cells(r, 1).Value = "ORD" & (1005 + i)
        ws.Cells(r, 2).Value = Date
        ws.Cells(r, 3).Value = "Test Customer " & i
        ws.Cells(r, 4).Value = "Sample Product"
        ws.Cells(r, 5).Value = i
        ws.Cells(r, 6).Value = 20 + i
        ws.Cells(r, 7).Value = 0.05
        ws.Cells(r, 8).Value = i * (20 + i) * (1 - 0.05)
        ws.Cells(r, 9).Value = "Pending"
        r = r + 1
    Next i
End Sub
Tips
expand arrow

1. Kopiere VerifyOrderTotals

  • Skriv inn Sub-rutinen nøyaktig som vist i seksjon 3.5 i modularket ditt — ingen endringer nødvendig ennå.
  • Kjør den én gang på de fem opprinnelige radene og bekreft at du får "All 5 order totals check out."

2. Med vilje ødelegge én Total

  • Velg en hvilken som helst ordres Total-celle og skriv inn et åpenbart feil tall direkte i regnearket (ikke via kode).
  • Kjør samme Sub på nytt — feilmeldingen skal vise nøyaktig den Order ID-en, sammen med hva arket viser og hva makroen har rekalkulert.
  • Rett opp cellen etterpå hvis du ønsker et rent ark til neste steg.

3. Legge til ti nye rader

  • Skriv inn nye ordredata direkte i radene 7–16 — samme ni kolonner, bruk troverdige verdier.
  • Ikke rør makroen i det hele tatt. lastRow beregnes på nytt hver gang Sub-rutinen kjøres, og array-lesingen (ws.Range("A2:I" & lastRow).Value) vokser automatisk — det er hele poenget som demonstreres.
Løsning
expand arrow
Option Explicit

Sub VerifyOrderTotals()
    Dim ws As Worksheet
    Dim dataArr As Variant
    Dim lastRow As Long
    Dim i As Long
    Dim recalculated As Double
    Dim issues As String

    Set ws = ThisWorkbook.Worksheets("Orders")
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    Application.ScreenUpdating = False

    dataArr = ws.Range("A2:I" & lastRow).Value
    issues = ""

    For i = 1 To UBound(dataArr, 1)
        recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
        If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
            issues = issues & dataArr(i, 1) & ": sheet=" & dataArr(i, 8) & _
                      ", expected=" & Format(recalculated, "0.00") & vbNewLine
        End If
    Next i

    Application.ScreenUpdating = True

    If issues = "" Then
        MsgBox "All " & UBound(dataArr, 1) & " order totals check out."
    Else
        MsgBox "Discrepancies found:" & vbNewLine & issues
    End If
End Sub
Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 3. Kapittel 5

Spør AI

expand

Spør AI

ChatGPT

Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår

Effektiv Databehandling

Alt hittil har jobbet med én celle om gangen — greit for fem ordre, men smertefullt tregt for femti tusen. Løsningen er å slutte å behandle regnearket celle for celle, og i stedet flytte hele blokken inn i et array i minnet, jobbe med det der, og skrive det tilbake i én operasjon.

Lese et område inn i et array

Dim dataArr As Variant
dataArr = ws.Range("A2:I6").Value    ' one read, not 45 individual reads

dataArr er nå et 2D-array i minnet: dataArr(1,1) er ORD1001, dataArr(1,4) er "Laptop Stand", og så videre — VBA-arrays som leses fra et område er 1-baserte, ikke 0-baserte, noe som ofte fører til feil.

Behandle arrayet

Dette gjøres med vanlige løkker — men nå løkker du over minnet, som er tusenvis av ganger raskere enn å løkke over regnearket:

Dim i As Long
Dim recalculated As Double
 
For i = 1 To UBound(dataArr, 1)
    recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
    If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
        Debug.Print "Mismatch on row " & i & ": sheet says " & dataArr(i, 8) & _
                    ", recalculated " & Format(recalculated, "0.00")
    End If
Next i

Skrive arrayet tilbake

Igjen én enkelt operasjon:

ws.Range("A2:I6").Value = dataArr

Unngå Select og Activate

Opptaksmakroer bruker ofte disse (Range("A1").Select deretter Selection.Font.Bold = True), men de er unødvendige og trege — hver .Select tvinger Excel til å tegne skjermen på nytt. Referer direkte til området eller objektet i stedet:

' Avoid:
ws.Range("A1").Select
Selection.Font.Bold = True
 
' Prefer:
ws.Range("A1").Font.Bold = True

Ytelseshensyn

Disse blir viktige når datamengden overstiger noen hundre rader:

Application.ScreenUpdating = False   ' stop redrawing while the macro runs
Application.Calculation = xlCalculationManual   ' pause recalculation
Application.EnableEvents = False     ' suppress other macros triggering mid-run
 
' ... your fast array-based code here ...
 
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True

Gjenopprett alltid disse innstillingene til slutt — og pakk gjenopprettingen inn i feilhåndtering slik at et krasj underveis ikke etterlater Excel med skjermoppdatering avslått.

Gjennomgangseksempel: Order Integrity Checker

Dette kapittelet har bygget opp mot dette:

Option Explicit
 
Sub VerifyOrderTotals()
    Dim ws As Worksheet
    Dim dataArr As Variant
    Dim lastRow As Long
    Dim i As Long
    Dim recalculated As Double
    Dim issues As String
 
    Set ws = ThisWorkbook.Worksheets("Orders")
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
 
    Application.ScreenUpdating = False
 
    dataArr = ws.Range("A2:I" & lastRow).Value
    issues = ""
 
    For i = 1 To UBound(dataArr, 1)
        recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
        If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
            issues = issues & dataArr(i, 1) & ": sheet=" & dataArr(i, 8) & _
                      ", expected=" & Format(recalculated, "0.00") & vbNewLine
        End If
    Next i
 
    Application.ScreenUpdating = True
 
    If issues = "" Then
        MsgBox "All " & UBound(dataArr, 1) & " order totals check out."
    Else
        MsgBox "Discrepancies found:" & vbNewLine & issues
    End If
End Sub

Kjør dette mot eksempel-tabellen og det skal rapportere at alle fem summer er korrekte — prøv å endre Total for ORD1002 på arket til noe feil og kjør på nytt for å se varslingen.

Oppgave

  1. Kopier VerifyOrderTotals inn i arbeidsboken din og kjør den mot de fem eksempelordrene.
  2. Endre manuelt én ordres Total på arket (skriv inn et åpenbart feil tall) og kjør på nytt — bekreft at avviket rapporteres med riktig Order ID.
  3. Legg til ti nye rader med fiktive ordredata under rad 6, og bekreft at makroen fortsatt fungerer uten endringer i koden — dette viser fordelen med lastRow og array-behandling.
Hjelper
expand arrow

Valgfri hjelper hvis du heller vil generere de ti ekstra radene i kode i stedet for å skrive dem inn manuelt:

Sub AddTestOrders()
    Dim ws As Worksheet
    Dim i As Long
    Dim r As Long

    Set ws = ThisWorkbook.Worksheets("Orders")
    r = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1

    For i = 1 To 10
        ws.Cells(r, 1).Value = "ORD" & (1005 + i)
        ws.Cells(r, 2).Value = Date
        ws.Cells(r, 3).Value = "Test Customer " & i
        ws.Cells(r, 4).Value = "Sample Product"
        ws.Cells(r, 5).Value = i
        ws.Cells(r, 6).Value = 20 + i
        ws.Cells(r, 7).Value = 0.05
        ws.Cells(r, 8).Value = i * (20 + i) * (1 - 0.05)
        ws.Cells(r, 9).Value = "Pending"
        r = r + 1
    Next i
End Sub
Tips
expand arrow

1. Kopiere VerifyOrderTotals

  • Skriv inn Sub-rutinen nøyaktig som vist i seksjon 3.5 i modularket ditt — ingen endringer nødvendig ennå.
  • Kjør den én gang på de fem opprinnelige radene og bekreft at du får "All 5 order totals check out."

2. Med vilje ødelegge én Total

  • Velg en hvilken som helst ordres Total-celle og skriv inn et åpenbart feil tall direkte i regnearket (ikke via kode).
  • Kjør samme Sub på nytt — feilmeldingen skal vise nøyaktig den Order ID-en, sammen med hva arket viser og hva makroen har rekalkulert.
  • Rett opp cellen etterpå hvis du ønsker et rent ark til neste steg.

3. Legge til ti nye rader

  • Skriv inn nye ordredata direkte i radene 7–16 — samme ni kolonner, bruk troverdige verdier.
  • Ikke rør makroen i det hele tatt. lastRow beregnes på nytt hver gang Sub-rutinen kjøres, og array-lesingen (ws.Range("A2:I" & lastRow).Value) vokser automatisk — det er hele poenget som demonstreres.
Løsning
expand arrow
Option Explicit

Sub VerifyOrderTotals()
    Dim ws As Worksheet
    Dim dataArr As Variant
    Dim lastRow As Long
    Dim i As Long
    Dim recalculated As Double
    Dim issues As String

    Set ws = ThisWorkbook.Worksheets("Orders")
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    Application.ScreenUpdating = False

    dataArr = ws.Range("A2:I" & lastRow).Value
    issues = ""

    For i = 1 To UBound(dataArr, 1)
        recalculated = dataArr(i, 5) * dataArr(i, 6) * (1 - dataArr(i, 7))
        If Abs(recalculated - dataArr(i, 8)) > 0.01 Then
            issues = issues & dataArr(i, 1) & ": sheet=" & dataArr(i, 8) & _
                      ", expected=" & Format(recalculated, "0.00") & vbNewLine
        End If
    Next i

    Application.ScreenUpdating = True

    If issues = "" Then
        MsgBox "All " & UBound(dataArr, 1) & " order totals check out."
    Else
        MsgBox "Discrepancies found:" & vbNewLine & issues
    End If
End Sub
Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 3. Kapittel 5
some-alt