UML软件工程组织

将代码从 VBA 转换到 Visual Basic .NET
Kathleen McGrath
Microsoft Corporation

2003 年 6 月

适用于:
    Microsoft® "Visual Studio Tools for Office" Beta
    Microsoft Office Word 2003 Beta 2
    Microsoft Office Excel 2003 Beta 2
    Microsoft Visual Basic® for Applications (VBA)
    Microsoft Visual Studio® .NET 2003
    Microsoft Visual Basic .NET

摘要:介绍将 Microsoft Office 解决方案从 Visual Basic for Applications (VBA) 转换到 Visual Basic .NET 中时需要考虑的问题。概述了两者之间的差异,并使用来自 Word 和 Excel 的示例来说明如何使用“Visual Studio Tools for Office”转换代码。(本文包含一些指向英文站点的链接。)

目录

简介
是否应该将 VBA 代码转换到 Visual Basic .NET
VBA 与 Visual Basic .NET 之间的差异
   语言差异
   项目管理差异
   安全性差异
   部署差异
转换 VBA 代码
   Word 中的 VBA 代码示例
   Excel 中的 VBA 代码示例
小结
附录
相关文章

简介

本文介绍将 Microsoft® Visual Basic® for Applications (VBA) 代码转换到 Microsoft Visual Basic .NET 时开始可能会遇到的问题。并帮助您学习当从 VBA 代码(非托管代码)迁移到由 Microsoft .NET Framework 管理的代码(托管代码)时,需要进行哪些更改。首先讨论是否将代码转换到 Visual Basic .NET 的依据。然后介绍转换代码时会出现的多种变化,包括集成开发环境 (IDE) 中的差异、语言差异、用户窗体差异、安全性差异和部署差异。最后向您展示如何使用 Microsoft 的“Visual Studio Tools for Office”将现有 Word 和 Excel 代码模块中的 VBA 代码转换到 Visual Basic .NET。

是否应该将 VBA 代码转换到 Visual Basic .NET

在开始将 VBA 代码转换到 Visual Basic .NET 之前,您可能希望了解两者的优缺点。使用“Visual Studio Tools for Office”,您可以在 Microsoft Office Word 2003 文档和 Microsoft Office Excel 2003 工作簿背后编写托管代码。能够使用自定义属性链接到托管代码程序集的文档或工作簿被称为具有“托管代码扩展”功能。使用托管代码扩展,您可以利用 Microsoft Visual Studio® .NET 和 Microsoft .NET Framework 中的资源,包括安全性、部署、完全支持 XML Web Service、结构化异常处理和 Microsoft Windows® 窗体。但是,也可能存在因没有转换 VBA 代码而受益的情况。

当考虑是否将 VBA 代码转换到 Visual Basic .NET 时,请考虑以下信息:

使用 VBA...

  • 当代码需要与文档紧密绑定时;例如,代码需要与文档一起移动时。
  • 当组织中存在部署限制时,例如,.NET Framework 对最终用户不可用时。
  • 当需要使用 Excel 自定义函数时。
  • 当需要创建截取 Word 自有命令的方法时。
  • 当自定义除 Microsoft Office Word 2003 和 Microsoft Office Excel 2003 以外的 Microsoft Office 应用程序时。“Visual Studio Tools for Office”不支持这些应用程序。

使用 Visual Basic .NET...

  • 当需要利用 Visual Studio .NET 环境(包括服务器资源管理器和增强的智能感知功能)时。
  • 当您的解决方案可以从 .NET Framework 的全部资源中受益时,例如,内置 Web 服务支持、更容易进行 XML 分析和可以访问 .NET Framework 中的所有类。
  • 当需要更简单的代码维护时。程序集中的代码与文档分离,多个文档能够引用同一个程序集。
  • 当需要灵活的部署选项时。程序集可以部署为网络共享;此后,当用户每次打开连接到网络的 Excel 或 Word 文档时,可以立即使用程序集中更新后的代码。
  • 当要实现更灵活的安全模式时。

VBA 与 Visual Basic .NET 之间的差异

了解 VBA 与 Visual Basic .NET 之间的差异有助于您在转换代码时作出更明智的决定。本节介绍以下方面的差异:

  • 语言
  • 项目管理
  • 安全性
  • 部署

语言差异

