简体   繁体   English

找到所有打开的Excel工作簿

[英]find all open Excel workbooks

I'm trying to get a list of all currently open Excel workbooks, so that the user can select which one of them to get some data from. 我正在尝试获取所有当前打开的Excel工作簿的列表,以便用户可以选择从哪一个获取一些数据。

I tried this: 我试过这个:

List<string> excelList = new List<string>();
Process[] processList = Process.GetProcessesByName("excel");
foreach (Process p in processList)
{
 excelList.Add(p.MainWindowTitle);
 Console.WriteLine(p.MainWindowTitle);
}

But that only gets the first open instance of Excel and the most recently opened instance, so any workbooks that were opened between those two aren't in the list. 但这只能获得Excel的第一个打开实例和最近打开的实例,因此在这两个之间打开的任何工作簿都不在列表中。

I also started exploring the solution described in the blog link in the answer to this SO question , and tried to get access to the Running Object Table with the code suggested in the blog entry: 我也开始在这个SO问题的答案中探索博客链接中描述的解决方案,并尝试使用博客条目中建议的代码访问运行对象表:

IBindCtx bc;
IRunningObjectTable rot;
CreateBindCtx(0, out bc);
bc.GetRunningObjectTable(out rot);

Problem here is that CreateBindCtx actually accepts a UCOMIBindCTX instead of IBindCTX , but UCOMIBindCTX is obsolete per MSDN . 这里的问题是, CreateBindCtx实际上接受UCOMIBindCTX代替IBindCTX ,但UCOMIBindCTX每过时MSDN

Is there a simpler way to do what I'm trying to do: get a list of Workbook objects corresponding to all the open Excel books? 有没有更简单的方法来做我正在尝试做的事情:获取与所有打开的Excel书籍相对应的Workbook对象列表?

Ok, I found a way to do this. 好的,我找到了一种方法来做到这一点。 The blog that describes the solution appears to no longer be available, but there is a Google cached version . 描述解决方案的博客似乎不再可用,但有一个Google缓存版本

I slightly adapted the code so that the constructor accepts a MainWindowHandle, since I'm iterating through the handles for all processes. 我略微调整了代码,以便构造函数接受MainWindowHandle,因为我正在迭代所有进程的句柄。

The class is as follows. 课程如下。 I've left some of Andrew Whitechapel's comments in to explain what's happening, since this code is beyond my present knowledge of Windows OS management: 我已经留下了一些Andrew Whitechapel的评论来解释发生了什么,因为这段代码超出了我目前对Windows操作系统管理的了解:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;

namespace DTEExcel
{
    class ExcelApplicationRetriever
    {
        [DllImport("Oleacc.dll")]
        public static extern int AccessibleObjectFromWindow(
              int hwnd, uint dwObjectID, byte[] riid,
              ref Microsoft.Office.Interop.Excel.Window ptr);

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

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

        public delegate bool EnumChildCallback(int hwnd, ref int lParam);
        private EnumChildCallback cb;
        public Excel.Application xl;

        public ExcelApplicationRetriever(int winHandle)
        {
            // We need to enumerate the child windows to find one that
            // supports accessibility. To do this, instantiate the
            // delegate and wrap the callback method in it, then call
            // EnumChildWindows, passing the delegate as the 2nd arg.
            if (winHandle != 0)
            {
                int hwndChild = 0;
                cb = new EnumChildCallback(EnumChildProc);
                EnumChildWindows(winHandle, cb, ref hwndChild);

                // If we found an accessible child window, call
                // AccessibleObjectFromWindow, passing the constant
                // OBJID_NATIVEOM (defined in winuser.h) and
                // IID_IDispatch - we want an IDispatch pointer
                // into the native object model.
                if (hwndChild != 0)
                {
                    const uint OBJID_NATIVEOM = 0xFFFFFFF0;
                    Guid IID_IDispatch = new Guid(
                         "{00020400-0000-0000-C000-000000000046}");
                    Excel.Window ptr = null;

                    int hr = AccessibleObjectFromWindow(
                          hwndChild, OBJID_NATIVEOM,
                         IID_IDispatch.ToByteArray(), ref ptr);
                    if (hr >= 0)
                    {
                        // If we successfully got a native OM
                        // IDispatch pointer, we can QI this for
                        // an Excel Application (using the implicit
                        // cast operator supplied in the PIA).
                        xl = ptr.Application;
                    }
                }
            }
        }

