diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgType.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgType.java new file mode 100644 index 000000000..08254658c --- /dev/null +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgType.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.poi.excel; + +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Excel支持的图片类型枚举 + * + * @author Looly + * @see Workbook#PICTURE_TYPE_EMF + * @see Workbook#PICTURE_TYPE_WMF + * @see Workbook#PICTURE_TYPE_PICT + * @see Workbook#PICTURE_TYPE_JPEG + * @see Workbook#PICTURE_TYPE_PNG + * @see Workbook#PICTURE_TYPE_DIB + * @since 6.0.0 + */ +public enum ExcelImgType { + /** + * Extended windows meta file + */ + EMF(Workbook.PICTURE_TYPE_EMF), + + /** + * Windows Meta File + */ + WMF(Workbook.PICTURE_TYPE_WMF), + + /** + * Mac PICT format + */ + PICT(Workbook.PICTURE_TYPE_PICT), + + /** + * JPEG format + */ + JPEG(Workbook.PICTURE_TYPE_JPEG), + + /** + * PNG format + */ + PNG(Workbook.PICTURE_TYPE_PNG), + + /** + * Device independent bitmap + */ + DIB(Workbook.PICTURE_TYPE_DIB); + + private final int value; + + /** + * 构造 + * + * @param value 类型编码 + */ + ExcelImgType(final int value) { + this.value = value; + } + + /** + * 获取类型编码 + * + * @return 编码 + */ + public int getValue() { + return this.value; + } +} diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgUtil.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgUtil.java index be2676d04..40df5eedb 100644 --- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgUtil.java +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelImgUtil.java @@ -12,25 +12,15 @@ package org.dromara.hutool.poi.excel; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.ooxml.POIXMLDocumentPart; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.*; import org.dromara.hutool.core.collection.CollUtil; import org.dromara.hutool.core.io.file.FileTypeUtil; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.map.multi.ListValueMap; import org.dromara.hutool.core.text.StrUtil; -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.hssf.usermodel.HSSFPicture; -import org.apache.poi.hssf.usermodel.HSSFPictureData; -import org.apache.poi.hssf.usermodel.HSSFShape; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ss.usermodel.PictureData; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFDrawing; -import org.apache.poi.xssf.usermodel.XSSFPicture; -import org.apache.poi.xssf.usermodel.XSSFShape; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; import java.io.File; @@ -51,22 +41,22 @@ public class ExcelImgUtil { * @return 图片类型,默认PNG * @since 6.0.0 */ - public static int getImgType(final File imgFile) { + public static ExcelImgType getImgType(final File imgFile) { final String type = FileTypeUtil.getType(imgFile); if (StrUtil.equalsAnyIgnoreCase(type, "jpg", "jpeg")) { - return Workbook.PICTURE_TYPE_JPEG; + return ExcelImgType.JPEG; } else if (StrUtil.equalsAnyIgnoreCase(type, "emf")) { - return Workbook.PICTURE_TYPE_EMF; + return ExcelImgType.EMF; } else if (StrUtil.equalsAnyIgnoreCase(type, "wmf")) { - return Workbook.PICTURE_TYPE_WMF; + return ExcelImgType.WMF; } else if (StrUtil.equalsAnyIgnoreCase(type, "pict")) { - return Workbook.PICTURE_TYPE_PICT; + return ExcelImgType.PICT; } else if (StrUtil.equalsAnyIgnoreCase(type, "dib")) { - return Workbook.PICTURE_TYPE_DIB; + return ExcelImgType.DIB; } // 默认格式 - return Workbook.PICTURE_TYPE_PNG; + return ExcelImgType.PNG; } /** @@ -91,6 +81,27 @@ public class ExcelImgUtil { } } + /** + * 写出图片,本方法只是将数据写入Workbook中的Sheet,并不写出到文件
+ * 添加图片到当前sheet中 + * + * @param sheet {@link Sheet} + * @param pictureData 数据bytes + * @param imgType 图片类型,对应poi中Workbook类中的图片类型2-7变量 + * @param clientAnchor 图片的位置和大小信息 + * @author vhukze + * @since 6.0.0 + */ + public static void writeImg(final Sheet sheet, final byte[] pictureData, + final ExcelImgType imgType, final SimpleClientAnchor clientAnchor) { + final Drawing patriarch = sheet.createDrawingPatriarch(); + final Workbook workbook = sheet.getWorkbook(); + final ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor(); + clientAnchor.copyTo(anchor); + + patriarch.createPicture(anchor, workbook.addPicture(pictureData, imgType.getValue())); + } + // -------------------------------------------------------------------------------------------------------------- Private method start /** diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelUtil.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelUtil.java index 412cbacc3..748da1280 100644 --- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelUtil.java +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/ExcelUtil.java @@ -261,7 +261,7 @@ public class ExcelUtil { /** * 获得{@link ExcelWriter},默认写出到第一个sheet
* 不传入写出的Excel文件路径,只能调用ExcelWriter#flush(OutputStream)方法写出到流
- * 若写出到文件,还需调用{@link ExcelWriter#setDestFile(File)}方法自定义写出的文件,然后调用{@link ExcelWriter#flush()}方法写出到文件 + * 若写出到文件,还需调用{@link ExcelWriter#setTargetFile(File)}方法自定义写出的文件,然后调用{@link ExcelWriter#flush()}方法写出到文件 * * @return {@link ExcelWriter} * @since 3.2.1 @@ -277,7 +277,7 @@ public class ExcelUtil { /** * 获得{@link ExcelWriter},默认写出到第一个sheet
* 不传入写出的Excel文件路径,只能调用ExcelWriter#flush(OutputStream)方法写出到流
- * 若写出到文件,还需调用{@link ExcelWriter#setDestFile(File)}方法自定义写出的文件,然后调用{@link ExcelWriter#flush()}方法写出到文件 + * 若写出到文件,还需调用{@link ExcelWriter#setTargetFile(File)}方法自定义写出的文件,然后调用{@link ExcelWriter#flush()}方法写出到文件 * * @param isXlsx 是否为xlsx格式 * @return {@link ExcelWriter} @@ -370,7 +370,7 @@ public class ExcelUtil { /** * 获得{@link BigExcelWriter},默认写出到第一个sheet
* 不传入写出的Excel文件路径,只能调用ExcelWriter#flush(OutputStream)方法写出到流
- * 若写出到文件,还需调用{@link BigExcelWriter#setDestFile(File)}方法自定义写出的文件,然后调用{@link BigExcelWriter#flush()}方法写出到文件 + * 若写出到文件,还需调用{@link BigExcelWriter#setTargetFile(File)}方法自定义写出的文件,然后调用{@link BigExcelWriter#flush()}方法写出到文件 * * @return {@link BigExcelWriter} * @since 4.1.13 @@ -386,7 +386,7 @@ public class ExcelUtil { /** * 获得{@link BigExcelWriter},默认写出到第一个sheet
* 不传入写出的Excel文件路径,只能调用ExcelWriter#flush(OutputStream)方法写出到流
- * 若写出到文件,还需调用{@link BigExcelWriter#setDestFile(File)}方法自定义写出的文件,然后调用{@link BigExcelWriter#flush()}方法写出到文件 + * 若写出到文件,还需调用{@link BigExcelWriter#setTargetFile(File)}方法自定义写出的文件,然后调用{@link BigExcelWriter#flush()}方法写出到文件 * * @param rowAccessWindowSize 在内存中的行数 * @return {@link BigExcelWriter} diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/setters/ImgCellSetter.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/setters/ImgCellSetter.java index d47b5d385..209d8d6c1 100644 --- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/setters/ImgCellSetter.java +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/setters/ImgCellSetter.java @@ -14,7 +14,9 @@ package org.dromara.hutool.poi.excel.cell.setters; import org.apache.poi.ss.usermodel.*; import org.dromara.hutool.core.io.file.FileUtil; +import org.dromara.hutool.poi.excel.ExcelImgType; import org.dromara.hutool.poi.excel.ExcelImgUtil; +import org.dromara.hutool.poi.excel.SimpleClientAnchor; import java.io.File; @@ -27,7 +29,7 @@ import java.io.File; public class ImgCellSetter implements CellSetter { private final byte[] pictureData; - private final int imgType; + private final ExcelImgType imgType; // region ----- 构造 @@ -37,7 +39,7 @@ public class ImgCellSetter implements CellSetter { * @param pictureData 图片数据 */ public ImgCellSetter(final byte[] pictureData) { - this(pictureData, Workbook.PICTURE_TYPE_PNG); + this(pictureData, ExcelImgType.PNG); } /** @@ -55,7 +57,7 @@ public class ImgCellSetter implements CellSetter { * @param pictureData 图片数据 * @param imgType 图片类型 */ - public ImgCellSetter(final byte[] pictureData, final int imgType) { + public ImgCellSetter(final byte[] pictureData, final ExcelImgType imgType) { this.pictureData = pictureData; this.imgType = imgType; } @@ -64,18 +66,10 @@ public class ImgCellSetter implements CellSetter { @Override public void setValue(final Cell cell) { final Sheet sheet = cell.getSheet(); - final Workbook workbook = sheet.getWorkbook(); - final Drawing patriarch = sheet.createDrawingPatriarch(); - final ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor(); - final int columnIndex = cell.getColumnIndex(); final int rowIndex = cell.getRowIndex(); - // 填充当前单元格 - anchor.setCol1(columnIndex); - anchor.setRow1(rowIndex); - anchor.setCol2(columnIndex + 1); - anchor.setRow2(rowIndex + 1); - patriarch.createPicture(anchor, workbook.addPicture(this.pictureData, this.imgType)); + ExcelImgUtil.writeImg(sheet, this.pictureData, this.imgType, + new SimpleClientAnchor(columnIndex, rowIndex, columnIndex + 1, rowIndex + 1)); } } diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/BigExcelWriter.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/BigExcelWriter.java index 60fcb0a31..918d4e63c 100644 --- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/BigExcelWriter.java +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/BigExcelWriter.java @@ -49,7 +49,7 @@ public class BigExcelWriter extends ExcelWriter { /** * 构造,默认生成xlsx格式的Excel文件
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(java.io.OutputStream)}方法写出到流
- * 若写出到文件,还需调用{@link #setDestFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 + * 若写出到文件,还需调用{@link #setTargetFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 */ public BigExcelWriter() { this(DEFAULT_WINDOW_SIZE); @@ -136,7 +136,7 @@ public class BigExcelWriter extends ExcelWriter { /** * 构造
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(java.io.OutputStream)}方法写出到流
- * 若写出到文件,还需调用{@link #setDestFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 + * 若写出到文件,还需调用{@link #setTargetFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 * * @param workbook {@link SXSSFWorkbook} * @param sheetName sheet名,做为第一个sheet名并写出到此sheet,例如sheet1 @@ -148,7 +148,7 @@ public class BigExcelWriter extends ExcelWriter { /** * 构造
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(java.io.OutputStream)}方法写出到流
- * 若写出到文件,还需调用{@link #setDestFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 + * 若写出到文件,还需调用{@link #setTargetFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 * * @param sheet {@link Sheet} * @since 4.0.6 diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriteConfig.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriteConfig.java index a8582e3b4..7e5b17f70 100644 --- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriteConfig.java +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriteConfig.java @@ -14,9 +14,14 @@ package org.dromara.hutool.poi.excel.writer; import org.dromara.hutool.core.comparator.IndexedComparator; import org.dromara.hutool.core.map.MapUtil; +import org.dromara.hutool.core.map.TableMap; +import org.dromara.hutool.core.map.multi.RowKeyTable; +import org.dromara.hutool.core.map.multi.Table; +import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.poi.excel.ExcelConfig; import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -85,4 +90,31 @@ public class ExcelWriteConfig extends ExcelConfig { } return aliasComparator; } + + /** + * 为指定的key列表添加标题别名,如果没有定义key的别名,在onlyAlias为false时使用原key
+ * key为别名,value为字段值 + * + * @param rowMap 一行数据 + * @return 别名列表 + */ + public Table aliasTable(final Map rowMap) { + final Table filteredTable = new RowKeyTable<>(new LinkedHashMap<>(), TableMap::new); + if (MapUtil.isEmpty(headerAlias)) { + rowMap.forEach((key, value) -> filteredTable.put(key, key, value)); + } else { + rowMap.forEach((key, value) -> { + final String aliasName = headerAlias.get(StrUtil.toString(key)); + if (null != aliasName) { + // 别名键值对加入 + filteredTable.put(key, aliasName, value); + } else if (!onlyAlias) { + // 保留无别名设置的键值对 + filteredTable.put(key, key, value); + } + }); + } + + return filteredTable; + } } diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriter.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriter.java index 1ef7917cc..8ec35b0f0 100644 --- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriter.java +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/ExcelWriter.java @@ -13,15 +13,13 @@ package org.dromara.hutool.poi.excel.writer; import org.apache.poi.common.usermodel.Hyperlink; -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.hssf.usermodel.HSSFPatriarch; -import org.apache.poi.hssf.usermodel.HSSFSimpleShape; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.streaming.SXSSFSheet; -import org.apache.poi.xssf.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.apache.poi.xssf.usermodel.XSSFSheet; import org.dromara.hutool.core.bean.BeanUtil; import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.io.IORuntimeException; @@ -29,9 +27,7 @@ import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.io.file.FileUtil; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.map.MapUtil; -import org.dromara.hutool.core.map.TableMap; import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap; -import org.dromara.hutool.core.map.multi.RowKeyTable; import org.dromara.hutool.core.map.multi.Table; import org.dromara.hutool.core.reflect.FieldUtil; import org.dromara.hutool.core.text.StrUtil; @@ -60,7 +56,6 @@ import java.util.concurrent.atomic.AtomicInteger; * @author Looly * @since 3.2.0 */ -@SuppressWarnings("resource") public class ExcelWriter extends ExcelBase { /** @@ -81,7 +76,7 @@ public class ExcelWriter extends ExcelBase { /** * 构造,默认生成xlsx格式的Excel文件
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(OutputStream)}方法写出到流
- * 若写出到文件,还需调用{@link #setDestFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 + * 若写出到文件,还需调用{@link #setTargetFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 * * @since 3.2.1 */ @@ -145,18 +140,22 @@ public class ExcelWriter extends ExcelBase { /** * 构造 * - * @param destFile 目标文件,可以不存在 - * @param sheetName sheet名,做为第一个sheet名并写出到此sheet,例如sheet1 + * @param targetFile 目标文件,可以不存在 + * @param sheetName sheet名,做为第一个sheet名并写出到此sheet,例如sheet1 */ - public ExcelWriter(final File destFile, final String sheetName) { - this(WorkbookUtil.createBookForWriter(destFile), sheetName); - this.targetFile = destFile; + public ExcelWriter(final File targetFile, final String sheetName) { + this(WorkbookUtil.createBookForWriter(targetFile), sheetName); + + if (!FileUtil.exists(targetFile)) { + this.targetFile = targetFile; + } + // 如果是已经存在的文件,则作为模板加载,此时不能写出到模板文件 } /** * 构造
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(OutputStream)}方法写出到流
- * 若写出到文件,还需调用{@link #setDestFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 + * 若写出到文件,还需调用{@link #setTargetFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 * * @param workbook {@link Workbook} * @param sheetName sheet名,做为第一个sheet名并写出到此sheet,例如sheet1 @@ -168,7 +167,7 @@ public class ExcelWriter extends ExcelBase { /** * 构造
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(OutputStream)}方法写出到流
- * 若写出到文件,还需调用{@link #setDestFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 + * 若写出到文件,还需调用{@link #setTargetFile(File)}方法自定义写出的文件,然后调用{@link #flush()}方法写出到文件 * * @param sheet {@link Sheet} * @since 4.0.6 @@ -188,16 +187,16 @@ public class ExcelWriter extends ExcelBase { @Override public ExcelWriter setSheet(final int sheetIndex) { + super.setSheet(sheetIndex); // 切换到新sheet需要重置开始行 - reset(); - return super.setSheet(sheetIndex); + return reset(); } @Override public ExcelWriter setSheet(final String sheetName) { + super.setSheet(sheetName); // 切换到新sheet需要重置开始行 - reset(); - return super.setSheet(sheetName); + return reset(); } /** @@ -205,15 +204,14 @@ public class ExcelWriter extends ExcelBase { * *
 	 * 1. 当前行游标归零
-	 * 2. 清空别名比较器
-	 * 3. 清除标题缓存
+	 * 2. 清除标题缓存
 	 * 
* * @return this */ public ExcelWriter reset() { - resetRow(); - return this; + this.headLocationCache.clear(); + return resetRow(); } /** @@ -250,6 +248,7 @@ public class ExcelWriter extends ExcelBase { * @return this * @since 4.0.12 */ + @SuppressWarnings("resource") public ExcelWriter autoSizeColumnAll(final boolean useMergedCells, final float widthRatio) { final int columnCount = this.getColumnCount(); for (int i = 0; i < columnCount; i++) { @@ -379,13 +378,14 @@ public class ExcelWriter extends ExcelBase { } /** - * 设置写出的目标文件 + * 设置写出的目标文件
+ * 注意这个文件不能存在,存在则{@link #flush()}时会被覆盖 * - * @param destFile 目标文件 + * @param targetFile 目标文件 * @return this */ - public ExcelWriter setDestFile(final File destFile) { - this.targetFile = destFile; + public ExcelWriter setTargetFile(final File targetFile) { + this.targetFile = targetFile; return this; } @@ -600,6 +600,7 @@ public class ExcelWriter extends ExcelBase { * @return this * @since 4.0.10 */ + @SuppressWarnings("resource") public ExcelWriter merge(final int lastColumn, final Object content, final boolean isSetHeaderStyle) { Assert.isFalse(this.isClosed, "ExcelWriter has been closed!"); @@ -696,6 +697,7 @@ public class ExcelWriter extends ExcelBase { * @param isWriteKeyAsHead 是否强制写出标题行(Map或Bean) * @return this */ + @SuppressWarnings("resource") public ExcelWriter write(final Iterable data, final boolean isWriteKeyAsHead) { Assert.isFalse(this.isClosed, "ExcelWriter has been closed!"); boolean isFirst = true; @@ -723,7 +725,7 @@ public class ExcelWriter extends ExcelBase { * @return this * @since 3.2.3 */ - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings({"rawtypes", "unchecked", "resource"}) public ExcelWriter write(final Iterable data, final Comparator comparator) { Assert.isFalse(this.isClosed, "ExcelWriter has been closed!"); boolean isFirstRow = true; @@ -787,7 +789,7 @@ public class ExcelWriter extends ExcelBase { * @author vhukze * @since 6.0.0 */ - public ExcelWriter writeImg(final File imgFile, final int imgType, final SimpleClientAnchor clientAnchor) { + public ExcelWriter writeImg(final File imgFile, final ExcelImgType imgType, final SimpleClientAnchor clientAnchor) { return writeImg(FileUtil.readBytes(imgFile), imgType, clientAnchor); } @@ -802,12 +804,8 @@ public class ExcelWriter extends ExcelBase { * @author vhukze * @since 6.0.0 */ - public ExcelWriter writeImg(final byte[] pictureData, final int imgType, final SimpleClientAnchor clientAnchor) { - final Drawing patriarch = this.sheet.createDrawingPatriarch(); - final ClientAnchor anchor = this.workbook.getCreationHelper().createClientAnchor(); - clientAnchor.copyTo(anchor); - - patriarch.createPicture(anchor, this.workbook.addPicture(pictureData, imgType)); + public ExcelWriter writeImg(final byte[] pictureData, final ExcelImgType imgType, final SimpleClientAnchor clientAnchor) { + ExcelImgUtil.writeImg(this.sheet, pictureData, imgType, clientAnchor); return this; } @@ -844,34 +842,8 @@ public class ExcelWriter extends ExcelBase { * @return this * @since 6.0.0 */ - public ExcelWriter writeSimpleShape(final SimpleClientAnchor clientAnchor, ShapeConfig shapeConfig) { - final Drawing patriarch = this.sheet.createDrawingPatriarch(); - final ClientAnchor anchor = this.workbook.getCreationHelper().createClientAnchor(); - clientAnchor.copyTo(anchor); - - if (null == shapeConfig) { - shapeConfig = ShapeConfig.of(); - } - final Color lineColor = shapeConfig.getLineColor(); - if (patriarch instanceof HSSFPatriarch) { - final HSSFSimpleShape simpleShape = ((HSSFPatriarch) patriarch).createSimpleShape((HSSFClientAnchor) anchor); - simpleShape.setShapeType(shapeConfig.getShapeType().ooxmlId); - simpleShape.setLineStyle(shapeConfig.getLineStyle().getValue()); - simpleShape.setLineWidth(shapeConfig.getLineWidth()); - if (null != lineColor) { - simpleShape.setLineStyleColor(lineColor.getRed(), lineColor.getGreen(), lineColor.getBlue()); - } - } else if (patriarch instanceof XSSFDrawing) { - final XSSFSimpleShape simpleShape = ((XSSFDrawing) patriarch).createSimpleShape((XSSFClientAnchor) anchor); - simpleShape.setShapeType(shapeConfig.getShapeType().ooxmlId); - simpleShape.setLineStyle(shapeConfig.getLineStyle().getValue()); - simpleShape.setLineWidth(shapeConfig.getLineWidth()); - if (null != lineColor) { - simpleShape.setLineStyleColor(lineColor.getRed(), lineColor.getGreen(), lineColor.getBlue()); - } - } else { - throw new UnsupportedOperationException("Unsupported patriarch type: " + patriarch.getClass().getName()); - } + public ExcelWriter writeSimpleShape(final SimpleClientAnchor clientAnchor, final ShapeConfig shapeConfig) { + SimpleShapeUtil.writeSimpleShape(this.sheet, clientAnchor, shapeConfig); return this; } // endregion @@ -914,6 +886,7 @@ public class ExcelWriter extends ExcelBase { * @param rowData 一行的数据 * @return this */ + @SuppressWarnings("resource") public ExcelWriter writeSecHeadRow(final Iterable rowData) { final Row row = RowUtil.getOrCreateRow(this.sheet, this.currentRow.getAndIncrement()); final Iterator iterator = rowData.iterator(); @@ -994,6 +967,7 @@ public class ExcelWriter extends ExcelBase { * @param isWriteKeyAsHead 为true写出两行,Map的keys做为一行,values做为第二行,否则只写出一行values * @return this */ + @SuppressWarnings("resource") public ExcelWriter writeRow(final Map rowMap, final boolean isWriteKeyAsHead) { Assert.isFalse(this.isClosed, "ExcelWriter has been closed!"); if (MapUtil.isEmpty(rowMap)) { @@ -1001,7 +975,7 @@ public class ExcelWriter extends ExcelBase { return passCurrentRow(); } - final Table aliasTable = aliasTable(rowMap); + final Table aliasTable = this.config.aliasTable(rowMap); if (isWriteKeyAsHead) { // 写出标题行,并记录标题别名和列号的关系 writeHeadRow(aliasTable.columnKeys()); @@ -1075,6 +1049,7 @@ public class ExcelWriter extends ExcelBase { * @param isWriteKeyAsHead 是否将Map的Key作为表头输出,如果为True第一行为表头,紧接着为values * @return this */ + @SuppressWarnings("resource") public ExcelWriter writeCol(final Map> colMap, int startColIndex, final boolean isWriteKeyAsHead) { for (final Object k : colMap.keySet()) { final Iterable v = colMap.get(k); @@ -1112,6 +1087,7 @@ public class ExcelWriter extends ExcelBase { * @param isResetRowIndex 如果为true,写入完毕后Row index 将会重置为写入之前的未知,如果为false,写入完毕后Row index将会在写完的数据下方 * @return this */ + @SuppressWarnings("resource") public ExcelWriter writeCol(final Object headerVal, final int colIndex, final Iterable colData, final boolean isResetRowIndex) { Assert.isFalse(this.isClosed, "ExcelWriter has been closed!"); int currentRowIndex = currentRow.get(); @@ -1297,7 +1273,7 @@ public class ExcelWriter extends ExcelBase { /** * 将Excel Workbook刷出到预定义的文件
* 如果用户未自定义输出的文件,将抛出{@link NullPointerException}
- * 预定义文件可以通过{@link #setDestFile(File)} 方法预定义,或者通过构造定义 + * 预定义文件可以通过{@link #setTargetFile(File)} 方法预定义,或者通过构造定义 * * @return this * @throws IORuntimeException IO异常 @@ -1360,6 +1336,7 @@ public class ExcelWriter extends ExcelBase { * 关闭工作簿
* 如果用户设定了目标文件,先写出目标文件后给关闭工作簿 */ + @SuppressWarnings("resource") @Override public void close() { if (null != this.targetFile) { @@ -1378,36 +1355,4 @@ public class ExcelWriter extends ExcelBase { // 清空对象 this.styleSet = null; } - - // region ----- Private method start - - /** - * 为指定的key列表添加标题别名,如果没有定义key的别名,在onlyAlias为false时使用原key
- * key为别名,value为字段值 - * - * @param rowMap 一行数据 - * @return 别名列表 - */ - private Table aliasTable(final Map rowMap) { - final Table filteredTable = new RowKeyTable<>(new LinkedHashMap<>(), TableMap::new); - final Map headerAlias = this.config.getHeaderAlias(); - final boolean onlyAlias = this.config.onlyAlias; - if (MapUtil.isEmpty(headerAlias)) { - rowMap.forEach((key, value) -> filteredTable.put(key, key, value)); - } else { - rowMap.forEach((key, value) -> { - final String aliasName = headerAlias.get(StrUtil.toString(key)); - if (null != aliasName) { - // 别名键值对加入 - filteredTable.put(key, aliasName, value); - } else if (!onlyAlias) { - // 保留无别名设置的键值对 - filteredTable.put(key, key, value); - } - }); - } - - return filteredTable; - } - // endregion } diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/SimpleShapeUtil.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/SimpleShapeUtil.java new file mode 100644 index 000000000..5a4be7cfa --- /dev/null +++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/writer/SimpleShapeUtil.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.poi.excel.writer; + +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFSimpleShape; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDrawing; +import org.apache.poi.xssf.usermodel.XSSFSimpleShape; +import org.dromara.hutool.poi.excel.SimpleClientAnchor; +import org.dromara.hutool.poi.excel.style.ShapeConfig; + +import java.awt.Color; + +/** + * 简单形状工具类
+ * 用于辅助写出指定的图形 + * + * @author Looly + * @since 6.0.0 + */ +public class SimpleShapeUtil { + + /** + * 绘制简单形状 + * + * @param sheet {@link Sheet} + * @param clientAnchor 绘制区域信息 + * @param shapeConfig 形状配置,包括形状类型、线条样式、线条宽度、线条颜色、填充颜色等 + * @since 6.0.0 + */ + public static void writeSimpleShape(final Sheet sheet, final SimpleClientAnchor clientAnchor, ShapeConfig shapeConfig) { + final Drawing patriarch = sheet.createDrawingPatriarch(); + final ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); + clientAnchor.copyTo(anchor); + + if (null == shapeConfig) { + shapeConfig = ShapeConfig.of(); + } + final Color lineColor = shapeConfig.getLineColor(); + if (patriarch instanceof HSSFPatriarch) { + final HSSFSimpleShape simpleShape = ((HSSFPatriarch) patriarch).createSimpleShape((HSSFClientAnchor) anchor); + simpleShape.setShapeType(shapeConfig.getShapeType().ooxmlId); + simpleShape.setLineStyle(shapeConfig.getLineStyle().getValue()); + simpleShape.setLineWidth(shapeConfig.getLineWidth()); + if (null != lineColor) { + simpleShape.setLineStyleColor(lineColor.getRed(), lineColor.getGreen(), lineColor.getBlue()); + } + } else if (patriarch instanceof XSSFDrawing) { + final XSSFSimpleShape simpleShape = ((XSSFDrawing) patriarch).createSimpleShape((XSSFClientAnchor) anchor); + simpleShape.setShapeType(shapeConfig.getShapeType().ooxmlId); + simpleShape.setLineStyle(shapeConfig.getLineStyle().getValue()); + simpleShape.setLineWidth(shapeConfig.getLineWidth()); + if (null != lineColor) { + simpleShape.setLineStyleColor(lineColor.getRed(), lineColor.getGreen(), lineColor.getBlue()); + } + } else { + throw new UnsupportedOperationException("Unsupported patriarch type: " + patriarch.getClass().getName()); + } + } +}