2012-01-12 19 views
7

Tengo un libro de trabajo bastante grande que toma mucho tiempo para calcular. Solía ​​ser todo un desafío hacer que calculara todo el camino, ya que Excel está tan ansioso por abortar el cálculo en silencio si lo miras.¿Cómo puedo determinar si el cálculo se completó o detectar el cálculo interrumpido?

Para ayudar a aliviar el problema, creé un código VBA para iniciar el cálculo, que se inicia con un formulario, y el resultado es que no es tan fácil interrumpir el proceso de cálculo, pero aún es posible . (Puedo hacerlo fácilmente haciendo clic en Cerrar X en el formulario, pero me imagino que hay otras formas)

En lugar de tomar más medidas para tratar de dificultar la interrupción del cálculo, me gustaría tener el código detectar si el cálculo está completo, por lo que puede notificar al usuario en lugar de solo forzar ciegamente el resto de los pasos en mi código. Hasta ahora, no puedo encontrar ninguna manera de hacer eso.

He visto referencias a Application.CalculationState, pero el valor es xlDone después de interrumpir el cálculo, incluso si interrumpo el cálculo después de unos segundos (normalmente toma alrededor de una hora).

No puedo pensar en una forma de hacerlo comprobando el valor de las celdas, ya que no sé cuál se calcula al final. Veo que hay una manera de marcar las celdas como "sucias", pero no he podido encontrar la forma de verificar la suciedad de una celda. Y no sé si ese es incluso el camino correcto a tomar, ya que probablemente tenga que verificar cada celda en cada hoja.

El acto de interrumpir el cálculo no genera un error, por lo que mi ERROR ENCENDIDO no se activa.

¿Hay algo que me falta? ¿Algunas ideas?

¿Alguna idea?

+1

Puede evitar que ocurra una interrupción, pero le sugiero que dedique un poco de esfuerzo a acelerar el cálculo: una hora para calcular es extremadamente excesiva. Ver http://www.decisionmodels.com/optspeed.htm o http://msdn.microsoft.com/en-us/library/ff700515.aspx –

+0

Estoy totalmente de acuerdo. Pero incluso si reduzco el tiempo de ejecución de la secuencia de comandos en un orden de magnitud, se ejecutará durante 6 minutos, y todavía me pregunto, dada la tendencia de Excel a ser tan silencioso sobre el cálculo interrumpido, si mis datos son precisos. Estoy realmente menos interesado en evitar la interrupción y más interesado en saber si ocurrió una interrupción. – BenTobin

+2

Gran pregunta. Observé que cuando se interrumpe el cálculo, aparece la palabra "Calcular" en la barra de estado. Aparte de simplemente mirar la barra de estado, no sé de ninguna manera para aprovechar esa información. – JimmyPena

Respuesta

0

Nunca lo he usado, pero creo que esto podría funcionar para evitar que se interrumpa el cálculo.

Application.CalculationInterruptKey = xlNoKey

+0

Eso puede ayudar a prevenir interrupciones accidentales, pero aún no me permitirá saber si el cálculo se ha interrumpido o no. – BenTobin

+0

Tienes razón. Es más una carrera final alrededor del problema. (Suponiendo que funcione.) – mischab1

2

Creo que el truco es necesario implementar (si estás aplicación se ejecuta en Excel 2007 o posterior) es manejar esto con el evento Application.AfterCalculate, que se eleva después de que tanto el cálculo es completa y no hay consultas pendientes.

Si nunca antes ha trabajado con eventos en VBA, hay una buena descripción general desde cpearson.com.

1

Creo que estoy escuchando que necesita una forma de controlar si se ejecutó cada paso dentro de los cálculos que se están realizando.

Suponiendo que usted no está interesado en la reingeniería del libro de utilizar métodos que son más fáciles de seguir que las hojas de cálculo (como cálculos volátiles dentro de VBA o tablas dinámicas), esto puede funcionar para usted:

Dentro de VB, puede utilizar .EnableCalculation y . Calcule para establecer una hoja de cálculo completa como "Sucia" (que necesita cálculo) y luego vuelva a calcular. La diferencia clave entre este y su proceso actual es que realizaremos estas acciones una hoja de cálculo a la vez en modo manual. Al iniciar los cálculos una hoja de trabajo a la vez desde dentro de VBA, podrá realizar acciones intermedias adicionales que se pueden usar para rastrear qué tan lejos llegó en el proceso de cálculo.

Tenga en cuenta que este enfoque supone una estructura de libro bastante lineal de modo que su libro de trabajo producirá los resultados correctos si primero recalcula Sheet1, luego Sheet2, Sheet3, y así sucesivamente, en el orden que desee. Si las dependencias de su fórmula son más "espaguetis" que lineales, probablemente esto no funcione para usted. También supone que está trabajando en Excel 2000 o posterior.

Por ejemplo, podría escribir una rutina de VBA que cumpla con los siguientes pasos. Deberá conocer sus dependencias para saber qué cálculos deben presentarse antes que otros, y comenzar con la hoja de trabajo en un estado "limpio" donde no hay cálculos actualmente pendientes.

Paso 1: Establecer la hoja activa a la primera hoja de cálculo donde se necesita un nuevo cálculo