由于 Visual Basic .NET 是为利用 .NET Framework 而设计的,它包含非常多的改动,在许多地方已经不再与以前的语言版本兼容。以下列出了 Visual Basic .NET 中 Visual Basic 语言的部分修改。有关详细信息,请参阅 Introduction to Visual Basic .NET for Visual Basic Veterans

  • 后期绑定:VBA 和 Visual Basic .NET 都支持后期绑定;但是,使用早期绑定对象可以使代码更易于阅读和维护,同时还可以启用智能感知。Visual Basic .NET 引入 Option Strict On 语句,该语句强制进行早期绑定并禁止进行可能导致数据丢失的隐式转换。编译器默认情况下使用 Option Strict Off。这非常重要的一个原因是 Office 对象的许多方法和属性的返回类型为 Object,您必须显式地将对象转换为正确的类型,如下例所示:
    ' 使用 Ctype 将 Sheet1 返回的对象转换成工作表。
    MsgBox(CType(ThisWorkbook.Worksheets("Sheet1"), Excel.Worksheet).Name)
    
  • 声明变量:在 VBA 中,可以使用 Option Explicit 语句来强制进行显式变量声明。也可以通过选中 VBA IDE 选项中的 Require Variable Declaration(需要变量声明)复选框来自动设定这项功能,该复选框默认情况下为未选中状态。所有隐式声明的变量都是 Variant 类型。

    Visual Basic .NET 编译器强制进行显式声明,要求声明每个变量。可以使用语句 Option Explicit Off 取消使用这项功能。所有隐式声明的变量都是 Object 类型。当将代码从 VBA 复制并粘贴到 Visual Basic .NET 中时,应该考虑这一点,因为 Variant 数据类型不再被支持,而且会被自动转换成 Object 数据类型。应该显式指定项目中所有已声明变量的类型。

  • 默认属性:在 Visual Basic .NET 中,仅支持具有参数的默认属性。而在 VBA 中,通过消除默认属性,键入代码时可以使用快捷方式。例如:
    ActiveDocument.Tables(1).Cell(1, 1).Range = "Name"
    

    当将此代码转换到 Visual Basic .NET 时,必须指定 Range 对象的默认属性,即 Text

    ThisApplication.ActiveDocument.Tables(1).Cell(1, 1).Range.Text = "Name"
    

    请注意,不需要指出 Tables 对象的默认属性 Item,因为该对象具有索引参数。然而,如果包含所有默认属性,代码将更易于阅读:

    ThisApplication.ActiveDocment.Tables.Item(1).Cell(1, 1).Range.Text _
        = "Name"
    
  • ByVal、ByRef 参数:在 VBA 中,默认情况下“按引用”传递参数。而在 Visual Basic .NET 中,默认情况下“按值”传递参数。当准备将代码转换到 Visual Basic .NET 时,您可能需要检查:所有方法都明确定义是按引用还是按值来传递参数。当在没有定义参数的情况下将代码粘贴到 Visual Studio .NET IDE 中时,ByVal 将被自动添加到列表中的每个参数上。
  • 枚举:Visual Basic .NET 中的枚举常量必须进行完全限定。当转换 VBA 代码时,必须将完全限定的枚举名称添加到 Word 和 Excel 常量中。例如,在 Word VBA 中执行搜索时,可以使用 wd 常量指定 SelectionRangeFindWrap 值。给出了三个选项:wdFindStopwdFindAskwdFindContinue。在 VBA 中,您可以仅指定常量,因为枚举常量在项目中是全局有效的:
    Selection.Find.Wrap = wdFindContinue
    

    而在 Visual Basic .NET 中,常量必须具有完全限定的枚举名称:

    ThisApplication.Selection.Find.Wrap = Word.WdFindWrap.wdFindContinue
    

    这看起来像是额外键入许多内容,但如果您使用 Visual Studio .NET 的智能感知功能,定位和键入限定的常量就相当容易,而且会使代码更易于阅读。如果您熟悉常量名称,将会发现枚举名称与常量名称通常完全匹配。在上面的示例中,两者都包含 wdFind。要浏览可用枚举,可以键入 Word.Wd 并滚动智能感知下拉列表中的项目(键入 Excel.XL 以滚动 Excel 的可用枚举列表)。

  • 非零下限数组:在 VBA 中,数组维数的默认下限为 0(零)。使用 Option Base,您可以将下限改为 1。在 Visual Basic .NET 中,不支持 Option Base 语句,并且每个数组维数的下限必须为 0。此外,不能使用 ReDim 声明数组。当使用 Visual Basic .NET 中的 Office 集合时,请注意大多数 Office 集合的数组下限从 1 开始。
  • 方法调用时括号的使用:在 VBA 中,当调用子例程时,括号在某些情况下是可选的,并且需要括号时有时很难想起使用括号。而在 Visual Basic .NET 中,在方法调用过程中,传递参数时需要使用括号。
  • Set 关键字:在 VBA 中,区分对象赋值和对象的默认属性赋值时,需要使用 Set 关键字。由于 Visual Basic .NET 不支持默认属性,因此不需要使用 Set 关键字,也不再支持该关键字。以下示例说明了这一变化:
    ' VBA
    Dim mySelection as Selection
    Dim myOtherSelection as String
    Set mySelection = Selection
    myOtherSelection = Selection
    
    ' Visual Basic .NET
    Dim mySelection As Word.Selection
    Dim myOtherSelection As String
    mySelection = ThisApplication.Selection
    myOtherSelection = ThisApplication.Selection.Text
    
  • 数据访问:Microsoft Visual Basic .NET 不支持数据访问对象 (DAO) 和远程数据对象 (RDO) 数据源的数据绑定。为了向后兼容,支持 ActiveX® Data Objects (ADO) 数据绑定;但您可能会考虑转换到 ADO.NET。有关详细信息,请参阅 Comparison of ADO.NET and ADO
  • 将用户窗体转换成 Windows 窗体:VBA 用户窗体不能被复制或导入到 Visual Studio .NET 中。大多数情况下,您需要重新将窗体创建为 Windows 窗体。拖放控件与 VBA 中创建窗体时相同,但对 Windows 窗体控件的事件处理程序的处理不同。获得的许多新功能使创建窗体比以前更容易,例如:
    • 控件锁定现在成为可能,因此当用户调整窗体大小时,控件将自动调整尺寸并正确地进行重定位。
    • 使用 Windows 窗体使设置 Tab 键顺序更容易。单击 View(视图)菜单上的 Tab Order(Tab 键顺序)启用 Tab 键顺序。然后只要单击首选顺序中的每个控件。
    • 创建内嵌菜单是对 VBA 中菜单创建的改善。
    • 在 VBA 中,可以将窗体显示为 vbModalvbModeless。而在 Visual Basic .NET 中,ShowDialog 方法用于以模式方式显示窗体;Show 方法用于以无模式方式显示窗体。但是,请注意,尽管窗体将以无模式方式显示,但在 Word 或 Excel 文档中单击时,窗体将移至背景,这可能会使用户产生疑惑。
    • Visual Basic .NET 中提供了许多新的窗体控件,例如数据输入验证器、标准对话框、超链接标签、系统任务栏图标、面板、数字升降、迅速可设计树视图、帮助文件链接器以及工具提示扩展程序等。

