java实现easyexcel填充数据并合并相同列属性的工具类
时间: 2023-08-28 18:06:15 浏览: 94
java操作excel的工具类
以下是一个示例Java类,演示如何使用EasyExcel库来填充数据并合并相同列属性:
```java
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import com.alibaba.excel.write.metadata.holder.WriteSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class EasyExcelUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(EasyExcelUtil.class);
/**
* 填充数据
* @param filePath 文件路径
* @param sheetName 工作表名称
* @param data 数据
*/
public static void fillData(String filePath, String sheetName, List<List<String>> data) {
EasyExcel.write(filePath)
.sheet(sheetName)
.registerWriteHandler(new MergeStrategy())
.registerWriteHandler(new CustomHeadWriteHandler())
.doWrite(data);
}
/**
* 自定义合并策略
*/
private static class MergeStrategy extends AbstractMergeStrategy {
private Map<Integer, List<Integer>> mergeMap = new HashMap<>();
@Override
protected void merge(SheetMergeProperties sheetMergeProperties) {
Integer columnIndex = sheetMergeProperties.getColumnIndex();
List<Integer> mergeIndexes = mergeMap.get(columnIndex);
if (mergeIndexes == null) {
mergeIndexes = new ArrayList<>();
mergeMap.put(columnIndex, mergeIndexes);
}
mergeIndexes.add(sheetMergeProperties.getRowIndex());
}
@Override
public void afterSheetCreate(WriteSheet writeSheet, AnalysisContext analysisContext) {
super.afterSheetCreate(writeSheet, analysisContext);
mergeMap.clear();
}
@Override
public void afterSheetDispose(WriteSheet writeSheet, AnalysisContext analysisContext) {
super.afterSheetDispose(writeSheet, analysisContext);
mergeMap.clear();
}
@Override
public void addContent(List<List<String>> content, WriteSheet writeSheet, AnalysisContext analysisContext) {
for (Map.Entry<Integer, List<Integer>> entry : mergeMap.entrySet()) {
Integer columnIndex = entry.getKey();
List<Integer> mergeIndexes = entry.getValue();
mergeColumn(content, columnIndex, mergeIndexes);
}
}
private void mergeColumn(List<List<String>> content, Integer columnIndex, List<Integer> mergeIndexes) {
if (mergeIndexes.size() <= 1) return;
Integer rowIndex = mergeIndexes.get(0);
String value = content.get(rowIndex).get(columnIndex);
for (int i = 1; i < mergeIndexes.size(); i++) {
Integer nextRowIndex = mergeIndexes.get(i);
String nextValue = content.get(nextRowIndex).get(columnIndex);
if (!StringUtils.isEmpty(nextValue) && !nextValue.equals(value)) {
LOGGER.warn("Cannot merge cells due to different values in column[{}]: '{}' != '{}'", columnIndex, value, nextValue);
return;
}
}
for (int i = 1; i < mergeIndexes.size(); i++) {
Integer nextRowIndex = mergeIndexes.get(i);
content.get(nextRowIndex).set(columnIndex, null);
}
}
}
/**
* 自定义表头写入处理器
*/
private static class CustomHeadWriteHandler extends AnalysisEventListener<List<String>> {
private Map<Integer, String> headMap = new HashMap<>();
@Override
public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
super.invokeHead(headMap, context);
this.headMap.clear();
for (Map.Entry<Integer, CellData> entry : headMap.entrySet()) {
this.headMap.put(entry.getKey(), entry.getValue().getStringValue());
}
}
@Override
public void extra(CellExtra extra, AnalysisContext context) {
super.extra(extra, context);
if (extra.getType() == CellExtraTypeEnum.MERGE) {
mergeHead(extra.getRowIndex(), extra.getColumnIndex(), extra.getRowIndex() + extra.getRowSpan() - 1, extra.getColumnIndex() + extra.getColSpan() - 1);
}
}
private void mergeHead(Integer startRowIndex, Integer startColumnIndex, Integer endRowIndex, Integer endColumnIndex) {
if (startRowIndex.equals(endRowIndex)) {
String value = headMap.get(startColumnIndex);
if (value != null) {
for (int i = startColumnIndex + 1; i <= endColumnIndex; i++) {
String nextValue = headMap.get(i);
if (!StringUtils.isEmpty(nextValue) && !nextValue.equals(value)) {
LOGGER.warn("Cannot merge column headers due to different values in row[{}]: '{}' != '{}'", startRowIndex, value, nextValue);
return;
}
}
for (int i = startColumnIndex + 1; i <= endColumnIndex; i++) {
headMap.remove(i);
}
}
} else if (startColumnIndex.equals(endColumnIndex)) {
String value = headMap.get(startColumnIndex);
if (value != null) {
for (int i = startRowIndex + 1; i <= endRowIndex; i++) {
String nextValue = headMap.get(i);
if (!StringUtils.isEmpty(nextValue) && !nextValue.equals(value)) {
LOGGER.warn("Cannot merge row headers due to different values in column[{}]: '{}' != '{}'", startColumnIndex, value, nextValue);
return;
}
}
for (int i = startRowIndex + 1; i <= endRowIndex; i++) {
headMap.remove(i);
}
}
}
}
@Override
public void invoke(List<String> data, AnalysisContext context) {
if (context.readRowHolder().getRowIndex() == 0) {
for (int i = 0; i < data.size(); i++) {
String value = data.get(i);
if (value != null) {
headMap.put(i, value);
}
}
}
}
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
super.onException(exception, context);
LOGGER.error("Exception occurred during analysis", exception);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
headMap.clear();
}
@Override
public void onException(Exception exception, AnalysisContext context, List<ExcelContentProperty> list) throws Exception {
super.onException(exception, context, list);
LOGGER.error("Exception occurred during analysis", exception);
}
@Override
public boolean hasNext(AnalysisContext context) {
return super.hasNext(context);
}
@Override
public List<List<String>> invokeHead(Map<Integer, CellData> headMap, Head head, AnalysisContext context) {
return super.invokeHead(headMap, head, context);
}
}
}
```
这个工具类包括两个主要的功能:
- `fillData`方法:使用EasyExcel库将数据填充到指定的Excel工作表中。该方法接收三个参数:文件路径、工作表名称和数据列表。它还注册了一个自定义的合并策略和一个自定义的表头写入处理器。
- `MergeStrategy`类:合并策略是一个实现`AbstractMergeStrategy`抽象类的内部类。它使用一个`mergeMap`来跟踪要合并的列和行,然后在`addContent`方法中执行实际的合并操作。
- `CustomHeadWriteHandler`类:表头写入处理器是一个实现`AnalysisEventListener`接口的内部类。它用来处理表头合并和异常处理。
使用这个工具类非常简单。只需调用`fillData`方法并传递文件路径、工作表名称和数据列表即可。例如:
```java
List<List<String>> data = new ArrayList<>();
// 添加数据
EasyExcelUtil.fillData("test.xlsx", "Sheet1", data);
```
这个示例只是一个简单的例子,您可以根据自己的需求对这个工具类进行修改和扩展。
阅读全文