自ExcelUtility类推出以来,经过项目中的实际使用与不断完善,现在又做了许多的优化并增加了许多的功能,本篇不再讲述原理,直接贴出示例代码以及相关的模板、结果图,以便大家快速掌握,另外这些示例说明我也已同步到GIT中,大家可以下载与学习,不足之处,
自ExcelUtility类推出以来,经过项目中的实际使用与不断完善,现在又做了许多的优化并增加了许多的功能,本篇不再讲述原理,直接贴出示例代码以及相关的模板、结果图,以便大家快速掌握,另外这些示例说明我也已同步到GIT中,大家可以下载与学习,不足之处,敬请见谅,谢谢!
一、ExcelUtility类库操作说明(模板导出示例)
1.
/// <summary> /// 测试方法:测试依据模板+DataTable来生成EXCEL /// </summary> [TestMethod] public void TestExportToExcelWithTemplateByDataTable() { DataTable dt = GetDataTable();//获取数据 string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/excel.xlsx"; //获得EXCEL模板路径 SheetFormatterContainer formatterContainers = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 PartFormatterBuilder partFormatterBuilder = new PartFormatterBuilder();//实例化一个局部元素格式化器 partFormatterBuilder.AddFormatter("Title", "跨越IT学员");//将模板表格中Title的值设置为跨越IT学员 formatterContainers.AppendFormatterBuilder(partFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 CellFormatterBuilder cellFormatterBuilder = new CellFormatterBuilder();//实例化一个单元格格式化器 cellFormatterBuilder.AddFormatter("rptdate", DateTime.Today.ToString("yyyy-MM-dd HH:mm"));//将模板表格中rptdate的值设置为当前日期 formatterContainers.AppendFormatterBuilder(cellFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 //实例化一个表格格式化器,dt.Select()是将DataTable转换成DataRow[],name表示的模板表格中第一行第一个单元格要填充的数据参数名 TableFormatterBuilder<DataRow> tableFormatterBuilder = new TableFormatterBuilder<DataRow>(dt.Select(), "name"); tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<DataRow, object>>{ {"name",r=>r["Col1"]},//将模板表格中name对应DataTable中的列Col1 {"sex",r=>r["Col2"]},//将模板表格中sex对应DataTable中的列Col2 {"km",r=>r["Col3"]},//将模板表格中km对应DataTable中的列Col3 {"score",r=>r["Col4"]},//将模板表格中score对应DataTable中的列Col4 {"result",r=>r["Col5"]}//将模板表格中result对应DataTable中的列Co5 }); formatterContainers.AppendFormatterBuilder(tableFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, "table", formatterContainers); Assert.IsTrue(File.Exists(excelPath)); }
模板如下:
导出结果如下:
2.
/// <summary> /// 测试方法:测试依据模板+List来生成EXCEL /// </summary> [TestMethod] public void TestExportToExcelWithTemplateByList() { List<Student> studentList = GetStudentList();//获取数据 string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/excel.xlsx"; //获得EXCEL模板路径 SheetFormatterContainer formatterContainers = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 PartFormatterBuilder partFormatterBuilder = new PartFormatterBuilder();//实例化一个局部元素格式化器 partFormatterBuilder.AddFormatter("Title", "跨越IT学员");//将模板表格中Title的值设置为跨越IT学员 formatterContainers.AppendFormatterBuilder(partFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 CellFormatterBuilder cellFormatterBuilder = new CellFormatterBuilder();//实例化一个单元格格式化器 cellFormatterBuilder.AddFormatter("rptdate", DateTime.Today.ToString("yyyy-MM-dd HH:mm"));//将模板表格中rptdate的值设置为当前日期 formatterContainers.AppendFormatterBuilder(cellFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 //实例化一个表格格式化器,studentList本身就是可枚举的无需转换,name表示的模板表格中第一行第一个单元格要填充的数据参数名 TableFormatterBuilder<Student> tableFormatterBuilder = new TableFormatterBuilder<Student>(studentList, "name"); tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<Student, object>>{ {"name",r=>r.Name},//将模板表格中name对应Student对象中的属性Name {"sex",r=>r.Sex},//将模板表格中sex对应Student对象中的属性Sex {"km",r=>r.KM},//将模板表格中km对应Student对象中的属性KM {"score",r=>r.Score},//将模板表格中score对应Student对象中的属性Score {"result",r=>r.Result}//将模板表格中result对应Student对象中的属性Result }); formatterContainers.AppendFormatterBuilder(tableFormatterBuilder); string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, "table", formatterContainers); Assert.IsTrue(File.Exists(excelPath)); }
模板同上一个模板
导出结果如下:
3.
/// <summary> /// 测试方法:测试依据模板+DataTable来生成多表格EXCEL(注意:由于ExcelReport框架限制,目前仅支持模板文件格式为:xls) /// </summary> [TestMethod] public void TestExportToRepeaterExcelWithTemplateByDataTable() { DataTable dt = GetDataTable();//获取数据 string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/excel2.xls"; //获得EXCEL模板路径 SheetFormatterContainer formatterContainers = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 //实例化一个可重复表格格式化器,dt.Select()是将DataTable转换成DataRow[],rpt_begin表示的模板表格开始位置参数名,rpt_end表示的模板表格结束位置参数名 RepeaterFormatterBuilder<DataRow> tableFormatterBuilder = new RepeaterFormatterBuilder<DataRow>(dt.Select(), "rpt_begin", "rpt_end"); tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<DataRow, object>>{ {"sex",r=>r["Col2"]},//将模板表格中sex对应DataTable中的列Col2 {"km",r=>r["Col3"]},//将模板表格中km对应DataTable中的列Col3 {"score",r=>r["Col4"]},//将模板表格中score对应DataTable中的列Col4 {"result",r=>r["Col5"]}//将模板表格中result对应DataTable中的列Co5 }); PartFormatterBuilder<DataRow> partFormatterBuilder2 = new PartFormatterBuilder<DataRow>();//实例化一个可嵌套的局部元素格式化器 partFormatterBuilder2.AddFormatter("name", r => r["Col1"]);//将模板表格中name对应DataTable中的列Col1 tableFormatterBuilder.AppendFormatterBuilder(partFormatterBuilder2);//添加到可重复表格格式化器中,作为其子格式化器 CellFormatterBuilder<DataRow> cellFormatterBuilder = new CellFormatterBuilder<DataRow>();//实例化一个可嵌套的单元格格式化器 cellFormatterBuilder.AddFormatter("rptdate", r => DateTime.Today.ToString("yyyy-MM-dd HH:mm"));//将模板表格中rptdate的值设置为当前日期 tableFormatterBuilder.AppendFormatterBuilder(cellFormatterBuilder);//添加到可重复表格格式化器中,作为其子格式化器 formatterContainers.AppendFormatterBuilder(tableFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, "multtable", formatterContainers); Assert.IsTrue(File.Exists(excelPath)); }
模板如下:
导出结果如下:
4.
/// <summary> /// 测试方法:测试依据复杂模板(含固定表格,可重复表格)+DataTable来生成EXCEL (注意:由于ExcelReport框架限制,目前仅支持模板文件格式为:xls) /// </summary> [TestMethod] public void TestExportToExcelWithTemplateByList2() { var schoolLevelList = SchoolLevel.GetList(); var classList = ClassInfo.GetList(); string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/mb.xls"; //获得EXCEL模板路径 SheetFormatterContainer formatterContainers = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 PartFormatterBuilder partFormatterBuilder = new PartFormatterBuilder(); partFormatterBuilder.AddFormatter("school", "跨越小学"); formatterContainers.AppendFormatterBuilder(partFormatterBuilder); TableFormatterBuilder<SchoolLevel> tableFormatterBuilder = new TableFormatterBuilder<SchoolLevel>(schoolLevelList, "lv");//实例化一个表格格式化器 tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<SchoolLevel, object>> { {"lv",r=>r.LevelName}, //模板参数与数据源SchoolLevel属性对应关系,下同 {"clscount",r=>r.ClassCount}, {"lvmaster",r=>r.Master} }); formatterContainers.AppendFormatterBuilder(tableFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 RepeaterFormatterBuilder<ClassInfo> repeaterFormatterBuilder = new RepeaterFormatterBuilder<ClassInfo>(classList, "lv_begin", "lv_end");//实例化一个可重复表格格式化器 repeaterFormatterBuilder.AddFormatters(new Dictionary<string, Func<ClassInfo, object>> { {"class",r=>r.ClassName}, //模板参数与数据源ClassInfo属性对应关系,下同 {"stucount",r=>r.StudentCount}, {"clsmaster",r=>r.Master}, {"lvitem",r=>r.LevelName} }); formatterContainers.AppendFormatterBuilder(repeaterFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, "school", formatterContainers); Assert.IsTrue(File.Exists(excelPath)); }
模板如下:
导出结果如下:
5.
/// <summary> /// 测试方法:测试依据复杂模板(含固定表格,可重复表格中嵌套表格)+DataTable来生成EXCEL (注意:由于ExcelReport框架限制,目前仅支持模板文件格式为:xls) /// </summary> [TestMethod] public void TestExportToExcelWithTemplateByList3() { var schoolLevelList = SchoolLevel.GetList(); var classList = ClassInfo.GetListWithLevels(); string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/mb1.xls"; //获得EXCEL模板路径 SheetFormatterContainer formatterContainers = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 PartFormatterBuilder partFormatterBuilder = new PartFormatterBuilder(); partFormatterBuilder.AddFormatter("school", "跨越小学"); formatterContainers.AppendFormatterBuilder(partFormatterBuilder); TableFormatterBuilder<SchoolLevel> tableFormatterBuilder = new TableFormatterBuilder<SchoolLevel>(schoolLevelList, "lv");//实例化一个表格格式化器 tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<SchoolLevel, object>> { {"lv",r=>r.LevelName}, //模板参数与数据源SchoolLevel属性对应关系,下同 {"clscount",r=>r.ClassCount}, {"lvmaster",r=>r.Master} }); formatterContainers.AppendFormatterBuilder(tableFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 RepeaterFormatterBuilder<KeyValuePair<string, List<ClassInfo>>> repeaterFormatterBuilder = new RepeaterFormatterBuilder<KeyValuePair<string, List<ClassInfo>>>(classList, "lv_begin", "lv_end"); repeaterFormatterBuilder.AddFormatter("lvitem",r=>r.Key); TableFormatterBuilder<KeyValuePair<string, List<ClassInfo>>,ClassInfo> tableFormatterBuilder2=new TableFormatterBuilder<KeyValuePair<string, List<ClassInfo>>,ClassInfo>(r=>r.Value,"class"); tableFormatterBuilder2.AddFormatter("class",r=>r.ClassName); tableFormatterBuilder2.AddFormatter("stucount",r=>r.StudentCount); tableFormatterBuilder2.AddFormatter("clsmaster",r=>r.Master); repeaterFormatterBuilder.AppendFormatterBuilder(tableFormatterBuilder2); formatterContainers.AppendFormatterBuilder(repeaterFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, "school", formatterContainers); Assert.IsTrue(File.Exists(excelPath)); }
模板如下:
导出结果如下:
6.
/// <summary> /// 测试方法:测试依据复杂模板(多工作薄,且含固定表格,可重复表格)+DataSet来生成EXCEL,只支持XLS /// </summary> [TestMethod] public void TestExportToExcelWithTemplateByDataSet() { var ds = GetDataSet(); string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/mb2.xls"; //获得EXCEL模板路径 Dictionary<string, SheetFormatterContainer> formatterContainerDic = new Dictionary<string, SheetFormatterContainer>(); //实例化一个模板数据格式化容器数组,包含两个SheetFormatterContainer用于格式化两个工作薄 #region 创建第一个工作薄格式化容器,并设置相关参数对应关系 SheetFormatterContainer formatterContainer1 = new SheetFormatterContainer(); PartFormatterBuilder partFormatterBuilder = new PartFormatterBuilder(); partFormatterBuilder.AddFormatter("school", "跨越小学"); formatterContainer1.AppendFormatterBuilder(partFormatterBuilder); TableFormatterBuilder<DataRow> tableFormatterBuilder = new TableFormatterBuilder<DataRow>(ds.Tables[0].Select(), "lv");//实例化一个表格格式化器 tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<DataRow, object>> { {"lv",r=>r["Col1"]}, //模板参数与数据源DataTable属性对应关系,下同 {"clscount",r=>r["Col2"]}, {"lvmaster",r=>r["Col3"]} }); formatterContainer1.AppendFormatterBuilder(tableFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 RepeaterFormatterBuilder<DataRow> repeaterFormatterBuilder = new RepeaterFormatterBuilder<DataRow>(ds.Tables[1].Select(), "lv_begin", "lv_end");//实例化一个可重复表格格式化器 repeaterFormatterBuilder.AddFormatters(new Dictionary<string, Func<DataRow, object>> { {"class",r=>r["Col1"]}, //模板参数与数据源ClassInfo属性对应关系,下同 {"stucount",r=>r["Col2"]}, {"clsmaster",r=>r["Col3"]}, {"lvitem",r=>r["Col4"]} }); formatterContainer1.AppendFormatterBuilder(repeaterFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 formatterContainerDic.Add("table1", formatterContainer1);//添加到工作薄格式容器数组中,注意此处的Key值为模板上工作薄的名称,此处即为:table1 #endregion #region 创建第二个工作薄格式化容器,并设置相关参数对应关系 SheetFormatterContainer formatterContainer2 = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 PartFormatterBuilder partFormatterBuilder2 = new PartFormatterBuilder();//实例化一个局部元素格式化器 partFormatterBuilder2.AddFormatter("Title", "跨越IT学员");//将模板表格中Title的值设置为跨越IT学员 formatterContainer2.AppendFormatterBuilder(partFormatterBuilder2);//添加到工作薄格式容器中,注意只有添加进去了才会生效 CellFormatterBuilder cellFormatterBuilder2 = new CellFormatterBuilder();//实例化一个单元格格式化器 cellFormatterBuilder2.AddFormatter("rptdate", DateTime.Today.ToString("yyyy-MM-dd HH:mm"));//将模板表格中rptdate的值设置为当前日期 formatterContainer2.AppendFormatterBuilder(cellFormatterBuilder2);//添加到工作薄格式容器中,注意只有添加进去了才会生效 //实例化一个表格格式化器,dt.Select()是将DataTable转换成DataRow[],name表示的模板表格中第一行第一个单元格要填充的数据参数名 TableFormatterBuilder<DataRow> tableFormatterBuilder2 = new TableFormatterBuilder<DataRow>(ds.Tables[2].Select(), "name"); tableFormatterBuilder2.AddFormatters(new Dictionary<string, Func<DataRow, object>>{ {"name",r=>r["Col1"]},//将模板表格中name对应DataTable中的列Col1 {"sex",r=>r["Col2"]},//将模板表格中sex对应DataTable中的列Col2 {"km",r=>r["Col3"]},//将模板表格中km对应DataTable中的列Col3 {"score",r=>r["Col4"]},//将模板表格中score对应DataTable中的列Col4 {"result",r=>r["Col5"]}//将模板表格中result对应DataTable中的列Co5 }); formatterContainer2.AppendFormatterBuilder(tableFormatterBuilder2);//添加到工作薄格式容器中,注意只有添加进去了才会生效 formatterContainerDic.Add("table2", formatterContainer2);//添加到工作薄格式容器数组中,注意此处的Key值为模板上工作薄的名称,此处即为:table2 #endregion string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, formatterContainerDic); Assert.IsTrue(File.Exists(excelPath)); }
模板如下:
导出结果如下:
二、ExcelUtility类库操作说明(嵌入图片示例)
一、 制作模板(含图片)
1. 制作模板的文件格式需为兼容格式,即:xls或xlt;
2. 模板变量(或称为占位符)定义与之前相同,即:$[变量名];
3. 图片变量定义如下:
a) 绘制一个图形,图形形状尽可能的与要显示的图片相同,比如:印章,则可绘制一个圆形;
b) 图形必需是透明背景,边框可要可不要,建议留着,这样后续调整比较方便,如下图中的蓝色透明背景圆形:
c) 图形大小尽可能与要显示的图片大小相同,如下图示:
由于EXCEL上大小默认采用厘米,而图片一般采用像素,所以需要自己换算一下像素对应的厘米数(也可将EXCEL计算单位设为像素,方法自行网上查找);也可网上下载单位转换工具
另外图形属性建议设置成如下图:
温馨提示:图形形状、属性若未设置一般不影响导出效果,但不排除其它异常情况,图形大小是一定要设置,且尽可能与要显示图形大小(高、宽)相同,否则有可能造成导出变形
代码示例:
/// <summary> /// 测试方法:测试依据模板+DataTable+图片来生成包含图片的EXCEL,只支持XLS /// </summary> [TestMethod] public void TestInsertPic() { DataTable dt = GetDataTable();//获取数据 string templateFilePath = AppDomain.CurrentDomain.BaseDirectory + "/excel.xls"; //获得EXCEL模板路径 SheetFormatterContainer formatterContainers = new SheetFormatterContainer(); //实例化一个模板数据格式化容器 PartFormatterBuilder partFormatterBuilder = new PartFormatterBuilder();//实例化一个局部元素格式化器 partFormatterBuilder.AddFormatter("Title", "跨越IT学员");//将模板表格中Title的值设置为跨越IT学员d formatterContainers.AppendFormatterBuilder(partFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 CellFormatterBuilder cellFormatterBuilder = new CellFormatterBuilder();//实例化一个单元格格式化器 cellFormatterBuilder.AddFormatter("rptdate", DateTime.Today.ToString("yyyy-MM-dd HH:mm"));//将模板表格中rptdate的值设置为当前日期 formatterContainers.AppendFormatterBuilder(cellFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 //实例化一个表格格式化器,dt.Select()是将DataTable转换成DataRow[],name表示的模板表格中第一行第一个单元格要填充的数据参数名 TableFormatterBuilder<DataRow> tableFormatterBuilder = new TableFormatterBuilder<DataRow>(dt.Select(), "name"); tableFormatterBuilder.AddFormatters(new Dictionary<string, Func<DataRow, object>>{ {"name",r=>r["Col1"]},//将模板表格中name对应DataTable中的列Col1 {"sex",r=>r["Col2"]},//将模板表格中sex对应DataTable中的列Col2 {"km",r=>r["Col3"]},//将模板表格中km对应DataTable中的列Col3 {"score",r=>r["Col4"]},//将模板表格中score对应DataTable中的列Col4 {"result",r=>r["Col5"]}//将模板表格中result对应DataTable中的列Co5 }); formatterContainers.AppendFormatterBuilder(tableFormatterBuilder);//添加到工作薄格式容器中,注意只有添加进去了才会生效 string picPath = AppDomain.CurrentDomain.BaseDirectory + "\\tz.png";//图片路径 PictureWithShapeFormatterBuilder pictureBuilder = new PictureWithShapeFormatterBuilder();//实例化一个图片关联图形格式化器 //pictureBuilder.AddFormatter(picPath);//当sheet中只有一个图形时,我们可以省略指定区域,那么默认就是把整个工作薄区域当成一个寻找图形区域,若sheet中包含多个,则应指定区域,替换成如下语句 pictureBuilder.AddFormatter(picPath,5,60000, 0, 3, false);//第一个参数为图片路径,中间4个参数为数字型指定图形寻找的工作薄区域(行索引,列索引,索引从0开始计),最后一个为是否自适应大小,一般不建议使用,除非压缩图片 formatterContainers.AppendFormatterBuilder(pictureBuilder); string excelPath = ExcelUtility.Export.ToExcelWithTemplate(templateFilePath, "table", formatterContainers); Assert.IsTrue(File.Exists(excelPath)); }
模板如下:
注意图片若需要为透明背景格式,则必需使用PNG格式,NPOI支持的图片主要格式有:PNG,JPG
导出结果如下:
温馨提示:
pictureBuilder.AddFormatter(picPath);//当sheet中只有一个图形时,我们可以省略指定区域,那么默认就是把整个工作薄区域当成一个寻找图形区域,若sheet中包含多个,则应指定区域,替换成如下语句
pictureBuilder.AddFormatter(picPath,5,60000, 0, 3, false);//第一个参数为图片路径,中间4个参数为数字型指定图形寻找的工作薄区域(行索引(起止),列索引(起止),索引从0开始计),最后一个为是否自适应大小,一般不建议使用,除非压缩图片
如果图形可能随单元格进行位置调整,那么在指定图形区域时需注意,如果图形会随单元格下移,那么结束行索引(MinRow)就需要指定一个可能的最大值或不指定,如果图形会随单元格右移,那么结束列索引(MinColumn)就需要指定一个可能的最大值或不指定,如果存在多个图形区域,则上述情况都必需给定具体值(可能的最大值),以免造成区域交叉,从而导致图片显示不正确,如下示例:
//图形可能下移,可能右移,那么将结束行设为可能最大值:60000,结束列设为可能最大值:255
pictureBuilder.AddFormatter(picPath, 5, 60000, 0, 255, false);
//此处只指定开始行与开始列,与上面差不多,但建议使用上面的用法
pictureBuilder.AddFormatter(new PictureWithShapeInfo(picPath, new SheetRange() {MinRow=5,MinColumn=0 },false));
特别说明:
1.本类库是基于NPOI+ExcelReport,所有功能凡我的类库能够实现的,NPOI与ExcelReport都可以实现,只是用法及复杂程度不同而矣,我封装的目的就是为了降低大家的学习难度,提高使用效率,免费且开源,源代码同步更新至开源社区的GIT目录中,具体地址请看我该系列之前的文章有列出,在此就不再说明。
2.上述图片关联图形显示功能我是在ExcelReport基础上增加了一个PictureWithShapeFormatter类及其相关的类:PictureWithShapeInfo、SheetRange,因没有关联GIT,所以是在本地更新的,这几个类的代码如下:
PictureWithShapeFormatter:
using NPOI.Extend; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ExcelReport { public class PictureWithShapeFormatter : ElementFormatter { PRivate PictureWithShapeInfo PictureInfo = null; public PictureWithShapeFormatter(PictureWithShapeInfo pictureInfo) { this.PictureInfo = pictureInfo; } public override void Format(SheetAdapter sheetAdapter) { var sheet = sheetAdapter.CurrentSheet; var shapes = PictureInfo.GetShapes(sheet); bool isCompatible = false; if (sheet is HSSFSheet) { isCompatible = true; } if (shapes == null || shapes.Count <= 0) { throw new Exception(string.Format("未能获取到工作薄[{0}]指定区域的图形对象列表!", sheet.SheetName)); } byte[] bytes = System.IO.File.ReadAllBytes(PictureInfo.FilePath); int pictureIdx = -1; IDrawing drawing = null; IClientAnchor anchor = null; if (isCompatible) { var shape = shapes[0] as HSSFShape; anchor = shape.Anchor as IClientAnchor; drawing = shape.Patriarch; shape.LineStyle = LineStyle.None; } else { var shape = shapes[0] as XSSFShape; anchor = shape.GetAnchor() as IClientAnchor; drawing = shape.GetDrawing(); shape.LineStyle = LineStyle.None; } pictureIdx = sheet.Workbook.AddPicture(bytes, PictureInfo.PictureType); var picture = drawing.CreatePicture(anchor, pictureIdx); if (PictureInfo.AutoSize) { picture.Resize(); } } } }
PictureWithShapeInfo、SheetRange:
using NPOI.SS.UserModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel; using NPOI.Extend; namespace ExcelReport { /// <summary> /// 图片关联图形信息 /// 作者:Zuowenjun /// </summary> public class PictureWithShapeInfo { private SheetRange _SheetRange = new SheetRange(); public string FilePath { get; set; } public PictureType PictureType { get; set; } public SheetRange ShapeRange { get { return _SheetRange; } set { if (value != null) { _SheetRange = value; } } } public bool AutoSize { get; set; } public PictureWithShapeInfo() { } public PictureWithShapeInfo(string filePath, SheetRange shapeRange = null, bool autoSize = false) { this.FilePath = filePath; this.ShapeRange = shapeRange; this.AutoSize = autoSize; this.PictureType = GetPictureType(filePath); } public List<object> GetShapes(ISheet sheet) { List<object> shapeAllList = new List<object>(); var shapeContainer = sheet.DrawingPatriarch; if (sheet is HSSFSheet) { var shapeContainerHSSF = sheet.DrawingPatriarch as HSSFShapeContainer; if (null != shapeContainer) { var shapeList = shapeContainerHSSF.Children; foreach (var shape in shapeList) { if (shape is HSSFShape && shape.Anchor is HSSFClientAnchor) { var anchor = shape.Anchor as HSSFClientAnchor; if (IsInternalOrIntersect(ShapeRange.MinRow, ShapeRange.MaxRow, ShapeRange.MinColumn, ShapeRange.MaxColumn, anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, true)) { shapeAllList.Add(shape); } } } } } else { var documentPartList = (sheet as XSSFSheet).GetRelations(); foreach (var documentPart in documentPartList) { if (documentPart is XSSFDrawing) { var drawing = (XSSFDrawing)documentPart; var shapeList = drawing.GetShapes(); foreach (var shape in shapeList) { var anchorResult = shape.GetAnchor(); if (shape is XSSFShape && anchorResult is XSSFClientAnchor) { var anchor = anchorResult as XSSFClientAnchor; if (IsInternalOrIntersect(ShapeRange.MinRow, ShapeRange.MaxRow, ShapeRange.MinColumn, ShapeRange.MaxColumn, anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, true)) { shapeAllList.Add(shape); } } } } } } return shapeAllList; } private PictureType GetPictureType(string filePath) { string ext = Path.GetExtension(filePath).ToUpper(); switch (ext) { case ".JPG": { return PictureType.JPEG; } case ".PNG": { return PictureType.PNG; } default: { return PictureType.None; } } } private bool IsInternalOrIntersect(int? rangeMinRow, int? rangeMaxRow, int? rangeMinCol, int? rangeMaxCol, int pictureMinRow, int pictureMaxRow, int pictureMinCol, int pictureMaxCol, bool onlyInternal) { int _rangeMinRow = rangeMinRow ?? pictureMinRow; int _rangeMaxRow = rangeMaxRow ?? pictureMaxRow; int _rangeMinCol = rangeMinCol ?? pictureMinCol; int _rangeMaxCol = rangeMaxCol ?? pictureMaxCol; if (onlyInternal) { return (_rangeMinRow <= pictureMinRow && _rangeMaxRow >= pictureMaxRow && _rangeMinCol <= pictureMinCol && _rangeMaxCol >= pictureMaxCol); } else { return ((Math.Abs(_rangeMaxRow - _rangeMinRow) + Math.Abs(pictureMaxRow - pictureMinRow) >= Math.Abs(_rangeMaxRow + _rangeMinRow - pictureMaxRow - pictureMinRow)) && (Math.Abs(_rangeMaxCol - _rangeMinCol) + Math.Abs(pictureMaxCol - pictureMinCol) >= Math.Abs(_rangeMaxCol + _rangeMinCol - pictureMaxCol - pictureMinCol))); } } } /// <summary> /// 工作薄区域 /// 作者:Zuowenjun /// </summary> public class SheetRange { public int? MinRow { get; set; } public int? MaxRow { get; set; } public int? MinColumn { get; set; } public int? MaxColumn { get; set; } public SheetRange() { } public SheetRange(int minRow, int maxRow, int minColumn, int maxColumn) { this.MinRow = minRow; this.MaxRow = maxRow; this.MinColumn = minColumn; this.MaxColumn = maxColumn; } public override bool Equals(object obj) { bool equalResult = false; equalResult = base.Equals(obj); if (!equalResult) { var otherSheetRange = obj as SheetRange; if (otherSheetRange != null) { equalResult = (this.MinRow <= otherSheetRange.MinRow && this.MaxRow >= otherSheetRange.MaxRow && this.MinColumn <= otherSheetRange.MinColumn && this.MaxColumn >= otherSheetRange.MaxColumn); } } return equalResult; } public override int GetHashCode() { return this.ToString().GetHashCode(); } public override string ToString() { return string.Format("MinRow:{0},MaxRow:{1},MinColumn:{2},MaxColumn:{3}", this.MinRow, this.MaxRow, this.MinColumn, this.MaxColumn); } } }
分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility 其它相关文章链接:
分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility (续篇)

夸克网盘和百度网盘都是很便利的存储工具,不少的用户们都在询问这两款软件互通吗?夸克网盘怎么分享到百度网盘?下面就让本站来为用户们来仔细的介绍一下夸克网盘的文件怎么保存到百度网盘方法吧。 夸克网盘的文件怎么保存到百度网盘方法 1、想要知道怎么把夸克网盘的文件转到百度网盘,首先在夸克网盘上下载需要保存的文件,然后打开百度网盘客户端后,选择压缩文件要保存的文件夹,双击打开该文件夹。 2、打开该文件夹后,点击窗口左上角区域的“上传”。 3、在电脑中找到需要上传的压缩文件,点击选

芒果TV拥有各种类型的电影、电视剧、综艺等资源,用户可以在其中自由的选择进行观看。芒果tv会员不仅能够看到全部的VIP剧而且还能够设置最高清的画质,帮助用户爽快看剧,下面小编就给大家带来一些芒果tv免费的会员账号供用户们使用,赶紧来看一看吧。芒果tv最新会员账号免费分享2023:注意:都是收集的最新会员账号,可以直接登录使用,不要随意的修改密码。账号:13842025699密码:qds373账号:15804882888密码:evr6982账号:13330925667密码:jgqae账号:1703

win7企业版激活密钥有没有最新的?如果你安装的是官方win7企业版,会提示用windows7企业版产品密钥来激活,否则不能正常使用。所以小编接下来跟大家分享一些win7企业版激活密码,大家一起来看看吧。Q3VMJ-TMJ3M-99RF9-CVPJ3-Q7VF3KGMPT-GQ6XF-DM3VM-HW6PR-DX9G8MT39G-9HYXX-J3V3Q-RPXJB-RQ6D79JBBV-7Q7P7-CTDB7-KYBKG-X8HHCP72QK-2Y3B8-YDHDV-29DQB-QKWWM6JQ

win7系统如何分享wifi热点?我们电脑在连接了网络之后,也是可以进行无线网络的分享的。很多用户想要将自己电脑的网络分享到手机上来使用。很多小伙伴不知道怎么详细操作,小编下面整理了win7系统如何分享wifi热点的操作方法步骤,如果你感兴趣的话,跟着小编一起往下看看吧! win7系统如何分享wifi热点的操作方法步骤 1、要想开启wifi热点,首先得要有无线网卡,笔记本是有自带的,pc的话可以购买一个随身wifi来分享wifi,这里就不叙述了。首先按下键盘上的windows键打开开始菜

惠普打印机是很多办公室内必备的打印设备,在电脑上安装打印机驱动,可以完美解决打印机无法连接等等问题。那么惠普打印机驱动怎么安装?下面小编就给大家介绍两个惠普打印机驱动程序安装方法。 第一种方法:官网下载驱动 1、在搜索引擎中搜索惠普中国官网,在支持一栏中,选择【软件与驱动程序】。 2、选择【打印机】分类,在搜索框中输入你的打印机型号,点击【提交】,即可查找到你的打印机驱动。 3、根据你电脑的系统选择对应的打印机,win10即选择win10系统的驱动。 4、下载成功后,在文件夹中找到

番茄小说是丰富的小说宝库,其中汇聚了海量优质的小说资源。在这里,你可以根据自己的喜好,从多种不同类型的小说中挑选出心仪之作。对于热爱阅读的你,这无疑是一片可以自由翱翔的文学天地。有的时候遇到心仪的读物也像分享给好友一起阅读,但是很多用户们还不清楚究竟该如何分享,那么这篇教程攻略就将为大家带来详细的攻略介绍,想要了解的玩家们就快来跟着本文一起阅读吧!番茄小说怎么分享书给好友?1、打开番茄小说,点击进入小说,点击右上角分享图标。2、选择分享渠道,这里小编以分享至微信好友为例。3、点击分享。4、即可查

标题:解决Discuz微信分享无法显示的问题,需要具体代码示例随着移动互联网的发展,微信成为了人们日常生活中不可或缺的一部分。在网站开发中,为了提升用户体验和扩大网站的曝光度,很多站点会集成微信分享功能,让用户能够方便地分享网站的内容到朋友圈或者微信群中。然而,有时候在使用Discuz等开源论坛系统时,会遇到微信分享无法显示的问题,这给用户体验带来了一定的困

wps是一款颇受欢迎的办公软件,无论是在学习、工作还是生活中,都能大大提高工作效率。我们经常会将wps文件分享给需要的朋友,具体要怎么操作呢?下面就由小编来演示一下详细操作。 1、打开需要分享的文件。 2、点击文件,再点击分享文档。 3、权限选择仅指定人可查看/编辑,然后点击创建并分享。 4、然后点击复制链接。 5、打开自己要分享的途径,如分享微信好友,在输入框点击鼠标右键,选择粘贴。 6、然后点击发送就可以了。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

Dreamweaver Mac版
视觉化网页开发工具

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),