这篇文章可能会写很久,很久。
在vba中不要试图全面控制Webbrowser,因为那是用vba办不到,即使能办到也一定是办不好的事情。
而且全面控制webbrowser的复杂度会大大超出你的意料。
可以说在所有使用webbrowser的编程语言中,vba调用是最简便的一种。
html与winform的交互,主要是两种类型的交互。一种是html(js)与vba函数的互相调用,一种是html(js)与recordset的数据交互
一、html(js)如何与vba函数互相调用?
vba通过html的dom,可以全面读写html和js,这是很容易做到的。但html或js如何调用vba函数呢?
主要有两种方式:
1、通过事件,来通知winform执行vba函数。 引用microsoft html object libray类型库
Dim WithEvents m_Doc As MSHTML.HTMLDocument
Private Sub Form_Load()
Me.WebBrowser1.Navigate2 "http://www.baidu.com"
End Sub
Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object,
URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData
As Variant, Headers As Variant, Cancel As Boolean)
Set m_Doc = Me.WebBrowser1.Document
End Sub
Private Function m_Doc_onclick() As Boolean
Dim elem As IHTMLElement
Set elem = m_Doc.parentWindow.event.srcElement
select case elem.id '这其实是一个事件列表
case id1
call mySub1
case id2
call mysub2
……
end select
End
这里重点用到的是Dom的window.event对象,并且主要是用到srcElement属性。
使用 window.event 对象,可以捕获 WebBrowser 众多的鼠标和键盘事件,如鼠标坐标、按 下了键盘哪个键,以及键盘
Ctrl、Alt、Shift 键的状态、当前网页元素的ID、索引等等。
可以说这是VBA与webbrowser交互的唯一简便途径了。
这种方式的缺点:
(1)、必须为每一个htm页面写特定的事件列表,虽然这当中最主要是onclick事件。
它的抽象度非常差。如果你有什么更好的方式,不妨提出来讨论一下。
(2)、WebBrowse 控件的 event
对象只能捕捉主页面的有关事件,对网页包含的内嵌网页和框架无能为力。要捕捉内嵌网页和框架的有关事件,必须为每个网页定义一个捕捉事件,但 VBA 的
WithEvents 语句并不支持定义数组事件。
这里很容易转换成另一个问题:
如何让withEvents支持collection或数组?这个问题的答案,能解决的事情范围变得很大了,如access的mdi问题等。 2、通过window.external来调用vba函数
通过window.external调用vba函数,其实是比较理想的方式,所有的ie的activeX插件,几乎都是通过这种方式。但 Webbrowser只有在实现IDocHostUIHandler接口后,window.external才能调用VBA函数。
这在vb6中可以做到,但在access中办不到,因为它必须引用olelib.tlb,而access本身没有任何编译功能。( 写到这里,我忍不住想起mde,accde,这种编译其实是彻头彻尾的骗人小把戏)
很可惜,这种方式只能放弃了。
表面看起来,似乎缺陷蛮多的,功能有限,但别忘了我们在Access中使用html,并不是想用html来全面替代winform的功能,因为这不科学,也完全没必要。所以还是可以承受的。不要以为用c++,c#、vb.net调用webbrowser会更容易,坦白地说,它们只会带来更多的麻烦和痛不欲生的折磨而已。也不要以为用webkit会更容易,那是永远不可能的。
二、数据交互:
准备好几种工具:
1、 json的vba版解析器。在html5时代,不管你见或不见,json就在那里,不远、不近,你回避不了。所以了解json格式是必须的,很容易在网络上搜到几十种vb6版或asp版的json解析器。它们都很方便。挑一种符合你使用的,或有人最近两三年还在维护的json解析器。