项目管理差异

当开始使用 Visual Basic .NET 来创建 Office 解决方案时,您将注意到代码在项目中的位置发生了改变。当使用 VBA 创建 Office 解决方案时,代码位于 Word 模板、Word 文档或 Excel 工作簿的模块、用户窗体和类模块中。当使用“Visual Studio Tools for Office”时,代码位于被编译到程序集的类和 Windows 窗体中,并被 Word 或 Excel 文档引用。

虽然 Visual Studio .NET IDE 具有增强功能,但在许多方面与 VBA IDE 相似。两者都具有查看项目、模块、窗体和参考的资源管理器。两者都提供属性窗口、工具箱、对象浏览器和调试功能。表 1 列出了管理项目时您可能会注意到的一些差异。

表 1:VBA 与 Visual Studio .NET IDE 之间的差异

VBA IDE Visual Studio .NET IDE
项目资源管理器包含当前打开的所有项目(模板、文档和外接程序)的动态列表。 解决方案浏览器包含打开的解决方案中的一个或多个项目的静态列表。
项目文件存储在子文件夹中:用户窗体、模块和类模块。 项目文件按字母顺序存储到子文件夹中,且不进行分类。
在 Word 中,项目包含一个文件夹,该文件夹显示共用模板的引用。在 Word 和 Excel 中,使用 Tools(工具)菜单中的 References(引用)命令来设置外部引用。

如果使用 Web 服务工具包创建 Web 引用,将为 Web 服务及其所有方法创建类。这些类位于类模块文件夹中。

项目包含一个文件夹,该文件夹显示使用 Projects(项目)菜单中的 Add Reference(添加引用)命令设置的引用。

如果创建 Web 引用,引用将位于 Web 引用文件夹中。

不同的项目文件具有不同的文件扩展名:用户窗体 (.frm)、类模块 (.cls) 和模块 (.bas)。 窗体、模块和类模块的项目文件具有相同的 .vb 扩展名。支持文件具有其他扩展名(.xml、.aspx 等)。
在 Word 模板或文档的 VBA 解决方案中,ThisDocument 位于 Microsoft Word 对象文件夹中。

在 Excel 文档的 VBA 解决方案中,ThisWorkbook 和工作表位于 Microsoft Excel 对象文件夹中。

Visual Basic .NET Word 项目包含 ThisDocument 代码文件。

Visual Basic .NET Excel 项目包含 ThisWorkbook 代码文件。

在使用 ActiveX 控件过程中,您将发现两者之间的另一个不同之处。在 VBA 中,ActiveX 控件是顶级对象并支持智能感知。而在 Visual Basic .NET 中,必须使用“Visual Studio Tools for Office”中的 FindControl 方法为控件定义变量并将它们转换成严格类型以便使用智能感知。

安全性差异

Microsoft .NET Framework 提供了 VBA 中没有提供的安全功能。在 VBA 中,有三种基本的安全选项:

  • 在用户计算机上将安全性设置成高并对代码进行数字签名。
  • 当显示宏病毒警告时,让用户决定是否信任代码。
  • 将安全性设置成低以允许所有代码运行(包括恶意代码)。请注意,应从不使用第三种选项。

具有使用 Visual Basic .NET 创建的托管代码扩展功能的 Word 和 Excel 文档不使用依赖于 Office 证书存储的 Office 宏安全。它们融合了 Microsoft .NET Framework 1.1 中的标准安全功能,例如:

  • 不再需要代码签名,因为 NET Framework 中有多种类型的安全措施,包括应用程序目录、严格命名、URL 等。
  • 管理员可以使用标准工具来设置安全策略。安全策略必须向程序集授予完全信任,否则代码不能运行。
  • 最终用户无法更改 Word 或 Excel 中的安全选项来允许运行未授予信任的代码。如果最终用户打开带有未授予信任代码的文档,代码将不能运行。

有关设置 .NET Framework 中安全措施的详细信息,请参阅“Visual Studio Tools for Office”帮助主题“使用托管代码扩展的 Office 解决方案中的安全性”或参阅 An Overview of Security in the .NET Framework

部署差异

部署 Visual Basic .NET 应用程序与部署 VBA 应用程序存在非常大的差异。“Visual Studio Tools for Office”项目通常由两个文件组成:包含编译代码的程序集和包含指向该程序集的自定义属性的文档(Excel 工作表或者是 Word 文档或模板)。文档和程序集被单独进行部署。与在文档中嵌入代码的许多 VBA 项目不同,在“Visual Studio Tools for Office”项目中,程序集可以存储在共享的网络位置中,也可以被复制到每个最终用户的计算机中。在网络位置中部署程序集的优点在于更易于更新代码,因为网络共享中只有一份程序集。用户可以修改和自定义自己的文档,每次打开文档时,可以访问更新后的程序集。这会自动发生,无需用户的参与。

转换 VBA 代码

本节介绍如何使用“Visual Studio Tools for Office”将 VBA 代码转换到 Visual Basic .NET,并列举分别来自 Word 和 Excel 的两个例子。附录中提供了这两个例子的完整 Visual Basic .NET 代码。

Word 中的 VBA 代码示例

以下 Word 宏创建一个新样式(如果该样式不存在),然后将该样式应用到活动文档中所有左对齐的段落。

' VBA
Private Sub Document_Open()
    Dim currentParagraph As Paragraph

    ' 调用 CreateStyle,传递样式名称和有关属性。
    CreateStyle "MyNewStyle", "Arial", 9.5, True, False, 0.5

    ' 将样式应用到每个左对齐的段落。
    For Each currentParagraph In ActiveDocument.Paragraphs
        If currentParagraph.Alignment = wdAlignParagraphLeft Then
            currentParagraph.Style = "MyNewStyle"
        End If
    Next currentParagraph
End Sub
Private Function StyleExists(styleName As String) As Boolean
    Dim currentStyle As Style
    Dim stylePresent As Boolean
    stylePresent = False

    ' 检查活动文档中是否存在该样式。
    For Each currentStyle In ActiveDocument.Styles
        If currentStyle.NameLocal = styleName Then
            stylePresent = True
            Exit For
        End If
    Next currentStyle

    ' 返回。
    StyleExists = stylePresent
End Function

Private Sub CreateStyle(styleName As String, styleFontName As String, _
    styleFontSize As Single, styleBold As Boolean, _
    styleItalic As Boolean, Optional styleFirstLineIndent As Single, _
    Optional styleSpaceBefore As Single)

    ' 检查样式是否已经存在。
    If Not StyleExists(styleName) Then

        ' 通过传递的属性创建样式。
        ActiveDocument.Styles.Add styleName
        With ActiveDocument.Styles(styleName)
            .Font.Name = styleFontName
            .Font.Size = styleFontSize
            .Font.Bold = styleBold
            .Font.Italic = styleItalic
            .ParagraphFormat.FirstLineIndent = _ 
                InchesToPoints(styleFirstLineIndent)
            .ParagraphFormat.SpaceBefore = _
                InchesToPoints(styleSpaceBefore)
            .ParagraphFormat.Alignment = wdAlignParagraphLeft
        End With
    End If
End Sub

创建 Visual Basic .NET 项目

要转换 VBA 代码,必须使用“Visual Studio Tools for Office”在 Visual Studio .NET 中创建 Word 文档项目。

要创建新的 Word 文档项目

  1. File(文件)菜单中,指向 New(新建),然后单击 Project(项目)。
  2. New Project(新建项目)对话框中,展开 Microsoft Office 2003 Projects(Microsoft Office 2003 项目),然后选择 Visual Basic Projects(Visual Basic 项目)。
  3. Templates(模板)窗格中,选择 Word Document(Word 文档)。
  4. 将项目命名为 Create Word Style(创建 Word 样式),然后单击 OK(确定)。
  5. 当出现 Microsoft Office Project Wizard(Microsoft Office 项目向导)时,确保选择了 Create new document(创建新文档),然后单击 Finish(完成)。

然后向 Word 文档添加文本。

要向文档添加文本

  1. 打开 Microsoft Office Word 2003 中的 Create Word Style.doc 文档。

    因为您还没有编译该程序集,可能会出现一个警告,提示程序集名称或程序集链接位置属性被破坏。单击 OK(确定)关闭警告。

  2. 添加多段文本,设置不同的段落对齐。例如,居中对齐标题,左对齐一些段落并右对齐另一些段落。
  3. 保存并关闭 Word 文档。

复制代码

然后,必须将 VBA 代码复制并粘贴到 Visual Studio .NET 的新 Word 文档项目中。

要将 VBA 代码复制并粘贴到 Word 项目中

  1. 在 Visual Basic .NET 项目中,定位 OfficeCodeBehind 类。
  2. 复制 Document_Open 子例程中的 VBA 代码(不包括 SubEnd Sub 关键字)并粘贴到 ThisDocument_Open 方法中。
  3. 将完整的 StyleExists 函数和 CreateStyle 子例程复制并粘贴到 ThisDocument_Close 方法下面(未包含在此方法中)的 OfficeCodeBehind 类中。

    请注意,某些对象(StyleActiveDocument)具有蓝色波浪下划线,这说明代码中的这些对象存在问题。还要注意,在粘贴代码时,ByVal 将自动添加到函数 StyleExists 的参数列表中,而不是添加到 CreateStyle 子例程的参数列表中。这是因为 CreateStyle 子例程具有需要默认值的可选参数,这将在本文后面介绍。

    提示:您可能已经注意到 Visual Studio .NET Tools(工具)菜单包含 Upgrade Visual Basic 6 Code(升级 Visual Basic 6 代码)菜单项。此工具将转换 Visual Basic 6 语言差异;但是,“Visual Studio Tools for Office”使用 Microsoft Office Word 2003 主互用程序集 (PIA) 作为访问 Word 对象模型的方法(托管代码与 COM 互用的方式),而不能使用升级工具来解决。相反,问题和警告将以注释形式出现在整个代码中。利用当鼠标指针悬停在含有蓝色波浪线的文本上时出现的智能感知功能,将 VBA 代码直接粘贴到 Visual Studio .NET IDE 中时,也可以获得同样的信息。有关 Office 主互用程序集的详细信息,请参阅 Working with the Office XP Primary Interop Assemblies

转换代码

将 VBA 代码复制到新项目中后,就可以开始转换代码了。

