2013-03-01 4 views
1

Как загрузить листы из шаблона в существующую книгу Excel (если нет существующей книги, а затем создать пустую первую).Excel Interop Load Template в существующую рабочую книгу

Я попытался

Excel.Application.Workbooks.Open("path"); 

это работает, но каждый раз, когда он создает новую сессию Excel, как это создание новой книги. Я не смог найти что-либо через Google о том, как загрузить данные в виде нового листа в существующую книгу.

+0

Когда вы говорите «существующая книга», вы имеете в виду тот, который в настоящее время открыт на машине пользователя? Если это так, вам нужно получить экземпляр Excel, в котором он находится первым. –

+0

Да, рабочая книга, открытая пользователем. – clicky

ответ

0

ответа (спасибо Jon49 @ NetOffice доски обсуждений: http://netoffice.codeplex.com/discussions/434906):

Excel.Application.Sheets.Add(Type:="TemplateWorkbookPath") 

Вы можете сделать это из своей переменной рабочей книги, которой вы являетесь в настоящее время , работающих в:

wkb.Application.Sheets.Add(Type:="TemplateWorkbookPath") 
1

Как вы узнали, только вызов Open() в рабочей книге создает новый экземпляр Excel и не подключается к текущему. То, что вам нужно, намного сложнее. Ниже приведен метод, который я использую для подключения к книге, название которого вы уже знаете (вы также можете настроить эту функцию, чтобы позволить пользователю выбрать один они хотят открыть):

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; 
} 

The Release() методы вызываемый выше, просто установите ссылки на нуль и назовите их 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); 
+0

Спасибо! Вы должны посмотреть на NetOffice - у них есть простой способ получить текущий экземпляр Excel, за исключением остальной части API, такой же, как MS Interop :( – clicky

+0

@Murtuza Согласен, NetOffice будет намного проще, к сожалению, я нахожусь в организации, которая не любит сторонние библиотеки. –

+0

@Murtuza Ответил ли этот вопрос на ваш вопрос? –

Смежные вопросы