摘要:.NET Excel導出方法及其常見問題詳解。html
1、Excel導出的實現方法java
在.net 程序開發中,對於Excel文件的導出咱們一共有三種導出方式:安全
這種方式的導出方法是比較簡單就能夠實現的,咱們其實是針對相似於html中table表格的輸出服務器
a.針對想要的Excel合併樣式寫一個table標籤代碼app
1 <table border="1"> 2 <thead> 3 <tr> 4 <th style="background-color:yellow" colspan="7" align="center">物料彙總單</th> 5 </tr> 6 <tr> 7 <th style="background-color:yellow">物料碼</th> 8 <th style="background-color:yellow">物料名稱</th> 9 <th style="background-color:yellow">型號</th> 10 <th style="background-color:yellow">單位</th> 11 <th style="background-color:yellow">數量</th> 12 <th style="background-color:yellow">備註</th> 13 <th style="background-color:yellow">排序</th> 14 </tr> 15 </thead> 16 <tbody> 17 <tr> 18 <th>{0}</th> 19 <th>{0}</th> 20 <th>{0}</th> 21 <th>{0}</th> 22 <th>{0}</th> 23 <th>{0}</th> 24 <th>{0}</th> 25 </tr> 26 </tbody> 27 </table>
table的border屬性能夠控制展示爲Excel文件時是否顯示網格線,通常若是不設置爲border="1"時,導出的文件是不會生成網格線的,實際上table的各類屬性和樣式最終在生成爲Excel文件時,都大體會以相同的格式展示出來,也就是說咱們只要設計好table的樣式就行,不用考慮其它的問題了。測試
而對於表頭中的顏色設置:網站
1 <tr> 2 <th style="background-color:yellow">物料碼</th> 3 <th style="background-color:yellow">物料名稱</th> 4 <th style="background-color:yellow">型號</th> 5 <th style="background-color:yellow">單位</th> 6 <th style="background-color:yellow">數量</th> 7 <th style="background-color:yellow">備註</th> 8 <th style="background-color:yellow">排序</th> 9 </tr>
有很多人會疑惑:爲何不在<tr>設置background-color不是更方便?this
1 <tr style="background-color:yellow"> 2 <th>物料碼</th> 3 <th>物料名稱</th> 4 <th>型號</th> 5 <th>單位</th> 6 <th>數量</th> 7 <th>備註</th> 8 <th>排序</th> 9 </tr>
這樣作的確省了很多事,可是這樣作當轉化爲Excel文件時效果就不是很相同了。spa
咱們理想中的效果:.net
但實際上會展現爲:
轉化爲Excel文件時並未在固定的列數設置背景顏色,而是整行都被設置爲黃色。針對其餘的細節咱們能夠慢慢的去嘗試,去調整。
此時咱們先要針對現有的table標籤進行數據填充:
1 ber.Append("<table border=\"1\">"); 2 ber.Append("<thead>"); 3 ber.Append("<tr><th style=\"background-color:yellow\" colspan=\"7\" align=\"center\">物料彙總單</th></tr>"); 4 5 ber.Append("<tr>"); 6 7 ber.Append("<th style=\"background-color:yellow\">物料碼</th>"); 8 ber.Append("<th style=\"background-color:yellow\">物料名稱</th>"); 9 ber.Append("<th style=\"background-color:yellow\">型號</th>"); 10 ber.Append("<th style=\"background-color:yellow\">單位</th>"); 11 ber.Append("<th style=\"background-color:yellow\">數量</th>"); 12 ber.Append("<th style=\"background-color:yellow\">備註</th>"); 13 ber.Append("<th style=\"background-color:yellow\">排序</th>"); 14 15 ber.Append("</tr>"); 16 ber.Append("</thead>"); 17 18 ber.Append("<tbody>"); 19 foreach (ExcelTMaterial item in all_models) 20 { 21 ber.Append("<tr>"); 22 ber.AppendFormat("<th>{0}</th>", item.mt_code); 23 ber.AppendFormat("<th>{0}</th>", item.mt_name); 24 ber.AppendFormat("<th>{0}</th>", item.mt_model); 25 ber.AppendFormat("<th>{0}</th>", item.mt_unit); 26 ber.AppendFormat("<th>{0}</th>", item.count); 27 ber.AppendFormat("<th>{0}</th>", item.mt_remake); 28 ber.AppendFormat("<th>{0}</th>", item.mt_sort); 29 ber.Append("</tr>"); 30 } 31 32 33 ber.Append("</tbody>"); 34 ber.Append("</table>");
咱們將數據填充完畢之後得到到的將是字符串文本,而後咱們則經過如下方法導出Excel文件
1)通用輸出流方法
/// <summary> /// 輸入HTTP頭,而後把指定的流輸出到指定的文件名,而後指定文件類型 /// </summary> /// <param name="OutType">輸出類型</param> /// <param name="FileName">文件名稱</param> /// <param name="ExcelContent">內容</param> public void ExportToExcel(string OutType, string FileName, string dataSource) { lock (this) { System.Web.HttpContext.Current.Response.Charset = "UTF-8"; System.Web.HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8; System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8).ToString()); System.Web.HttpContext.Current.Response.ContentType = OutType; System.IO.StringWriter tw = new System.IO.StringWriter(); System.Web.HttpContext.Current.Response.Output.Write(dataSource); System.Web.HttpContext.Current.Response.Flush(); System.Web.HttpContext.Current.Response.End(); } }
2)調用方法獲取Excel文件下載
1 string data =GetMySourceStr(); 2 ExportToExcel("application/ms-excel", "導出Excel文件.xls", data);
這裏要注意參數:
string OutType:application/ms-excel輸出方式;
string FileName:指定文件的名稱+.xls,後綴咱們最好不要更改,默認.xls便可;
string dataSource:拼接好的數據源字符串;
此時總體下來咱們即可以完成簡單的Excel表格導出功能了。
注:在某種特殊狀況下,文檔數據會存在丟失現象,如:文件傳送給他人計算機,爲避免這種狀況只能採起導出後將內容Copy到新建的Excel文件中,所以此方法不推薦使用!(2019-01-28注)
二、第三方插件進行Excel導出
網上推薦使用:NPOI導出。如下是百度百科的介紹:
NPOI是指構建在POI 3.x版本之上的一個程序,NPOI能夠在沒有安裝Office的狀況下對Word或Excel文檔進行讀寫操做。 POI是一個開源的Java讀寫Excel、WORD等微軟OLE2組件文檔的項目。
能夠看出NPOI的優點在於獨立性,不依賴於Office去完成一系列操做,針對Java和C#均可以使用;其官方網址:NPOI官方網站,因爲暫時還未採用第三方插件進行導出,暫不對此進行介紹。而對於B\S端我我的更推薦使用此方法,由於它的一些基本操做以及相關的依賴,NPOI對於格式和生成的速度都是有必定優點的。
(2019-01-28新增)
去年中旬開始,針對業務調整,發現微軟提供的microsoft.office.interop.excel.dll使用上雖然很方便,可是對於部署上真是一言難盡,好比以前的服務器帳號註銷、速度等問題,所以後續調整便採用NPOI。
對於NPOI的使用十分的簡單且方便
1)咱們須要安裝或引用NPOI依賴包
2)建立Book、Sheet、Row、Cell,NPOI在建立這些對象上很直觀明瞭,操做起來和寫文章同樣
類及接口 | 說明 |
NPOI.HSSF.UserModel.HSSFWorkbook | 建立Excek文件對象 |
NPOI.SS.UserModel.ISheet | Excel中的工做簿 |
NPOI.SS.UserModel.IRow | Excel工做部中的行 |
NPOI.SS.UserModel.ICell | Excel工做部中的單元格 |
對於建立Excel文件及簡單填充數據很簡單(簡單的測試方法,Copy便可使用):
public void G() { //建立Excel文件的對象 HSSFWorkbook book = new HSSFWorkbook(); //添加一個sheet ISheet sheet = book.CreateSheet($"工做簿1"); //行下標記錄 int rowIndex = 0; //建立首行 IRow row0 = sheet.CreateRow(rowIndex++); //建立單元格 ICell cell0 = row0.CreateCell(0); //設置單元格內容 cell0.SetCellValue("測試首行"); //建立多行 for (int i = 0; i < 10; i++) { var row = sheet.CreateRow(rowIndex++); //連寫建立單元格並設置單元格內容 (通常這樣寫更好點) row.CreateCell(0).SetCellValue("A"+i.ToString()); } using (FileStream st = new FileStream(AppDomain.CurrentDomain.BaseDirectory+ "test.xls", FileMode.OpenOrCreate)) { book.Write(st); } }
打開生成的文件以下圖:
2)多工做簿實現
咱們只須要簡單改一改就能夠實現,Book是固定惟一的,此時咱們針對Sheet動態實現便可,通常多是手動去建立,咱們使用簡單循環實現一下吧
public void G() { //建立Excel文件的對象 HSSFWorkbook book = new HSSFWorkbook(); //添加一個sheet for (int index = 0; index < 3; index++) { ISheet sheet = book.CreateSheet($"工做簿{(index + 1)}"); //行下標記錄 int rowIndex = 0; //建立首行 IRow row0 = sheet.CreateRow(rowIndex++); //建立單元格 ICell cell0 = row0.CreateCell(0); //設置單元格內容 cell0.SetCellValue("測試首行"); //建立多行 for (int i = 0; i < 10; i++) { var row = sheet.CreateRow(rowIndex++); //連寫建立單元格並設置單元格內容 (通常這樣寫更好點) row.CreateCell(0).SetCellValue("A" + i.ToString()); } } using (FileStream st = new FileStream(AppDomain.CurrentDomain.BaseDirectory+ "test.xls", FileMode.OpenOrCreate)) { book.Write(st); } }
從以上能夠看出,NPOI對於Excel導出非常實用,對於NPOI其餘功能暫時還沒使用到,所以不作評價。
注:由於工做中開始使用Java作服務,而Java提供了更爲的Excel、Word、Pdf等文件的處理,所以後續考慮吧文件處理交給java服務程序去完成,.Net作核心功能業務。
三、微軟提供的microsoft.office.interop.excel.dll
microsoft.office.interop.excel.dll是針對COM+的包裝,它便於在託管代碼中使用,依賴本地安裝的Office軟件。若是本地未安裝Office則此方法不適合操做Excel以及其餘相關如:
這些都是微軟其Office產品提供的插件,惟一的缺點則是依賴性,咱們在本地開發須要安裝Office,部署在服務器也是須要安裝Office,在B\S端的響應速度不是太好。
1)DLL引用
Microsoft.Office.Interop.Excel.dll、Microsoft.Office.core.dll
2)引用方式
Microsoft.Office.Interop.Excel.dll:
經過NuGet包管理器進行安裝,要與本地Office版本相對應。
Microsoft.Office.core.dll:
經過項目的右鍵>添加引用>COM>類型庫 --查找-->Microsoft Office 15.0 Object Library(此處針對Office2013,其它版本能夠查找相應的Microsoft Office xx.0 Object Library)。
3)使用方法
a.引入命名空間
咱們能夠直接引入一下命名空間:
using Microsoft.Office.Interop.Excel;
也能夠這樣引入:
using OfcExcel = Microsoft.Office.Interop.Excel;
這樣作主要是針對較長方法的簡寫。
b.方法的實現
咱們首先建立一個ApplicationClass對象,可是發現彷佛提示了一個錯誤,第一次使用的時候發現代碼並沒用什麼問題,後來查閱了一些文檔和教程咱們只須要作一下操做即可以解決:
在引用中找到Microsoft.Office.Interop.Excel查看屬性->嵌入互操做類型由True改成False便可。
再編寫如下代碼:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using Microsoft.Office.Interop.Excel; 7 using System.Drawing; 8 using System.IO; 9 10 namespace OutExcel 11 { 12 public class Utility 13 { 14 public static void ExcelOut() 15 { 16 17 ApplicationClass app = new ApplicationClass(); 18 19 /*針對Excel 對象及工做簿單元格操做*/ 20 Workbook workbook_1 = (Workbook)app.Workbooks.Add(true);//添加workbook 21 Worksheet worksheet_1 = (Worksheet)workbook_1.Worksheets[1];//選擇第一個,即默認的工做簿 22 Range sheet_cells = worksheet_1.Cells;//工做簿單元格 23 24 string[] columns = new string[] { "系統", "設備信息", "類別", "代碼", "名稱", "型號", "單位", "數量", "備註" };//列數 25 int row = 1;//默認行數 26 Range rg = sheet_cells.Range[app.Cells[row, 1], app.Cells[row, columns.Length]];//選擇光標-----選擇第一行 1 到10列 27 rg.Merge(false);//合併單元格 28 rg.Value2 = "內容";//設置選中單元格內容 29 row++;//下移一行 30 31 32 for (int index = 0; index < columns.Length; index++) 33 { 34 sheet_cells[row, index + 1] = columns[index];//設置列標題內容 35 } 36 37 rg = sheet_cells.Range[app.Cells[1, 1], app.Cells[row, columns.Length]];//選擇標題頭 38 39 /*針對選中單元格樣式設置*/ 40 rg.Borders.LineStyle = XlLineStyle.xlContinuous; 41 rg.HorizontalAlignment = XlHAlign.xlHAlignCenter; 42 rg.VerticalAlignment = XlHAlign.xlHAlignCenter; 43 rg.Interior.Color = Color.Yellow; 44 45 string path_ = AppDomain.CurrentDomain.BaseDirectory.ToString()+ "excel導出.xlsx"; 46 if (File.Exists(path_)) 47 { 48 File.Delete(path_); 49 } 50 try 51 { 52 workbook_1.SaveAs(path_, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, XlSaveAsAccessMode.xlNoChange, 1, false, Type.Missing, Type.Missing, Type.Missing); 53 54 } 55 catch (Exception ex) 56 { 57 path_ = null; 58 } 59 finally 60 { 61 workbook_1.Close(true, path_, Type.Missing); 62 workbook_1 = null; 63 } 64 } 65 } 66 }
以上代碼只是參考示例基礎操做,你可使用過程當中對經常使用方法進行封裝。
C\S端再調用此方法時會在Debug目錄下生成:
B\S生成則在根目錄下,咱們能夠指定本身存放的路徑。
生成結果:
此時針對Microsoft.Office.Interop.Excel.dll操做基本完成,而針對它的操做方法能夠查閱相關文檔便可實現。對於B\S調用出現的問題能夠參考下面的方法解決。
2、提示的錯誤信息
一、導出Excel提示信息錯誤
檢索 COM 類工廠中 CLSID 爲 {00024500-0000-0000-C000-000000000046} 的組件失敗,緣由是出現如下錯誤: 8000401a 由於配置標識不正確,系統沒法開始服務器進程。請檢查用戶名和密碼。 (異常來自 HRESULT:0x8000401A)。
1)問題表現
服務器斷開鏈接,導出功能報錯即以上錯誤。服務器登錄,導出正常。
2)分析
帳號的登錄與斷開,表現爲帳戶所屬權限問題。
3)解決過程
參照着網上的一些教程總結,得出一下方法:
a.設置DCOM
win+r鍵,輸入:dcomcnfg.exe 調出=》組件服務
選擇 組件服務>計算機>個人電腦>DCOM 配置 --查找-->Microsoft Excel Application
右鍵>屬性>安全,設置以下
標識設置:
若是此時仍是報錯,則能夠考慮設置 標識 爲 下列用戶 即指定一個用戶:
保存配置在關閉,斷開服務器鏈接,導出Excel不在報8000401A錯誤。
問題0x8000401A 參考文獻:http://blog.csdn.net/caobingyi/article/details/5175281