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传递给它,打印区域将被忽略。

我尝试了几种常识性的解决方案,包括:

但没有结果:我的应用程序创建的 pdf 仍然“忽略打印区域”。

有没有人有关于这个特定主题的建议或经验,可以指导我解决这个问题?

谢谢。

更新

感谢我将有用的已接受答案附加到解决方案上方的代码以供参考,请注意两件事:

  1. 包含解决方法的 RestoreOriginalPrintArea 过程
  2. 最后调用oWB.Close(false)

错误的根本原因:

当使用自动化打开文件时,

Excel 在 non-English 版本的应用程序中丢失打印区域设置。

为什么会这样:

当您在 sheet 中定义打印区域时,Excel 会在内部创建一个 named range。它有两个定义其名称的属性:

  1. Name 这个 属性 总是 WorksheetsName!Print_Area 的形式(如果 sheet 的名称包含一些特殊字符,它也用单引号引起来)。
  2. NameLocal 具有相似的结构,但第二部分被翻译成应用程序的语言。

这是您在 Excel 中打开文件并在 VBA 中检查这些属性时的样子,但是当您使用自动化打开同一个文件时(例如使用有问题的代码), 那么 NameLocal 就不再翻译了。此错误导致命名范围无法被正确识别为打印区域。 oSheet.PageSetup.PrintArea returns 空字符串。

解决方法:

使用以下方法打开文件后恢复原始打印区域:

oSheet.PageSetup.PrintArea:='Print_Area';

当sheet中没有定义打印区域时,这行代码会抛出异常,所以有两种选择:

  1. 将线放在 try..except 块内。
  2. 迭代 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 进程仍然 运行 不可见。