2010-03-29 12 views
7

Diariamente, una persona necesita verificar que los libros de trabajo específicos se hayan actualizado correctamente con los datos del mercado de Bloomberg y Reuters; es decir, todos los datos se han procesado y los 'números parecen correctos'. En el pasado, las personas no estaban verificando los 'números', lo que ocasionaba cargas inexactas a otros sistemas.¿Cómo utilizar eficazmente el evento WorkbookBeforeClose correctamente?

La idea es que 'algo' debe desarrollarse para evitar que el uso cierre/guarde el libro de trabajo a menos que haya verificado que las actualizaciones sean correctas y precisas. La acción numbers look correct es un ejercicio puramente intuitivo, por lo que no se codificará de ninguna manera.

La solución simple fue solicitar a los usuarios antes de cerrar el libro de trabajo específico para verificar que los datos se hayan comprobado.

con VSTO SE para Excel 2007, un complemento fue creado que se engancha en el caso WorkbookBeforeClose que se inicializa en el complemento ThisAddIn_Startup

private void wb_BeforeClose(Xl.Workbook wb, ref bool cancel) 
{ 
    //.... snip ... 

    if (list.Contains(wb.Name)) 
    { 
     DailogResult result = MessageBox.Show("some message", "sometitle", MessageBoxButtons.YesNo); 

     if (result != DialogResult.Yes) 
     { 
      cancel = true; // i think this prevents the whole application from closing 
     } 
    } 
} 

He encontrado el siguiente ThisApplication.WorkbookBeforeSave vs ThisWorkbook.Application.WorkbookBeforeSave que recomienda que uno debe use el evento ThisApplication.WorkbookBeforeClose que creo que es lo que estoy haciendo ya que abarcará todos los archivos abiertos.

El problema que tengo con este enfoque es que el supuesto de que tengo varios archivos abiertos, algunos de los cuales están en mi list, el evento impide que Excel se cierre todos los archivos de forma secuencial. Ahora requiere que cada archivo se cierre de forma individual. Editar: esto ocurre cuando Salir de Excel se utiliza desde el menú Archivo.

Preguntas

  1. estoy usando el evento WorkbookBeforeClose correcta y efectiva es esta & uso eficiente del evento?
  2. ¿Debo usar el evento de nivel de aplicación o el evento de nivel de documento ?
  3. ¿El comportamiento descrito arriba es normal?
  4. Otras sugerencias son bienvenidos al utilizar eventos libro en un complemento

Actualización [30-Mar-2010]:

Tinkering alrededor, también probé los siguientes, que intentó unir el controlador de eventos BeforeClose de todos los libros que se abrieron como se sugiere en el enlace anterior.

private void ThisAddIn_Startup(...) 
{ 
    // snip 
    Globals.ThisAddin.Application.WorkbookOpen += Application_Open; 
} 

private void Application_Open(XL.Workbook wb) 
{ 
    wb.BeforeClose += Document_WorkbookBeforeClose; // method does the same as above 
} 

El problema que me encontré con este enfoque es que es trato de cerca de todos los archivos de Excel (usando la opción Salir de Excel ) el controlador de eventos no se ejecuta. Según mi observación, esto sucede cuando el documento que se va a verificar no es el documento activo.

Este método parece errático en comparación con mi enfoque inicial. Lo único con lo que no estoy seguro o con lo que me siento cómodo es vinculando el evento cada vez que se abre un documento.

Actualización [07-Apr-2010]:

respuesta sugerida de Glen es útil, pero no aborda las cuestiones inmediatas a la mano, por lo tanto me han aclarado la última pregunta un poco más lejos.

También he encontrado este blog How to Get an Excel VSTO Workbook Closed Event que es algo relevante para mi problema, ya que podría ser utilizado dentro de un enfoque alternativo para mi solución utilizando un enfoque de tipo de monitor para el manejo de los libros (y posiblemente también utilizar el OnWorkbookClosed evento recién introducido)

Actualización [08-Apr-2010]:

Parece haber cierta confusión, no estoy preocupado por ninguna validación de los libros ellos mismos, sino más bien si el método que estoy utilizando (es decir, el uso de la Aplicación nivel WorkbookBeforeClose evento) es correcto. El comentario de @Mathias a continuación muestra la comprensión correcta de parte del problema en relación con la pregunta 3, aunque creo que este es el comportamiento de Excel predeterminado. La solución para superar esto fue crear una función de cierre que cierra solo mis archivos específicos.

  1. es el comportamiento descrito encima de lo normal? Sí, pero ¿por qué? Dado que el complemento se engancha en el evento de nivel de aplicación, las verificaciones y la cancelación del evento bloquean la aplicación para que no cierre más libros de trabajo. La clave aquí es el argumento ref bool cancel (cancel=false permite el cierre normal del libro (por defecto), cancel=true impide el libro desde el cierre)

VS 2005 con VSTO SE

+1

Sólo para asegurarse de que entiendo su problema correctamente, es este el escenario que tiene en mente: el usuario ha ficheros A, B, C abierta> cierra Excel (Salida Excel)> dice que sí a cerrar una, sin al archivo B. Qué tiene actualmente: Excel cancela los cierres A y B y C. Lo que desea: Excel cierra A, mantiene B abierto y continúa preguntando si C debe cerrarse. ¿Entiendo tu problema correctamente? es decir, su problema es que cuando un usuario sale de Excel, le gustaría poder cerrar los archivos que se pueden cerrar y solo mantener abiertos los que necesitan una validación. – Mathias

+0

