add ExcelImgType

This commit is contained in:
Looly 2024-08-11 19:08:19 +08:00
parent eef88779cf
commit 7a1983235f
8 changed files with 274 additions and 138 deletions

View File

@ -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;
}
}

View File

@ -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并不写出到文件<br>
* 添加图片到当前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
/**

View File

@ -261,7 +261,7 @@ public class ExcelUtil {
/**
* 获得{@link ExcelWriter}默认写出到第一个sheet<br>
* 不传入写出的Excel文件路径只能调用ExcelWriter#flush(OutputStream)方法写出到流<br>
* 若写出到文件还需调用{@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<br>
* 不传入写出的Excel文件路径只能调用ExcelWriter#flush(OutputStream)方法写出到流<br>
* 若写出到文件还需调用{@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<br>
* 不传入写出的Excel文件路径只能调用ExcelWriter#flush(OutputStream)方法写出到流<br>
* 若写出到文件还需调用{@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<br>
* 不传入写出的Excel文件路径只能调用ExcelWriter#flush(OutputStream)方法写出到流<br>
* 若写出到文件还需调用{@link BigExcelWriter#setDestFile(File)}方法自定义写出的文件然后调用{@link BigExcelWriter#flush()}方法写出到文件
* 若写出到文件还需调用{@link BigExcelWriter#setTargetFile(File)}方法自定义写出的文件然后调用{@link BigExcelWriter#flush()}方法写出到文件
*
* @param rowAccessWindowSize 在内存中的行数
* @return {@link BigExcelWriter}

View File

@ -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));
}
}

View File

@ -49,7 +49,7 @@ public class BigExcelWriter extends ExcelWriter {
/**
* 构造默认生成xlsx格式的Excel文件<br>
* 此构造不传入写出的Excel文件路径只能调用{@link #flush(java.io.OutputStream)}方法写出到流<br>
* 若写出到文件还需调用{@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 {
/**
* 构造<br>
* 此构造不传入写出的Excel文件路径只能调用{@link #flush(java.io.OutputStream)}方法写出到流<br>
* 若写出到文件还需调用{@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 {
/**
* 构造<br>
* 此构造不传入写出的Excel文件路径只能调用{@link #flush(java.io.OutputStream)}方法写出到流<br>
* 若写出到文件还需调用{@link #setDestFile(File)}方法自定义写出的文件然后调用{@link #flush()}方法写出到文件
* 若写出到文件还需调用{@link #setTargetFile(File)}方法自定义写出的文件然后调用{@link #flush()}方法写出到文件
*
* @param sheet {@link Sheet}
* @since 4.0.6

View File

@ -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<br>
* key为别名value为字段值
*
* @param rowMap 一行数据
* @return 别名列表
*/
public Table<?, ?, ?> aliasTable(final Map<?, ?> rowMap) {
final Table<Object, Object, Object> 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;
}
}

View File

@ -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<ExcelWriter, ExcelWriteConfig> {
/**
@ -81,7 +76,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
/**
* 构造默认生成xlsx格式的Excel文件<br>
* 此构造不传入写出的Excel文件路径只能调用{@link #flush(OutputStream)}方法写出到流<br>
* 若写出到文件还需调用{@link #setDestFile(File)}方法自定义写出的文件然后调用{@link #flush()}方法写出到文件
* 若写出到文件还需调用{@link #setTargetFile(File)}方法自定义写出的文件然后调用{@link #flush()}方法写出到文件
*
* @since 3.2.1
*/
@ -145,18 +140,22 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
/**
* 构造
*
* @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;
}
// 如果是已经存在的文件则作为模板加载此时不能写出到模板文件
}
/**
* 构造<br>
* 此构造不传入写出的Excel文件路径只能调用{@link #flush(OutputStream)}方法写出到流<br>
* 若写出到文件还需调用{@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<ExcelWriter, ExcelWriteConfig> {
/**
* 构造<br>
* 此构造不传入写出的Excel文件路径只能调用{@link #flush(OutputStream)}方法写出到流<br>
* 若写出到文件还需调用{@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<ExcelWriter, ExcelWriteConfig> {
@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<ExcelWriter, ExcelWriteConfig> {
*
* <pre>
* 1. 当前行游标归零
* 2. 清空别名比较器
* 3. 清除标题缓存
* 2. 清除标题缓存
* </pre>
*
* @return this
*/
public ExcelWriter reset() {
resetRow();
return this;
this.headLocationCache.clear();
return resetRow();
}
/**
@ -250,6 +248,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
}
/**
* 设置写出的目标文件
* 设置写出的目标文件<br>
* 注意这个文件不能存在存在则{@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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
* @return this
* @since 3.2.3
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@SuppressWarnings({"rawtypes", "unchecked", "resource"})
public ExcelWriter write(final Iterable<?> data, final Comparator<String> comparator) {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
boolean isFirstRow = true;
@ -787,7 +789,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
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<ExcelWriter, ExcelWriteConfig> {
* @param isWriteKeyAsHead 是否将Map的Key作为表头输出如果为True第一行为表头紧接着为values
* @return this
*/
@SuppressWarnings("resource")
public ExcelWriter writeCol(final Map<?, ? extends Iterable<?>> 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<ExcelWriter, ExcelWriteConfig> {
* @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<ExcelWriter, ExcelWriteConfig> {
/**
* 将Excel Workbook刷出到预定义的文件<br>
* 如果用户未自定义输出的文件将抛出{@link NullPointerException}<br>
* 预定义文件可以通过{@link #setDestFile(File)} 方法预定义或者通过构造定义
* 预定义文件可以通过{@link #setTargetFile(File)} 方法预定义或者通过构造定义
*
* @return this
* @throws IORuntimeException IO异常
@ -1360,6 +1336,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
* 关闭工作簿<br>
* 如果用户设定了目标文件先写出目标文件后给关闭工作簿
*/
@SuppressWarnings("resource")
@Override
public void close() {
if (null != this.targetFile) {
@ -1378,36 +1355,4 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
// 清空对象
this.styleSet = null;
}
// region ----- Private method start
/**
* 为指定的key列表添加标题别名如果没有定义key的别名在onlyAlias为false时使用原key<br>
* key为别名value为字段值
*
* @param rowMap 一行数据
* @return 别名列表
*/
private Table<?, ?, ?> aliasTable(final Map<?, ?> rowMap) {
final Table<Object, Object, Object> filteredTable = new RowKeyTable<>(new LinkedHashMap<>(), TableMap::new);
final Map<String, String> 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
}

View File

@ -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;
/**
* 简单形状工具类<br>
* 用于辅助写出指定的图形
*
* @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());
}
}
}