java--poi生成excel动态合并内容相同的行
2017-03-22 20:23
591 查看
先开始接到这个需求的时候,第一想法是这得要多复杂的算才能实现,因为不是每一列的合并的行数一样,比如第一列1-4行的内容都相同,那么需要合并,而第二列1-2相同,所以1和2合并,3-4相同,3和4合并;然后一层一层的,就和树一样,逐层向下;
毋庸置疑,通过算法肯定能实现,但是我觉得太绕了,一下子也想不出来什么好的算法;后来我就想到约瑟夫环的问题,一个典型的java面向对象的例子;后来就通过建一个单元格对象,属性有单元格内容,与单元格同一列的上一行内容,起始行,起始列,就这四个属性;详细解释我放在代码中:
model对象:
/**
* Created by zelei.fan on 2017/3/20.
*/
public class PoiModel {
private String content;
private String oldContent;
private int rowIndex;
private int cellIndex;
public String getOldContent() {
return oldContent;
}
public void setOldContent(String oldContent) {
this.oldContent = oldContent;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getRowIndex() {
return rowIndex;
}
public void setRowIndex(int rowIndex) {
this.rowIndex = rowIndex;
}
public int getCellIndex() {
return cellIndex;
}
public void setCellIndex(int cellIndex) {
this.cellIndex = cellIndex;
}
}
Test:
生成的文件效果(两种情况的):
毋庸置疑,通过算法肯定能实现,但是我觉得太绕了,一下子也想不出来什么好的算法;后来我就想到约瑟夫环的问题,一个典型的java面向对象的例子;后来就通过建一个单元格对象,属性有单元格内容,与单元格同一列的上一行内容,起始行,起始列,就这四个属性;详细解释我放在代码中:
model对象:
/**
* Created by zelei.fan on 2017/3/20.
*/
public class PoiModel {
private String content;
private String oldContent;
private int rowIndex;
private int cellIndex;
public String getOldContent() {
return oldContent;
}
public void setOldContent(String oldContent) {
this.oldContent = oldContent;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getRowIndex() {
return rowIndex;
}
public void setRowIndex(int rowIndex) {
this.rowIndex = rowIndex;
}
public int getCellIndex() {
return cellIndex;
}
public void setCellIndex(int cellIndex) {
this.cellIndex = cellIndex;
}
}
Test:
import cn.yoho.perf.common.model.PoiModel; import com.beust.jcommander.internal.Maps; import com.google.common.collect.Lists; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.*; /** * Created by zelei.fan on 2017/3/14. */ public class Test{ /** * @param title 标题集合 tilte的长度应该与list中的model的属性个数一致 * @param maps 内容集合 * @param mergeIndex 合并单元格的列 */ public static String createExcel(String[] title, Map<String/*sheet名*/, List<Map<String/*对应title的值*/, String>>> maps, int[] mergeIndex){ if (title.length==0){ return null; } /*初始化excel模板*/ Workbook workbook = new XSSFWorkbook(); Sheet sheet = null; int n = 0; /*循环sheet页*/ for(Map.Entry<String, List<Map<String/*对应title的值*/, String>>> entry : maps.entrySet()){ /*实例化sheet对象并且设置sheet名称,book对象*/ try { sheet = workbook.createSheet(); workbook.setSheetName(n, entry.getKey()); workbook.setSelectedTab(0); }catch (Exception e){ e.printStackTrace(); } /*初始化head,填值标题行(第一行)*/ Row row0 = sheet.createRow(0); for(int i = 0; i<title.length; i++){ /*创建单元格,指定类型*/ Cell cell_1 = row0.createCell(i, Cell.CELL_TYPE_ST 4000 RING); cell_1.setCellValue(title[i]); } /*得到当前sheet下的数据集合*/ List<Map<String/*对应title的值*/, String>> list = entry.getValue(); /*遍历该数据集合*/ List<PoiModel> poiModels = Lists.newArrayList(); if(null!=workbook){ Iterator iterator = list.iterator(); int index = 1;/*这里1是从excel的第二行开始,第一行已经塞入标题了*/ while (iterator.hasNext()){ Row row = sheet.createRow(index); /*取得当前这行的map,该map中以key,value的形式存着这一行值*/ Map<String, String> map = (Map<String, String>)iterator.next(); /*循环列数,给当前行塞值*/ for(int i = 0; i<title.length; i++){ String old = ""; /*old存的是上一行统一位置的单元的值,第一行是最上一行了,所以从第二行开始记*/ if(index > 1){ old = poiModels.get(i)==null?"":poiModels.get(i).getContent(); } /*循环需要合并的列*/ for(int j = 0; j < mergeIndex.length; j++){ if(index == 1){ /*记录第一行的开始行和开始列*/ PoiModel poiModel = new PoiModel(); poiModel.setOldContent(map.get(title[i])); poiModel.setContent(map.get(title[i])); poiModel.setRowIndex(1); poiModel.setCellIndex(i); poiModels.add(poiModel); break; }else if(i > 0 && mergeIndex[j] == i){/*这边i>0也是因为第一列已经是最前一列了,只能从第二列开始*/ /*当前同一列的内容与上一行同一列不同时,把那以上的合并, 或者在当前元素一样的情况下,前一列的元素并不一样,这种情况也合并*/ /*如果不需要考虑当前行与上一行内容相同,但是它们的前一列内容不一样则不合并的情况,把下面条件中||poiModels.get(i).getContent().equals(map.get(title[i])) && !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))去掉就行*/ if(!poiModels.get(i).getContent().equals(map.get(title[i])) || poiModels.get(i).getContent().equals(map.get(title[i])) && !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))){ /*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/ CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex()/*从第二行开始*/, index - 1/*到第几行*/, poiModels.get(i).getCellIndex()/*从某一列开始*/, poiModels.get(i).getCellIndex()/*到第几列*/); //在sheet里增加合并单元格 sheet.addMergedRegion(cra); /*重新记录该列的内容为当前内容,行标记改为当前行标记,列标记则为当前列*/ poiModels.get(i).setContent(map.get(title[i])); poiModels.get(i).setRowIndex(index); poiModels.get(i).setCellIndex(i); } } /*处理第一列的情况*/ if(mergeIndex[j] == i && i == 0 && !poiModels.get(i).getContent().equals(map.get(title[i]))){ /*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/ CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex()/*从第二行开始*/, index - 1/*到第几行*/, poiModels.get(i).getCellIndex()/*从某一列开始*/, poiModels.get(i).getCellIndex()/*到第几列*/); //在sheet里增加合并单元格 sheet.addMergedRegion(cra); /*重新记录该列的内容为当前内容,行标记改为当前行标记*/ poiModels.get(i).setContent(map.get(title[i])); poiModels.get(i).setRowIndex(index); poiModels.get(i).setCellIndex(i); } /*最后一行没有后续的行与之比较,所有当到最后一行时则直接合并对应列的相同内容*/ if(mergeIndex[j] == i && index == list.size()){ CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex()/*从第二行开始*/, index/*到第几行*/, poiModels.get(i).getCellIndex()/*从某一列开始*/, poiModels.get(i).getCellIndex()/*到第几列*/); //在sheet里增加合并单元格 sheet.addMergedRegion(cra); } } Cell cell = row.createCell(i, Cell.CELL_TYPE_STRING); cell.setCellValue(map.get(title[i])); /*在每一个单元格处理完成后,把这个单元格内容设置为old内容*/ poiModels.get(i).setOldContent(old); } index++; } } n++; } /*生成临时文件*/ FileOutputStream out = null; String localPath = null; File tempFile = null; String fileName = String.valueOf(new Date().getTime()/1000); try { tempFile = File.createTempFile(fileName, ".xlsx"); localPath = tempFile.getAbsolutePath(); out = new FileOutputStream(localPath); workbook.write(out); }catch (IOException e){ e.printStackTrace(); }finally { try { out.flush(); out.close(); }catch (IOException e){ e.printStackTrace(); } } return localPath; } public static void main(String[] args) throws IOException{ /*此处标题的数组则对应excel的标题*/ String[] title = {"id","标题","描述","负责人","开始时间"}; List<Map<String, String>> list = Lists.newArrayList(); /*这边是制造一些数据,注意每个list中map的key要和标题数组中的元素一致*/ for(int i = 0; i<10; i++){ HashMap<String, String> map = com.google.common.collect.Maps.newHashMap(); if(i > 5){ if(i<7){ map.put("id","333"); map.put("标题","mmmm"); }else { map.put("id","333"); map.put("标题","aaaaa"); } }else if (i >3){ map.put("id","222"); map.put("标题","哈哈哈哈"); }else if (i>1 && i<3){ map.put("id","222"); map.put("标题","hhhhhhhh"); }else { map.put("id","222"); map.put("标题","bbbb"); } map.put("描述","sssssss"); map.put("负责人","vvvvv"); map.put("开始时间","2017-02-27 11:20:26"); list.add(map); } Map<String/*此处的key为每个sheet的名称,一个excel中可能有多个sheet页*/, List<Map<String/*此处key对应每一列的标题*/, String>>/*该list为每个sheet页的数据*/> map = Maps.newHashMap(); map.put("测试合并数据", list); System.out.println(createExcel(title, map, new int[]{0,1,2}/*此处数组为需要合并的列,可能有的需求是只需要某些列里面相同内容合并*/)); } }
生成的文件效果(两种情况的):
相关文章推荐
- java使用poi导出excel的内容,同时可以利用反射进行动态获取信息
- Java导出excel时合并同一列中相同内容的行思路详解
- java实现任意带table表格的html页面,生成与表格相同内容的excel文件
- 使用poi Java封装对Excel内容的读取,支持合并列形式
- Table中合并相同内容列+Excel中合并相同内容列。
- java根据内容生成动态图片
- 使用JAVA通过JXL(JExcel)动态生成Excel文件 转载至台湾某博客
- 利用java代码生成Excel格式,并获取excel表中的内容
- 简单OA项目笔记(5):生成、下载excel格式的动态表格(POI)
- excel 将A列相同的值对应的B列的单元格进行合并,并保留单元格内容
- 【原创文章】JAVA-POI实现EXCEL下拉框的级联(POI生成Excel中带有可级联的下拉框)
- excel 宏学习(合并相同内容单元格)
- Struts2 + poi 动态生成Excel 下载
- Flex通过Java读取Excel(详细流程)----Excel在客户端(DataGrid动态根据Excel生成)
- Java利用POI生成Excel强制换行 (转载)
- Java利用POI生成Excel强制换行
- Java 使用 poi生成 Excel的方法
- poi 实现 java生成excel
- java利用poi生成excel报表
- Java POI 生成Excel时显示货币格式,如: 23,332.00