1.模板将各列的字体和单元格格式等都定义完成后。
2.利用NPOI2.0.1.DLL操作方法,读取模板→添加数据→增加单元格边框→另保存为。
问题出现了.
1 private void NPOI_SetExcel(string filename, DataTable dt) 2 { 3 FileStream file = new FileStream(@"..\..\Template/" + filename + ".xls", FileMode.Open, FileAccess.Read); 4 HSSFWorkbook hssfworkbook = new HSSFWorkbook(file); 5 file.Close(); 6 ISheet sheet1 = null; 7 8 9 #region 发料单 10 if (filename == "material issue report") 11 { 12 13 sheet1 = hssfworkbook.GetSheet("Sheet1"); 14 HSSFRow row = null; 15 HSSFCell cell = null; 16 //单元格边框样式 17 HSSFCellStyle style = hssfworkbook.CreateCellStyle() as HSSFCellStyle; 18 style.BorderBottom = NPOI.SS.UserModel.BorderStyle.THIN; 19 style.BorderLeft = NPOI.SS.UserModel.BorderStyle.THIN; 20 style.BorderRight = NPOI.SS.UserModel.BorderStyle.THIN; 21 style.BorderTop = NPOI.SS.UserModel.BorderStyle.THIN; 22 //单元格字体 23 //HSSFFont font = hssfworkbook.CreateFont() as HSSFFont; 24 //style.SetFont(font); 25 //font.FontName = "宋体"; 26 //font.FontHeightInPoints = 8; 27 //单元格格式 28 //HSSFDataFormat format = (HSSFDataFormat)hssfworkbook.CreateDataFormat(); 29 //string[] arr = new string[16] { "0", "0", "0", "General", "General", "#,##0.00", "#,##0.00", "#,##0.00", "General", "0", "General", "yyyy-MM-dd", "0", "General", "#,##0.00", "General" }; 30 #region 填充数据 31 for (int x = 0; x < dt.Rows.Count; x++) 32 { 33 if (sheet1.GetRow(x + 7) == null) 34 { 35 sheet1.CreateRow(x + 7); 36 } 37 for (int y = 0; y < dt.Columns.Count - 1; y++) 38 { 39 if (y == 0) 40 { 41 sheet1.GetRow(x + 7).CreateCell(y).SetCellFormula("row()-7"); 42 } 43 else if (y == 1) 44 { 45 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 46 } 47 else if (y == 2) 48 { 49 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 50 } 51 else if (y == 9) 52 { 53 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 54 } 55 else 56 { 57 switch (dt.Columns[y].DataType.ToString()) 58 { 59 case "System.String"://字符串类型 60 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(dt.Rows[x][y].ToString()); 61 break; 62 case "System.DateTime"://日期类型 63 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(DateTime.Parse(dt.Rows[x][y].ToString()).ToString("yyyy-MM-dd")); 64 break; 65 case "System.Int16"://整型 66 case "System.Int32": 67 case "System.Int64": 68 case "System.Byte": 69 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 70 break; 71 case "System.Decimal"://浮点型 72 case "System.Double": 73 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(double.Parse(dt.Rows[x][y].ToString())); 74 break; 75 case "System.DBNull"://空值处理 76 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(""); 77 break; 78 default: 79 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(""); 80 break; 81 } 82 } 83 row = sheet1.GetRow(x + 7) as HSSFRow; 84 cell = row.GetCell(y) as HSSFCell; 85 //cell.CellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.THIN; 86 //style.BorderBottom = NPOI.SS.UserModel.BorderStyle.THIN; 87 cell.CellStyle = style;//填充格式的时候,会将我模板定义好的格式替换掉,可是我并没有设置单元格格式,只是设置了边框。 88 } 89 } 90 #endregion 91 } 92 #endregion 93 sheet1.ForceFormulaRecalculation = true; 94 FileStream file2 = new FileStream(@"c:\" + filename + "-" + FromDateTime.Text + "-" + ToDateTime.Text + ".xls", FileMode.Create, FileAccess.Write); 95 hssfworkbook.Write(file2); 96 file2.Close(); 97 }
请问这个问题如何解决?
问题:在填充style的时候会将我模板的格式覆盖掉(如果我只是设置style的边框,在填充的时候会覆盖掉我模板的字体)这个问题如何解决?请给予勇于回答,并给与示例。
你那是cell.CellStyle=style;这种赋值操作,你为什么会觉得它应该是追加样式呢?
正确的做法是,先取出这个cell的样式,然后操作style对象,增加边框,然后赋值回去。
你好,很感谢你的回复。确实很有帮助,但是出现了第二个问题。请看代码和截图。
1 sheet1 = hssfworkbook.GetSheet("Sheet1"); 2 HSSFRow row = null; 3 HSSFCell cell = null; 4 //单元格边框样式 5 HSSFCellStyle style = hssfworkbook.CreateCellStyle() as HSSFCellStyle; 6 #region 填充数据 7 for (int x = 0; x < dt.Rows.Count; x++) 8 { 9 if (sheet1.GetRow(x + 7) == null) 10 { 11 sheet1.CreateRow(x + 7); 12 } 13 for (int y = 0; y < dt.Columns.Count - 1; y++) 14 { 15 if (y == 0) 16 { 17 sheet1.GetRow(x + 7).CreateCell(y).SetCellFormula("row()-7"); 18 } 19 else if (y == 1) 20 { 21 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 22 } 23 else if (y == 2) 24 { 25 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 26 } 27 else if (y == 9) 28 { 29 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 30 } 31 else 32 { 33 switch (dt.Columns[y].DataType.ToString()) 34 { 35 case "System.String"://字符串类型 36 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(dt.Rows[x][y].ToString()); 37 break; 38 case "System.DateTime"://日期类型 39 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(DateTime.Parse(dt.Rows[x][y].ToString()).ToString("yyyy-MM-dd")); 40 break; 41 case "System.Int16"://整型 42 case "System.Int32": 43 case "System.Int64": 44 case "System.Byte": 45 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); 46 break; 47 case "System.Decimal"://浮点型 48 case "System.Double": 49 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(double.Parse(dt.Rows[x][y].ToString())); 50 break; 51 case "System.DBNull"://空值处理 52 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(""); 53 break; 54 default: 55 sheet1.GetRow(x + 7).CreateCell(y).SetCellValue(""); 56 break; 57 } 58 } 59 row = sheet1.GetRow(x + 7) as HSSFRow; 60 cell = row.GetCell(y) as HSSFCell; 61 style = cell.CellStyle as HSSFCellStyle; 62 style.BorderBottom = NPOI.SS.UserModel.BorderStyle.THIN; 63 style.BorderLeft = NPOI.SS.UserModel.BorderStyle.THIN; 64 style.BorderRight = NPOI.SS.UserModel.BorderStyle.THIN; 65 style.BorderTop = NPOI.SS.UserModel.BorderStyle.THIN; 66 cell.CellStyle = style; 67 } 68 } 69 }
如图所示。它将所有行的单元格都加了边框。如何解决?我在上面也设定了X行和Y列的单元格,可是无效啊。
@Setme: 似乎是你的代码逻辑问题哦~
@幻天芒: 可以帮我看一下么? 难道步骤是:
1、创建各个单元格
2、设置单元格样式
3、填充数据
要三次嵌套for循环么?
@Setme: 我看你的代码好像是对所有单元格设置边框呢,检查下条件判断~
@幻天芒:
现在的问题是,如果我将设置style格式的代码放在循环里,就会变成所有单元格都会有边框,如果放在循环外面就是正确的。
可是如果我放在循环外面,我该如何去进行style = cell.CellStyle as HSSFCellStyle;得到模板的单元格格式呢?好郁闷啊,我快被折腾死了
@Setme: 你的代码两个地方有问题:
1、sheet1.GetRow(x + 7).CreateCell(y).SetCellFormula("row()-7");
每次操作Cell,都是CreateCell,那么新创建的这个Cell肯定是没样式的,所以复制样式就没用了。(本身就是默认样式);
2、使用样式时,需要每次创建一个新的。
参考代码:
if (sheet1.GetRow(x + 7) == null) { sheet1.CreateRow(x + 7); } for (int y = 0; y < dt.Columns.Count - 1; y++) { ICell cell1 = sheet1.GetRow(x + 7).GetCell(y); if (y == 0) { cell1.SetCellFormula("row()-7"); } else if (y == 1) { cell1.SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); } else if (y == 2) { cell1.SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); } else if (y == 9) { cell1.SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); } else { switch (dt.Columns[y].DataType.ToString()) { case "System.String"://字符串类型 cell1.SetCellValue(dt.Rows[x][y].ToString()); break; case "System.DateTime"://日期类型 cell1.SetCellValue(DateTime.Parse(dt.Rows[x][y].ToString()).ToString("yyyy-MM-dd")); break; case "System.Int16"://整型 case "System.Int32": case "System.Int64": case "System.Byte": cell1.SetCellValue(Int64.Parse(dt.Rows[x][y].ToString())); break; case "System.Decimal"://浮点型 case "System.Double": cell1.SetCellValue(double.Parse(dt.Rows[x][y].ToString())); break; case "System.DBNull"://空值处理 cell1.SetCellValue(""); break; default: cell1.SetCellValue(""); break; } } ICellStyle style = hssfworkbook.CreateCellStyle();//创建新样式 style.CloneStyleFrom(cell1.CellStyle);//复制原本的样式 style.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; style.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; style.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; style.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; cell1.CellStyle = style;
注意红色的代码。
@幻天芒: 你好,用style.CloneStyleFrom(cell1.CellStyle)这个方法确实可以继承原始格式,太有帮助了,谢谢你。
但是又出现了一个问题,那就是单元格格式。
例如:单元格row[0][0]格式是数字,单元格row[0][1]格式是日期,单元格row[0][2]格式是"#,##0.00".
现在的问题是,我用了style.CloneStyleFrom(cell1.CellStyle),导出excel后。
所有的单元格的格式都变成了"#,##0.00",他将所有单元格格式都替换成了最后一个,这又是为什么呢?如何解决啊?
@Setme: 你再检查下代码,我测试的时候没有遇到这个问题。
@幻天芒: 你好,天芒兄。我现在才理解你说的每次创建新单元格的时候要创建新的CellStyle.
但是我的数据有几千条。当我为每个单元格都创建新的cellstyle的时候会报4000异常(单元格样式不能超过4000个,感觉是作者故意限定的。不会要交钱后才能用吧?),你那里会报这个异常吗?
@Setme: 没测试这么大的数据,这个插件是开源的,应该不会是作者故意限制的,可能Excel有这个限制吧。我晚上测试下创建很多CellStyle,是否会出错。
@幻天芒: 好的,谢谢你啊
@Setme: 客气了~
0-0这问题还卡在啊
模板的用法不对
如果有要新生成的行和列,那么我们也要对新的行和列的样式进行设置,怎么设置样式那是你自己考虑的问题了
如果新生成的行和列是在原来的模板的固定的数据填充区域,并且超过了填充区域范围,样式也会被覆盖掉,因为你是相当于新生成数据填充区域
参考http://www.cnblogs.com/yzb305070/archive/2012/06/23/2483433.html
style = cell.CellStyle as HSSFCellStyle; style.BorderBottom = NPOI.SS.UserModel.BorderStyle.THIN; style.BorderLeft = NPOI.SS.UserModel.BorderStyle.THIN; style.BorderRight = NPOI.SS.UserModel.BorderStyle.THIN; style.BorderTop = NPOI.SS.UserModel.BorderStyle.THIN; cell.CellStyle = style;
现在的问题是,如果我将设置style格式的代码放在循环里,就会变成所有单元格都会有边框,如果放在循环外面就是正确的。
可是如果我放在循环外面,我该如何去进行style = cell.CellStyle as HSSFCellStyle;得到模板的单元格格式呢?好郁闷啊,我快被折腾死了
@澜紫癜青