迷思
一直有人在問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();
}
}
