浏览代码

fix poi bug

Looly 5 年之前
父节点
当前提交
a2e372b81b

+ 1 - 0
CHANGELOG.md

@@ -25,6 +25,7 @@
 * 【poi    】     修复添加图片尺寸的单位问题(issue#I1C2ER@Gitee)
 * 【setting】     修复getStr中逻辑问题(pr#113@Gitee)
 * 【json   】     修复JSONUtil.toXml汉字被编码的问题(pr#795@Gitee)
+* 【poi    】     修复导出的Map列表中每个map长度不同导致的对应不一致的问题(issue#793@Gitee)
 
 -------------------------------------------------------------------------------------------------------------
 ## 5.2.3

+ 54 - 28
hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java

@@ -1,18 +1,20 @@
 package cn.hutool.poi.excel;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.comparator.IndexedComparator;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.URLUtil;
 import cn.hutool.poi.excel.cell.CellLocation;
+import cn.hutool.poi.excel.cell.CellUtil;
+import cn.hutool.poi.excel.style.Align;
 import org.apache.poi.hssf.usermodel.DVConstraint;
 import org.apache.poi.hssf.usermodel.HSSFDataValidation;
 import org.apache.poi.ss.usermodel.Cell;
@@ -28,20 +30,18 @@ import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
 import org.apache.poi.xssf.usermodel.XSSFDataValidationHelper;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.comparator.IndexedComparator;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.CharsetUtil;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.core.util.URLUtil;
-import cn.hutool.poi.excel.cell.CellUtil;
-import cn.hutool.poi.excel.style.Align;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Excel 写入器<br>
@@ -69,6 +69,8 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
 	private Comparator<String> aliasComparator;
 	/** 样式集,定义不同类型数据样式 */
 	private StyleSet styleSet;
+	/** 标题项对应列号缓存,每次写标题更新此缓存 */
+	private Map<String, Integer> headLocationCache;
 
 	// -------------------------------------------------------------------------- Constructor start
 	/**
@@ -193,6 +195,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
 	 * <pre>
 	 * 1. 当前行游标归零
 	 * 2. 清空别名比较器
+	 * 3. 清除标题缓存
 	 * </pre>
 	 * 
 	 * @return this
@@ -200,6 +203,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
 	public ExcelWriter reset() {
 		resetRow();
 		this.aliasComparator = null;
+		this.headLocationCache = null;
 		return this;
 	}
 
@@ -776,7 +780,16 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
 	 */
 	public ExcelWriter writeHeadRow(Iterable<?> rowData) {
 		Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
-		RowUtil.writeRow(this.sheet.createRow(this.currentRow.getAndIncrement()), rowData, this.styleSet, true);
+		this.headLocationCache = new ConcurrentHashMap<>();
+		final Row row = this.sheet.createRow(this.currentRow.getAndIncrement());
+		int i = 0;
+		Cell cell;
+		for (Object value : rowData) {
+			cell = row.createCell(i);
+			CellUtil.setCellValue(cell, value, this.styleSet, true);
+			this.headLocationCache.put(StrUtil.toString(value), i);
+			i++;
+		}
 		return this;
 	}
 
@@ -842,7 +855,20 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
 		if (isWriteKeyAsHead) {
 			writeHeadRow(aliasMap.keySet());
 		}
-		writeRow(aliasMap.values());
+
+		// 如果已经写出标题行,根据标题行找对应的值写入
+		if(MapUtil.isNotEmpty(this.headLocationCache)){
+			final Row row = RowUtil.getOrCreateRow(this.sheet, this.currentRow.getAndIncrement());
+			Integer location;
+			for (Entry<?, ?> entry : aliasMap.entrySet()) {
+				location = this.headLocationCache.get(StrUtil.toString(entry.getKey()));
+				if(null != location){
+					CellUtil.setCellValue(CellUtil.getOrCreateCell(row, location), entry.getValue(), this.styleSet, false);
+				}
+			}
+		} else{
+			writeRow(aliasMap.values());
+		}
 		return this;
 	}
 

+ 67 - 20
hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelWriteTest.java

@@ -1,28 +1,29 @@
 package cn.hutool.poi.excel.test;
 
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import cn.hutool.core.util.IdUtil;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.junit.Ignore;
-import org.junit.Test;
-
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.poi.excel.ExcelUtil;
 import cn.hutool.poi.excel.ExcelWriter;
 import cn.hutool.poi.excel.style.StyleUtil;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * 写出Excel单元测试
@@ -75,7 +76,7 @@ public class ExcelWriteTest {
 			rows.add(ObjectUtil.clone(row1));
 		}
 
-		String filePath = "f:/test/writeTest.xlsx";
+		String filePath = "d:/test/writeTest.xlsx";
 		FileUtil.del(filePath);
 		// 通过工具类创建writer
 		ExcelWriter writer = ExcelUtil.getWriter(filePath);
@@ -105,7 +106,7 @@ public class ExcelWriteTest {
 		List<List<?>> rows = CollUtil.newArrayList(row1, row2, row3, row4, row5);
 
 		// 通过工具类创建writer
-		ExcelWriter writer = ExcelUtil.getWriter("e:/mergeTest.xlsx");
+		ExcelWriter writer = ExcelUtil.getWriter("d:/test/mergeTest.xlsx");
 		CellStyle style = writer.getStyleSet().getHeadCellStyle();
 		StyleUtil.setColor(style, IndexedColors.RED, FillPatternType.SOLID_FOREGROUND);
 
@@ -143,7 +144,7 @@ public class ExcelWriteTest {
 		ArrayList<Map<String, Object>> rows = CollUtil.newArrayList(row1, row2);
 
 		// 通过工具类创建writer
-		ExcelWriter writer = ExcelUtil.getWriter("f:/test/writeMapTest.xlsx");
+		ExcelWriter writer = ExcelUtil.getWriter("d:/test/writeMapTest.xlsx");
 		// 合并单元格后的标题行,使用默认标题样式
 		writer.merge(row1.size() - 1, "一班成绩单");
 
@@ -254,7 +255,7 @@ public class ExcelWriteTest {
 
 		List<Map<Object, Object>> rows = CollUtil.newArrayList(row1, row2);
 		// 通过工具类创建writer
-		String file = "e:/writeMapAlias.xlsx";
+		String file = "d:/test/writeMapAlias.xlsx";
 		FileUtil.del(file);
 		ExcelWriter writer = ExcelUtil.getWriter(file);
 		// 自定义标题
@@ -411,7 +412,7 @@ public class ExcelWriteTest {
 	@Ignore
 	public void addSelectTest() {
 		List<String> row = CollUtil.newArrayList("姓名", "加班日期", "下班时间", "加班时长", "餐补", "车补次数", "车补", "总计");
-		ExcelWriter overtimeWriter = ExcelUtil.getWriter("f:/excel/single_line.xlsx");
+		ExcelWriter overtimeWriter = ExcelUtil.getWriter("d:/test/single_line.xlsx");
 		overtimeWriter.writeCellValue(3, 4, "AAAA");
 		overtimeWriter.addSelect(3, 4, row.toArray(new String[0]));
 		overtimeWriter.close();
@@ -419,6 +420,24 @@ public class ExcelWriteTest {
 
 	@Test
 	@Ignore
+	public void addSelectTest2() {
+		ExcelWriter writer = ExcelUtil.getWriter("d:/test/select.xlsx");
+		writer.writeCellValue(0, 0, "请选择科目");
+		int firstRow = 0;
+		int lastRow = 0;
+		int firstCol = 0;
+		int lastCol = 0;
+		CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
+		writer.addSelect(addressList, "1001", "1002", "1003");
+
+		List<?> rows = new ArrayList<>();
+		writer.write(rows, true);
+
+		writer.close();
+	}
+
+	@Test
+	@Ignore
 	public void writeMultiSheetTest(){
 		List<Map<String, Object>> rows = new LinkedList<>();
 		for (int i = 0; i < 10; i++) {
@@ -440,4 +459,32 @@ public class ExcelWriteTest {
 		writer.autoSizeColumnAll();
 		writer.close();
 	}
+
+	@Test
+	@Ignore
+	public void writeMapsTest(){
+		List<Map<String,Object>> rows = new ArrayList<>();
+
+		Map<String, Object> map1 = new HashMap<>();
+		map1.put("a",1);
+		map1.put("b",2);
+		map1.put("c",3);
+		map1.put("d",4);
+		map1.put("e",5);
+		Map<String, Object> map2 = new HashMap<>();
+		map2.put("c",3);
+		map2.put("d",4);
+		map2.put("e",5);
+		Map<String, Object> map3 = new HashMap<>();
+		map3.put("d",4);
+		map3.put("e",5);
+
+		rows.add(map1);
+		rows.add(map2);
+		rows.add(map3);
+
+		final ExcelWriter writer = ExcelUtil.getWriter("d:/test/rows.xlsx");
+		writer.write(rows);
+		writer.close();
+	}
 }