编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

asp.net下NPOI生成Excel使用心得

wxchong 2024-06-22 21:09:54 开源技术 10 ℃ 0 评论


之前一直是用sql文查询数据完了手动粘贴在Excel文件里,虽然也用不了多少时间,但对于我这种懒人来说确实比较麻烦,于是乎就着手于将这部分工作交由代码完成,我们只用动动手指点两个按钮便可完成,何乐而不为呢?

本来想用Spire来着,之前也用过效果不错。看了看项目里已经引用NPOI了,那就勉为其难重新学习一下吧,毕竟一个项目里有两个导出库多少有点不合适。

表格填充

表格填充就比较简单了

1. 创建一个文件薄 var wb = new XSSFWorkbook();

2. 创建表单var sheet = wb.CreateSheet("xxxx");

3. 创建行var row= sheet.CreateRow(0);

4. 创建单元格var cell = row.CreateCell(0);

可以通过row.Height = 400 来配置单元格的行高;

sheet下面有sheet.SetColumnWidth(0, 4000)方法可以配置列宽,第一个参数是列号,第二个参数是列宽。

cell的话可以通过cell.CellStyle属性自定义每个单元格的样式,style下有很多方法可以用,也可以配置font调整单元格字体,format调整单元格显示格式。cell.SetCellValue()来设置单元格的值。

style.Alignment = HorizontalAlignment.Left;//文字水平对齐方式
style.VerticalAlignment = VerticalAlignment.Center;//文字垂直对齐方式

//设置边框
style.BorderBottom = BorderStyle.Thin;
style.BorderLeft = BorderStyle.Thin;
style.BorderRight = BorderStyle.Thin;
style.BorderTop = BorderStyle.Thin;
style.WrapText = true;自动换行

style.FillForegroundColor = HSSFColor.White.Index;设置单元格背景色
style.FillPattern = FillPattern.SolidForeground;设置背景颜色时一定要与这个方法一起使用,否则没有效果

//字体
var font= wb.CreateFont();
font.FontName = "楷体";
font.Color = HSSFColor.Red.Index;//字体颜色
font.Boldweight = (short)FontBoldWeight.Normal;//字体加粗样式
font.FontHeight = 200;
style.SetFont(font);//样式里的字体设置具体的字体样式

var dataFormatCustom = wb.CreateDataFormat();
dateStyle.DataFormat = dataFormatCustom.GetFormat("yyyy-MM-dd HH:mm:ss");

还有一个合并单元格的方法,四个参数分别是起始行号,结束行号,起始列号,结束列号。

sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(x1, x2, y1, y2));

生成图表

生成图表个人感觉不是特别好用,有些spire支持的属性在这边不能修改,不知道是不是我用的NPOI版本太低了,我先把功能做好,这个等以后有空了再研究。

图表还是再sheet下生成的,首先拿到绘图工具,

var drawing = sheet.CreateDrawingPatriarch();

然后通过绘图工具把锚点创建出来,大概意思就相当于是你这个图表的四个角在那个位置。前面四个参数是偏移量,我这个需求不涉及这个我就填0了,后面4个参数分别代表开始的列号,开始的行号,结束的列号,结束的行号。
var anchor = drawing.CreateAnchor(0, 0, 0, 0, col1, row1, col2,row2)

锚点创建好后,还是通过绘图工具把图表创建出来。

var chart = drawing.CreateChart(anchor);

var chart = drawing.CreateChart(anchor) as XSSFChart;
//生成图例,就是图表中每一根线条代表了什么意思
var legend = chart.GetOrCreateLegend();
//图例位置
legend.Position = LegendPosition.Top;

//图表,生成图表的方法有两个泛型,第一个泛型代表的是标题列的数据类型,第二个轴代表的是数据列的数据类型。
var data = chart.ChartDataFactory.CreateLineChartData<string, double>();

// X轴Y轴.,x轴可以调整为在图表的上方或下方,Y轴可以调整为在图表的左边或右边
var bottomAxis = chart.ChartAxisFactory.CreateCategoryAxis(AxisPosition.Bottom) as XSSFCategoryAxis;
IValueAxis leftAxis = chart.ChartAxisFactory.CreateValueAxis(AxisPosition.Left);

