Java根据模板导出Excel报表并复制模板生成多个Sheet页
程序员文章站
2024-03-31 18:32:40
因为最近用报表导出比较多,所有就提成了一个工具类,本工具类使用的场景为 根据提供的模板来导出excel报表
并且可根据提供的模板sheet页进行复制 从而实现...
因为最近用报表导出比较多,所有就提成了一个工具类,本工具类使用的场景为 根据提供的模板来导出excel报表
并且可根据提供的模板sheet页进行复制 从而实现多个sheet页的需求,
使用本工具类时,如果需求是每个sheet页中的数据都不一致,但是表格样式和模板都一样
那么只需要在实际情况中根据 sql 来查询要添加的数据源 (只需更改数据源即可)
采用的技术为 poi 导出,因为类的缘故,目前只支持2003版本的excel.
使用前请先下载相应jar包!
后期有时间的话会进行进一步完善,初次写工具类,若有不完善的地方还请包涵!
先看看模板样式和运行结果,然后直接上代码
这是excel的模板样式
这是导出结果
具体实现看demo
package com.sgcc.xyz.util; import java.io.file; import java.io.fileinputstream; import java.io.outputstream; import java.util.list; import java.util.map; import javax.servlet.http.httpservletresponse; import org.apache.poi.hssf.usermodel.hssfcell; import org.apache.poi.hssf.usermodel.hssfcellstyle; import org.apache.poi.hssf.usermodel.hssfrow; import org.apache.poi.hssf.usermodel.hssfsheet; import org.apache.poi.hssf.usermodel.hssfworkbook; import org.apache.poi.hssf.util.hssfcolor; import org.apache.poi.hssf.util.region; import org.apache.poi.poifs.filesystem.poifsfilesystem; import com.sgcc.uap.persistence.impl.hibernatedaoimpl; /** * 报表导出工具类 * * @author jyliu @巴黎的雨季 本工具是根据poi对excel2003进行报表导出 本工具类可根据模板进行excel的导出 * 并且可根据提供的模板sheet页进行复制 从而实现多个sheet页的需求 * 使用本工具类时,如果需求是每个sheet页中的数据都不一致,但是表格样式和模板都一样 * 那么只需要在实际情况中根据 sql 来查询要添加的数据源 (只需更改数据源即可) */ public class excelutil { /** * 根据模板导出报表,可导出多个sheet页 * * @param 导出的excel文件名 * @param 模板路径 (全路径) * @param 数据源 * @param 返回请求 * @param 生成的sheet页的名称集合 * @param 数据源中map集合的key值 (key值对应的value值顺序要列名顺序一致) * @param 开始 循环写入数据 的行数(从第几行开始写入数据) */ public static void excelbymodel(string excelname, string modelurl, list<map<string, string>> datasource, httpservletresponse response, string[] sheetnames, string[] keynames, int rownum) throws exception { // 设置导出excel报表的导出形式 response.setcontenttype("application/vnd.ms-excel"); // 设置导出excel报表的响应文件名 string filename = new string(excelname.getbytes("utf-8"), "iso-8859-1"); response.setheader("content-disposition", "attachment;filename=" + filename + ".xls"); // 创建一个输出流 outputstream fileout = response.getoutputstream(); // 读取模板文件路径 file file = new file(modelurl); fileinputstream fins = new fileinputstream(file); poifsfilesystem fs = new poifsfilesystem(fins); // 读取excel模板 hssfworkbook wb = new hssfworkbook(fs); // 设置边框样式 hssfcellstyle style = wb.createcellstyle(); style.setborderbottom(hssfcellstyle.border_thin); style.setborderleft(hssfcellstyle.border_thin); style.setborderright(hssfcellstyle.border_thin); style.setbordertop(hssfcellstyle.border_thin); // 设置边框样式的颜色 style.setbottombordercolor(hssfcolor.black.index); style.setleftbordercolor(hssfcolor.black.index); style.setrightbordercolor(hssfcolor.black.index); style.settopbordercolor(hssfcolor.black.index); // 模板页 hssfsheet sheetmodel = null; // 新建的sheet页 hssfsheet newsheet = null; // 创建行 hssfrow row = null; // 创建列 hssfcell cell = null; // 循环建立sheet页 for (int i = 0; i < sheetnames.length; i++) { // 读取模板中模板sheet页中的内容 sheetmodel = wb.getsheetat(0); // 设置新建sheet的页名 newsheet = wb.createsheet(sheetnames[i]); // 将模板中的内容复制到新建的sheet页中 copysheet(wb, sheetmodel, newsheet, sheetmodel.getfirstrownum(), sheetmodel.getlastrownum()); //获取到新建sheet页中的第一行为其中的列赋值 row=newsheet.getrow(0); row.getcell(1).setcellvalue("这是为表代码赋的值"); //注意 合并的单元格也要按照合并前的格数来算 row.getcell(6).setcellvalue("这是为外部代码赋的值"); //获取模板中的第二列,并赋值 row=newsheet.getrow(1); row.getcell(1).setcellvalue("表名称赋值"); //注意 合并的单元格也要按照合并前的格数来算 row.getcell(6).setcellvalue("这是为是否系统表赋的值"); // 遍历数据源 开始写入数据(因为excel中是从0开始,所以减一) int num = rownum - 1; for (map<string, string> item : datasource) { // 循环遍历,新建行 row = newsheet.createrow((short) num); //判断有多少列数据 for (int j = 0; j < keynames.length; j++) { // 设置每列的数据 设置每列的样式 设置每列的值 cell = row.createcell(j); cell.setcellstyle(style); cell.setcellvalue(item.get(keynames[j])); } num++; } // break 加break可以测试只添加一个sheet页的情况 } // 写入流 wb.write(fileout); // 关闭流 fileout.close(); } /** * * @param excel工作簿对象 * @param 模板sheet页 * @param 新建sheet页 * @param 模板页的第一行 * @param 模板页的最后一行 */ private static void copysheet(hssfworkbook wb, hssfsheet fromsheet, hssfsheet newsheet, int firstrow, int lasttrow) { // 复制一个单元格样式到新建单元格 if ((firstrow == -1) || (lasttrow == -1) || lasttrow < firstrow) { return; } // 复制合并的单元格 region region = null; for (int i = 0; i < fromsheet.getnummergedregions(); i++) { region = fromsheet.getmergedregionat(i); if ((region.getrowfrom() >= firstrow) && (region.getrowto() <= lasttrow)) { newsheet.addmergedregion(region); } } hssfrow fromrow = null; hssfrow newrow = null; hssfcell newcell = null; hssfcell fromcell = null; // 设置列宽 for (int i = firstrow; i < lasttrow; i++) { fromrow = fromsheet.getrow(i); if (fromrow != null) { for (int j = fromrow.getlastcellnum(); j >= fromrow.getfirstcellnum(); j--) { int colnum = fromsheet.getcolumnwidth((short) j); if (colnum > 100) { newsheet.setcolumnwidth((short) j, (short) colnum); } if (colnum == 0) { newsheet.setcolumnhidden((short) j, true); } else { newsheet.setcolumnhidden((short) j, false); } } break; } } // 复制行并填充数据 for (int i = 0; i < lasttrow; i++) { fromrow = fromsheet.getrow(i); if (fromrow == null) { continue; } newrow = newsheet.createrow(i - firstrow); newrow.setheight(fromrow.getheight()); for (int j = fromrow.getfirstcellnum(); j < fromrow.getphysicalnumberofcells(); j++) { fromcell = fromrow.getcell((short) j); if (fromcell == null) { continue; } newcell = newrow.createcell((short) j); newcell.setcellstyle(fromcell.getcellstyle()); int ctype = fromcell.getcelltype(); newcell.setcelltype(ctype); switch (ctype) { case hssfcell.cell_type_string: newcell.setcellvalue(fromcell.getrichstringcellvalue()); break; case hssfcell.cell_type_numeric: newcell.setcellvalue(fromcell.getnumericcellvalue()); break; case hssfcell.cell_type_formula: newcell.setcellvalue(fromcell.getcellformula()); break; case hssfcell.cell_type_boolean: newcell.setcellvalue(fromcell.getbooleancellvalue()); break; case hssfcell.cell_type_error: newcell.setcellvalue(fromcell.geterrorcellvalue()); break; default: newcell.setcellvalue(fromcell.getrichstringcellvalue()); break; } } } } }
以上便是整个工具类的核心代码了
测试数据如下
/** * 测试多sheet页导出数据表格方法 */ public static void exceltest(httpservletresponse response){ //构建数据源 list<map<string, string>> datasourcelist=new arraylist<map<string,string>>(){ { add(new hashmap<string, string>(){{ put("字段编号", "1"); put("字段代码", "business_id"); put("字段含义", "业务id"); put("数据类型", "varchar"); put("长度", "64"); put("主键", "是"); put("主码", ""); }}); add(new hashmap<string, string>(){{ put("字段编号", "2"); put("字段代码", "proc_inst_id"); put("字段含义", "流程实例编号"); put("数据类型", "varchar"); put("长度", "64"); put("主键", ""); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "3"); put("字段代码", "proc_state"); put("字段含义", "流程状态"); put("数据类型", "varchar"); put("长度", "64"); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "4"); put("字段代码", "applicant"); put("字段含义", "申请人"); put("数据类型", "varchar"); put("长度", "64"); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "5"); put("字段代码", "leave_type"); put("字段含义", "请假类型"); put("数据类型", "varchar"); put("长度", "64"); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "6"); put("字段代码", "reason"); put("字段含义", "请假事因"); put("数据类型", "varchar"); put("长度", "64"); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "7"); put("字段代码", "begin_time"); put("字段含义", "起始时间"); put("数据类型", "timestamp"); put("长度", ""); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "8"); put("字段代码", "end_time"); put("字段含义", "结束时间"); put("数据类型", "timestamp"); put("长度", ""); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "9"); put("字段代码", "insert_person"); put("字段含义", "登记人"); put("数据类型", "varchar"); put("长度", "64"); put("主键", " "); put("主码", " "); }}); add(new hashmap<string, string>(){{ put("字段编号", "10"); put("字段代码", "approvedby"); put("字段含义", "批准人"); put("数据类型", "varchar"); put("长度", "64"); put("主键", " "); put("主码", " "); }}); } }; //构建数据源中的key值 string[] keysstrings={"字段编号","字段代码","字段含义","数据类型","长度","主键","主码"}; //每页的名称 string [] sheetnamestrings={"sheet1","sheet2","sheet3","sheet4","sheet5","sheet6"}; string modelurlstring="d:\\model\\model.xls"; try { excelutil.excelbymodel("测试模板导出", modelurlstring, datasourcelist, response, sheetnamestrings, keysstrings, 6); } catch (exception e) { e.printstacktrace(); } }
以上就是关于excel报表根据模板导出并生成多个sheet也的小工具了,需要的可以参考代码,根据实际业务需求进行代码调整。
希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
上一篇: C# 接口的隐式与显示实现及适应场景