利用類別產生XSD檔
產出XSD檔的目的在於提供Word樣板設計之資料框架
在此使用微軟提供之XML Schema Definition Tool (Xsd.exe)工具產生XSD檔
1. 定義類別
04 |
public string BookId { get ; set ; }
|
05 |
public string Name { get ; set ; }
|
06 |
public string price { get ; set ; }
|
12 |
public string BuyerName { get ; set ; }
|
13 |
public List<Book> Books { get ; set ; }
|
14 |
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內容如下
01 |
<? xml version = "1.0" encoding = "utf-8" ?>
|
03 |
< xs:element name = "Order" nillable = "true" type = "Order" />
|
04 |
< xs:complexType name = "Order" >
|
06 |
< xs:element minOccurs = "0" maxOccurs = "1" name = "BuyerName" type = "xs:string" />
|
07 |
< xs:element minOccurs = "0" maxOccurs = "1" name = "Books" type = "ArrayOfBook" />
|
08 |
< xs:element minOccurs = "1" maxOccurs = "1" name = "TotalPrice" type = "xs:int" />
|
11 |
< xs:complexType name = "ArrayOfBook" >
|
13 |
< xs:element minOccurs = "0" maxOccurs = "unbounded" name = "Book" nillable = "true" type = "Book" />
|
16 |
< xs:complexType name = "Book" >
|
18 |
< xs:element minOccurs = "0" maxOccurs = "1" name = "BookId" type = "xs:string" />
|
19 |
< xs:element minOccurs = "0" maxOccurs = "1" name = "Name" type = "xs:string" />
|
20 |
< xs:element minOccurs = "0" maxOccurs = "1" name = "price" type = "xs:string" />
|
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
http://www.microsoft.com/downloads/details.aspx?familyid=ca83cb4f-8dee-41a3-9c25-dd889aea781c&displaylang=en
2. 將Word檔另存為XML
3. 利用WML2XSLT.exe 將 Order.xml 轉換成 Order.xslt
點選所需的namespace即可
組合資料產生Word檔
資料 + 顯示樣式
= 資料物件序列化(XML) + XSLT
= 產生具有資料及指定樣式Word檔
01 |
private void CreateWord()
|
04 |
string xsltLocation = @"D:\Order.xslt" ;
|
05 |
string outputPath = @"D:\Order.doc" ;
|
08 |
Order order = new Order()
|
10 |
BuyerName = "Chris Chen" ,
|
12 |
Books = new List<Book>()
|
14 |
new Book(){BookId= "B001" , Name= "Name01" , price= "100" },
|
15 |
new Book(){BookId= "B002" , Name= "Name02" , price= "200" },
|
16 |
new Book(){BookId= "B003" , Name= "Name03" , price= "300" },
|
20 |
// Data XML (一定要namespace)
|
22 |
XmlTextReader xmlReader = new XmlTextReader( new System.IO.StringReader(szInputXml));
|
25 |
XmlReader xsltReader = XmlReader.Create(xsltLocation);
|
28 |
byte [] wordDoc = GetWord(xmlReader, xsltReader);
|
30 |
// Write resulting array to HDD, show process information
|
31 |
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
|
32 |
fs.Write(wordDoc, 0, wordDoc.Length);
|
34 |
// Display resulting report in Word
|
35 |
Process.Start( new ProcessStartInfo(outputPath));
|
38 |
public string Serialize( object obj, string defaultNamespace)
|
40 |
// encoding issue: utf-16 => utf-8
|
43 |
XmlSerializer xs = new XmlSerializer(obj.GetType(), defaultNamespace);
|
45 |
MemoryStream stream = new MemoryStream();
|
46 |
XmlWriterSettings setting = new XmlWriterSettings();
|
47 |
setting.Encoding = new UTF8Encoding( false );
|
48 |
setting.Indent = true ;
|
50 |
using (XmlWriter writer = XmlWriter.Create(stream, setting))
|
51 |
{ xs.Serialize(writer, obj); }
|
53 |
return Encoding.UTF8.GetString(stream.ToArray());
|
56 |
public static byte [] GetWord(XmlReader xmlData, XmlReader xsltReader)
|
58 |
XslCompiledTransform xslt = new XslCompiledTransform();
|
59 |
XsltArgumentList args = new XsltArgumentList();
|
61 |
using (MemoryStream swResult = new MemoryStream())
|
63 |
// Load XSLT to reader and perform transformation
|
64 |
xslt.Load(xsltReader);
|
65 |
xslt.Transform(xmlData, args, swResult);
|
67 |
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
http://blogs.msdn.com/b/williamcornwill/archive/2007/01/17/document-generation-using-wordml-word-2003.aspx