2010-05-04 24 views
5

Başka hi bütün eksik Kapat olay,Excel otomasyon:

C# Interop aracılığıyla Excel otomasyonu yapıyorum ve bir çalışma kitabı kapandığında haberdar olmak istiyorum. Ancak, çalışma kitabında Kapatma olayı veya uygulamada bir Çık olayı yoktur.

Bunu daha önce yapmış olan var mı? Kapsanan çalışma kitabına tepki veren bir kod parçasını nasıl yazabilirim (yalnızca çalışma kitabı gerçekten kapalıysa çalıştırılırsa çalıştırılır)? İdeal olarak, çalışma kitabını kapattıktan sonra olması gerekir, böylece tüm değişiklikleri yansıtacak şekilde dosyaya güvenebilirim. Bugüne kadar ne buldum yaklaşık

Detayları:

bir BeforeClose() olay yok, ancak kaydedilmemiş değişiklikler varsa kullanıcı, onları kurtarmak için olsun isteniyor önce bu olay ortaya elimden an çok olayı işleyin, son dosyam yok ve COM nesnelerini yayınlayamıyorum, gerek duyduğum/yapmam gereken şeyler. Kullanıcının kapanışı iptal etmeyi seçebileceğinden, çalışma kitabının gerçekten kapalı olup olmayacağını bile bilmiyorum.

Daha sonra bir BeforeSave() olayı var. Bu nedenle, kullanıcı kaydedilmemiş değişiklikleri kaydetmek için "Evet" i seçerse, Önceden Kaydetme() BeforeClose() öğesinden sonra çalıştırılır. Bununla birlikte, kullanıcı "İptal" seçeneğini seçerse, "dosya-> kaydet" seçeneğine ulaşırsa, aynı olay sırası yürütülür. Ayrıca, kullanıcı "Hayır" seçerse, BeforeSave() hiç çalıştırılmaz. Aynı şey kullanıcının bu seçeneklerden herhangi birini tıklamadığı sürece de geçerlidir.

cevap

4

Bir yoklama benzeri bir yaklaşım kullanarak yazarlardan oluşturduk ve çalışır: gözlemlemek için çalışma kitabı Verilen

, ben periyodik çalışma kitapları koleksiyonunda bu çalışma kitabını bulmaya çalışır bir iş parçacığı oluşturun.

(DisposableCom sınıf properly cleanup COM objects benim şimdiki çözümdür.)
Excel.Application app = wbWorkbook.Application; 
string sWorkbookName = wbWorkbook.Name; 

Thread overseeWorkbooksThread = new Thread(new ThreadStart(
    delegate() 
    { 
     bool bOpened = false; 

     Excel.Workbooks wbsWorkbooks = app.Workbooks; 
     using (new DisposableCom<Excel.Workbooks>(wbsWorkbooks)) 
     { 
      while (true) 
      { 
       Thread.Sleep(1000); 

       if (wbsWorkbooks.ContainsWorkbookProperly(sWorkbookName)) 
        bOpened = true; 
       else 
        if (bOpened) 
         // Workbook was open, so it has been closed. 
         break; 
        else 
        { 
         // Workbook simply not finished opening, do nothing 
        } 
      } 

      // Workbook closed 
      RunTheCodeToBeRunAfterWorkbookIsClosed(); 
     } 
    })); 

overseeWorkbooksThread.Start(); 

"ContainsWorkbookProperly" uzantısı yöntemlerine

şuna benzer: daha basit varsa

public static bool ContainsWorkbookProperly(this Excel.Workbooks excelWbs, 
    string sWorkbookName) 
{ 
    Excel.Workbook wbTemp = null; 
    try 
     wbTemp = excelWbs.Item(sWorkbookName); 
    catch (Exception) 
    { 
     // ignore 
    } 

    if (wbTemp != null) 
    { 
     new DisposableCom<Excel.Workbook>(wbTemp).Dispose(); 
     return true; 
    } 

    return false; 
} 

Hala ilgi olacağını veya daha iyi bir çözüm.

-1

Her iki etkinliği de kullanabilir misiniz? BeforeClose() öğesinde bir bayrak ayarlanır, ardından Bayrağın() ayarlanıp işaretlenmediğine bakın. BeforeClose() öğesinin tetiklenmesi ve BeforeSave() öğesinin olmaması durumunda, sıfırlamanız için bir yönteme ihtiyacınız olacaktır. Bununla ilgili başka bir şey olup olmadığından emin değil.

Düzenleme: Bu, "olayların tam olarak aynı sırayla yürütülmesi" ile kapsanmış gibi görünüyor. Ancak, onu sıfırlamanın bir yolunu (başka bir "İptal" etkinliği) bulabilirseniz, işe yarayabilir.

+0

Merhaba Nelson - evet, bunu zaten yaptım. Sorun şu ki "ve BeforeSave()" teklifinizin bir parçası semidecidable. Eğer çağrılmazsa, bekleyebilirim ama asla bunun iptal edilip edilmediğine karar vermez, hayır seçmez, ya da henüz herhangi bir düğmeye henüz tıklamamıştır. – chiccodoro

3

Bu benim kodu değil, ama bu benim için bir tedavi çalıştı:

https://gist.github.com/jmangelo/301884

Kopya yapıştır: Ben kullanıldığında

using System; 
using Excel = Microsoft.Office.Interop.Excel; 

namespace Helpers.Vsto 
{ 
    public sealed class WorkbookClosedMonitor 
    { 
     internal class CloseRequestInfo 
     { 
      public CloseRequestInfo(string name, int count) 
      { 
       this.WorkbookName = name; 
       this.WorkbookCount = count; 
      } 

      public string WorkbookName { get; set; } 

      public int WorkbookCount { get; set; } 
     } 

     public WorkbookClosedMonitor(Excel.Application application) 
     { 
      if (application == null) 
      { 
       throw new ArgumentNullException("application"); 
      } 

      this.Application = application; 

      this.Application.WorkbookActivate += Application_WorkbookActivate; 
      this.Application.WorkbookBeforeClose += Application_WorkbookBeforeClose; 
      this.Application.WorkbookDeactivate += Application_WorkbookDeactivate; 
     } 

     public event EventHandler<WorkbookClosedEventArgs> WorkbookClosed; 

     public Excel.Application Application { get; private set; } 

     private CloseRequestInfo PendingRequest { get; set; } 

     private void Application_WorkbookDeactivate(Excel.Workbook wb) 
     { 
      if (this.Application.Workbooks.Count == 1) 
      { 
       // With only one workbook available deactivating means it will be closed 
       this.PendingRequest = null; 

       this.OnWorkbookClosed(new WorkbookClosedEventArgs(wb.Name)); 
      } 
     } 

     private void Application_WorkbookBeforeClose(Excel.Workbook wb, ref bool cancel) 
     { 
      if (!cancel) 
      { 
       this.PendingRequest = new CloseRequestInfo(
        wb.Name, 
        this.Application.Workbooks.Count); 
      } 
     } 

     private void Application_WorkbookActivate(Excel.Workbook wb) 
     { 
      // A workbook was closed if a request is pending and the workbook count decreased 
      bool wasWorkbookClosed = true 
       && this.PendingRequest != null 
       && this.Application.Workbooks.Count < this.PendingRequest.WorkbookCount; 

      if (wasWorkbookClosed) 
      { 
       var args = new WorkbookClosedEventArgs(this.PendingRequest.WorkbookName); 

       this.PendingRequest = null; 

       this.OnWorkbookClosed(args); 
      } 
      else 
      { 
       this.PendingRequest = null; 
      } 
     } 

     private void OnWorkbookClosed(WorkbookClosedEventArgs e) 
     { 
      var handler = this.WorkbookClosed; 

      if (handler != null) 
      { 
       handler(this, e); 
      } 
     } 
    } 

    public sealed class WorkbookClosedEventArgs : EventArgs 
    { 
     internal WorkbookClosedEventArgs(string name) 
     { 
      this.Name = name; 
     } 

     public string Name { get; private set; } 
    } 
} 

Karşılığında ismi onu değiştirdi Çalışma kitabını referans olarak kullanmak için çalışma kitabı.

İlgili konular