He creado un código en Excel para tomar los datos de una tabla dinámica e insertarlos en un gráfico; un gráfico dinámico vinculado directamente a la tabla no me dará la maniobrabilidad que estoy buscando. La razón por la que me he tomado la molestia de crear un código tan "complejo" es que para cada combinación de información de planta y prueba, necesito que sea una entrada separada en el cuadro.
Entonces, el punto principal de este código es revisar cada combinación de planta e información de prueba (los comandos anidados) y luego insertar los datos en el gráfico. Mi usuario no cambiará la ubicación de la columna para xey, por lo que las compensaciones funcionan bien.
Mi problema es que si la combinación de información de planta/prueba no existe, la ingresa en el gráfico de todos modos. Cuando intento usar el comando goto y enviarlo al Next PI2 usando un identificador de error, no funciona (tal vez debido a los comandos if anidados). Estaba mirando a mi alrededor tratando de encontrar un comando que pudiera enviar mi código a una línea particular en el código (es decir, justo después de los comandos del gráfico) pero no tuve suerte...
¿Alguien conoce alguna forma de saltar a una línea concreta en caso de error?
Agregué el conjunto de comandos para reanudar en el siguiente PI2, donde digo en caso de error ir a errhandler, luego desde errhandler ir a la siguiente iteración, pero cuando ejecuto el código y obtengo un error, no sigue esta ruta, es en lugar de detenerse en la línea de 'intersección'.
Sub CreatePivotChart()
Dim PF1 As PivotField
Dim PI1 As PivotItem
Dim PI2 As PivotItem
Dim PF2 As PivotField
Dim chartcount As Integer
Dim pt As PivotTable
Set pt = Worksheets("Pivot Table").PivotTables("PivotTable")
'set up pivot field locations 1 - plant and unit , 2 - test conditions
Set PF1 = Worksheets("PivotTable").PivotTables("PivotTable").PivotFields("Plant")
Set PF2 = Worksheets("Pivot Table").PivotTables("PivotTable").PivotFields("Test Info")
'clear the chart from previous run
chartcount = 0
Sheets("Pivot Table Graph").ChartObjects("Chart 1").Chart.ChartArea.ClearContents
On Error GoTo ErrHandler
'find each visible unit
For Each PI1 In PF1.PivotItems
If PI1.Visible = True Then
Unit = PI1.Name
For Each PI2 In PF2.PivotItems
'for each unit and test condition find the information at their intersection
If PI2.Visible = True Then
TC = PI2.Name
'find the information that corresponds to each unit/test condition combination
Intersect(pt.PivotFields("Plant").PivotItems(Unit).DataRange.EntireRow, pt.PivotFields("Test Info").PivotItems(TC).DataRange).Select
Selection.Offset(-1, 0).Select
ForXRanges = "='Pivot Table'!" & Selection.Address
Selection.Offset(0, 1).Select
ForYRanges = "='Pivot Table'!" & Selection.Address
ForRangesName = Unit & "_" & TC
'for each combination create a new series on the chart
chartcount = chartcount + 1
Sheets("Pivot Table Graph").ChartObjects("Chart 1").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(chartcount).Name = ForRangesName
ActiveChart.SeriesCollection(chartcount).XValues = ForXRanges
ActiveChart.SeriesCollection(chartcount).Values = ForYRanges
End If
NextIteration:
Next PI2
End If
Next PI1
Exit Sub
ErrHandler:
Resume NextIteration:
End Sub
Respuesta1
Un mejor enfoque sería probar sus datos con una declaración if para garantizar que sus datos sean válidos. De lo contrario, no continúe con el bloque de código que puede generar un error.
En su ejemplo, esto puede funcionar... cambie esto:
'find the information that corresponds to each unit/test condition combination
Intersect(pt.PivotFields("Plant").PivotItems(Unit).DataRange.EntireRow, pt.PivotFields("Test Info").PivotItems(TC).DataRange).Select
Selection.Offset(-1, 0).Select
ForXRanges = "='Pivot Table'!" & Selection.Address
Selection.Offset(0, 1).Select
ForYRanges = "='Pivot Table'!" & Selection.Address
ForRangesName = Unit & "_" & TC
'for each combination create a new series on the chart
chartcount = chartcount + 1
Sheets("Pivot Table Graph").ChartObjects("Chart 1").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(chartcount).Name = ForRangesName
ActiveChart.SeriesCollection(chartcount).XValues = ForXRanges
ActiveChart.SeriesCollection(chartcount).Values = ForYRanges
A esto:
'find the information that corresponds to each unit/test condition combination
Set isect = Application.Intersect(pt.PivotFields("Plant").PivotItems(Unit).DataRange.EntireRow, pt.PivotFields("Test Info").PivotItems(TC).DataRange)
If isect Is Nothing Then
'Msgbox "Ranges do not intersect"
Else
isect.Select
Selection.Offset(-1, 0).Select
ForXRanges = "='Pivot Table'!" & Selection.Address
Selection.Offset(0, 1).Select
ForYRanges = "='Pivot Table'!" & Selection.Address
ForRangesName = Unit & "_" & TC
'for each combination create a new series on the chart
chartcount = chartcount + 1
Sheets("Pivot Table Graph").ChartObjects("Chart 1").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(chartcount).Name = ForRangesName
ActiveChart.SeriesCollection(chartcount).XValues = ForXRanges
ActiveChart.SeriesCollection(chartcount).Values = ForYRanges
End If
No puedo probar esto porque no tengo su libro de trabajo, pero si no funciona, debería demostrar el enfoque.
Respuesta2
Puede manejar errores sin goto
VBA de esta manera:
Sub ErrorHandling()
Dim A, d
On Error Resume Next
REM Line that throws an error
A = A / 0
REM Store details about your error before it gets cleared
d = Err.Description
On Error GoTo 0
REM You see and can handle your error message here
MsgBox d
End Sub
On Error Resume Next
Desactiva los errores de lanzamiento
On Error GoTo 0
Permite arrojar errores y borra el Err
objeto.
Respuesta3
Terminé respondiendo mis propias preguntas, al continuar revisando publicaciones antiguas, etc., encontréhttp://www.cpearson.com/excel/errorhandling.htmser de gran ayuda.
Resultó que estaba intentando usar dos comandos ir a, primero para ir al controlador de errores y luego a la siguiente iteración. Lo que tenía que hacer era cambiar el segundo punto para reanudar.
Gracias por toda la ayuda chicos, ¡el código anterior funciona perfectamente!