在 Delphi 應用程式中,我多年來一直使用以下代碼將 xlxs 匯出為 pdf:
function TExportTool.ExportExcelToPDF(aFileName, aNewFileName: String): Boolean;
// reference : http://embarcadero.newsgroups.archived.at/public.delphi.oleautomation/200811/081103142.html
// unluckily the link above is dead
{- Sheet is counted from 1 and upwards !! }
Var
App,oWB,oSheet : OleVariant;
begin
Result := False;
App:= CreateOleObject('Excel.Application');
Try
App.Visible:= 0;
oWb := App.WorkBooks.Open(ExpandUNCFileName(afilename),1); // Open read only
Try
oSheet := oWB.ActiveSheet;
oSheet.ExportAsFixedFormat(0, //xlTypePDF is constant 0
aNewFileName,
EmptyParam,
EmptyParam,
EmptyParam, // this should be IgnorePrintAreas
EmptyParam,
EmptyParam,
EmptyParam,
EmptyParam
);
Finally
End;
Result := True;
Finally
App.Quit;
App:= UnAssigned;
End;
end;
// IMPROVED WORKING CODE FOLLOWS
function TExportTool.ExportExcelToPDF(aFileName, aNewFileName: String): Boolean;
// reference : http://embarcadero.newsgroups.archived.at/public.delphi.oleautomation/200811/081103142.html
{- Sheet is counted from 1 and upwards !! }
procedure RestoreOriginalPrintArea (oSheet: OleVariant);
// Excel loses print area settings in non-English version of application when file is opened using automation:
// https://stackoverflow.com/questions/71379893/exportasfixedformats-ignoreprintareas-parameter-seems-not-to-have-effect
var
i:Integer;
begin
for i:= 1 to oSheet.Names.Count do
begin
if VarToStr(oSheet.Names.Item(i).Name).EndsWith('!Print_Area') then
begin
oSheet.PageSetup.PrintArea:='Print_area';
Break;
end;
end;
end;
Var
App,oWB,oSheet : OleVariant;
i:Integer;
begin
Result := False;
App:= CreateOleObject('Excel.Application');
Try
App.Visible:= 0;
oWb := App.WorkBooks.Open(ExpandUNCFileName(afilename),1); // Open read only
Try
oSheet := oWB.ActiveSheet;
RestoreOriginalPrintArea(oSheet); // workaround
oSheet.ExportAsFixedFormat(0, //xlTypePDF is constant 0
aNewFileName,
0, // standard quality = 0, Max quality = 1
false, //include doc properties
false, //ignore print area
EmptyParam,
EmptyParam,
EmptyParam,
EmptyParam
);
Finally
End;
Result := True;
Finally
oWB.Close(false); // better to close the WorkBook too
App.Quit;
App:= UnAssigned;
End;
end;
現在我意識到使用此代碼創建的 pdf 的行為就像使用“忽略列印區域”選項從 Excel 保存到 pdf 時一樣(它是從 Excel 功能匯出到 pdf 的選項之一)。
因此,我決定也從代碼中“取消選中”該復選框,并研究了ExportAsFixedFormat(參考此處)的引數。
第五個引數是IgnorePrintAreas,所以我假設將 False 傳遞給它,列印區域將被忽略。
我嘗試了幾種常識解決方案,包括:
- 僅傳遞該引數(傳遞 True 或 False )
- 傳遞所有前 5 個引數(以防它們在運行時是必需的)
but no result: the pdf created by my application still "ignores the print areas".
Does anyone has a suggestion or has experience on this specific subject to give me a pointer to fix this issue?
Thanks.
UPDATE
Thanks to the useful accepted answer I appended to the code above the solution for reference, notice two things:
- the RestoreOriginalPrintArea procedure that contains the workaround
- the call to oWB.Close(false) at the end
uj5u.com熱心網友回復:
錯誤的根本原因:
使用自動化打開檔案時,Excel 會丟失非英文版應用程式中的列印區域設定。
為什么會這樣:
當您在作業表中定義列印區域時,Excel 會在內部創建一個命名范圍。它有兩個定義其名稱的屬性:
Name此屬性始終采用這種形式WorksheetsName!Print_Area(如果作業表的名稱包含一些特殊字符,則它也用單引號括起來)。NameLocal具有類似的結構,但第二部分被翻譯成應用程式的語言。
這就是您在 Excel 中打開檔案并在 VBA 中檢查這些屬性時的樣子,但是當您使用自動化打開同一檔案時(例如使用相關代碼),則NameLocal不再翻譯。此錯誤導致命名范圍無法正確識別為列印區域。oSheet.PageSetup.PrintArea回傳一個空字串。
解決方法:
使用以下命令打開檔案后恢復原始列印區域:
oSheet.PageSetup.PrintArea:='Print_Area';
這行代碼在sheet中沒有定義列印區域時會拋出例外,所以有兩種選擇:
- 將線放在
try..except塊內。 - 迭代
Names集合并查找以Name結尾!Print_Area,例如:
var i:Integer;
for i:= 1 to oSheet.Names.Count do
begin
if VarToStr(oSheet.Names.Item(i).Name).EndsWith('!Print_Area') then
begin
oSheet.PageSetup.PrintArea:='Print_area';
Break;
end;
end;
其他重要變化:
因為檔案可能已被修改,您還需要添加:
oWB.Close(false); //do not save changes
before closing the application, otherwise each call to this function would result in another Excel process still running invisible.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/441861.html
標籤:delphi file-conversion excel-automation
