2016年3月2日 星期三

網頁資料套用表單格式 -- 20160302

緣由:

最近想把將自己手邊上的工作,藉由網路的方式來處理,由於自己寫程式算是初學者,所以東湊西湊的寫出這簡單的網頁(網址),但朋友建議我若可以寫出套表的話,那網站就會更棒,在好奇心的驅使一下,結果我花了半天時間就搞定了。挖塞~真不敢相信我自己的能力。

※軟體:Visual Studio 2012開發軟體、作業系統為Windows 10



---------------以下是網頁套表的寫法:------------------------


步驟一、先下載Open XML SDK 2.0 for Microsoft Office套件,且下載時會有兩個檔案(OpenXMLSDKv2.msi、OpenXMLSDKTool.msi),記得兩個檔案都要下載,並且安裝起來。

備註:OpenXMLSDKv2.msi 報表開發所需的軟體
            OpenXMLSDKTool.msi 觀察OpenXML的工具軟體






步驟二、在專案中開啟Bin資料夾,並將DocumentFormat.OpenXml.dllWindowsBase.dll兩個檔案,複製到Bin資料夾中。

備註:
  • DocumentFormat.OpenXml.dll 放置路徑
            →  C:\Program Files (x86)\Open XML SDK\V2.0\lib
  • WindowsBase.dll 放置路徑 
             → C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0


































































































步驟三、準備好報表樣式,並將報表格式存檔成*.docx格式(目前這方法僅適用於docx檔案),並將已設計好的報表樣式(FixTable.docx)放置report資料夾中。






























































步驟四、簡易製作網頁,且網頁的欄位可以套用到表格樣版中。








































步驟五、開始寫程式碼。

































[程式碼一]

using System.Text;
using DocumentFormat.OpenXml.Packaging;
using System.IO;



[程式碼二]

namespace Darkthread.OpenXml
{
    /// <summary>
    /// Ver 1.0 By Jeffrey Lee, 2009-07-29
    /// </summary>
    public class DocxHelper
    {
        /// <summary>
        /// Replace the parser tags in docx document
        /// </summary>
        /// <param name="oxp">OpenXmlPart object</param>
        /// <param name="dct">Dictionary contains parser tags to replace</param>
        
        private static void parse(OpenXmlPart oxp, Dictionary<string, string> dct)
        {
            string xmlString = null;
            using (StreamReader sr = new StreamReader(oxp.GetStream()))
            { xmlString = sr.ReadToEnd(); }
            foreach (string key in dct.Keys)
                xmlString = xmlString.Replace("[$" + key + "$]", dct[key]);
            using (StreamWriter sw = new StreamWriter(oxp.GetStream(FileMode.Create)))
            { sw.Write(xmlString); }
        }

        /// <summary>
        /// Parse template file and replace all parser tags, return the binary content of
        /// new docx file.
        /// </summary>
        /// <param name="templateFile">template file path</param>
        /// <param name="dct">a Dictionary containing parser tags and values</param>
        /// <returns></returns>
        
        public static byte[] MakeDocx(string templateFile, Dictionary<string, string> dct)
        {
            string tempFile = Path.GetTempPath() + ".docx";
            File.Copy(templateFile, tempFile);

            using (WordprocessingDocument wd = WordprocessingDocument.Open(tempFile, true))
            {
                //Replace document body
                parse(wd.MainDocumentPart, dct);
                foreach (HeaderPart hp in wd.MainDocumentPart.HeaderParts)
                    parse(hp, dct);
                foreach (FooterPart fp in wd.MainDocumentPart.FooterParts)
                    parse(fp, dct);
            }

            byte[] buff = File.ReadAllBytes(tempFile);
            File.Delete(tempFile);
            return buff;
        }

    }
}


※上述的程式碼出處為:來源



[程式碼三]

TextBox2.Text = DateTime.Now.ToString();




在Button2_Click事件中,將下列的程式碼貼至事件中。(黃色框是依據您自行撰寫的表格樣版的擺放位置、表格欄位而定義的,其欄位名稱可自由調整。)









































[程式碼四]

string template = Server.MapPath("report/FixTable.docx");

Dictionary<string, string> dct = new Dictionary<string, string>()
    { 
        { "Unit", DropDownList1.SelectedValue },
        { "Today", DateTime.Today.ToString("yyyy/MM/dd") },
        { "UserName", TextBox1.Text },
        { "ProType", DropDownList2.SelectedValue },
        { "Content", TextBox3.Text } 
    };

Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename=Notice.docx");

Response.BinaryWrite(    Darkthread.OpenXml.DocxHelper.MakeDocx(Server.MapPath("report/FixTable.docx"),dct));

Response.End();



步驟六、程式碼與表單欄位互相對應。開啟表單樣版,在欄位上輸入[$欄位名稱$],然而,表格上面的欄位名稱要與程式碼相同。別忘了,表單欄位內容編輯好之後記得儲存。







































步驟七、執行設計好的網頁,且查看是否有將網頁內容套用到表單中。




※開啟下載後的檔案,結果發現部分欄位無法套用文字(時常會出現這種情況)。由於無法得知哪裡出問題,所以可透過「Open XML SDK 2.0 Productivity Tool」工具來檢查問題發生的原因。


























※正常的情況,因該是如下圖所顯示的畫面。


























補充:如何使用Open XML SDK 2.0 Productivity Tool呢?

首先,開啟已安裝完成的Open XML SDK 2.0 Productivity Tool工具。





































開啟表格樣版,開啟 File → Open File → FixTable.docx。




































按下「Reflect Code」,可看見該表格樣版的所有程式碼。(老實說,我很懶得看。)








































本人採用的方法,先點選該檔案,按下滑鼠右鍵,會出現Find..功能,透過搜尋功能直接找到「關鍵表格欄位名稱」。'































正常的情況,搜尋到因該是[$Today$]格式。


















將問題發生的欄位,採用關鍵字搜尋時,發現理當因該是[$UserName$],但出現卻是"UserName",肯定是這地方有問題。於是重新將表單樣版的Keyin一次。








































在嘗試直行網頁程式,查看套表是否至正常。






下載後,開啟檔案發現已恢復正常,及製作完成套表。
















































參考網址:ola的家黑暗執行諸






結論:

老實說,我寫程式真的算是初學者,甚至連基礎都不太會了,當在網路爬文的時候,很多時候都是看不懂得,但自己總是保持者「別人都可以,為何我不行?的心態去嘗試看看」往往這樣都會有不錯的結果,就算是做不出來,也是一個很不錯的經驗,這例子我只花了半天時間就可以製作出來,不瞞您們,這程式碼有三分之二看不懂,但最終還是被我亂矇亂搞給弄出來,真的很爽拉。網路上有提到工具可以查出問題,但只有點到為止,一開始我還真的不會用這工具,後來不小心把它稍微搞懂,於是也順便寫下來幫助其他網友,希望大家都能一起進步。