NPOI 匯出 Excel

      在〈NPOI 匯出 Excel〉中尚無留言

迷思

一直有人在問DataGrid的資料如何匯出Excel. DataGrid並沒有存取每個Cell值的方法, 硬要作的話就是要寫一大堆代碼。

但試想, DataGrid裏的值, 是那裏來的? 就是使用 grid.DataContext = DataTable, 把DataTable裏放入DataGrid裏

所以主題要變換一下, 如何把DataTable匯出Excel

Excel套件

網路上大都教學使用Microsoft.Office.Interop.Excel套件,此套件是微軟自行開發的。在匯出資料時,會於背景開啟Excel, 然後與C#進行資料的傳輸。此方法除了效能極差之外,客戶端必需安裝Excel才可執行。所以根本就不建議使用此方法。

本章要介紹的,是另一個效能極高的NPOI套件,而且客戶端不需安裝Excel就能執行。請先由工具/NuGet套件管理員/管理方案的NuGet套件,然後於瀏覽搜尋NPOI套件,進行安裝即可

建立工作簿及工作表

NPOI.XSSF是建立Excel 2006及以上的版本,副檔名為 .xlsx。NPOI.HSSF則是建立2006以前的版本,副檔名為 .xls。

首先使用XSSFWorkbook()產生一個工作簿物件workbook, 再由workbook.CreateSheet(“Sheet”)工作表 sheet 物件。然後就可以開始由sheet進行資料填入。

using NPOI.XSSF.UserModel;
XSSFWorkbook workbook = new XSSFWorkbook(); //新建xlsx工作簿
workbook.CreateSheet("Sheet1");
XSSFSheet sheet = (XSSFSheet)workbook.GetSheet("Sheet1");

建立列

使用sheet.CreateRow(列),參數的列,由0開始。建立後,即可由sheet.GetRow(列)取得列物件

var row=sheet.CreateRow(i);

建立欄

使用row.CreateCell(欄)建立欄物件,再使用SetCellValue(值)將資料填入儲存格

row.CreateCell(j).SetCellValue(f)

儲存檔案

先產生FileStream file檔案物件,然後由工作簿workbook.Write(file)。記得後續需close file及workbook.

FileStream file = new FileStream(excelFileName, FileMode.Create);
workbook.Write(file);
file.Close();
workbook.Close();

圖片

1. 先使用new WebClient().DownloadData(url)下載圖片置於byte[]陣列中。
2. 使用workbook.AddPicture()將圖片加入工作簿,並記錄圖片索引 pictureIdx。
3. 使用sheet.CreateDrawingPatriarch在工作表建立Patriarch
4. 使用XSSFClientAnchor()建立描點。前四個參數為圖片位置,可全設為0。後四個分別為(啟始欄,啟始列,結束欄,結束列)
5. 使用patriach.CreatePicture將圖片加入

string url;
byte[] bytes;
IDrawing patriarch;
XSSFClientAnchor anchor;
XSSFPicture pict;
try//底下有可能圖片不見了找不到
{
    url = t.Rows[i][j].ToString();
    bytes = new WebClient().DownloadData(url);
    pictureIdx = workbook.AddPicture(bytes, XSSFWorkbook.PICTURE_TYPE_JPEG);
    patriarch = sheet.CreateDrawingPatriarch();
    anchor = new XSSFClientAnchor(0, 0, 0, 0, j, i + 1, j + 1, i + 2);//(0,0,0,0,啟始欄,啟始列,結束欄,結束列)
    pict = (XSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
}
catch { }

完整代碼

private void ExportExcel(Object table)
{
	SaveFileDialog saveFileDialog = new SaveFileDialog();
	saveFileDialog.Filter = "Excel Files(*.xlsx)|*.xlsx";
	if (saveFileDialog.ShowDialog() == true)
	{
		psBar.Value = 0;
		psBar.IsIndeterminate = false;
		psBar.Visibility = Visibility.Visible;
		btn匯出Excel.IsEnabled = false;
		new Thread(() => {
			int h = 115, pictureIdx;
			string url, content;
			byte[] bytes;
			IDrawing patriarch;
			XSSFClientAnchor anchor;
			XSSFPicture pict;
			string fileName = saveFileDialog.FileName;
			DataTable t = (DataTable)table;
			XSSFWorkbook workbook = new XSSFWorkbook(); //新建xlsx工作簿
			workbook.CreateSheet("Sheet1");
			XSSFSheet sheet = (XSSFSheet)workbook.GetSheet("Sheet1");
			sheet.SetColumnWidth(0, 30 * 256);
			sheet.SetColumnWidth(1, 30 * 256);
			sheet.SetColumnWidth(2, 10 * 256);//來源
			sheet.SetColumnWidth(3, 17 * 256);//巡查案號
			sheet.SetColumnWidth(4, 10 * 256);//日期
			sheet.SetColumnWidth(5, 50 * 256);//地址
			sheet.SetColumnWidth(6, 10 * 256);//損壞類別
			sheet.SetColumnWidth(7, 10 * 256);//巡查員
			sheet.SetColumnWidth(8, 15 * 256);//道管編號
			sheet.SetColumnWidth(9, 15 * 256);//會勘編號
			sheet.SetColumnWidth(10, 15 * 256);//派工單號
			sheet.SetColumnWidth(11, 15 * 256);//回報單號
			IRow row=sheet.CreateRow(0);
			row = sheet.CreateRow(0);
			for (int i = 0; i < t.Columns.Count; i++)
			{
				row.CreateCell(i).SetCellValue(t.Columns[i].ToString());
			}
			for (int i = 0; i < t.Rows.Count; i++)
			{
				row = sheet.CreateRow(i+1);
				row.HeightInPoints = h;
				for (int j = 0; j < t.Columns.Count; j++)
				{
					if (t.Rows[i][j].ToString().StartsWith("http"))
					{
						try//底下有可能圖片不見了找不到
						{
							url = t.Rows[i][j].ToString();
							bytes = new WebClient().DownloadData(url);
							pictureIdx = workbook.AddPicture(bytes, XSSFWorkbook.PICTURE_TYPE_JPEG);
							patriarch = sheet.CreateDrawingPatriarch();
							anchor = new XSSFClientAnchor(0, 0, 0, 0, j, i + 1, j + 1, i + 2);//(0,0,0,0,啟始欄,啟始列,結束欄,結束列)
							pict = (XSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
						}
						catch { }
					}
					else
					{
						content = t.Rows[i][j].ToString();
						if (!content.Equals("'"))row.CreateCell(j).SetCellValue(t.Rows[i][j].ToString());
					}
				}
				Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
					psBar.Value = (int)((float)i / t.Rows.Count * 100);
				}));
			}

			FileStream file = new FileStream(fileName, FileMode.Create);
			workbook.Write(file);
			file.Close();
			workbook.Close();
			Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
				psBar.Value = 100;
				psBar.IsIndeterminate = false;
				psBar.Visibility = Visibility.Collapsed;
				MessageBox.Show(string.Format("匯出Excel完成\n{0}", fileName), "派工單維護明細");
				btn匯出Excel.IsEnabled = true;
			}));

		}).Start();
	}
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *