如何:通过使用 Visual C# 2010 功能访问 Office 互操作对象(C# 编程指南)
Visual C# 2010 引入了可简化对 Office API 对象的访问的新功能。 这些新功能包括命名实参和可选实参、名为 dynamic 的新类型,以及将实参传递到 COM 方法中的引用形参(就好像它们是值形参一样)的功能。
在本主题中,您将使用这些新功能编写创建和显示 Microsoft Office Excel 工作表的代码。 然后,您将编写代码来添加一个 Office Word 文档,其中包含链接到该 Excel 工作表的图标。
若要完成此演练,您必须在计算机上安装 Microsoft Office Excel 2007 和 Microsoft Office Word 2007。
如果使用的操作系统低于 Windows Vista,请务必安装 .NET Framework 2.0。
提示
对于在以下说明中使用的某些 Visual Studio 用户界面元素,您的计算机可能会显示不同的名称或位置。这些元素取决于您所使用的 Visual Studio 版本和您所使用的设置。有关更多信息,请参见 Visual Studio 设置。
创建一个新的控制台应用程序
启动 Visual Studio。
在**“文件”菜单上指向“新建”,再单击“项目”。 此时将出现“新建项目”**对话框。
在**“已安装的模板”窗格中,展开“Visual C#”,然后单击“Windows”**。
查看**“新建项目”对话框的顶部,确保选择“.NET Framework 4”**作为目标框架。
在**“模板”窗格中单击“控制台应用程序”**。
在**“名称”**字段中键入项目的名称。
单击**“确定”**。
新项目出现在**“解决方案资源管理器”**中。
添加引用
在**“解决方案资源管理器”中,右击项目的名称,然后单击“添加引用”。 此时将出现“添加引用”**对话框。
在**“.NET”页上的“组件名称”列表中,选择“Microsoft.Office.Interop.Word”,然后按下 Ctrl 键并选择“Microsoft.Office.Interop.Excel”**。
单击**“确定”**。
添加必要的 using 指令
在**“解决方案资源管理器”中,右击“Program.cs”文件,然后单击“查看代码”**。
将以下 using 指令添加到代码文件的顶部。
using Excel = Microsoft.Office.Interop.Excel; using Word = Microsoft.Office.Interop.Word;
创建银行帐户的列表
将以下类定义粘贴到**“Program.cs”**中 Program 类的下方。
public class Account { public int ID { get; set; } public double Balance { get; set; } }
将以下代码添加到 Main 方法,以创建一个包含两个帐户的 bankAccounts 列表。
// Create a list of accounts. var bankAccounts = new List<Account> { new Account { ID = 345678, Balance = 541.27 }, new Account { ID = 1230221, Balance = -127.44 } };
声明将帐户信息导出到 Excel 的方法
将以下方法添加到 Program 类以设置一个 Excel 工作表。
方法 Add 具有用于指定特定模板的可选形参。 利用可选形参(Visual C# 2010 中的新功能),您将能够在希望使用形参的默认值的情况下省略该形参的实参。 由于在下面的代码中未发送参数,因此 Add 使用默认模板并创建一个新工作簿。 C# 早期版本中的等效语句需要占位符参数:ExcelApp.Workbooks.Add(Type.Missing)。
static void DisplayInExcel(IEnumerable<Account> accounts) { var excelApp = new Excel.Application(); // Make the object visible. excelApp.Visible = true; // Create a new, empty workbook and add it to the collection returned // by property Workbooks. The new workbook becomes the active workbook. // Add has an optional parameter for specifying a praticular template. // Because no argument is sent in this example, Add creates a new workbook. excelApp.Workbooks.Add(); // This example uses a single workSheet. The explicit type casting is // removed in a later procedure. Excel._Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet; }
将下面的代码添加到 DisplayInExcel 的末尾。 该代码将值插入到工作表第一行的前两列中。
// Establish column headings in cells A1 and B1. workSheet.Cells[1, "A"] = "ID Number"; workSheet.Cells[1, "B"] = "Current Balance";
将下面的代码添加到 DisplayInExcel 的末尾。 foreach 循环将帐户列表中的信息放入工作表的连续几行的前两列。
var row = 1; foreach (var acct in accounts) { row++; workSheet.Cells[row, "A"] = acct.ID; workSheet.Cells[row, "B"] = acct.Balance; }
将以下代码添加到 DisplayInExcel 的末尾,用于根据内容的需要调整列宽。
workSheet.Columns[1].AutoFit(); workSheet.Columns[2].AutoFit();
C# 的早期版本需要为这些操作执行显式强制转换,原因是 ExcelApp.Columns[1] 返回 Object,并且 AutoFit 是 Excel 的 Range 方法。 以下各行显示强制转换。
((Excel.Range)workSheet.Columns[1]).AutoFit(); ((Excel.Range)workSheet.Columns[2]).AutoFit();
如果程序集是通过 /link 编译器选项引用的,或者,与之相当,如果 Excel 的**“嵌入互操作类型”**属性设置为 true,则 Visual C# 2010 会将返回的 Object 自动转换为 dynamic。 此属性的默认值为 True。
运行项目
将以下行添加到 Main 的末尾。
// Display the list in an Excel spreadsheet. DisplayInExcel(bankAccounts);
按 Ctrl+F5。
将出现一个 Excel 工作表,其中包含两个帐户中的数据。
添加 Word 文档
为了演示 Visual C# 2010 用于增强 Office 编程的其他方法,下面的代码将打开 Word 应用程序,并创建一个链接到 Excel 工作表的图标。
将此步骤后面提供的方法 CreateIconInWordDoc 粘贴到 Program 类中。 CreateIconInWordDoc 使用命名参数和可选参数,以降低对 Add 和 PasteSpecial 的方法调用的复杂性。 这些调用结合了 Visual C# 2010 的其他两个新功能,这两个功能可简化对具有引用参数的 COM 方法的调用。 首先,您可以将实参发送到引用形参,就好像它们是值形参一样。 也就是说,您可以直接发送值,而无需为每个引用形参创建变量。 编译器将生成临时变量来容纳实参值,并在您从调用中返回时丢弃这些变量。 其次,您可以在实参列表中省略 ref 关键字。
Add 方法具有四个引用形参,这四个形参都是可选的。 在 Visual C# 2010 中,如果要使用任何或全部形参的默认值,您可以为它们省略实参。 在 Visual C# 2008 及早期版本中,必须为每个形参提供实参,并且,由于形参是引用形参,因此实参必须为变量。
PasteSpecial 方法插入剪贴板的内容。 该方法具有七个引用形参,这七个形参都是可选的。 下面的代码为其中两个形参指定实参:Link(用于创建指向剪贴板内容源的链接)和 DisplayAsIcon(用于将链接显示为图标)。 在 Visual C# 2010 中,您可以为这两个形参使用命名实参,并忽略其他形参。 尽管这些形参是引用形参,但您不必使用 ref 关键字,或创建变量以作为实参发送。 可以直接发送这些值。 在 Visual C# 2008 及早期版本中,您必须为每个引用形参发送变量实参。
static void CreateIconInWordDoc() { var wordApp = new Word.Application(); wordApp.Visible = true; // The Add method has four reference parameters, all of which are // optional. Visual C# 2010 allows you to omit arguments for them if // the default values are what you want. wordApp.Documents.Add(); // PasteSpecial has seven reference parameters, all of which are // optional. This example uses named arguments to specify values // for two of the parameters. Although these are reference // parameters, you do not need to use the ref keyword, or to create // variables to send in as arguments. You can send the values directly. wordApp.Selection.PasteSpecial( Link: true, DisplayAsIcon: true); }
在 Visual C# 2008 或该语言的早期版本中,需要以下更复杂的代码。
static void CreateIconInWordDoc2008() { var wordApp = new Word.Application(); wordApp.Visible = true; // The Add method has four parameters, all of which are optional. // In Visual C# 2008 and earlier versions, an argument has to be sent // for every parameter. Because the parameters are reference // parameters of type object, you have to create an object variable // for the arguments that represents 'no value'. object useDefaultValue = Type.Missing; wordApp.Documents.Add(ref useDefaultValue, ref useDefaultValue, ref useDefaultValue, ref useDefaultValue); // PasteSpecial has seven reference parameters, all of which are // optional. In this example, only two of the parameters require // specified values, but in Visual C# 2008 an argument must be sent // for each parameter. Because the parameters are reference parameters, // you have to contruct variables for the arguments. object link = true; object displayAsIcon = true; wordApp.Selection.PasteSpecial( ref useDefaultValue, ref link, ref useDefaultValue, ref displayAsIcon, ref useDefaultValue, ref useDefaultValue, ref useDefaultValue); }
将以下语句添加到 Main 的末尾。
// Create a Word document that contains an icon that links to // the spreadsheet. CreateIconInWordDoc();
将以下语句添加到 DisplayInExcel 的末尾。 Copy 方法将工作表添加到剪贴板。
// Put the spreadsheet contents on the clipboard. The Copy method has one // optional parameter for specifying a destination. Because no argument // is sent, the destination is the Clipboard. workSheet.Range["A1:B3"].Copy();
按 Ctrl+F5。
此时将出现一个包含图标的 Word 文档。 双击该图标以显示工作表。
设置“嵌入互操作类型”属性
当您在运行时调用不需要主互操作程序集 (PIA) 的 COM 类型时,可以使用其他增强功能。 如果去除对 PIA 的依赖,将可实现版本中立性,并可更加轻松地进行部署。 有关不使用 PIA 进行编程的优势的更多信息,请参见演练:嵌入托管程序集中的类型(C# 和 Visual Basic)。
此外,由于可以使用类型 dynamic(而不是 Object)来表示 COM 方法需要和返回的类型,因此编程将更加轻松。 在运行时之前不会计算具有类型 dynamic 的变量,从而无需进行显式强制转换。 有关更多信息,请参见使用类型 dynamic(C# 编程指南)。
在 Visual C# 2010 中,默认行为是嵌入类型信息(而不是使用 PIA)。 由于有这种默认行为,因此前面的几个示例可以得到简化,原因是不需要进行显式强制转换。 例如,DisplayInExcel 中 worksheet 声明的编写方式为 Excel._Worksheet workSheet = excelApp.ActiveSheet,而不是 Excel._Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet。 在同一方法中调用 AutoFit 也将需要显式强制转换,而不使用默认行为,因为 ExcelApp.Columns[1] 会返回 Object,且 AutoFit 是 Excel 方法。 下面的代码演示强制转换。
((Excel.Range)workSheet.Columns[1]).AutoFit(); ((Excel.Range)workSheet.Columns[2]).AutoFit();
若要更改默认行为并使用 PIA(而不是嵌入类型信息),请在**“解决方案资源管理器”中展开“引用”节点,然后选择“Microsoft.Office.Interop.Excel”或“Microsoft.Office.Interop.Word”**。
如果看不到**“属性”**窗口,请按 F4。
在属性列表中找到**“嵌入互操作类型”,并将它的值更改为“False”**。 与之相当,您可以在命令提示符处使用 /reference 编译器选项(而不是 /link)进行编译。
向表中添加其他格式设置
将对 DisplayInExcel 中 AutoFit 的两个调用替换为以下语句。
// Call to AutoFormat in Visual C# 2010. workSheet.Range["A1", "B3"].AutoFormat( Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
AutoFormat 方法有七个值形参,所有这些形参都是可选的。 利用命名实参和可选实参,您可以为这些形参中的部分或全部提供实参,或者不为其中任何形参提供实参。 在前面的语句中,只为其中一个形参 Format 提供了实参。 由于 Format 是形参列表中的第一个形参,因此您不必提供形参名称。 不过,如果包括形参名称,语句将可能更容易理解,如下面的代码所示。
// Call to AutoFormat in Visual C# 2010. workSheet.Range["A1", "B3"].AutoFormat(Format: Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
按 Ctrl+F5 查看结果。 其他格式列在 XlRangeAutoFormat 枚举中。
将步骤 1 中的语句与下面的代码进行比较,该代码显示了 Visual C# 2008 或早期版本中需要的参数。
// The AutoFormat method has seven optional value parameters. The // following call specifies a value for the first parameter, and uses // the default values for the other six. // Call to AutoFormat in Visual C# 2008. This code is not part of the // current solution. excelApp.get_Range("A1", "B4").AutoFormat(Excel.XlRangeAutoFormat.xlRangeAutoFormatTable3, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
示例
下面的代码显示完整的示例。
using System;
using System.Collections.Generic;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
namespace OfficeProgramminWalkthruComplete
{
class Walkthrough
{
static void Main(string[] args)
{
// Create a list of accounts.
var bankAccounts = new List<Account>
{
new Account {
ID = 345678,
Balance = 541.27
},
new Account {
ID = 1230221,
Balance = -127.44
}
};
// Display the list in an Excel spreadsheet.
DisplayInExcel(bankAccounts);
// Create a Word document that contains an icon that links to
// the spreadsheet.
CreateIconInWordDoc();
}
static void DisplayInExcel(IEnumerable<Account> accounts)
{
var excelApp = new Excel.Application();
// Make the object visible.
excelApp.Visible = true;
// Create a new, empty workbook and add it to the collection returned
// by property Workbooks. The new workbook becomes the active workbook.
// Add has an optional parameter for specifying a praticular template.
// Because no argument is sent in this example, Add creates a new workbook.
excelApp.Workbooks.Add();
// This example uses a single workSheet.
Excel._Worksheet workSheet = excelApp.ActiveSheet;
// Earlier versions of C# require explicit casting.
//Excel._Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet;
// Establish column headings in cells A1 and B1.
workSheet.Cells[1, "A"] = "ID Number";
workSheet.Cells[1, "B"] = "Current Balance";
var row = 1;
foreach (var acct in accounts)
{
row++;
workSheet.Cells[row, "A"] = acct.ID;
workSheet.Cells[row, "B"] = acct.Balance;
}
workSheet.Columns[1].AutoFit();
workSheet.Columns[2].AutoFit();
// Call to AutoFormat in Visual C# 2010. This statement replaces the
// two calls to AutoFit.
workSheet.Range["A1", "B3"].AutoFormat(
Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
// Put the spreadsheet contents on the clipboard. The Copy method has one
// optional parameter for specifying a destination. Because no argument
// is sent, the destination is the Clipboard.
workSheet.Range["A1:B3"].Copy();
}
static void CreateIconInWordDoc()
{
var wordApp = new Word.Application();
wordApp.Visible = true;
// The Add method has four reference parameters, all of which are
// optional. Visual C# 2010 allows you to omit arguments for them if
// the default values are what you want.
wordApp.Documents.Add();
// PasteSpecial has seven reference parameters, all of which are
// optional. This example uses named arguments to specify values
// for two of the parameters. Although these are reference
// parameters, you do not need to use the ref keyword, or to create
// variables to send in as arguments. You can send the values directly.
wordApp.Selection.PasteSpecial(Link: true, DisplayAsIcon: true);
}
}
public class Account
{
public int ID { get; set; }
public double Balance { get; set; }
}
}
请参见
任务
如何:在 Office 编程中使用命名参数和可选参数(C# 编程指南)