將資料存放區中的專案連接到SQL Server資料庫
Word 可讓您建立資料驅動解決方案來產生檔。 您可以建立包含自訂 XML 元件的範本檔,並使用內容控制項使用 XML 對應系結至自訂 XML 資料。 雖然此內容中使用「 範本 」一詞,但本檔不是 Word 範本,但會共用 Word 範本檔的一些特性。 然後,您可以建立受控 Web 型應用程式,以根據範本檔建置新檔。 受控 Web 應用程式會開啟範本檔、從 Microsoft SQL Server 資料庫擷取資料以建置新的自訂 XML 元件、將範本檔的自訂 XML 元件取代為新的元件,並將範本檔儲存為新的 Word 檔。
本逐步解說說明如何建置新的範本檔,以及如何建立伺服器端應用程式來產生檔,以顯示儲存在 Microsoft SQL Server 資料庫中的資料。 若要建置此應用程式,您將完成下列兩項工作:
建立 Word 範本檔。
建立伺服器端 Web 型應用程式,從 Microsoft SQL Server 資料庫提取資料,並根據 Word 範本檔產生新檔。
此範例中使用的程式設計物件如下所示:
Microsoft Office 系統核心物件模型中的CustomXMLPart ()
Microsoft Office 系統核心物件模型中的CustomXMLParts ()
如需內容控制項的詳細資訊,請參閱使用內容控制項。
商務案例:建立客戶檔產生器
若要建立 Word 檔產生器,將資料存放區中的專案連線至 Microsoft SQL Server 資料庫,您必須先建置範本客戶信件產生器檔,其中包含對應至 XML 檔案的內容控制項。 接下來,您會建立檔產生 Web 型應用程式,讓您選取公司名稱來產生自訂檔。 應用程式會從 Microsoft SQL Server 資料庫擷取客戶資料,並使用客戶信件產生器來建置新檔,以根據使用者選擇來顯示客戶資料。 檔會顯示下列資訊:
- 公司名稱
- 連絡人名稱
- 連絡人標題
- 電話號碼
使用下列一般步驟來建立 Word 檔產生器。
若要建立自訂檔產生器,並定義每個內容控制項的 XML 對應
開啟 Word 並建立空白檔。
將純文字內容控制項新增至檔,以系結至資料存放區中的節點。
內容控制項是預先定義的內容片段。 Word 提供數種內容控制項。 這包括文字區塊、核取方塊、下拉式功能表、下拉式方塊、行事曆控制項和圖片。 您可以將這些內容控制項對應至 XML 檔案中的元素。 您可以使用 XPath 運算式,以程式設計方式將 XML 檔案中的內容對應至內容控制項。 這可讓您撰寫簡單而簡短的應用程式來操作和修改檔中的資料。
若要新增內容控制項,請在 [ 開發人員 ] 索引標籤的 [ 控制項 ] 群組中,按一下 [純文字內容控制項]。
將四個純文字內容控制項新增至檔。 新增每個控制項之後,請為每個控制項指派標題:按一下控制項;在 [ 控制項] 群組中,按一下 [ 屬性];在 [ 標題] 方塊中,輸入控制項的標題,如下列清單所示;然後按一下 [ 確定]。
- 公司名稱
- 連絡人名稱
- 連絡人標題
- 電話號碼
您也可以使用下列 Visual Basic for Applications (VBA) 程式碼,將內容控制項新增至檔。 按 ALT+F11 開啟 Visual Basic 編輯器,將程式碼貼到程式碼視窗中,按一下程式中的任何位置,然後按 F5 執行程式碼,並將四個內容控制項新增至您的範本檔。
Sub AddContentControls() Selection.Range.ContentControls.Add (wdContentControlText) Selection.ParentContentControl.Title = "Company Name" Selection.ParentContentControl.Tag = "Company Name" Selection.MoveDown Unit:=wdLine, Count:=1 Selection.TypeParagraph Selection.Range.ContentControls.Add (wdContentControlText) Selection.ParentContentControl.Title = "Contact Name" Selection.ParentContentControl.Tag = "Contact Name" Selection.MoveDown Unit:=wdLine, Count:=1 Selection.TypeParagraph Selection.Range.ContentControls.Add (wdContentControlText) Selection.ParentContentControl.Title = "Contact Title" Selection.ParentContentControl.Tag = "Contact Title" Selection.MoveDown Unit:=wdLine, Count:=1 Selection.TypeParagraph Selection.Range.ContentControls.Add (wdContentControlText) Selection.ParentContentControl.Title = "Phone Number" Selection.ParentContentControl.Tag = "Phone Number" Selection.MoveDown Unit:=wdLine, Count:=1 Selection.TypeParagraph End Sub
在內容控制項上設定 XML 對應。
XML 對應是 Word 的一項功能,可讓您建立檔與 XML 檔案之間的連結。 如此一來,會建立文件格式設定與自訂 XML 資料之間的真正資料/檢視區隔。
若要載入自訂 XML 元件,您必須先使用CustomXMLParts集合的Add方法,將新的資料存放區新增至Document物件。 這會將新的空白資料存放區附加至檔。 因為它是空的,所以您還無法使用它。 接下來,您必須藉由呼叫CustomXMLPart物件的 Load 方法,以使用 XML 檔案的有效路徑做為參數,將自訂 XML 元件從 XML 檔案載入資料存放區。
儲存檔,並將它命名為 CustomerLetterGenerator.docm。
注意事項
因為它包含 VBA 程式碼,所以您必須將檔儲存為啟用巨集檔檔案 (.docm) .|
下列程式說明如何將內容控制項對應至範例自訂 XML 檔案。 您可以建立有效的自訂 XML 檔案、儲存檔案,然後使用 Visual Basic for Applications (VBA) 程式碼,將包含您要對應之資訊的資料存放區新增至範本。
在內容控制項上設定 XML 對應
建立文字檔,並將其儲存為CustomerData.xml。
將下列 XML 程式碼複製到文字檔中,然後儲存檔案。
<?xml version="1.0"?> <Customer> <CompanyName>Alfreds Futterkiste</CompanyName> <ContactName>Maria Anders</ContactName> <ContactTitle>Sales Representative</ContactTitle> <Phone>030-0074321</Phone> </Customer>
按 ALT+F11 開啟 Visual Basic 編輯器,將下列程式碼貼到程式碼視窗中,按一下程式中的任何位置,然後按 F5 執行程式碼並將 XML 檔案附加至您的範本檔,使其成為可用的資料存放區專案。
Public Sub LoadXML() ' Load CustomerData.xml file ActiveDocument.CustomXMLParts.Add ActiveDocument.CustomXMLParts(ActiveDocument.CustomXMLParts.Count).Load ("C:\CustomerData.xml") End Sub
注意事項
至少有三個預設的自訂 XML 元件一律會使用檔建立:'Cover pages'、'Doc properties' 和 'App properties'。 此外,您可以根據數個因素,在指定的電腦上建立各種其他自訂 XML 元件。 這些包括安裝哪些附加元件、與 SharePoint 的連線等等。 在上一個程式碼的CustomXMLParts集合上呼叫Add方法會新增載入 XML 檔案的其他 XML 元件。 在該部分上,會在下一行程式碼中呼叫 Load 方法。
若要判斷要載入 XML 檔案之元件的索引編號,必須將自訂 XML 元件的計數傳遞至 Load 方法。
ActiveDocument.CustomXMLParts(ActiveDocument.CustomXMLParts.Count).Load ("C:\CustomerData.xml")
在參考新增資料存放區中節點的內容控制項上設定 XML 對應。
若要建立 XML 對應,請使用 XPath 運算式,指向您想要對應內容控制項之自訂 XML 資料元件中的節點。 將資料存放區新增至檔 (,且資料存放區指向有效的 XML 檔案) 之後,您就可以將其其中一個節點對應至內容控制項。
若要這樣做,請使用ContentControl物件 (的XMLMapping 屬性,使用 XMLMapping物件的SetMapping方法,將包含有效XPath的String傳遞至ContentControl物件) 。 開啟 Visual Basic 編輯器並執行下列 VBA 程式碼,將內容控制項系結至資料存放區中的專案。
Public Sub MapXML() Dim strXPath1 As String strXPath1 = "/Customer/CompanyName" ActiveDocument.ContentControls(1).XMLMapping.SetMapping strXPath1 Dim strXPath2 As String strXPath2 = "/Customer/ContactName" ActiveDocument.ContentControls(2).XMLMapping.SetMapping strXPath2 Dim strXPath3 As String strXPath3 = "/Customer/ContactTitle" ActiveDocument.ContentControls(3).XMLMapping.SetMapping strXPath3 Dim strXPath4 As String strXPath4 = "/Customer/Phone" ActiveDocument.ContentControls(4).XMLMapping.SetMapping strXPath4
建立從SQL Server資料庫提取資料並產生新檔的Server-Side應用程式
您可以建立 Web 應用程式,讓使用者選取公司名稱並產生自訂信件。 Web 應用程式會從SQL Server資料庫擷取客戶資料、開啟客戶信件範本檔,並建立新檔,根據使用者選擇來顯示客戶資料。 此 Web 應用程式不需要使用 Word 或 VBA。 使用您最愛的 Managed 程式碼 (Visual Basic .NET 或 C#) 語言來建置此應用程式。
注意事項
此處顯示的 Web 應用程式會從 Northwind.mdf 資料庫取得其資料。 此資料庫已與舊版的 SQL Server 和 Office 一起安裝。 如果您的電腦上沒有 Northwind 資料庫,您可以從下列網站下載: Northwind 資料庫
建立從SQL Server資料庫提取資料並產生新檔的伺服器端應用程式
開啟 Visual Studio 或 Visual Web 開發人員。
建立 ASP.NET Web 應用程式,並將它命名為 SqlServerSample。
在下列步驟中,您會將 ASP.NET Web 應用程式連線到 SQL Server 資料庫。
將下列連接字串新增至 Visual Studio 專案中的 Web.config 檔案。
<connectionStrings> <add name="NorthwindConnectionString" connectionString="data source=(local);database=Northwind; integrated security=SSPI;persist security info=false;" providerName="System.Data.SqlClient" /> </connectionStrings>
在 Visual Studio 專案中,將 CustomerLetterGenerator.docm 檔新增至 App_Data 資料夾:以滑鼠右鍵按一下 [App_Data],指向 [ 新增],按一下 [ 現有專案],流覽至您儲存檔的位置,選取該檔,然後按一下 [ 新增]。
將參考新增至專案WindowsBase.dll:以滑鼠右鍵按一下 [ 參考],按一下 [ 新增參考],按一下 [.NET] 索引標籤,選取 [WindowsBase],然後按一下 [ 確定]。
在Web.config檔案中設定元件,如下所示。
<compilation debug="false"> <assemblies> <add assembly="WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> </assemblies> </compilation>
將 Web 表單新增至您的專案:在 [ 專案 ] 功能表上,按一下 [ 新增專案];在 [ 已安裝的範本] 底下,按一下 [ Web];選取 [Web Form],然後按一下 [ 新增]。
在方案總管中,以滑鼠右鍵按一下 [屬性],然後按一下 [開啟]。
在 [Web] 索引 標籤的 [ 啟動動作] 下,選取 [ 特定頁面],按一下瀏覽按鈕,然後流覽至 網頁 WebForm1.aspx。
將下列程式碼新增至 WebForm1.aspx 檔案,覆寫以開頭和結尾
<html>
標記系結的檔案部分。<html xmlns="https://www.w3.org/1999/xhtml"> <head runat="server"> <title>Data-Driven Document Generation - SQL Server Sample</title> </head> <body> <form id="form1" runat="server"> <div> <h1>Customer Letter Generator</h1> <table border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 12%"> <tr> <td> Choose a customer:</td> <td> <asp:DropDownList ID="ddlCustomer" runat="server" AutoPostBack="True" DataSourceID="CustomerData" DataTextField="CompanyName" DataValueField="CustomerID" Width="301px"> </asp:DropDownList> <asp:SqlDataSource ID="CustomerData" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT [CustomerID], [CompanyName] FROM [Customers]" ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>"> </asp:SqlDataSource> </td> </tr> </table> </div> <br /> <asp:Button ID="Button1" runat="server" OnClick="SubmitBtn_Click" Text="Create Letter" Width="123px" /> </form> </body> </html>
根據您使用的程式碼語言,將下列 Visual Basic .NET 或 C# 程式碼新增至專案中適當的 WebForm1.aspx 程式碼後置頁面。
範例程式碼:Visual Basic .NET
下列 Visual Basic .NET 範例示範如何系結至SQL Server資料庫,以根據客戶選取專案擷取資料,並根據 CustomerLetterGenerator.docm 範本檔建立新檔。 將下列程式碼新增至 WebForm1.aspx.vb 檔案,覆寫檔案中的現有程式碼。
Imports System.Collections.Generic
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports System.IO.Packaging
Imports System.Linq
Imports System.Xml
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Private Const strRelRoot As String = "https://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Private Sub CreateDocument()
' Get the template document file and create a stream from it
Const DocumentFile As String = "~/App_Data/CustomerLetterGenerator.docm"
' Read the file into memory
Dim buffer() As Byte = File.ReadAllBytes(Server.MapPath(DocumentFile))
Dim memoryStream As MemoryStream = New MemoryStream(buffer, True)
buffer = Nothing
' Open the document in the stream and replace the custom XML part
Dim pkgFile As Package = Package.Open(memoryStream, FileMode.Open, FileAccess.ReadWrite)
Dim pkgrcOfficeDocument As PackageRelationshipCollection = pkgFile.GetRelationshipsByType(strRelRoot)
For Each pkgr As PackageRelationship In pkgrcOfficeDocument
If (pkgr.SourceUri.OriginalString = "/") Then
' Get the root part
Dim pkgpRoot As PackagePart = pkgFile.GetPart(New Uri(("/" + pkgr.TargetUri.ToString), UriKind.Relative))
' Add a custom XML part to the package
Dim uriData As Uri = New Uri("/customXML/item1.xml", UriKind.Relative)
If pkgFile.PartExists(uriData) Then
' Delete part "/customXML/item1.xml" part
pkgFile.DeletePart(uriData)
End If
' Load the custom XML data
Dim pkgprtData As PackagePart = pkgFile.CreatePart(uriData, "application/xml")
GetDataFromSQLServer(pkgprtData.GetStream, ddlCustomer.SelectedValue)
End If
Next
' Close the file
pkgFile.Close()
' Return the result
Response.ClearContent()
Response.ClearHeaders()
Response.AddHeader("content-disposition", "attachment; filename=document.docx")
Response.ContentEncoding = System.Text.Encoding.UTF8
memoryStream.WriteTo(Response.OutputStream)
memoryStream.Close()
Response.End()
End Sub
Private Sub GetDataFromSQLServer(ByVal stream As Stream, ByVal customerID As String)
'Connect to a SQL Server database and get data
Dim source As String = ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString
Const SqlStatement As String = "SELECT CompanyName, ContactName, ContactTitle, Phone FROM Customers WHERE CustomerID=@customerID"
Dim conn As SqlConnection = New SqlConnection(source)
conn.Open()
Dim cmd As SqlCommand = New SqlCommand(SqlStatement, conn)
cmd.Parameters.AddWithValue("@customerID", customerID)
Dim dr As SqlDataReader = cmd.ExecuteReader
If dr.Read Then
Dim writer As XmlWriter = XmlWriter.Create(stream)
writer.WriteStartElement("Customer")
writer.WriteElementString("CompanyName", CType(dr("CompanyName"), String))
writer.WriteElementString("ContactName", CType(dr("ContactName"), String))
writer.WriteElementString("ContactTitle", CType(dr("ContactTitle"), String))
writer.WriteElementString("Phone", CType(dr("Phone"), String))
writer.WriteEndElement()
writer.Close()
End If
dr.Close()
conn.Close()
End Sub
Protected Sub SubmitBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
CreateDocument()
End Sub
End Class
範例程式碼:C#
下列 C# 範例示範如何系結至SQL Server資料庫,以根據客戶選取專案擷取資料,並根據 CustomerLetterGenerator.docm 範本檔建立新檔。 將下列程式碼新增至 WebForm1.Aspx.cs 檔案,並複製現有的程式碼。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Xml;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SQLServerSample
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
private const string strRelRoot = "https://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
private void CreateDocument()
{
// Get the template document file and create a stream from it
const string DocumentFile = @"~/App_Data/CustomerLetterGenerator.docm";
// Read the file into memory
byte[] buffer = File.ReadAllBytes(Server.MapPath(DocumentFile));
MemoryStream memoryStream = new MemoryStream(buffer, true);
buffer = null;
// Open the document in the stream and replace the custom XML part
Package pkgFile = Package.Open(memoryStream, FileMode.Open, FileAccess.ReadWrite);
PackageRelationshipCollection pkgrcOfficeDocument = pkgFile.GetRelationshipsByType(strRelRoot);
foreach (PackageRelationship pkgr in pkgrcOfficeDocument)
{
if (pkgr.SourceUri.OriginalString == "/")
{
// Get the root part
PackagePart pkgpRoot = pkgFile.GetPart(new Uri("/" + pkgr.TargetUri.ToString(), UriKind.Relative));
// Add a custom XML part to the package
Uri uriData = new Uri("/customXML/item1.xml", UriKind.Relative);
if (pkgFile.PartExists(uriData))
{
// Delete document "/customXML/item1.xml" part
pkgFile.DeletePart(uriData);
}
// Load the custom XML data
PackagePart pkgprtData = pkgFile.CreatePart(uriData, "application/xml");
GetDataFromSQLServer(pkgprtData.GetStream(), ddlCustomer.SelectedValue);
}
}
// Close the file
pkgFile.Close();
// Return the result
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("content-disposition", "attachment; filename=CustomLetter.docx");
Response.ContentEncoding = System.Text.Encoding.UTF8;
memoryStream.WriteTo(Response.OutputStream);
memoryStream.Close();
Response.End();
}
private void GetDataFromSQLServer(Stream stream, string customerID)
{
// Connect to a SQL Server database and get data
String source = System.Configuration.ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
const string SqlStatement =
"SELECT CompanyName, ContactName, ContactTitle, Phone FROM Customers WHERE CustomerID=@customerID";
using (SqlConnection conn = new SqlConnection(source))
{
conn.Open();
SqlCommand cmd = new SqlCommand(SqlStatement, conn);
cmd.Parameters.AddWithValue("@customerID", customerID);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
XmlWriter writer = XmlWriter.Create(stream);
writer.WriteStartElement("Customer");
writer.WriteElementString("CompanyName", (string)dr["CompanyName"]);
writer.WriteElementString("ContactName", (string)dr["ContactName"]);
writer.WriteElementString("ContactTitle", (string)dr["ContactTitle"]);
writer.WriteElementString("Phone", (string)dr["Phone"]);
writer.WriteEndElement();
writer.Close();
}
dr.Close();
conn.Close();
}
}
protected void SubmitBtn_Click(object sender, EventArgs e)
{
CreateDocument();
}
}
}
如需使用 ASP.NET 2.0 的詳細資訊,請參閱 https://www.asp.net/get-started/ 。
本文說明如何從SQL Server資料庫擷取資料,並將其插入您的範本檔中。 您也可以從其他資料來源擷取資料,例如 Access 和 Excel。 如需如何以程式設計方式連線到這些應用程式中資料的詳細資訊,請參閱 Access 和 Excel 開發人員檔。
支援和意見反應
有關於 Office VBA 或這份文件的問題或意見反應嗎? 如需取得支援服務並提供意見反應的相關指導,請參閱 Office VBA 支援與意見反應。