También comencé a jugar con esto, y los 2 enfoques (libro cerrado atrapado en el nivel de la aplicación o el libro de trabajo) se comportan exactamente de la misma manera en mi máquina. – Mathias

+0

@mathias - exactamente, tengo que actualizar la pregunta aún más porque he logrado lograr lo que está describiendo – Ahmad

Respuesta

6

El nivel de aplicación WorkbookBeforeClose es la de usar. El problema es que el comportamiento errático es el resultado de archivos que no se guardan cuando se llama al WorkbookBeforeClose. Si no lo son, el evento Save se activará y efectivamente habrá perdido el evento WorkbookBeforeClose porque ya se ha producido. Aquí hay un código de VBA que ayuda a manejar esto.

Private Sub Workbook_BeforeClose(Cancel As Boolean) 
    If Not Me.Saved Then 
     NotSavedPrompt = Me.Name & " has not been saved. Would you like to save now?" 
     SaveYesNo = MsgBox(NotSavedPrompt, vbQuestion + vbYesNoCancel) 
     Select Case SaveYesNo 
      Case vbYes 
       Me.Save 
      Case vbNo 
       Me.Saved = True 
      Case vbCancel 
       Cancel = True 
       Exit Sub 
      End Select 
    End If 
    Call MyRoutine() //'this should be your sub that does what you want 
End Sub 
+0

soy la mejor respuesta hasta el momento que cubre la mayoría de mis preguntas ... – Ahmad

+0

@Ahmad: Gracias, avíseme si tiene más preguntas o inquietudes. –

+0

Me acabo de dar cuenta de que mi firma de método C# es diferente a la tuya 'Application_WorkbookBeforeClose (Xl.Workbook wb, ref bool cancel)' - ¿Estás seguro de que este es el método de evento de nivel de aplicación en tu código? – Ahmad

3

Ya que se están ejecutando en problemas con este enfoque, y Excel puede no permitirle hacer lo que necesita, tal vez podría considerar otro enfoque para resolver el problema general.

¿Podría generar algo en el libro que lo señala como "Verificado/No verificado", según si alguien ha verificado los números? Dependiendo de cómo se use realmente el libro (no está claro a partir de la pregunta), la forma de mostrarlo como no verificado podría variar ... (visual) establecer el color de fondo a un tono claro de rojo, o (programático) cambiar el nombre utilizado rango para apuntar a un área en blanco para que otros complementos/macros no encuentren los datos.

Un usuario que debe verificar el libro de trabajo debería hacer clic en un botón (en el libro de trabajo o en una barra de herramientas) para indicar que lo ha verificado. Su código desharía los cambios anteriores y establecería un indicador que indica que el libro de trabajo ha sido verificado. Esto podría estar en una celda oculta en algún lugar del libro, o en las propiedades del módulo VBA.

Para recapitular ... al abrir, marque la bandera. Si no está configurado, cambie el libro de trabajo para que parezca no verificado. Si está configurado, entonces no se necesitan cambios. Cuando el usuario verifique el libro, configure el indicador y guárdelo permanentemente.

Espero que esto ayude!

+0

Háganme saber dónde he indicado dónde tengo problemas - puedo aclarar la pregunta un poco más ... – Ahmad

+0

Hmm .. Me gusta la idea de un estado verificado/no verificado (esto puede ser algo que podría hacer en el futuro) Estaba considerando un enfoque de estilo de tablero de instrumentos (un libro de trabajo temporal) que se desglosa por libro de trabajo/por hoja de trabajo para una visión general completa del estado en lugar de un indicador de libro de trabajo. Sin embargo, no puedo agregar/modificar nada en el libro de trabajo, ya que estos son formatos prescritos, podría eliminarlos o volver al estado original antes de guardarlos, pero prefiero no hacerlo. – Ahmad

+0

Para el "estado", puede guardar el valor en las propiedades de VBA del archivo. O agrega una hoja de trabajo oculta. O agregue un comentario a una celda específica ... –

1
  1. estoy usando el evento WorkbookBeforeClose correcta y efectiva es esta & uso eficiente del evento?

    No puedo encontrar ningún evento mejor para usar. Sin embargo, creo que un otro enfoque sería tener Save&Close función que utiliza el evento WorkbookBeforeSave

  2. ¿Debo utilizar el evento de nivel de aplicación o evento nivel de documento ?

    En el momento de escribir esto, diría que sí. Como no puedo crear un complemento a nivel de documento con las herramientas que tengo, esta es la mejor solución disponible. Si las herramientas hubieran sido disponibles, habría modificado las propiedades del documento _AssemblyName y _AssemblyLocation de los archivos relevantes. Sin embargo, habría cambiado la estrategia de solución usando plantillas y luego guardando los archivos según sea necesario. Además, antes de guardar, no haber explorado esto por completo, para agregar/eliminar las propiedades correctas del documento. El evento a nivel de documento se habría adecuado utilizando el enfoque descrito anteriormente.

  3. ¿Es normal el comportamiento descrito anteriormente?

    Sí, pero ¿por qué? Debido a que el complemento se engancha en el evento de nivel de aplicación, las verificaciones y la cancelación del evento impiden que la aplicación cierre más libros de trabajo. La clave aquí es el argumento de ref bool cancel (cancelar = falso permite el cierre normal del libro de trabajo (predeterminado), cancelar = verdadero evita que el libro de trabajo se cierre). Si me equivoco aquí, házmelo saber.

  4. Otras sugerencias son bienvenidos al utilizar eventos libro en un complemento

    Ver por encima de respuestas para los enfoques alternativos y el uso de diferentes eventos.

Cuestiones relacionadas