GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
字體大小: +
3 分鐘閱讀時間 (520 個字)

使用 Aspose.Word 達成合併列印套表

angle-view-of-microsoft-surface-laptop-mockup
前陣子接到了一個需求,客戶希望能透過人事系統列印當年度每位員工的年終獎金發放通知單,
同時客戶提供了通知單範本,範本檔內容類似下圖:


因為是範本檔是 Word 的關係,第一個想到的是 合併列印套表
所以先將幾個動態資訊以 MergeField 取代,取代後的樣子如下圖:


結果後來跟同事確認後,才知道考勤獎金、春節獎金、績效獎金 這三個項目並不是固定的。
舉例來說,王小明有考勤獎金、春節獎金、績效獎金,但換作是其他人可能就只有春節獎金,
所以上圖的做法完全不行...

後來看了 RM 的文章 [.NET]透過 Aspose.Words 來做合併列印-每筆資料長一個Table才知道原來合併列印也有類似迴圈的功能變數可以設定,
那年終獎金明細的部分就有解了!
但該如何讓程式知道目前合併列印的是A員工資料,並且長出A員工的年終獎金明細?

當時想到的方法是...如果將範本檔設計成巢狀的概念是否也能夠達成?
外層為主檔(TableM),包含年度、部門、員工姓名、績效評等、獎金總計。
內層為明細檔(TableD),包含薪資項目名稱與薪資項目金額。

有了初步的想法,就先試著實作...

▍準備範本檔


 
▍準備測試資料
Private Function GetMasterData() As DataTable
Dim dt As New DataTable
dt.Columns.Add("EMP_ID")
dt.Columns.Add("EMP_NAME")
dt.Columns.Add("DEP_NAME")
dt.Columns.Add("PFM_YEAR")
dt.Columns.Add("PFM_RANK")
dt.Columns.Add("TOTAL_AMOUNT")
dt.Rows.Add("A0001", "王大明", "財務部", "2018", "A", "30000")
dt.Rows.Add("A0002", "陳拉拉", "資訊部", "2018", "B", "2000")
Return dt
End Function
Private Function GetDetailData() As DataTable
Dim dt As New DataTable
dt.Columns.Add("EMP_ID")
dt.Columns.Add("ITEM_NAME")
dt.Columns.Add("AMOUNT")

'王大明年終獎金明細
dt.Rows.Add("A0001", "考勤獎金", "5000")
dt.Rows.Add("A0001", "春節獎金", "5000")
dt.Rows.Add("A0001", "績效獎金", "20000")

'陳拉拉年終獎金明細
dt.Rows.Add("A0002", "考勤獎金", "2000")

Return dt
End Function


 
▍使用 Aspose.Word 合併列印套表

Dim strTemplatePath As String = "D:\MailMergeSample.doc"
Dim strResultPath As String = "D:\MailMergeResult_{0}.doc"

Dim dtMaster As DataTable = GetMasterData()
Dim dtDetail As DataTable = GetDetailData()

Dim dtTableM As New DataTable
Dim dtTableD As New DataTable
Dim strEmpID As String

For i As Integer = 0 To dtMaster.Rows.Count - 1
dtTableM = dtMaster.Clone
dtTableD = dtDetail.Clone
strEmpID = dtMaster.Rows(i).Item("EMP_ID")

For Each dr As DataRow In dtMaster.Select(String.Format("EMP_ID='{0}'", strEmpID))
dtTableM.ImportRow(dr)
Next

For Each dr As DataRow In dtDetail.Select(String.Format("EMP_ID='{0}'", strEmpID))
dtTableD.ImportRow(dr)
Next

dtTableM.TableName = "TableM"
dtTableD.TableName = "TableD"

Dim ds As DataSet = New DataSet
ds.Tables.Add(dtTableM)
ds.Tables.Add(dtTableD)

Dim doc As New Aspose.Words.Document(strTemplatePath)
doc.MailMerge.CleanupOptions = MailMerging.MailMergeCleanupOptions.RemoveEmptyParagraphs
doc.MailMerge.ExecuteWithRegions(ds)
doc.Save(String.Format(strResultPath, strEmpID), SaveFormat.Doc)
Next


 
▍輸出結果

應該會產出兩個檔案,分別為 MailMergeResult_A0001.doc 與 MailMergeResult_A0002.doc



×
Stay Informed

When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.

Windows Server 2016安裝ASP.NET 1.1 程式
SQL 某個欄位包含 文字、符號及數值,是否可依 數值、文字來排序?
 

評論

尚無評論
已經注冊了? 這裡登入
2025年10月27日, 星期一

Captcha 圖像