演练:更改服务器上的工作簿中的缓存数据

此演练演示如何通过使用 ServerDocument 类在不启动 Excel 的情况下修改 Microsoft Office Excel 工作簿中缓存的数据集。 此演练提供了有关使用如何:更改服务器上的工作簿中的缓存数据中提供的代码示例的分步说明。

**适用于:**本主题中的信息适用于 Excel 2007 和 Excel 2010 的文档级项目。有关更多信息,请参见按 Office 应用程序和项目类型提供的功能

本演练阐释了以下任务:

  • 定义一个数据集,其中包含 AdventureWorksLT 数据库中的数据。

  • 在 Excel 工作簿项目和控制台应用程序项目中创建此数据集的实例。

  • 创建一个绑定到工作簿中的此数据集的 ListObject,并在打开此工作簿时用数据填充此 ListObject

  • 将工作簿中的此数据集添加到数据缓存中。

  • 在不启动 Excel 的情况下,通过在控制台应用程序中运行代码来修改缓存的数据集中的一列数据。

尽管此演练假设您是在开发计算机上运行代码,但此演练演示的代码可以在未安装 Excel 的服务器上使用。

提示

以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 您安装的 Visual Studio 版本以及使用的设置决定了这些元素。 有关更多信息,请参见 使用设置

系统必备

您需要以下组件来完成本演练:

-

Visual Studio 2010 的一个版本,其中包含 Microsoft Office 开发工具。有关更多信息,请参见[将计算机配置为开发 Office 解决方案](bb398242\(v=vs.100\).md)。

创建定义数据集的类库项目

若要在 Excel 工作簿项目和控制台应用程序中使用同一数据集,您必须在这两个项目都引用的一个单独程序集中定义此数据集。 对于此演练,请在类库项目中定义数据集。

创建类库项目

  1. 启动 Visual Studio。

  2. 在**“文件”菜单上指向“新建”,再单击“项目”**。

  3. 在“模板”窗格中,展开**“Visual C#”“Visual Basic”,然后单击“窗口”**。

  4. 在项目模板列表中,选择**“类库”**。

  5. 在**“名称”**框中键入 AdventureWorksDataSet。

  6. 单击**“浏览”,导航至 %UserProfile%\My Documents(对于 Windows XP 及更低版本)或 %UserProfile%\Documents(对于 Windows Vista)文件夹,然后单击“选择文件夹”**。

  7. 在**“新建项目”对话框中,确保“创建解决方案的目录”**复选框未选中。

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

    Visual Studio 会将**“AdventureWorksDataSet”项目添加到“解决方案资源管理器”中,并打开“Class1.cs”“Class1.vb”**代码文件。

  9. 在**“解决方案资源管理器”中,右击“Class1.cs”“Class1.vb”,然后单击“删除”**。 此演练不需要此文件。

在类库项目中定义数据集

定义一个类型化数据集,其中包含 SQL Server 2005 附带的 AdventureWorksLT 数据库中的数据。 在此演练后面的部分中,您将从一个 Excel 工作簿项目和一个控制台应用程序项目中引用此数据集。

此数据集是一个类型化数据集,表示 AdventureWorksLT 数据库的 Product 表中的数据。 有关类型化的数据集的更多信息,请参见 在 Visual Studio 中使用数据集

在类库项目中定义类型化数据集

  1. 在**“解决方案资源管理器”中,单击“AdventureWorksDataSet”**项目。

  2. 在**“数据”菜单上,单击“添加新数据源”**。

    **“数据源配置向导”**打开。

  3. 单击**“数据库”,然后单击“下一步”**。

  4. 如果已与 AdventureWorksLT 数据库建立连接,请选择此连接,然后单击**“下一步”**。

    否则,请单击**“新建连接”,然后使用“添加连接”**对话框创建新连接。 有关更多信息,请参见如何:连接到数据库中的数据

  5. 在**“将连接字符串保存到应用程序配置文件中”页中,单击“下一步”**。

  6. 在**“选择数据库对象”页中,展开“表”,然后选择“Product (SalesLT)”**。

  7. 单击**“完成”**。

    AdventureWorksLTDataSet.xsd 文件即会添加到 AdventureWorksDataSet 项目中。 此文件定义以下项:

    • 一个名为 AdventureWorksLTDataSet 的类型化数据集。 此数据集表示 AdventureWorksLT 数据库中的 Product 表的内容。

    • 一个名为 ProductTableAdapter 的 TableAdapter。 此 TableAdapter 可用来在 AdventureWorksLTDataSet 中读取和写入数据。 有关更多信息,请参见 TableAdapter 概述

    在此演练后面的部分中,这两个对象都会用到。

  8. 在**“解决方案资源管理器”中右击“AdventureWorksDataSet”,再单击“生成”**。

    验证项目已生成且未发生错误。

