Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Creación de Tablas Dinámicas con VBA | Automatización de Tablas e Informes
Excel VBA para Automatización Empresarial

Creación de Tablas Dinámicas con VBA

Desliza para mostrar el menú

Una tabla dinámica resume una tabla arrastrando campos a Filas, Columnas y Valores; cada una de estas acciones de arrastrar y soltar tiene un equivalente directo en VBA, lo que significa que un informe de tabla dinámica completo puede reconstruirse desde cero mediante una macro cada vez que llegan nuevos datos.

Figura 4.3

Creación de una tabla dinámica

Sub BuildProfitPivot()
    Dim wsData As Worksheet, wsPivot As Worksheet
    Dim tbl As ListObject
    Dim pc As PivotCache
    Dim pt As PivotTable
 
    Set wsData = ThisWorkbook.Worksheets("Reports")
    Set tbl = wsData.ListObjects("tblReports")
 
    ' start clean: remove an existing Pivot sheet if this has run before
    On Error Resume Next
    Application.DisplayAlerts = False
    ThisWorkbook.Worksheets("Pivot").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0
 
    Set wsPivot = ThisWorkbook.Worksheets.Add
    wsPivot.Name = "Pivot"
 
    Set pc = ThisWorkbook.PivotCaches.Create( _
        SourceType:=xlDatabase, SourceData:=tbl.Range)
 
    Set pt = pc.CreatePivotTable( _
        TableDestination:=wsPivot.Range("A3"), _
        TableName:="ptProfitByRegion")
 
    With pt
        .PivotFields("Region").Orientation = xlRowField
        .PivotFields("Month").Orientation = xlColumnField
        .AddDataField .PivotFields("Profit"), "Sum of Profit", xlSum
    End With
End Sub
Explicación línea por línea
expand arrow
  • On Error Resume Next junto con el cambio de DisplayAlerts y .Delete es un patrón seguro de "eliminar si existe": eliminar una hoja que no existe normalmente generaría un error y detendría la macro, pero On Error Resume Next le indica a VBA que continúe silenciosamente ante ese error específico; DisplayAlerts = False suprime la ventana emergente de confirmación de Excel "¿Está seguro de que desea eliminar esta hoja?";
  • On Error GoTo 0 inmediatamente después restablece la notificación normal de errores — dejar On Error Resume Next activo durante el resto del Sub ocultaría silenciosamente cualquier error posterior no relacionado, lo cual es una trampa que conviene evitar;
  • ThisWorkbook.PivotCaches.Create toma una instantánea de los datos de la tabla — el PivotCache, no la propia tabla dinámica — que es el objeto a partir del cual realmente se construye cada tabla dinámica en segundo plano;
  • pc.CreatePivotTable convierte esa instantánea en una tabla dinámica visible, ubicada a partir de la celda A3 en la nueva hoja Pivot y con el nombre ptProfitByRegion para que el código posterior (como RefreshTable) pueda encontrarla por nombre;
  • PivotFields("Region").Orientation = xlRowField y la línea de Month justo debajo son el equivalente en código a arrastrar Region al cuadro de Filas y Month al cuadro de Columnas en la lista de campos;
  • AddDataField es lo que llena el área de Valores — el segundo argumento ("Sum of Profit") es solo la etiqueta que Excel muestra como encabezado de columna, y xlSum le indica que sume los valores en lugar de promediarlos o contarlos.

Actualización de informes

Una vez que existe una tabla dinámica, no se reconstruye cada vez que llegan nuevos datos — se actualiza, lo cual es más rápido y conserva cualquier ajuste manual de diseño realizado por el usuario:

ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion").RefreshTable

Esta sola línea vuelve a leer el PivotCache desde el estado actual de tblReports y actualiza todos los números en la tabla dinámica para que coincidan — pero deja el diseño exactamente igual, incluyendo anchos de columna, formato de números o disposición de campos que el usuario haya ajustado manualmente después de crear la tabla dinámica. Esa es la principal ventaja frente a llamar de nuevo a BuildProfitPivot: reconstruir desde cero recrearía la hoja y eliminaría todos esos ajustes manuales.

Actualización de gráficos dinámicos

Un gráfico dinámico basado en una tabla dinámica actualiza sus datos automáticamente cada vez que se actualiza la tabla dinámica — por lo tanto, refrescar la tabla suele ser todo lo que necesita hacer una macro de informe para mantener actualizado un gráfico vinculado:

Dim pt As PivotTable
Set pt = ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion")
pt.RefreshTable
' any PivotChart based on pt updates automatically — no extra code needed

Esto contrasta con los gráficos normales que se verán en la siguiente sección: un gráfico regular necesita una llamada explícita a SetSourceData para apuntar a los nuevos datos, mientras que un gráfico dinámico está permanentemente vinculado a su tabla dinámica y simplemente se actualiza automáticamente. Si un panel necesita un gráfico que siempre refleje los últimos datos de la tabla dinámica con el menor código posible, crearlo como gráfico dinámico en lugar de gráfico independiente suele ser la mejor opción.

