Arbeta med Excel-tabeller
Svep för att visa menyn
En Excel-tabell — som VBA kallar ett ListObject — är ett namngivet, självexpanderande område med inbyggda filterpilar, bandade rader och strukturerade kolumnreferenser. Om dina data inte redan är en tabell, markera en cell i området och tryck på Ctrl+T, eller låt VBA skapa en med ListObjects.Add.
Referera till ett ListObject
Dim ws As Worksheet
Dim tbl As ListObject
Set ws = ThisWorkbook.Worksheets("Reports")
Set tbl = ws.ListObjects("tblReports")
Debug.Print tbl.Range.Address ' full table including header
Debug.Print tbl.DataBodyRange.Rows.Count ' data rows only, no header
Att deklarera tbl As ListObject (istället för bara As Range) är det som låser upp alla tabellspecifika funktioner som används i resten av detta avsnitt — ListRows, ListColumns och Total Row kommer alla från att objektet är korrekt typat. Notera skillnaden mellan de två Debug.Print-raderna:
tbl.Range omfattar hela tabellen inklusive rubrikraden, medan tbl.DataBodyRange endast omfattar data under rubriken.
Nästan allt du gör — lägga till en rad, summera en kolumn, loopa genom poster — bör använda DataBodyRange, just för att du inte vill att rubriktexten av misstag behandlas som en datarad.
Lägga till rader
ListRows.Add lägger till en ny rad direkt under tabellen — och viktigt, alla strukturerade referensformler i andra kolumner utökas automatiskt till den, vilket är en av de största praktiska fördelarna en tabell har jämfört med ett vanligt område.
Dim newRow As ListRow
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "April"
newRow.Range(1, 2).Value = "North"
newRow.Range(1, 3).Value = 45200
newRow.Range(1, 4).Value = 30750
newRow.Range(1, 5).Value = 14450
newRow.Range(1, 6).Value = 41000
tbl.ListRows.Add skapar den tomma raden och returnerar den som ett ListRow-objekt, vilket är anledningen till att de sex följande raderna skriver till newRow istället för tillbaka till tbl. newRow.Range(1, 1) betyder "rad 1 i just denna nya rad, kolumn 1" — indexeringen börjar om på 1 för den nya raden, den räknar inte från toppen av hela tabellen. Detta är en betydligt bättre vana än att hitta bladets sista rad med End(xlUp) och skriva en kolumn förbi den manuellt: ListRows.Add hamnar alltid korrekt inom tabellens gräns, så alla totalrader, strukturerade referensformler eller villkorsstyrda formateringsregler som tillämpas på tabellen utökas automatiskt för att inkludera den.
Uppdatera poster
För att uppdatera en befintlig rad, loopa genom DataBodyRange och matcha på en nyckelkolumn — här uppdateras Central-regionens Target för februari efter en budgetändring:
Dim r As Long
For r = 1 To tbl.DataBodyRange.Rows.Count
If tbl.DataBodyRange.Cells(r, 1).Value = "February" And _
tbl.DataBodyRange.Cells(r, 2).Value = "Central" Then
tbl.DataBodyRange.Cells(r, 6).Value = 52000 ' revised Target
Exit For
End If
Next r
Detta är samma uppifrån-och-ner, stoppa-vid-första-träff-mönster som används vid villkorslogik, tillämpat på riktiga rader istället för hårdkodade värden: loopen kontrollerar Månad och Region tillsammans med And, och så fort båda matchar uppdateras Target-kolumnen och Exit For anropas så att den inte fortsätter att söka igenom resterande rader i onödan. Genom att använda tbl.DataBodyRange.Cells(r, 1) istället för ett arbetsbladsnivå Cells-referens hålls radnumreringen inom tabellens egna data — rad 1 här betyder första dataraden, oavsett vilken fysisk rad tabellen råkar börja på i arbetsbladet.
Referera till tabellkolumner
Strukturerade referenser — ListColumns("Name") — är mer läsbara och mer robusta än att räkna kolumner med nummer, särskilt när en tabell redigeras och kolumner flyttas:
Dim profitCol As Range
Set profitCol = tbl.ListColumns("Profit").DataBodyRange
Debug.Print Application.WorksheetFunction.Sum(profitCol)
Debug.Print Application.WorksheetFunction.Average(profitCol)
ListColumns("Profit") hittar kolumnen via dess rubriktext istället för genom att räkna position, så koden fortsätter fungera även om Profit senare flyttas från kolumn E till kolumn F — att manuellt räkna Cells(r, 5) skulle tyst sluta fungera i det scenariot. Application.WorksheetFunction är bryggan som låter VBA anropa vanliga Excel-funktioner som SUM och AVERAGE direkt mot ett Range-objekt, istället för att du skriver en manuell loop med en löpande summa, vilket både är mindre kod och mindre risk för räknefel.
Uppgift
- Öppna
Section_4_Reports.xlsx, spara den somSection_4_Reports.xlsmoch bekräfta att data på bladet Reports är en tabell med namnettblReports(klicka i valfri cell i tabellen — fliken Tabellverktyg ska visas). - Skriv en makro som lägger till en rad för april för var och en av de fem regionerna med hjälp av
ListRows.Add(totalt fem nya rader, påhittade siffror går bra). - Skriv en andra makro som använder
ListColumns("Sales").DataBodyRangeochWorksheetFunction.Sumför att skriva ut den totala försäljningen för alla rader till Direktfönstret.
1. Öppna och bekräfta tabellen
- Spara bara om med Arkiv → Spara som och välj "Excel-arbetsbok med makron (*.xlsm)" i formatlistan — ingen kod behövs för detta steg.
- Klicka i valfri cell i Reports-data och kontrollera att fliken Tabellverktyg visas i menyfliksområdet — det bekräftar att det är en riktig Excel-tabell och inte bara ett vanligt område som ser likadant ut.
2. Lägg till fem aprilrader med ListRows.Add
- Du behöver en
ListObject-variabel som pekar påtblReports, och sedan anropa.ListRows.Adden gång per region — fem separata anrop, eller en loop som körs fem gånger. - Varje ny rad behöver sex värden: Månad, Region, Sales, Expenses, Profit, Target — referera till dem via position (
newRow.Range(1, 1),(1, 2)osv.), på samma sätt som i det genomgångna exemplet i kapitel 4. - En array med de fem regionnamnen gör loopen smidigare än att skriva fem nästan identiska kodblock för hand.
3. Summera Sales med WorksheetFunction
ListColumns("Sales")hittar kolumnen via dess rubrik —.DataBodyRangebegränsar det till endast datacellerna, utan rubrik.Application.WorksheetFunction.Sum(...)tar det området direkt — ingen loop behövs.Debug.Printskickar resultatet till Direktfönstret (Ctrl+G) istället för en popup.
Option Explicit
Sub AddAprilRows()
Dim tbl As ListObject
Dim newRow As ListRow
Dim regions As Variant
Dim i As Long
Set tbl = ThisWorkbook.Worksheets("Reports").ListObjects("tblReports")
regions = Array("North", "South", "East", "West", "Central")
For i = 0 To 4
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "April"
newRow.Range(1, 2).Value = regions(i)
newRow.Range(1, 3).Value = 46000 + i * 500 ' Sales — invented
newRow.Range(1, 4).Value = 31000 + i * 300 ' Expenses — invented
newRow.Range(1, 5).Value = 15000 + i * 200 ' Profit — invented
newRow.Range(1, 6).Value = 41000 ' Target — invented
Next i
End Sub
Sub PrintTotalSales()
Dim tbl As ListObject
Dim salesCol As Range
Set tbl = ThisWorkbook.Worksheets("Reports").ListObjects("tblReports")
Set salesCol = tbl.ListColumns("Sales").DataBodyRange
Debug.Print "Total Sales: " & Application.WorksheetFunction.Sum(salesCol)
End Sub
Kör först AddAprilRows och sedan PrintTotalSales — summan ska automatiskt inkludera de fem nya aprilraderna, eftersom DataBodyRange alltid speglar tabellens aktuella storlek.
Tack för dina kommentarer!
Fråga AI
Fråga AI
Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal