[C++][Office] Excel 增益集自訂另存新檔及存成XPS、PDF問題

  • 2163
  • 0

摘要:[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
	}
}