要在 Visual Basic .NET 中转换代码

  1. StyleExists 函数的声明语句中:
    Dim currentStyle as Style
    Dim stylePresent As Boolean
    stylePresent = False
    

    Style 对象属于 Word 命名空间,因此必须将其更改为 Word.Style 限定引用。也可以将 stylePresent 的声明语句与将其赋值为 False 的语句合并成一个语句:

    Dim currentStyle as Word.Style
    Dim stylePresent As Boolean = False
    
  2. For Each 语句的第一行中:
    For Each currentStyle in ActiveDocument.Styles
    

    在 VBA 中,ActiveDocumentApplication 对象的成员。因为是在应用程序中直接编写代码,所以自动引用 Application 对象。在 VBA 中,您可以(但不是必须)写成 Application.ActiveDocument

    当使用“Visual Studio Tools for Office”创建 Word 文档项目时,将创建 Word.Document (ThisDocument) 和 Word.Application (ThisApplication)。ActiveDocument 必须被更改为 ThisApplication.ActiveDocument

    提示:可以在整个代码中通过执行全局查找和替换操作来快速更改 ActiveDocument
    For Each currentStyle in ThisApplication.ActiveDocument.Styles
    
    提示:如果只使用一个文档,ThisDocument 也可以指活动文档。ThisDocument 实际上是指与程序集相关的文档(创建“Visual Studio Tools for Office”项目时使用的文档)。
  3. 在函数的最后一行中:
    StyleExists = stylePresent
    

    可以使用关键字 Return 返回变量。将 StyleExists = 更改为 Return

    Return stylePresent
    
  4. 在 CreateStyle 子例程中:
    Private Sub CreateStyle(styleName As String, styleFontName As String, _
        styleFontSize As Single, styleBold As Boolean, _
        styleItalic As Boolean, Optional styleFirstLineIndent As Single, _
        Optional styleSpaceBefore As Single )
    

    可选参数后的逗号下面出现的蓝色波浪线表明代码中存在问题。将鼠标指针放在波浪线上,将会显示工具提示“可选参数必须指定默认值。”

    为每个可选参数添加默认值 0,如下例所示。

    Optional ByVal styleFirstLineIndent as Single = 0, _
    Optional ByVal styleSpaceBefore As Single = 0)
    

    请注意,当可选参数被解析时,将向每个参数自动添加 ByVal

    提示:在 Visual Basic .NET 中,使用可选参数的首选方法是创建重载方法。有关详细信息,请参阅 Overloaded Properties and Methods
  5. 在设置 FirstLineIndent 的行中:
    ParagraphFormat.FirstLineIndent = _
        InchesToPoints(styleFirstLineIndent)
    

    InchesToPoints 方法是 Application 对象的成员。将方法更改为 ThisApplication.InchesToPoints

    ParagraphFormat.FirstLineIndent = _
        ThisApplication.InchesToPoints(styleFirstLineIndent)
    
  6. 与此类似,在下一行中,将 InchesToPoints 方法更改为 ThisApplication.InchesToPoints
    ParagraphFormat.SpaceBefore = _
        ThisApplication.InchesToPoints(styleSpaceBefore)
    
  7. 在下一行中:
    ParagraphFormat.Alignment = wdAlignParagraphLeft
    

    需要完全限定 wdAlignParagraphLeft 常量的枚举名称:

    ParagraphFormat.Alignment = _
        Word.WdParagraphAlignment.wdAlignParagraphLeft
    
  8. ThisDocument_Open 方法的变量声明语句中:
    Dim currentParagraph As Paragraph
    

    Paragraph 对象属于 Word 命名空间,因此需要将其更改成 Word.Paragraph 限定引用,如下所示:

    Dim currentParagraph As Word.Paragraph
    
  9. For Each 语句中,向 ActiveDocument 添加 ThisApplication 限定符(如果已经执行了全局查找和替换操作,这可能已经被更改):
    For Each currentParagraph In _
        ThisApplication.ActiveDocument.Paragraphs
    
  10. 在下一行中:
    If currentParagraph.Alignment = wdAlignParagraphLeft Then
    

    需要完全限定 wdAlignParagraphLeft 常量的枚举名称:

    If currentParagraph.Alignment = _
        Word.WdParagraphAlignment.wdAlignParagraphLeft Then
    
  11. 单击 Build(生成)并选择 Build Solution(生成解决方案)以生成解决方案。

当再次打开 Word 文档时,您将发现所有左对齐的段落都被应用了 NewStyle 样式。

Excel 中的 VBA 代码示例

以下 Excel VBA 宏创建一个新样式(如果该样式不存在),并将其应用到一个单元格区域 (A1-C2)。

Private Sub Workbook_Open()
    Dim cellRange As Range
    Dim styleName As String
    Dim cellFormat As String
    cellFormat = "_($* #,##0.00_)"
    styleName = "NewStyle"
    
    ' 设置单元格区域 A1-C2。
    Set cellRange = Range("A1:C2")    

    ' 如果样式不存在,则创建该样式并为其设置格式。
    If Not StyleExists(styleName) Then
        FormatStyle styleName, "Times New Roman", 9, cellFormat
    End If
    
    ' 对区域应用样式。
    cellRange.Style = styleName
End Sub

Function StyleExists(styleName As String) As Boolean
    On Error GoTo StyleExists_Err
    Dim blnStyleExists As Boolean

    ' 假定开始时样式不存在。
    blnStyleExists = False
    ActiveWorkbook.Styles.Add (styleName)

StyleExists_End:
    StyleExists = blnStyleExists
    Exit Function

StyleExists_Err:
    Select Case Err.Number
        Case 1004
            ' 错误号为 1004,因此样式存在。
            blnStyleExists = True
        Case Else
            ' 处理其他情况。
    End Select
    Resume StyleExists_End
End Function

Sub FormatStyle(styleName As String, styleFont As String, _
        styleFontSize As Single, styleFormat As String)
        
        ' 设置样式的格式。
        With ActiveWorkbook.Styles(styleName)
            .Font.Name = styleFont
            .Font.Size = styleFontSize
            .NumberFormat = styleFormat
        End With
End Sub

创建项目

