直接在 Excel 工作表上使用 ActiveX 控件的必要条件和充分条件是啥?
Posted
技术标签:
【中文标题】直接在 Excel 工作表上使用 ActiveX 控件的必要条件和充分条件是啥?【英文标题】:What requirements are necessary and sufficient for an ActiveX control to be used directly on an Excel worksheet?直接在 Excel 工作表上使用 ActiveX 控件的必要条件和充分条件是什么? 【发布时间】:2016-07-10 22:45:46 【问题描述】:Microsoft Office 支持文章“Add or register an ActiveX control”说:
重要提示:并非所有 ActiveX 控件都可以直接在工作表上使用;有些只能在 Microsoft Visual Basic for Applications (VBA) 用户窗体上使用。当您使用这些控件时,如果您尝试将它们添加到工作表中,Excel 会显示消息无法插入对象。
但是,我无法在任何地方找到必要和足够的要求,以便直接在工作表上使用控件。
我创建了一个新的 C++/ATL 项目,并在其中添加了一个 ATL 控件,始终接受默认设置。编译、构建和注册控件后,它会出现在 Excel 的“更多控件”列表中(在开发人员 > 插入 > ActiveX 控件 > 更多控件...下访问),但在尝试插入工作表时,会看到“无法插入对象” " 错误。
我必须进行哪些更改才能解决此问题?
或
Excel 对 ActiveX 控件的要求记录在哪里?
对于它的价值,我已经验证了由向导生成的控件在其他方面工作正常(使用ActiveX Control Test Container 测试,我从Visual C++ 2008 samples pack 构建)。
此外,我知道documentation for the ATL Control wizard's "Appearance" tab 对“可插入”复选框的描述如下:
选择此选项可使您的控件出现在 Word 和 Excel 等应用程序的“插入对象”对话框中。然后,任何支持嵌入对象的应用程序都可以通过此对话框插入您的控件。
然而,这个复选框(它只是将“Insertable”子项添加到注册表中)只会导致控件出现在“插入”>“文本”>“对象”对话框中——为免生疑问,我尝试了有和没有这个检查并以任何方式产生相同的错误。
我目前正在比较尝试插入控件时的 Excel 执行路径与尝试插入工作 (Forms 2.0) 控件时的执行路径。关键区别似乎在于加载类型库时的 VBE7.dll(OLE/COM Object Viewer 能够从我的 DLL 中正确加载——然而在 Excel 执行了所有相同的读取之后,它在写出 EXD 之前中止)。 ..我现在正在研究一些程序集,但希望我能弄明白,但肯定某人已经为 Excel 构建了一个工作控件并且知道我缺少什么可以节省我这么痛?!
Microsoft Windows 10 专业版 v1511 (10.0.10586.164) 64 位 Microsoft Excel 2016 MSO (16.0.4312.1000) 64 位 Microsoft Visual Studio 社区 2015(14.0.24720.00 更新 1)
【问题讨论】:
只是出于好奇:您为什么要发布一个具有相同标题的新问题而不是编辑您的第一个问题? @Filburt:我找不到旧的了! 看起来这可以用赏金来做......不是我有野心,但它会让你更容易找到;-) 【参考方案1】:要实现可插入 MS Excel 工作表的 ATL ActiveX 控件,请执行以下步骤:
确保在 C:\Users\$(UserName)\AppData\Local\Temp\Excel8.0 中没有缓存 ActiveX 控件信息 *.exd 文件,这可能是一个不明显的障碍
使用所有默认值创建 ATL DLL 项目
2.1。添加 x64 配置作为现有 Win32 的副本 - 对于 64 位 Excel,您将需要 64 位 ActiveX 控件
-
使用向导添加 ATL 控件类
3.1。确保填写 ProgID 字段
3.2。在 Interfaces 页面添加 IPersistStreamInit
构建 DLL 并注册 (regsvr32)
在 Excel 中,新控件在菜单 Developer、...、More Controls 中可见
-
插入它并从中获得乐趣
源代码:Subversion/Trac
更新:来自 cmets 的问题如下:
...Excel 是否支持无窗口激活?
要查看实际的控制操作,让我们添加一些代码around there:
CSample()
CTrace::SetLevel(4);
和
HRESULT OnDraw(ATL_DRAWINFO& di)
const CComQIPtr<IOleInPlaceSiteWindowless> pOleInPlaceSiteWindowless = m_spClientSite;
ATLTRACE(_T("m_spClientSite 0x%p, pOleInPlaceSiteWindowless 0x%p, m_hWnd 0x%08X\n"), m_spClientSite, pOleInPlaceSiteWindowless, m_hWnd);
这将打印出有助于识别窗口/无窗口模式的控件成员。输出是(最终在激活对象之后或从一开始):
...
Sample.h(118) : atlTraceGeneral - m_spClientSite 0x0000027A9CA7B460, pOleInPlaceSiteWindowless 0x0000000000000000, m_hWnd 0x0105069C
...
Sample.h(118) : atlTraceGeneral - m_spClientSite 0x0000027A9CA7B460, pOleInPlaceSiteWindowless 0x0000000000000000, m_hWnd 0x0105069C
该控件可以激活有窗口和无窗口(除非m_bWindowOnly
设置为true,在这种情况下强制窗口模式)。跟踪显示控件处于窗口模式,并且该容器没有IOleInPlaceSiteWindowless
,这对于无窗口来说是必需的。
【讨论】:
我完全相信我已经尝试过这些步骤,但显然我必须在此过程中改变了一些其他的东西。这非常有效——非常感谢! @eggyal:真正令人困惑的是 *.exd 文件。 Excel 会缓存控制信息,并且可能会忽略您的一些代码更改并尝试修复这种情况。这可能是您的好代码在某些时候仍被 Excel 拒绝的原因。 实际上我很早就发现 Excel 会在 EXD 中缓存类型库,并且知道这在某些情况下可能会导致问题——但我发现在我的情况下甚至没有写出 EXD .我对汇编的深入研究表明,类型库中任何非双重接口的存在都会导致整个库被拒绝:因此,我在单个项目中尝试多种不同的控制配置的尝试被一个失败的案例所阻挠。这无疑是一个相当混乱的根源! 你知道Excel是否支持无窗口激活吗?我原以为会,但是现在四处寻找我无法让它工作......如果你愿意,很高兴发布另一个 q (有另一个赏金)! ;-) 我不确定,但我想 Excel 实现了托管无窗口控件所需的一切。特别是在此示例控件的代码中,如果我在OnDraw
中设置断点,我会看到托管控件是可见的,并且无需创建窗口 (m_hWnd == NULL
) 即可完成其工作。【参考方案2】:
我对 ActiveX 和 COM 技术有一些经验,但对 Excel 的世界还没有深入挖掘。据我所知,除非您确切知道自己在做什么,否则所有 COM 组件总是散发出过于复杂的味道,但并不总是能够找到需要做的事情。
无论如何 - 我已经快速扫描/谷歌搜索 - 这些是我能够找到的链接:
从这里:http://itdocument.com/6551512544/
Excel 97 和 2000 问题 Excel 97 和 2000 问题 Q171280 Q171280,错误消息“无法插入对象”在 Excel97。
ActiveX 控件必须支持聚合才能插入 ActiveX 控件必须支持聚合才能插入 到电子表格中。如果他们不支持进入电子表格。如果他们不支持存在 聚合后,Excel 将不允许插入它们。聚合后,Excel 将不允许插入它们。 更多信息请参见 Q143432 Q143432 中提供更多信息 文章底部。文章底部。
任何通过尝试查找文章 Q143432 经常以不存在的页面结束 - 但能够找到这篇文章:
https://support.microsoft.com/en-us/kb/143432
这里报告了一些与它的使用相关的问题:
http://www.verycomputer.com/418_e81ed24b6ac0cb79_1.htm
然而,我的建议是尽可能避免使用 ActiveX 技术,如果不可能 - 尝试上面的链接 - 或者可能会找到一些类似的开源代码示例。
以下是我设法找到的一些示例:
这是俄语: https://habrahabr.ru/post/149277/
这显然是同一页面的谷歌翻译版本: http://developers-club.com/posts/149277/
它是源代码 - 我认为: https://github.com/Lovesan/MyActiveX
我希望这会对您有所帮助,但是 - 不确定 - 我自己还没有尝试过。
【讨论】:
以上是关于直接在 Excel 工作表上使用 ActiveX 控件的必要条件和充分条件是啥?的主要内容,如果未能解决你的问题,请参考以下文章
Excel VBA 将文本框(文本和格式)复制到另一个文本框(无 ActiveX / 用户表单)
从 Excel 调用 VBA 函数 - 在选定工作表上的选定列中查找
Microsoft Excel ActiveX 控件已禁用?