创建 Excel 工作簿项目

为数据的接口创建一个 Excel 工作簿项目。 在此演练后面的部分中,您将创建一个显示这些数据的 ListObject,并且您将向此工作簿中的数据缓存添加此数据集的实例。

创建 Excel 工作簿项目

  1. 在**“解决方案资源管理器”中右击“AdventureWorksDataSet”解决方案,指向“添加”,再单击“新建项目”**。

  2. 在“模板”窗格中,展开**“Visual C#”“Visual Basic”,然后展开“Office”**。

  3. 在展开的**“Office”节点下,选择“2007”“2010”**节点。

  4. 在项目模板列表中,选择“Excel 工作簿”项目。

  5. 在**“名称”**框中键入 AdventureWorksReport。 请勿修改位置。

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

    会打开**“Visual Studio Tools for Office 项目向导”**。

  7. 确保已选择**“创建新文档”,然后单击“确定”**。

    Visual Studio 将在设计器中打开 AdventureWorksReport 工作簿,并将**“AdventureWorksReport”项目添加到“解决方案资源管理器”**。

在 Excel 工作簿项目中将此数据集添加到数据源

必须先在 Excel 工作簿项目中将此数据集添加到数据源,然后才能在 Excel 工作簿中显示此数据集。

在 Excel 工作簿项目中将此数据集添加到数据源

  1. 在**“解决方案资源管理器”中,双击“AdventureWorksReport”项目下的“Sheet1.cs”“Sheet1.vb”**。

    工作簿即会在设计器中打开。

  2. 在**“数据”菜单上,单击“添加新数据源”**。

    **“数据源配置向导”**打开。

  3. 单击**“对象”,然后单击“下一步”**。

  4. 在**“选择希望绑定到的对象”页中,单击“添加引用”**。

  5. 在**“项目”选项卡上,单击“AdventureWorksDataSet”,再单击“确定”**。

  6. 在**“AdventureWorksDataSet”程序集的“AdventureWorksDataSet”命名空间下,单击“AdventureWorksLTDataSet”,然后单击“完成”**。

    **“数据源”窗口即会打开,并且“AdventureWorksLTDataSet”**会添加到数据源列表中。

创建绑定到此数据集的实例的 ListObject

若要在工作簿中显示此数据集,请创建一个绑定到此数据集的实例的 ListObject。 有关将控件绑定到数据的更多信息,请参见将数据绑定到 Office 解决方案中的控件

创建绑定到此数据集的实例的 ListObject

  1. 在**“数据源”窗口中,展开“AdventureWorksDataSet”下的“AdventureWorksLTDataSet”**节点。

  2. 选择**“Product”节点,单击出现的下拉箭头,然后在下拉列表中选择“ListObject”**。

    如果未出现下拉箭头,请确认是否在设计器中打开了工作簿。

  3. 将**“Product”**表拖到 A1 单元格中。

    这样就在工作簿中创建了一个名为 productListObject 的 ListObject 控件,此控件的起始单元格为 A1。 同时,会将一个名为 adventureWorksLTDataSet 的数据集对象和一个名为 productBindingSource 的 BindingSource 添加到项目中。 此 ListObject 绑定到 BindingSource,而后者又绑定到此数据集对象。

将此数据集添加到数据缓存中

若要使 Excel 工作簿项目外部的代码能够访问工作簿中的此数据集,必须将此数据集添加到数据缓存中。 有关数据缓存的更多信息,请参见文档级自定义项中的缓存数据缓存数据

