需要预先新建编辑好一个excel文件,设置好样式。

编辑好输出的数据,根据excel坐标一一对应。

支持列表数据输出,列表中列合并。

代码如下:

  1. package com.icourt.util;
  2.  
  3. import org.apache.commons.collections4.CollectionUtils;
  4. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  5. import org.apache.poi.ss.usermodel.*;
  6. import org.apache.poi.ss.util.CellRangeAddress;
  7.  
  8. import java.io.*;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Map.Entry;
  14. import java.util.regex.Matcher;
  15. import java.util.regex.Pattern;
  16.  
  17. /**
  18. * 描述:poi根据模板导出excel,根据excel坐标赋值,如(B1)
  19. */
  20. public class ExcelExportUtil {
  21.  
  22. //模板map
  23. private Map<String, Workbook> tempWorkbook = new HashMap<String, Workbook>();
  24. //模板输入流map
  25. private Map<String, InputStream> tempStream = new HashMap<String, InputStream>();
  26.  
  27. /**
  28. * 功能:按模板向Excel中相应地方填充数据
  29. */
  30. public void writeData(String templateFilePath, Map<String, Object> dataMap, int sheetNo) throws IOException, InvalidFormatException {
  31. if (dataMap == null || dataMap.isEmpty()) {
  32. return;
  33. }
  34. //读取模板
  35. Workbook wbModule = getTempWorkbook(templateFilePath);
  36. //数据填充的sheet
  37. Sheet wsheet = wbModule.getSheetAt(sheetNo);
  38.  
  39. for (Entry<String, Object> entry : dataMap.entrySet()) {
  40. String point = entry.getKey();
  41. Object data = entry.getValue();
  42.  
  43. TempCell cell = getCell(point, data, wsheet);
  44. //指定坐标赋值
  45. setCell(cell, wsheet);
  46. }
  47.  
  48. //设置生成excel中公式自动计算
  49. wsheet.setForceFormulaRecalculation(true);
  50. }
  51.  
  52. /**
  53. * 功能:按模板向Excel中列表填充数据.只支持列合并
  54. */
  55. public void writeDateList(String templateFilePath, String[] heads, List<Map<Integer, Object>> datalist, int sheetNo) throws IOException, InvalidFormatException {
  56. if (heads == null || heads.length <= 0 || CollectionUtils.isEmpty(datalist)) {
  57. return;
  58. }
  59. //读取模板
  60. Workbook wbModule = getTempWorkbook(templateFilePath);
  61. //数据填充的sheet
  62. Sheet wsheet = wbModule.getSheetAt(sheetNo);
  63.  
  64. //列表数据模板cell
  65. List<TempCell> tempCells = new ArrayList<TempCell>(heads.length);
  66. for (String point : heads) {
  67. TempCell tempCell = getCell(point, null, wsheet);
  68. //取得合并单元格位置 -1:表示不是合并单元格
  69. int pos = isMergedRegion(wsheet, tempCell.getRow(), tempCell.getColumn());
  70. if (pos > -1) {
  71. CellRangeAddress range = wsheet.getMergedRegion(pos);
  72. tempCell.setColumnSize(range.getLastColumn() - range.getFirstColumn());
  73. }
  74. tempCells.add(tempCell);
  75. }
  76. //赋值
  77. for (int i = 0; i < datalist.size(); i++) {//数据行
  78. Map<Integer, Object> dataMap = datalist.get(i);
  79. for (int j = 0; j < tempCells.size(); j++) {//列
  80. TempCell tempCell = tempCells.get(j);
  81. tempCell.setData(dataMap.get(j + 1));
  82. setCell(tempCell, wsheet);
  83. tempCell.setRow(tempCell.getRow() + 1);
  84. }
  85. }
  86. }
  87.  
  88. /**
  89. * 功能:获取输入工作区
  90. */
  91. private Workbook getTempWorkbook(String templateFilePath) throws IOException, InvalidFormatException {
  92. if (!tempWorkbook.containsKey(templateFilePath)) {
  93. InputStream inputStream = getInputStream(templateFilePath);
  94. tempWorkbook.put(templateFilePath, WorkbookFactory.create(inputStream));
  95. }
  96. return tempWorkbook.get(templateFilePath);
  97. }
  98.  
  99. /**
  100. * 功能:获得模板输入流
  101. */
  102. private InputStream getInputStream(String templateFilePath) throws FileNotFoundException {
  103. if (!tempStream.containsKey(templateFilePath)) {
  104. tempStream.put(templateFilePath, new FileInputStream((templateFilePath)));
  105. }
  106. return tempStream.get(templateFilePath);
  107. }
  108.  
  109. /**
  110. * 功能:获取单元格数据,样式(根据坐标:B3)
  111. */
  112. private TempCell getCell(String point, Object data, Sheet sheet) {
  113. TempCell tempCell = new TempCell();
  114.  
  115. //得到列 字母
  116. String lineStr = "";
  117. String reg = "[A-Z]+";
  118. Pattern p = Pattern.compile(reg);
  119. Matcher m = p.matcher(point);
  120. while (m.find()) {
  121. lineStr = m.group();
  122. }
  123. //将列字母转成列号 根据ascii转换
  124. char[] ch = lineStr.toCharArray();
  125. int column = 0;
  126. for (int i = 0; i < ch.length; i++) {
  127. char c = ch[i];
  128. int post = ch.length - i - 1;
  129. int r = (int) Math.pow(10, post);
  130. column = column + r * ((int) c - 65);
  131. }
  132. tempCell.setColumn(column);
  133.  
  134. //得到行号
  135. reg = "[1-9]+";
  136. p = Pattern.compile(reg);
  137. m = p.matcher(point);
  138. while (m.find()) {
  139. tempCell.setRow((Integer.parseInt(m.group()) - 1));
  140. }
  141.  
  142. //获取模板指定单元格样式,设置到tempCell(写列表数据的时候用)
  143. Row rowIn = sheet.getRow(tempCell.getRow());
  144. if (rowIn == null) {
  145. rowIn = sheet.createRow(tempCell.getRow());
  146. }
  147. Cell cellIn = rowIn.getCell(tempCell.getColumn());
  148. if (cellIn == null) {
  149. cellIn = rowIn.createCell(tempCell.getColumn());
  150. }
  151. tempCell.setCellStyle(cellIn.getCellStyle());
  152. tempCell.setData(data);
  153. return tempCell;
  154. }
  155.  
  156. /**
  157. * 功能:给指定坐标单元格赋值
  158. */
  159. private void setCell(TempCell tempCell, Sheet sheet) {
  160. if (tempCell.getColumnSize() > -1) {
  161. CellRangeAddress rangeAddress = mergeRegion(sheet, tempCell.getRow(), tempCell.getRow(), tempCell.getColumn(), tempCell.getColumn() + tempCell.getColumnSize());
  162. setRegionStyle(tempCell.getCellStyle(), rangeAddress, sheet);
  163. }
  164.  
  165. Row rowIn = sheet.getRow(tempCell.getRow());
  166. if (rowIn == null) {
  167. copyRows(tempCell.getRow() - 1, tempCell.getRow() - 1, tempCell.getRow(), sheet);//复制上一行
  168. rowIn = sheet.getRow(tempCell.getRow());
  169. }
  170. Cell cellIn = rowIn.getCell(tempCell.getColumn());
  171. if (cellIn == null) {
  172. cellIn = rowIn.createCell(tempCell.getColumn());
  173. }
  174. //根据data类型给cell赋值
  175. if (tempCell.getData() instanceof String) {
  176. cellIn.setCellValue((String) tempCell.getData());
  177. } else if (tempCell.getData() instanceof Integer) {
  178. cellIn.setCellValue((int) tempCell.getData());
  179. } else if (tempCell.getData() instanceof Double) {
  180. cellIn.setCellValue((double) tempCell.getData());
  181. } else {
  182. cellIn.setCellValue((String) tempCell.getData());
  183. }
  184. //样式
  185. if (tempCell.getCellStyle() != null && tempCell.getColumnSize() == -1) {
  186. cellIn.setCellStyle(tempCell.getCellStyle());
  187. }
  188. }
  189.  
  190. /**
  191. * 功能:写到输出流并移除资源
  192. */
  193. public void writeAndClose(String templateFilePath, OutputStream os) throws IOException, InvalidFormatException {
  194. if (getTempWorkbook(templateFilePath) != null) {
  195. getTempWorkbook(templateFilePath).write(os);
  196. tempWorkbook.remove(templateFilePath);
  197. }
  198. if (getInputStream(templateFilePath) != null) {
  199. getInputStream(templateFilePath).close();
  200. tempStream.remove(templateFilePath);
  201. }
  202. }
  203.  
  204. /**
  205. * 功能:判断指定的单元格是否是合并单元格
  206. */
  207. private Integer isMergedRegion(Sheet sheet, int row, int column) {
  208. for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
  209. CellRangeAddress range = sheet.getMergedRegion(i);
  210. int firstColumn = range.getFirstColumn();
  211. int lastColumn = range.getLastColumn();
  212. int firstRow = range.getFirstRow();
  213. int lastRow = range.getLastRow();
  214. if (row >= firstRow && row <= lastRow) {
  215. if (column >= firstColumn && column <= lastColumn) {
  216. return i;
  217. }
  218. }
  219. }
  220. return -1;
  221. }
  222.  
  223. /**
  224. * 功能:合并单元格
  225. */
  226. private CellRangeAddress mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
  227. CellRangeAddress rang = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
  228. sheet.addMergedRegion(rang);
  229. return rang;
  230. }
  231.  
  232. /**
  233. * 功能:设置合并单元格样式
  234. */
  235. private void setRegionStyle(CellStyle cs, CellRangeAddress region, Sheet sheet) {
  236. for (int i = region.getFirstRow(); i <= region.getLastRow(); i++) {
  237. Row row = sheet.getRow(i);
  238. if (row == null) row = sheet.createRow(i);
  239. for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {
  240. Cell cell = row.getCell(j);
  241. if (cell == null) {
  242. cell = row.createCell(j);
  243. cell.setCellValue("");
  244. }
  245. cell.setCellStyle(cs);
  246. }
  247. }
  248. }
  249.  
  250. /**
  251. * 功能:copy rows
  252. */
  253. private void copyRows(int startRow, int endRow, int pPosition, Sheet sheet) {
  254. int pStartRow = startRow - 1;
  255. int pEndRow = endRow - 1;
  256. int targetRowFrom;
  257. int targetRowTo;
  258. int columnCount;
  259. CellRangeAddress region = null;
  260. int i;
  261. int j;
  262. if (pStartRow == -1 || pEndRow == -1) {
  263. return;
  264. }
  265. // 拷贝合并的单元格
  266. for (i = 0; i < sheet.getNumMergedRegions(); i++) {
  267. region = sheet.getMergedRegion(i);
  268. if ((region.getFirstRow() >= pStartRow)
  269. && (region.getLastRow() <= pEndRow)) {
  270. targetRowFrom = region.getFirstRow() - pStartRow + pPosition;
  271. targetRowTo = region.getLastRow() - pStartRow + pPosition;
  272. CellRangeAddress newRegion = region.copy();
  273. newRegion.setFirstRow(targetRowFrom);
  274. newRegion.setFirstColumn(region.getFirstColumn());
  275. newRegion.setLastRow(targetRowTo);
  276. newRegion.setLastColumn(region.getLastColumn());
  277. sheet.addMergedRegion(newRegion);
  278. }
  279. }
  280. // 设置列宽
  281. for (i = pStartRow; i <= pEndRow; i++) {
  282. Row sourceRow = sheet.getRow(i);
  283. columnCount = sourceRow.getLastCellNum();
  284. if (sourceRow != null) {
  285. Row newRow = sheet.createRow(pPosition - pStartRow + i);
  286. newRow.setHeight(sourceRow.getHeight());
  287. for (j = 0; j < columnCount; j++) {
  288. Cell templateCell = sourceRow.getCell(j);
  289. if (templateCell != null) {
  290. Cell newCell = newRow.createCell(j);
  291. copyCell(templateCell, newCell);
  292. }
  293. }
  294. }
  295. }
  296. }
  297.  
  298. /**
  299. * 功能:copy cell,不copy值
  300. */
  301. private void copyCell(Cell srcCell, Cell distCell) {
  302. distCell.setCellStyle(srcCell.getCellStyle());
  303. if (srcCell.getCellComment() != null) {
  304. distCell.setCellComment(srcCell.getCellComment());
  305. }
  306. int srcCellType = srcCell.getCellType();
  307. distCell.setCellType(srcCellType);
  308. }
  309.  
  310. /**
  311. * 描述:临时单元格数据
  312. */
  313. class TempCell {
  314. private int row;
  315. private int column;
  316. private CellStyle cellStyle;
  317. private Object data;
  318. //用于列表合并,表示几列合并
  319. private int columnSize = -1;
  320.  
  321. public int getColumn() {
  322. return column;
  323. }
  324.  
  325. public void setColumn(int column) {
  326. this.column = column;
  327. }
  328.  
  329. public int getRow() {
  330. return row;
  331. }
  332.  
  333. public void setRow(int row) {
  334. this.row = row;
  335. }
  336.  
  337. public CellStyle getCellStyle() {
  338. return cellStyle;
  339. }
  340.  
  341. public void setCellStyle(CellStyle cellStyle) {
  342. this.cellStyle = cellStyle;
  343. }
  344.  
  345. public Object getData() {
  346. return data;
  347. }
  348.  
  349. public void setData(Object data) {
  350. this.data = data;
  351. }
  352.  
  353. public int getColumnSize() {
  354. return columnSize;
  355. }
  356.  
  357. public void setColumnSize(int columnSize) {
  358. this.columnSize = columnSize;
  359. }
  360. }
  361.  
  362. public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException {
  363. String templateFilePath = ExcelExportUtil.class.getClassLoader().getResource("plugin/ProTiming.xlsx").getPath();
  364. File file = new File("/Users/sql/Downloads/test/data.xlsx");
  365. OutputStream os = new FileOutputStream(file);
  366.  
  367. ExcelExportUtil excel = new ExcelExportUtil();
  368. Map<String, Object> dataMap = new HashMap<String, Object>();
  369. dataMap.put("B1", "03_Alpha_项目工作时间统计表");
  370. dataMap.put("B2", "统计时间:2017/01/01 - 2017/03/31");
  371.  
  372. excel.writeData(templateFilePath, dataMap, 0);
  373.  
  374. List<Map<Integer, Object>> datalist = new ArrayList<Map<Integer, Object>>();
  375. Map<Integer, Object> data = new HashMap<Integer, Object>();
  376. data.put(1, "3/10/17");
  377. data.put(2, "18:50");
  378. data.put(3, "19:00");
  379. data.put(4, "李子鹏");
  380. data.put(5, "新增项目键值对接口,供任务计时调用");
  381. data.put(6, "代码开发");
  382. data.put(7, "3.17");
  383.  
  384. datalist.add(data);
  385. data = new HashMap<Integer, Object>();
  386. data.put(1, "3/10/17");
  387. data.put(2, "18:50");
  388. data.put(3, "19:00");
  389. data.put(4, "李子鹏");
  390. data.put(5, "新增项目键值对接口,供任务计时调用");
  391. data.put(6, "代码开发");
  392. data.put(7, "3.17");
  393. datalist.add(data);
  394. data = new HashMap<Integer, Object>();
  395. data.put(1, "3/10/17");
  396. data.put(2, "18:50");
  397. data.put(3, "19:00");
  398. data.put(4, "李子鹏");
  399. data.put(5, "新增项目键值对接口,供任务计时调用");
  400. data.put(6, "代码开发");
  401. data.put(7, "3.17");
  402. datalist.add(data);
  403. data = new HashMap<Integer, Object>();
  404. data.put(1, "3/10/17");
  405. data.put(2, "18:50");
  406. data.put(3, "19:00");
  407. data.put(4, "李子鹏");
  408. data.put(5, "新增项目键值对接口,供任务计时调用");
  409. data.put(6, "代码开发");
  410. data.put(7, "3.17");
  411. datalist.add(data);
  412. data = new HashMap<Integer, Object>();
  413. data.put(1, "3/10/17");
  414. data.put(2, "18:50");
  415. data.put(3, "19:00");
  416. data.put(4, "李子鹏");
  417. data.put(5, "新增项目键值对接口,供任务计时调用");
  418. data.put(6, "代码开发");
  419. data.put(7, "3.17");
  420. datalist.add(data);
  421. data = new HashMap<Integer, Object>();
  422. data.put(1, "3/10/17");
  423. data.put(2, "18:50");
  424. data.put(3, "19:00");
  425. data.put(4, "李子鹏");
  426. data.put(5, "新增项目键值对接口,供任务计时调用");
  427. data.put(6, "代码开发");
  428. data.put(7, "3.17");
  429. datalist.add(data);
  430. data = new HashMap<Integer, Object>();
  431. data.put(1, "3/10/17");
  432. data.put(2, "18:50");
  433. data.put(3, "19:00");
  434. data.put(4, "李子鹏");
  435. data.put(5, "新增项目键值对接口,供任务计时调用");
  436. data.put(6, "代码开发");
  437. data.put(7, "3.17");
  438. datalist.add(data);
  439. data = new HashMap<Integer, Object>();
  440. data.put(1, "3/10/17");
  441. data.put(2, "18:50");
  442. data.put(3, "19:00");
  443. data.put(4, "李子鹏");
  444. data.put(5, "新增项目键值对接口,供任务计时调用");
  445. data.put(6, "代码开发");
  446. data.put(7, "3.17");
  447. datalist.add(data);
  448.  
  449. data = new HashMap<Integer, Object>();
  450. data.put(1, "3/10/17");
  451. data.put(2, "18:50");
  452. data.put(3, "19:00");
  453. data.put(4, "李子鹏");
  454. data.put(5, "新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用新增项目键值对接口,供任务计时调用");
  455. data.put(6, "代码开发");
  456. data.put(7, "3.17");
  457. datalist.add(data);
  458. data = new HashMap<Integer, Object>();
  459. data.put(1, "");
  460. data.put(2, "");
  461. data.put(3, "");
  462. data.put(4, "");
  463. data.put(5, "");
  464. data.put(6, "");
  465. data.put(7, "");
  466. datalist.add(data);
  467.  
  468. String[] heads = new String[]{"B4", "C4", "D4", "E4", "F4", "G4", "H4"};
  469. excel.writeDateList(templateFilePath, heads, datalist, 0);
  470.  
  471. //写到输出流并移除资源
  472. excel.writeAndClose(templateFilePath, os);
  473.  
  474. os.flush();
  475. os.close();
  476. }
  477.  
  478. }

