注册 登录
编程论坛 VFP论坛

如何获取人工打开的Excel对象

easyppt 发布于 2022-04-15 15:23, 2762 次点击
VFP要控制的的Excel不是VFP打开的,而是人工打开的,能实现吗,怎么获取
22 回复
#2
吹水佬2022-04-15 19:16
只有本站会员才能查看附件,请 登录
#3
csyx2022-04-15 21:55
GetObject函数在Win7以上有可能失效,上图为证
只有本站会员才能查看附件,请 登录

#4
foxfans2022-04-15 22:14
肯定可以的,是你的前面excel文件名没写上。
试试 ?GETOBJECT("excel.xlsx","excel.application")

[此贴子已经被作者于2022-4-15 22:26编辑过]

#5
csyx2022-04-15 23:14
以下是引用foxfans在2022-4-15 22:14:59的发言:

肯定可以的,是你的前面excel文件名没写上。
试试 ?GETOBJECT("excel.xlsx","excel.application")

加上文件名?说明你根本没明白GetObject这个函数的用法,加上文件名的GetObject就跟NewObject的作用一样,是创建另一个Excel实例,去任务管理器里看看吧

[此贴子已经被作者于2022-4-15 23:16编辑过]

#6
foxfans2022-04-15 23:42
如果是控制已经打开的excel,为啥要带类名,直接引用即可, cc=GETOBJECT("c:\2.xlsx")
只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2022-4-15 23:43编辑过]

#7
easyppt2022-04-16 08:29
我的测试结果 和 csyx   说的是一样的:

环境:Win10系统 和Office Excel 2016
测试结果:
1、带文件名,就变成打开了, 而且因为已经人工打开该文件,还会出现错误提示。
2、如果不带文件名,直接  Getobject(,'Excel.application')  获取不到。

也正因为我已经测试了这样的结果,所以才来论坛发帖的。
只有本站会员才能查看附件,请 登录





[此贴子已经被作者于2022-4-16 08:30编辑过]

#8
独木星空2022-04-16 08:35
扯点闲的,大家发的帖子有截图,我连个截图也做不来,可能自己没有往这里想过,做不出来,也就不奇怪了。
#9
csyx2022-04-16 18:22
这个问题是有实际意义的,例如软件要导出一些统计数据,通常默认有固定的文件夹和文件名,如果恰好手工打开了这个文件,我们的软件以前是提示用户手工关闭它,但我们希望的是在提示后根据我们的选择自动关闭它或取消导出,要做到自动关闭,就需要获取已经打开的Excel对象。虽然在指定文件名时可以改名,但我们不希望有太多的人工干涉,一是操作人员的电脑知识欠缺(年龄等原因,他们工作经验丰富无法替代),二是统计报表太多,最好只保留最后一份正确的
我参与了软件公司就此问题的工作会议,后来经过开发人员的努力成功解决了,我大概说一下产生此问题的原因和解决思路吧
在xp+Office2003时代,基本不会遇到此类问题,因为那时的Excel大都是以单实例方式运行的。6楼同学可能就是单实例模式,因此用带文件名的GetObject不会提示程序已在运行中,你我都是多实例模式,所以会有提示,同样,我们的各部门使用的Excel版本不同,有高有低,运行模式是安装时默认的(也许通过修改注册表啥的可以都修改,但我们不想采纳)
另一个取不到已经打开的Excel对象问题,就涉及到用户权限,这在xp时代也基本不存在。细究起来就很复杂了,涉及到COM基础知识,可以百度下(知乎 COM编程攻略,浏览下第十六章),GetObject可能就是从ROT表中查找运行中Excel对象的,最关键的问题在于ROT是上下文敏感的,换句话说就是进程权限不同是不会共享的,这才是导致GetObject取不到的关键因素
因此,可以说vfp的GetObject函数,不带第一个参数的用法已部分废废了,之所以说部分废废,是因为如果权限一致时是不会有问题的。双击一个xls文件是用当前登录账号的权限打开文件的,而你的vfp却可能运行在管理员权限下(检查下vfp9.exe是否勾选了以管理员身份运行)。我们使用的软件因为会读写注册表的部分敏感区域(好像还有动态注册控件),需要设置成以管理员身份运行,因此才会遇到你提到的情况。弄清楚了为何取不到,也就知道需要避开ROT这个坑,另寻出路曲线救国了
具体的代码我没有,就算我能看到也无权贴出来,只能根据当时的记录把思路贴出来,希望你自己能实现它(这里高手如云,特别是像吹版这样的高手,有这思路写代码实现易如反掌)
先查找特定窗口句柄,所有的Excel都有一个名为Excel7的子窗口,窗口父子关系是 XLMAIN -> XLDESK -> EXCEL7,找到此窗口句柄后,再用AccessibleObjectFromWindow得到工作簿对象,有了Book对象,再访问Excel,Sheet这些对象就是再普通不过的事儿了
啰啰嗦嗦一大堆,希望对你有所帮助
#10
吹水佬2022-04-16 20:24
回复 9楼 csyx
查看了一下EXCEL2003、2007确是能找到Book对象
只有本站会员才能查看附件,请 登录

