首先,我先说明我的需求:
我需要这个样子的模板。6到8行空着,是为了方便填充数据,其实只需要第6行这一行就好,当做模板复制。有多少行数据,我就会在sheet中插入多少行。
在做的过程中,发现饼图并不会随着插入的行而位置向下移。也就是说,图中饼图的位置是12行到27行,当我插入40行数据时,饼图的位置,还是在12行到27行。
插入行的方法,将在下一节提到。
因为我用的是NPOI的方法,查了很多资料,发现目前NPOI不支持对图的捕捉和设置。所以,迫不得已,只能采用笨方法,那就是预先设置好足够的行数,例如1000行,然后将数据填充进去,将多的数据隐藏掉。
//隐藏多余行 for (int i = 5 + count * 100 + dtDay.Rows.Count; i < 77 + count * 100; i++) { IRow dataRowD = unionSheet.GetRow(i);//获取行 //将行的高度设为0,隐藏起来 dataRowD.Height = 0; dataRowD.ZeroHeight = true; //sheet.RemoveRow(dataRowD); }
Excel中,每个单元格都有可能会被计算,所以我们在填充数据的时候,要先知道数据的类型,然后将数据类型的类型转化一下,再用SetCellValue函数,将数值填充进去。
//这里有个for循环,循环获取dtDay的每个值,然后判断类型再填充进去 switch (dtDay.Columns[j].DataType.ToString()) { case "System.String"://字符串类型 unionCell.SetCellValue(drValue); break; case "System.DateTime"://日期类型 DateTime dateV; DateTime.TryParse(drValue, out dateV); unionCell.SetCellValue(dateV); break; case "System.Boolean"://布尔型 bool boolV = false; bool.TryParse(drValue, out boolV); unionCell.SetCellValue(boolV); break; case "System.Int16"://整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; int.TryParse(drValue, out intV); unionCell.SetCellValue(intV); break; case "System.Decimal"://浮点型 case "System.Double": double doubV = 0; double.TryParse(drValue, out doubV); unionCell.SetCellValue(doubV); break; case "System.DBNull"://空值处理 unionCell.SetCellValue(""); break; default: unionCell.SetCellValue(""); break; }
最后,有个需要注意的地方,在填充好数据后,准备写入Excel前,我们要先执行一下下面的语句,用来使模板中计算公式生效。
// 格式化当前sheet,用于数据计算
UnionBook.SetForceFormulaRecalculation(true);