利用 NPOI Library 合併多個 Excel 檔

利用 NPOI Library 合併多個 Excel 檔

之前看了小朱大大寫的 CodePlex 教學文章 -- 在 Server 端存取 Excel 檔案的利器:NPOI Library,拜讀完除了感念朱大的佛心、留下兩行熱淚以外,一直還沒有進一步實作…,今天終於有個好動機了。

所謂合併多個 Excel 檔,是指可能有多張欄位相同的工作表 (Sheet),分散在多個活頁簿 (Workbook,一個實體 Excel 檔),使用者希望可以寫一支程式自由指定上傳的活頁簿,接著點個按鈕就能把多張工作表由上而下、一個接一個合併成為一張大工作表。這需求在仔細端詳教學文之後,估計利用 NPOI 函式庫來做應該是可行的,且似乎能夠省去一堆麻煩事,所以就來寫寫看吧!

預備知識以及環境設定就不提了,請自行參考上述教學文,網頁配置如下 (僅列重點):

<div>
    <asp:FileUpload ID="FileUpload1" runat="server" /><br />
    <asp:FileUpload ID="FileUpload2" runat="server" /><br />
    <asp:FileUpload ID="FileUpload3" runat="server" /><br />
    <asp:Button ID="MergeButton" runat="server" Text=" 合併讀取 " OnClick="MergeButton_Click" /><hr />
    <asp:GridView ID="gvXLS" runat="server" BackColor="White" BorderColor="#336666" BorderStyle="Double"
        BorderWidth="3px" CellPadding="4" GridLines="Horizontal">
        <RowStyle BackColor="White" ForeColor="#333333" />
        <FooterStyle BackColor="White" ForeColor="#333333" />
        <PagerStyle BackColor="#336666" ForeColor="White" HorizontalAlign="Center" />
        <SelectedRowStyle BackColor="#339966" Font-Bold="True" ForeColor="White" />
        <HeaderStyle BackColor="#336666" Font-Bold="True" ForeColor="White" />
    </asp:GridView>
</div>
</form>

主要程式碼改寫自教學文,只修改小部分而已:

// using System.Data;
// using System.IO;
// using NPOI.HSSF.UserModel;
private void MergeData(Stream fileStream, DataTable dt)
{
    HSSFWorkbook workbook = new HSSFWorkbook(fileStream);
    HSSFSheet sheet = workbook.GetSheetAt(0);

    HSSFRow headerRow = sheet.GetRow(0);
    int cellCount = headerRow.LastCellNum;

    if (dt.Rows.Count == 0)
    {
        // 首次執行仍未有資料,須先建立 Header
        for (int i = headerRow.FirstCellNum; i < cellCount; i++)
        {
            DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
            dt.Columns.Add(column);
        }
    }
    else
    {
        // TODO:檢查後續 sheet 欄位是否相符
    }

    int rowCount = sheet.LastRowNum + 1;

    for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++)
    {
        HSSFRow row = sheet.GetRow(i);
        DataRow dataRow = dt.NewRow();

        for (int j = row.FirstCellNum; j < cellCount; j++)
        {
            if (row.GetCell(j) != null)
                dataRow[j] = row.GetCell(j).ToString();
        }

        dt.Rows.Add(dataRow);
    }

    workbook = null;
    sheet = null;
}

protected void MergeButton_Click(object sender, EventArgs e)
{
    DataTable dt = new DataTable();

    foreach (Control c in Page.Form.Controls)
    {
        if (c.GetType().Equals(typeof(FileUpload)))
        {
            FileUpload f = c as FileUpload;

            if (f.HasFile)
                MergeData(f.FileContent, dt);
        }
    }

    if (dt.Rows.Count > 0)
    {
        gvXLS.DataSource = dt;
        gvXLS.DataBind();
    }
}

這樣就可以了,接著準備三個活頁簿,資料如圖所示:

npoi_practice_4

程式開起來,依次選取三個 Excel 檔、點合併讀取,實際執行效果可以看底下截圖:

npoi_practice_2
npoi_practice_3

嘖嘖嘖…除了讚嘆還是讚嘆!NPOI 果然是好物一枚,跟著教學文實作,可以說是毫無滯礙,更有一種難得的暢快感!你甚至不必在伺服器端安裝 Excel 程式、擔心 Excel 工作行程沒有釋放,也不必為了 x64 平台上沒有 Microsoft.Jet.OLEDB.4.0 這個 Provider 而懊惱,最讓人激賞的是沒寫幾行程式,輕輕鬆鬆就完成合併 Excel 的功能,簡單俐落到了極點。

以上只是最基本的示範,進一步的擴充好比說:在合理限度內讓使用者動態增加上傳檔數量,或者各活頁簿擁有的工作表數量不固定,通通一併處理,以及各工作表欄位是否相符等錯誤處理機制,甚至合併多個 Excel 檔之後還要寫到資料庫或其他進一步處理…這些就留給大家自行補強囉!


更新紀錄