6

現在開いているすべての Excel ワークブックのリストを取得しようとしています。これにより、ユーザーはデータを取得するワークブックを選択できます。

私はこれを試しました:

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

ただし、これは Excel の最初に開いたインスタンスと最後に開いたインスタンスのみを取得するため、これら 2 つの間に開いたブックは一覧に表示されません。

また、この SO の質問への回答のブログ リンクで説明されているソリューションの調査を開始し、ブログ エントリで提案されているコードを使用して、実行中のオブジェクト テーブルにアクセスしようとしました。

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

ここでの問題は、実際には の代わりに をCreateBindCtx受け入れますが、MSDNでは廃止されていることです。UCOMIBindCTXIBindCTXUCOMIBindCTX

私がやろうとしていることを行うためのより簡単な方法はありますか:Workbook開いているすべての Excel ブックに対応するオブジェクトのリストを取得しますか?

4

3 に答える 3

3

わかりました、これを行う方法を見つけました。解決策を説明しているブログはもう利用できないようですが、Google のキャッシュ バージョンがあります。

すべてのプロセスのハンドルを反復処理しているため、コンストラクターが MainWindowHandle を受け入れるようにコードを少し変更しました。

クラスは以下の通りです。このコードは、Windows OS の管理に関する現在の知識を超えているため、Andrew Whitechapel のコメントをいくつか残して、何が起こっているのかを説明しました。

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

    }
}
于 2012-12-10T20:07:06.267 に答える
0

このコードは、最後のコメントのリソース (リンク) と提供されたコードを使用してまとめられました。これにより、開いているすべてのワークブック名​​が取り込まれます。

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;
}
于 2012-12-10T18:53:29.600 に答える
0
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();
            }
        }
    }
}
于 2016-02-18T20:09:54.137 に答える