2017-05-19 2 views
2

Actuellement, j'essaie d'annuler l'événement de fermeture d'Excel en utilisant Python et win32com. J'ai déjà réussi à gérer ce problème avec IronPython il y a un mois. Mais pour d'autres objectifs de mon département des entreprises cela devrait aussi être possible avec Python. Suivi, vous verrez deux extraits. Le premier contiendra le code IronPython travailAnnuler l'événement de fermeture d'Excel en utilisant python et win32com

import clr 
clr.AddReference("Microsoft.Office.Interop.Excel") 
clr.AddReference("System.Windows.Forms") 
from Microsoft.Office.Interop import Excel 
from System.Windows.Forms import Form, Application, MessageBox, MessageBoxButtons, MessageBoxIcon, DialogResult 

class CloseEventTry(Form): 
    def __init__(self): 
     excel = Excel.ApplicationClass() 
     excel.Visible = True 
     excel.DisplayAlerts = False 
     self.workbooks = excel.Workbooks.Add() 
     self.Text = "Dummy GUI Window"  
     #link "BeforeCloseEvent" to the "beforeClose" method 
     self.workbooks.BeforeClose +=Excel.WorkbookEvents_BeforeCloseEventHandler(self.beforeClose) 

    def beforeClose(self, cancel): 
     print type(cancel) #Type: 'StrongBox[bool] 
     choice = MessageBox.Show("Close Excel", "Close", MessageBoxButtons.YesNo, MessageBoxIcon.Information) 
     if choice == DialogResult.Yes: 
      cancel.Value = False #do't cancel the close action 
      self.Close() 
     elif choice == DialogResult.No: 
      cancel.Value = True  #prevent excel from closing 

Application.Run(CloseEventTry()) 

Le second contiendra la version avec Python et win32com. Celui-ci est basé sur mon extrait IronPython et l'échantillon de ce lien

https://win32com.goermezer.de/microsoft/office/events-in-microsoft-word-and-excel.html

import clr 
clr.AddReference("System.Windows.Forms") 
from System.Windows.Forms import Form, Application, MessageBox, MessageBoxButtons, MessageBoxIcon, DialogResult 
import win32com.client as win32 

#workbook event handler class. Needed according to this example https://win32com.goermezer.de/microsoft/office/events-in-microsoft-word-and-excel.html 
class WorkBookEvents(object): 
    def OnBeforeClose(self, cancel): 
     print(type(cancel)) #Type: class 'bool' 
     choice = MessageBox.Show("Close Excel", "Close", MessageBoxButtons.YesNo, MessageBoxIcon.Information) 
     if choice == DialogResult.Yes: 
      #do't cancel the close action => raises AttributeError: 'bool' object has no attribute 'Value' Exception 
      cancel.Value = False  
      self.Close() 
     elif choice == DialogResult.No: 
      #prevent excel from closing => raises AttributeError: 'bool' object has no attribute 'Value' Exception 
      cancel.Value = True  

class CloseEventTry(Form): 
    def __init__(self): 
     excel = win32.DispatchEx('Excel.Application') 
     excel.Visible = True # makes the Excel application visible to the user 
     excel.DisplayAlerts = False 
     self.Text = "Dummy GUI Window" 
     self.workbooks = excel.Workbooks.Add() 
     #define event handler according to this example https://win32com.goermezer.de/microsoft/office/events-in-microsoft-word-and-excel.html 
     self.workbooks = win32.DispatchWithEvents(self.workbooks, WorkBookEvents) 

Application.Run(CloseEventTry()) 

Comme vous le verrez, je pouvais connecter à l'événement « OnBeforeClose », mais ne peut pas annuler l'événement à proximité comme je l'ai fait avec la version IronPython. Comme mentionné dans le commentaire du dernier extrait de code, la version Python déclenche une exception AttributeError. En outre, vous pouvez également voir que les types de la variable "cancel" nécessaire des gestionnaires d'événements ont deux types différents. Dans la version IronPython c'est un "StrongBox [bool]". D'un autre côté, le type de la version Python est un type commun "class 'bool'" (ce qui explique l'exception). C'est de cette façon que j'ai essayé de simplement taper

cancel = True #prevent excel from closing 

Mais de cette façon, Excel se ferme de toute façon. J'ai aussi fait des recherches mais je n'ai pas trouvé de solution à ce problème. Mon hypothèse est qu'il y a une sorte d'emballage nécessaire?

+0

Avez-vous essayé pythonnet? – denfromufa

+0

Tout d'abord, merci pour votre réponse. Vous voulez dire en ajoutant une référence à 'Microsoft.Office.Interop.Excel' et utiliser le code égal à celui de IronPython? Ce fut la première chose que j'ai essayé de faire, mais il a lancé l'exception suivante System.IO.FileNotFoundException: Impossible de trouver l'assembly 'Microsoft.Office.Interop.Excel'. at Python.Runtime.CLRModule.AddReference (nom de la chaîne) –

+1

Vous devez trouver l'emplacement de cet assembly 'Microsoft.Office.Interop.Excel'. Sinon, vous pouvez le télécharger depuis Nuget. Ajoutez ensuite une référence en ajoutant son emplacement à sys.path. Pour pythonnet il y a des instructions spéciales pour accéder aux objets com dynamiques: https://github.com/pythonnet/pythonnet/issues/260 – denfromufa

Répondre

1

vous pouvez obtenir le même comportement que la version IronPython en retournant la valeur d'annulation souhaitée, par ex.

return True 

si vous souhaitez annuler l'événement Close.

Cordialement

+0

Merci qui a fonctionné pour moi –