如何:通过使用 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 设置

创建一个新的控制台应用程序

  1. 启动 Visual Studio。

  2. 在**“文件”菜单上指向“新建”,再单击“项目”。 此时将出现“新建项目”**对话框。

  3. 在**“已安装的模板”窗格中,展开“Visual C#”,然后单击“Windows”**。

  4. 查看**“新建项目”对话框的顶部,确保选择“.NET Framework 4”**作为目标框架。

  5. 在**“模板”窗格中单击“控制台应用程序”**。

  6. 在**“名称”**字段中键入项目的名称。

  7. 单击**“确定”**。

    新项目出现在**“解决方案资源管理器”**中。

添加引用

  1. 在**“解决方案资源管理器”中,右击项目的名称,然后单击“添加引用”。 此时将出现“添加引用”**对话框。

  2. 在**“.NET”页上的“组件名称”列表中,选择“Microsoft.Office.Interop.Word”,然后按下 Ctrl 键并选择“Microsoft.Office.Interop.Excel”**。

  3. 单击**“确定”**。

添加必要的 using 指令

  1. 在**“解决方案资源管理器”中,右击“Program.cs”文件,然后单击“查看代码”**。

  2. 将以下 using 指令添加到代码文件的顶部。

    using Excel = Microsoft.Office.Interop.Excel;
    using Word = Microsoft.Office.Interop.Word;
    

创建银行帐户的列表

  1. 将以下类定义粘贴到**“Program.cs”**中 Program 类的下方。

    public class Account
    {
        public int ID { get; set; }
        public double Balance { get; set; }
    }
    
  2. 将以下代码添加到 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 的方法

  1. 将以下方法添加到 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;
    }
    
  2. 将下面的代码添加到 DisplayInExcel 的末尾。 该代码将值插入到工作表第一行的前两列中。

    // Establish column headings in cells A1 and B1.
    workSheet.Cells[1, "A"] = "ID Number";
    workSheet.Cells[1, "B"] = "Current Balance";
    
  3. 将下面的代码添加到 DisplayInExcel 的末尾。 foreach 循环将帐户列表中的信息放入工作表的连续几行的前两列。

    
    var row = 1;
    foreach (var acct in accounts)
    {
        row++;
        workSheet.Cells[row, "A"] = acct.ID;
        workSheet.Cells[row, "B"] = acct.Balance;
    }
    
  4. 将以下代码添加到 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。

运行项目

  1. 将以下行添加到 Main 的末尾。

    // Display the list in an Excel spreadsheet.
    DisplayInExcel(bankAccounts);
    
  2. 按 Ctrl+F5。

    将出现一个 Excel 工作表,其中包含两个帐户中的数据。

添加 Word 文档

  1. 为了演示 Visual C# 2010 用于增强 Office 编程的其他方法,下面的代码将打开 Word 应用程序,并创建一个链接到 Excel 工作表的图标。

    将此步骤后面提供的方法 CreateIconInWordDoc 粘贴到 Program 类中。 CreateIconInWordDoc 使用命名参数和可选参数,以降低对 AddPasteSpecial 的方法调用的复杂性。 这些调用结合了 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);
    }
    
  2. 将以下语句添加到 Main 的末尾。

    // Create a Word document that contains an icon that links to
    // the spreadsheet.
    CreateIconInWordDoc();
    
  3. 将以下语句添加到 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();
    
  4. 按 Ctrl+F5。

    此时将出现一个包含图标的 Word 文档。 双击该图标以显示工作表。

设置“嵌入互操作类型”属性

  1. 当您在运行时调用不需要主互操作程序集 (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();
    
  2. 若要更改默认行为并使用 PIA(而不是嵌入类型信息),请在**“解决方案资源管理器”中展开“引用”节点,然后选择“Microsoft.Office.Interop.Excel”“Microsoft.Office.Interop.Word”**。

  3. 如果看不到**“属性”**窗口,请按 F4

  4. 在属性列表中找到**“嵌入互操作类型”,并将它的值更改为“False”**。 与之相当,您可以在命令提示符处使用 /reference 编译器选项(而不是 /link)进行编译。

向表中添加其他格式设置

  1. 将对 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);
    
  2. 按 Ctrl+F5 查看结果。 其他格式列在 XlRangeAutoFormat 枚举中。

  3. 将步骤 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# 编程指南)

参考

dynamic(C# 参考)

Type.Missing

概念

命名实参和可选实参(C# 编程指南)

其他资源

使用类型 dynamic(C# 编程指南)