Excel COM与C++:如何检查RangeFromPoint返回的是范围对象还是形状对象

huangapple go评论76阅读模式
英文:

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
        &#39;do something
    Else
        &#39;Shape object, do something else
    End If
End If

C++:

std::any pXlRFP = pXlApp-&gt;ActiveWindow-&gt;RangeFromPoint(75, 250);

if (&amp;pXlRFP) {
  if (pXlRFP.type() == typeid(Excel::RangePtr)) { // This doesn&#39;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-&gt;RangeFromPoint(250, 250);

Excel::RangePtr pRange;
if (!pUnk) 
{
	// pUnk is empty
	MessageBox(0, L&quot;Empty&quot;, L&quot;RangeFromPoint&quot;, 0);
}
else if (pUnk-&gt;QueryInterface(IID_PPV_ARGS(&amp;pRange)) == S_OK)
{
	// pRange refers to a Range now
	_bstr_t addy = pRange-&gt;GetAddress(_variant_t(VARIANT_FALSE), _variant_t(VARIANT_FALSE), Excel::xlA1);
	MessageBox(0, addy, L&quot;RangeFromPoint&quot;, 0);
}
else 
{
	// pUnk is something else
	MessageBox(0, L&quot;Some other type&quot;, L&quot;RangeFromPoint&quot;, 0);
}

Full sample gist (elides error checking and message loop).

huangapple
  • 本文由 发表于 2023年7月23日 21:12:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748417.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定