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);
正在开发将 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);