![](/img/trans.png)
[英]c++ Excel OLE automation. Setting the values of an entire cell-range 'at once'
[英]OLE Automation - Ghost Excel Instance in Task Manager
我正在使用wxAutomationObject
將數據導出到 MS Excel。 我創建了一些幫助類 ExcelApp、ExcelWorkbook 等......所有這些都繼承自wxAutomationObject
。
簡而言之,ExcelApp如下:
class ExcelApp :public wxAutomationObject
{
public:
ExcelApp(WXIDISPATCH* dispatchPtr = NULL);
~ExcelApp() = default;
void Quit();
std::unique_ptr<ExcelWorkbook> CreateWorkbook(bool Visible = true);
std::vector<std::unique_ptr<ExcelWorkbook>> GetOpenedWorkbooks();
long GetNumberofOpenedWorkbooks() const;
private:
wxAutomationObject m_App;
};
構造函數實現如下:
ExcelApp::ExcelApp(WXIDISPATCH* dispatchPtr):wxAutomationObject(dispatchPtr)
{
if (!m_App.GetInstance("Excel.Application"))
throw std::exception("An instance of Excel object could not be created.");
}
為了創建一個工作簿,我曾經使用以下代碼:
std::unique_ptr<ExcelWorkbook> ExcelApp::CreateWorkbook(bool Visible)
{
auto wb = std::make_unique<ExcelWorkbook>();
bool suc = m_App.GetObject(*wb, "Workbooks.Add");
if (!suc)
return nullptr;
if (Visible)
m_App.PutProperty("Visible", true);
return std::move(wb);
}
這整個 OLE 實現是動態菜單的一部分。 菜單事件處理程序的部分代碼是:
void MyFrame::OnExportToExcelButtonHandler(wxCommandEvent& event)
{
auto item = static_cast<wxMenu*>(event.GetEventObject());
std::unique_ptr<ExcelWorkbook> xlsWB ((ExcelWorkbook*)event.GetEventUserData());
bool CreateNewWB = false;
try
{
//Export either the entire workbook or the active worksheet to a new Workbook
if (xlsWB == nullptr)
{
auto xlsApp = ExcelApp();
xlsWB = std::move(xlsApp.CreateWorkbook());
CreateNewWB = true;
}
在導出數據和格式化方面,一切正常。 但是,關閉創建的 Workbooks 后Excel.exe 仍然保留在任務欄列表中。 我想知道我可能會錯過什么?
順便說一句,我嘗試了 wxWidgets 附帶的非常基本的示例,退出后似乎沒有 Excel 的幽靈實例。 我
我使用 VS 2019 在 Windows 10 上使用 wxWidgets 3.1.4。
編輯1:
生成動態菜單的功能區按鈕:
void MyFrame::OnExportToExcelButtonClicked(wxRibbonButtonBarEvent& event)
{
auto excel = sys::win32::ole::ExcelApp();
auto PrepareMenu = [&](wxMenu* Menu)
{
try
{
wxMenuItem* item1 = Menu->Append(wxID_ANY, "New Excel Workbook");
item1->SetBitmap(wxArtProvider::GetBitmap(wxART_NEW));
Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExportToExcelButtonHandler, this, item1->GetId());
auto wbs = excel.GetOpenedWorkbooks();
if (wbs.size() > 0)
{
for (int i = 0; i < wbs.size(); ++i)
{
auto ExcelWB = std::move(wbs[i]);
wxMenuItem* item1 = Menu->Append(wxID_ANY, ExcelWB->GetFullName());
Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExportToExcelButtonHandler, this, item1->GetId(), wxID_ANY, ExcelWB.release());
}
}
}
}
問題似乎源於以下行:
Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExportToExcelButtonHandler, this, item1->GetId(), wxID_ANY, ExcelWB.release());
ExcelWB
指針現在歸 wxWidgets 系統所有,因此保留了一個引用,因此保留了幽靈 Excel.exe。
為了解決這個問題,我在以下過程中添加了:
void MyFrame::OnExportToExcelButtonHandler(wxCommandEvent& event)
{
Unbind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExportToExcelButtonHandler, this, event.GetId(), wxID_ANY, xlsWB.get());
但問題仍然存在。 我不確定如何正確擺脫菜單現在擁有的指針。 我用 shared_ptr 重新設計了一些部分,但沒有幫助。
你可能已經這樣做了,但只是為了確定。
調試此類事情時,請確保應用程序實例始終可見,以便您可以看到它何時卡住等待用戶輸入,例如,要求保存修改后的工作簿,防止它退出。
我已經編寫了基於 wxWidgets 的 MS Excel 自動化包裝器wxAutoExcel (它對 Excel 對象使用共享指針而不是唯一指針),並且我從未遇到過應用程序幽靈,除非我在調試時終止了我的應用程序,而沒有處理 ZC1D81AF563E58D4ED8FDCZD9 對象。
順便說一句,我不明白為什么您的ExcelApp
都派生自wxAutomationObject
並將wxAutomationObject
作為成員變量( m_App
)。 ExcelApp
ctor 中使用的IDispatch
有什么用?
最后,似乎我使用以下步驟解決了這個問題:
wxAutomationObject
繼承對象都通過 std::unique_ptr 傳遞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.