大体思路:

最主要是制作好模版

代码根据模版,读取设置好的列的格式,在循环数据行,读取模版中的对应的行,存在该行就取得,不存在看是否需要copy某一行,不需要就手动创建无制定格式的行,后面在为该行的每一列对应的给个单元格制定格式和数据。

apache poi根据模板导出excel的更多相关文章

  1. POI通过模板导出EXCEL文件

    一般的EXCEL导出使用POI先创建一个HSSFWorkbook,然后通过不断创建HSSFRow,HSSFCell后设置单元格内容便可以完成导出. 这次在项目中需要用到模板,导出的内容包括(1.模板中 ...

  2. 使用Apache poi来编写导出excel的工具类

    在JavaWeb开发的需求中,我们会经常看到导出excel的功能需求,然后java并没有提供操作office文档的功能,这个时候我们就需要使用额外的组件来帮助我们完成这项功能了. 很高兴Apache基 ...

  3. java后台poi根据模板导出excel

    public class ExcelUtils { private static final String INSPECTIONRECORD_SURFACE_TEMPLET_PATH = " ...

  4. poi根据excel模板导出Excel

    /****单元格值对象**/public class Cells { /*** * 行 */ private int row; /** * 列 */ private int column; /** * ...

  5. Java无模板导出Excel,Apache-POI插件实现

    开发环境 jdk 1.8 Maven 3.6 Tomcat 8.5 SpringBoot 2.1.4.RELEASE Apache-POI 3.6 Idea 注意: 我是在现有的基于SpringBoo ...

  6. Java中使用poi导入、导出Excel

    一.介绍 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统.银行系统).或者是:我们已经习惯用Excel打印.这样在我们实际 ...

  7. Java使用POI实现数据导出excel报表

    Java使用POI实现数据导出excel报表 在上篇文章中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅 ...

  8. POI导入和导出Excel总结

    POI导入和导出Excel总结   POI使用总结 1.POI读取Excel 打开工作簿的方式有以下两种简单的应用,POI读取和输出工作簿文件都可以通过以下两种方式来声明: //通过输入流的方式打开本 ...

  9. aspose.cells根据模板导出excel

    又隔十多天没写博客了,最近都在忙项目的事情,公司人事变动也比较大,手头上就又多了一个项目.最近做用aspose.cells根据模板导出excel报价单的功能,顺便把相关的核心记下来,先上模板和导出的效 ...

随机推荐

  1. 文本编辑器 未完成 Treap

    #include<bits/stdc++.h> using namespace std; const int maxn = 2e6+1e5; unsigned int SEED = 17; ...

  2. springboot(五)-使用Redis

    Redis服务器 springboot要使用redis,首先当然要确保redis服务器能够正常跑起来. pom.xml 这里添加redis的依赖,当然也是springboot集成好的. <!-- ...

  3. window 中安装 hadoop

    win10上部署Hadoop-2.7.3——非Cygwin.非虚拟机   开始接触Hadoop,听人说一般都是在Lunix下部署Hadoop,但是本人Lunix不是很了解,所以Google以下如何在W ...

  4. Oracle分组函数之CUBE魅力

    Oracle的CUBE与ROLLUP功能很相似,也是在数据统计分析领域的一把好手. 关于ROLLUP的查询统计功能请参考文章<Oracle分组函数之ROLLUP魅力>(http://www ...

  5. Android 自动分析apk加固方式

    本实例只对apk中lib文件夹中的文件进行分析import java.io.File;import java.io.IOException;import java.util.ArrayList;imp ...

  6. 多租户概念以及FreeLink多租户设计思想

    多租户实现思想 多租户技术的实现重点,在于不同租户间应用程序环境的隔离(application context isolation)以及数据的隔离(data isolation),以维持不同租户间应用 ...

  7. js数组方法详解

    Array对象的方法-25个 /*js数组方法详解 */ /* * 1 concat() 用于连接多个数组或者值-------------- * 2 copyWithin() 方法用于从数组的指定位置 ...

  8. ABP Zero集成微信小程序登录

    首先是ABPZero的第三方登录模块,通过调用第三方的登录接口返回用户信息,再交给ABP的登录验证模块去执行对应的登录注册. 涉及的数据库表主要是这两个表,AbpUsers存储了用户信息,AbpUse ...

  9. Beam概念学习系列之PTransform数据处理

    不多说,直接上干货! PTransform数据处理 PTransform对PCollection进行并行处理,每次处理1条,例如Filter过滤.Groupby分组.Combine统计.Join关联等 ...

  10. Oracle使用sys登录时报错ORA-28009解决方法

    情况一:使用sqlplus登录: 正常输入用户名的口令,就会报错,因为SYS是在数据库之外的超级管理员,所以我们在登录的时候 要在输入口令:口令+as sysdba(比如:123456 as sysd ...