2

我正在尝试使用下面的代码从 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。它可能已被移动、重命名或删除?

带有源中断位置的屏幕

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;

有谁知道解决方案?

Update1: ​​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: 发送原始字符串文字会导致相同的异常

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

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

4

3 回答 3

2

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

L"D:\1.xlsx"

你需要写

L"D:\\1.xlsx"

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

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

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

于 2014-12-15T22:50:09.663 回答
1

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

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

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

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

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

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

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

于 2015-02-11T15:22:17.643 回答
0

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

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

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

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

于 2014-12-16T02:31:51.250 回答