无法将字符串从 VBA (Excel) 传递到我的 COM 对象
Unable to pass a string from VBA (Excel) to my COM object
我正在尝试为我的应用程序创建一个 COM 接口,以便允许例如。 VBA 驱动我的应用程序的某些部分。
我安装了我的 COM 库 运行,甚至可以在 Delphi IDE 中调试在 Excel 中调用的例程。
这是我使用按钮从 Excel 激活的 VBA 代码:
Sub TestAMQMOLE_OpenProject()
Dim vConnection As String
Dim vAMQM As Object
Dim vAMProject As Object
vConnection = "$(MYSRC)\LCCAMQM38\UnitTestData\AnalyseSortingAndGrouping"
Set vAMQM = CreateObject("LCCAMQM_AX.LCCAMQM_Application")
vAMQM.Connect
Set vAMQMProject = vAMQM.OpenProject(vConnection) 'This parameter does not get through
Set vAMQMProject.Active = True
Set vAMQMProject = Nothing
vAMQM.Disconnect
Set vAMQM = Nothing
End Sub
Delphi 中处理它的部分如下所示:
function TLCCAMQM_Application.OpenProject(const aFolderOrAlias: WideString): ILCCAMQM_Project;
begin
try
Result:=TLCCAMQM_Project.Create(aFolderOrAlias); // wrapper om TdmAMEditBase
except
SHowMessage(ExceptionToString(ExceptObject,ExceptAddr));
end;
end;
代码失败的地方是因为 aFolderOrAlias
参数字符串为空。我添加了异常处理程序以便在 Delphi IDE 之外进行调试。在 IDE 内部调试时,参数字符串确实显示为空。
我还尝试将参数作为 Variant
或 const Variant
传递(并相应地调整类型库),但在那种情况下我得到了 VT_RECORD
变体类型(0x0024) 这对我来说没有任何意义。
下面是类型库的接口定义。
....
[
uuid(EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5),
helpstring("Dispatch interface for LCCAMQM_Application Object"),
dual,
oleautomation
]
interface ILCCAMQM_Application: IDispatch
{
[id(0x000000C9)]
int _stdcall Connect(void);
[id(0x000000CA)]
int _stdcall Disconnect(void);
[id(0x000000CB)]
ILCCAMQM_Project* _stdcall OpenProject([in] BSTR aFolderOrAlias);
[propget, id(0x000000CC)]
HRESULT _stdcall Connected([out, retval] VARIANT_BOOL* Value);
};
[
uuid(590DBF46-76C9-4877-8F47-5A926AFF389F),
helpstring("LCCAMQM_Application Object")
]
coclass LCCAMQM_Application
{
[default] interface ILCCAMQM_Application;
};
....
我相当确定一定有一种方法可以将字符串从 VBA 传递到 COM 对象。但是在摆弄了几个小时之后我迷路了:s.
事实证明,ComIntern 和 Remy 是对的。我完全误解了整个 stdcall
和 safecall
接口。
.ridl 文件现在看起来像这样:
....
interface ILCCAMQM_Application: IDispatch
{
[id(0x000000C9)]
int _stdcall Connect(void);
[id(0x000000CA)]
int _stdcall Disconnect(void);
[propget, id(0x000000CC)]
HRESULT _stdcall Connected([out, retval] VARIANT_BOOL* Value);
[id(0x000000CB)]
HRESULT _stdcall OpenProject([in] BSTR aFolderOrAlias, [out, retval] ILCCAMQM_Project** Value);
};
....
生成的...TLB.pas 文件如下所示:
....
// *********************************************************************//
// Interface: ILCCAMQM_Application
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}
// *********************************************************************//
ILCCAMQM_Application = interface(IDispatch)
['{EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}']
function Connect: SYSINT; stdcall;
function Disconnect: SYSINT; stdcall;
function Get_Connected: WordBool; safecall;
function OpenProject(const aFolderOrAlias: WideString): ILCCAMQM_Project; safecall;
property Connected: WordBool read Get_Connected;
end;
// *********************************************************************//
// DispIntf: ILCCAMQM_ApplicationDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}
// *********************************************************************//
ILCCAMQM_ApplicationDisp = dispinterface
['{EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}']
function Connect: SYSINT; dispid 201;
function Disconnect: SYSINT; dispid 202;
property Connected: WordBool readonly dispid 204;
function OpenProject(const aFolderOrAlias: WideString): ILCCAMQM_Project; dispid 203;
end;
....
而且 OpenProject 现在可以在我的内部单元测试(用 delphi 编写)以及 Excel-VBA.
中运行
现在我正在努力设置属性并通过 Excel VBA 以及通过 delphi 中的 OleVariant。但我必须把它放在 .
中
我正在尝试为我的应用程序创建一个 COM 接口,以便允许例如。 VBA 驱动我的应用程序的某些部分。
我安装了我的 COM 库 运行,甚至可以在 Delphi IDE 中调试在 Excel 中调用的例程。
这是我使用按钮从 Excel 激活的 VBA 代码:
Sub TestAMQMOLE_OpenProject()
Dim vConnection As String
Dim vAMQM As Object
Dim vAMProject As Object
vConnection = "$(MYSRC)\LCCAMQM38\UnitTestData\AnalyseSortingAndGrouping"
Set vAMQM = CreateObject("LCCAMQM_AX.LCCAMQM_Application")
vAMQM.Connect
Set vAMQMProject = vAMQM.OpenProject(vConnection) 'This parameter does not get through
Set vAMQMProject.Active = True
Set vAMQMProject = Nothing
vAMQM.Disconnect
Set vAMQM = Nothing
End Sub
Delphi 中处理它的部分如下所示:
function TLCCAMQM_Application.OpenProject(const aFolderOrAlias: WideString): ILCCAMQM_Project;
begin
try
Result:=TLCCAMQM_Project.Create(aFolderOrAlias); // wrapper om TdmAMEditBase
except
SHowMessage(ExceptionToString(ExceptObject,ExceptAddr));
end;
end;
代码失败的地方是因为 aFolderOrAlias
参数字符串为空。我添加了异常处理程序以便在 Delphi IDE 之外进行调试。在 IDE 内部调试时,参数字符串确实显示为空。
我还尝试将参数作为 Variant
或 const Variant
传递(并相应地调整类型库),但在那种情况下我得到了 VT_RECORD
变体类型(0x0024) 这对我来说没有任何意义。
下面是类型库的接口定义。
....
[
uuid(EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5),
helpstring("Dispatch interface for LCCAMQM_Application Object"),
dual,
oleautomation
]
interface ILCCAMQM_Application: IDispatch
{
[id(0x000000C9)]
int _stdcall Connect(void);
[id(0x000000CA)]
int _stdcall Disconnect(void);
[id(0x000000CB)]
ILCCAMQM_Project* _stdcall OpenProject([in] BSTR aFolderOrAlias);
[propget, id(0x000000CC)]
HRESULT _stdcall Connected([out, retval] VARIANT_BOOL* Value);
};
[
uuid(590DBF46-76C9-4877-8F47-5A926AFF389F),
helpstring("LCCAMQM_Application Object")
]
coclass LCCAMQM_Application
{
[default] interface ILCCAMQM_Application;
};
....
我相当确定一定有一种方法可以将字符串从 VBA 传递到 COM 对象。但是在摆弄了几个小时之后我迷路了:s.
事实证明,ComIntern 和 Remy 是对的。我完全误解了整个 stdcall
和 safecall
接口。
.ridl 文件现在看起来像这样:
....
interface ILCCAMQM_Application: IDispatch
{
[id(0x000000C9)]
int _stdcall Connect(void);
[id(0x000000CA)]
int _stdcall Disconnect(void);
[propget, id(0x000000CC)]
HRESULT _stdcall Connected([out, retval] VARIANT_BOOL* Value);
[id(0x000000CB)]
HRESULT _stdcall OpenProject([in] BSTR aFolderOrAlias, [out, retval] ILCCAMQM_Project** Value);
};
....
生成的...TLB.pas 文件如下所示:
....
// *********************************************************************//
// Interface: ILCCAMQM_Application
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}
// *********************************************************************//
ILCCAMQM_Application = interface(IDispatch)
['{EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}']
function Connect: SYSINT; stdcall;
function Disconnect: SYSINT; stdcall;
function Get_Connected: WordBool; safecall;
function OpenProject(const aFolderOrAlias: WideString): ILCCAMQM_Project; safecall;
property Connected: WordBool read Get_Connected;
end;
// *********************************************************************//
// DispIntf: ILCCAMQM_ApplicationDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}
// *********************************************************************//
ILCCAMQM_ApplicationDisp = dispinterface
['{EDD8E7FC-5D96-49F1-ADB7-F04EE9FED7B5}']
function Connect: SYSINT; dispid 201;
function Disconnect: SYSINT; dispid 202;
property Connected: WordBool readonly dispid 204;
function OpenProject(const aFolderOrAlias: WideString): ILCCAMQM_Project; dispid 203;
end;
....
而且 OpenProject 现在可以在我的内部单元测试(用 delphi 编写)以及 Excel-VBA.
中运行现在我正在努力设置属性并通过 Excel VBA 以及通过 delphi 中的 OleVariant。但我必须把它放在