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

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

因為是範本檔是 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

發表迴響