我为ms office创建了一个插件,它在office 2019 Excel & wps office 2019 ET上运行良好,但它在2013年ms office上存在问题。
以下是对以下情况的描述:
rst = disp->QueryInterface(__uuidof(Excel::_Worksheet), (void**)&sheet);
disp->Release();
Excel::Range* rawRange = nullptr;
Excel::IRange* rows = nullptr;
rst = sheet->get_Rows(&rawRange);
rst = rawRange ->QueryInterface( __uuidof(Excel::IRange), (void**)&rows);get_Rows工作正常,并返回S_OK,but范围::QueryInterface返回E_NOINTERFACE,这很奇怪!我不明白,我错过了什么吗?
有许多名为QueryInterface方法的位置,但只有Range类型查询( IRange类型)才会失败。
Office 2019 & WPS 2010工作正常,2013年已经重新安装了office,但仍然没有工作。也许是微软的漏洞?
发布于 2022-11-30 12:19:22
正如@Joseph Willcoxson所说,Range类型没有实现IRange接口,但是它实现了这些特性,我们可以使用IDispatch接口Invoke方法来做同样的事情。我想分享我的实用程序代码。
template<class T, size_t N>
constexpr size_t ArrayLen(T(&ref)[N]) {
return N;
}
enum class RangeDispID : DISPID {
// Props
NumberFormat = 0x000000c1,
Column = 0x000000f0,
Row = 0x00000101,
Rows = 0x00000102,
Columns = 0x000000f1,
Text = 0x0000008a,
Item = 0x000000aa,
Cells = 0x000000ee,
Count = 0x00000076,
Value2 = 0x0000056c,
// Methods
Select = 0x000000eb,
Find = 0x0000018e,
AutoFilter = 0x00000319,
Activate = 0x00000130,
};
enum class WindowDispID : DISPID {
FreezePanes = 0x0000028a
};
enum class WorksheetDispID : DISPID {
Rows = 0x00000102,
Range = 0x000000c5,
UsedRange = 0x0000019c,
};
template<class T>
struct DispIDBridge {};
template<>
struct DispIDBridge<RangeDispID> {
using DispIDType = RangeDispID;
using UUIDType = Excel::IRange;
DispIDBridge(DispIDType id) : id_(id){}
operator DispIDType() const { return id_; }
operator DISPID() const { return (DISPID)id_; }
private:
DispIDType id_;
};
template<>
struct DispIDBridge<WindowDispID> {
using DispIDType = WindowDispID;
using UUIDType = Excel::IWindow;
DispIDBridge(DispIDType id) : id_(id) {}
operator DispIDType() const { return id_; }
operator DISPID() const { return (DISPID)id_; }
private:
DispIDType id_;
};
template<>
struct DispIDBridge<WorksheetDispID> {
using DispIDType = WorksheetDispID;
using UUIDType = Excel::_Worksheet;
DispIDBridge(DispIDType id) : id_(id) {}
operator DispIDType() const { return id_; }
operator DISPID() const { return (DISPID)id_; }
private:
DispIDType id_;
};
template<class T>
HRESULT DispSetProperty(IDispatch* obj, T id, CComVariant& val) {
DISPID dispid = DISPID_PROPERTYPUT;
DISPPARAMS params; {
params.cNamedArgs = 1;
params.rgdispidNamedArgs = &dispid;
params.cArgs = 1;
params.rgvarg = &val;
}
UINT errIn;
auto rst = obj->Invoke(
(DISPID)id,
__uuidof(DispIDBridge<T>::UUIDType),
chs_lcid,
DISPATCH_PROPERTYPUT,
¶ms,
nullptr,
nullptr,
&errIn
);
return rst;
}
template<class T>
CComVariant DispGetProperty(IDispatch* obj, T id, CComVariant* args = nullptr, int argc = 0) {
if (argc > 1) {
std::reverse(args, args + argc);
}
CComVariant ret;
DISPPARAMS params; {
params.cNamedArgs = 0;
params.rgdispidNamedArgs = nullptr;
params.cArgs = argc;
params.rgvarg = args;
}
UINT errIn;
auto rst = obj->Invoke(
(DISPID)id,
__uuidof(DispIDBridge<T>::UUIDType),
chs_lcid,
DISPATCH_PROPERTYGET,
¶ms,
&ret,
nullptr,
&errIn
);
if (rst == S_OK) {
return ret;
}
else {
return CComVariant();
}
}
template<class T>
HRESULT DispCallMethod(IDispatch* obj, T id, CComVariant* args, int argc) {
if (argc > 1) {
std::reverse(args, args + argc);
}
DISPPARAMS dispParams{};
dispParams.cArgs = argc;
dispParams.rgvarg = args;
UINT errIn;
auto rst = obj->Invoke(
(DISPID)id,
__uuidof(DispIDBridge<T>::UUIDType),
chs_lcid,
DISPATCH_METHOD,
&dispParams,
nullptr,
nullptr,
&errIn
);
return rst;
}
template<class T>
CComVariant DispCallMethodWithRet(IDispatch* obj, T id, CComVariant* args, int argc) {
if (argc > 1) {
std::reverse(args, args + argc);
}
DISPPARAMS dispParams{};
dispParams.cArgs = argc;
dispParams.rgvarg = args;
UINT errIn;
CComVariant ret;
auto rst = obj->Invoke(
(DISPID)id,
__uuidof(DispIDBridge<T>::UUIDType),
chs_lcid,
DISPATCH_METHOD,
&dispParams,
&ret,
nullptr,
&errIn
);
assert(rst == S_OK);
return ret;
}我们可以用这种方法
CComVariant top5Row; {
CComVariant args[] = {cellLoc};
top5Row = DispGetProperty(sheet, WorksheetDispID::Range, args, ArrayLen(args));
}https://stackoverflow.com/questions/74457049
复制相似问题