简体   繁体   English

Excel自动化在C ++ Builder XE7中不起作用

[英]Excel automation isn't working in C++Builder XE7

I am trying to use the code below to open an .xlsx file from C++Builder in RAD Studio XE7: 我正在尝试使用下面的代码从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

But the last line causes exception with message: 但是最后一行导致消息异常:

Project2.exe raised exception class EOleException with message 'Unfortunately, we were unable to find the file TRUE.xlsx. Project2.exe引发异常类EOleException并显示消息“很遗憾,我们无法找到文件TRUE.xlsx。 It may have been moved, renamed or deleted?'. 它可能已被移动,重命名或删除了?”。

Screen with place where the source breaks 屏幕与来源中断的地方

The code in Delphi seems to work fine: 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;

Does anyone know the solution? 有人知道解决方案吗?

Update1: The following code in VB also works fine: 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

Update2: Sending a raw string literal causes the same exception . Update2:发送原始字符串文字会导致相同的exception

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

It also doesn't seem to be an environment problem. 这似乎也不是环境问题。 I tested the example at several computers with no effect. 我在几台计算机上测试了该示例,但没有任何效果。

In C++ the backslash character is the escape character in string literals and so needs itself to be escaped. 在C ++中,反斜杠字符是字符串文字中的转义字符,因此需要对自身进行转义。 Instead of 代替

L"D:\1.xlsx"

you need to write 你需要写

L"D:\\1.xlsx"

The error message is strange though. 错误消息是奇怪的。 It is almost as though some conversion in the COM dispatch code interprets the 1 as a truth value and converts it to text. 几乎就像COM调度代码中的某些转换将1解释为真值并将其转换为文本一样。 You could try passing the filename as a System::WideString which might side-step the issue. 您可以尝试将文件名作为System::WideString传递,这可以System::WideString该问题。

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

What you are reporting seems almost too weird to be true though! 您所报告的内容似乎太不可思议了! I have to confess I'm having some trouble believing it because it is so outlandish. 我不得不承认,由于它太古怪,我很难相信它。

Just faced a similar problem with C++ Builder XE7 and thought I would share what I found. 刚刚遇到了C ++ Builder XE7的类似问题,并认为我会分享发现的内容。 Any attempt to set or send a string literal of any type caused either a Bad Variable Type error, was set as TRUE in Excel like Dmitrii or caused a memory error. 任何试图设置或发送任何类型的字符串文字的尝试都会导致Bad Variable Type错误,在Excel中像Dmitrii一样被设置为TRUE或导致内存错误。

What I eventually found was that there is an OLEVariant type in C++ Builder that contains data types compatible with OLE automation and at runtime can convert as required. 我最终发现,C ++ Builder中存在一个OLEVariant类型,其中包含与OLE自动化兼容的数据类型,并且在运行时可以根据需要进行转换。

I first tried changing all my Variant variables to OLEVariant without success but then was able to use a cast on any string I sent to make it work, even older char strings. 我首先尝试将所有Variant变量都更改为OLEVariant,但没有成功,但随后我可以对我发送的任何字符串使用强制类型转换,以使其正常工作,甚至是较旧的char字符串。 So you might try 所以你可以尝试

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

even without the WideString formatting it worked for what I was doing so this might work as well 即使没有WideString格式,它也可以正常工作,所以也可以

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

As for escaping I'm not sure if you need to escape the backslash in the second case with a simple string or not. 至于转义,我不确定在第二种情况下是否需要使用简单的字符串来转义反斜杠。

The problem seems very specifically related to the use of C++ and thus the way that C++ compilers deal with literal strings (or at least this particular C++ compiler). 该问题似乎与C ++的使用特别相关,因此与C ++编译器处理文字字符串(或至少是此特定C ++编译器)的方式有关。 Quite what the problem is in this case I cannot say - it could even be a bug in the compiler since (seemingly) correct escaping doesn't address the problem. 在这种情况下,我无法说出问题的确切原因-甚至可能是编译器中的错误,因为(貌似)正确的转义无法解决问题。

You could employ various strategies to eliminate the possibility that it is handling of the literal string in this case. 您可以采用各种策略来消除在这种情况下处理文字字符串的可能性。 But since this does involve a literal string and since you are using XE7 I believe you should be able to bypass this more explicitly by expressing the literal as a raw string (as per C++11, which is/should be supported by C++ Builder XE7): 但是由于这确实涉及文字字符串,并且由于您使用的是XE7,我相信您应该能够通过将文字表示为原始字符串来更明确地绕过此字符串(按照C ++ 11,C ++ Builder应该支持XE7):

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

Note that with raw string literals you specifically do not escape \\ chars. 请注意,使用原始字符串文字时,您不会转义\\ char。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM