英文:
Excel COM with C++: How to check if RangeFromPoint returns a range or a shape object
问题
C++:
std::any pXlRFP = pXlApp->ActiveWindow->RangeFromPoint(75, 250);
if (!pXlRFP.has_value()) {
// pXlRFP doesn't contain a value, handle the case accordingly
} else if (pXlRFP.type() == typeid(Excel::RangePtr)) {
// pXlRFP points to an Excel::RangePtr, so you can treat it as a range
Excel::RangePtr range = std::any_cast<Excel::RangePtr>(pXlRFP);
// do something with 'range'
} else {
// pXlRFP contains something other than an Excel::RangePtr, handle it as needed
}
英文:
I would like to convert the following code from VBA to C++. I get the Excel COM API by using import directives.
VBA:
Dim objRFP As Object
Set objRFP = ActiveWindow.RangeFromPoint(X:=75, Y:=250)
If Not objRFP Is Nothing Then
If TypeOf objRFP Is Excel.Range Then
'do something
Else
'Shape object, do something else
End If
End If
C++:
std::any pXlRFP = pXlApp->ActiveWindow->RangeFromPoint(75, 250);
if (&pXlRFP) {
if (pXlRFP.type() == typeid(Excel::RangePtr)) { // This doesn't work!!!
// do something
}
else {
// Shape object; do something else
}
}
How can I check if pXlRFP points to a range?
答案1
得分: 0
COM仅处理接口。要检查COM指针是否支持特定接口,请使用适当的IID调用QueryInterface
。
根据您使用的智能指针库,可能有一种有效的方法来执行此操作。如果您没有使用智能指针并且QI成功,确保Release
已获得的接口。
假设您使用的是MSVC #import
(因此使用了_com_ptr
),代码可能如下所示:
IDispatchPtr pUnk = pWindow->RangeFromPoint(250, 250);
Excel::RangePtr pRange;
if (!pUnk)
{
// pUnk为空
MessageBox(0, L"Empty", L"RangeFromPoint", 0);
}
else if (pUnk->QueryInterface(IID_PPV_ARGS(&pRange)) == S_OK)
{
// pRange现在引用一个范围
_bstr_t addy = pRange->GetAddress(_variant_t(VARIANT_FALSE), _variant_t(VARIANT_FALSE), Excel::xlA1);
MessageBox(0, addy, L"RangeFromPoint", 0);
}
else
{
// pUnk是其他类型
MessageBox(0, L"Some other type", L"RangeFromPoint", 0);
}
完整示例代码链接(省略了错误检查和消息循环部分)。
英文:
COM only deals with interfaces. To check if a COM pointer supports a particular interface, call QueryInterface
with the appropriate IID.
Depending on what smart pointer library you are using, there is likely an efficient way to do this. Make sure to Release
the interface acquired if you are not using smart pointers and QI succeeds.
Assuming you are using MSVC #import
(and therefore _com_ptr
), that would look something like:
IDispatchPtr pUnk = pWindow->RangeFromPoint(250, 250);
Excel::RangePtr pRange;
if (!pUnk)
{
// pUnk is empty
MessageBox(0, L"Empty", L"RangeFromPoint", 0);
}
else if (pUnk->QueryInterface(IID_PPV_ARGS(&pRange)) == S_OK)
{
// pRange refers to a Range now
_bstr_t addy = pRange->GetAddress(_variant_t(VARIANT_FALSE), _variant_t(VARIANT_FALSE), Excel::xlA1);
MessageBox(0, addy, L"RangeFromPoint", 0);
}
else
{
// pUnk is something else
MessageBox(0, L"Some other type", L"RangeFromPoint", 0);
}
Full sample gist (elides error checking and message loop).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论