mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add template support
This commit is contained in:
parent
01e81de806
commit
e8ceffa98d
@ -39,6 +39,7 @@ import org.dromara.hutool.poi.excel.style.StyleSet;
|
||||
public class CellUtil {
|
||||
|
||||
// region ----- getCellValue
|
||||
|
||||
/**
|
||||
* 获取单元格值
|
||||
*
|
||||
@ -103,6 +104,7 @@ public class CellUtil {
|
||||
// endregion
|
||||
|
||||
// region ----- setCellValue
|
||||
|
||||
/**
|
||||
* 设置单元格值<br>
|
||||
* 根据传入的styleSet自动匹配样式<br>
|
||||
@ -169,8 +171,8 @@ public class CellUtil {
|
||||
* 根据传入的styleSet自动匹配样式<br>
|
||||
* 当为头部样式时默认赋值头部样式,但是头部中如果有数字、日期等类型,将按照数字、日期样式设置
|
||||
*
|
||||
* @param cell 单元格
|
||||
* @param value 值或{@link CellSetter}
|
||||
* @param cell 单元格
|
||||
* @param value 值或{@link CellSetter}
|
||||
* @since 5.6.4
|
||||
*/
|
||||
public static void setCellValue(final Cell cell, final Object value) {
|
||||
@ -191,10 +193,11 @@ public class CellUtil {
|
||||
// endregion
|
||||
|
||||
// region ----- getCell
|
||||
|
||||
/**
|
||||
* 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回{@code null}
|
||||
*
|
||||
* @param sheet {@link Sheet}
|
||||
* @param sheet {@link Sheet}
|
||||
* @param x X坐标,从0计数,即列号
|
||||
* @param y Y坐标,从0计数,即行号
|
||||
* @param isCreateIfNotExist 单元格不存在时是否创建
|
||||
@ -249,6 +252,7 @@ public class CellUtil {
|
||||
// endregion
|
||||
|
||||
// region ----- merging 合并单元格
|
||||
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
@ -287,7 +291,7 @@ public class CellUtil {
|
||||
for (int i = 0; i < sheetMergeCount; i++) {
|
||||
ca = sheet.getMergedRegion(i);
|
||||
if (y >= ca.getFirstRow() && y <= ca.getLastRow()
|
||||
&& x >= ca.getFirstColumn() && x <= ca.getLastColumn()) {
|
||||
&& x >= ca.getFirstColumn() && x <= ca.getLastColumn()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -297,7 +301,7 @@ public class CellUtil {
|
||||
/**
|
||||
* 合并单元格,可以根据设置的值来合并行和列
|
||||
*
|
||||
* @param sheet 表对象
|
||||
* @param sheet 表对象
|
||||
* @param cellRangeAddress 合并单元格范围,定义了起始行列和结束行列
|
||||
* @return 合并后的单元格号
|
||||
*/
|
||||
@ -308,9 +312,9 @@ public class CellUtil {
|
||||
/**
|
||||
* 合并单元格,可以根据设置的值来合并行和列
|
||||
*
|
||||
* @param sheet 表对象
|
||||
* @param sheet 表对象
|
||||
* @param cellRangeAddress 合并单元格范围,定义了起始行列和结束行列
|
||||
* @param cellStyle 单元格样式,只提取边框样式,null表示无样式
|
||||
* @param cellStyle 单元格样式,只提取边框样式,null表示无样式
|
||||
* @return 合并后的单元格号
|
||||
*/
|
||||
public static int mergingCells(final Sheet sheet, final CellRangeAddress cellRangeAddress, final CellStyle cellStyle) {
|
||||
@ -360,8 +364,8 @@ public class CellUtil {
|
||||
return null;
|
||||
}
|
||||
return ObjUtil.defaultIfNull(
|
||||
getCellIfMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()),
|
||||
cell);
|
||||
getCellIfMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()),
|
||||
cell);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -376,8 +380,8 @@ public class CellUtil {
|
||||
*/
|
||||
public static Cell getMergedRegionCell(final Sheet sheet, final int x, final int y) {
|
||||
return ObjUtil.defaultIfNull(
|
||||
getCellIfMergedRegion(sheet, x, y),
|
||||
() -> SheetUtil.getCell(sheet, y, x));
|
||||
getCellIfMergedRegion(sheet, x, y),
|
||||
() -> SheetUtil.getCell(sheet, y, x));
|
||||
}
|
||||
// endregion
|
||||
|
||||
@ -420,13 +424,25 @@ public class CellUtil {
|
||||
// 修正在XSSFCell中未设置地址导致错位问题
|
||||
comment.setAddress(cell.getAddress());
|
||||
comment.setString(factory.createRichTextString(commentText));
|
||||
if(null != commentAuthor){
|
||||
if (null != commentAuthor) {
|
||||
comment.setAuthor(commentAuthor);
|
||||
}
|
||||
cell.setCellComment(comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定单元格
|
||||
*
|
||||
* @param cell 单元格
|
||||
*/
|
||||
public static void remove(final Cell cell) {
|
||||
if (null != cell) {
|
||||
cell.getRow().removeCell(cell);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 获取合并单元格,非合并单元格返回{@code null}<br>
|
||||
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
|
||||
|
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.poi.excel.cell;
|
||||
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.dromara.hutool.poi.excel.cell.values.FormulaCellValue;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 虚拟单元格,表示一个单元格的位置、值和样式,但是并非实际创建的单元格<br>
|
||||
* 注意:虚拟单元格设置值和样式均不会在实际工作簿中生效
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class VirtualCell extends CellBase {
|
||||
|
||||
private final Row row;
|
||||
private final int columnIndex;
|
||||
private final int rowIndex;
|
||||
|
||||
private CellType cellType;
|
||||
private Object value;
|
||||
private CellStyle style;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param cell 参照单元格
|
||||
* @param x 新的列号,从0开始
|
||||
* @param y 新的行号,从0开始
|
||||
*/
|
||||
public VirtualCell(final Cell cell, final int x, final int y) {
|
||||
this(cell.getRow(), x, y);
|
||||
this.cellType = cell.getCellType();
|
||||
this.value = CellUtil.getCellValue(cell);
|
||||
this.style = cell.getCellStyle();
|
||||
this.comment = cell.getCellComment();
|
||||
}
|
||||
|
||||
private Comment comment;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param row 行
|
||||
* @param y 行号,从0开始
|
||||
* @param x 列号,从0开始
|
||||
*/
|
||||
public VirtualCell(final Row row, final int x, final int y) {
|
||||
this.row = row;
|
||||
this.rowIndex = y;
|
||||
this.columnIndex = x;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellTypeImpl(final CellType cellType) {
|
||||
this.cellType = cellType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellFormulaImpl(final String formula) {
|
||||
this.value = new FormulaCellValue(formula);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFormulaImpl() {
|
||||
if (this.value instanceof FormulaCellValue) {
|
||||
this.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellValueImpl(final double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellValueImpl(final Date value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellValueImpl(final LocalDateTime value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellValueImpl(final Calendar value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellValueImpl(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCellValueImpl(final RichTextString value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpreadsheetVersion getSpreadsheetVersion() {
|
||||
return SpreadsheetVersion.EXCEL2007;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnIndex() {
|
||||
return this.columnIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowIndex() {
|
||||
return this.rowIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sheet getSheet() {
|
||||
return this.row.getSheet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Row getRow() {
|
||||
return this.row;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellType getCellType() {
|
||||
return this.cellType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellType getCachedFormulaResultType() {
|
||||
if (this.value instanceof FormulaCellValue) {
|
||||
return ((FormulaCellValue) this.value).getResultType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCellFormula() {
|
||||
if (this.value instanceof FormulaCellValue) {
|
||||
return ((FormulaCellValue) this.value).getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNumericCellValue() {
|
||||
return (double) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getDateCellValue() {
|
||||
return (Date) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getLocalDateTimeCellValue() {
|
||||
return (LocalDateTime) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RichTextString getRichStringCellValue() {
|
||||
return (RichTextString) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringCellValue() {
|
||||
return (String) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCellValue(final boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCellErrorValue(final byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanCellValue() {
|
||||
return (boolean) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getErrorCellValue() {
|
||||
return (byte) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCellStyle(final CellStyle style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellStyle getCellStyle() {
|
||||
return this.style;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsActiveCell() {
|
||||
throw new UnsupportedOperationException("Virtual cell cannot be set as active cell");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCellComment(final Comment comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comment getCellComment() {
|
||||
return this.comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCellComment() {
|
||||
this.comment = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hyperlink getHyperlink() {
|
||||
return (Hyperlink) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHyperlink(final Hyperlink link) {
|
||||
this.value = link;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeHyperlink() {
|
||||
if (this.value instanceof Hyperlink) {
|
||||
this.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellRangeAddress getArrayFormulaRange() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartOfArrayFormulaGroup() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.poi.excel.cell.values;
|
||||
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.dromara.hutool.poi.excel.cell.setters.CellSetter;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
||||
@ -40,6 +41,7 @@ public class FormulaCellValue implements CellValue<String>, CellSetter {
|
||||
* 结果,使用ExcelWriter时可以不用
|
||||
*/
|
||||
private final Object result;
|
||||
private final CellType resultType;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -57,8 +59,20 @@ public class FormulaCellValue implements CellValue<String>, CellSetter {
|
||||
* @param result 结果
|
||||
*/
|
||||
public FormulaCellValue(final String formula, final Object result) {
|
||||
this(formula, result, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param formula 公式
|
||||
* @param result 结果
|
||||
* @param resultType 结果类型
|
||||
*/
|
||||
public FormulaCellValue(final String formula, final Object result, final CellType resultType) {
|
||||
this.formula = formula;
|
||||
this.result = result;
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,12 +87,22 @@ public class FormulaCellValue implements CellValue<String>, CellSetter {
|
||||
|
||||
/**
|
||||
* 获取结果
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public Object getResult() {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结果类型
|
||||
*
|
||||
* @return 结果类型,{@code null}表示未明确
|
||||
*/
|
||||
public CellType getResultType() {
|
||||
return this.resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getResult().toString();
|
||||
|
@ -91,7 +91,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
/**
|
||||
* 构造<br>
|
||||
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(OutputStream)}方法写出到流<br>
|
||||
* 若写出到文件,需要调用{@link #flush(File)} 写出到文件
|
||||
* 若写出到文件,需要调用{@link #flush(File, boolean)} 写出到文件
|
||||
*
|
||||
* @param isXlsx 是否为xlsx格式
|
||||
* @since 3.2.1
|
||||
@ -112,7 +112,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
/**
|
||||
* 构造<br>
|
||||
* 此构造不传入写出的Excel文件路径,只能调用{@link #flush(OutputStream)}方法写出到流<br>
|
||||
* 若写出到文件,需要调用{@link #flush(File)} 写出到文件
|
||||
* 若写出到文件,需要调用{@link #flush(File, boolean)} 写出到文件
|
||||
*
|
||||
* @param isXlsx 是否为xlsx格式
|
||||
* @param sheetName sheet名,第一个sheet名并写出到此sheet,例如sheet1
|
||||
@ -152,7 +152,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
|
||||
if (!FileUtil.exists(targetFile)) {
|
||||
this.targetFile = targetFile;
|
||||
} else{
|
||||
} else {
|
||||
// 如果是已经存在的文件,则作为模板加载,此时不能写出到模板文件
|
||||
// 初始化模板
|
||||
this.templateContext = new TemplateContext(this.sheet);
|
||||
@ -549,6 +549,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
}
|
||||
|
||||
// region ----- merge
|
||||
|
||||
/**
|
||||
* 合并当前行的单元格
|
||||
*
|
||||
@ -640,6 +641,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
// endregion
|
||||
|
||||
// region ----- write
|
||||
|
||||
/**
|
||||
* 写出数据,本方法只是将数据写入Workbook中的Sheet,并不写出到文件<br>
|
||||
* 写出的起始行为当前行号,可使用{@link #getCurrentRow()}方法调用,根据写出的的行数,当前行号自动增加
|
||||
@ -1010,21 +1012,16 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
|
||||
// region ----- fill
|
||||
|
||||
public ExcelWriter fillRow(final Map<?, ?> rowMap){
|
||||
rowMap.forEach((key, value)->{
|
||||
|
||||
});
|
||||
/**
|
||||
* 填充模板行
|
||||
*
|
||||
* @param rowMap 行数据
|
||||
* @return this
|
||||
*/
|
||||
public ExcelWriter fillRow(final Map<?, ?> rowMap) {
|
||||
rowMap.forEach((key, value) -> this.templateContext.fillAndPointToNext(StrUtil.toStringOrNull(key), rowMap));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExcelWriter fillCell(final String name, final Object value){
|
||||
final Cell cell = this.templateContext.getCell(name);
|
||||
if(null != cell){
|
||||
CellUtil.setCellValue(cell, value, this.config.getCellEditor());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region ----- writeCol
|
||||
@ -1282,21 +1279,39 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public ExcelWriter flush() throws IORuntimeException {
|
||||
return flush(this.targetFile);
|
||||
return flush(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Excel Workbook刷出到预定义的文件<br>
|
||||
* 如果用户未自定义输出的文件,将抛出{@link NullPointerException}<br>
|
||||
* 预定义文件可以通过{@link #setTargetFile(File)} 方法预定义,或者通过构造定义
|
||||
*
|
||||
* @param override 是否覆盖已有文件
|
||||
* @return this
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public ExcelWriter flush(final boolean override) throws IORuntimeException {
|
||||
Assert.notNull(this.targetFile, "[targetFile] is null, and you must call setTargetFile(File) first.");
|
||||
return flush(this.targetFile, override);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Excel Workbook刷出到文件<br>
|
||||
* 如果用户未自定义输出的文件,将抛出{@link NullPointerException}
|
||||
*
|
||||
* @param destFile 写出到的文件
|
||||
* @param targetFile 写出到的文件
|
||||
* @param override 是否覆盖已有文件
|
||||
* @return this
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public ExcelWriter flush(final File destFile) throws IORuntimeException {
|
||||
Assert.notNull(destFile, "[destFile] is null, and you must call setDestFile(File) first or call flush(OutputStream).");
|
||||
return flush(FileUtil.getOutputStream(destFile), true);
|
||||
public ExcelWriter flush(final File targetFile, final boolean override) throws IORuntimeException {
|
||||
Assert.notNull(targetFile, "targetFile is null!");
|
||||
if (FileUtil.exists(targetFile) && !override) {
|
||||
throw new IORuntimeException("File to write exist: " + targetFile);
|
||||
}
|
||||
return flush(FileUtil.getOutputStream(targetFile), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1321,6 +1336,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
||||
*/
|
||||
public ExcelWriter flush(final OutputStream out, final boolean isCloseOut) throws IORuntimeException {
|
||||
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
|
||||
|
||||
try {
|
||||
this.workbook.write(out);
|
||||
out.flush();
|
||||
|
@ -20,11 +20,14 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.regex.ReUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.poi.excel.SheetUtil;
|
||||
import org.dromara.hutool.poi.excel.cell.CellUtil;
|
||||
import org.dromara.hutool.poi.excel.cell.VirtualCell;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
@ -50,7 +53,7 @@ public class TemplateContext {
|
||||
private static final Pattern ESCAPE_VAR_PATTERN = Pattern.compile("\\\\\\{([.$_a-zA-Z]+\\d*[.$_a-zA-Z]*)\\\\}");
|
||||
|
||||
// 存储变量对应单元格的映射
|
||||
private final Map<String, Cell> varMap = new HashMap<>();
|
||||
private final Map<String, Cell> varMap = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -62,7 +65,7 @@ public class TemplateContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取变量对应的单元格,列表变量以.开头
|
||||
* 获取变量对应的当前单元格,列表变量以开头
|
||||
*
|
||||
* @param varName 变量名
|
||||
* @return 单元格
|
||||
@ -71,6 +74,45 @@ public class TemplateContext {
|
||||
return varMap.get(varName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充变量名name指向的单元格,并将变量指向下一列
|
||||
*
|
||||
* @param name 变量名
|
||||
* @param rowData 一行数据的键值对
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public void fillAndPointToNext(final String name, final Map<?, ?> rowData) {
|
||||
Cell cell = varMap.get(name);
|
||||
if (null == cell) {
|
||||
// 没有对应变量占位
|
||||
return;
|
||||
}
|
||||
|
||||
final String templateStr = cell.getStringCellValue();
|
||||
|
||||
// 指向下一列的单元格
|
||||
final Cell next = new VirtualCell(cell, cell.getColumnIndex(), cell.getRowIndex() + 1);
|
||||
next.setCellValue(templateStr);
|
||||
varMap.put(name, next);
|
||||
|
||||
if(cell instanceof VirtualCell){
|
||||
// 虚拟单元格,转换为实际单元格
|
||||
final Cell newCell = CellUtil.getCell(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex(), true);
|
||||
Assert.notNull(newCell, "Can not get or create cell at {},{}", cell.getColumnIndex(), cell.getRowIndex());
|
||||
newCell.setCellStyle(cell.getCellStyle());
|
||||
cell = newCell;
|
||||
}
|
||||
|
||||
// 模板替换
|
||||
if(StrUtil.equals(name, StrUtil.unWrap(templateStr, "{", "}"))){
|
||||
// 一个单元格只有一个变量
|
||||
CellUtil.setCellValue(cell, rowData.get(name));
|
||||
} else {
|
||||
// 模板中存在多个变量或模板填充
|
||||
CellUtil.setCellValue(cell, StrUtil.format(templateStr, rowData));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化,提取变量及位置,并将转义的变量回填
|
||||
*
|
||||
|
@ -143,7 +143,7 @@ public class ExcelWriteTest {
|
||||
writer.writeRow(row2);
|
||||
|
||||
// 生成文件或导出Excel
|
||||
writer.flush(FileUtil.file("d:/test/writeWithSheetTest.xlsx"));
|
||||
writer.flush(FileUtil.file("d:/test/writeWithSheetTest.xlsx"), true);
|
||||
|
||||
writer.close();
|
||||
}
|
||||
@ -868,7 +868,7 @@ public class ExcelWriteTest {
|
||||
|
||||
writer.writeImg(file, 0, 0, 5, 10);
|
||||
|
||||
writer.flush(new File("C:\\Users\\zsz\\Desktop\\2.xlsx"));
|
||||
writer.flush(new File("C:\\Users\\zsz\\Desktop\\2.xlsx"), true);
|
||||
|
||||
writer.close();
|
||||
}
|
||||
|
@ -22,6 +22,6 @@ public class TemplateContextTest {
|
||||
final ExcelWriter writer = ExcelUtil.getWriter("template.xlsx");
|
||||
final TemplateContext templateContext = new TemplateContext(writer.getSheet());
|
||||
Assertions.assertNotNull(templateContext.getCell("date"));
|
||||
Assertions.assertNotNull(templateContext.getCell(".month"));
|
||||
Assertions.assertNotNull(templateContext.getCell("month"));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package org.dromara.hutool.poi.excel.writer;
|
||||
|
||||
import org.dromara.hutool.core.io.file.FileUtil;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.poi.excel.ExcelUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TemplateWriterTest {
|
||||
@Test
|
||||
void writeRowTest() {
|
||||
final ExcelWriter writer = ExcelUtil.getWriter("d:/test/template.xlsx");
|
||||
|
||||
// 单个替换的变量
|
||||
writer.fillRow(MapUtil
|
||||
.builder("date", (Object)"2024-01-01")
|
||||
.build());
|
||||
|
||||
// 列表替换
|
||||
for (int i = 0; i < 10; i++) {
|
||||
writer.fillRow(MapUtil
|
||||
.builder("user.name", (Object)"张三")
|
||||
.put("user.age", 18)
|
||||
.put("year", 2024)
|
||||
.put("month", 8)
|
||||
.put("day", 24)
|
||||
.put("day", 24)
|
||||
.put("user.area123", "某某市")
|
||||
.put("invalid", "不替换")
|
||||
.build());
|
||||
}
|
||||
|
||||
writer.flush(FileUtil.file("d:/test/templateResult.xlsx"), true);
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user