Trabajando con Tablas de Excel
Desliza para mostrar el menú
Una tabla de Excel — lo que VBA llama un ListObject — es un rango nombrado y autoexpandible con flechas de filtro integradas, filas alternas y referencias estructuradas de columnas. Si tus datos aún no son una Tabla, selecciona cualquier celda dentro de ellos y presiona Ctrl+T, o deja que VBA cree una usando ListObjects.Add.
Referencia a un 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
Declarar tbl As ListObject (en lugar de solo As Range) es lo que habilita todas las funciones específicas de Tabla que se usan en el resto de esta sección — ListRows, ListColumns y la Total Row provienen de que el objeto esté correctamente tipado. Observa la distinción entre las dos líneas de Debug.Print:
tbl.Range cubre toda la Tabla incluyendo la fila de encabezado, mientras que tbl.DataBodyRange cubre solo los datos debajo de ella.
Casi todo lo que hagas — agregar una fila, sumar una columna, recorrer registros — debe usar DataBodyRange, precisamente porque no quieres que el texto del encabezado se trate accidentalmente como una fila de datos.
Agregar filas
ListRows.Add agrega una nueva fila directamente debajo de la tabla — y, de manera crucial, cualquier fórmula de referencia estructurada en otras columnas se extiende automáticamente a ella, lo que es una de las mayores ventajas prácticas de una Tabla sobre un rango común.
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 crea la fila en blanco y la devuelve como un objeto ListRow, por lo que las siguientes seis líneas escriben en newRow en lugar de volver a tbl. newRow.Range(1, 1) significa "fila 1 de esta fila nueva específica, columna 1" — la indexación se reinicia en 1 para la nueva fila, no cuenta desde la parte superior de toda la tabla. Esto es una práctica significativamente mejor que buscar la última fila de la hoja con End(xlUp) y escribir una columna después manualmente: ListRows.Add siempre cae correctamente dentro del límite de la Tabla, por lo que cualquier Fila de Totales, fórmula de referencia estructurada o regla de formato condicional aplicada a la Tabla se extiende automáticamente para incluirla.
Actualizar registros
Para actualizar una fila existente, recorre DataBodyRange y haz coincidir una columna clave — aquí, actualizando el Target de la región Central de febrero después de una revisión presupuestaria:
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
Este es el mismo patrón de arriba hacia abajo, detenerse en la primera coincidencia, que se usa en la lógica condicional, aplicado a filas reales en lugar de valores codificados: el bucle verifica Mes y Región juntos con And, y en el momento en que ambos coinciden, actualiza la columna Target y llama a Exit For para no seguir revisando las filas restantes innecesariamente. Usar tbl.DataBodyRange.Cells(r, 1) en lugar de una referencia Cells a nivel de hoja mantiene la numeración de filas limitada a los datos de la Tabla — la fila 1 aquí significa la primera fila de datos, sin importar en qué fila física de la hoja comience la Tabla.
Referencia a columnas de la tabla
Las referencias estructuradas — ListColumns("Name") — son más legibles y más resistentes que contar columnas por número, especialmente cuando una tabla se edita y las columnas se mueven:
Dim profitCol As Range
Set profitCol = tbl.ListColumns("Profit").DataBodyRange
Debug.Print Application.WorksheetFunction.Sum(profitCol)
Debug.Print Application.WorksheetFunction.Average(profitCol)
ListColumns("Profit") encuentra la columna por su texto de encabezado en lugar de por posición, por lo que el código sigue funcionando incluso si Profit luego se mueve de la columna E a la columna F — contar Cells(r, 5) manualmente fallaría silenciosamente en ese escenario. Application.WorksheetFunction es el puente que permite a VBA llamar directamente a funciones comunes de Excel como SUM y AVERAGE sobre un objeto Range, en lugar de escribir un bucle manual con un total acumulado, lo que implica menos código y menos probabilidad de cometer un error de desfase.
Tarea
- Abrir
Section_4_Reports.xlsx, guardarlo comoSection_4_Reports.xlsmy confirmar que los datos de la hoja Reports son una Tabla llamadatblReports(haz clic en cualquier celda dentro de ella — la pestaña Diseño de tabla debe aparecer). - Escribir una macro que agregue una fila de abril para cada una de las cinco regiones usando
ListRows.Add(cinco filas nuevas en total, las cifras pueden ser inventadas). - Escribir una segunda macro usando
ListColumns("Sales").DataBodyRangeyWorksheetFunction.Sumpara imprimir el total de ventas de todas las filas en la Ventana inmediata.
1. Abrir y confirmar la Tabla
- Simplemente vuelve a guardar con Archivo → Guardar como, eligiendo "Libro de Excel habilitado para macros (*.xlsm)" en el menú de formato — no se necesita código para esta parte.
- Haz clic en cualquier celda dentro de los datos de Reports y revisa la cinta para ver si aparece la pestaña Diseño de tabla — eso confirma que es una Tabla de Excel genuina, no solo un rango que se ve similar.
2. Agregar cinco filas de abril con ListRows.Add
- Necesitas una variable
ListObjectapuntando atblReports, luego llama a.ListRows.Adduna vez por región — cinco llamadas separadas, o un bucle que se ejecute cinco veces. - Cada nueva fila necesita seis valores escritos: Month, Region, Sales, Expenses, Profit, Target — refiérete a ellos por posición (
newRow.Range(1, 1),(1, 2), etc.), igual que en el ejemplo trabajado del Capítulo 4. - Un arreglo con los nombres de las cinco regiones hace que la versión con bucle sea más limpia que escribir cinco bloques casi idénticos a mano.
3. Sumar ventas con WorksheetFunction
ListColumns("Sales")encuentra la columna por su encabezado —.DataBodyRangelo reduce solo a las celdas de datos, sin incluir el encabezado.Application.WorksheetFunction.Sum(...)toma ese rango directamente — no se requiere bucle.Debug.Printenvía el resultado a la Ventana inmediata (Ctrl+G) en lugar de una ventana emergente.
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
Ejecuta primero AddAprilRows, luego PrintTotalSales — el total debe incluir automáticamente las cinco nuevas filas de abril, ya que DataBodyRange siempre refleja el tamaño actual de la Tabla.
¡Gracias por tus comentarios!
Pregunte a AI
Pregunte a AI
Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla