VBA算是非主流语言,接触过的人想必不多,在此就谈谈我对VBA的一些肤浅的看法。
VBA就是Visual Basic for Application 的简称,它有两大特点,一就是它是采用BASIC语法的脚本语言(解释执行),另一个就是它嵌入到某个其他应用中来控制调用这个应用系统的功能。在我印象中,它最早是出现在微软的Office中,比如Word或Excel的宏,并逐步扩展到其他应用中,比如AutoCad,VS.NET集成开发环境等就支持VBA。在微软.NET框架中,就已经包含了一个VBA的运行引擎,使用这个引擎可以使得我们开发的系统也支持VBA。
IE浏览器支持VBScript,它采用Basic的语法,也能调用浏览器的某些功能,但个人认为不算VBA,因为VBScript的控制力度太弱了,而且有着很多安全限制。但VBA除了能控制应用系统处理的文档内容外,还能控制更多的模块,而且一般没有安全限制,可以连接数据库或访问二进制文件。可以说VBA是普通编程语言和脚本语言的中间体,同时具有两者的优点和缺点。当个功能不复杂,用常规编程方式太麻烦,若系统支持VBA,则可以考虑使用VBA来实现。
VBA有一个显著的特点就是和应用系统的紧密结合,能方便的调用系统接口,比如对于Word或Excel,可在系统界面上新增菜单或按钮来映射到VBA函数,可以定义快捷键,这样就临时扩展了应用系统的功能。
在此演示一个在VS.NET2003集成开发环境的VBA的开发和应用。
对VS.NET进行扩展编程,首先想到的是插件,VS.NET提供了比较复杂的API,大家要写程序并编译生成可执行文件,然后对VS.NET进行一定的配置才能使用。若使用VBA则过程大大简化。
自此想实现一个功能,将一个C#工程中所有的文件拷贝到一个目录下面,而在工程目录中但不包含在工程中的文件将不拷贝。VS.NET2003的C#工程文件扩展名为 .csproj , 它内容是一个XML文档,没有XML声明头,采用ANSI编码格式,我们的VBA代码将加载并解析这个XML文档,分析其中的工程引用信息和包含的文件清单,将引用的DLL文件和所有的工程文件拷贝到指定目录下。其所有的VBA代码如下
Dim myPrj As EnvDTE.Project = DTE.ActiveWindow.Project
If UCase(System.IO.Path.GetExtension(myPrj.FullName)) <> ".CSPROJ" Then
MsgBox("当前工程不是 C# 工程", MsgBoxStyle.Information, "复制CS工程")
Exit Sub
End If
Dim myFile As New System.IO.StreamReader(myPrj.FullName, System.Text.Encoding.GetEncoding(936))
Dim myDoc As New System.Xml.XmlDocument
myDoc.LoadXml(myFile.ReadToEnd())
myFile.Close()
Dim strPath As String = InputBox("请输入输出目录名称", "输入")
If strPath Is Nothing Then
Return
End If
If strPath.Length = 0 Then
Return
End If
Dim ThisPath As String = System.IO.Path.GetDirectoryName(myPrj.FullName)
CopyFile(myPrj.FullName, strPath)
Dim FileCount As Integer
Dim myElement As System.Xml.XmlElement
Dim strFileName As String
Dim strNewFileName As String
For Each myElement In myDoc.SelectNodes("VisualStudioProject/CSHARP/Build/Referencds/Reference")
strFileName = myElement.GetAttribute("HintPath")
If strFileName.StartsWith("c:") = False And strFileName.StartsWith("C:") = False Then
CopyFile(ThisPath, strPath, strFileName)
FileCount = FileCount + 1
End If
Next
For Each myElement In myDoc.SelectNodes("VisualStudioProject/CSHARP/Files/Include/File")
strFileName = myElement.GetAttribute("RelPath")
If Not strFileName Is Nothing Then
If strFileName.IndexOf(":") = -1 Then
CopyFile(ThisPath, strPath, strFileName)
FileCount = FileCount + 1
End If
End If
Next
MsgBox("共拷贝 " & FileCount.ToString() & " 个文件")
End Sub
Public Sub CreateDirectory(ByVal strDir As String)
If System.IO.Directory.Exists(strDir) = False Then
System.IO.Directory.CreateDirectory(strDir)
End If
End Sub
Public Sub CopyFile(ByVal strPath1 As String, ByVal strPath2 As String, ByVal strFilePath As String)
Dim strName1 As String = System.IO.Path.Combine(strPath1, strFilePath)
Dim strName2 As String = System.IO.Path.Combine(strPath2, strFilePath)
Dim dir1 As String = System.IO.Path.GetDirectoryName(strName1)
If System.IO.Directory.Exists(dir1) = False Then
System.IO.Directory.CreateDirectory(dir1)
End If
Dim dir2 As String = System.IO.Path.GetDirectoryName(strName2)
If System.IO.Directory.Exists(dir2) = False Then
System.IO.Directory.CreateDirectory(dir2)
End If
System.IO.File.Copy(strName1, strName2, True)
End Sub
Public Sub CopyFile(ByVal strFileName As String, ByVal strNewPath As String)
System.IO.File.Copy(strFileName, System.IO.Path.Combine(strNewPath, System.IO.Path.GetFileName(strFileName)), True)
End Sub
代码编写完毕后就在VS.NET工具条上新增一个按钮来映射到这段代码,其过程演示如下。
从上面看出,实现这个过程非常简单,采用了简单的面向过程的编程方法,没有复杂的配置,而且这里的VBA没有安全限制,可以调用.NET框架的所有的类,可以连接数据库,操作二进制文件,启动其他程序等。我们可以编写VBA来实现各种需要的功能,比如检查文档内容,自动生成源代码等等。有兴趣大家一起来研究研究。
在这里提醒一下,这段代码只能在VS.NET2003中运行,由于VS.NET2005的C#工程文件格式和2003的不同,因此进行移植时需要修改解析c#工程文件的部分代码。而且VBA调用 System.Windows.Forms 下面的类型时可能有问题,VBA正在运行时可能会影响VS.NET的正常工作,有时VBA不能运行,则关闭VS.NET然后重新打开就能用了。
袁永福 ( http://www.xdesigner.cn ) 2006-12-1