Microsoft Office 为组织提供了一个最终用户非常熟悉的环境来快速创建业务应用程序。构建Office 业务应用程序为组织提供了利用以下内容的大量机会:编辑客户关系管理(CRM) 系统、将从业务线应用程序提取的数据前置、托管商业智能报告,以及很多其他可能性。
尽管 Office 开发为组织提供了很多有价值的机会,但是之前它也为这些应用程序的开发和部署提出了一些挑战。早期的托管语言版本也推动了使用Office 创建应用程序的方式。
调用大量的 Office API 方法通常很难,因为其中包含很多参数,而且大多数参数都无用。Visual Basic 的可选参数功能简化了这一操作,但是使用C# 语言的开发人员将不得不编写大量无用的初始化表达式或空语句,以填写所需的方法签名参数。如果您使用的是Visual Basic,您将无法使用类似于C# 3.0 的lambda 的功能来在调用代理时提供内联方法。
在本实验中,您将看到Visual Studio 2010、 C# 4.0 和 Visual Basic 10 中的新功能如何消除上述段落中提到的问题。此外,您还将看到其他一些强大功能,这些功能加速了其他Office 要素的开发。
目标
在本次动手实验中,您将学习如何:
• 学习新语言功能如何加速业务实体的创建
• 探索一些新的语言功能,这些功能使业务实体与Excel 的交互变得更容易
• 利用支持在Office 程序之间进行快速交互的新语言功能
• 了解新的构建过程如何简化向最终用户部署Office 应用程序的过程
系统要求
您必须拥有以下内容才能完成本实验:
• Microsoft Visual Studio 2010 Beta 2
• .Net Framework 4
• Microsoft Excel 2007
• Microsoft Word 2007
安装
使用 Configuration Wizard 验证本实验的所有先决条件。要确保正确配置所有内容,请按照以下步骤进行。
注意:要执行安装步骤,您需要使用管理员权限在命令行窗口中运行脚本。
1. 如果之前没有执行,运行Training Kit 的 Configuration Wizard。为此,运行位于%TrainingKitInstallationFolder%\Labs\Dev10Office\Setup 文件夹下的CheckDependencies.cmd 脚本。安装先决条件中没有安装的软件(如有必要请重新扫描),并完成向导。
注意:为了方便,本实验管理的许多代码都可用于Visual Studio 代码片段。CheckDependencies.cmd文件启动Visual Studio 安装程序文件安装该代码片段。
练习
本次动手实验由以下练习组成:
1. 创建一个帐户类集合并在Microsoft Excel 中显示帐户信息
2. 将Microsoft Excel 工作表嵌入 Microsoft Word 文档中
3. 调整VS 项目文件,以支持在不使用PIA 的情况下部署程序
完成本实验的估计时间:60分钟。
下一步
练习 1:创建一个业务实体集合并将其值插入Excel 工作表中
练习 1:创建一个业务实体集合并将其值插入Excel 工作表中
业务实体是一种常用模式,它通过应用程序或系统承载数据。业务实体可能反映一个银行帐户(显示帐户结余和帐户持有人),或者可能反映放置了很多东西的购物车,其中每项都是它自己的业务实体。
在本练习中,您将学习如何创建业务实体集合,并将这些实体的值写入Excel 工作表中。在本练习中,您还将学习C# 4.0 和Visual Basic 10 中新的语言功能,这些新功能大大加快了业务实体的创建速度。
注意:要验证每个步骤是否正确执行,建议在每次任务结束时生成解决方案。
任务 1 –创建一个新控制台应用程序并引用Microsoft Office 互操作程序集
在本任务中,您将创建一个新控制台应用程序并将其添加到进行Office 开发所需的程序集。
1. 从Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 打开Microsoft Visual Studio 2010。
2. 在Microsoft Visual Studio 初始页面, 单击New Project 图标。
注意:本实验将使用C# 和Visual Basic 两种语言进行展示。您可以使用任何您熟悉的语言。在实验过程中,将指出Visual Studo 2010 和每种语言的新功能。
3. 在C# 或Visual Basic 项目模板列表中,选择Windows | Console Application.
4. 在Name字段中,输入“OfficeApplication”
5. 在右上角,确保选择了.NET Framework 4.0 版本。
6. 接受默认的位置和解决方案名称。单击OK 按钮。该解决方案将使用一个控制台应用程序项目进行创建。
7. 右键单击OfficeApplication 项目节点并选择Add Reference…。
8. 在Add Reference 对话框的 .NET选项卡下,选择Microsoft.Office.Interop.Excel。按住 CTRL 键并单击Microsoft.Office.Interop.Word。单击 OK 按钮。
注意:由于本实验针对的是Office 2007,所以要确保在添加引用时选择了版本12.0.0.0。
完成时,控制台应用程序的引用列表应如下所示:
图 1
Office 开发引用
任务 2 –创建业务实体集合
在本任务中,您将创建一个将预先填充数据的业务实体集合。预先填充用于模拟从单独的源加载带有数据的实体。在此我们将重点介绍数据访问。
首先从创建单独实体开始。
1. 在Solution Explorer 中,右键单击OfficeApplication 项目的节点,并从菜单中选择Add…| Class 。
2. 将出现Add New Item 对话框,其中包含已选中的Class 模板。将名称更改为Account.cs (C#) 或 Account.vb (Visual Basic),单击Add 按钮。
a. 如果使用C# 语言进行本实验,将Account 类的定义更改为public,如下所示:
C#
public class Account
{
}
3. 为Account 添加公共属性ID (integer)、Balance (double) 和 AccountHolder (string),如下所示:
(代码片段– Office编程实验- 练习1 Account 属性 CSharp)
C#
public class Account
{
public int ID { get; set; }
public double Balance { get; set; }
public string AccountHolder { get; set; }
}
(代码片段– Office编程实验- 练习1 Account 属性 VB)
Visual Basic
Public Class Account
Property ID As Integer
Property Balance As Double
Property AccountHolder As String
End Class
注意:Visual Basic 有一项新功能,那就是无需声明一个存储值的单独字段就可以声明属性。这种自动实现属性的工作方式就好象开发人员声明了一个私有字段来存储数据并实现了简单的“getter”和“setter”方法。它们的调用方式与传统属性的调用方式相同。如果属性访问需要更可靠的逻辑,那么仍然可以创建在私有字段中存储数据的传统属性。VS 2008 相应的Visual Basic 代码如下所示:
Visual Basic
' This is the old style using backing variables instead of
' auto-implemented properties
Public Class Account
Private _id As Integer
Private _balance As Double
Private _accountHolder As String
Property ID() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Property Balance() As Double
Get
Return _balance
End Get
Set(ByVal value As Double)
_balance = value
End Set
End Property
Property AccountHolder() As String
Get
Return _accountHolder
End Get
Set(ByVal value As String)
_accountHolder = value
End Set
End Property
End Class
4. Account 类表示您的单个实体类型。通常,应用程序会创建这些实体集合中的某些实体,并使用一些数据填充这些实体。为了保持本实验简洁明了,将通过在创建列表时将值推入各个对象来填充列表。在Module1.vb (VB) 或 Program.cs (C#) 文件中,创建一个名为CreateAccountList 的新方法,如以下代码所示:
(代码片段– Office编程实验- 练习1 CreateAccountList VB)
Visual Basic
Private Function CreateAccountList() As List(Of Account)
Dim checkAccounts As New List(Of Account) From {
New Account With {
.ID = 1,
.Balance = 285.93,
.AccountHolder = "John Doe"
},
New Account With {
.ID = 2,
.Balance = 2349.23,
.AccountHolder = "Richard Roe"
},
New Account With {
.ID = 3,
.Balance = -39.46,
.AccountHolder = "I Dunoe"
}
}
Return checkAccounts
End Function
注意:上述代码强调了Visual Basic 的另一项新功能:集合初始化程序。这使开发人员能够节省大量时间,因为他们可以直接在声明列表时初始化列表的内容。无需实例化列表,然后逐个“更新”更新各项将其添加到列表中。
(代码片段– Office编程实验- 练习1 CreateAccountList CSharp)
C#
private static List<Account> CreateAccountList()
{
var checkAccounts = new List<Account> {
new Account{
ID = 1,
Balance = 285.93,
AccountHolder = "John Doe"
},
new Account{
ID = 2,
Balance = 2349.23,
AccountHolder = "Richard Roe"
},
new Account{
ID = 3,
Balance =-39.46,
AccountHolder = "I Dunoe"
}
};
return checkAccounts;
}
5. 从Module1.vb (VB) 或 Program.cs (C#) 文件中的Main 方法调用CreateAccountList 方法,如下所示:
Visual Basic
Sub Main()
Dim checkAccounts = CreateAccountList()
End Sub
C#
static void Main(string[] args)
{
var checkAccounts = CreateAccountList();
}
任务 3 –创建Excel 工作簿并使用来自业务实体的数据填充它
在本任务中,您将创建一个新Excel 工作簿。然后您可以遍历业务对象集合并将数据插入Excel 工作簿中。最后您将格式化工作表。
1. 第一步是使用Imports (VB) 或 using (C#) 语句导入Office 命名空间。在Module1.vb (VB) 或 Program.cs (C#) 文件的顶部输入以下代码:
(代码片段– Office编程实验- 练习1 Namespaces VB)
Visual Basic
Imports Microsoft.Office.Interop
Imports System.Runtime.CompilerServices
(代码片段– Office编程实验- 练习1 Namespaces CSharp)
C#
using Microsoft.Office.Interop;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
2. 将数据插入Excel 的代码作为Extension 方法实现。
该(和所有)扩展方法的第一个参数表示该方法(在帐户列表中)所操作的类型。第二个参数(DisplayFunc) 是一个类型为 delegate 的Action。Action代理可以接受任意多个参数,但总是返回void。
该代码块创建了一个具有工作簿的新Excel 应用程序,将一些标题文本插入工作簿中,调用一个帮助程序方法来显示Account 对象的值,然后将每列设置为AutoFit 模式,以更好地显示每列的值。
在 Module1.vb (VB) 或 Program.cs (C#) 中的Main 方法后输入以下代码:
(代码片段– Office编程实验- 练习1 DisplayInExcel VB)
Visual Basic
<Extension()>
Sub DisplayInExcel(ByVal accounts As IEnumerable(Of Account), ByVal DisplayFunc As Action(Of Account, Excel.Range))
With New Excel.Application
.Workbooks.Add()
.Visible = True
.Range("A1").Value = "ID"
.Range("B1").Value = "Balance"
.Range("C1").Value = "Account Holder"
.Range("A2").Select()
For Each ac In accounts
DisplayFunc(ac, .ActiveCell)
.ActiveCell.Offset(1, 0).Select()
Next
.Columns(1).AutoFit()
.Columns(2).AutoFit()
.Columns(3).AutoFit()
End With
End Sub
注意:在 C# 中,有必要将Program.cs 中的 Program 类声明更改为static。
(代码片段– Office编程实验- 练习1 DisplayInExcel CSharp)
C#
static void DisplayInExcel(this IEnumerable<Account> accounts,
Action<Account, Excel.Range> DisplayFunc)
{
var x1 = new Excel.Application();
//see the Note below
x1.Workbooks.Add();
x1.Visible = true;
x1.get_Range("A1").Value2 = "ID";
x1.get_Range("B1").Value2 = "Balance";
x1.get_Range("C1").Value2 = "Account Holder";
x1.get_Range("A2").Select();
foreach (var ac in accounts)
{
DisplayFunc(ac, x1.ActiveCell);
x1.ActiveCell.get_Offset(1, 0).Select();
}
((Excel.Range)x1.Columns[1]).AutoFit();
((Excel.Range)x1.Columns[2]).AutoFit();
((Excel.Range)x1.Columns[3]).AutoFit();
}
注意:语句x1.Workbooks.Add(); 反映了 .NET Framework 4.0 和C# 4.0 中的一个重要变化:可选参数。Microsoft.Office.Interop.Excel.Workbook COM 互操作程序集的早期版本需要传入一个参数。此外,C#的早期版本不支持可选参数,而Visual Basic 开发人员多年来都偏爱使用可选参数。之前,该语句显示为x1.Workbooks.Add(Missing.Value);.NET Framework 4.0 中新的互操作程序集与C# 4.0 对可选参数的全新支持结合使用,可以使您的语法更简洁、更清晰。
3. 下一步是从程序的Main 方法调用扩展方法。将以下代码添加到Main 方法的底部:
(代码片段– Office编程实验- 练习1 DisplayInExcel 调用 VB)
Visual Basic
checkAccounts.DisplayInExcel(Sub(account, cell)
cell.Value2 = account.ID
cell.Offset(0, 1).Value2 = account.Balance
cell.Offset(0, 2).Value2 = account.AccountHolder
If account.Balance < 0 Then
cell.Interior.Color = RGB(255, 0, 0)
cell.Offset(0, 1).Interior.Color = RGB(255, 0, 0)
cell.Offset(0, 2).Interior.Color = RGB(255, 0, 0)
End If
End Sub)
注意:这里您看到了Visual Basic 的另一个新功能:语句lambda。语句lambda 是一个匿名代码块,它与变量类似,可以将其用作方法的参数,正如本例所示。lambda的语法是“声明”一系列参数,在本例中是account 和cell,然后提供该lambda 的逻辑。使用语句lambdas 函数或 sub 时,不需要名称但要推理参数类型。
(代码片段– Office编程实验- 练习1 DisplayInExcel 调用 CSharp)
C#
checkAccounts.DisplayInExcel((account, cell) =>
{
cell.Value2 = account.ID;
cell.get_Offset(0, 1).Value2 = account.Balance;
cell.get_Offset(0, 2).Value2 = account.AccountHolder;
if (account.Balance < 0)
{
cell.Interior.Color = 255;
cell.get_Offset(0, 1).Interior.Color = 255;
cell.get_Offset(0, 2).Interior.Color = 255;
}
});
DisplayInExcel 扩展方法接受一个参数,Action代理接受两个参数。Action代理的参数可以是Account 对象的实例,也可以是Excel 工作表单元格的实例。扩展方法实际上是一个功能单位,它将被DisplayInExcel 函数主体中的 for each 循环中的每个Account 调用。
DisplayInExcel 函数包含创建和执行Excel 工作簿的设置的逻辑。您所提供的代理包含从Account 对象获取单个值并将其放在Excel 工作表中的逻辑。
下一步
练习 1:验证
练习 1:验证
在本验证中,您将运行控制台应用程序,并可以看到,打开了Excel 工作表并且您的帐户数据被填充到工作表中。
1. 在Visual Studio 中,按 F5 键以调试模式运行应用程序。
2. 可以看到,应用程序启动了一个Microsoft Excel 实例并将您的数据插入到第一个工作表中:
图 2
Excel 工作表中的帐户数据
注意:注意,列已设置为根据内容调整列宽。此外还要注意, 根据传入到 DisplayInExcel 函数的代理的 for each 循环的逻辑,有负债的帐户背景颜色为红色。
3. 关闭Excel。不要保存任何更改。
下一步
练习 2:将 Excel 工作表嵌入Microsoft Word 中
练习 2:将 Excel 工作表嵌入Microsoft Word 中
在本练习中,将把您的Excel 工作表嵌入到Microsoft Word 文档中。本练习还将向C# 开发人员介绍可选参数。
注意:要验证每个步骤是否正确执行,建议在每次任务结束时生成解决方案。
任务 1 –将Excel 工作表嵌入到新Microsoft Word 文档中
1. 从Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 打开Microsoft Visual Studio 2010。
2. 打开OfficeApplication.sln 解决方案文件。默认情况下,该文件位于以下文件夹:%TrainingKitInstallFolder%\Labs\Dev10Office\Source\Ex02-EmbeddingWorksheet\Begin\,并选择您喜欢的语言。您也可以继续使用上一个练习完成时获得的解决方案。
3. 复制Excel 工作表,以将其粘贴到Word 文档中。Copy()方法可以完成此操作。将以下代码添加到DisplayInExcel 方法(在 Visual Basic 方法中,该命令需要位于With 块中)的末尾:
Visual Basic
.Range("A1:C4").Copy()
C#
x1.get_Range("A1:C4").Copy();
4. 将工作表粘贴到剪贴板后,您需要创建一个Word 文档并将工作表粘贴到该文档中。在Module1.vb (VB) 或 Program.cs (C#) 文件中,创建一个名为EmbedInWordDocument 的新方法,如以下代码所示:
(代码片段– Office编程实验- 练习2 EmbedInWordDocument VB)
Visual Basic
private bool LoadDictionaries()
Dim word As New Word.Application
word.Visible = True
word.Documents.Add()
word.Selection.PasteSpecial(Link:=True, DisplayAsIcon:=False)
End Sub
(代码片段– Office编程实验- 练习2 EmbedInWordDocument CSharp)
C#
private static void EmbedInWordDocument()
{
var word = new Word.Application();
word.Visible = true;
word.Documents.Add();
word.Selection.PasteSpecial(Link:true, DisplayAsIcon:false);
}
注意:C# 开发人员将在调用PasteSpecial 的过程中发现 C# 4.0 的一项新功能:可选参数的使用。PasteSpecial实际上有7 个参数。在大多数情况下,您不需要提供这些参数的值,因为默认值已足够。在C# 的早期版本中,这些值仍然需要提供,即使提供的值为System.Reflection.Missing.Value 类型(这将导致调用PasteSpecial,如下所示):
C#
object iconIndex = System.Reflection.Missing.Value;
object link = true;
object placement = System.Reflection.Missing.Value;
object displayAsIcon = false;
object dataType = System.Reflection.Missing.Value;
object iconFileName = System.Reflection.Missing.Value;
object iconLabel = System.Reflection.Missing.Value;
word.Selection.PasteSpecial(ref iconIndex,
ref link,
ref placement,
ref displayAsIcon,
ref dataType,
ref iconFileName,
ref iconLabel);
注意:C# 开发人员还会注意到,即使PasteSpecial 的参数仍然被引用,也没有必要使用ref 关键字说明这一点。
5. 从Module1.vb (VB) 或 Program.cs (C#) 文件的 Main 方法调用EmbedInWordDocument 方法,如下所示:
Visual Basic
Sub Main()
Dim checkAccounts = CreateAccountList()
checkAccounts.DisplayInExcel(Sub(account, cell)
cell.Value2 = account.ID
cell.Offset(0, 1).Value2 = account.Balance
cell.Offset(0, 2).Value2 = account.AccountHolder
If account.Balance < 0 Then
cell.Interior.Color = RGB(255, 0, 0)
cell.Offset(0, 1).Interior.Color = RGB(255, 0, 0)
cell.Offset(0, 2).Interior.Color = RGB(255, 0, 0)
End If
End Sub)
EmbedInWordDocument()
End Sub
C#
static void Main(string[] args)
{
var checkAccounts = CreateAccountList();
checkAccounts.DisplayInExcel((account, cell) =>
{
cell.Value2 = account.ID;
cell.get_Offset(0, 1).Value2 = account.Balance;
cell.get_Offset(0, 2).Value2 = account.AccountHolder;
if (account.Balance < 0)
{
cell.Interior.Color = 255;
cell.get_Offset(0, 1).Interior.Color = 255;
cell.get_Offset(0, 2).Interior.Color = 255;
}
});
EmbedInWordDocument();
}
下一步
练习 2:验证
练习 2:验证
在本验证中,您将运行控制台应用程序并可以看到,除了应用程序在上一个验证中执行的活动外,您的Excel 工作表也嵌入到了Microsoft Word 应用程序中。
1. 在Visual Studio 中,按 F5 键以调试模式运行应用程序。
2. 可以看到,和之前一样,应用程序启动了Microsoft Excel 的一个实例并将您的数据插入到第一个工作表中。
3. 创建了Excel 工作表后,应用程序将会在Microsoft Word 的一个实例中启动并将您的数据插入到文档中:
图 3
Word 文档中的帐户数据
4. 关闭Excel 和Word。不要保存任何更改。
下一步
练习 3:从应用程序移除PIA 依赖关系
练习 3:从应用程序移除PIA 依赖关系
Office 编程功能依赖于Office PIA 类型来与 Office 套件中的各种应用程序进行交互。过去,由于多种原因,这极大地影响了自定义Office 应用程序的部署。第一,不同版本的Ofice 使用不同版本的PIA,所以管理程序集变得很复杂。第二,IT人员必须确定部署策略,确保所需的PIA 资源在其支持库中可用。另外,部署应用程序的PIA 会导致安装程序较大,安装了不需要的无用功能。
注意:主互操作程序集(PIA)是所有.NET framework 应用程序与 COM 组件进行交互的关键部分。常规互操作程序集用于描述COM 类型,支持在编译时将托管代码与COM 类型绑定。互操作程序集还有助于CLR 了解在运行时如何封送这些COM 类型。主互操作程序集与常规互操作程序集的不同之处在于,它是所有类型描述的“正式”所有者,并由供应商签署以确保其有效性。
Visual Studio 2010 中的开发通过从应用程序清除PIA 依赖关系减轻了这些负担。清除了依赖关系后,编译器将直接从PIA 导入应用程序所需的任何类型;您只需部署应用程序,并了解您所需的所有PIA 是否都包含在您的应用程序集中。
任务 1 –检查 PIA 依赖关系是否已被默认清除
在 Visual Studio 2010 中,默认已清除了PIA 依赖关系,要验证这一点:
1. 从Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 打开Microsoft Visual Studio 2010。
2. 打开OfficeApplication.sln 解决方案文件。默认情况下,该文件位于以下文件夹:%TrainingKitInstallFolder%\Labs\Dev10Office\Source\RemovingPIA\Begin\,并选择您喜欢的语言。您也可以继续使用上一个练习完成时获得的解决方案。
3. 展开项目的References。
4. 右键单击项目引用中的Microsoft.Office.Interop.Excel,并选择Properties。
5. 注意,Embed Interop Types 的值设置为 True。
6. 右键单击项目引用中的Microsoft.Office.Interop.Word,并选择Properties。
7. 注意,Embed Interop Types 的值设置为 True。
下一步
总结
总结
在本实验中,您看到了使用Office 创建自定义应用程序的简单性。您使用了新的语言功能,如Visual Basic 新的自动属性和集合初始化程序,这些新功能使您能够快速构建类和方法。
对于其他语言功能,您还看到了C# 4.0 的可选参数,并了解了该功能如何让使用Office 的PIA 变得更简洁且不易出错。此外,您还学习了Visual Basic 的多行 lambda,以及语句lambda 如何使您简洁地将代理变为合适的语句。
最后,您还学习了如何将互操作类型嵌入Office 业务应用程序中,以显著减轻部署Office 应用程序的负担。这是对以前的Office 开发环境的极大改进,在以前的开发环境中,您不得不辛苦地处理多个不同版本的依赖关系。
Visual Studio 2010 的最新版本在工具、平台和语言方面的所有这些更新都会提高您创建强大、灵活的Office 业务应用程序的能力。