        public bool EnumChildProc(int hwndChild, ref int lParam)
        {
            StringBuilder buf = new StringBuilder(128);
            GetClassName(hwndChild, buf, 128);
            if (buf.ToString() == "EXCEL7")
            {
                lParam = hwndChild;
                return false;
            }
            return true;
        }

    }
}

This code was put together using the resource (Link) in the last comment and the code you supplied. 此代码使用最后一条注释中的资源(链接)和您提供的代码放在一起。 This should pull in all open workbook names. 这应该拉入所有打开的工作簿名称。

using Excel = Microsoft.Office.Interop.Excel;        

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


// Callback passed to EnumChildWindows to find any window with the
// registered classname "paneClassDC" - this is the class name of
// PowerPoint's accessible document window.
public bool EnumChildProc(int hwnd, ref int lParam)
{
    StringBuilder windowClass = new StringBuilder(128);
    GetClassName(hwnd, windowClass, 128);
    s += windowClass.ToString() + "\n";
    if (windowClass.ToString() == "EXCEL7")
    {
        lParam = hwnd;
    }
    return true;
}

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


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


[DllImport("User32")]
public static extern int FindWindowEx(
    int hwndParent, int hwndChildAfter, string lpszClass,
    int missing);


// AccessibleObjectFromWindow gets the IDispatch pointer of an object
// that supports IAccessible, which allows us to get to the native OM.
[DllImport("Oleacc.dll")]
private static extern int AccessibleObjectFromWindow(
    int hwnd, uint dwObjectID,
    byte[] riid,
    ref Excel.Window ptr);


// Get the window handle for a running instance of PowerPoint.
internal List<String> GetAccessibleObject()
{

    List<String> workbookNames = new List<String>();
    try
    {
        // Walk the children of the desktop to find PowerPoint’s main
        // window.
        int hwnd = FindWindowEx(0, 0, "XLMAIN", 0);
        while(hwnd != 0)
        if (hwnd != 0)
        {
            // Walk the children of this window to see if any are
            // IAccessible.
            int hWndChild = 0;
            EnumChildCallback cb =
                new EnumChildCallback(EnumChildProc);
            EnumChildWindows(hwnd, cb, ref hWndChild);


            if (hWndChild != 0)
            {
                // OBJID_NATIVEOM gets us a pointer to the native 
                // object model.
                uint OBJID_NATIVEOM = 0xFFFFFFF0;
                Guid IID_IDispatch =
                    new Guid("{00020400-0000-0000-C000-000000000046}");
                Excel.Window ptr = null;
                int hr = AccessibleObjectFromWindow(
                    hWndChild, OBJID_NATIVEOM,
                    IID_IDispatch.ToByteArray(), ref ptr);
                if (hr >= 0)
                {
                    Excel.Application eApp = ptr.Application;
                    if (eApp != null)
                    {
                        foreach (Excel.Workbook wb in eApp.Workbooks)
                        {
                            workbookNames.Add(wb.FullName);
                        }
                        Marshal.ReleaseComObject(eApp);
                        GC.WaitForPendingFinalizers();
                        GC.Collect();
                    }
                }

                hwnd = FindWindowEx(0, hwnd, "XLMAIN", 0);
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.ToString());
    }
    return workbookNames;
}
public void closeOpenedFile(string file_name)
{
    //Excel Application Object
    Microsoft.Office.Interop.Excel.Application oExcelApp;
    //Get reference to Excel.Application from the ROT.
    if (Process.GetProcessesByName("EXCEL").Count() > 0)
    {
        oExcelApp = (Microsoft.Office.Interop.Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");

        foreach (Microsoft.Office.Interop.Excel.Workbook WB in oExcelApp.Workbooks)
        {
            //MessageBox.Show(WB.FullName);
            if (WB.Name == file_name)
            {
                WB.Save();
                WB.Close();
                //oExcelApp.Quit();
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM