摘要:[C++][Office] Excel 增益集自訂另存新檔
在 Excel 增益集當中我們需要取得存檔之後的檔名,所以在 WorkbookBeforeSave 事件當中進行嘗試。
因為這個事件在存檔前就已經觸發了,無法取得使用者到底存成了什麼檔名,所以我們取消掉 Office 自己呼叫的 SaveAs Dialog,讓我們自行呼叫,這樣就可以讓使用者在我們自己產生的 Dialog 中存檔,進行後續動作。
呼叫 SaveAsDialog 的方式有兩種,各有優缺
如何自行呼叫 SaveAsDialog
1. 使用 Office::FileDialog,可以容易取得存檔後的檔名、附檔,但原本 PDF 及 XPS 檔的發佈選項將會不見
void CALLBACK CConnect::WorkbookBeforeSave(
Excel::_Workbook* Wb,
VARIANT_BOOL SaveAsUI,
VARIANT_BOOL* Cancel)
{
Office:: FileDialog* fileDialog;
*Cancel = true;
Wb->Application->get_FileDialog(Office::mosFileDialogSaveAs, &fileDialog);
if(fileDialog->Show() == VARIANT_TRUE)
{
fileDialog->Execute(); // 執行存檔
}
else
{
//Do something if Cancel
}
}
2. 使用 XlBuiltInDialog,原有的 SaveAsDialog
void CALLBACK CConnect::WorkbookBeforeSave(
Excel::_Workbook* Wb,
VARIANT_BOOL SaveAsUI,
VARIANT_BOOL* Cancel)
{
*Cancel = true;
CComPtr App(Wb->Application);
CComPtr dlg = App->Dialogs->GetItem(Excel::XlBuiltInDialog::xlDialogSaveAs);
if(dlg->Show() == VARIANT_TRUE)
{
_bstr_t fileName = Wb->Name;
_bstr_t fullName = Wb->FullName[0];
}
else
{
//Do something if Cancel
}
}
Office::FileDialog 存成 PDF 或 XPS 時 需要另行處理
基本上以上兩種都可以完成存檔,但使用 Office::FileDialog 時發現如果另存為 PDF 或 XPS 兩種格式文件時會有問題,檔案是儲存了沒錯,但是打開時兩種都出現格式錯誤的問題,將他們的副檔名再改為.xlsx 時又可以用 EXCEL 開啟,事實上根本就是假存檔真改副檔名罷了。
要另存成 PDF 或 XPS 時需要呼叫 ExportAsFixedFormat,所以延伸第一種 Dialog 寫法另做判斷
void CALLBACK CConnect::WorkbookBeforeSave(
Excel::_Workbook* Wb,
VARIANT_BOOL SaveAsUI,
VARIANT_BOOL* Cancel)
{
Office:: FileDialog* fileDialog;
*Cancel = true;
Wb->Application->get_FileDialog(Office::mosFileDialogSaveAs, &fileDialog);
if(fileDialog->Show() == VARIANT_TRUE)
{
Office::FileDialogSelectedItemsPtr selectedItems = fileDialog->SelectedItems;
_bstr_t path = selectedItems.Item(1);
WCHAR ext[_MAX_FNAME]={0x00};
_wsplitpath(path, NULL, NULL, NULL, ext);
if(ext == L".pdf")
{
Wb->ExportAsFixedFormat(Excel::xlTypePDF, L"C:\myExportPDF.pdf", vtMissing,
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, vtMissing);
}
else if(ext == L".xps)
{
Wb->ExportAsFixedFormat(Excel::xlTypeXPS, L"C:\myExportXPS.xps", vtMissing,
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, vtMissing);
}
else
{
fileDialog->Execute(); // 執行一般格式存檔
}
}
}
如何取得存檔後的檔名
使用 Office::FileDialog,從 dialog 內取得參數
bool isCustomSaveAs = false;
void CALLBACK CConnect::WorkbookBeforeSave(
Excel::_Workbook* Wb,
VARIANT_BOOL SaveAsUI,
VARIANT_BOOL* Cancel)
{
if(isCustomSaveAs)
return;
// 沒有顯示 UI 表示他為"存檔"事件
if(SaveAsUI != VARIANT_TRUE)
return;
isCustomSaveAs = true; //fileDialog.Show() 會再次觸發此事件,需要濾掉
*Cancel = true; // 取消原本的另存新檔行為
// 自訂另存新檔流程
CcomPtr App(Wb->Application);
Office::FileDialog* fileDialog;
App->get_FileDialog(Office::msoFileDialogSaveAs, &fileDialog);
if(fileDialog->Show() != VARIANT_TRUE)
return;
// 取得存檔後的檔名
Office::FileDialogSelectedItemsPtr items = fileDialog->SelectedItems;
_bstr_t fileName = selectedItems->Items(1);
// 取得存檔的類型
int typeIndex = fileDialog->FilterIndex;
Office::FileDialogFilterPtr flterPtr = fileDialog->GetFilters()->Item(typeIndex);
_bstr_t ext = flterPtr->GetExtensions();
}
使用 XlBuiltInDialog,從 Workbook 取得檔名
void CALLBACK CConnect::WorkbookBeforeSave(
Excel::_Workbook* Wb,
VARIANT_BOOL SaveAsUI,
VARIANT_BOOL* Cancel)
{
*Cancel = true;
CComPtr App(Wb->Application);
CComPtr dlg = App->Dialogs->GetItem(Excel::XlBuiltInDialog::xlDialogSaveAs);
if(dlg->Show() == VARIANT_TRUE)
{
// 存成 XPS、PDF 時取不到存檔後的檔名,或許有方法,但我還沒找到
_bstr_t fileName = Wb->Name;
_bstr_t fullName = Wb->FullName[0];
}
else
{
//Do something if Cancel
}
}