---
# System prepended metadata

title: WPF匯出Excel--推薦套件「EPPlus」
tags: [WPF]

---

原本使用「Microsoft.Office.Interop.Excel」套件
但寫一寫出現"HRESULT: 0x800A03EC"錯誤訊息
上網查一查，看到有人推薦EPPlus這套件
就載來試試並且換個簡單方法撰寫。

### 前端.xmal設計匯出如下：
```
  <StackPanel Orientation="Horizontal"
       Margin="0 8 8 0"
       VerticalAlignment="Center"
       HorizontalAlignment="Right">
      <Button Style="{StaticResource PageFuncIconButton}"
       Content="{materialDesign:PackIcon Kind=FileExport, Size=36}"
       Command="{Binding ExportCommand}"
       CommandParameter="{Binding ElementName=MyDataGrid}"
       ToolTip="匯出" />
  </StackPanel>
```
可愛的匯出圖案
![image](https://hackmd.io/_uploads/HyJgQmzMC.png)
### viewModel.cs寫法如下(並不是用Click的方式)：

```
public ICommand ExportCommand
{
    get
    {
        if (exportCommand == null)
            exportCommand = new RelayCommand(Export);
        return exportCommand;
    }
}
```


#### Export()：
因為匯出功能想要當作共用，因此開新的檔案來撰寫此功能。
```
 public DataGrid MyDataGrid { get; set; }
 ExportExcel exportexcel = null;
 private  void Export()
 {
     if (exportexcel == null)
         exportexcel = new ExportExcel();
     if (QueryItemResults != null && QueryItemResults.Any())
     {
         exportexcel.ExportDataExcel(QueryItemResults);
     }
 }
```
#### ExportExcel.cs
```
using CommunityToolkit.Mvvm.Messaging;
using OfficeOpenXml;
using PIDC_LMS.Messages;
using PIDC_LMS.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using System.Windows;
using static log4net.Appender.RollingFileAppender;
```
**註記：**
1.原先自動抓欄位的屬性，因欄位名稱都固定，因此直接設計Cells[1列, 1欄].Value欄位
2.<font color="blue">儲存格是從1開始數</font>
3.原先抓DataGrid的寫法會讓日期格式的值跑掉，因此改寫另一種日期格式寫法
4.獲取當前時間，將時間寫在檔名中，是為了避免每次匯出，會覆蓋前一次內容
5.匯出後跳出一個視窗，告訴使用者已匯出完畢
```
namespace PIDC_LMS.Libs
{
    public class ExportExcel
    {
        public void ExportDataExcel(ObservableCollection<QueryItem> queryItems)
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // 關閉新許可模式通知
            // 獲取當前日期時間的時間戳
            string timeStamp = DateTime.Now.ToString("yyyyMMddHHmmss");

            // 在文件名中添加時間戳，可以避免檔案覆蓋
            var file = new FileInfo(@"D:\匯出_" + timeStamp + ".xlsx");

            using (var excel = new ExcelPackage())
            {
                // 建立分頁
                var ws = excel.Workbook.Worksheets.Add("MySheet");

                #region 自動抓欄位屬性
                //int rowindex = 1;
                //int colindex = 1;
                //foreach (var pp in typeof(QueryItem).GetProperties())
                //{
                //    ws.Cells[rowindex,colindex].Value = pp.Name;
                //    colindex++;
                //}
                #endregion

                // 設置中文欄位名稱
                ws.Cells[1, 1].Value = "條碼號";
                ws.Cells[1, 2].Value = "書名";
                ws.Cells[1, 3].Value = "狀態";
                ws.Cells[1, 4].Value = "借閱次數";
                ws.Cells[1, 5].Value = "借閱者";
                ws.Cells[1, 6].Value = "借閱日期";
                ws.Cells[1, 7].Value = "歸還日期";
                ws.Cells[1, 8].Value = "建檔日期";

                //寫入資料
                int rowindex = 2;
                foreach (var item in queryItems)
                {
                    //colindex = 1;
                    //foreach (var pp in typeof(QueryItem).GetProperties())
                    //{
                    //    ws.Cells[rowindex, colindex].Value =pp.GetValue(item);
                    //    colindex++;
                    //}
                    //rowindex++;

                    ws.Cells[rowindex, 1].Value = item.ItemID;
                    ws.Cells[rowindex, 2].Value = item.ItemName;
                    // 狀態欄位根據您的邏輯來填寫
                    ws.Cells[rowindex, 3].Value = item.ItemState == "03" ? "在庫" : "已借閱";
                    ws.Cells[rowindex, 4].Value = item.CheckOutTimes;
                    ws.Cells[rowindex, 5].Value = item.CheckOutPatronName;
                    // 借閱日期和歸還日期套用格式
                    ws.Cells[rowindex, 6].Value = ((DateTime)item.CheckOutDateTime).ToString("yyyy-MM-dd HH:mm:ss");
                    ws.Cells[rowindex, 7].Value = ((DateTime)item.CheckOutDueDate).ToString("yyyy-MM-dd");
                    //ws.Cells[rowindex, 8].Value = item.CreatedDateTime.ToString("yyyy-MM-dd HH:mm:ss");
                    rowindex++;
                }

                // 儲存 Excel
                excel.SaveAs(file);
                MessageBox.Show("匯出成功！", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }

    }
}
```

### 參考資料
[EPPlus —— 輕鬆處理 Excel](https://igouist.github.io/post/2020/04/epplus/#%E5%BB%BA%E7%AB%8B-excel)