【问题标题】:Excel automation isn't working in C++Builder XE7Excel 自动化在 C++Builder XE7 中不起作用
【发布时间】:2014-12-15 22:45:23
【问题描述】:

我正在尝试使用下面的代码从 RAD Studio XE7 中的 C++Builder 打开一个 .xlsx 文件:

#include "ComObj.hpp"

Variant Excel = CreateOleObject("Excel.Application");
Variant Books = Excel.OlePropertyGet("Workbooks");
Excel.OlePropertySet("Visible", true);
// An escape character is missing but the problem remains
Books.OleProcedure("Open", L"D:\1.xlsx"); // exception here

但最后一行导致异常消息:

Project2.exe 引发异常类 EOleException,并带有消息“不幸的是,我们无法找到文件 TRUE.xlsx。它可能已被移动、重命名或删除?'。

Screen with place where the source breaks

Delphi 中的代码似乎运行良好:

uses ComObj;

var
  Excel, Books: Variant;
begin
    Excel := CreateOleObject('Excel.Application');
    Books := Excel.Workbooks;
    Excel.Visible := True;
    Books.Open('D:\1.xlsx'); // code passes
end;

有人知道解决办法吗?

更新1: VB中的以下代码也可以正常工作:

Sub Button1_Click()
 Dim xlApp As Excel.Application
 Dim xlBooks As Excel.Workbooks

 Set xlApp = CreateObject("Excel.Application")
 Set xlBooks = xlApp.Workbooks

 xlApp.Visible = True
 xlBooks.Open ("D:\1.xlsx")
End Sub

更新 2: 发送原始字符串文字会导致相同的exception

Books.OleProcedure("Open", uR"(D:\1.xlsx)");

这似乎也不是环境问题。我在几台计算机上测试了该示例,但没有任何效果。

【问题讨论】:

  • 请不要更改问题。随时在编辑中添加更多信息。但不要删除原来的问题。
  • 抱歉,添加了它们,但也没有任何变化。看起来像是屏幕上带有 static_cast 转换的东西,不是吗?
  • 我认为演员工作正常。
  • 当您将文件名更改为 1 以外的名称时会发生什么?
  • 当我将路径更改为“D:\\file.xlsx”时,错误仍然存​​在

标签: excel delphi ole delphi-xe7 c++builder-xe7


【解决方案1】:

在 C++ 中,反斜杠字符是字符串文字中的转义字符,因此需要对其自身进行转义。而不是

L"D:\1.xlsx"

你需要写

L"D:\\1.xlsx"

错误信息很奇怪。就好像 COM 调度代码中的某些转换将 1 解释为真值并将其转换为文本。您可以尝试将文件名作为System::WideString 传递,这可能会回避问题。

System::WideString filename = L"D:\\1.xlsx";
Books.OleProcedure("Open", filename);

不过,您所报告的内容似乎太奇怪了!我不得不承认我很难相信它,因为它太古怪了。

【讨论】:

  • 糟糕,抱歉,添加了它们,但也没有任何变化。
  • 我的第一个想法和大卫的一样,但你说问题仍然存在。下一个问题:如果您尝试使用与您的 Delphi Books.Open() 等效的 VBA 代码在 Excel 宏中打开文件,您会遇到同样的问题吗?
  • System::WideString 帮助了,谢谢!这似乎是一个错误?还有其他方法可以传输 wchar_t 数组吗?
  • 看起来像一个错误,不是吗。调度代码中的某些内容未能正确地将 C 字符串转换为 COM BSTR。就你个人而言,我希望尽早绑定 COM。
  • 我尝试使用 TExcelApplication 类。有一个方法 Excel->Workbooks->Open(wchar_t*)。出现同样的情况:如果我使用 String 变量中的 c_str() ,我会得到一个错误。但是,如果我使用 WideString 变量中的 c_bstr(),则该方法有效。
【解决方案2】:

刚刚遇到了与 C++ Builder XE7 类似的问题,并认为我会分享我的发现。任何设置或发送任何类型的字符串文字的尝试都会导致错误的变量类型错误、在 Excel 中设置为 TRUE(如 Dmitrii)或导致内存错误。

我最终发现的是,C++ Builder 中有一个 OLEVariant 类型,它包含与 OLE 自动化兼容的数据类型,并且在运行时可以根据需要进行转换。

我首先尝试将我的所有 Variant 变量更改为 OLEVariant 但没有成功,但随后能够对我发送的任何字符串使用强制转换以使其工作,甚至是旧的字符字符串。所以你可以试试

Books.OleProcedure("Open", (OleVariant)L"D:\1.xlsx");

即使没有 WideString 格式,它也适用于我正在做的事情,所以这也可以工作

Books.OleProcedure("Open", (OleVariant)"D:\1.xlsx");

至于转义,我不确定是否需要在第二种情况下用简单的字符串转义反斜杠。

【讨论】:

  • 希望我能投票两次。感谢您为我省去了很多悲伤。
【解决方案3】:

这个问题似乎与 C++ 的使用特别相关,因此 C++ 编译器处理文字字符串的方式(或者至少是这个特定的 C++ 编译器)。在这种情况下问题出在哪里,我不能说 - 它甚至可能是编译器中的一个错误,因为(看似)正确的转义并不能解决问题。

在这种情况下,您可以采用各种策略来消除它正在处理文字字符串的可能性。但是由于这确实涉及文字字符串,并且由于您使用的是 XE7,我相信您应该能够通过将文字表示为原始字符串来更明确地绕过它(根据 C++11,C++ Builder 应该/应该支持它) XE7):

Books.OleProcedure("Open", uR"(D:\1.xlsx)"); // uR indicates UTF-16 Raw string

请注意,对于原始字符串文字,您特别不要转义 \ 字符。

【讨论】:

  • @Deltics 很难想象存在一个编译器无法转义文字中的反斜杠。
  • 可能,但如果问题出在 OLE 对象、文件系统或 OLE 自动化服务器中,那么无论涉及哪种语言,您都会看到相同的结果。仅当使用一种特定语言时才会出现问题,这太巧合了。这是我们正在谈论的 Embarcadero 编译器......一个不以工作质量而闻名的供应商。最近肯定不会。在 Visual Studio 中尝试相同的 C/C++ 代码,看看会发生什么?先排除不可能的……
  • @Deltics Escapes in literals 适用于所有编译器。这是 Emba 独有的 COM 调度。我无法想象他们是如何把它塞满的。
  • 啊,是的,没有发现 OleProcedure() 中间体。正如我所说...不是以工作质量而闻名的供应商...;)
猜你喜欢
  • 2015-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-27
  • 2015-11-03
相关资源
最近更新 更多