2013-04-05 22 views
0

原來這就是我需要做的編程方式保存在打開的窗口中的Excel表格,到文件

有它連接到一些服務器,並以每秒約15-20項的速度從中提取數據的程序

就在當與服務器的連接已經建立的那一刻,一個Excel窗口中打開,並從服務器獲取所有條目,動態移動成Excel表格

但是,所有的內容仍然在RAM中,即Excel文件本身僅在我們嘗試關閉Excel窗口並出現「另存爲...」對話框時才創建

正如你可能已經明白,我不希望保存每次手動文件,因此我需要一些方法以編程方式保存Excel表格在打開的窗口中,到一個文件

有什麼辦法做到這一點?

+0

您是否嘗試過使用EPPlus? – Ron 2013-04-05 15:06:23

+0

我簡要介紹了EPPlus,但看不到任何解決方案。 EPPlus專門用於處理Excel表格,而我的問題基本上是關於處理系統中打開的窗口 – mangusta 2013-04-05 17:53:39

+0

已將其表格填充的Excel實例是否在服務器上運行?您是否需要將此作爲服務運行,或者您是否會手動運行該程序以保存Excel工作簿? – 2013-04-06 03:42:01

回答

0

如果您沒有在服務器上運行此操作,並且您不介意手動觸發Excel保存,則可以使用Interop創建將連接到Excel實例的內容。下面將連接到Excel實例,並返回一個Excel.Workbook對象指定的工作簿的名稱:

private Excel.Workbook GetWorkbook(string workbookName) 
{ 
    Excel.Window window = null;  // Excel window object from which application is grabbed 
    Excel.Application app = null; // Excel instance from which we get all the open workbooks 
    Excel.Workbooks wbs = null;  // List of workbooks 
    Excel.Workbook wb = null;  // Workbook to return 
    EnumChildCallback cb;   // Callback routine for child window enumeration routine 
    List<Process> procs = new List<Process>();   // List of processes 

    // Get a full list of all processes that have a name of "excel" 

    procs.AddRange(Process.GetProcessesByName("excel")); 

    foreach (Process proc in procs) 
    { 
     // Make sure we have a valid handle for the window 

     if ((int)proc.MainWindowHandle > 0) 
     { 
      // Get the handle of the child window in the current Excel process 

      int childWindow = 0; 
      cb = new EnumChildCallback(EnumChildProc); 
      EnumChildWindows((int)proc.MainWindowHandle, cb, ref childWindow); 

      // Make sure we got a valid handle 

      if (childWindow > 0) 
      { 
       // Get the address of the child window so that we can talk to it and 
       // get all the workbooks 

       const uint OBJID_NATIVEOM = 0xFFFFFFF0; 
       Guid IID_IDispatch = 
        new Guid("{00020400-0000-0000-C000-000000000046}"); 
       int res = AccessibleObjectFromWindow(childWindow, OBJID_NATIVEOM, 
        IID_IDispatch.ToByteArray(), ref window); 

       if (res >= 0) 
       { 
        app = window.Application; 
        wbs = app.Workbooks; 

        // Loop through all the workbooks within the current Excel window 
        // to see if any match 

        for (int i = 1; i <= wbs.Count; i++) 
        { 
         wb = wbs[i]; 

         if (wb.Name == workbookName) 
         { 
          break; 
         } 

         wb = null; 
        } 
       } 
      } 
     } 

     // If we've already found our workbook then there's no point in continuing 
     // through the remaining processes 

     if (wb != null) 
     { 
      break; 
     } 
    } 

    Release(wbs); 
    Release(app); 
    Release(window); 

    return wb; 
} 

Release()方法稱爲上面簡單地將引用設置爲null,呼籲他們Marshal.FinalReleaseComObject(),否則你最終無頭實例的Excel到處都是。

您還需要以下進行一些功能搶到窗口:

private delegate bool EnumChildCallback(int hwnd, ref int lParam); 

[DllImport("User32.dll")] 
private static extern bool EnumChildWindows(int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam); 

[DllImport("Oleacc.dll")] 
private static extern int AccessibleObjectFromWindow(int hwnd, uint dwObjectID, byte[] riid, ref Excel.Window ptr); 

private bool EnumChildProc(int hwndChild, ref int lParam) 
{ 
    // Get the name of the class that owns the passed-in window handle 

    StringBuilder buf = new StringBuilder(128); 
    GetClassName(hwndChild, buf, 128); 

    // If the class name is EXCEL7 then we've got an valid Excel window 

    if (buf.ToString() == "EXCEL7") 
    { 
     lParam = hwndChild; 
     return false; 
    } 

    return true; 
} 

[DllImport("User32.dll")] 
private static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount); 

一旦你的工作簿,然後你可以叫Workbook.SaveAs()保存它。

+0

會彈出「另存爲...」對話框嗎?我不應該手動觸發Excel保存,應該由程序自動完成。 (考慮到我們希望將Excel表保存到的文件名) – mangusta 2013-04-07 11:55:03

+0

@mangusta您可以通過使用SaveAs()調用並在其中指定文件名來防止彈出另存爲對話框。看看[這裏](http://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.workbook.saveas(v = vs.100).aspx)。 – 2013-04-07 17:49:02

相關問題