Paso 2: Ajuste el modo de cálculo manual de la siguiente manera:

Application.Calculation = xlCalculationManual 

Paso 3 : "Sucio" toda la hoja activa de la siguiente manera:

With ActiveSheet 

    .EnableCalculation = False 

    .EnableCalculation = True 

Paso 4: Iniciar un nuevo cálculo para esta hoja de trabajo solamente (no todo el libro de trabajo) usando:

.Calculate 

    End With 

Observe que si el modo de cálculo se establece en automático, Paso 3 iniciaría un nuevo cálculo a través de la libro de trabajo completo. Al usar el modo manual y With, estamos limitando ese cálculo a la hoja actual.

Ahora has ensuciado y vuelto a calcular la primera hoja (¡hurra!). Ahora, al incorporar los pasos 3 y 4 en un bucle For/Each o For/Next, puede repetir el proceso para cada hoja de trabajo en su libro de trabajo. De nuevo, asegúrese de conocer el orden en el que deben calcularse sus hojas de trabajo (si se necesita un pedido).

Ahora para el gran final: al crear una variable de contador dentro de su ciclo, puede rastrear qué tan lejos ingresó en los cálculos al actualizar el valor de la variable de contador cada vez que completa un cálculo de hoja de cálculo. Por ejemplo, después de volver a calcular una hoja de cálculo, puede establecer el valor del contador en el valor actual + 1 y almacenar los resultados en una variable global (para que persista incluso después de que termine su rutina VBA) o en una celda dentro de su hoja de trabajo . De esta forma, puede verificar este valor más tarde para ver cuántas hojas de trabajo se actualizaron antes de que los cálculos se completaran o se interrumpieran.

Si tiene relativamente pocas hojas de trabajo en sus libros de trabajo, el mismo enfoque podría aplicarse a un rango a la vez en lugar de una hoja.

No entraré en detalles sobre cómo construir un "contador", bucles o variables globales aquí, pero si es necesario, esta información se puede encontrar fácilmente usando su motor de búsqueda favorito. También recomiendo volver a habilitar los cálculos automáticos una vez que haya terminado, ya que es fácil olvidar que se ha configurado en modo manual.

Espero que esto funcione para usted - para obtener más información sobre los modos de cálculo y recálculo, esto es un enlace útil: http://msdn.microsoft.com/en-us/library/bb687891.aspx

+0

Gracias por la sugerencia, pero mi experiencia hasta ahora ha sido que si se interrumpe el cálculo, cualquier código que se ejecute se mueve inmediatamente desde la llamada .calculate, exactamente como si se hubiera completado normalmente. Entonces, el resultado del contador no sería diferente si el cálculo fue interrumpido o no. Sin embargo, todavía necesito investigar el enfoque impulsado por eventos mencionado en otra respuesta. – BenTobin

-1

matrices en Excel puede ser un poco estúpida.Es decir, para realizar algunas tareas, las personas evitan utilizar columnas/filas intermedias para almacenar datos (temporales), por lo que las matrices deben volver a calcular el personal desde el principio en todo momento, lo que hace que la velocidad sea realmente lenta. Mi sugerencia sería:

  1. arreglos arreglados para evitar búsquedas múltiples. Utilizar las celdas ocultas u hojas, incluso ocultos
  2. evitar el uso de: A y en lugar utilizar A1: A1000 especialmente en Excel 2007 o posterior
  3. usan fórmulas para iguales a cero o error (por ejemplo: NA()) mientras que los artículos anteriores no son calculado, por lo que puede ver claramente si se realiza una operación en absoluto.
  4. algunos VBA podría ser utilizado para inyectar las fórmulas en lugar de un paso a la vez, realizar cálculos, a continuación, proceder al siguiente paso, pero esto podría significar un montón de trabajo ...
0

Tal vez la siguiente funcionaría:

Do Until Application.CalculationState = xlDone 
    DoEvents 
Loop 

no puedo decir que he probado, ni que sé cómo robusta la funcionalidad de Application.CalculationState realmente es determinar si se ha producido cálculo 'completo', en contraposición a algo interrumpir el proceso y marcar el estado de cálculo como hecho.

0
Private sub SomeCodeThatGeneratesFormulas 
    Application.Calculation = xlCalculation.xlCalculationManual 
    '...Some formulas are copied here' 
    Application.OnTime DateTime.DateAdd ("s",.01,DateTime.Now), "Module1.CalculateFullRebuildAndSubsequentSteps" 'By using Application.OnTime, this method will be called in a way that locks the end-user out of providing inputs into Excel until the calculation itself is complete. 
end sub 

public sub CalculateFullRebuildAndSubsequentSteps 
    Application.CalculateFullRebuild 
    '...Do next steps, i.e. paste as values' 
end sub 
0

En la barra de estado, a mano derecha, dirá Calculating (N processors) X% (donde N es el número de procesadores en el equipo y se X% cuánto se ha completado) al recalcular. Si no ve el texto allí, no está recalculando.

Estoy usando Office 2010, pero debería estar allí en todas las versiones. Es un poco sutil, así que es fácil pasar por alto.

Cuestiones relacionadas