OLE Excel 个文件中的名称冲突

Name conflict in Excel files by OLE

正在开发将 Excel 文件转换为 PDF 的程序。这是我的代码:

  procedure ExcelToPDF(const InputFileName, OutputFileName: string);
  var
    Excel: Variant;
    Workbook: Variant;
  begin
    try
      CoInitializeEx(nil, 0);

      //Открытие Excel
      Excel := CreateOleObject('Excel.Application');
//      Excel.Application.EnableEvents := False;
      Excel.Application.DisplayAlerts := False;
      Excel.Visible := False;

      if not VarIsNull(Excel) then
      begin
        //Открытие файла
        Workbook := Excel.Workbooks.Open(InputFileName);
        //Сохранение в PDF
        Workbook.ExportAsFixedFormat(xlTypePDF, OutputFileName);        

        Writeln('OK');
      end
      else
      begin
        raise Exception.Create('Не удалось открыть Excel');
      end;
    finally
      if not VarIsNull(Excel) then
      begin
        Excel.Quit;
        Excel := 0;
      end;
    end;
  end;

它工作正常,但对于某些工作簿,当程序尝试打开工作簿时出现错误输入对话框(另请查看屏幕截图):

名称冲突
名称不能与内置名称相同。
旧名称:Print_Area
新名称:
确定 取消

旧名称可以是 Print_Area 或 _FilterDatabase 或其他名称。这是非常常见的错误,但我没有找到真正的解决方案。但关键问题在这里:当我自己打开 Excel 中的问题工作簿时,它没有任何对话框就可以正常工作,只有当我在我的程序中通过 OLE 打开它时它才会出现。如果在 OLE 中我们只使用 Excel 怎么办?那么也许 Excel 使用其他参数打开文件?我正在试验 Open 方法参数,但没有。

感谢您的所有评论。我找到了解决方案。在 VBA 中有 GetObject 函数。我在互联网上找到了它的 Delphi 实现。就是这样:

  function GetObject(const AFileName: TFileName): IDispatch;
  var
    vDispatch : IDispatch;
    vBindCtx : IBindCtx;
    vMoniker : IMoniker;
    vChEaten : Integer;
  begin
    Result := nil;
    vDispatch := nil;
    vBindCtx := nil;
    if CreateBindCtx(0, vBindCtx) = S_OK then
    begin
      vMoniker := nil;
      if MkParseDisplayName(vBindCtx, PWideChar(WideString(AFileName)),
        vChEaten, vMoniker) = S_OK then
      begin
        if vMoniker.BindToObject(vBindCtx, nil, IDispatch, vDispatch) = S_OK then
          Result := vDispatch;
      end;
    end;
  end;

所以,而不是这两行:

Excel := CreateOleObject('Excel.Application');
Workbook := Excel.Workbooks.Open(InputFileName);

只使用一个:

Workbook := GetObject(InputFileName);