refactor(excel): file => excel

This commit is contained in:
2025-06-17 21:19:57 +08:00
parent 8806eb9942
commit 5a53d953da
19 changed files with 253 additions and 119 deletions

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>top.continew</groupId>
<artifactId>continew-starter-excel</artifactId>
<version>${revision}</version>
</parent>
<artifactId>continew-starter-excel-core</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>ContiNew Starter Excel 文件处理模块 - 核心模块</description>
</project>

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel导出注解
*
* @author jiang4yu
* @since 2.13.0
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelExport {
/**
* 字段名称
*/
String value();
/**
* 导出排序先后: 数字越小越靠前默认按Java类字段顺序导出
*/
int sort() default 0;
/**
* 导出映射格式如0-未知;1-男;2-女
*/
String kv() default "";
/**
* 导出模板示例值(有值的话,直接取该值,不做映射)
*/
String example() default "";
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel 导入注解
*
* @author jiang4yu
* @since 2.13.0
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelImport {
/**
* 字段名称
*/
String value();
/**
* 导出映射格式如0-未知;1-男;2-女
*/
String kv() default "";
/**
* 是否为必填字段(默认为非必填)
*/
boolean required() default false;
/**
* 最大长度默认255
*/
int maxLength() default 255;
/**
* 导入唯一性验证(多个字段则取联合验证)
*/
boolean unique() default false;
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>top.continew</groupId>
<artifactId>continew-starter-excel</artifactId>
<version>${revision}</version>
</parent>
<artifactId>continew-starter-excel-fastexcel</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>ContiNew Starter Excel 文件处理模块 - FastExcel</description>
<dependencies>
<!-- Excel 文件处理模块 - 核心模块 -->
<dependency>
<groupId>top.continew</groupId>
<artifactId>continew-starter-excel-core</artifactId>
</dependency>
<!-- FastExcel基于 Java 的快速、简洁、解决大文件内存溢出的 Excel 处理工具) -->
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.excel.converter;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.enums.BaseEnum;
/**
* Easy Excel 枚举接口转换器
*
* @author Charles7c
* @see BaseEnum
* @since 1.2.0
*/
public class ExcelBaseEnumConverter implements Converter<BaseEnum<?>> {
@Override
public Class<BaseEnum> supportJavaTypeKey() {
return BaseEnum.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 转换为 Java 数据(读取 Excel
*/
@Override
public BaseEnum<?> convertToJavaData(ReadCellData<?> cellData,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return BaseEnum.getByDescription(cellData.getStringValue(), contentProperty.getField().getType());
}
/**
* 转换为 Excel 数据(写入 Excel
*/
@Override
public WriteCellData<String> convertToExcelData(BaseEnum<?> value,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (value == null) {
return new WriteCellData<>(StringConstants.EMPTY);
}
return new WriteCellData<>(value.getDescription());
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.excel.converter;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
/**
* Easy Excel 大数值转换器
* <p>
* Excel 中对长度超过 15 位的数值输入是有限制的,从 16 位开始无论录入什么数字均会变为 0因此输入时只能以文本的形式进行录入
* </p>
*
* @author Charles7c
* @since 1.0.0
*/
public class ExcelBigNumberConverter implements Converter<Long> {
/**
* Excel 输入数值长度限制
*/
private static final int MAX_LENGTH = 15;
@Override
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 转换为 Java 数据(读取 Excel
*/
@Override
public Long convertToJavaData(ReadCellData<?> cellData,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return Convert.toLong(cellData.getData());
}
/**
* 转换为 Excel 数据(写入 Excel
*/
@Override
public WriteCellData<Object> convertToExcelData(Long value,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (value != null) {
String str = Long.toString(value);
if (str.length() > MAX_LENGTH) {
return new WriteCellData<>(str);
}
}
WriteCellData<Object> writeCellData = new WriteCellData<>(NumberUtil.toBigDecimal(value));
writeCellData.setType(CellDataTypeEnum.NUMBER);
return writeCellData;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.excel.converter;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import org.springframework.stereotype.Component;
import top.continew.starter.core.constant.StringConstants;
import java.util.List;
/**
* Easy Excel List 集合转换器
*
* <p>
* 仅适合 List<基本类型> <=> xxx,xxx 转换
* </p>
*
* @author Charles7c
* @since 2.0.2
*/
@Component
public class ExcelListConverter implements Converter<List> {
@Override
public Class supportJavaTypeKey() {
return List.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public List convertToJavaData(ReadCellData<?> cellData,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
String stringValue = cellData.getStringValue();
return CharSequenceUtil.split(stringValue, StringConstants.COMMA);
}
@Override
public WriteCellData<Object> convertToExcelData(List value,
ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
WriteCellData<Object> writeCellData = new WriteCellData<>(CollUtil.join(value, StringConstants.COMMA));
writeCellData.setType(CellDataTypeEnum.STRING);
return writeCellData;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.excel.util;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.URLUtil;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.continew.starter.core.exception.BaseException;
import top.continew.starter.excel.converter.ExcelBigNumberConverter;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* Excel 工具类
*
* @author Charles7c
* @since 1.0.0
*/
public class ExcelUtils {
private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);
private ExcelUtils() {
}
/**
* 导出
*
* @param list 导出数据集合
* @param fileName 文件名
* @param clazz 导出数据类型
* @param response 响应对象
*/
public static <T> void export(List<T> list, String fileName, Class<T> clazz, HttpServletResponse response) {
export(list, fileName, "Sheet1", Collections.emptySet(), clazz, response);
}
/**
* 导出
*
* @param list 导出数据集合
* @param fileName 文件名
* @param sheetName 工作表名称
* @param excludeColumnFieldNames 排除字段
* @param clazz 导出数据类型
* @param response 响应对象
*/
public static <T> void export(List<T> list,
String fileName,
String sheetName,
Set<String> excludeColumnFieldNames,
Class<T> clazz,
HttpServletResponse response) {
try {
String exportFileName = URLUtil.encode("%s_%s.xlsx".formatted(fileName, DateUtil
.format(new Date(), DatePattern.PURE_DATETIME_PATTERN)));
response.setHeader("Content-disposition", "attachment;filename=" + exportFileName);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
FastExcelFactory.write(response.getOutputStream(), clazz)
.autoCloseStream(false)
// 自动适配宽度
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
// 自动转换大数值
.registerConverter(new ExcelBigNumberConverter())
.sheet(sheetName)
.excludeColumnFieldNames(excludeColumnFieldNames)
.doWrite(list);
} catch (Exception e) {
log.error("Export excel occurred an error: {}. fileName: {}.", e.getMessage(), fileName, e);
response.reset();
throw new BaseException("导出 Excel 出现错误");
}
}
}

View File

@@ -0,0 +1,35 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>top.continew</groupId>
<artifactId>continew-starter-excel</artifactId>
<version>${revision}</version>
</parent>
<artifactId>continew-starter-excel-poi</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>ContiNew Starter Excel 文件处理模块 - POI</description>
<dependencies>
<!-- Excel 文件处理模块 - 核心模块 -->
<dependency>
<groupId>top.continew</groupId>
<artifactId>continew-starter-excel-core</artifactId>
</dependency>
<!-- Apache POI适用于 Microsoft 文档的 Java API -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- 文件上传 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* 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 top.continew.starter.excel.model;
import java.util.LinkedHashMap;
/**
* Excel 字段信息
*
* @author jiang4yu
* @since 2.13.0
*/
public class ExcelClassField {
/**
* 字段名称
*/
private String fieldName;
/**
* 表头名称
*/
private String name;
/**
* 映射关系
*/
private LinkedHashMap<String, String> kvMap;
/**
* 示例值
*/
private Object example;
/**
* 排序
*/
private int sort;
/**
* 是否为注解字段0-否1-是
*/
private int hasAnnotation;
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LinkedHashMap<String, String> getKvMap() {
return kvMap;
}
public void setKvMap(LinkedHashMap<String, String> kvMap) {
this.kvMap = kvMap;
}
public Object getExample() {
return example;
}
public void setExample(Object example) {
this.example = example;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public int getHasAnnotation() {
return hasAnnotation;
}
public void setHasAnnotation(int hasAnnotation) {
this.hasAnnotation = hasAnnotation;
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>top.continew</groupId>
<artifactId>continew-starter</artifactId>
<version>${revision}</version>
</parent>
<artifactId>continew-starter-excel</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>ContiNew Starter Excel 文件处理模块</description>
<modules>
<module>continew-starter-excel-core</module>
<module>continew-starter-excel-fastexcel</module>
<module>continew-starter-excel-poi</module>
</modules>
<dependencies>
<!-- 核心模块 -->
<dependency>
<groupId>top.continew</groupId>
<artifactId>continew-starter-core</artifactId>
</dependency>
</dependencies>
</project>