Asp.net導出Excel續章(自定義合並單元格,非Office組件)


結合上次寫的導出Excel方法,這次上頭要求我將列頭進行一下合並

以前的效果:

 

改進后的效果:

 

在上篇文章中寫到了Excel的導出方法,這次為了避免在生產環境中使用Office組件,服務器各種權限配置的麻煩,這次就不使用Office組件來生成Excel了。

上篇文章:Asp.net導出Excel(HTML輸出)

關鍵代碼如下圖:

 

說道這里,其實主要思路已經很明顯了。

在數據綁定結束后,重新繪制表頭替換掉原來的表頭就行了。

TableCell自定義表頭的時候是table標簽的,很方便。

 

另外發現了一個小技巧:

我使用Office Excel 2013 繪畫好表頭,然后直接復制,在Macromedia Dreamweaver 8的設計面板粘貼就可以貼上去了,然后轉到代碼頁面就可以快速得到table代碼。

最后貼上這幾句代碼:

1 gvw.HeaderRow.Cells.Clear();
2 TableCell tc = new TableCell();
3 //重新繪制表頭
4 tc.Text = "<tr> ...... </tr>";
5 gvw.HeaderRow.Cells.Add(tc);
重繪表頭

 

另外,看見博友推薦我使用NPOI.HSSF.Util組件,聽說很操作很方便。這里也推薦啦!

//- 創建 Excel
   HSSFWorkbook hssfworkbook = new HSSFWorkbook();
   //- 創建 Sheet
   var sheet = hssfworkbook.CreateSheet("淘汰選項報表");
 
   //- Sheet 里的每一個 Row
   NPOI.SS.UserModel.Row row;
   //- 創建一個“繪畫器”,這個繪畫器用於所有的圖片寫入。
   //- 請注意,是所有的圖片,不可一張圖片創建一個!否則將導致沒有圖片
   var patriarch = sheet.CreateDrawingPatriarch();
 
   //- 默認單元格的樣式以及字體,是“Excel 級”的,如果對其進行設置,將導致所有的單元格都是這些字體以及樣式
   //- 創建一個新的字體以及樣式,可以確保這些“單元格”獨立的字體與樣式。
   //- 這里是創建一個標題的樣式
   var cellFont = hssfworkbook.CreateFont();
   var cellStyle = hssfworkbook.CreateCellStyle();
 
   //- 加粗,白色前景色
   cellFont.Boldweight = (short)NPOI.SS.UserModel.FontBoldWeight.BOLD;
   cellFont.Color = NPOI.HSSF.Util.HSSFColor.WHITE.index;
 
   //- 很費解 FillForegroundColor 這個屬性,我設置了是背景色,可從字義上來說,這個似乎叫“前景色”?
   //- 更令人無語的是,還有 FillBackgroundColor 屬性。真不知道做什么的。
   cellStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.GREY_40_PERCENT.index;
   //- 這個是填充的模式,可以是網格、花式等。如果需要填充單色,請使用:SOLID_FOREGROUND
   cellStyle.FillPattern = NPOI.SS.UserModel.FillPatternType.SOLID_FOREGROUND;
   //- 設置這個樣式的字體,如果沒有設置,將與所有單元格擁有共同字體!
   cellStyle.SetFont(cellFont);
 
   for(int i = 0 ; i <= gridView1.RowCount ; i++)
   {//- 遍歷行 這是 GridControl 控件的 GridView,i <= gridView1.RowCount的原因是首行我們設置為 標題行
 
       row = sheet.CreateRow(i);
       foreach(GridColumn column in gridView1.Columns)
       {
           //- 確保只需要顯示的列
           if(column.Visible)
           {
               //- 創建當前 row 指定列索引的 cell
               NPOI.SS.UserModel.Cell cell = row.CreateCell(column.VisibleIndex);
               //- 標題行
               if(i == 0)
               {
                   row.HeightInPoints = 50f;           //- 設置行高  row.Height 需要 乘以 20
                   cell.SetCellValue(column.Caption); ; //-設置單元格內容
                   cell.CellStyle = cellStyle;         //- 設置單元格的獨立樣式
               }
               else
               {
                   row.HeightInPoints = 100f;          // 設置行高  row.Height 需要 乘以 20
                   object value = gridView1.GetRowCellValue(i - 1, column);
 
                   //- 如果是一個圖片
                   if(value != null && value.GetType() == typeof(byte[]))
                   {
                       sheet.SetColumnWidth(column.VisibleIndex, 50 * 256);//- 設置列寬,需要 乘以 256
 
                       //- 插入圖片到 Excel,並返回一個圖片的標識
                       var pictureIdx = hssfworkbook.AddPicture((byte[])value, NPOI.SS.UserModel.PictureType.JPEG);
 
                       //- 創建圖片的位置
                       var anchor = new HSSFClientAnchor(
                           0, 0,                               //- 上左 到 上右 的位置,是基於下面的行列位置
                           0, 0,                               //- 下左 到 下右 的位置,是基於下面的行列位置
                           column.VisibleIndex, i,
                           column.VisibleIndex + 1, i + 1);
                       //- 圖片輸出的位置這么計算的:
                       //- 假設我們要將圖片放置於第 5(E) 列的第 2 行 
                       //- 對應索引為是 4 : 1 (默認位置)
                       //- 放置的位置就等於(默認位置)到(默認位置各自加上一行、一列)
 
 
                       patriarch.CreatePicture(anchor, pictureIdx);//- 使用繪畫器繪畫圖片
                   }
                   else
                   {
                       cell.SetCellValue(value.ToStringOrEmpty());
                   }
               }
               //- 居中
               cell.CellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.CENTER;
               cell.CellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.CENTER;
 
               //- 細邊緣
               cell.CellStyle.BorderBottom = NPOI.SS.UserModel.CellBorderType.THIN;
               cell.CellStyle.BorderLeft = NPOI.SS.UserModel.CellBorderType.THIN;
               cell.CellStyle.BorderRight = NPOI.SS.UserModel.CellBorderType.THIN;
               cell.CellStyle.BorderTop = NPOI.SS.UserModel.CellBorderType.THIN;
 
               cell.CellStyle.BottomBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
               cell.CellStyle.LeftBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
               cell.CellStyle.RightBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
               cell.CellStyle.TopBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
           }
       }
 
   }
 
   FileStream file = new FileStream(fileName, FileMode.Create);
   hssfworkbook.Write(file);//- 保存
   file.Close();
