add ExcelConfig

This commit is contained in:
Looly 2024-08-10 23:35:34 +08:00
parent 103e48cf06
commit 6440c302a5
19 changed files with 539 additions and 426 deletions

View File

@ -31,18 +31,22 @@ import java.io.Closeable;
import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Excel基础类用于抽象ExcelWriter和ExcelReader中共用部分的对象和方法
*
* @param <T> 子类类型用于返回this
* @param <C> ExcelConfig类型
* @author looly
* @since 4.1.4
*/
public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
public class ExcelBase<T extends ExcelBase<T, C>, C extends ExcelConfig> implements Closeable {
/**
* Excel配置此项不为空
*/
protected C config;
/**
* 是否被关闭
*/
@ -59,22 +63,40 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* Excel中对应的Sheet
*/
protected Sheet sheet;
/**
* 标题行别名
*/
protected Map<String, String> headerAlias;
/**
* 构造
*
* @param config config
* @param sheet Excel中的sheet
*/
public ExcelBase(final Sheet sheet) {
Assert.notNull(sheet, "No Sheet provided.");
this.sheet = sheet;
public ExcelBase(final C config, final Sheet sheet) {
this.config = Assert.notNull(config);
this.sheet = Assert.notNull(sheet, "No Sheet provided.");
this.workbook = sheet.getWorkbook();
}
/**
* 设置Excel配置
*
* @param config Excel配置
* @return this
*/
@SuppressWarnings("unchecked")
public T setConfig(final C config) {
this.config = config;
return (T) this;
}
/**
* 获取Excel配置
*
* @return Excel配置
*/
public C getConfig() {
return this.config;
}
/**
* 获取Workbook
*
@ -428,24 +450,26 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
/**
* 创建 {@link Hyperlink}默认内容标签为链接地址本身
* @param type 链接类型
*
* @param type 链接类型
* @param address 链接地址
* @return 链接
* @since 5.7.13
*/
public Hyperlink createHyperlink(final HyperlinkType type, final String address){
public Hyperlink createHyperlink(final HyperlinkType type, final String address) {
return createHyperlink(type, address, address);
}
/**
* 创建 {@link Hyperlink}默认内容
* @param type 链接类型
*
* @param type 链接类型
* @param address 链接地址
* @param label 标签即单元格中显示的内容
* @param label 标签即单元格中显示的内容
* @return 链接
* @since 5.7.13
*/
public Hyperlink createHyperlink(final HyperlinkType type, final String address, final String label){
public Hyperlink createHyperlink(final HyperlinkType type, final String address, final String label) {
final Hyperlink hyperlink = this.workbook.getCreationHelper().createHyperlink(type);
hyperlink.setAddress(address);
hyperlink.setLabel(label);
@ -572,66 +596,4 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
this.workbook = null;
this.isClosed = true;
}
/**
* 获得标题行的别名Map
*
* @return 别名Map
*/
public Map<String, String> getHeaderAlias() {
return headerAlias;
}
/**
* 设置标题行的别名Map
*
* @param headerAlias 别名Map
* @return this
*/
@SuppressWarnings("unchecked")
public T setHeaderAlias(final Map<String, String> headerAlias) {
this.headerAlias = headerAlias;
return (T) this;
}
/**
* 增加标题别名
*
* @param header 标题
* @param alias 别名
* @return this
*/
@SuppressWarnings("unchecked")
public T addHeaderAlias(final String header, final String alias) {
Map<String, String> headerAlias = this.headerAlias;
if (null == headerAlias) {
headerAlias = new LinkedHashMap<>();
}
this.headerAlias = headerAlias;
this.headerAlias.put(header, alias);
return (T) this;
}
/**
* 去除标题别名
*
* @param header 标题
* @return this
*/
@SuppressWarnings("unchecked")
public T removeHeaderAlias(final String header) {
this.headerAlias.remove(header);
return (T) this;
}
/**
* 清空标题别名key为Map中的keyvalue为别名
*
* @return this
*/
@SuppressWarnings("unchecked")
public T clearHeaderAlias() {
this.headerAlias = null;
return (T) this;
}
}

View File

@ -0,0 +1,156 @@
/*
* 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.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.dromara.hutool.poi.excel.cell.CellReferenceUtil;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Excel读取和写出通用配置
*
* @author Looly
* @since 6.0.0
*/
public class ExcelConfig {
/**
* 标题行别名
*/
protected Map<String, String> headerAlias;
/**
* 单元格值处理接口
*/
protected CellEditor cellEditor;
/**
* 获得标题行的别名Map
*
* @return 别名Map
*/
public Map<String, String> getHeaderAlias() {
return headerAlias;
}
/**
* 设置标题行的别名Map
*
* @param headerAlias 别名Map
* @return this
*/
public ExcelConfig setHeaderAlias(final Map<String, String> headerAlias) {
this.headerAlias = headerAlias;
return this;
}
/**
* 增加标题别名
*
* @param header 标题
* @param alias 别名
* @return this
*/
public ExcelConfig addHeaderAlias(final String header, final String alias) {
Map<String, String> headerAlias = this.headerAlias;
if (null == headerAlias) {
headerAlias = new LinkedHashMap<>();
this.headerAlias = headerAlias;
}
headerAlias.put(header, alias);
return this;
}
/**
* 去除标题别名
*
* @param header 标题
* @return this
*/
public ExcelConfig removeHeaderAlias(final String header) {
this.headerAlias.remove(header);
return this;
}
/**
* 清空标题别名key为Map中的keyvalue为别名
*
* @return this
*/
public ExcelConfig clearHeaderAlias() {
return setHeaderAlias(null);
}
/**
* 转换标题别名如果没有别名则使用原标题当标题为空时列号对应的字母便是header
*
* @param headerList 原标题列表
* @return 转换别名列表
*/
public List<String> aliasHeader(final List<Object> headerList) {
if (CollUtil.isEmpty(headerList)) {
return new ArrayList<>(0);
}
final int size = headerList.size();
final List<String> result = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
result.add(aliasHeader(headerList.get(i), i));
}
return result;
}
/**
* 转换标题别名如果没有别名则使用原标题当标题为空时列号对应的字母便是header
*
* @param headerObj 原标题
* @param index 标题所在列号当标题为空时列号对应的字母便是header
* @return 转换别名列表
*/
public String aliasHeader(final Object headerObj, final int index) {
if (null == headerObj) {
return CellReferenceUtil.indexToColName(index);
}
final String header = headerObj.toString();
if (null != this.headerAlias) {
return ObjUtil.defaultIfNull(this.headerAlias.get(header), header);
}
return header;
}
/**
* 获取单元格值处理器
*
* @return 单元格值处理器
*/
public CellEditor getCellEditor() {
return this.cellEditor;
}
/**
* 设置单元格值处理逻辑<br>
* 当Excel中的值并不能满足我们的读取要求时通过传入一个编辑接口可以对单元格值自定义例如对数字和日期类型值转换为字符串等
*
* @param cellEditor 单元格值处理接口
* @return this
*/
public ExcelConfig setCellEditor(final CellEditor cellEditor) {
this.cellEditor = cellEditor;
return this;
}
}

View File

@ -73,7 +73,7 @@ public class RowUtil {
*/
public static List<Object> readRow(final Row row, final int startCellNumInclude, final int endCellNumInclude, final CellEditor cellEditor) {
if (null == row) {
return new ArrayList<>(0);
return ListUtil.empty();
}
final short rowLength = row.getLastCellNum();
if (rowLength < 0) {

View File

@ -13,16 +13,8 @@
package org.dromara.hutool.poi.excel.reader;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.poi.excel.RowUtil;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.dromara.hutool.poi.excel.cell.CellReferenceUtil;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dromara.hutool.poi.excel.ExcelConfig;
/**
* 抽象{@link Sheet}数据读取实现
@ -33,26 +25,15 @@ import java.util.Map;
*/
public abstract class AbstractSheetReader<T> implements SheetReader<T> {
/**
* 读取起始行包含从0开始计数
*/
protected final int startRowIndex;
/**
* 读取结束行包含从0开始计数
*/
protected final int endRowIndex;
protected final CellRangeAddress cellRangeAddress;
/**
* 是否忽略空行
*/
protected boolean ignoreEmptyRow = true;
/**
* 单元格值处理接口
* Excel配置
*/
protected CellEditor cellEditor;
/**
* 标题别名
*/
private Map<String, String> headerAlias;
protected ExcelConfig config;
/**
* 构造
@ -61,18 +42,28 @@ public abstract class AbstractSheetReader<T> implements SheetReader<T> {
* @param endRowIndex 结束行包含从0开始计数
*/
public AbstractSheetReader(final int startRowIndex, final int endRowIndex) {
this.startRowIndex = startRowIndex;
this.endRowIndex = endRowIndex;
this(new CellRangeAddress(
Math.min(startRowIndex, endRowIndex),
Math.max(startRowIndex, endRowIndex),
0, Integer.MAX_VALUE));
}
/**
* 设置单元格值处理逻辑<br>
* 当Excel中的值并不能满足我们的读取要求时通过传入一个编辑接口可以对单元格值自定义例如对数字和日期类型值转换为字符串等
* 构造
*
* @param cellEditor 单元格值处理接口
* @param cellRangeAddress 读取范围
*/
public void setCellEditor(final CellEditor cellEditor) {
this.cellEditor = cellEditor;
public AbstractSheetReader(final CellRangeAddress cellRangeAddress) {
this.cellRangeAddress = cellRangeAddress;
}
/**
* 设置Excel配置
*
* @param config Excel配置
*/
public void setExcelConfig(final ExcelConfig config) {
this.config = config;
}
/**
@ -83,78 +74,4 @@ public abstract class AbstractSheetReader<T> implements SheetReader<T> {
public void setIgnoreEmptyRow(final boolean ignoreEmptyRow) {
this.ignoreEmptyRow = ignoreEmptyRow;
}
/**
* 设置标题行的别名Map
*
* @param headerAlias 别名Map
*/
public void setHeaderAlias(final Map<String, String> headerAlias) {
this.headerAlias = headerAlias;
}
/**
* 增加标题别名
*
* @param header 标题
* @param alias 别名
*/
public void addHeaderAlias(final String header, final String alias) {
Map<String, String> headerAlias = this.headerAlias;
if (null == headerAlias) {
headerAlias = new LinkedHashMap<>();
}
this.headerAlias = headerAlias;
this.headerAlias.put(header, alias);
}
/**
* 转换标题别名如果没有别名则使用原标题当标题为空时列号对应的字母便是header
*
* @param headerList 原标题列表
* @return 转换别名列表
*/
protected List<String> aliasHeader(final List<Object> headerList) {
if (CollUtil.isEmpty(headerList)) {
return new ArrayList<>(0);
}
final int size = headerList.size();
final ArrayList<String> result = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
result.add(aliasHeader(headerList.get(i), i));
}
return result;
}
/**
* 转换标题别名如果没有别名则使用原标题当标题为空时列号对应的字母便是header
*
* @param headerObj 原标题
* @param index 标题所在列号当标题为空时列号对应的字母便是header
* @return 转换别名列表
* @since 4.3.2
*/
protected String aliasHeader(final Object headerObj, final int index) {
if (null == headerObj) {
return CellReferenceUtil.indexToColName(index);
}
final String header = headerObj.toString();
if(null != this.headerAlias){
return ObjUtil.defaultIfNull(this.headerAlias.get(header), header);
}
return header;
}
/**
* 读取某一行数据
*
* @param sheet {@link Sheet}
* @param rowIndex 行号从0开始
* @return 一行数据
*/
protected List<Object> readRow(final Sheet sheet, final int rowIndex) {
return RowUtil.readRow(sheet.getRow(rowIndex), this.cellEditor);
}
}

View File

@ -12,10 +12,10 @@
package org.dromara.hutool.poi.excel.reader;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.bean.copier.CopyOptions;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.poi.excel.ExcelConfig;
import java.util.ArrayList;
import java.util.List;
@ -63,13 +63,12 @@ public class BeanSheetReader<T> implements SheetReader<List<T>> {
}
/**
* 设置单元格值处理逻辑<br>
* 当Excel中的值并不能满足我们的读取要求时通过传入一个编辑接口可以对单元格值自定义例如对数字和日期类型值转换为字符串等
* 设置Excel配置
*
* @param cellEditor 单元格值处理接口
* @param config Excel配置
*/
public void setCellEditor(final CellEditor cellEditor) {
this.mapSheetReader.setCellEditor(cellEditor);
public void setExcelConfig(final ExcelConfig config) {
this.mapSheetReader.setExcelConfig(config);
}
/**
@ -80,23 +79,4 @@ public class BeanSheetReader<T> implements SheetReader<List<T>> {
public void setIgnoreEmptyRow(final boolean ignoreEmptyRow) {
this.mapSheetReader.setIgnoreEmptyRow(ignoreEmptyRow);
}
/**
* 设置标题行的别名Map
*
* @param headerAlias 别名Map
*/
public void setHeaderAlias(final Map<String, String> headerAlias) {
this.mapSheetReader.setHeaderAlias(headerAlias);
}
/**
* 增加标题别名
*
* @param header 标题
* @param alias 别名
*/
public void addHeaderAlias(final String header, final String alias) {
this.mapSheetReader.addHeaderAlias(header, alias);
}
}

View File

@ -12,8 +12,10 @@
package org.dromara.hutool.poi.excel.reader;
import org.dromara.hutool.poi.excel.cell.CellUtil;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.dromara.hutool.poi.excel.cell.CellUtil;
import java.util.ArrayList;
import java.util.List;
@ -26,8 +28,6 @@ import java.util.List;
*/
public class ColumnSheetReader extends AbstractSheetReader<List<Object>> {
private final int columnIndex;
/**
* 构造
*
@ -36,17 +36,18 @@ public class ColumnSheetReader extends AbstractSheetReader<List<Object>> {
* @param endRowIndex 结束行包含从0开始计数
*/
public ColumnSheetReader(final int columnIndex, final int startRowIndex, final int endRowIndex) {
super(startRowIndex, endRowIndex);
this.columnIndex = columnIndex;
super(new CellRangeAddress(startRowIndex, endRowIndex, columnIndex, columnIndex));
}
@Override
public List<Object> read(final Sheet sheet) {
final List<Object> resultList = new ArrayList<>();
final int startRowIndex = Math.max(this.startRowIndex, sheet.getFirstRowNum());// 读取起始行包含
final int endRowIndex = Math.min(this.endRowIndex, sheet.getLastRowNum());// 读取结束行包含
final int startRowIndex = Math.max(this.cellRangeAddress.getFirstRow(), sheet.getFirstRowNum());// 读取起始行包含
final int endRowIndex = Math.min(this.cellRangeAddress.getLastRow(), sheet.getLastRowNum());// 读取结束行包含
final int columnIndex = this.cellRangeAddress.getFirstColumn();
final CellEditor cellEditor = this.config.getCellEditor();
Object value;
for (int i = startRowIndex; i <= endRowIndex; i++) {
value = CellUtil.getCellValue(CellUtil.getCell(sheet.getRow(i), columnIndex), cellEditor);

View File

@ -0,0 +1,65 @@
/*
* 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.reader;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.core.func.SerBiConsumer;
import org.dromara.hutool.poi.excel.cell.CellUtil;
/**
* 读取Excel的Sheet使用Consumer方式处理单元格
*
* @author Looly
* @since 6.0.0
*/
public class ConsumerSheetReader extends AbstractSheetReader<Void> {
private final SerBiConsumer<Cell, Object> cellHandler;
/**
* 构造
*
* @param startRowIndex 起始行包含从0开始计数
* @param endRowIndex 结束行包含从0开始计数
* @param cellHandler 单元格处理器用于处理读到的单元格及其数据
*/
public ConsumerSheetReader(final int startRowIndex, final int endRowIndex, final SerBiConsumer<Cell, Object> cellHandler) {
super(startRowIndex, endRowIndex);
this.cellHandler = cellHandler;
}
@Override
public Void read(final Sheet sheet) {
final int startRowIndex = Math.max(this.cellRangeAddress.getFirstRow(), sheet.getFirstRowNum());// 读取起始行包含
final int endRowIndex = Math.min(this.cellRangeAddress.getLastRow(), sheet.getLastRowNum());// 读取结束行包含
Row row;
for (int y = startRowIndex; y <= endRowIndex; y++) {
row = sheet.getRow(y);
if (null != row) {
final short startColumnIndex = (short) Math.max(this.cellRangeAddress.getFirstColumn(), row.getFirstCellNum());
final short endColumnIndex = (short) Math.min(this.cellRangeAddress.getLastColumn(), row.getLastCellNum());
Cell cell;
for (short x = startColumnIndex; x < endColumnIndex; x++) {
cell = row.getCell(x);
cellHandler.accept(cell, CellUtil.getCellValue(cell));
}
}
}
return null;
}
}

View File

@ -12,18 +12,17 @@
package org.dromara.hutool.poi.excel.reader;
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.func.SerBiConsumer;
import org.dromara.hutool.poi.excel.*;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.dromara.hutool.poi.excel.cell.CellUtil;
import org.apache.poi.ss.extractor.ExcelExtractor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.dromara.hutool.core.func.SerBiConsumer;
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.poi.excel.*;
import org.dromara.hutool.poi.excel.cell.CellUtil;
import org.dromara.hutool.poi.excel.writer.ExcelWriter;
import java.io.File;
@ -38,16 +37,12 @@ import java.util.Map;
* @author Looly
* @since 3.1.0
*/
public class ExcelReader extends ExcelBase<ExcelReader> {
public class ExcelReader extends ExcelBase<ExcelReader, ExcelConfig> {
/**
* 是否忽略空行
*/
private boolean ignoreEmptyRow = true;
/**
* 单元格值处理接口
*/
private CellEditor cellEditor;
// ------------------------------------------------------------------------------------------------------- Constructor start
/**
@ -139,7 +134,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* @param sheet Excel中的sheet
*/
public ExcelReader(final Sheet sheet) {
super(sheet);
super(new ExcelConfig(), sheet);
}
// ------------------------------------------------------------------------------------------------------- Constructor end
@ -165,17 +160,6 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
return this;
}
/**
* 设置单元格值处理逻辑<br>
* 当Excel中的值并不能满足我们的读取要求时通过传入一个编辑接口可以对单元格值自定义例如对数字和日期类型值转换为字符串等
*
* @param cellEditor 单元格值处理接口
* @return this
*/
public ExcelReader setCellEditor(final CellEditor cellEditor) {
this.cellEditor = cellEditor;
return this;
}
// ------------------------------------------------------------------------------------------------------- Getters and Setters end
/**
@ -220,9 +204,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
*/
public List<List<Object>> read(final int startRowIndex, final int endRowIndex, final boolean aliasFirstLine) {
final ListSheetReader reader = new ListSheetReader(startRowIndex, endRowIndex, aliasFirstLine);
reader.setCellEditor(this.cellEditor);
reader.setExcelConfig(this.config);
reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
reader.setHeaderAlias(headerAlias);
return read(reader);
}
@ -249,9 +232,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
*/
public List<Object> readColumn(final int columnIndex, final int startRowIndex, final int endRowIndex) {
final ColumnSheetReader reader = new ColumnSheetReader(columnIndex, startRowIndex, endRowIndex);
reader.setCellEditor(this.cellEditor);
reader.setExcelConfig(this.config);
reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
reader.setHeaderAlias(headerAlias);
return read(reader);
}
@ -275,25 +257,13 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* @param cellHandler 单元格处理器用于处理读到的单元格及其数据
* @since 5.3.8
*/
public void read(int startRowIndex, int endRowIndex, final SerBiConsumer<Cell, Object> cellHandler) {
public void read(final int startRowIndex, final int endRowIndex, final SerBiConsumer<Cell, Object> cellHandler) {
checkNotClosed();
startRowIndex = Math.max(startRowIndex, this.sheet.getFirstRowNum());// 读取起始行包含
endRowIndex = Math.min(endRowIndex, this.sheet.getLastRowNum());// 读取结束行包含
Row row;
short columnSize;
for (int y = startRowIndex; y <= endRowIndex; y++) {
row = this.sheet.getRow(y);
if (null != row) {
columnSize = row.getLastCellNum();
Cell cell;
for (short x = 0; x < columnSize; x++) {
cell = row.getCell(x);
cellHandler.accept(cell, CellUtil.getCellValue(cell));
}
}
}
final ConsumerSheetReader reader = new ConsumerSheetReader(startRowIndex, endRowIndex, cellHandler);
reader.setExcelConfig(this.config);
reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
reader.read(sheet);
}
/**
@ -317,9 +287,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
*/
public List<Map<String, Object>> read(final int headerRowIndex, final int startRowIndex, final int endRowIndex) {
final MapSheetReader reader = new MapSheetReader(headerRowIndex, startRowIndex, endRowIndex);
reader.setCellEditor(this.cellEditor);
reader.setExcelConfig(this.config);
reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
reader.setHeaderAlias(headerAlias);
return read(reader);
}
@ -360,9 +329,8 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
*/
public <T> List<T> read(final int headerRowIndex, final int startRowIndex, final int endRowIndex, final Class<T> beanType) {
final BeanSheetReader<T> reader = new BeanSheetReader<>(headerRowIndex, startRowIndex, endRowIndex, beanType);
reader.setCellEditor(this.cellEditor);
reader.setExcelConfig(this.config);
reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
reader.setHeaderAlias(headerAlias);
return read(reader);
}
@ -421,7 +389,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* @since 4.0.3
*/
public Object readCellValue(final int x, final int y) {
return CellUtil.getCellValue(getCell(x, y), this.cellEditor);
return CellUtil.getCellValue(getCell(x, y), this.config.getCellEditor());
}
/**
@ -452,7 +420,7 @@ public class ExcelReader extends ExcelBase<ExcelReader> {
* @return 单元格值列表
*/
private List<Object> readRow(final Row row) {
return RowUtil.readRow(row, this.cellEditor);
return RowUtil.readRow(row, this.config.getCellEditor());
}
/**

View File

@ -15,6 +15,8 @@ package org.dromara.hutool.poi.excel.reader;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.convert.Convert;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.poi.excel.RowUtil;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import java.util.ArrayList;
import java.util.List;
@ -46,15 +48,17 @@ public class ListSheetReader extends AbstractSheetReader<List<List<Object>>> {
public List<List<Object>> read(final Sheet sheet) {
final List<List<Object>> resultList = new ArrayList<>();
final int startRowIndex = Math.max(this.startRowIndex, sheet.getFirstRowNum());// 读取起始行包含
final int endRowIndex = Math.min(this.endRowIndex, sheet.getLastRowNum());// 读取结束行包含
final int startRowIndex = Math.max(this.cellRangeAddress.getFirstRow(), sheet.getFirstRowNum());// 读取起始行包含
final int endRowIndex = Math.min(this.cellRangeAddress.getLastRow(), sheet.getLastRowNum());// 读取结束行包含
List<Object> rowList;
final CellEditor cellEditor = this.config.getCellEditor();
for (int i = startRowIndex; i <= endRowIndex; i++) {
rowList = readRow(sheet, i);
rowList = RowUtil.readRow(sheet.getRow(i), cellEditor);
if (CollUtil.isNotEmpty(rowList) || !ignoreEmptyRow) {
if (aliasFirstLine && i == startRowIndex) {
// 第一行作为标题行替换别名
rowList = Convert.toList(Object.class, aliasHeader(rowList));
rowList = Convert.toList(Object.class, this.config.aliasHeader(rowList));
}
resultList.add(rowList);
}

View File

@ -17,6 +17,7 @@ import org.dromara.hutool.core.collection.iter.IterUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.poi.excel.RowUtil;
import java.util.ArrayList;
import java.util.List;
@ -57,15 +58,18 @@ public class MapSheetReader extends AbstractSheetReader<List<Map<String, Object>
throw new IndexOutOfBoundsException(StrUtil.format("Header row index {} is lower than first row index {}.", headerRowIndex, firstRowNum));
} else if (headerRowIndex > lastRowNum) {
throw new IndexOutOfBoundsException(StrUtil.format("Header row index {} is greater than last row index {}.", headerRowIndex, lastRowNum));
} else if (startRowIndex > lastRowNum) {
}
int startRowIndex = this.cellRangeAddress.getFirstRow();
if (startRowIndex > lastRowNum) {
// issue#I5U1JA 只有标题行的Excel起始行是1标题行最后的行号是0
return ListUtil.empty();
}
final int startRowIndex = Math.max(this.startRowIndex, firstRowNum);// 读取起始行包含
final int endRowIndex = Math.min(this.endRowIndex, lastRowNum);// 读取结束行包含
startRowIndex = Math.max(startRowIndex, firstRowNum);// 读取起始行包含
final int endRowIndex = Math.min(this.cellRangeAddress.getLastRow(), lastRowNum);// 读取结束行包含
// 读取header
final List<String> headerList = aliasHeader(readRow(sheet, headerRowIndex));
final List<String> headerList = this.config.aliasHeader(readRow(sheet, headerRowIndex));
final List<Map<String, Object>> result = new ArrayList<>(endRowIndex - startRowIndex + 1);
List<Object> rowList;
@ -80,4 +84,15 @@ public class MapSheetReader extends AbstractSheetReader<List<Map<String, Object>
}
return result;
}
/**
* 读取某一行数据
*
* @param sheet {@link Sheet}
* @param rowIndex 行号从0开始
* @return 一行数据
*/
private List<Object> readRow(final Sheet sheet, final int rowIndex) {
return RowUtil.readRow(sheet.getRow(rowIndex), this.config.getCellEditor());
}
}

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.poi.excel.writer;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.io.IORuntimeException;
import org.apache.poi.ss.usermodel.Sheet;
@ -32,6 +33,9 @@ import java.io.OutputStream;
*/
public class BigExcelWriter extends ExcelWriter {
/**
* 默认内存中保存的行数默认100
*/
public static final int DEFAULT_WINDOW_SIZE = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
/**
@ -181,6 +185,7 @@ public class BigExcelWriter extends ExcelWriter {
return this;
}
@SuppressWarnings("resource")
@Override
public void close() {
if (null != this.destFile && !isFlushed) {
@ -188,7 +193,7 @@ public class BigExcelWriter extends ExcelWriter {
}
// 清理临时文件
((SXSSFWorkbook) this.workbook).dispose();
IoUtil.closeIfPossible(this.workbook);
super.closeWithoutFlush();
}
}

View File

@ -0,0 +1,88 @@
/*
* 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.dromara.hutool.core.comparator.IndexedComparator;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.poi.excel.ExcelConfig;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
/**
* Excel写出配置
*
* @author Looly
* @since 6.0.0
*/
public class ExcelWriteConfig extends ExcelConfig {
/**
* 是否只保留别名对应的字段
*/
protected boolean onlyAlias;
/**
* 标题顺序比较器
*/
protected Comparator<String> aliasComparator;
@Override
public ExcelWriteConfig setHeaderAlias(final Map<String, String> headerAlias) {
this.aliasComparator = null;
return (ExcelWriteConfig) super.setHeaderAlias(headerAlias);
}
@Override
public ExcelWriteConfig addHeaderAlias(final String header, final String alias) {
this.aliasComparator = null;
return (ExcelWriteConfig) super.addHeaderAlias(header, alias);
}
@Override
public ExcelWriteConfig removeHeaderAlias(final String header) {
this.aliasComparator = null;
return (ExcelWriteConfig) super.removeHeaderAlias(header);
}
/**
* 设置是否只保留别名中的字段值如果为true则不设置alias的字段将不被输出false表示原样输出
* Bean中设置@Alias时setOnlyAlias是无效的这个参数只和addHeaderAlias配合使用原因是注解是Bean内部的操作而addHeaderAlias是Writer的操作不互通
*
* @param isOnlyAlias 是否只保留别名中的字段值
* @return this
*/
public ExcelWriteConfig setOnlyAlias(final boolean isOnlyAlias) {
this.onlyAlias = isOnlyAlias;
return this;
}
/**
* 获取单例的别名比较器比较器的顺序为别名加入的顺序
*
* @return Comparator
*/
public Comparator<String> getCachedAliasComparator() {
final Map<String, String> headerAlias = this.headerAlias;
if (MapUtil.isEmpty(headerAlias)) {
return null;
}
Comparator<String> aliasComparator = this.aliasComparator;
if (null == aliasComparator) {
final Set<String> keySet = headerAlias.keySet();
aliasComparator = new IndexedComparator<>(keySet.toArray(new String[0]));
this.aliasComparator = aliasComparator;
}
return aliasComparator;
}
}

View File

@ -22,7 +22,6 @@ 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.comparator.IndexedComparator;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileUtil;
@ -63,16 +62,8 @@ import java.util.concurrent.atomic.AtomicInteger;
* @since 3.2.0
*/
@SuppressWarnings("resource")
public class ExcelWriter extends ExcelBase<ExcelWriter> {
public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
/**
* 是否只保留别名对应的字段
*/
private boolean onlyAlias;
/**
* 标题顺序比较器
*/
private Comparator<String> aliasComparator;
/**
* 样式集定义不同类型数据样式
*/
@ -81,10 +72,6 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* 标题项对应列号缓存每次写标题更新此缓存
*/
private Map<String, Integer> headLocationCache;
/**
* 单元格值处理接口
*/
private CellEditor cellEditor;
/**
* 当前行
*/
@ -188,22 +175,16 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* @since 4.0.6
*/
public ExcelWriter(final Sheet sheet) {
super(sheet);
super(new ExcelWriteConfig(), sheet);
this.styleSet = new DefaultStyleSet(workbook);
this.currentRow = new AtomicInteger(0);
}
// endregion
/**
* 设置单元格值处理逻辑<br>
* 当Excel中的值并不能满足我们的读取要求时通过传入一个编辑接口可以对单元格值自定义例如对数字和日期类型值转换为字符串等
*
* @param cellEditor 单元格值处理接口
* @return this
*/
public ExcelWriter setCellEditor(final CellEditor cellEditor) {
this.cellEditor = cellEditor;
return this;
@Override
public ExcelWriter setConfig(final ExcelWriteConfig config) {
return super.setConfig(config);
}
@Override
@ -410,39 +391,6 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
}
//region header alias
@Override
public ExcelWriter setHeaderAlias(final Map<String, String> headerAlias) {
// 新增别名时清除比较器缓存
this.aliasComparator = null;
return super.setHeaderAlias(headerAlias);
}
@Override
public ExcelWriter clearHeaderAlias() {
// 清空别名时清除比较器缓存
this.aliasComparator = null;
return super.clearHeaderAlias();
}
@Override
public ExcelWriter addHeaderAlias(final String name, final String alias) {
// 新增别名时清除比较器缓存
this.aliasComparator = null;
return super.addHeaderAlias(name, alias);
}
/**
* 设置是否只保留别名中的字段值如果为true则不设置alias的字段将不被输出false表示原样输出
* Bean中设置@Alias时setOnlyAlias是无效的这个参数只和addHeaderAlias配合使用原因是注解是Bean内部的操作而addHeaderAlias是Writer的操作不互通
*
* @param isOnlyAlias 是否只保留别名中的字段值
* @return this
* @since 4.1.22
*/
public ExcelWriter setOnlyAlias(final boolean isOnlyAlias) {
this.onlyAlias = isOnlyAlias;
return this;
}
//endregion
/**
@ -704,7 +652,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
// 设置内容
if (null != content) {
final Cell cell = getOrCreateCell(cellRangeAddress.getFirstColumn(), cellRangeAddress.getFirstRow());
CellUtil.setCellValue(cell, content, cellStyle, this.cellEditor);
CellUtil.setCellValue(cell, content, cellStyle, this.config.getCellEditor());
}
return this;
}
@ -911,11 +859,12 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
this.headLocationCache = new SafeConcurrentHashMap<>();
final Row row = this.sheet.createRow(this.currentRow.getAndIncrement());
final CellEditor cellEditor = this.config.getCellEditor();
int i = 0;
Cell cell;
for (final Object value : rowData) {
cell = row.createCell(i);
CellUtil.setCellValue(cell, value, this.styleSet, true, this.cellEditor);
CellUtil.setCellValue(cell, value, this.styleSet, true, cellEditor);
this.headLocationCache.put(StrUtil.toString(value), i);
i++;
}
@ -939,6 +888,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
final Iterator<?> iterator = rowData.iterator();
//如果获取的row存在单元格则执行复杂表头逻辑否则直接调用writeHeadRow(Iterable<?> rowData)
if (row.getLastCellNum() != 0) {
final CellEditor cellEditor = this.config.getCellEditor();
for (int i = 0; i < this.workbook.getSpreadsheetVersion().getMaxColumns(); i++) {
Cell cell = row.getCell(i);
if (cell != null) {
@ -946,7 +896,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
}
if (iterator.hasNext()) {
cell = row.createCell(i);
CellUtil.setCellValue(cell, iterator.next(), this.styleSet, true, this.cellEditor);
CellUtil.setCellValue(cell, iterator.next(), this.styleSet, true, cellEditor);
} else {
break;
}
@ -975,10 +925,12 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public ExcelWriter writeRow(final Object rowBean, final boolean isWriteKeyAsHead) {
final ExcelWriteConfig config = this.config;
final Map rowMap;
if (rowBean instanceof Map) {
if (MapUtil.isNotEmpty(this.headerAlias)) {
rowMap = MapUtil.newTreeMap((Map) rowBean, getCachedAliasComparator());
if (MapUtil.isNotEmpty(config.getHeaderAlias())) {
rowMap = MapUtil.newTreeMap((Map) rowBean, config.getCachedAliasComparator());
} else {
rowMap = (Map) rowBean;
}
@ -990,11 +942,11 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
// Hyperlink当成一个值
return writeRow(ListUtil.of(rowBean), isWriteKeyAsHead);
} else if (BeanUtil.isReadableBean(rowBean.getClass())) {
if (MapUtil.isEmpty(this.headerAlias)) {
if (MapUtil.isEmpty(config.getHeaderAlias())) {
rowMap = BeanUtil.beanToMap(rowBean, new LinkedHashMap<>(), false, false);
} else {
// 别名存在情况下按照别名的添加顺序排序Bean数据
rowMap = BeanUtil.beanToMap(rowBean, new TreeMap<>(getCachedAliasComparator()), false, false);
rowMap = BeanUtil.beanToMap(rowBean, new TreeMap<>(config.getCachedAliasComparator()), false, false);
}
} else {
// 其它转为字符串默认输出
@ -1033,6 +985,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
// 如果已经写出标题行根据标题行找对应的值写入
if (MapUtil.isNotEmpty(this.headLocationCache)) {
final Row row = RowUtil.getOrCreateRow(this.sheet, this.currentRow.getAndIncrement());
final CellEditor cellEditor = this.config.getCellEditor();
Integer location;
for (final Table.Cell<?, ?, ?> cell : aliasTable) {
// 首先查找原名对应的列号
@ -1042,7 +995,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
location = this.headLocationCache.get(StrUtil.toString(cell.getColumnKey()));
}
if (null != location) {
CellUtil.setCellValue(CellUtil.getOrCreateCell(row, location), cell.getValue(), this.styleSet, false, this.cellEditor);
CellUtil.setCellValue(CellUtil.getOrCreateCell(row, location), cell.getValue(), this.styleSet, false, cellEditor);
}
}
} else {
@ -1061,7 +1014,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
*/
public ExcelWriter writeRow(final Iterable<?> rowData) {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
RowUtil.writeRow(this.sheet.createRow(this.currentRow.getAndIncrement()), rowData, this.styleSet, false, this.cellEditor);
RowUtil.writeRow(this.sheet.createRow(this.currentRow.getAndIncrement()), rowData, this.styleSet, false, this.config.getCellEditor());
return this;
}
// endregion
@ -1185,7 +1138,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
*/
public ExcelWriter writeCellValue(final int x, final int y, final Object value, final boolean isHeader) {
final Cell cell = getOrCreateCell(x, y);
CellUtil.setCellValue(cell, value, this.styleSet, isHeader, this.cellEditor);
CellUtil.setCellValue(cell, value, this.styleSet, isHeader, this.config.getCellEditor());
return this;
}
// endregion
@ -1406,15 +1359,17 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
*/
private Table<?, ?, ?> aliasTable(final Map<?, ?> rowMap) {
final Table<Object, Object, Object> filteredTable = new RowKeyTable<>(new LinkedHashMap<>(), TableMap::new);
if (MapUtil.isEmpty(this.headerAlias)) {
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 = this.headerAlias.get(StrUtil.toString(key));
final String aliasName = headerAlias.get(StrUtil.toString(key));
if (null != aliasName) {
// 别名键值对加入
filteredTable.put(key, aliasName, value);
} else if (!this.onlyAlias) {
} else if (!onlyAlias) {
// 保留无别名设置的键值对
filteredTable.put(key, key, value);
}
@ -1423,24 +1378,5 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
return filteredTable;
}
/**
* 获取单例的别名比较器比较器的顺序为别名加入的顺序
*
* @return Comparator
* @since 4.1.5
*/
private Comparator<String> getCachedAliasComparator() {
if (MapUtil.isEmpty(this.headerAlias)) {
return null;
}
Comparator<String> aliasComparator = this.aliasComparator;
if (null == aliasComparator) {
final Set<String> keySet = this.headerAlias.keySet();
aliasComparator = new IndexedComparator<>(keySet.toArray(new String[0]));
this.aliasComparator = aliasComparator;
}
return aliasComparator;
}
// endregion
}

View File

@ -27,7 +27,7 @@ public class CellEditorTest {
@org.junit.jupiter.api.Test
public void readTest(){
final ExcelReader excelReader= ExcelUtil.getReader("cell_editor_test.xlsx");
excelReader.setCellEditor(new ExcelHandler());
excelReader.getConfig().setCellEditor(new ExcelHandler());
final List<Test> excelReaderObjects=excelReader.readAll(Test.class);
Assertions.assertEquals("0", excelReaderObjects.get(0).getTest1());

View File

@ -19,6 +19,7 @@ import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.util.ObjUtil;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.dromara.hutool.poi.excel.ExcelConfig;
import org.dromara.hutool.poi.excel.ExcelUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
@ -48,7 +49,7 @@ public class ExcelReadTest {
headerAlias.put("库房", "storageName");
headerAlias.put("盘点权限", "checkPerm");
headerAlias.put("领料审批权限", "allotAuditPerm");
reader.setHeaderAlias(headerAlias);
reader.getConfig().setHeaderAlias(headerAlias);
// 读取list时默认首个非空行为标题
final List<List<Object>> read = reader.read(0, Integer.MAX_VALUE, true);
@ -146,10 +147,11 @@ public class ExcelReadTest {
@Test
public void excelReadToBeanListTest() {
final ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("aaa.xlsx"));
reader.addHeaderAlias("姓名", "name");
reader.addHeaderAlias("年龄", "age");
reader.addHeaderAlias("性别", "gender");
reader.addHeaderAlias("鞋码", "shoeSize");
final ExcelConfig config = reader.getConfig();
config.addHeaderAlias("姓名", "name");
config.addHeaderAlias("年龄", "age");
config.addHeaderAlias("性别", "gender");
config.addHeaderAlias("鞋码", "shoeSize");
final List<Person> all = reader.readAll(Person.class);
Assertions.assertEquals("张三", all.get(0).getName());
@ -162,9 +164,10 @@ public class ExcelReadTest {
@Disabled
public void excelReadToBeanListTest2() {
final ExcelReader reader = ExcelUtil.getReader("f:/test/toBean.xlsx");
reader.addHeaderAlias("姓名", "name");
reader.addHeaderAlias("年龄", "age");
reader.addHeaderAlias("性别", "gender");
final ExcelConfig config = reader.getConfig();
config.addHeaderAlias("姓名", "name");
config.addHeaderAlias("年龄", "age");
config.addHeaderAlias("性别", "gender");
final List<Person> all = reader.read(0, 2, Person.class);
for (final Person person : all) {
@ -220,7 +223,8 @@ public class ExcelReadTest {
@Test
public void nullValueEditTest(){
final ExcelReader reader = ExcelUtil.getReader("null_cell_test.xlsx");
reader.setCellEditor((cell, value)-> ObjUtil.defaultIfNull(value, "#"));
final ExcelConfig config = reader.getConfig();
config.setCellEditor((cell, value)-> ObjUtil.defaultIfNull(value, "#"));
final List<List<Object>> read = reader.read();
// 对于任意一个单元格有值的情况下之前的单元格值按照null处理
@ -271,14 +275,14 @@ public class ExcelReadTest {
//https://gitee.com/dromara/hutool/issues/I5OSFC
final ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("read.xlsx"));
final List<Map<String, Object>> read = reader.read(1,2,2);
for (Map<String, Object> map : read) {
for (final Map<String, Object> map : read) {
Console.log(map);
}
//超出lastIndex 抛出相应提示startRowIndex row index 4 is greater than last row index 2.
//而非:Illegal Capacity: -1
try {
final List<Map<String, Object>> readGreaterIndex = reader.read(1,4,4);
} catch (Exception e) {
} catch (final Exception e) {
Console.log(e.toString());
}
}

View File

@ -191,11 +191,12 @@ public class BigExcelWriteTest {
FileUtil.del(FileUtil.file(file));
final BigExcelWriter writer = ExcelUtil.getBigWriter(file);
//自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("score", "分数");
writer.addHeaderAlias("isPass", "是否通过");
writer.addHeaderAlias("examDate", "考试时间");
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
config.addHeaderAlias("score", "分数");
config.addHeaderAlias("isPass", "是否通过");
config.addHeaderAlias("examDate", "考试时间");
// 合并单元格后的标题行使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容使用默认样式
@ -234,8 +235,9 @@ public class BigExcelWriteTest {
final String path = "d:/test/issue1210.xlsx";
FileUtil.del(FileUtil.file(path));
final BigExcelWriter writer = ExcelUtil.getBigWriter(path);
writer.addHeaderAlias("id", "SN");
writer.addHeaderAlias("userName", "User Name");
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("id", "SN");
config.addHeaderAlias("userName", "User Name");
final List<Map<String, Object>> list = new ArrayList<>();
list.add(new HashMap<String, Object>() {

View File

@ -306,11 +306,12 @@ public class ExcelWriteTest {
FileUtil.del(FileUtil.file(file));
final ExcelWriter writer = ExcelUtil.getWriter(file);
// 自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("score", "分数");
writer.addHeaderAlias("isPass", "是否通过");
writer.addHeaderAlias("examDate", "考试时间");
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
config.addHeaderAlias("score", "分数");
config.addHeaderAlias("isPass", "是否通过");
config.addHeaderAlias("examDate", "考试时间");
// 合并单元格后的标题行使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容使用默认样式
@ -340,10 +341,11 @@ public class ExcelWriteTest {
final String file = "f:/test/test_alias.xlsx";
FileUtil.del(FileUtil.file(file));
final ExcelWriter writer = ExcelUtil.getWriter(file);
writer.setOnlyAlias(true);
final ExcelWriteConfig config = writer.getConfig();
config.setOnlyAlias(true);
// 自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
// 合并单元格后的标题行使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容使用默认样式
@ -372,10 +374,11 @@ public class ExcelWriteTest {
// 通过工具类创建writer
final String file = "d:/test/test_alias.xls";
final ExcelWriter writer = ExcelUtil.getWriter(file, "test1");
// writer.setOnlyAlias(true);
// 自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
final ExcelWriteConfig config = writer.getConfig();
// writer.setOnlyAlias(true);
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
// 一次性写出内容使用默认样式
writer.write(rows, true);
// 关闭writer释放内存
@ -403,12 +406,13 @@ public class ExcelWriteTest {
// 通过工具类创建writer
final String file = "d:/test/test_alias.xls";
final ExcelWriter writer = ExcelUtil.getWriter(file, "test1");
writer.setOnlyAlias(true);
final ExcelWriteConfig config = writer.getConfig();
config.setOnlyAlias(true);
// 自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("examDate", "考试时间");
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
config.addHeaderAlias("examDate", "考试时间");
// 一次性写出内容使用默认样式
writer.write(rows, true);
@ -438,12 +442,13 @@ public class ExcelWriteTest {
final String file = "e:/writeBeanTest.xlsx";
FileUtil.del(FileUtil.file(file));
final ExcelWriter writer = ExcelUtil.getWriter(file);
final ExcelWriteConfig config = writer.getConfig();
// 自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("score", "分数");
writer.addHeaderAlias("isPass", "是否通过");
writer.addHeaderAlias("examDate", "考试时间");
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
config.addHeaderAlias("score", "分数");
config.addHeaderAlias("isPass", "是否通过");
config.addHeaderAlias("examDate", "考试时间");
// 合并单元格后的标题行使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容使用默认样式
@ -471,9 +476,10 @@ public class ExcelWriteTest {
FileUtil.del(FileUtil.file(file));
final ExcelWriter writer = ExcelUtil.getWriter(file);
// 自定义标题
writer.addHeaderAlias("id", "编号");
writer.addHeaderAlias("num", "序号");
writer.addHeaderAlias("body", "内容");
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("id", "编号");
config.addHeaderAlias("num", "序号");
config.addHeaderAlias("body", "内容");
// 一次性写出内容使用默认样式
writer.write(rows, true);
// 关闭writer释放内存
@ -529,18 +535,19 @@ public class ExcelWriteTest {
rows.add(tempList);
}
final ExcelWriter writer = ExcelUtil.getWriter("D:\\test\\multiSheet.xlsx", "正常数据");
writer.addHeaderAlias("1", "row1");
writer.addHeaderAlias("3", "row2");
writer.setOnlyAlias(true);
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("1", "row1");
config.addHeaderAlias("3", "row2");
config.setOnlyAlias(true);
writer.write(rows, true);
writer.autoSizeColumnAll(false, 0);
//表2
writer.setSheet("当前重复数据");
writer.clearHeaderAlias();
writer.addHeaderAlias("3", "行3");
writer.addHeaderAlias("1", "行1");
config.clearHeaderAlias();
config.addHeaderAlias("3", "行3");
config.addHeaderAlias("1", "行1");
writer.write(rows, true);
writer.autoSizeColumnAll(false, 0);
@ -749,7 +756,7 @@ public class ExcelWriteTest {
//通过工具类创建writer
FileUtil.del(FileUtil.file("d:/test/writeTest2123.xlsx"));
final ExcelWriter writer = ExcelUtil.getWriter("d:/test/writeTest2123.xlsx");
writer.addHeaderAlias("xmnf", "项目年份");//1
writer.getConfig().addHeaderAlias("xmnf", "项目年份");//1
//合并单元格后的标题行使用默认标题样式
writer.merge(7, "测试标题");

View File

@ -37,9 +37,10 @@ public class Issue2221Test {
public void writeDuplicateHeaderAliasTest() {
final ExcelWriter writer = ExcelUtil.getWriter("d:/test/duplicateAlias.xlsx");
// 设置别名
writer.addHeaderAlias("androidLc", "安卓");
writer.addHeaderAlias("androidAc", "安卓");
writer.setOnlyAlias(true);
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("androidLc", "安卓");
config.addHeaderAlias("androidAc", "安卓");
config.setOnlyAlias(true);
// 写入数据
final List<Map<Object, Object>> data = ListUtil.view(
@ -77,12 +78,13 @@ public class Issue2221Test {
writer.setFreezePane(2);
// 设置别名
writer.addHeaderAlias("date", "日期");
writer.addHeaderAlias("androidLc", "安卓");
writer.addHeaderAlias("iosLc", "iOS");
writer.addHeaderAlias("androidAc", " 安卓");
writer.addHeaderAlias("iosAc", " iOS");
writer.setOnlyAlias(true);
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("date", "日期");
config.addHeaderAlias("androidLc", "安卓");
config.addHeaderAlias("iosLc", "iOS");
config.addHeaderAlias("androidAc", " 安卓");
config.addHeaderAlias("iosAc", " iOS");
config.setOnlyAlias(true);
// 设置合并的单元格
writer.merge(new CellRangeAddress(0, 1, 0, 0), "日期", true);

View File

@ -57,8 +57,9 @@ public class IssueI66Z6BTest {
final ExcelWriter writer = ExcelUtil.getWriter(destFile);
//自定义标题别名
writer.addHeaderAlias("姓名", "name");
writer.addHeaderAlias("年龄", "age");
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("姓名", "name");
config.addHeaderAlias("年龄", "age");
writer.write(dataList, true);
writer.close();