Java根据模板导出Excel并生成多个Sheet

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lchq1995/article/details/84820950

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

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

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

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

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

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

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

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

这是Excel的模板样式

这是导出结果

具体实现看demo

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

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;

    }

   }

  }

 }

}

以上便是整个工具类的核心代码了

测试数据如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

/**

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

 分享一个网上看到的列子,使用的是EasyPoi,其实是对poi的一个封装使其更简单易用,简单的导入导出可直接使用复杂坑较多

EasyPoi教程地址:  http://easypoi.mydoc.io/#text_197818

个人在项目中使用了easypoi和poi结合使用,因为easypoi使用确实简单一些,后续做简单的案例介绍!

猜你喜欢

转载自blog.csdn.net/lchq1995/article/details/84820950