只有本站会员才能查看附件,请 登录
#11
easyppt2022-04-17 01:47
csyx  和 吹版  太厉害了,分析的好详细啊!

期待 吹版 能解决啊!!
#12
sych2022-04-17 07:21
https://blog.
这是一个大师级的总结,可以终结这个话题
#13
吹水佬2022-04-17 18:05
以下是引用sych在2022-4-17 07:21:44的发言:

https://blog.
这是一个大师级的总结,可以终结这个话题

这个大师总结的是VFP用CreateObject()和GetObject()创建Excel对象。
这个话题的第9楼谈到是用MSAA的IAccessible接口获取Excel对象。
VFP的CreateObject()和GetObject()与MSAA的IAccessible接口有无关系就不清楚,但MSAA的IAccessible接口是windows API 的东西,层面应该更低些。
不能轻易就说“可以终结这个话题”吧
#14
吹水佬2022-04-17 18:23
回复 11楼 easyppt
以下是引用easyppt在2022-4-15 15:23:34的发言:

VFP要控制的的Excel不是VFP打开的,而是人工打开的,能实现吗,怎么获取

具体情况不明,不只是看看有无EXCEL在运行吧,是就在当前进程表里找有无EXCEL进程,有可能还不只一个EXCEL进程。
#15
csyx2022-04-17 18:36
吹版威武哈,你贴的截图是自己做的vfp版Inspect ?
#16
csyx2022-04-17 18:45
以下是引用吹水佬在2022-4-17 18:23:15的发言:
具体情况不明,不只是看看有无EXCEL在运行吧,是就在当前进程表里找有无EXCEL进程,有可能还不只一个EXCEL进程。

是的,不一定只有一个Excel实例在运行中,所以应该枚举出所有的Excel对象并返回一个集合给调用者,调用者可以根据book.FullPath来判断哪个是他需要的Excel对象
虽然使用了MSAA的AccessibleObjectFromWindow函数,但需要的功能与IAccessible接口并没多大关系,只需要用OBJID_NATIVEOM来获取IDispatch接口即可
#17
吹水佬2022-04-18 07:01
以下是引用csyx在2022-4-17 18:36:24的发言:

你贴的截图是自己做的vfp版Inspect ?

以前学习MSAA时写的,为省点时间用VFP写。
#18
吹水佬2022-04-18 07:04
以下是引用csyx在2022-4-17 18:45:28的发言:

虽然使用了MSAA的AccessibleObjectFromWindow函数,但需要的功能与IAccessible接口并没多大关系,只需要用OBJID_NATIVEOM来获取IDispatch接口即可


    MSAA的全称是Microsoft Active Accessibility。这是类似DCOM技术。技术模型是这样的,UI程序可以暴露出一个Interface,方便另一个程序对其进行控制。MSAA技术的初衷是为了方便残疾人使用Windows 程序。比如盲人看不到窗口,但是盲人可以通过一个USB读屏器连接到电脑上,读屏器通过UI程序暴露出来的这个Interface,就可以获取程序信息,通过盲文或者其它形式传递给盲人。

    MSAA提供了如此方便的功能, UI自动化测试自然可以借用这项技术。MSAA暴露出来的Interface叫做 IAccessible。
#19
csyx2022-04-18 08:50
我意思是使用AccessibleObjectFromWindow的目的,是用名为Excel7窗口的句柄,加上OBJID_NATIVEOM和IID参数,就得到了Excel.Workbook的COM界面指针,足以满足楼主提出的要求,不怎么需要用到IAccessible接口提供的其他功能,MSAA的典型应用自然是遍历用户界面的内部对象
#20
sych2022-04-18 09:11
这个帖子是“如何获取人工打开的Excel对象”?
下面的代码可以实现获取人工打开的EXCEL文件对象
测试环境 WINDOWS 7 旗舰版,VFP9,OFFICE 2016 专业增强版
ole2 = getobject( ,'excel.application' )
?ole2.Workbooks.Count
for i=1 to ole2.Workbooks.Count
?ole2.Workbooks(i).name
next


[此贴子已经被作者于2022-4-18 09:17编辑过]

#21
sych2022-04-18 09:14
MSAA是不是可以获取QQ的聊天窗口信息?
#22
csyx2022-04-18 12:18
以下是引用sych在2022-4-18 09:11:19的发言:
下面的代码可以实现获取人工打开的EXCEL文件对象
测试环境 WINDOWS 7 旗舰版,VFP9,OFFICE 2016 专业增强版
ole2 = getobject( ,'excel.application' )
。。。

右击 vfp9.exe -> 属性 -> 兼容性 -> 勾选【以管理员身份运行此程序】,再试试
#23
bhyycwk2022-04-24 16:11
测试环境 w10,OFFICE2013 ,使用ole2 = getobject( ,'excel.application' ) 在安装版的VFP9里,出现楼主一样的问题。VFP9精简版获取Excel没有问题。编译成EXE运行,获取也没有问题。原因不明。
1