要转换 VBA 代码,必须使用“Visual Studio Tools for Office”在 Visual Studio .NET 中创建 Excel 工作簿项目。

要创建新的 Excel 工作簿项目

  1. File(文件)菜单中,指向 New(新建),然后单击 Project(项目)。
  2. New Project(新建项目)对话框中,展开 Microsoft Office 2003 Projects(Microsoft Office 2003 项目),然后选择 Visual Basic Projects(Visual Basic 项目)。
  3. Templates(模板)窗格中,选择 Excel Workbook(Excel 工作簿)。
  4. 将项目命名为 Create Excel Style(创建 Excel 样式),然后单击 OK(确定)。
  5. 当出现 Microsoft Office Project Wizard(Microsoft Office 项目向导)时,确保选择了 Create new document(创建新文档),然后单击 Finish(完成)。

然后需要向 Excel 工作簿添加文本。

要向工作簿添加文本

  1. 打开 Microsoft Office Excel 2003 中的 Create Excel Style.xls 工作簿。

    因为您还没有编译该程序集,可能会出现一个警告,提示程序集名称或程序集链接位置属性被破坏。单击 OK(确定)关闭警告。

  2. 向 Excel 工作表的区域 A1-C2 中添加数值。可以向其他单元格添加额外的文本以作为测试该代码仅影响 A1-C2 区域的一种方法。
  3. 保存并关闭 Excel 工作簿。

复制代码

然后需要将 VBA 代码复制到新的 Excel 工作簿项目中。将复制除了 StyleExists 方法以外的所有代码。

要将 VBA 代码复制并粘贴到 Excel 项目中

  1. 在 Visual Basic .NET 项目中,定位 OfficeCodeBehind 类。
  2. 将 VBA 代码中的 FormatStyle 子例程复制并粘贴到 ThisWorkbook_BeforeClose 方法下面(未包含在此方法中)的 OfficeCodeBehind 类中。

    请注意,已自动添加 ByVal 作为参数传递的默认方式。

  3. Workbook_Open 子例程中的 VBA 代码复制到 Visual Basic .NET 项目的 ThisWorkbook_Open 方法中(不包括 SubEnd Sub 关键字)。

转换代码

将 VBA 代码复制到新项目中后,就可以开始转换代码了。

要转换 Visual Basic .NET 中的代码

  1. FormatStyle 子例程的第一行中:
    With ActiveWorkbook.Styles(styleName)
    

    ActiveWorkbook 对象属于 Application 对象,因此必须添加 ThisApplication 限定符。

    With ThisApplication.ActiveWorkbook.Styles(styleName)
    

    另外,可以使用 ThisWorkbook 变量代替 ThisApplication.ActiveWorkbook。请注意,ThisWorkbook 可以不是指活动工作簿;实际上它指的是与项目相关的工作簿。

  2. 在 VBA Workbook_Open 子例程的第一行中:
    Dim cellRange as Range
    

    Range 对象属于 Excel 命名空间;因此,需要将该对象限定成 Excel.Range

    稍微向下一点,注意以下行:

    cellRange = Range("A1:C2")
    

    请注意,不支持 Set 关键字并已经自动从代码中删除该关键字。Range 属性是 Worksheet 对象的成员。要使用 Worksheet 对象,请使用 Ctype 函数初始化对象变量。需要将 Range 属性限定成 ThisApplication.Range。还可以将变量声明及其赋值合并成一个语句:

    Dim ThisWorksheet As Excel.Worksheet = _
        CType(ThisWorkbook.Worksheets.Item("Sheet1"), Excel.Worksheet)
    Dim cellRange As Excel.Range = ThisWorksheet.Range("A1:C2")
    
  3. 更改其他声明以包含变量赋值:
    Dim styleName As String = "NewStyle"
    Dim cellFormat As String = "_($* #,##0.00_)"
    
  4. 可以直接在 ThisWorkbook_Open 方法中添加结构化异常处理以测试样式是否存在,而不是调用 VBA 示例中的 StyleExists 函数。删除 If 语句并键入以下代码:
    ' 如果样式不存在,则创建该样式并为其设置格式。
    Try
        ThisApplication.ActiveWorkbook.Styles.Add(styleName)
    Finally
        FormatStyle(styleName, "Times New Roman", 9, cellFormat)
    End Try
    
  5. 单击 Build(生成)并选择 Build Solution(生成解决方案)以生成解决方案。

    当再次打开 Excel 工作簿时,您将发现单元格区域 A1-C2 应用了 NewStyle 样式。

小结

