lunes, junio 10, 2013

Tablas dinámicas – cambiar la función CONTAR por SUMA

Para totalizar los valores en los campos introducidos en el área de valores Excel utiliza la siguiente regla:


  • Si todos los valores en el campo (columna de la tabla de datos) de origen son numéricos, utiliza SUMA.
  • Si alguno de los valores no es numérico, utiliza CONTAR.


El problema con esta regla es que, a diferencia de la función SUMA usada en una celda de la hoja, las celdas vacías son consideradas no numéricas. Esto produce no pocos dolores de cabeza ya que basta que una de las celdas no contenga ningún valor para que la función usada para resumir los valores sea CONTAR.

El problema se agrava cuando tenemos varios campos de valores ya que Excel no cuenta con un método para cambiar la función de resumen de todos los campos de una sola vez. Si tenemos una tabla con muchos campos de valores, nuestro sufrido usuario deberá cambiar manualmente la función de cada uno de los campos.

En este ejemplo tenemos una tabla con los datos de una cadena de comercios para los meses de enero, febrero y marzo. Los datos son: zona, mes, número de visitantes, número de compradores (cuantos de los visitantes realizaron alguna compra) y ventas.



Como puede apreciarse, faltan los datos de marzo de la zona Sur, por lo que las celdas están vacías.

Al crear un reporte dinámico, veremos que Excel usa CONTAR para resumir los datos en lugar de SUMA, que era lo que esperábamos



En este estado de cosas podemos optar por una de estos tres caminos:


  1. modificar una a una la función de resumen
  2. rellenar las celdas vacías con ceros (lo que se puede hacer eficientemente con Ir a-Especial)
  3. usar esta macro para cambiar la función programáticamente:


Sub change_pt_function()
'Cambia la funcion de los campos de valor de CONTAR a SUMA
'Desarrollada por Jorge Dunkelman - JLDExcelsp.blogspot.com

    Dim pt As PivotTable
    Dim iDataFieldsCount As Integer
    Dim iX As Integer
       
    On Error Resume Next
    Set pt = ActiveCell.PivotTable
    On Error GoTo 0
   
    If pt Is Nothing Then
        MsgBox "La celda seleccionada no pertenece a una tabla dinamica", _
                    vbCritical, _
                    "Cambiar funcion en TD"
        Exit Sub
    End If
   
    iDataFieldsCount = pt.DataFields.Count
   
    For iX = 1 To iDataFieldsCount
        With pt.DataFields(iX)
            If .Function = xlCount Then
            .Function = xlSum
            .Name = Replace(.Name, "Cuenta de", "Suma de")
            End If
        End With
    Next iX
       
End Sub


Esta macro recorre todos los campos en el área de los valores; en caso que la función de resumen sea CONTAR, la reemplaza por SUMA.

Para usar la macro hay que seleccionar previamente alguna celda de la tabla dinámica, por eso usamos un MSgBox para informar al usuario en caso que no se haya seleccionado un celda de la tabla dinámica.
Otro detalle es que al usar la propiedad DataFields, el nombre del campo (label) no cambia al cambiar la función. Por eso, suponiendo que el usuario no ha cambiado el nombre por defecto del campo ("Cuenta de…"), reemplazamos "Cuenta de…" por "Suma de…" programáticamente.
Si no queremos cambiar los nombres de los campos, podemos poner un apóstrofe (') al comienzo de la sentencia .Name = Replace(.Name, "Cuenta de", "Suma de"), de manera que no sea ejecutada.

Para usar este código con comodidad podemos agregar un icono en la barra de acceso rápido.

16 comentarios:

  1. Te agradezco la rapidez en contestar a mi duda y el grado de detalle en la explicación. Realmente útil. Y la referencia a "Ir a-Especial", igualmente buena.

    Gracias por tu trabajo.

    ResponderBorrar
  2. Hola gracias por la información, de mucha ayuda. Yo no tengo conocimiento de VB y viene bien, pero no me funciona todo el código, sólo la parte donde identifica que no está en la tabla dinámica, me podéis ayudar por favor.
    Gracias.

    ResponderBorrar
  3. Antes de correr la macro tienes que seleccionar alguna celda de la tabla dinámica.

    ResponderBorrar
  4. Gracias por la pronta respuesta. Estoy en cualquier celda de la TD y la ejecuto y no funciona, me coloqué fuera para ver si por lo menos iba lo del error de que no estaba y eso si va.
    Qué problema puede ser?

    ResponderBorrar
  5. Maria Helena, si me mandas el archivo (ver el enlace Ayuda, en la parte superior de la plantilla) podría fijarme donde está el problema.

    ResponderBorrar
  6. Jorge, ya me funciona. Gracias. No sé exactamente lo que estaba haciendo mal.
    Un saludo.

    ResponderBorrar
  7. Buenisimo Muchas gracias, muy facil de utilizar

    ResponderBorrar
  8. Muchas, muchas gracias! La macro es un ahorro de tiempo impresionante!! Gracias!

    ResponderBorrar
  9. Muchisimas gracias!!! Me has ahorrado horas de trabajo!!

    ResponderBorrar
  10. Jorge Dunkelman necesito ayuda con tu macro. seria de utilidad aprender a uitlizarla

    ResponderBorrar
  11. Diego, todo lo que hay que hacer es copiar el código en un módulo deleditor de Vb y luego actvarla, lo que se puede hacer desde la cinta de opciones o creando un icono en la barra de acceso rápido.

    ResponderBorrar
  12. Hola, Me parece una gran solución. Pero me quedan los enteros sin decimales y los que tienen decimales me quedan con 4 #.#### Se podría incorporar a la macro el que además te actualice el formato número a, por ejemplo, 2 decimales?

    ResponderBorrar
  13. La macro no afecta el formato de los números. Eso tienes que resolverlo con el menú de formato numérico.

    ResponderBorrar
  14. Hola Jorge buen día.
    Lo felicito por su publicación y le agradezco por su generosidad.
    Por favor ayúdeme con lo siguiente: Necesito poner un nombre personalizado en los títulos de esas columnas de valores. De antemano muchas gracias.

    ResponderBorrar
    Respuestas
    1. Hola Edison
      ¿a que te referís por "nombre personalizado"? Si se trata de crear nombres definidos que se refieran a la celda, se puede pero no me queda claro cual es el objetivo.

      Borrar

Nota: sólo los miembros de este blog pueden publicar comentarios.