//通过设置AxisCrossBetween.Between可以解决图表图表坐标轴位置在刻度线上还是在刻度线之间的问题。
leftAxis.SetCrossBetween(AxisCrossBetween.Between);

//标题列和数据列也是通过range的方法从sheet里面获取的,这跟合并单元格的方法差不多。标题列可以是字符串也可以选择数字
IChartDataSource<string> xs = DataSources.FromStringCellRange(sheet, new CellRangeAddress(firstRow, endRow, titleCol, titleCol))

//数据列泛型必须是int,double等数字类型,而且只能通过FromNumericCellRange方法获取
IChartDataSource<double> ys1 = DataSources.FromNumericCellRange(sheet, new CellRangeAddress(firstRow, endRow, dataCol, dataCol));

//数据系列,每个图表里面可以加多个系列,可以显示多根线条,需要通过serial.SetTitle(title);的方法配置每个系列的名称,图例也会相应的增加。
var serial = data.AddSeries(xs, ys1);
serial.SetTitle(title);
chart.Plot(data, bottomAxis, leftAxis);

数据列需要注意的是在cell.SetCellValue()需要传int 或double的值进去,不可以直接传string的值,不然他内部不会给你自动解析,图表就显示不出来。

Plot方法调完图表就创建好了,创建出来大概像是这样的。


柱状图跟折线图比较类似,唯一一点区别就是用CreateBarChartData来创建

var data = chart.ChartDataFactory.CreateBarChartData<string, double>();

饼图

这个NPOI貌似并不支持,为了完成目标,只能用代码生成图片替代了,虽然不能编辑,但也像那么回事。

private static Bitmap GetPieGraphic(int width, int height, string name, float[] data, string[] titles, Color[] colors){

string familyName = "Arial";

//根据宽高生成Bitmap
Bitmap objbitmap = new Bitmap(width, height);
Graphics objgraphics = Graphics.FromImage(objbitmap);
objgraphics.Clear(Color.White);

//一些关于图片质量的设置
objgraphics.SmoothingMode = SmoothingMode.HighQuality;
objgraphics.CompositingQuality = CompositingQuality.HighQuality;
objgraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
objgraphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
//定位饼图相对于图片的位置,前两位为起始的x,y坐标,后两位为饼图的宽高
Rectangle rect = new Rectangle(width / 5, height / 5, 1300, 1500);
float currentdegree = 0.0f;
float Total = data.Sum();

//这便是绘制饼图的标题,PointF为字符串的位置x,y
objgraphics.DrawString(name, new Font(familyName, 40), Brushes.Black, new PointF(800, 100));
for (int i = 0; i < data.Length; i++)
{
Color temC = colors[i];
SolidBrush brush = new SolidBrush(temC);
objgraphics.FillPie(brush, rect, currentdegree, Convert.ToSingle(data[i] / Total * 360));
currentdegree += Convert.ToSingle(data[i] / Total * 360);
}
//放置图例 ,第一个图例的起始位置x,y
PointF basePoint = new PointF(32, 64);
//图例色块的大小
SizeF theSize = new SizeF(80, 48);
//第一个色块的说明文字的位置

PointF textPoint = new PointF(basePoint.X + 120, basePoint.Y);
for (int j = 0; j < data.Length; j++)
{
RectangleF baseRectangle = new RectangleF(basePoint, theSize);
//画代表色块

objgraphics.FillRectangle(new SolidBrush(colors[j]), baseRectangle);
var temstr = string.Format("{0}%", (data[j] / Total * 100).ToString("#0.00"));
objgraphics.DrawString(titles[j] + " " + temstr, new Font(familyName, 24), Brushes.Black, textPoint);
basePoint.Y += 64;
textPoint.Y += 64;
}
return objbitmap;

}

生成出来的饼图大概长这样,颜色,位置什么的可以自己diy,这个就无需多言了。

到这里基本需求就实现好了,但还有下面几个问题没有解决,

1. 折线图是带弧度的,不知道Excel里面这个平滑线的属性如何去掉


2. NPOI里面不能给图表设置标题,看了chart里面有一个title字段,但是是只读字段,不知道如何修改。

如果有哪位朋友恰巧研究过这2个问题,拜托一定留言,感谢了。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表