Tarea

  1. Ejecutar BuildProfitPivot exactamente como se muestra y confirmar que aparece una nueva hoja "Pivot" con Region en las filas y Month en las columnas.
  2. Agregar manualmente una nueva fila de March a tblReports para una sexta región ficticia, luego ejecutar solo la línea RefreshTable — confirmar que la tabla dinámica se actualiza sin reconstruirla desde cero.
  3. Modificar BuildProfitPivot para resumir Sales en lugar de Profit, e intercambiar Region y Month para que Month esté en las filas y Region en las columnas.
Ayuda
expand arrow

Aquí tienes el código para agregar una sexta región como una nueva fila de marzo en tblReports, usando ListRows.Add en lugar de escribirla manualmente:

Sub AddSixthRegion()
    Dim tbl As ListObject
    Dim newRow As ListRow

    Set tbl = ThisWorkbook.Worksheets("Reports").ListObjects("tblReports")
    Set newRow = tbl.ListRows.Add

    newRow.Range(1, 1).Value = "March"        ' Month
    newRow.Range(1, 2).Value = "Southwest"    ' Region
    newRow.Range(1, 3).Value = 41500          ' Sales
    newRow.Range(1, 4).Value = 28200          ' Expenses
    newRow.Range(1, 5).Value = 13300          ' Profit
    newRow.Range(1, 6).Value = 39000          ' Target
End Sub

Ejecuta esto una vez y luego ejecuta la Sub RefreshProfitPivot de antes — la tabla dinámica ahora debería mostrar "Southwest" como una nueva fila junto a North, South, East, West y Central, sin que hayas modificado en absoluto la macro que construye la tabla dinámica.

Pista
expand arrow

1. Ejecutar BuildProfitPivot tal cual

  • Copia la Sub exactamente como está escrita en el capítulo en tu módulo y ejecútala una vez.
  • Revisa el Explorador de Proyectos o las pestañas de tu hoja — debería aparecer una nueva hoja llamada literalmente "Pivot", con Región listada en las filas y Mes distribuido en las columnas, sumando el Beneficio.

2. Agregar una sexta región y solo actualizar

  • Escribe la nueva fila directamente en la hoja de cálculo (no mediante código) — ve al final de tblReports y agrega una fila de marzo para una región inventada, por ejemplo "Southwest".
  • No vuelvas a ejecutar BuildProfitPivot — eso eliminaría y reconstruiría toda la hoja Pivot desde cero, lo que va en contra del objetivo de este ejercicio.
  • En su lugar, ejecuta solo la instrucción de una línea RefreshTable del capítulo — necesitarás hacer referencia a la tabla dinámica existente por nombre, de la misma manera que el ejemplo de actualización del capítulo.

3. Intercambiar campos y cambiar el valor resumido

  • Debes cambiar tres líneas dentro del bloque With pt: qué campo es xlRowField, cuál es xlColumnField y a qué campo apunta AddDataField.
  • Da a esta versión modificada un nombre de Sub diferente y un TableName diferente — reutilizar los mismos nombres que el original provocaría un error o sobrescribiría silenciosamente la primera tabla dinámica.
  • La etiqueta pasada a AddDataField (el segundo argumento, como "Sum of Profit") es solo texto de visualización — actualízala para que coincida con lo que realmente estás resumiendo ahora.
Solución
expand arrow

Punto 2 — después de agregar manualmente la fila de la sexta región, ejecuta solo esto:

Sub RefreshProfitPivot()
    ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion").RefreshTable
End Sub

Punto 3 — una versión modificada y separada:

Sub BuildSalesPivotByMonth()
    Dim wsData As Worksheet, wsPivot As Worksheet
    Dim tbl As ListObject
    Dim pc As PivotCache
    Dim pt As PivotTable

    Set wsData = ThisWorkbook.Worksheets("Reports")
    Set tbl = wsData.ListObjects("tblReports")

    On Error Resume Next
    Application.DisplayAlerts = False
    ThisWorkbook.Worksheets("SalesPivot").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0

    Set wsPivot = ThisWorkbook.Worksheets.Add
    wsPivot.Name = "SalesPivot"

    Set pc = ThisWorkbook.PivotCaches.Create( _
        SourceType:=xlDatabase, SourceData:=tbl.Range)

    Set pt = pc.CreatePivotTable( _
        TableDestination:=wsPivot.Range("A3"), _
        TableName:="ptSalesByMonth")

    With pt
        .PivotFields("Month").Orientation = xlRowField
        .PivotFields("Region").Orientation = xlColumnField
        .AddDataField .PivotFields("Sales"), "Sum of Sales", xlSum
    End With
End Sub

Ejecuta BuildSalesPivotByMonth y deberías obtener una nueva hoja "SalesPivot" con Mes en las filas, Región en las columnas y totales de Ventas en el cuerpo — la imagen reflejada de la disposición original.

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 4. Capítulo 3

Pregunte a AI

expand

Pregunte a AI

ChatGPT

Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla

Sección 4. Capítulo 3
some-alt