利用XSD設計Word版面, 再將資料(XML)搭配XSLT產出特定格式Word檔案
利用類別產生XSD檔
產出XSD檔的目的在於提供Word樣板設計之資料框架
在此使用微軟提供之XML Schema Definition Tool (Xsd.exe)工具產生XSD檔
1. 定義類別
// 書籍資料
public class Book
{
public string BookId { get; set; }
public string Name { get; set; }
public string price { get; set; }
}
// 訂單資料
public class Order
{
public string BuyerName { get; set; }
public List<Book> Books { get; set; }
public int TotalPrice { get; set; }
}
2. 使用Xsd.exe工具產生XSD檔案
工具位置: C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools
工具語法: xsd D:\Projects\WordGenerator.exe /language:CS /outputdir:d:\Projects\Xsd /type:Order
3. XSD內容如下
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Order" nillable="true" type="Order" />
<xs:complexType name="Order">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="BuyerName" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Books" type="ArrayOfBook" />
<xs:element minOccurs="1" maxOccurs="1" name="TotalPrice" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfBook">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Book" nillable="true" type="Book" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Book">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="BookId" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="price" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
4. 加上Namespace
targetNamespace=http://schemas.chris.com/WordGenerator/Order.xsd
xmlns=http://schemas.chris.com/WordGenerator/Order.xsd
利用XSD檔產生特定格式之Word檔
筆者是以Word 2010進行實作,相關實作畫面如下。另外,若使用Word 2013的朋友是無法透過此方法自行定義XML標記的,因為移除自訂 XML 標記是2009年12月22日美國法院的判決結果,購買或取得 Word 2013 授權的客戶會發現此軟體不含特定的自訂 XML 標記實作;所以請使用非Word2013版本來實作此步驟。
http://support.microsoft.com/kb/2761189/zh-tw
1. 加入開發人員工具列
2. 點選開發人員工具列之結構描述
3. 選擇剛產生之XSD檔案
4. 開始編輯畫面與資料關聯
目前希望呈現的樣式(黃色是隨資料異動部分)
點選結構後,產生XML結構工具
圈選Order對應部分後,點選Order
此時會出現選取範圍,就選擇僅套用至選取範圍即可
此時就完成了第一次的資料對應關係
然後依序處理其他部分,結果如下
此時若發現有錯誤發生
調整一下XML選項設定即可
調整完畢後儲存為DOC檔案供下次修改使用
利用特定格式之Word檔產生XSLT檔
1. 下載安裝 Word 2003: XML SDK
2. 將Word檔另存為XML
3. 利用WML2XSLT.exe 將 Order.xml 轉換成 Order.xslt
點選所需的namespace即可
組合資料產生Word檔
資料 + 顯示樣式
= 資料物件序列化(XML) + XSLT
= 產生具有資料及指定樣式Word檔
private void CreateWord()
{
string xsltLocation = @"D:\Order.xslt";
string outputPath = @"D:\Order.doc";
// Data
Order order = new Order()
{
BuyerName = "Chris Chen",
TotalPrice = 600,
Books = new List<Book>()
{
new Book(){BookId="B001", Name="Name01", price="100"},
new Book(){BookId="B002", Name="Name02", price="200"},
new Book(){BookId="B003", Name="Name03", price="300"},
}
};
// Data XML (一定要namespace)
string szInputXml = Serialize(order, "http://schemas.chris.com/WordGenerator/Order.xsd");
XmlTextReader xmlReader = new XmlTextReader(new System.IO.StringReader(szInputXml));
// XSLT
XmlReader xsltReader = XmlReader.Create(xsltLocation);
// Create Word
byte[] wordDoc = GetWord(xmlReader, xsltReader);
// Write resulting array to HDD, show process information
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
fs.Write(wordDoc, 0, wordDoc.Length);
// Display resulting report in Word
Process.Start(new ProcessStartInfo(outputPath));
}
public string Serialize(object obj, string defaultNamespace)
{
// encoding issue: utf-16 => utf-8
// http://blog.csdn.net/dancefire/article/details/1912345
XmlSerializer xs = new XmlSerializer(obj.GetType(), defaultNamespace);
MemoryStream stream = new MemoryStream();
XmlWriterSettings setting = new XmlWriterSettings();
setting.Encoding = new UTF8Encoding(false);
setting.Indent = true;
using (XmlWriter writer = XmlWriter.Create(stream, setting))
{ xs.Serialize(writer, obj); }
return Encoding.UTF8.GetString(stream.ToArray());
}
public static byte[] GetWord(XmlReader xmlData, XmlReader xsltReader)
{
XslCompiledTransform xslt = new XslCompiledTransform();
XsltArgumentList args = new XsltArgumentList();
using (MemoryStream swResult = new MemoryStream())
{
// Load XSLT to reader and perform transformation
xslt.Load(xsltReader);
xslt.Transform(xmlData, args, swResult);
return swResult.ToArray();
}
}
結果如同我們所預期的將資料都填入Word檔中
期望效益
1. 開發過程可集中於資料模型的設計(類似ViewModel概念)
2. Word樣式可供客戶自行調整 (不變更資料項目為前提下,僅需自動轉為XSLT檔即可)
3. 資料自動綁定至Word並產生檔案輸出
參考資料
http://www.codeproject.com/Articles/20287/Generating-Word-Reports-Documents
http://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !