diff --git a/pom.xml b/pom.xml index b5ae5cbf..6477cfef 100644 --- a/pom.xml +++ b/pom.xml @@ -163,6 +163,7 @@ com/alibaba/excel/event/AnalysisEventListener.java com/alibaba/excel/metadata/DataFormatter.java com/alibaba/excel/util/DateUtils.java + com/alibaba/excel/util/MapUtils.java com/alibaba/excel/metadata/format/DataFormatter.java com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java diff --git a/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java b/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java index 86a93d48..2416635d 100644 --- a/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java +++ b/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java @@ -102,8 +102,7 @@ public class ClientAnchorData extends CoordinateData { ClientAnchor.AnchorType value; - // disallow non-sequential enum instance creation - private AnchorType(ClientAnchor.AnchorType value) { + AnchorType(ClientAnchor.AnchorType value) { this.value = value; } diff --git a/src/main/java/com/alibaba/excel/util/MapUtils.java b/src/main/java/com/alibaba/excel/util/MapUtils.java index eb4409a3..d46da90a 100644 --- a/src/main/java/com/alibaba/excel/util/MapUtils.java +++ b/src/main/java/com/alibaba/excel/util/MapUtils.java @@ -27,7 +27,7 @@ public class MapUtils { * @return a new, empty {@code HashMap} */ public static HashMap newHashMap() { - return new HashMap<>(); + return new HashMap<>(16); } /** diff --git a/src/main/java/com/alibaba/excel/util/StyleUtil.java b/src/main/java/com/alibaba/excel/util/StyleUtil.java index 4f10a1b0..0b70cf9b 100644 --- a/src/main/java/com/alibaba/excel/util/StyleUtil.java +++ b/src/main/java/com/alibaba/excel/util/StyleUtil.java @@ -18,6 +18,7 @@ import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.Units; import org.apache.poi.xssf.usermodel.XSSFRichTextString; /** @@ -25,8 +26,6 @@ import org.apache.poi.xssf.usermodel.XSSFRichTextString; */ public class StyleUtil { - public static int baseCoordinate = 10000; - private StyleUtil() {} /** @@ -191,7 +190,7 @@ public class StyleUtil { if (coordinate == null) { return 0; } - return baseCoordinate * coordinate; + return Units.toEMU(coordinate); } public static int getCellCoordinate(Integer currentCoordinate, Integer absoluteCoordinate, diff --git a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java index 879d16c2..aa8a2578 100644 --- a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java @@ -32,6 +32,7 @@ import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; @@ -61,6 +62,8 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { // Fill in picture information fillImage(cell, cellData.getImageDataList()); + //setImageValue(cellData,cell); + // Fill in comment information fillComment(cell, cellData.getCommentData()); @@ -197,10 +200,10 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { anchor.setDy1(StyleUtil.getCoordinate(imageData.getTop())); } if (imageData.getRight() != null) { - anchor.setDx2(StyleUtil.getCoordinate(imageData.getRight())); + anchor.setDx2(-StyleUtil.getCoordinate(imageData.getRight())); } if (imageData.getBottom() != null) { - anchor.setDy2(StyleUtil.getCoordinate(imageData.getBottom())); + anchor.setDy2(-StyleUtil.getCoordinate(imageData.getBottom())); } if (imageData.getLeft() != null) { anchor.setDx1(StyleUtil.getCoordinate(imageData.getLeft())); @@ -210,20 +213,24 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { anchor.setCol1(StyleUtil.getCellCoordinate(cell.getColumnIndex(), imageData.getFirstColumnIndex(), imageData.getRelativeFirstColumnIndex())); anchor.setRow2(StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), imageData.getLastRowIndex(), - imageData.getRelativeLastRowIndex())); + imageData.getRelativeLastRowIndex()) + 1); anchor.setCol2(StyleUtil.getCellCoordinate(cell.getColumnIndex(), imageData.getLastColumnIndex(), - imageData.getRelativeLastColumnIndex())); + imageData.getRelativeLastColumnIndex()) + 1); if (imageData.getAnchorType() != null) { anchor.setAnchorType(imageData.getAnchorType().getValue()); } - drawing.createPicture(anchor, index); + Picture picture = drawing.createPicture(anchor, index); + //picture.resize(0.5, 0.5); } } protected WriteCellData convert(WriteHolder currentWriteHolder, Class clazz, CellDataTypeEnum targetType, Cell cell, Object value, ExcelContentProperty excelContentProperty) { // This means that the user has defined the data. - if (value instanceof WriteCellData) { + if (clazz == WriteCellData.class) { + if (value == null) { + return new WriteCellData<>(CellDataTypeEnum.EMPTY); + } WriteCellData cellDataValue = (WriteCellData)value; if (cellDataValue.getType() != null) { return cellDataValue; diff --git a/src/main/java/com/alibaba/excel/write/metadata/RowData.java b/src/main/java/com/alibaba/excel/write/metadata/RowData.java index 937395b9..cb86a3e0 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/RowData.java +++ b/src/main/java/com/alibaba/excel/write/metadata/RowData.java @@ -6,9 +6,13 @@ package com.alibaba.excel.write.metadata; * @author Jiaju Zhuang */ public interface RowData { + /** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. + * + * @param index + * @return data */ Object get(int index); diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDemoData.java similarity index 78% rename from src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java rename to src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDemoData.java index 3fcb9484..ba80d6f1 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDemoData.java @@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.alibaba.excel.converters.string.StringImageConverter; +import com.alibaba.excel.metadata.data.WriteCellData; import lombok.Data; @@ -19,7 +20,7 @@ import lombok.Data; @Data @ContentRowHeight(100) @ColumnWidth(100 / 8) -public class ImageData { +public class ImageDemoData { private File file; private InputStream inputStream; /** @@ -34,4 +35,11 @@ public class ImageData { * @since 2.1.1 */ private URL url; + + /** + * 根据文件导出 并设置导出的位置。 + * + * @since 3.0.0-beta1 + */ + private WriteCellData writeCellDataFile; } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java index ced2ffde..a0c44853 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java @@ -18,6 +18,10 @@ import com.alibaba.excel.annotation.format.NumberFormat; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.data.ImageData; +import com.alibaba.excel.metadata.data.ImageData.ImageType; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.write.merge.LoopMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; @@ -194,7 +198,8 @@ public class WriteTest { excelWriter = EasyExcel.write(fileName).build(); // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面 for (int i = 0; i < 5; i++) { - // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变 + // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class + // 实际上可以一直变 WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build(); // 分页去数据库查询数据 这里可以去数据库查询每一页的数据 List data = data(); @@ -227,7 +232,7 @@ public class WriteTest { /** * 图片导出 *

- * 1. 创建excel对应的实体对象 参照{@link ImageData} + * 1. 创建excel对应的实体对象 参照{@link ImageDemoData} *

* 2. 直接写即可 */ @@ -237,19 +242,49 @@ public class WriteTest { // 如果使用流 记得关闭 InputStream inputStream = null; try { - List list = new ArrayList(); - ImageData imageData = new ImageData(); - list.add(imageData); + List list = new ArrayList<>(); + ImageDemoData imageDemoData = new ImageDemoData(); + list.add(imageDemoData); String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg"; // 放入五种类型的图片 实际使用只要选一种即可 - imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath))); - imageData.setFile(new File(imagePath)); - imageData.setString(imagePath); + imageDemoData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath))); + imageDemoData.setFile(new File(imagePath)); + imageDemoData.setString(imagePath); inputStream = FileUtils.openInputStream(new File(imagePath)); - imageData.setInputStream(inputStream); - imageData.setUrl(new URL( - "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg")); - EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list); + imageDemoData.setInputStream(inputStream); + imageDemoData.setUrl(new URL( + "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg")); + + // 这里演示 图片 不想顶格放 且占用2个单元格的情况 + WriteCellData writeCellData = new WriteCellData<>(); + imageDemoData.setWriteCellDataFile(writeCellData); + // 设置为空 代表当前单元格不需要写图片以外的数据 + writeCellData.setType(CellDataTypeEnum.EMPTY); + // 可以放入多个图片 + List imageDataList = new ArrayList<>(); + ImageData imageData = new ImageData(); + imageDataList.add(imageData); + writeCellData.setImageDataList(imageDataList); + // 放入2进制图片 + imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath))); + // 图片类型 + imageData.setImageType(ImageType.PICTURE_TYPE_PNG); + // 上 右 下 左 需要留空 + // 这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。 + imageData.setTop(5); + imageData.setRight(5); + imageData.setBottom(5); + imageData.setLeft(5); + // 设置图片的位置 假设 现在目标 是 覆盖 当前单元格 和当前单元格右边的单元格 + // 起点相对于当前单元格为0 当然可以不写 + imageData.setRelativeFirstRowIndex(0); + imageData.setRelativeFirstColumnIndex(0); + imageData.setRelativeLastRowIndex(0); + // 前面3个可以不写 下面这个需要写 也就是 结尾 需要相对当前单元格 往右移动一格 + imageData.setRelativeLastColumnIndex(1); + + // 写入数据 + EasyExcel.write(fileName, ImageDemoData.class).sheet().doWrite(list); } finally { if (inputStream != null) { inputStream.close(); @@ -325,7 +360,7 @@ public class WriteTest { // 背景设置为红色 headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex()); WriteFont headWriteFont = new WriteFont(); - headWriteFont.setFontHeightInPoints((short) 20); + headWriteFont.setFontHeightInPoints((short)20); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); @@ -335,7 +370,7 @@ public class WriteTest { contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 - contentWriteFont.setFontHeightInPoints((short) 20); + contentWriteFont.setFontHeightInPoints((short)20); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = @@ -428,7 +463,8 @@ public class WriteTest { /** * 自动列宽(不太精确) *

- * 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 {@link LongestMatchColumnWidthStyleStrategy}重新实现. + * 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 {@link LongestMatchColumnWidthStyleStrategy} + * 重新实现. *

* poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。 *