欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java根据模板导出Excel报表并复制模板生成多个Sheet页

程序员文章站 2024-03-31 18:32:40
因为最近用报表导出比较多,所有就提成了一个工具类,本工具类使用的场景为  根据提供的模板来导出excel报表 并且可根据提供的模板sheet页进行复制 从而实现...

因为最近用报表导出比较多,所有就提成了一个工具类,本工具类使用的场景为  根据提供的模板来导出excel报表

并且可根据提供的模板sheet页进行复制 从而实现多个sheet页的需求,

使用本工具类时,如果需求是每个sheet页中的数据都不一致,但是表格样式和模板都一样

那么只需要在实际情况中根据 sql 来查询要添加的数据源 (只需更改数据源即可)

采用的技术为 poi 导出,因为类的缘故,目前只支持2003版本的excel.

使用前请先下载相应jar包!

后期有时间的话会进行进一步完善,初次写工具类,若有不完善的地方还请包涵!

先看看模板样式和运行结果,然后直接上代码

这是excel的模板样式

Java根据模板导出Excel报表并复制模板生成多个Sheet页

这是导出结果

Java根据模板导出Excel报表并复制模板生成多个Sheet页

具体实现看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也的小工具了,需要的可以参考代码,根据实际业务需求进行代码调整。

希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!