2010-12-16 11 views
9

Esperemos que esta sea una tarea fácil. Tengo una serie de gráficos en MS Excel que apuntan a datos en la misma hoja de trabajo. Los datos en la hoja de cálculo se calculan utilizando una función VBA. Cuando la función VBA actualiza los datos, los nuevos números no se reflejan en los gráficos que los señalan. Intenté llamar a Application.Calculate, pero no funcionó. ¿Alguna idea?Los gráficos no se actualizan automáticamente cuando los cambios de datos


UDPATE:

que fue capaz de duplicar este número en una escala mucho más pequeña. Así es como:

  • Cree un nuevo libro
  • Cambiar el nombre de la hoja 1 a
  • abrir la hoja Resumen "Resumen"

  • Cambiar el nombre de la hoja 2 de "Datos" en el editor de VBA y pegar el siguiente código :

    Private Sub Worksheet_Change(ByVal Target As Range) 
        If Target.Parent.Range("worksheetDate") = Target Then 
         Application.CalculateFull 
        End If 
    End Sub 
    
  • Crear un nuevo m VBA ódulo

  • Pegue el código siguiente en el nuevo módulo de VBA (Me disculpo - No puedo conseguir desbordamiento de pila para dar formato a esto correctamente para la vida de mí - esto es lo mejor que podía llegar a hacer):
    .

    Function getWeekValue (weekNumber As Integer, valuesRange As Range) As Integer 
    
    Dim aCell As Range 
    Dim currentDate As Date 
    Dim arrayIndex As Integer 
    Dim weekValues(1 To 6) As Integer 
    
    currentDate = ThisWorkbook.Names("worksheetDate").RefersToRange.Value 
    arrayIndex = 1 
    For Each aCell In valuesRange 
        If month(currentDate) = month(ThisWorkbook.Sheets("Data").Cells(_ 
                aCell.Row - 1, aCell.Column)) Then 
         weekValues(arrayIndex) = aCell.Value 
         arrayIndex = arrayIndex + 1 
        End If 
    Next 
    
    getWeekValue = weekValues(weekNumber) 
    End Function 
    

    .

  • Modificar la hoja de datos para que coincida con la siguiente imagen:

alt text

  • Seleccione la celda B1 y el nombre de la gama "worksheetDate"
  • filas duplicadas 1 a 3 en la siguiente imagen:

alt text

  • En la fila 4, bajo los encabezamientos "Semana X", introduzca la siguiente fórmula

.

= getWeekValue(1, Data!$A$2:$M$2) 