将此数据集添加到数据缓存中

  1. 在设计器中,单击**“adventureWorksLTDataSet”**。

  2. 在**“属性”窗口中,将“Modifiers”属性设置为“Public”**。

  3. 将**“CacheInDocument”属性设置为“True”**。

初始化工作簿中的此数据集

必须先用数据填充缓存的数据集,然后才能通过使用控制台应用程序从缓存的数据集中检索数据。

初始化工作簿中的此数据集

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

  2. 用下面的代码替换 Sheet1_Startup 事件处理程序。 如果缓存的数据集当前是空的,则此代码使用在 AdventureWorksDataSet 项目中定义的 ProductTableAdapter 类的一个实例在此缓存的数据集中填充数据。

    Private ProductTableAdapter As New  _
        AdventureWorksDataSet.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter()
    
    Private Sub Sheet1_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup
        If Me.NeedsFill("AdventureWorksLTDataSet") Then
            Me.ProductTableAdapter.Fill(Me.AdventureWorksLTDataSet.Product)
        End If
    End Sub
    
    private AdventureWorksDataSet.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter productTableAdapter =
        new AdventureWorksDataSet.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter();
    
    private void Sheet1_Startup(object sender, System.EventArgs e)
    {
        if (this.NeedsFill("adventureWorksLTDataSet"))
        {
            this.productTableAdapter.Fill(this.adventureWorksLTDataSet.Product);
        }
    }
    

检查点

生成并运行此 Excel 工作簿项目,确保它在编译和运行时不出错。 此操作还会填充缓存的数据集并将数据保存在工作簿中。

生成并运行此项目

  1. 在**“解决方案资源管理器”中右击“AdventureWorksReport”项目,选择“调试”,然后单击“启动新实例”**。

    即会生成此项目,并在 Excel 中打开此工作簿。 确认以下事项:

    • ListObject 中填充了数据。

    • ListObject 第一行的**“ListPrice”列中的值为 1431.5。 在此演练后面的部分中,您将使用控制台应用程序来修改“ListPrice”**列中的值。

  2. 保存工作簿。 请勿修改工作簿的文件名和位置。

  3. 关闭 Excel。

创建控制台应用程序项目

创建一个控制台应用程序项目,用以修改工作簿中缓存的数据集中的数据。

创建控制台应用程序项目

  1. 在**“解决方案资源管理器”中右击“AdventureWorksDataSet”解决方案,指向“添加”,再单击“新建项目”**。

  2. 在**“项目类型”窗格中,展开“Visual C#”“Visual Basic”,然后单击“Windows”**。

  3. 在**“模板”窗格中选择“控制台应用程序”**。

  4. 在**“名称”**框中键入 DataWriter。 请勿修改位置。

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

    Visual Studio 即会将**“DataWriter”项目添加到“解决方案资源管理器”中,并打开“Program.cs”“Module1.vb”**代码文件。

通过使用控制台应用程序更改缓存的数据集中的数据

在控制台应用程序中使用 ServerDocument 类将数据读入本地 AdventureWorksLTDataSet 对象,修改此数据,然后将其存回缓存的数据集中。