在决定是否将 VBA 代码转换到 Visual Basic .NET 时,应该考虑两者在安全性、部署和代码维护等方面的差异,以及项目是否能从 Microsoft .NET Framework 提供的功能中受益。您需要根据 Visual Basic .NET 中的语言变化来调整自己的代码,重新将 VBA 用户窗体创建为 Windows 窗体,并确保最终用户的计算机上安装有 .NET Framework 和 Office 2003 主互用程序集。在通过主互用程序集访问 Word 和 Excel 对象模型时,您需要更改代码;但是对象模型相同,部分代码不必进行转换。使用“Visual Studio Tools for Office”和本文提供的信息,您可以开始将 Word 和 Excel 中的 VBA 代码转换到 Visual Basic .NET 中。

附录

本节包含 Word VBA 和 Excel VBA 示例的完整 Visual Basic .NET 代码。

Word 示例

' Visual Basic .NET
' 当文档被打开时调用。
Private Sub ThisDocument_Open() Handles ThisDocument.Open
    Dim currentParagraph As Word.Paragraph

    ' 调用 CreateStyle,传递样式名称和有关属性。
    CreateStyle("MyNewStyle", "Arial", 9.5, True, False, 0.5)

    ' 将样式应用到每个左对齐的段落。
    For Each currentParagraph In ThisApplication.ActiveDocument.Paragraphs
        If currentParagraph.Alignment = _
            Word.WdParagraphAlignment.wdAlignParagraphLeft Then
            currentParagraph.Style = "MyNewStyle"
        End If
    Next currentParagraph
End Sub

Private Function StyleExists(ByVal styleName As String) As Boolean
    Dim currentStyle As Word.Style
    Dim stylePresent As Boolean = False

    ' 检查活动文档中是否存在该样式。
    For Each currentStyle In ThisApplication.ActiveDocument.Styles
        If currentStyle.NameLocal = styleName Then
            stylePresent = True
            Exit For
        End If
    Next currentStyle

    ' 返回
    Return stylePresent
End Function

Private Sub CreateStyle(ByVal styleName As String, ByVal _
    styleFontName As String, ByVal styleFontSize As Single, _
    ByVal styleBold As Boolean, ByVal styleItalic As Boolean, _
    Optional ByVal styleFirstLineIndent As Single = 0, _
    Optional ByVal styleSpaceBefore As Single = 0)

    ' 检查样式是否已经存在。
    If Not StyleExists(styleName) Then

        ' 通过传递的属性创建样式。
        ThisApplication.ActiveDocument.Styles.Add(styleName)
        With ThisApplication.ActiveDocument.Styles(styleName)
            .Font.Name = styleFontName
            .Font.Size = styleFontSize
            .Font.Bold = styleBold
            .Font.Italic = styleItalic
            .ParagraphFormat.FirstLineIndent = _
                ThisApplication.InchesToPoints(styleFirstLineIndent)
.            ParagraphFormat.SpaceBefore = _
                ThisApplication.InchesToPoints(styleSpaceBefore)
.            ParagraphFormat.Alignment = _
                Word.WdParagraphAlignment.wdAlignParagraphLeft
        End With
    End If
End Sub

Excel 示例

' Visual Basic .NET
' 当工作簿被打开时调用。
Private Sub ThisWorkbook_Open() Handles ThisWorkbook.Open

    Dim ThisWorksheet As Excel.Worksheet = _
        CType(ThisWorkbook.Worksheets.Item("Sheet1"), Excel.Worksheet)
    Dim cellRange As Excel.Range = ThisWorksheet.Range("A1:C2")

    Dim styleName As String = "NewStyle"
    Dim cellFormat As String = "_($* #,##0.00_)"

    ' 设置单元格区域 A1-C2。
    cellRange = ThisApplication.Range("A1:C2")

    ' 如果样式不存在,则创建该样式并为其设置格式。
Try
    ThisApplication.ActiveWorkbook.Styles.Add(styleName)
Finally
    FormatStyle(styleName, "Times New Roman", 9, cellFormat)
End Try

    ' 对区域应用样式。
    cellRange.Style = styleName
End Sub

Sub FormatStyle(ByVal styleName As String, ByVal styleFont As String, _
    ByVal styleFontSize As Single, ByVal styleFormat As String)

    ' 设置样式的格式。
    With ThisApplication.ActiveWorkbook.Styles(styleName)
        .Font.Name = styleFont
        .Font.Size = styleFontSize
        .NumberFormat = styleFormat
    End With
End Sub

相关文章

Visual Studio Tools For Office
Introduction to Visual Basic .NET for Visual Basic Veterans
Comparison of ADO.NET and ADO
An Overview of Security in the .NET Framework
Working with the Office XP Primary Interop Assemblies
Understanding the Excel Object Model from a .NET Developer's Perspective
Understanding the Word Object Model from a .NET Developer's Perspective

 

 

版权所有:UML软件工程组织