NPOI.HSSF.Util組件使用方法(轉載)

 

新增(推薦)

通過模板(NPOI最新版)導出原生的Excel文件,並且支持excel內置函數。

NPOI:通過Nuget直接獲取最新版

數據源:List泛型集合

看上圖的模板,我在第三行定義了數據庫的字段名,然后隱藏,在遍歷過程中,通過這些名字來確定位置。即可正確導出數據。

幫助類:

 1 public class ExcelHelper {
 2 
 3         /// <summary>
 4         /// 利用模板,導出到Excel
 5         /// </summary>
 6         /// <param name="dataList"></param>
 7         /// <param name="strFileName">生成的文件路徑、名稱</param>
 8         /// <param name="strTemplateFileName">模板的文件路徑、名稱</param>
 9         /// <param name="titleName">表頭名稱</param>
10         public static void ExportExcelForDtByNpoi<T>(List<T> dataList, string strFileName, string strTemplateFileName, string titleName) where T : class {
11             HttpResponse response = HttpContext.Current.Response;
12             try {
13                 using (MemoryStream ms = ExportExcelForDtByNpoi<T>(dataList, strTemplateFileName, titleName)) {
14                     byte[] data = ms.ToArray();
15                     response.Clear();
16                     response.Charset = "UTF-8";
17                     response.ContentType = "application/vnd-excel"; //"application/vnd.ms-excel";
18                     HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=" + strFileName));
19                     HttpContext.Current.Response.BinaryWrite(data);
20                 }
21             }
22             catch (Exception e) {
23                 response.Write($@"<h1>導出出現錯誤!</h1>
24 錯誤詳情:
25 {e.Message}");
26             }
27 
28         }
29 
30         /// <summary>
31         /// 利用模板,導出到Excel
32         /// </summary>
33         /// <param name="dataList">DataTable</param>
34         /// <param name="strTemplateFileName">模板的文件路徑、名稱</param>
35         /// <param name="titleName">表頭名稱</param>
36         /// <returns></returns>
37         private static MemoryStream ExportExcelForDtByNpoi<T>(
38             List<T> dataList,
39             string strTemplateFileName,
40             string titleName) where T : class {
41             FileStream file = new FileStream(strTemplateFileName, FileMode.Open, FileAccess.Read);//讀入excel模板
42             HSSFWorkbook workbook = new HSSFWorkbook(file);
43             string sheetName = "Sheet1";
44             ISheet sheet = workbook.GetSheet(sheetName);
45 
46             #region 表頭
47             //IRow headerRow = sheet.GetRow(0);
48             //ICell headerCell = headerRow.GetCell(0);
49             //headerCell.SetCellValue(titleName);
50             #endregion
51 
52             Type type = typeof(T);
53             PropertyInfo[] pis = type.GetProperties();
54             var piIndex = 0;
55             int rowIndex = 3;           //起始行
56             IRow tag = sheet.GetRow(2); //標簽
57             foreach (T data in dataList) {
58                 IRow dataRow = sheet.CreateRow(rowIndex);
59                 while (piIndex < pis.Length) {
60                     try {
61                         var tagValue = tag.GetCell(piIndex).StringCellValue;
62                         var propertyInfo = data.GetType().GetProperty(tagValue).GetValue(data, null).ToString();
63                         dataRow.CreateCell(piIndex).SetCellValue(propertyInfo);
64                     }
65                     catch (Exception e) {
66                         dataRow.CreateCell(piIndex).SetCellValue("");
67                     }
68                     piIndex++;
69                 }
70                 piIndex = 0;
71                 rowIndex++;
72             }
73 
74             // 格式化當前sheet,用於數據total計算
75             sheet.ForceFormulaRecalculation = true;
76             using (MemoryStream ms = new MemoryStream()) {
77                 workbook.Write(ms);
78                 ms.Flush();
79                 ms.Position = 0;
80                 sheet = null;
81                 workbook = null;
82                 //sheet.Dispose();
83                 //workbook.Dispose();//一般只用寫這一個就OK了,他會遍歷並釋放所有資源,但當前版本有問題所以只釋放sheet
84                 return ms;
85             }
86         }
87 
88     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM