sig*_*gil 5 c# excel office-interop
我正在尝试获取所有当前打开的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);
}
Run Code Online (Sandbox Code Playgroud)
但这只会获得第一个打开的Excel实例和最近打开的实例,因此在这两个实例之间打开的任何工作簿都不会在列表中。
我也开始探索此SO问题的答案中博客链接中描述的解决方案,并尝试使用博客条目中建议的代码访问“运行对象表”:
IBindCtx bc;
IRunningObjectTable rot;
CreateBindCtx(0, out bc);
bc.GetRunningObjectTable(out rot);
Run Code Online (Sandbox Code Playgroud)
这里的问题是,CreateBindCtx实际上接受a UCOMIBindCTX代替IBindCTX,但是UCOMIBindCTX对于MSDN已经过时了。
有没有一种更简单的方法可以执行我想做的事情:获取Workbook与所有打开的Excel书籍相对应的对象列表?
好的,我找到了一种方法来做到这一点。描述该解决方案的博客似乎不再可用,但有一个Google 缓存版本。
我稍微修改了代码,以便构造函数接受 MainWindowHandle,因为我正在迭代所有进程的句柄。
班级如下。我留下了 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4922 次 |
| 最近记录: |