incrementando el primer argumento de la función getWeekValue en uno por cada semana (por ejemplo, pasar 1 para la Semana 1, 2 para la Semana 2, 3, para la Semana 3, etc.

  • Crear una gráfico de barras usando las celdas A3 a E4 como los datos
  • Cambie la fecha en la celda B2 a una fecha entre el 10/1/2010 y el 31/12/2010, eligiendo un mes distinto al mes que está actualmente en la celda. Por ejemplo, si la fecha es 12/11/2010, cámbiela a 11/11/2010 o 10/11/2010. Tenga en cuenta que tanto los datos como el gráfico se actualizan correctamente.
  • Modifique la fecha en la ganancia de la celda B2. Tenga en cuenta que las actualizaciones de datos, pero el gráfico no.

Curiosamente, después de un período de tiempo (varios minutos), el cuadro finalmente se actualiza. No estoy seguro de si esto se debe a que he estado realizando otras actividades que desencadenaron la actualización o porque Excel está activando una actualización después de varios minutos.

+0

son gráficos basados ​​en rangos de datos simples o son gráficos dinámicos que se basan en (a) tablas dinámicas (que a su vez pueden basarse en los valores calculados de VBA). Los dos tipos de gráficos se comportan de manera diferente: para actualizar este último debe actualizar los Pivots en lugar de volver a calcular, y los PivotCharts se seguirán automáticamente – MikeD

+0

@MikeD. Gracias por la información. Lo tendré en cuenta en el futuro. En este caso, estoy trabajando con un gráfico de barras que apunta a un dato que es un rango de datos simple que no está vinculado a una tabla dinámica. – Adam

+0

¿Entonces fue capaz de resolver esto después de todo? Me di cuenta de que al insertar la primera fila en la hoja de trabajo, actualicé el gráfico –

Respuesta

0

Por ejemplo:

Sub a() 
    Dim w As Worksheet 
    Dim a 
    Set w = Worksheets(1) 

    For Each a In w.Range("a1:a5") 
    a.Value = a.Value + 1 
    Next 

    w.ChartObjects(1).Chart.Refresh 

End Sub 

alt text

+0

Sabes, espero que funcione, pero no es así. Tampoco hace un Data -> Refresh All – Adam

+0

@ Adam lo probé en mi máquina antes de publicar –

+0

@ Adam Ver edit .. –

-2

Sólo una idea: en su Worksheet_Change Sub, inserte como la primera línea:

Application.EnableEvents = False 

con el fin de evitar eventos auto-combustión. ...
Por supuesto, vuelva a establecerlo en True al final del Sub.

0

Esta solución funcionó para mí. Para la hoja de trabajo ofensiva agregue:

Private Sub Worksheet_Activate() 
    Dim rngSelection   As Range 
    Dim objChartObject  As ChartObject 
    Dim objChart    As Chart 
    Dim objSeriesCollection As SeriesCollection 
    Dim objSeries    As Series 
    Dim strFormula   As String 

    Set rngSelection = Selection 

    For Each objChartObject In Me.ChartObjects 
    Set objChart = objChartObject.Chart 
    Set objSeriesCollection = objChart.SeriesCollection 
    For Each objSeries In objSeriesCollection 
     strFormula = objSeries.Formula 

     objSeries.Delete 

     Set objSeries = objSeriesCollection.NewSeries 

     objSeries.Formula = strFormula 
    Next objSeries 
    Next objChartObject 

    rngSelection.Select 
End Sub 
+0

Tenga cuidado al publicar copiar y pegar las respuestas al pie de página o verbatim a preguntas múltiples, estas tienden a ser señaladas como "spam" por la comunidad.Si está haciendo esto, generalmente significa que las preguntas son duplicadas, así que márquelas como tales en su lugar: http://stackoverflow.com/a/12322420/419 – Kev

+0

Gracias. Eliminaré mi otra respuesta. – SLeepdepD

0

al final de mis cambios cierro el libro de trabajo y lo vuelvo a abrir. esa parece ser la manera más fácil y confiable de actualizar todo para mí.

0

Es posible que el problema sea la lista de argumentos de getWeekValue, que incluye solo el número de semana y la secuencia de datos.

Si agrega un tercer argumento, worksheetDate, el motor de recálculo de Excel se verá afectado por el hecho de que getWeekValue usa el valor almacenado en worksheetDate. En su implementación actual, este hecho se mantiene solo en el código VBA, donde probablemente sea invisible para el motor de recálculo.

Escribo esto de una manera tan fea porque no conozco el funcionamiento interno del motor de recálculo. (Tal vez alguien que sabe sobre esto mejor de lo que puedo comentar sobre mi especulación) Pero hice una prueba, en la cual getWeekValue tiene ese tercer argumento, y la tabla se recalcula correctamente. Un buen beneficio adicional de este enfoque: puede eliminar toda esa otra gestión de eventos de VBA. -HTH

1

Acabo de descubrir la solución a este problema ya que sufría lo mismo.

Acabo de agregar "DoEvents()" antes de imprimir o exportar y la tabla se actualizó.

ejemplo

Sub a() 
    Dim w As Worksheet 
    Dim a 
    Set w = Worksheets(1) 

    For Each a In w.Range("a1:a5") 
    a.Value = a.Value + 1 
    Next 

    DoEvents 

End Sub 
0

he encontrado que llamar a este sub obras ...

Sub DoAllEvents() 
    DoEvents 
    DoEvents 
End Sub 

PERO Microsoft advierte de ser atrapados con las siguientes DoEvents ejecutar antes de los primeros DoEvents completa , lo que puede suceder según la frecuencia con la que se convoca sin demoras entre llamadas. Por lo tanto, DoEvents parece estar actuando como un tipo de interrupción no enmascarable, y las interrupciones que no se pueden enmascarar pueden hacer que la máquina se congele por múltiples razones sin otra recuperación que reiniciar.

(Nota:. Si uno no está llamando a la rutina anterior, a menudo y de forma rápida, anidación puede no ser un problema)

Usando la siguiente Sub abajo, que he modificado desde su sugerencia, evita que esto suceda.

Sub DoAllEvents() 
    On Error GoTo ErrorCheck 
    Dim i 
    For i = 1 To 4000 ' Start loop. Can be higher, MS sample shows 150000 
     'I've found twice is enough, but only increased it to four or 4000. 
     If i Mod 1000 = 0 Then  ' If loop has repeated 1000 times. 
      DoEvents ' Yield to operating system. 
     End If 
    Next i 
    Exit Sub 
ErrorCheck: 
    Debug.Print "Error: "; Error, Err 
    Resume Next 
End Sub 

Me parece que el número de DoEvents necesarios se basa en el número de tareas en segundo plano que se ejecutan en la máquina, y la actualización de la gráfica parece ser una tarea de fondo para la aplicación. Solo necesitaba dos DoEvents porque llamo a la rutina con frecuencia; sin embargo, puedo terminar subiéndolo más tarde si es necesario. También guardo el Mod en 1000 para no cambiar el desfase entre cada DoEvents como sugiere Microsoft, evitando el anidamiento. Una posible razón por la que puede querer aumentar el número de 2000 a un número más alto es si su sistema no actualiza el gráfico. Aumentar este número permite que la máquina maneje un mayor número de eventos de fondo que DoEvents podría encontrar a través de múltiples llamadas ya que probablemente estén en una pila, y el evento DoEvents solo puede ejecutar un número específico de ciclos antes de marcar su lugar en la pila para Permitir eventos no controlados y regresar, dejándolos en la próxima llamada. Por lo tanto, la necesidad de múltiples llamadas. Cambiar esto a su ejemplo de 150000 no parece ralentizar la máquina demasiado, para ir a lo seguro, puede hacerlo 150000.

Nota: el primer ejemplo Sub con dos DoEvents es probablemente seguro dependiendo de la frecuencia usted llama al Sub, sin embargo, si lo llama con demasiada frecuencia, su máquina podría congelarse. Tu llamada. ;-)

PD: DoEvents se convertirá en una de sus mejores llamadas si crea muchos bucles anidados y el programa no se comporta como se esperaba. ¡Afortunadamente, esto está disponible en todas las aplicaciones que usan VBA!

Cuestiones relacionadas