Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lära Effektiv Databehandling | Arbeta med Exceldata
Excel VBA för affärsautomatisering

Effektiv Databehandling

Svep för att visa menyn

Hittills har allt arbete skett en cell i taget — fungerar bra för fem beställningar, men är smärtsamt långsamt för femtiotusen. Lösningen är att sluta arbeta cell för cell i kalkylbladet och istället flytta hela blocket till en array i minnet, bearbeta det där och skriva tillbaka allt på en gång.

Läsa in ett område till en array

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

dataArr är nu en tvådimensionell array i minnet: dataArr(1,1) är ORD1001, dataArr(1,4) är "Laptop Stand" och så vidare — VBA-arrayer som läses från ett område är 1-baserade, inte 0-baserade, vilket ofta orsakar förväxling.

Bearbeta arrayen

Sker med vanliga loopar — men nu loopar du över minnet, vilket är tusentals gånger snabbare än att loopa över kalkylbladet:

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

Skriva tillbaka arrayen

Återigen en enda operation:

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

Undvik Select och Activate

Inspelade makron använder ofta dessa (Range("A1").Select följt av Selection.Font.Bold = True), men de är onödiga och långsamma — varje .Select tvingar Excel att rita om skärmen. Referera istället direkt till området eller objektet:

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

Prestandaöverväganden

Dessa blir viktiga när din data växer över några hundra 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

Återställ alltid dessa inställningar i slutet — och kapsla in återställningen i felhantering så att ett avbrott inte lämnar Excel med avstängd skärmuppdatering.

Genomgång: Order Integrity Checker

Detta kapitel har lett fram till detta:

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

Kör detta mot exempeltabellen och det ska rapportera att alla fem totaler är korrekta — prova att ändra ORD1002:s Total på bladet till något felaktigt och kör igen för att se varningen.

Uppgift

  1. Kopiera VerifyOrderTotals till din arbetsbok och kör den mot de fem exempelordrarna.
  2. Ändra manuellt en orders Total på bladet (skriv in ett uppenbart felaktigt tal) och kör igen — bekräfta att avvikelsen rapporteras med rätt Order ID.
  3. Lägg till tio rader med påhittad orderdata under rad 6 och kontrollera att makrot fortfarande fungerar utan kodändringar — detta är fördelen med lastRow och array-baserad bearbetning.
Hjälpmedel
expand arrow

Valfri hjälpfunktion om du hellre vill generera de tio extra raderna med kod istället för att skriva in dem manuellt:

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. Kopiera VerifyOrderTotals

  • Skriv in Sub-proceduren exakt som den visas i avsnitt 3.5 i din arbetsboksmodul — inga ändringar behövs än.
  • Kör den en gång på de fem ursprungliga raderna och bekräfta att du får "All 5 order totals check out."

2. Medvetet ändra ett Total-värde

  • Välj en valfri orders Total-cell och skriv in ett uppenbart felaktigt tal direkt i kalkylbladet (inte via kod).
  • Kör samma Sub igen — felmeddelandet ska ange exakt det Order ID, samt vad bladet visar jämfört med vad makrot räknade ut.
  • Återställ cellen om du vill ha ett rent blad för nästa steg.

3. Lägg till tio nya rader

  • Skriv bara in nya orderdata direkt i raderna 7–16 — samma nio kolumner, valfria rimliga värden.
  • Ändra inte makrot alls. lastRow räknas om varje gång Sub körs, och arrayläsningen (ws.Range("A2:I" & lastRow).Value) växer automatiskt — det är hela poängen som demonstreras.
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
Var allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 3. Kapitel 5

Fråga AI

expand

Fråga AI

ChatGPT

Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal

Avsnitt 3. Kapitel 5
some-alt