ExportAsFixedFormat 的 IgnorePrintAreas 参数好像没有效果
ExportAsFixedFormat's IgnorePrintAreas parameter seems not to have effect
在一个 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:
//
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 时的行为(它是从 [= 导出到 pdf 的选项之一) 50=] 特征)。
所以我决定也从代码中“取消选中”该复选框,并且我研究了 ExportAsFixedFormat
的参数(参考 here)。
第五个参数是IgnorePrintAreas
,所以我假设将False传递给它,打印区域将被忽略。
我尝试了几种常识性的解决方案,包括:
- 仅传递该参数(传递 True 或 False )
- 传递所有前 5 个参数(以防它们在运行时是必需的)
但没有结果:我的应用程序创建的 pdf 仍然“忽略打印区域”。
有没有人有关于这个特定主题的建议或经验,可以指导我解决这个问题?
谢谢。
更新
感谢我将有用的已接受答案附加到解决方案上方的代码以供参考,请注意两件事:
- 包含解决方法的 RestoreOriginalPrintArea 过程
- 最后调用oWB.Close(false)
错误的根本原因:
当使用自动化打开文件时,Excel 在 non-English 版本的应用程序中丢失打印区域设置。
为什么会这样:
当您在 sheet 中定义打印区域时,Excel 会在内部创建一个 named range。它有两个定义其名称的属性:
Name
这个 属性 总是 WorksheetsName!Print_Area
的形式(如果 sheet 的名称包含一些特殊字符,它也用单引号引起来)。
NameLocal
具有相似的结构,但第二部分被翻译成应用程序的语言。
这是您在 Excel 中打开文件并在 VBA 中检查这些属性时的样子,但是当您使用自动化打开同一个文件时(例如使用有问题的代码), 那么 NameLocal
就不再翻译了。此错误导致命名范围无法被正确识别为打印区域。 oSheet.PageSetup.PrintArea
returns 空字符串。
解决方法:
使用以下方法打开文件后恢复原始打印区域:
oSheet.PageSetup.PrintArea:='Print_Area';
当sheet中没有定义打印区域时,这行代码会抛出异常,所以有两种选择:
- 将线放在
try
..except
块内。
- 迭代
Names
集合并查找以 !Print_Area
结尾的 Name
,例如:
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
在关闭应用程序之前,否则每次调用此函数都会导致另一个 Excel 进程仍然 运行 不可见。
在一个 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:
//
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 时的行为(它是从 [= 导出到 pdf 的选项之一) 50=] 特征)。
所以我决定也从代码中“取消选中”该复选框,并且我研究了 ExportAsFixedFormat
的参数(参考 here)。
第五个参数是IgnorePrintAreas
,所以我假设将False传递给它,打印区域将被忽略。
我尝试了几种常识性的解决方案,包括:
- 仅传递该参数(传递 True 或 False )
- 传递所有前 5 个参数(以防它们在运行时是必需的)
但没有结果:我的应用程序创建的 pdf 仍然“忽略打印区域”。
有没有人有关于这个特定主题的建议或经验,可以指导我解决这个问题?
谢谢。
更新
感谢我将有用的已接受答案附加到解决方案上方的代码以供参考,请注意两件事:
- 包含解决方法的 RestoreOriginalPrintArea 过程
- 最后调用oWB.Close(false)
错误的根本原因:
当使用自动化打开文件时,Excel 在 non-English 版本的应用程序中丢失打印区域设置。
为什么会这样:
当您在 sheet 中定义打印区域时,Excel 会在内部创建一个 named range。它有两个定义其名称的属性:
Name
这个 属性 总是WorksheetsName!Print_Area
的形式(如果 sheet 的名称包含一些特殊字符,它也用单引号引起来)。NameLocal
具有相似的结构,但第二部分被翻译成应用程序的语言。
这是您在 Excel 中打开文件并在 VBA 中检查这些属性时的样子,但是当您使用自动化打开同一个文件时(例如使用有问题的代码), 那么 NameLocal
就不再翻译了。此错误导致命名范围无法被正确识别为打印区域。 oSheet.PageSetup.PrintArea
returns 空字符串。
解决方法:
使用以下方法打开文件后恢复原始打印区域:
oSheet.PageSetup.PrintArea:='Print_Area';
当sheet中没有定义打印区域时,这行代码会抛出异常,所以有两种选择:
- 将线放在
try
..except
块内。 - 迭代
Names
集合并查找以!Print_Area
结尾的Name
,例如:
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
在关闭应用程序之前,否则每次调用此函数都会导致另一个 Excel 进程仍然 运行 不可见。