テンプレートから既存のExcelブックにシートをロードするにはどうすればよいですか(既存のブックがない場合は、最初に空白のブックを作成します)。
私が試してみました
Excel.Application.Workbooks.Open("path");
これは機能しますが、新しいブックを作成しているときに新しいExcelセッションを作成するたびに。データを新しいシートとして既存の本に読み込む方法について、Googleで何も見つかりませんでした。
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;
}
上記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);
回答 (Jon49 @ NetOffice ディスカッション ボードに感謝: http://netoffice.codeplex.com/discussions/434906 ):
Excel.Application.Sheets.Add(Type:="TemplateWorkbookPath")
現在作業しているワークブック変数から実行できます。
wkb.Application.Sheets.Add(Type:="TemplateWorkbookPath")