更改缓存的数据集中的数据

  1. 在**“解决方案资源管理器”中右击“DataWriter”项目,然后单击“添加引用”**。

  2. 在**“.NET”**选项卡中,选择 Microsoft.VisualStudio.Tools.Applications.ServerDocument(如果 DataWriter 项目以 .NET Framework 4 为目标)或 Microsoft.VisualStudio.Tools.Applications.ServerDocument.v10.0(如果 DataWriter 项目以 .NET Framework 3.5 为目标)。

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

  4. 在**“解决方案资源管理器”中右击“DataWriter”项目,然后单击“添加引用”**。

  5. 在**“项目”选项卡上,选择“AdventureWorksDataSet”,然后单击“确定”**。

  6. 在代码编辑器中打开 Program.cs 或 Module1.vb 文件。

  7. 将下面的 using(对于 C#)或 Imports(对于 Visual Basic)语句添加到相应代码文件的顶部。

    Imports Microsoft.VisualStudio.Tools.Applications
    
    using Microsoft.VisualStudio.Tools.Applications;
    
  8. 将以下代码添加到 Main 方法中。 此代码声明了以下对象:

    • 在 AdventureWorksDataSet 项目中定义的 AdventureWorksLTDataSet 类型的一个实例。

    • AdventureWorksReport 项目的生成文件夹中 AdventureWorksReport 工作簿的路径。

    • 一个用于访问工作簿中数据缓存的 ServerDocument 对象。

      提示

      下面的代码假定您使用的是文件扩展名为 .xlsx 的工作簿。 如果您项目中的工作簿具有不同的文件扩展名,请在必要时修改路径。

    Dim productDataSet As New AdventureWorksDataSet.AdventureWorksLTDataSet()
    Dim workbookPath As String = System.Environment.GetFolderPath( _
        Environment.SpecialFolder.MyDocuments) & _
        "\AdventureWorksReport\bin\Debug\AdventureWorksReport.xlsx"
    Dim serverDocument1 As ServerDocument = Nothing
    
    AdventureWorksDataSet.AdventureWorksLTDataSet productDataSet =
        new AdventureWorksDataSet.AdventureWorksLTDataSet();
    string workbookPath = System.Environment.GetFolderPath(
        Environment.SpecialFolder.MyDocuments) +
        @"\AdventureWorksReport\bin\Debug\AdventureWorksReport.xlsx";
    ServerDocument serverDocument1 = null;
    
  9. 将下面的代码添加到 Main 方法中,接在上一步添加的代码后面。 这段代码执行下列任务:

    • 使用 ServerDocument 类的 CachedData 属性访问工作簿中缓存的数据集。

    • 将缓存的数据集中的数据读入本地数据集。

    • 更改数据集的 Product 表中每种产品的 ListPrice 值。

    • 将所做的更改保存到工作簿中缓存的数据集中。

    Try
        serverDocument1 = New ServerDocument(workbookPath)
        Dim dataHostItem1 As CachedDataHostItem = _
            serverDocument1.CachedData.HostItems("AdventureWorksReport.Sheet1")
        Dim dataItem1 As CachedDataItem = dataHostItem1.CachedData("AdventureWorksLTDataSet")
    
        If dataItem1 IsNot Nothing Then
            Console.WriteLine("Before reading data from the cache dataset, the local dataset has " & _
                "{0} rows.", productDataSet.Product.Rows.Count.ToString())
    
            ' Read the cached data from the worksheet dataset into the local dataset.
            Dim schemaReader As New System.IO.StringReader(dataItem1.Schema)
            Dim xmlReader As New System.IO.StringReader(dataItem1.Xml)
            productDataSet.ReadXmlSchema(schemaReader)
            productDataSet.ReadXml(xmlReader)
    
            Console.WriteLine("After reading data from the cache dataset, the local dataset has " & _
                "{0} rows.", productDataSet.Product.Rows.Count.ToString())
    
            ' Modify the prices of each product in the local dataset.
            Dim row As AdventureWorksDataSet.AdventureWorksLTDataSet.ProductRow
            For Each row In productDataSet.Product.Rows
                If row.ProductCategoryID < 20 Then
                    row.ListPrice = row.ListPrice + row.ListPrice * 0.1
                Else
                    row.ListPrice = row.ListPrice - row.ListPrice * 0.1
                End If
            Next row
    
            ' Write the modified local dataset to the worksheet dataset using the DiffGram format.
            Dim stringIn As New System.Text.StringBuilder()
            Dim stringOut As New System.IO.StringWriter(stringIn)
            productDataSet.WriteXml(stringOut, System.Data.XmlWriteMode.DiffGram)
            dataItem1.Xml = stringIn.ToString()
    
            serverDocument1.Save()
            Console.WriteLine("The product prices have been modified.")
        Else
            Console.WriteLine("The data object is not found in the data cache.")
        End If
    Catch ex As System.IO.FileNotFoundException
        Console.WriteLine("The specified workbook does not exist.")
    Catch ex As System.Xml.XmlException
        Console.WriteLine("The data object has invalid XML information.")
    Finally
        If Not (serverDocument1 Is Nothing) Then
            serverDocument1.Close()
        End If
        Console.WriteLine(vbLf & vbLf & "Press Enter to close the application.")
        Console.ReadLine()
    End Try
    
    try
    {
        serverDocument1 = new ServerDocument(workbookPath);
        CachedDataHostItem dataHostItem1 =
            serverDocument1.CachedData.HostItems["AdventureWorksReport.Sheet1"];
        CachedDataItem dataItem1 = dataHostItem1.CachedData["adventureWorksLTDataSet"];
    
        if (dataItem1 != null)
        {
            Console.WriteLine("Before reading data from the cache dataset, the local dataset has " +
                "{0} rows.", productDataSet.Product.Rows.Count.ToString());
    
            // Read the cached data from the worksheet dataset into the local dataset.
            System.IO.StringReader schemaReader = new System.IO.StringReader(dataItem1.Schema);
            System.IO.StringReader xmlReader = new System.IO.StringReader(dataItem1.Xml);
            productDataSet.ReadXmlSchema(schemaReader);
            productDataSet.ReadXml(xmlReader);
    
            Console.WriteLine("After reading data from the cache dataset, the local dataset has " +
                "{0} rows.", productDataSet.Product.Rows.Count.ToString());
    
            // Modify the prices of each product in the local dataset.
            foreach (AdventureWorksDataSet.AdventureWorksLTDataSet.ProductRow row in 
                     productDataSet.Product.Rows)
            {
                if (row.ProductCategoryID < 20)
                {
                    row.ListPrice = row.ListPrice + (row.ListPrice * (Decimal).10);
                }
                else
                {
                    row.ListPrice = row.ListPrice - (row.ListPrice * (Decimal).10);
                }
            }
    
            // Write the modified local dataset to the worksheet dataset using the DiffGram format.
            System.Text.StringBuilder stringIn = new System.Text.StringBuilder();
            System.IO.StringWriter stringOut = new System.IO.StringWriter(stringIn);
            productDataSet.WriteXml(stringOut, System.Data.XmlWriteMode.DiffGram);
            dataItem1.Xml = stringIn.ToString();
    
            serverDocument1.Save();
            Console.WriteLine("The product prices have been modified.");
        }
        else
        {
            Console.WriteLine("The data object is not found in the data cache.");
        }
    }
    catch (System.IO.FileNotFoundException)
    {
        Console.WriteLine("The specified workbook does not exist.");
    }
    catch (System.Xml.XmlException)
    {
        Console.WriteLine("The data object has invalid XML information.");
    }
    finally
    {
        if (serverDocument1 != null)
        {
            serverDocument1.Close();
        }
    
        Console.WriteLine("\n\nPress Enter to close the application.");
        Console.ReadLine();
    }
    
  10. 在**“解决方案资源管理器”中右击“DataWriter”项目,指向“调试”,然后单击“启动新实例”**。

    控制台应用程序在将缓存的数据集读入本地数据集,修改本地数据集中的产品价格以及将新值保存到缓存的数据集中时均会显示消息。 按 Enter 可关闭应用程序。

测试此工作簿

打开此工作簿时,ListObject 现在会显示您对缓存的数据集中 ListPrice 列的数据所做的更改。

测试此工作簿

  1. 如果 AdventureWorksReport 工作簿在 Visual Studio 设计器中仍处于打开状态,请关闭它。

  2. 打开位于 AdventureWorksReport 项目的生成文件夹中的 AdventureWorksReport 工作簿。 默认情况下,生成文件夹位于以下位置之一:

    • %UserProfile%\My Documents\AdventureWorksReport\bin\Debug(对于 Windows XP 及更低版本)

    • %UserProfile%\Documents\AdventureWorksReport\bin\Debug(对于 Windows Vista)

  3. 验证 ListObject 第一行的**“ListPrice”**列中的值现在是否为 1574.65。

  4. 关闭工作簿。

后续步骤

您可以从以下主题中了解到有关使用缓存的数据的更多内容:

请参见

任务

如何:向服务器上的工作簿中插入数据

如何:从服务器上的工作簿中检索缓存的数据

演练:将数据插入到服务器上的工作簿中

如何:将数据插入文档而不写入磁盘

概念

连接到 Windows 窗体应用程序中的数据