sheetList = Arrays.asList(sheetNums);
InputStream fis = null;
try {
//update-begin----author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作--------
//ClassPathResource resource = new ClassPathResource(url);
fis = new FileInputStream(url);
LOGGER.info(" >>> poi3升级到4兼容改造工作, url="+url);
//fis = resource.getInputStream();
//update-end-----author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作--------
Workbook wb = WorkbookFactory.create(fis);
// 删除其他的sheet
if (!needAll) {
for (int i = wb.getNumberOfSheets() - 1; i >= 0; i--) {
if (!sheetList.contains(i)) {
wb.removeSheetAt(i);
}
}
}
return wb;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
try {
fis.close();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
return null;
}
//update-end-author:wangshuai date:20200730 for:jar 包上传到服务器后 autopoi 读取不到excel模版文件 #1505
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/cache/ImageCache.java
================================================
/**
* Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com)
*
* 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.jeecgframework.poi.cache;
import org.apache.poi.util.IOUtils;
import org.jeecgframework.poi.cache.manager.POICacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
/**
* 图片缓存处理
*
* @author liusq
* 2022-05-27 下午4:16:32
*/
public class ImageCache {
private static final Logger LOGGER = LoggerFactory
.getLogger(ImageCache.class);
public static byte[] getImage(String imagePath) {
InputStream is = POICacheManager.getFile(imagePath);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
final ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
try {
int ch;
while ((ch = is.read()) != -1) {
swapStream.write(ch);
}
Image image = Toolkit.getDefaultToolkit().createImage(swapStream.toByteArray());
BufferedImage bufferImg = toBufferedImage(image);
ImageIO.write(bufferImg,
imagePath.substring(imagePath.lastIndexOf(".") + 1, imagePath.length()),
byteArrayOut);
return byteArrayOut.toByteArray();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
return null;
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(swapStream);
IOUtils.closeQuietly(byteArrayOut);
}
}
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
try {
int transparency = Transparency.OPAQUE;
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null),
image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
bimage = new BufferedImage(image.getWidth(null),
image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/cache/WordCache.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.cache;
import java.io.InputStream;
import org.jeecgframework.poi.cache.manager.POICacheManager;
import org.jeecgframework.poi.word.entity.MyXWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* word 缓存中心
*
* @author JEECG
* @date 2014年7月24日 下午10:54:31
*/
public class WordCache {
private static final Logger LOGGER = LoggerFactory.getLogger(WordCache.class);
public static MyXWPFDocument getXWPFDocumen(String url) {
InputStream is = null;
try {
is = POICacheManager.getFile(url);
MyXWPFDocument doc = new MyXWPFDocument(is);
return doc;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
try {
is.close();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
return null;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/cache/manager/FileLoade.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.cache.manager;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 文件加载类,根据路径加载指定文件
*
* @author JEECG
* @date 2014年2月10日
* @version 1.0
*/
class FileLoade {
private static final Logger LOGGER = LoggerFactory.getLogger(FileLoade.class);
public byte[] getFile(String url) {
FileInputStream fileis = null;
ByteArrayOutputStream baos = null;
try {
// 先用绝对路径查询,再查询相对路径
try {
fileis = new FileInputStream(url);
} catch (FileNotFoundException e) {
String path = PoiPublicUtil.getWebRootPath(url);
fileis = new FileInputStream(path);
}
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = fileis.read(buffer)) > -1) {
baos.write(buffer, 0, len);
}
baos.flush();
return baos.toByteArray();
} catch (FileNotFoundException e) {
LOGGER.error(e.getMessage(), e);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
} finally {
try {
if (fileis != null)
fileis.close();
if (fileis != null)
baos.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
LOGGER.error(fileis + "这个路径文件没有找到,请查询");
return null;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/cache/manager/POICacheManager.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.cache.manager;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
* 缓存管理
*
* @author JEECG
* @date 2014年2月10日
* @version 1.0
*/
public final class POICacheManager {
private static final Logger LOGGER = LoggerFactory.getLogger(POICacheManager.class);
private static LoadingCache loadingCache;
static {
loadingCache = CacheBuilder.newBuilder().expireAfterWrite(7, TimeUnit.DAYS).maximumSize(50).build(new CacheLoader() {
@Override
public byte[] load(String url) throws Exception {
return new FileLoade().getFile(url);
}
});
}
public static InputStream getFile(String id) {
try {
// 复杂数据,防止操作原数据
byte[] result = Arrays.copyOf(loadingCache.get(id), loadingCache.get(id).length);
return new ByteArrayInputStream(result);
} catch (ExecutionException e) {
LOGGER.error(e.getMessage(), e);
}
return null;
}
//update-begin---author:chenrui ---date:20240403 for:[issue/#5933]增加清除缓存方法------------
/**
* 清除所有缓存
*
* @author chenrui
* @date 2024/4/3 11:46
*/
public static void cleanAll() {
loadingCache.invalidateAll();
}
/**
* 清除缓存
*
* @param id 缓存key
* @author chenrui
* @date 2024/4/3 11:46
*/
public static void clean(String id) {
loadingCache.invalidate(id);
}
//update-end---author:chenrui ---date:20240403 for:[issue/#5933]增加清除缓存方法------------
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/cache/package-info.java
================================================
/**
* 对POI用到的模板进行缓存,进行统一管理,缓存工具暂时使用guava(脱离配置文件)
* 缓存方式统一为byte[] 屏蔽文件类型的差异
* 缓存获取方式,URL或者URL+index(EXcel的)
*/
/**
* @author JEECG
* @date 2014年2月10日
* @version 1.0
*/
package org.jeecgframework.poi.cache;
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/consts/ImageScaleMode.java
================================================
package org.jeecgframework.poi.consts;
/**
* 图片缩放模式枚举
* for [issues/8892] AutoPoi ImageEntity建议添加scale属性,控制图片导出缩放模式
*
* @author chenrui
* @date 2025-10-29
*/
public enum ImageScaleMode {
/**
* 拉伸填充
*/
STRETCH(0, "拉伸填充"),
/**
* 等比例缩放适应
*/
FIT(1, "等比例缩放适应"),
/**
* 不缩放(原始大小)
*/
ORIGINAL(2, "不缩放(原始大小)");
private final int code;
private final String description;
ImageScaleMode(int code, String description) {
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
/**
* 根据code获取枚举
*
* @param code 代码值
* @return 对应的枚举值,如果找不到则返回STRETCH
*/
public static ImageScaleMode valueOf(int code) {
for (ImageScaleMode mode : values()) {
if (mode.code == code) {
return mode;
}
}
return STRETCH;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/entity/ImageEntity.java
================================================
package org.jeecgframework.poi.entity;
import org.jeecgframework.poi.consts.ImageScaleMode;
/**
* word导出,图片设置和图片信息
*
* @author liusq
* @date 2022-5-27
*/
public class ImageEntity {
public static String URL = "url";
public static String Data = "data";
/**
* 图片输入方式
*/
private String type = URL;
/**
* 图片宽度
*/
private int width;
// 图片高度
private int height;
// 图片地址
private String url;
// 图片信息
private byte[] data;
private int rowspan = 1;
private int colspan = 1;
/**
* 图片缩放模式枚举
* for [issues/8892] AutoPoi ImageEntity建议添加scale属性,控制图片导出缩放模式
*/
private ImageScaleMode scaleModeEnum = ImageScaleMode.STRETCH;
public ImageEntity() {
}
public ImageEntity(byte[] data, int width, int height) {
this.data = data;
this.width = width;
this.height = height;
this.type = Data;
}
public ImageEntity(String url, int width, int height) {
this.url = url;
this.width = width;
this.height = height;
}
public byte[] getData() {
return data;
}
public int getHeight() {
return height;
}
public String getType() {
return type;
}
public String getUrl() {
return url;
}
public int getWidth() {
return width;
}
public void setData(byte[] data) {
this.data = data;
}
public void setHeight(int height) {
this.height = height;
}
public void setType(String type) {
this.type = type;
}
public void setUrl(String url) {
this.url = url;
}
public void setWidth(int width) {
this.width = width;
}
public int getRowspan() {
return rowspan;
}
public void setRowspan(int rowspan) {
this.rowspan = rowspan;
}
public int getColspan() {
return colspan;
}
public void setColspan(int colspan) {
this.colspan = colspan;
}
/**
* 获取图片缩放模式
* @deprecated 使用 {@link #getScaleModeEnum()} 代替
* @return 缩放模式代码值
*/
@Deprecated
public int getScaleMode() {
return scaleModeEnum.getCode();
}
/**
* 设置图片缩放模式
* @deprecated 使用 {@link #setScaleModeEnum(ImageScaleMode)} 代替
* @param scaleMode 缩放模式代码值
*/
@Deprecated
public void setScaleMode(int scaleMode) {
this.scaleModeEnum = ImageScaleMode.valueOf(scaleMode);
}
/**
* 获取图片缩放模式枚举
* @return 缩放模式枚举
*/
public ImageScaleMode getScaleModeEnum() {
return scaleModeEnum;
}
/**
* 设置图片缩放模式枚举
* @param scaleModeEnum 缩放模式枚举
*/
public void setScaleModeEnum(ImageScaleMode scaleModeEnum) {
this.scaleModeEnum = scaleModeEnum;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelExportUtil.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.TemplateExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.export.ExcelBatchExportServer;
import org.jeecgframework.poi.excel.export.ExcelExportServer;
import org.jeecgframework.poi.excel.export.template.ExcelExportOfTemplateUtil;
import org.jeecgframework.poi.handler.inter.IExcelExportServer;
import org.jeecgframework.poi.handler.inter.IExcelExportServerEnhanced;
import org.jeecgframework.poi.handler.inter.IWriter;
/**
* excel 导出工具类
*
* @author JEECG
* @version 1.0
* @date 2013-10-17
*/
//update-begin---author:chenrui ---date:20231221 for:[issue/#5248]加强继承扩展便利性(删除final)------------
public class ExcelExportUtil {
//update-end---author:chenrui ---date:20231221 for:[issue/#5248]加强继承扩展便利性(删除final)------------
//update-begin---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
//单sheet最大值
public static int USE_SXSSF_LIMIT = 100000;
//update-end---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
private ExcelExportUtil() {
}
//---update-begin-----autor:scott------date:20191016-------for:导出字段支持自定义--------
/**
* 根据Entity创建对应的Excel
*
* @param entity
* 表格标题属性
* @param pojoClass
* Excel对象Class
* @param dataSet
* Excel对象数据List
* @param exportFields
* 自定义导出Excel字段数组
*/
public static Workbook exportExcel(ExportParams entity, Class> pojoClass, Collection> dataSet,String[] exportFields) {
Workbook workbook;
if (ExcelType.HSSF.equals(entity.getType())) {
workbook = new HSSFWorkbook();
} else if (dataSet.size() < 1000) {
workbook = new XSSFWorkbook();
} else {
workbook = new SXSSFWorkbook();
}
new ExcelExportServer().createSheet(workbook, entity, pojoClass, dataSet,exportFields);
return workbook;
}
//---update-end-----autor:scott------date:20191016-------for:导出字段支持自定义--------
/**
* 根据Entity创建对应的Excel
*
* @param entity
* 表格标题属性
* @param pojoClass
* Excel对象Class
* @param dataSet
* Excel对象数据List
*/
public static Workbook exportExcel(ExportParams entity, Class> pojoClass, Collection> dataSet) {
Workbook workbook;
if (ExcelType.HSSF.equals(entity.getType())) {
workbook = new HSSFWorkbook();
} else if (dataSet.size() < 1000) {
workbook = new XSSFWorkbook();
} else {
workbook = new SXSSFWorkbook();
}
new ExcelExportServer().createSheet(workbook, entity, pojoClass, dataSet,null);
return workbook;
}
/**
* 根据Map创建对应的Excel
*
* @param entity
* 表格标题属性
* @param pojoClass
* Excel对象Class
* @param dataSet
* Excel对象数据List
*/
public static Workbook exportExcel(ExportParams entity, List entityList, Collection extends Map, ?>> dataSet) {
Workbook workbook;
if (ExcelType.HSSF.equals(entity.getType())) {
workbook = new HSSFWorkbook();
} else if (dataSet.size() < 1000) {
workbook = new XSSFWorkbook();
} else {
workbook = new SXSSFWorkbook();
}
new ExcelExportServer().createSheetForMap(workbook, entity, entityList, dataSet);
return workbook;
}
/**
* 一个excel 创建多个sheet
*
* @param list
* 多个Map key title 对应表格Title key entity 对应表格对应实体 key data
* Collection 数据
* @return
*/
public static Workbook exportExcel(List> list, ExcelType type) {
Workbook workbook;
if (ExcelType.HSSF.equals(type)) {
workbook = new HSSFWorkbook();
} else {
workbook = new XSSFWorkbook();
}
for (Map map : list) {
ExcelExportServer server = new ExcelExportServer();
server.createSheet(workbook, (ExportParams) map.get("title"), (Class>) map.get("entity"), (Collection>) map.get("data"),null);
}
return workbook;
}
/**
* 导出文件通过模板解析,不推荐这个了,推荐全部通过模板来执行处理
*
* @param params
* 导出参数类
* @param pojoClass
* 对应实体
* @param dataSet
* 实体集合
* @param map
*
* 模板集合
* @return
*/
public static Workbook exportExcel(TemplateExportParams params, Class> pojoClass, Collection> dataSet, Map map) {
return new ExcelExportOfTemplateUtil().createExcleByTemplate(params, pojoClass, dataSet, map);
}
/**
* 导出文件通过模板解析只有模板,没有集合
*
* @param params
* 导出参数类
* @param map
* 模板集合
* @return
*/
public static Workbook exportExcel(TemplateExportParams params, Map map) {
return new ExcelExportOfTemplateUtil().createExcleByTemplate(params, null, null, map);
}
//update-begin---author:liusq Date:20211227 for:[LOWCOD-2521]大数据导出方法【全局】----
/**
* 大数据量导出
*
* @param entity 表格标题属性
* @param pojoClass Excel对象Class
* @date 2022年1月4号
* @return ExcelBatchExportServer 批处理服务
*/
public static IWriter exportBigExcel(ExportParams entity, Class> pojoClass) {
ExcelBatchExportServer batchServer = new ExcelBatchExportServer();
batchServer.init(entity, pojoClass);
return batchServer;
}
/**
* 大数据量导出
*
* @param entity
* @param excelParams
* @date 2022年1月4号
* @return ExcelBatchExportServer 批处理服务
*/
public static IWriter exportBigExcel(ExportParams entity, List excelParams) {
ExcelBatchExportServer batchServer = new ExcelBatchExportServer();
batchServer.init(entity, excelParams);
return batchServer;
}
/**
* 大数据量导出
*
* @param entity 导出参数属性
* @param pojoClass Excel对象Class
* @param server 查询数据的接口
* @param queryParams 查询数据的参数
* @date 2022年1月4号
* @return Workbook
*/
public static Workbook exportBigExcel(ExportParams entity, Class> pojoClass,
IExcelExportServer server, Object queryParams) {
ExcelBatchExportServer batchServer = new ExcelBatchExportServer();
batchServer.init(entity, pojoClass);
return batchServer.exportBigExcel(server, queryParams);
}
/**
* 大数据量导出
* @param entity
* @param excelParams
* @param server 查询数据的接口
* @param queryParams 查询数据的参数
* @date 2022年1月4号
* @return Workbook
*/
public static Workbook exportBigExcel(ExportParams entity, List excelParams,
IExcelExportServer server, Object queryParams) {
ExcelBatchExportServer batchServer = new ExcelBatchExportServer();
batchServer.init(entity, excelParams);
return batchServer.exportBigExcel(server, queryParams);
}
//update-end---author:liusq Date:20211227 for:[LOWCOD-2521]大数据导出方法【全局】----
//update-begin---author:chenrui Date:20251103 for:[issues/8892]解决40万+数据导出查询效率问题----
/**
* 大数据量导出 - 高性能游标分页方案
* for [QQYUN-13964]演示系统数据量大,点击没反应
*
* 适用场景:
* 1. 数据量超过40万+的导出场景
* 2. 需要避免深分页性能问题
* 3. 数据表有自增ID或其他有序字段
*
* 性能对比:
* - 传统方式: 40万数据,最后一页查询可能需要10+秒
* - 游标方式: 40万数据,每页查询时间恒定在0.1秒左右
*
* 使用示例:
*
* ExportParams params = new ExportParams("订单列表", "订单");
* IExcelExportServerEnhanced server = new IExcelExportServerEnhanced() {
* public List selectListForExcelExport(Object queryParams, Object lastRecord, int pageSize) {
* Long lastId = lastRecord != null ? ((Order)lastRecord).getId() : 0L;
* return orderMapper.selectList(new QueryWrapper()
* .gt("id", lastId)
* .orderByAsc("id")
* .last("LIMIT " + pageSize));
* }
* };
* Workbook workbook = ExcelExportUtil.exportBigExcelEnhanced(params, Order.class, server, queryParams);
*
*
* @param entity 导出参数属性
* @param pojoClass Excel对象Class
* @param server 增强的查询数据接口(支持游标分页)
* @param queryParams 查询数据的参数
* @date 2025年11月3号
* @return Workbook
*/
public static Workbook exportBigExcelEnhanced(ExportParams entity, Class pojoClass,
IExcelExportServerEnhanced server, Object queryParams) {
ExcelBatchExportServer batchServer = new ExcelBatchExportServer();
batchServer.init(entity, pojoClass);
return batchServer.exportBigExcelEnhanced(server, queryParams);
}
/**
* 大数据量导出 - 高性能游标分页方案(自定义列)
*
* @param entity 导出参数属性
* @param excelParams 自定义导出列
* @param server 增强的查询数据接口(支持游标分页)
* @param queryParams 查询数据的参数
* @date 2025年11月3号
* @return Workbook
*/
public static Workbook exportBigExcelEnhanced(ExportParams entity, List excelParams,
IExcelExportServerEnhanced server, Object queryParams) {
ExcelBatchExportServer batchServer = new ExcelBatchExportServer();
batchServer.init(entity, excelParams);
return batchServer.exportBigExcelEnhanced(server, queryParams);
}
//update-end---author:chenrui Date:20251103 for:[issues/8892]解决40万+数据导出查询效率问题----
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportCheckUtil.java
================================================
package org.jeecgframework.poi.excel;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.jeecgframework.dict.service.AutoPoiDictServiceI;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
import org.jeecgframework.poi.excel.annotation.ExcelVerify;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.params.ExcelCollectionParams;
import org.jeecgframework.poi.excel.entity.params.ExcelImportEntity;
import org.jeecgframework.poi.excel.entity.params.ExcelVerifyEntity;
import org.jeecgframework.poi.excel.imports.ExcelImportServer;
import org.jeecgframework.poi.exception.excel.ExcelImportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelImportEnum;
import org.jeecgframework.poi.util.ExcelUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.util.*;
/**
* EXCEL INCLUE CHECK
* 验证excel标题是否存在,当前默认有0.8(80%)即可通过验证
*/
public class ExcelImportCheckUtil {
private final static Logger LOGGER = LoggerFactory.getLogger(ExcelImportCheckUtil.class);
/**当有标题到达多少可以通过验证*/
public static final Double defScreenRate = 0.8;
/**
* check inclue filed match rate
* @param inputstream
* @param pojoClass
* @param params
* @return
*/
public static Boolean check(InputStream inputstream, Class> pojoClass, ImportParams params) {
return check(inputstream,pojoClass,params,defScreenRate);
}
/**
* check inclue filed match rate
* @param inputstream
* @param pojoClass
* @param params
* @param screenRate field match rate (defalut:0.8)
* @return
*/
public static Boolean check(InputStream inputstream, Class> pojoClass, ImportParams params, Double screenRate) {
Workbook book = null;
int errorNum = 0;
int successNum = 0;
if (!(inputstream.markSupported())) {
inputstream = new PushbackInputStream(inputstream, 8);
}
try {
// if (POIFSFileSystem.hasPOIFSHeader(inputstream)) {
// book = new HSSFWorkbook(inputstream);
// } else if (POIXMLDocument.hasOOXMLHeader(inputstream)) {
// book = new XSSFWorkbook(OPCPackage.open(inputstream));
// }
book = WorkbookFactory.create(inputstream);
LOGGER.info(" >>> poi3升级到4兼容改造工作, pojoClass="+pojoClass);
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < params.getSheetNum(); i++) {
Row row = null;
//跳过表头和标题行
Iterator rows;
try{
rows= book.getSheetAt(i).rowIterator();
}catch (Exception e){
//为空说明读取不到,故不是excel
throw new RuntimeException("请导入正确格式的excel文件!");
}
for (int j = 0; j < params.getTitleRows() + params.getHeadRows(); j++) {
try{
row = rows.next();
}catch (NoSuchElementException e){
//为空说明标题不出在,excel格式错误
throw new RuntimeException("请填写内容标题!");
}
}
Sheet sheet = book.getSheetAt(i);
Map titlemap = null;
try {
titlemap = getTitleMap(sheet, params);
} catch (Exception e) {
e.printStackTrace();
}
Set columnIndexSet = titlemap.keySet();
Integer maxColumnIndex = Collections.max(columnIndexSet);
Integer minColumnIndex = Collections.min(columnIndexSet);
while (rows.hasNext() && (row == null || sheet.getLastRowNum() - row.getRowNum() > params.getLastOfInvalidRow())) {
row = rows.next();
Map excelParams = new HashMap();
List excelCollection = new ArrayList();
String targetId = null;
if (!Map.class.equals(pojoClass)) {
Field fileds[] = PoiPublicUtil.getClassFields(pojoClass);
ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
if (etarget != null) {
targetId = etarget.value();
}
try {
getAllExcelField(targetId, fileds, excelParams, excelCollection, pojoClass, null);
} catch (Exception e) {
e.printStackTrace();
}
}
try {
int firstCellNum = row.getFirstCellNum();
if (firstCellNum > minColumnIndex) {
firstCellNum = minColumnIndex;
}
int lastCellNum = row.getLastCellNum();
if (lastCellNum < maxColumnIndex + 1) {
lastCellNum = maxColumnIndex + 1;
}
for (int j = firstCellNum, le = lastCellNum; j < le; j++) {
String titleString = (String) titlemap.get(j);
if (excelParams.containsKey(titleString) || Map.class.equals(pojoClass)) {
successNum+=1;
}else{
if(excelCollection.size()>0){
Iterator var33 = excelCollection.iterator();
ExcelCollectionParams param = (ExcelCollectionParams)var33.next();
if (param.getExcelParams().containsKey(titleString)) {
successNum+=1;
}else{
errorNum+=1;
}
}else{
errorNum+=1;
}
}
}
if(successNumerrorNum){
if(errorNum>0){
double newNumber = (double) successNum / (successNum + errorNum);
BigDecimal bg = new BigDecimal(newNumber);
double f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
if(f1 getTitleMap(Sheet sheet, ImportParams params) throws Exception {
Map titlemap = new HashMap();
Iterator cellTitle = null;
String collectionName = null;
Row headRow = null;
int headBegin = params.getTitleRows();
int allRowNum = sheet.getPhysicalNumberOfRows();
while(headRow == null && headBegin < allRowNum){
headRow = sheet.getRow(headBegin++);
}
if(headRow==null){
throw new Exception("不识别该文件");
}
if (ExcelUtil.isMergedRegion(sheet, headRow.getRowNum(), 0)) {
params.setHeadRows(2);
}else{
params.setHeadRows(1);
}
cellTitle = headRow.cellIterator();
while (cellTitle.hasNext()) {
Cell cell = cellTitle.next();
String value = getKeyValue(cell);
if (StringUtils.isNotEmpty(value)) {
titlemap.put(cell.getColumnIndex(), value);//加入表头列表
}
}
//多行表头
for (int j = headBegin; j < headBegin + params.getHeadRows()-1; j++) {
headRow = sheet.getRow(j);
cellTitle = headRow.cellIterator();
while (cellTitle.hasNext()) {
Cell cell = cellTitle.next();
String value = getKeyValue(cell);
if (StringUtils.isNotEmpty(value)) {
int columnIndex = cell.getColumnIndex();
//当前cell的上一行是否为合并单元格
if(ExcelUtil.isMergedRegion(sheet, cell.getRowIndex()-1, columnIndex)){
collectionName = ExcelUtil.getMergedRegionValue(sheet, cell.getRowIndex()-1, columnIndex);
if(params.isIgnoreHeader(collectionName)){
titlemap.put(cell.getColumnIndex(), value);
}else{
titlemap.put(cell.getColumnIndex(), collectionName + "_" + value);
}
}else{
titlemap.put(cell.getColumnIndex(), value);
}
}
}
}
return titlemap;
}
/**
* 获取key的值,针对不同类型获取不同的值
*
* @Author JEECG
* @date 20201023
* @param cell
* @return
*/
private static String getKeyValue(Cell cell) {
if(cell==null){
return null;
}
Object obj = null;
switch (cell.getCellType()) {
case STRING:
obj = cell.getStringCellValue();
break;
case BOOLEAN:
obj = cell.getBooleanCellValue();
break;
case NUMERIC:
obj = cell.getNumericCellValue();
break;
case FORMULA:
obj = cell.getCellFormula();
break;
}
return obj == null ? null : obj.toString().trim();
}
/**
* 获取需要导出的全部字段
*
*
*
* @param targetId
* 目标ID
* @param fields
* @param excelCollection
* @throws Exception
*/
public static void getAllExcelField(String targetId, Field[] fields, Map excelParams, List excelCollection, Class> pojoClass, List getMethods) throws Exception {
ExcelImportEntity excelEntity = null;
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (PoiPublicUtil.isNotUserExcelUserThis(null, field, targetId)) {
continue;
}
if (PoiPublicUtil.isCollection(field.getType())) {
// 集合对象设置属性
ExcelCollectionParams collection = new ExcelCollectionParams();
collection.setName(field.getName());
Map temp = new HashMap();
ParameterizedType pt = (ParameterizedType)field.getGenericType();
Class> clz = (Class)pt.getActualTypeArguments()[0];
collection.setType(clz);
getExcelFieldList(targetId, PoiPublicUtil.getClassFields(clz), clz, temp, (List)null);
collection.setExcelParams(temp);
collection.setExcelName(((ExcelCollection)field.getAnnotation(ExcelCollection.class)).name());
additionalCollectionName(collection);
excelCollection.add(collection);
} else if (PoiPublicUtil.isJavaClass(field)) {
addEntityToMap(targetId, field, (ExcelImportEntity)excelEntity, pojoClass, getMethods, excelParams);
} else {
List newMethods = new ArrayList();
if (getMethods != null) {
newMethods.addAll(getMethods);
}
newMethods.add(PoiPublicUtil.getMethod(field.getName(), pojoClass));
getAllExcelField(targetId, PoiPublicUtil.getClassFields(field.getType()), excelParams, excelCollection, field.getType(), newMethods);
}
}
}
public static void getExcelFieldList(String targetId, Field[] fields, Class> pojoClass, Map temp, List getMethods) throws Exception {
ExcelImportEntity excelEntity = null;
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (!PoiPublicUtil.isNotUserExcelUserThis((List)null, field, targetId)) {
if (PoiPublicUtil.isJavaClass(field)) {
addEntityToMap(targetId, field, (ExcelImportEntity)excelEntity, pojoClass, getMethods, temp);
} else {
List newMethods = new ArrayList();
if (getMethods != null) {
newMethods.addAll(getMethods);
}
newMethods.add(PoiPublicUtil.getMethod(field.getName(), pojoClass, field.getType()));
getExcelFieldList(targetId, PoiPublicUtil.getClassFields(field.getType()), field.getType(), temp, newMethods);
}
}
}
}
/**
* 追加集合名称到前面
*
* @param collection
*/
private static void additionalCollectionName(ExcelCollectionParams collection) {
Set keys = new HashSet();
keys.addAll(collection.getExcelParams().keySet());
Iterator var3 = keys.iterator();
while(var3.hasNext()) {
String key = (String)var3.next();
collection.getExcelParams().put(collection.getExcelName() + "_" + key, collection.getExcelParams().get(key));
collection.getExcelParams().remove(key);
}
}
/**
* 把这个注解解析放到类型对象中
*
* @param targetId
* @param field
* @param excelEntity
* @param pojoClass
* @param getMethods
* @param temp
* @throws Exception
*/
public static void addEntityToMap(String targetId, Field field, ExcelImportEntity excelEntity, Class> pojoClass, List getMethods, Map temp) throws Exception {
Excel excel = field.getAnnotation(Excel.class);
excelEntity = new ExcelImportEntity();
excelEntity.setType(excel.type());
excelEntity.setSaveUrl(excel.savePath());
excelEntity.setSaveType(excel.imageType());
excelEntity.setReplace(excel.replace());
excelEntity.setDatabaseFormat(excel.databaseFormat());
excelEntity.setVerify(getImportVerify(field));
excelEntity.setSuffix(excel.suffix());
excelEntity.setNumFormat(excel.numFormat());
excelEntity.setGroupName(excel.groupName());
//update-begin-author:taoYan date:20180202 for:TASK #2067 【bug excel 问题】excel导入字典文本翻译问题
excelEntity.setMultiReplace(excel.multiReplace());
if(StringUtils.isNotEmpty(excel.dicCode())){
AutoPoiDictServiceI jeecgDictService = null;
try {
jeecgDictService = ApplicationContextUtil.getContext().getBean(AutoPoiDictServiceI.class);
} catch (Exception e) {
}
if(jeecgDictService!=null){
String[] dictReplace = jeecgDictService.queryDict(excel.dictTable(), excel.dicCode(), excel.dicText());
if(excelEntity.getReplace()!=null && dictReplace!=null && dictReplace.length!=0){
excelEntity.setReplace(dictReplace);
}
}
}
//update-end-author:taoYan date:20180202 for:TASK #2067 【bug excel 问题】excel导入字典文本翻译问题
getExcelField(targetId, field, excelEntity, excel, pojoClass);
if (getMethods != null) {
List newMethods = new ArrayList();
newMethods.addAll(getMethods);
newMethods.add(excelEntity.getMethod());
excelEntity.setMethods(newMethods);
}
temp.put(excelEntity.getName(), excelEntity);
}
public static void getExcelField(String targetId, Field field, ExcelImportEntity excelEntity, Excel excel, Class> pojoClass) throws Exception {
excelEntity.setName(getExcelName(excel.name(), targetId));
String fieldname = field.getName();
//update-begin-author:taoyan for:TASK #2798 【例子】导入扩展方法,支持自定义导入字段转换规则
excelEntity.setMethod(PoiPublicUtil.getMethod(fieldname, pojoClass, field.getType(),excel.importConvert()));
//update-end-author:taoyan for:TASK #2798 【例子】导入扩展方法,支持自定义导入字段转换规则
if (StringUtils.isNotEmpty(excel.importFormat())) {
excelEntity.setFormat(excel.importFormat());
} else {
excelEntity.setFormat(excel.format());
}
}
/**
* 判断在这个单元格显示的名称
*
* @param exportName
* @param targetId
* @return
*/
public static String getExcelName(String exportName, String targetId) {
if (exportName.indexOf("_") < 0) {
return exportName;
}
String[] arr = exportName.split(",");
for (String str : arr) {
if (str.indexOf(targetId) != -1) {
return str.split("_")[0];
}
}
return null;
}
/**
* 获取导入校验参数
*
* @param field
* @return
*/
public static ExcelVerifyEntity getImportVerify(Field field) {
ExcelVerify verify = field.getAnnotation(ExcelVerify.class);
if (verify != null) {
ExcelVerifyEntity entity = new ExcelVerifyEntity();
entity.setEmail(verify.isEmail());
entity.setInterHandler(verify.interHandler());
entity.setMaxLength(verify.maxLength());
entity.setMinLength(verify.minLength());
entity.setMobile(verify.isMobile());
entity.setNotNull(verify.notNull());
entity.setRegex(verify.regex());
entity.setRegexTip(verify.regexTip());
entity.setTel(verify.isTel());
return entity;
}
return null;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportUtil.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.result.ExcelImportResult;
import org.jeecgframework.poi.excel.imports.ExcelImportServer;
import org.jeecgframework.poi.excel.imports.sax.SaxReadExcel;
import org.jeecgframework.poi.excel.imports.sax.parse.ISaxRowRead;
import org.jeecgframework.poi.handler.inter.IExcelReadRowHanlder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Excel 导入工具
*
* @author JEECG
* @date 2013-9-24
* @version 1.0
*/
@SuppressWarnings({ "unchecked" })
public final class ExcelImportUtil {
private ExcelImportUtil() {
}
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelImportUtil.class);
/**
* Excel 导入 数据源本地文件,不返回校验结果 导入 字 段类型 Integer,Long,Double,Date,String,Boolean
*
* @param file
* @param pojoClass
* @param params
* @return
* @throws Exception
*/
public static List importExcel(File file, Class> pojoClass, ImportParams params) {
FileInputStream in = null;
List result = null;
try {
in = new FileInputStream(file);
result = new ExcelImportServer().importExcelByIs(in, pojoClass, params).getList();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
try {
in.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
return result;
}
/**
* Excel 导入 数据源IO流,不返回校验结果 导入 字段类型 Integer,Long,Double,Date,String,Boolean
*
* @param file
* @param pojoClass
* @param params
* @return
* @throws Exception
*/
public static List importExcel(InputStream inputstream, Class> pojoClass, ImportParams params) throws Exception {
return new ExcelImportServer().importExcelByIs(inputstream, pojoClass, params).getList();
}
/**
* Excel 导入 数据源IO流,返回校验结果 字段类型 Integer,Long,Double,Date,String,Boolean
*
* @param file
* @param pojoClass
* @param params
* @return
* @throws Exception
*/
public static ExcelImportResult importExcelVerify(InputStream inputstream, Class> pojoClass, ImportParams params) throws Exception {
return new ExcelImportServer().importExcelByIs(inputstream, pojoClass, params);
}
/**
* Excel 导入 数据源本地文件,返回校验结果 字段类型 Integer,Long,Double,Date,String,Boolean
*
* @param file
* @param pojoClass
* @param params
* @return
* @throws Exception
*/
public static ExcelImportResult importExcelVerify(File file, Class> pojoClass, ImportParams params) {
FileInputStream in = null;
try {
in = new FileInputStream(file);
return new ExcelImportServer().importExcelByIs(in, pojoClass, params);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
try {
in.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
return null;
}
/**
* Excel 通过SAX解析方法,适合大数据导入,不支持图片 导入 数据源IO流,不返回校验结果 导入 字段类型
* Integer,Long,Double,Date,String,Boolean
*
* @param inputstream
* @param pojoClass
* @param params
* @return
* @throws Exception
*/
public static List importExcelBySax(InputStream inputstream, Class> pojoClass, ImportParams params) {
return new SaxReadExcel().readExcel(inputstream, pojoClass, params, null, null);
}
/**
* Excel 通过SAX解析方法,适合大数据导入,不支持图片 导入 数据源本地文件,不返回校验结果 导入 字 段类型
* Integer,Long,Double,Date,String,Boolean
*
* @param file
* @param rowRead
* @return
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static void importExcelBySax(InputStream inputstream, Class> pojoClass, ImportParams params, IExcelReadRowHanlder hanlder) {
new SaxReadExcel().readExcel(inputstream, pojoClass, params, null, hanlder);
}
/**
* Excel 通过SAX解析方法,适合大数据导入,不支持图片 导入 数据源IO流,不返回校验结果 导入 字段类型
* Integer,Long,Double,Date,String,Boolean
*
* @param file
* @param rowRead
* @return
* @throws Exception
*/
public static List importExcelBySax(InputStream inputstream, ISaxRowRead rowRead) {
return new SaxReadExcel().readExcel(inputstream, null, null, rowRead, null);
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelToHtmlUtil.java
================================================
package org.jeecgframework.poi.excel;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecgframework.poi.excel.html.ExcelToHtmlServer;
/**
* Excel 变成界面
*
* @author JEECG
* @date 2015年5月10日 上午11:51:48
*/
public final class ExcelToHtmlUtil {
private ExcelToHtmlUtil() {
}
/**
* 转换成为Table
*
* @param wb
* Excel
* @return
*/
public static String toTableHtml(Workbook wb) {
return new ExcelToHtmlServer(wb, false, 0).printPage();
}
/**
* 转换成为Table
*
* @param wb
* Excel
* @param sheetNum
* sheetNum
* @return
*/
public static String toTableHtml(Workbook wb, int sheetNum) {
return new ExcelToHtmlServer(wb, false, sheetNum).printPage();
}
/**
* 转换成为完整界面
*
* @param wb
* Excel
* @param sheetNum
* sheetNum
* @return
*/
public static String toAllHtml(Workbook wb) {
return new ExcelToHtmlServer(wb, true, 0).printPage();
}
/**
* 转换成为完整界面
*
* @param wb
* Excel
* @param sheetNum
* sheetNum
* @return
*/
public static String toAllHtml(Workbook wb, int sheetNum) {
return new ExcelToHtmlServer(wb, true, sheetNum).printPage();
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/Excel.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Inherited;
/**
* Excel 导出基本注释
*
* @author JEECG
* @date 2014年6月20日 下午10:25:12
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
//update-begin---author:chenrui ---date:20231221 for:[issue/#5248]加强继承扩展便利性------------
@Inherited
//update-end---author:chenrui ---date:20231221 for:[issue/#5248]加强继承扩展便利性------------
public @interface Excel {
/**
* 导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式
*/
public String databaseFormat() default "yyyyMMddHHmmss";
/**
* 导出的时间格式,以这个是否为空来判断是否需要格式化日期
*/
public String exportFormat() default "";
/**
* 时间格式,相当于同时设置了exportFormat 和 importFormat
*/
public String format() default "";
/**
* 导出时在excel中每个列的高度 单位为字符,一个汉字=2个字符
*/
public double height() default 10;
/**
* 导出类型 1 从file读取_old ,2 是从数据库中读取字节文件, 3文件地址_new, 4网络地址 同样导入也是一样的
*
*/
public int imageType() default 3;
/**
* 导入的时间格式,以这个是否为空来判断是否需要格式化日期
*/
public String importFormat() default "";
/**
* 文字后缀,如% 90 变成90%
*/
public String suffix() default "";
/**
* 是否换行 即支持\n
*/
public boolean isWrap() default true;
/**
* 合并单元格依赖关系,比如第二列合并是基于第一列 则{1}就可以了
*/
public int[] mergeRely() default {};
/**
* 纵向合并内容相同的单元格
*/
public boolean mergeVertical() default false;
/**
* 导出时,对应数据库的字段 主要是用户区分每个字段, 不能有annocation重名的 导出时的列名
* 导出排序跟定义了annotation的字段的顺序有关 可以使用a_id,b_id来确实是否使用
*/
public String name();
/**
* 是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row)
*/
public boolean needMerge() default false;
/**
* 展示到第几个可以使用a_id,b_id来确定不同排序
*/
public String orderNum() default "0";
/**
* 值得替换 导出是{"男_1","女_0"} 导入反过来,所以只用写一个
*/
public String[] replace() default {};
/**
* 导入路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/
*
*/
public String savePath() default "upload";
/**
* 导出类型 0是常规, 1 是文本 2 是图片,3是函数,4是数字 默认是文本
*/
public int type() default 1;
/**
* 导出时在excel中每个列的宽 单位为字符,一个汉字=2个字符 如 以列名列内容中较合适的长度 例如姓名列6 【姓名一般三个字】
* 性别列4【男女占1,但是列标题两个汉字】 限制1-255
*/
public double width() default 10;
/**
* 是否自动统计数据,如果是统计,true的话在最后追加一行统计,把所有数据都和 这个处理会吞没异常,请注意这一点
*
* @return
*/
public boolean isStatistics() default false;
/**
* 方法描述: 数据字典表
* 作 者: yiming.zhang
* 日 期: 2014年5月11日-下午5:26:40
* @return
* 返回类型: String
*/
public String dictTable() default "";
/**
* 方法描述: 数据code
* 作 者: yiming.zhang
* 日 期: 2014年5月13日-下午9:37:16
* @return
* 返回类型: String
*/
public String dicCode() default "";
/**
* 方法描述: 数据Text
* 作 者: yiming.zhang
* 日 期: 2014年5月11日-下午5:29:05
* @return
* 返回类型: String
*/
public String dicText() default "";
/**
* 导入数据是否需要转化
* 若是为true,则需要在pojo中加入 方法:convertset字段名(String text)
* @return
*/
public boolean importConvert() default false;
/**
* 导出数据是否需要转化
* 若是为true,则需要在pojo中加入方法:convertget字段名()
* @return
*/
public boolean exportConvert() default false;
/**
* 值的替换是否支持替换多个(默认true,若数据库值本来就包含逗号则需要配置该值为false)
* @author taoYan
* @since 2018年8月1日
*/
public boolean multiReplace() default true;
/**
* 父表头
* @return
*/
String groupName() default "";
/**
* 数字格式化,参数是Pattern,使用的对象是DecimalFormat
* @return
*/
String numFormat() default "";
/**
* 是否需要隐藏该列
* @return
*/
public boolean isColumnHidden() default false;
/**
* 固定的某一列,解决不好解析的问题
* @return
*/
public int fixedIndex() default -1;
/**
* 这个是不是超链接,如果是需要实现接口返回对象
* @return
*/
public boolean isHyperlink() default false;
//update-begin-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
/**
* 是否为动态列
*/
public boolean dynamic() default false;
/**
* 动态列标题字段名,默认 name
*/
public String dynamicField() default "name";
/**
* 动态列表格值字段名,默认 value
*/
public String dynamicVal() default "value";
/**
* 是否保留原始字段列,默认不保留
*/
public boolean dynamicKeepSelf() default false;
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelCollection.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
/**
* 导出的集合
*
* @author JEECG 2013年8月24日
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelCollection {
/**
* 定义excel导出ID 来限定导出字段,处理一个类对应多个不同名称的情况
*/
public String id() default "";
/**
* 导出时,对应数据库的字段 主要是用户区分每个字段, 不能有annocation重名的 导出时的列名
* 导出排序跟定义了annotation的字段的顺序有关 可以使用a_id,b_id来确实是否使用
*/
public String name();
/**
* 展示到第几个同样可以使用a_id,b_id
*
*/
public String orderNum() default "0";
/**
* 创建时创建的类型 默认值是 arrayList
*/
public Class> type() default ArrayList.class;
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记是不是导出excel 标记为实体类
*
* @author JEECG
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelEntity {
/**
* 定义excel导出ID 来限定导出字段,处理一个类对应多个不同名称的情况
*/
public String id() default "";
/**
* 导出时,对应数据库的字段 主要是用户区分每个字段, 不能有annocation重名的 导出时的列名
* 导出排序跟定义了annotation的字段的顺序有关 可以使用a_id,b_id来确实是否使用
*/
public String name() default "";
/**
* 导出时,是否展示name对应的文本
* @return
*/
boolean show() default false;
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelIgnore.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记为excel 创建实体忽略,放置死循环的造成
*
* @author JEECG
* @date 2013-9-24
* @version 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelIgnore {
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelTarget.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* excel 导出是用于标记id的
*
* @author JEECG
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface ExcelTarget {
/**
* 定义excel导出ID 来限定导出字段
*/
public String value();
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelVerify.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel 导入校验
*
* @author JEECG
* @date 2014年6月23日 下午10:46:26
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelVerify {
/**
* 接口校验
*
* @return
*/
public boolean interHandler() default false;
/**
* 是电子邮件
*
* @return
*/
public boolean isEmail() default false;
/**
* 是13位移动电话
*
* @return
*/
public boolean isMobile() default false;
/**
* 是座机号码
*
* @return
*/
public boolean isTel() default false;
/**
* 最大长度
*
* @return
*/
public int maxLength() default -1;
/**
* 最小长度
*
* @return
*/
public int minLength() default -1;
/**
* 不允许空
*
* @return
*/
public boolean notNull() default false;
/**
* 正在表达式
*
* @return
*/
public String regex() default "";
/**
* 正在表达式,错误提示信息
*
* @return
*/
public String regexTip() default "数据不符合规范";
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExcelBaseParams.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity;
import org.jeecgframework.poi.handler.inter.IExcelDataHandler;
/**
* 基础参数
*
* @author JEECG
* @date 2014年6月20日 下午1:56:52
*/
public class ExcelBaseParams {
/**
* 数据处理接口,以此为主,replace,format都在这后面
*/
private IExcelDataHandler dataHanlder;
public IExcelDataHandler getDataHanlder() {
return dataHanlder;
}
public void setDataHanlder(IExcelDataHandler dataHanlder) {
this.dataHanlder = dataHanlder;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExportParams.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerDefaultImpl;
/**
* Excel 导出参数
*
* @author JEECG
* @version 1.0 2013年8月24日
*/
public class ExportParams extends ExcelBaseParams {
/**
* 表格名称
*/
private String title;
/**
* 表格名称
*/
private short titleHeight = 10;
/**
* 第二行名称
*/
private String secondTitle;
/**
* 表格名称
*/
private short secondTitleHeight = 8;
/**
* sheetName
*/
private String sheetName;
/**
* 过滤的属性
*/
private String[] exclusions;
/**
* 是否添加需要需要
*/
private boolean addIndex;
/**
* 是否添加需要需要
*/
private String indexName = "序号";
/**
* 冰冻列
*/
private int freezeCol;
/**
* 表头颜色
*/
private short color = IndexedColors.WHITE.index;
/**
* 属性说明行的颜色 例如:HSSFColor.SKY_BLUE.index 默认
*/
private short headerColor = IndexedColors.SKY_BLUE.index;
/**
* Excel 导出版本
*/
private ExcelType type = ExcelType.HSSF;
/**
* Excel 导出style
*/
private Class> style = ExcelExportStylerDefaultImpl.class;
/**
* 是否创建表头
*/
private boolean isCreateHeadRows = true;
/**
* 本地文件存储根路径 base path
*/
private String imageBasePath;
//update-begin---author:liusq Date:20220104 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
/**
* 是否固定表头
*/
private boolean isFixedTitle = true;
/**
* 单sheet最大值
* 03版本默认6W行,07默认100W
*/
private int maxNum = 0;
/**
* 导出时在excel中每个列的高度 单位为字符,一个汉字=2个字符
* 全局设置,优先使用
*/
private short height = 0;
/**
* 只读
*/
private boolean readonly = false;
//update-end---author:liusq Date:20220104 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
public ExportParams() {
}
public ExportParams(String title, String sheetName) {
this.title = title;
this.sheetName = sheetName;
}
public ExportParams(String title, String sheetName, ExcelType type) {
this.title = title;
this.sheetName = sheetName;
this.type = type;
}
public ExportParams(String title, String secondTitle, String sheetName) {
this.title = title;
this.secondTitle = secondTitle;
this.sheetName = sheetName;
}
public ExportParams(String title, String secondTitle, String sheetName, ExcelType type) {
this.title = title;
this.secondTitle = secondTitle;
this.sheetName = sheetName;
this.type = type;
}
public ExportParams(String title, String secondTitle, String sheetName,String imageBasePath) {
this.title = title;
this.secondTitle = secondTitle;
this.sheetName = sheetName;
this.imageBasePath = imageBasePath;
}
public short getColor() {
return color;
}
public String[] getExclusions() {
return exclusions;
}
public short getHeaderColor() {
return headerColor;
}
public String getSecondTitle() {
return secondTitle;
}
public short getSecondTitleHeight() {
return (short) (secondTitleHeight * 50);
}
public String getSheetName() {
return sheetName;
}
public String getTitle() {
return title;
}
public short getTitleHeight() {
return (short) (titleHeight * 50);
}
public boolean isAddIndex() {
return addIndex;
}
public void setAddIndex(boolean addIndex) {
this.addIndex = addIndex;
}
public void setColor(short color) {
this.color = color;
}
public void setExclusions(String[] exclusions) {
this.exclusions = exclusions;
}
public void setHeaderColor(short headerColor) {
this.headerColor = headerColor;
}
public void setSecondTitle(String secondTitle) {
this.secondTitle = secondTitle;
}
public void setSecondTitleHeight(short secondTitleHeight) {
this.secondTitleHeight = secondTitleHeight;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public void setTitle(String title) {
this.title = title;
}
public void setTitleHeight(short titleHeight) {
this.titleHeight = titleHeight;
}
public ExcelType getType() {
return type;
}
public void setType(ExcelType type) {
this.type = type;
}
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public Class> getStyle() {
return style;
}
public void setStyle(Class> style) {
this.style = style;
}
public int getFreezeCol() {
return freezeCol;
}
public void setFreezeCol(int freezeCol) {
this.freezeCol = freezeCol;
}
public boolean isCreateHeadRows() {
return isCreateHeadRows;
}
public void setCreateHeadRows(boolean isCreateHeadRows) {
this.isCreateHeadRows = isCreateHeadRows;
}
public String getImageBasePath() {
return imageBasePath;
}
public void setImageBasePath(String imageBasePath) {
this.imageBasePath = imageBasePath;
}
public int getMaxNum() {
return maxNum;
}
public void setMaxNum(int maxNum) {
this.maxNum = maxNum;
}
public short getHeight() {
return height == -1 ? -1 : (short) (height * 50);
}
public void setHeight(short height) {
this.height = height;
}
public boolean isFixedTitle() {
return isFixedTitle;
}
public void setFixedTitle(boolean fixedTitle) {
isFixedTitle = fixedTitle;
}
public boolean isReadonly() {
return readonly;
}
public void setReadonly(boolean readonly) {
this.readonly = readonly;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ImportParams.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity;
import org.jeecgframework.poi.handler.inter.IExcelVerifyHandler;
import java.util.List;
/**
* 导入参数设置
*
* @author JEECG
* @date 2013-9-24
* @version 1.0
*/
public class ImportParams extends ExcelBaseParams {
/**
* 表格标题行数,默认0
*/
private int titleRows = 0;
/**
* 表头行数,默认1
*/
private int headRows = 1;
/**
* 字段真正值和列标题之间的距离 默认0
*/
private int startRows = 0;
/**
* 主键设置,如何这个cell没有值,就跳过 或者认为这个是list的下面的值
*/
private int keyIndex = 0;
//update-begin-author:liusq date:20220605 for:https://gitee.com/jeecg/jeecg-boot/issues/I57UPC 导入 ImportParams 中没有startSheetIndex参数
/**
* 开始读取的sheet位置,默认为0
*/
private int startSheetIndex = 0;
//update-end-author:liusq date:20220605 for:https://gitee.com/jeecg/jeecg-boot/issues/I57UPC 导入 ImportParams 中没有startSheetIndex参数
//update-begin-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错
/**
* 上传表格需要读取的sheet 数量,默认为0
*/
private int sheetNum = 0;
//update-end-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错
/**
* 是否需要保存上传的Excel,默认为false
*/
private boolean needSave = false;
/**
* 保存上传的Excel目录,默认是 如 TestEntity这个类保存路径就是
* upload/excelUpload/Test/yyyyMMddHHmss_***** 保存名称上传时间_五位随机数
*/
private String saveUrl = "upload/excelUpload";
/**
* 校验处理接口
*/
private IExcelVerifyHandler verifyHanlder;
/**
* 最后的无效行数
*/
private int lastOfInvalidRow = 0;
/**
* 不需要解析的表头 只作为多表头展示,无字段与其绑定
*/
private List ignoreHeaderList;
/**
* 指定导入的sheetName
*/
private String sheetName;
/**
* 图片列 集合
*/
private List imageList;
public int getHeadRows() {
return headRows;
}
public int getKeyIndex() {
return keyIndex;
}
public String getSaveUrl() {
return saveUrl;
}
public int getSheetNum() {
return sheetNum;
}
public int getStartRows() {
return startRows;
}
public int getTitleRows() {
return titleRows;
}
public IExcelVerifyHandler getVerifyHanlder() {
return verifyHanlder;
}
public boolean isNeedSave() {
return needSave;
}
public void setHeadRows(int headRows) {
this.headRows = headRows;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public void setNeedSave(boolean needSave) {
this.needSave = needSave;
}
public void setSaveUrl(String saveUrl) {
this.saveUrl = saveUrl;
}
public void setSheetNum(int sheetNum) {
this.sheetNum = sheetNum;
}
public void setStartRows(int startRows) {
this.startRows = startRows;
}
public void setTitleRows(int titleRows) {
this.titleRows = titleRows;
}
public void setVerifyHanlder(IExcelVerifyHandler verifyHanlder) {
this.verifyHanlder = verifyHanlder;
}
public int getLastOfInvalidRow() {
return lastOfInvalidRow;
}
public void setLastOfInvalidRow(int lastOfInvalidRow) {
this.lastOfInvalidRow = lastOfInvalidRow;
}
public List getImageList() {
return imageList;
}
public void setImageList(List imageList) {
this.imageList = imageList;
}
public List getIgnoreHeaderList() {
return ignoreHeaderList;
}
public void setIgnoreHeaderList(List ignoreHeaderList) {
this.ignoreHeaderList = ignoreHeaderList;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
/**
* 根据表头显示的文字 判断是否忽略该表头
* @param text
* @return
*/
public boolean isIgnoreHeader(String text){
if(ignoreHeaderList!=null && ignoreHeaderList.indexOf(text)>=0){
return true;
}
return false;
}
public int getStartSheetIndex() {
return startSheetIndex;
}
public void setStartSheetIndex(int startSheetIndex) {
this.startSheetIndex = startSheetIndex;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerDefaultImpl;
import java.io.IOException;
import java.io.InputStream;
/**
* 模板导出参数设置
*
* @author JEECG
* @date 2013-10-17
* @version 1.0
*/
public class TemplateExportParams extends ExcelBaseParams {
/**
* 输出全部的sheet
*/
private boolean scanAllsheet = false;
/**
* 模板的路径
*/
private String templateUrl;
/**
* 模板
*/
private Workbook templateWb;
/**
* 需要导出的第几个 sheetNum,默认是第0个
*/
private Integer[] sheetNum = new Integer[] { 0 };
/**
* 这只sheetName 不填就使用原来的
*/
private String[] sheetName;
/**
* 表格列标题行数,默认1
*/
private int headingRows = 1;
/**
* 表格列标题开始行,默认1
*/
private int headingStartRow = 1;
/**
* 设置数据源的NUM
*/
private int dataSheetNum = 0;
/**
* Excel 导出style
*/
private Class> style = ExcelExportStylerDefaultImpl.class;
/**
* FOR EACH 用到的局部变量
*/
private String tempParams = "t";
//列循环支持
private boolean colForEach = false;
/**
* 默认构造器
*/
public TemplateExportParams() {
}
/**
* 构造器
*
* @param templateUrl
* 模板路径
* @param scanAllsheet
* 是否输出全部的sheet
* @param sheetName
* sheet的名称,可不填
*/
public TemplateExportParams(String templateUrl, boolean scanAllsheet, String... sheetName) {
this.templateUrl = templateUrl;
this.scanAllsheet = scanAllsheet;
if (sheetName != null && sheetName.length > 0) {
this.sheetName = sheetName;
}
}
/**
* 构造器
*
* @param templateUrl
* 模板路径
* @param sheetNum
* sheet 的位置,可不填
*/
public TemplateExportParams(String templateUrl, Integer... sheetNum) {
this.templateUrl = templateUrl;
if (sheetNum != null && sheetNum.length > 0) {
this.sheetNum = sheetNum;
}
}
/**
* 单个sheet输出构造器
*
* @param templateUrl
* 模板路径
* @param sheetName
* sheet的名称
* @param sheetNum
* sheet的位置,可不填
*/
public TemplateExportParams(String templateUrl, String sheetName, Integer... sheetNum) {
this.templateUrl = templateUrl;
this.sheetName = new String[] { sheetName };
if (sheetNum != null && sheetNum.length > 0) {
this.sheetNum = sheetNum;
}
}
//update-begin-author:liusq---date:2024-09-03--for: [issues/7048]TemplateExportParams类建议增加传入模板文件InputStream的方式
/**
* 构造器
* @param inputStream 输入流
* @param scanAllsheet 是否输出全部的sheet
* @param sheetName sheet的名称,可不填
*/
public TemplateExportParams(InputStream inputStream, boolean scanAllsheet, String... sheetName) throws IOException {
this.templateWb = WorkbookFactory.create(inputStream);
this.scanAllsheet = scanAllsheet;
if (sheetName != null && sheetName.length > 0) {
this.sheetName = sheetName;
}
}
/**
* 构造器
* @param inputStream 输入流
* @param sheetNum sheet 的位置,可不填
*/
public TemplateExportParams(InputStream inputStream, Integer... sheetNum) throws IOException {
this.templateWb = WorkbookFactory.create(inputStream);
if (sheetNum != null && sheetNum.length > 0) {
this.sheetNum = sheetNum;
}
}
/**
* 单个sheet输出构造器
* @param inputStream 输入流
* @param sheetName sheet的名称
* @param sheetNum sheet的位置,可不填
*/
public TemplateExportParams(InputStream inputStream, String sheetName, Integer... sheetNum) throws IOException {
this.templateWb = WorkbookFactory.create(inputStream);
this.sheetName = new String[] { sheetName };
if (sheetNum != null && sheetNum.length > 0) {
this.sheetNum = sheetNum;
}
}
//update-end-author:liusq---date:2024-09-03--for: [issues/7048]TemplateExportParams类建议增加传入模板文件InputStream的方式
public int getHeadingRows() {
return headingRows;
}
public int getHeadingStartRow() {
return headingStartRow;
}
public String[] getSheetName() {
return sheetName;
}
public Integer[] getSheetNum() {
return sheetNum;
}
public String getTemplateUrl() {
return templateUrl;
}
public void setHeadingRows(int headingRows) {
this.headingRows = headingRows;
}
public void setHeadingStartRow(int headingStartRow) {
this.headingStartRow = headingStartRow;
}
public void setSheetName(String[] sheetName) {
this.sheetName = sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = new String[] { sheetName };
}
public void setSheetNum(Integer[] sheetNum) {
this.sheetNum = sheetNum;
}
public void setSheetNum(Integer sheetNum) {
this.sheetNum = new Integer[] { sheetNum };
}
public void setTemplateUrl(String templateUrl) {
this.templateUrl = templateUrl;
}
public Class> getStyle() {
return style;
}
public void setStyle(Class> style) {
this.style = style;
}
public int getDataSheetNum() {
return dataSheetNum;
}
public void setDataSheetNum(int dataSheetNum) {
this.dataSheetNum = dataSheetNum;
}
public boolean isScanAllsheet() {
return scanAllsheet;
}
public void setScanAllsheet(boolean scanAllsheet) {
this.scanAllsheet = scanAllsheet;
}
public String getTempParams() {
return tempParams;
}
public void setTempParams(String tempParams) {
this.tempParams = tempParams;
}
public boolean isColForEach() {
return colForEach;
}
public void setColForEach(boolean colForEach) {
this.colForEach = colForEach;
}
public Workbook getTemplateWb() {
return templateWb;
}
public void setTemplateWb(Workbook templateWb) {
this.templateWb = templateWb;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/CellValueType.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.enmus;
/**
* Cell 值得类型
*
* @author JEECG
* @date 2014年12月29日 下午10:20:49
*/
public enum CellValueType {
String, Number, Boolean, Date, TElement, Null, None;
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelStyleType.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.enmus;
import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerBorderImpl;
import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerColorImpl;
import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerDefaultImpl;
/**
* 插件提供的几个默认样式
*
* @author JEECG
* @date 2015年1月9日 下午9:02:24
*/
public enum ExcelStyleType {
NONE("默认样式", ExcelExportStylerDefaultImpl.class), BORDER("边框样式", ExcelExportStylerBorderImpl.class), COLOR("间隔行样式", ExcelExportStylerColorImpl.class);
private String name;
private Class> clazz;
ExcelStyleType(String name, Class> clazz) {
this.name = name;
this.clazz = clazz;
}
public Class> getClazz() {
return clazz;
}
public String getName() {
return name;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelType.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.enmus;
/**
* Excel 文件格式类型枚举
* 用于指定导出/导入的 Excel 文件格式版本
*
* @author JEECG
* @date 2014年12月29日 下午9:08:21
*/
public enum ExcelType {
/**
* HSSF 格式 - Excel 97-2003 版本 (.xls)
*
* 文件扩展名:.xls
* 最大行数:65,536 行(2^16)
* 最大列数:256 列(2^8)
* 适用场景:兼容老版本 Excel,数据量较小的场景
* 对应 POI 类:HSSFWorkbook
*
*/
HSSF,
/**
* XSSF 格式 - Excel 2007+ 版本 (.xlsx)
*
* 文件扩展名:.xlsx
* 最大行数:1,048,576 行(2^20)
* 最大列数:16,384 列(2^14)
* 适用场景:现代 Excel 版本,大数据量导出,推荐使用
* 对应 POI 类:XSSFWorkbook
* 优势:支持更大数据量,文件压缩比更高,功能更丰富
*
* 注意: 导出时请确保文件扩展名与格式类型匹配,避免文件损坏
*/
XSSF;
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelBaseEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.params;
import java.lang.reflect.Method;
import java.util.List;
/**
* Excel 导入导出基础对象类
*
* @author JEECG
* @date 2014年6月20日 下午2:26:09
*/
public class ExcelBaseEntity {
/**
* 对应name
*/
protected String name;
/**
* 对应type
*/
private int type = 1;
/**
* 数据库格式
*/
private String databaseFormat;
/**
* 导出日期格式
*/
private String format;
/**
* 数字格式化,参数是Pattern,使用的对象是DecimalFormat
*/
private String numFormat;
/**
* 替换值表达式 :"男_1","女_0"
*/
private String[] replace;
/**
* 替换是否是替换多个值
*/
private boolean multiReplace;
/**
* 表头组名称
*/
private String groupName;
/**
* set/get方法
*/
private Method method;
/**
* 固定的列
*/
private Integer fixedIndex;
/**
* 字典名称
*/
private String dict;
/**
* 这个是不是超链接,如果是需要实现接口返回对象
*/
private boolean hyperlink;
private List methods;
public String getDatabaseFormat() {
return databaseFormat;
}
public String getFormat() {
return format;
}
public Method getMethod() {
return method;
}
public List getMethods() {
return methods;
}
public String getName() {
return name;
}
public String[] getReplace() {
return replace;
}
public int getType() {
return type;
}
public void setDatabaseFormat(String databaseFormat) {
this.databaseFormat = databaseFormat;
}
public void setFormat(String format) {
this.format = format;
}
public void setMethod(Method method) {
this.method = method;
}
public void setMethods(List methods) {
this.methods = methods;
}
public void setName(String name) {
this.name = name;
}
public void setReplace(String[] replace) {
this.replace = replace;
}
public void setType(int type) {
this.type = type;
}
public boolean isMultiReplace() {
return multiReplace;
}
public void setMultiReplace(boolean multiReplace) {
this.multiReplace = multiReplace;
}
public String getNumFormat() {
return numFormat;
}
public void setNumFormat(String numFormat) {
this.numFormat = numFormat;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public Integer getFixedIndex() {
return fixedIndex;
}
public void setFixedIndex(Integer fixedIndex) {
this.fixedIndex = fixedIndex;
}
public String getDict() {
return dict;
}
public void setDict(String dict) {
this.dict = dict;
}
public boolean isHyperlink() {
return hyperlink;
}
public void setHyperlink(boolean hyperlink) {
this.hyperlink = hyperlink;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelCollectionParams.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.params;
import java.util.Map;
/**
* Excel 对于的 Collection
*
* @author JEECG
* @date 2013-9-26
* @version 1.0
*/
public class ExcelCollectionParams {
/**
* 集合对应的名称
*/
private String name;
/**
* Excel 列名称
*/
private String excelName;
/**
* 实体对象
*/
private Class> type;
/**
* 这个list下面的参数集合实体对象
*/
private Map excelParams;
public Map getExcelParams() {
return excelParams;
}
public String getName() {
return name;
}
public Class> getType() {
return type;
}
public void setExcelParams(Map excelParams) {
this.excelParams = excelParams;
}
public void setName(String name) {
this.name = name;
}
public void setType(Class> type) {
this.type = type;
}
public String getExcelName() {
return excelName;
}
public void setExcelName(String excelName) {
this.excelName = excelName;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelExportEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.params;
import java.util.ArrayList;
import java.util.List;
/**
* excel 导出工具类,对cell类型做映射
*
* @author JEECG
* @version 1.0 2013年8月24日
*/
public class ExcelExportEntity extends ExcelBaseEntity implements Comparable {
/**
* 如果是MAP导出,这个是map的key
*/
private Object key;
private double width = 10;
private double height = 10;
/**
* 图片的类型,1是文件地址(class目录),2是数据库字节,3是文件地址(磁盘目录),4网络图片
*/
private int exportImageType = 3;
/**
* 图片储存位置(磁盘目录) 用于导出获取图片绝对路径
*/
private String imageBasePath;
/**
* 排序顺序
*/
private int orderNum = 0;
/**
* 是否支持换行
*/
private boolean isWrap;
/**
* 是否需要合并
*/
private boolean needMerge;
/**
* 单元格纵向合并
*/
private boolean mergeVertical;
/**
* 合并依赖
*/
private int[] mergeRely;
/**
* 后缀
*/
private String suffix;
/**
* 统计
*/
private boolean isStatistics;
/**
* 是否横向合并
*/
private boolean colspan;
/**
* 被横向合并的列名称
*/
private List subColumnList;
/**
* 父表头的名称
*/
private String groupName;
/**
* 是否隐藏列
*/
private boolean isColumnHidden;
//update-begin-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
/**
* 是否为动态列
*/
private boolean dynamic;
/**
* 动态列标题字段
*/
private String dynamicField;
/**
* 动态列值字段
*/
private String dynamicValue;
/**
* 是否保留原始列
*/
private boolean dynamicKeepSelf;
/**
* 当前动态列对应的标题名称
*/
private String dynamicColumnName;
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
private List list;
public ExcelExportEntity() {
}
public ExcelExportEntity(String name) {
super.name = name;
}
public ExcelExportEntity(String name, Object key) {
super.name = name;
this.key = key;
}
/**
* 构造器
* @param name 描述-文字
* @param key 存储key 如果是MAP导出,这个是map的key
* @param colspan 是否为合并列(a,b列公用一个表头c,则a,b,c都需要设置为true)
*/
public ExcelExportEntity(String name, Object key, boolean colspan) {
super.name = name;
this.key = key;
this.colspan = colspan;
this.needMerge = colspan;
}
public ExcelExportEntity(String name, Object key, int width) {
super.name = name;
this.width = width;
this.key = key;
}
public int getExportImageType() {
return exportImageType;
}
public double getHeight() {
return height;
}
public Object getKey() {
return key;
}
public List getList() {
return list;
}
public int[] getMergeRely() {
return mergeRely == null ? new int[0] : mergeRely;
}
public int getOrderNum() {
return orderNum;
}
public double getWidth() {
return width;
}
public boolean isMergeVertical() {
return mergeVertical;
}
public boolean isNeedMerge() {
return needMerge;
}
public boolean isWrap() {
return isWrap;
}
public void setExportImageType(int exportImageType) {
this.exportImageType = exportImageType;
}
public void setHeight(double height) {
this.height = height;
}
public void setKey(Object key) {
this.key = key;
}
public void setList(List list) {
this.list = list;
}
public void setMergeRely(int[] mergeRely) {
this.mergeRely = mergeRely;
}
public void setMergeVertical(boolean mergeVertical) {
this.mergeVertical = mergeVertical;
}
public void setNeedMerge(boolean needMerge) {
this.needMerge = needMerge;
}
public void setOrderNum(int orderNum) {
this.orderNum = orderNum;
}
public void setWidth(double width) {
this.width = width;
}
public void setWrap(boolean isWrap) {
this.isWrap = isWrap;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public boolean isStatistics() {
return isStatistics;
}
public void setStatistics(boolean isStatistics) {
this.isStatistics = isStatistics;
}
public String getImageBasePath() {
return imageBasePath;
}
public void setImageBasePath(String imageBasePath) {
this.imageBasePath = imageBasePath;
}
public boolean isColspan() {
return colspan;
}
public void setColspan(boolean colspan) {
this.colspan = colspan;
}
public List getSubColumnList() {
return subColumnList;
}
public void setSubColumnList(List subColumnList) {
this.subColumnList = subColumnList;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public boolean isColumnHidden() {
return isColumnHidden;
}
public void setColumnHidden(boolean columnHidden) {
isColumnHidden = columnHidden;
}
/**
* 是否为合并子列
* @return
*/
public boolean isSubColumn(){
return this.colspan && (this.subColumnList==null || this.subColumnList.size()==0);
}
/**
* 是否为合并父列
* @return
*/
public boolean isMergeColumn(){
return this.colspan && this.subColumnList!=null && this.subColumnList.size()>0;
}
public boolean isDynamic() {
return dynamic;
}
public void setDynamic(boolean dynamic) {
this.dynamic = dynamic;
}
public String getDynamicField() {
return dynamicField;
}
public void setDynamicField(String dynamicField) {
this.dynamicField = dynamicField;
}
public String getDynamicValue() {
return dynamicValue;
}
public void setDynamicValue(String dynamicValue) {
this.dynamicValue = dynamicValue;
}
public boolean isDynamicKeepSelf() {
return dynamicKeepSelf;
}
public void setDynamicKeepSelf(boolean dynamicKeepSelf) {
this.dynamicKeepSelf = dynamicKeepSelf;
}
public String getDynamicColumnName() {
return dynamicColumnName;
}
public void setDynamicColumnName(String dynamicColumnName) {
this.dynamicColumnName = dynamicColumnName;
}
/**
* 获取被合并的子列
* @param all
* @return
*/
public List initSubExportEntity(List all){
List sub = new ArrayList();
for (ExcelExportEntity temp : all) {
if(this.subColumnList.contains(temp.getKey())){
sub.add(temp);
}
}
this.setList(sub);
return sub;
}
@Override
public int compareTo(ExcelExportEntity prev) {
return this.getOrderNum() - prev.getOrderNum();
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java
================================================
package org.jeecgframework.poi.excel.entity.params;
import java.io.Serializable;
import java.util.Stack;
import org.apache.poi.ss.usermodel.CellStyle;
/**
* 模板for each是的参数
* @author JueYue
* @date 2015年4月29日 下午9:22:48
*/
public class ExcelForEachParams implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* key
*/
private String name;
/**
* key
*/
private Stack tempName;
/**
* 模板的cellStyle
*/
private CellStyle cellStyle;
/**
* 行高
*/
private short height;
/**
* 常量值
*/
private String constValue;
/**
* 列合并
*/
private int colspan = 1;
/**
* 行合并
*/
private int rowspan = 1;
/**
* 行合并
*/
private boolean collectCell;
public ExcelForEachParams() {
}
public ExcelForEachParams(String name, CellStyle cellStyle, short height) {
this.name = name;
this.cellStyle = cellStyle;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CellStyle getCellStyle() {
return cellStyle;
}
public void setCellStyle(CellStyle cellStyle) {
this.cellStyle = cellStyle;
}
public short getHeight() {
return height;
}
public void setHeight(short height) {
this.height = height;
}
public String getConstValue() {
return constValue;
}
public void setConstValue(String constValue) {
this.constValue = constValue;
}
public int getColspan() {
return colspan;
}
public void setColspan(int colspan) {
this.colspan = colspan;
}
public int getRowspan() {
return rowspan;
}
public void setRowspan(int rowspan) {
this.rowspan = rowspan;
}
public boolean isCollectCell() {
return collectCell;
}
public void setCollectCell(boolean collectCell) {
this.collectCell = collectCell;
}
public Stack getTempName() {
return tempName;
}
public void setTempName(Stack tempName) {
this.tempName = tempName;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelImportEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.params;
import java.util.List;
/**
* excel 导入工具类,对cell类型做映射
*
* @author JEECG
* @version 1.0 2013年8月24日
*/
public class ExcelImportEntity extends ExcelBaseEntity {
/**
* 对应 Collection NAME
*/
private String collectionName;
/**
* 保存图片的地址 当saveType设置为3/4时,此值可以设置为:local,minio,alioss
*/
private String saveUrl;
/**
* 保存图片的类型,1是文件_old,2是数据库字节,3文件地址_new,4网络地址
*/
private int saveType;
/**
* 对应exportType
*/
private String classType;
/**
* 校驗參數
*/
private ExcelVerifyEntity verify;
/**
* 后缀
*/
private String suffix;
private List list;
public String getClassType() {
return classType;
}
public String getCollectionName() {
return collectionName;
}
public List getList() {
return list;
}
public int getSaveType() {
return saveType;
}
public String getSaveUrl() {
return saveUrl;
}
public ExcelVerifyEntity getVerify() {
return verify;
}
public void setClassType(String classType) {
this.classType = classType;
}
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
public void setList(List list) {
this.list = list;
}
public void setSaveType(int saveType) {
this.saveType = saveType;
}
public void setSaveUrl(String saveUrl) {
this.saveUrl = saveUrl;
}
public void setVerify(ExcelVerifyEntity verify) {
this.verify = verify;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java
================================================
package org.jeecgframework.poi.excel.entity.params;
import java.io.Serializable;
import org.apache.poi.ss.usermodel.CellStyle;
/**
* 模板便利是的参数
*
* @author JEECG
* @date 2015年4月29日 下午9:22:48
*/
public class ExcelTemplateParams implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* key
*/
private String name;
/**
* 模板的cellStyle
*/
private CellStyle cellStyle;
/**
* 行高
*/
private short height;
public ExcelTemplateParams() {
}
public ExcelTemplateParams(String name, CellStyle cellStyle, short height) {
this.name = name;
this.cellStyle = cellStyle;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CellStyle getCellStyle() {
return cellStyle;
}
public void setCellStyle(CellStyle cellStyle) {
this.cellStyle = cellStyle;
}
public short getHeight() {
return height;
}
public void setHeight(short height) {
this.height = height;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelVerifyEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.params;
/**
* Excel 校验对象
*
* @author JEECG
* @date 2014年6月29日 下午4:24:59
*/
public class ExcelVerifyEntity {
/**
* 接口校验
*
* @return
*/
private boolean interHandler;
/**
* 不允许空
*
* @return
*/
private boolean notNull;
/**
* 是13位移动电话
*
* @return
*/
private boolean isMobile;
/**
* 是座机号码
*
* @return
*/
private boolean isTel;
/**
* 是电子邮件
*
* @return
*/
private boolean isEmail;
/**
* 最小长度
*
* @return
*/
private int minLength;
/**
* 最大长度
*
* @return
*/
private int maxLength;
/**
* 正在表达式
*
* @return
*/
private String regex;
/**
* 正在表达式,错误提示信息
*
* @return
*/
private String regexTip;
public int getMaxLength() {
return maxLength;
}
public int getMinLength() {
return minLength;
}
public String getRegex() {
return regex;
}
public String getRegexTip() {
return regexTip;
}
public boolean isEmail() {
return isEmail;
}
public boolean isInterHandler() {
return interHandler;
}
public boolean isMobile() {
return isMobile;
}
public boolean isNotNull() {
return notNull;
}
public boolean isTel() {
return isTel;
}
public void setEmail(boolean isEmail) {
this.isEmail = isEmail;
}
public void setInterHandler(boolean interHandler) {
this.interHandler = interHandler;
}
public void setMaxLength(int maxLength) {
this.maxLength = maxLength;
}
public void setMinLength(int minLength) {
this.minLength = minLength;
}
public void setMobile(boolean isMobile) {
this.isMobile = isMobile;
}
public void setNotNull(boolean notNull) {
this.notNull = notNull;
}
public void setRegex(String regex) {
this.regex = regex;
}
public void setRegexTip(String regexTip) {
this.regexTip = regexTip;
}
public void setTel(boolean isTel) {
this.isTel = isTel;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/MergeEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.params;
import java.util.List;
/**
* 合并单元格使用对象
*
* Created by jue on 14-6-11.
*/
public class MergeEntity {
/**
* 合并开始行
*/
private int startRow;
/**
* 合并结束行
*/
private int endRow;
/**
* 文字
*/
private String text;
/**
* 依赖关系文本
*/
private List relyList;
public MergeEntity() {
}
public MergeEntity(String text, int startRow, int endRow) {
this.text = text;
this.endRow = endRow;
this.startRow = startRow;
}
public int getEndRow() {
return endRow;
}
public List getRelyList() {
return relyList;
}
public int getStartRow() {
return startRow;
}
public String getText() {
return text;
}
public void setEndRow(int endRow) {
this.endRow = endRow;
}
public void setRelyList(List relyList) {
this.relyList = relyList;
}
public void setStartRow(int startRow) {
this.startRow = startRow;
}
public void setText(String text) {
this.text = text;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelImportResult.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.result;
import java.util.List;
import org.apache.poi.ss.usermodel.Workbook;
/**
* 导入返回类
*
* @author JEECG
* @date 2014年6月29日 下午5:12:10
*/
public class ExcelImportResult {
/**
* 结果集
*/
private List list;
/**
* 是否存在校验失败
*/
private boolean verfiyFail;
/**
* 数据源
*/
private Workbook workbook;
public ExcelImportResult() {
}
public ExcelImportResult(List list, boolean verfiyFail, Workbook workbook) {
this.list = list;
this.verfiyFail = verfiyFail;
this.workbook = workbook;
}
public List getList() {
return list;
}
public Workbook getWorkbook() {
return workbook;
}
public boolean isVerfiyFail() {
return verfiyFail;
}
public void setList(List list) {
this.list = list;
}
public void setVerfiyFail(boolean verfiyFail) {
this.verfiyFail = verfiyFail;
}
public void setWorkbook(Workbook workbook) {
this.workbook = workbook;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelVerifyHanlderResult.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.result;
/**
* Excel导入处理返回结果
*
* @author JEECG
* @date 2014年6月23日 下午11:03:29
*/
public class ExcelVerifyHanlderResult {
/**
* 是否正确
*/
private boolean success;
/**
* 错误信息
*/
private String msg;
public ExcelVerifyHanlderResult() {
}
public ExcelVerifyHanlderResult(boolean success) {
this.success = success;
}
public ExcelVerifyHanlderResult(boolean success, String msg) {
this.success = success;
this.msg = msg;
}
public String getMsg() {
return msg;
}
public boolean isSuccess() {
return success;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setSuccess(boolean success) {
this.success = success;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/sax/SaxReadCellEntity.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.sax;
import org.jeecgframework.poi.excel.entity.enmus.CellValueType;
/**
* Cell 对象
*
* @author JEECG
* @date 2014年12月29日 下午10:12:57
*/
public class SaxReadCellEntity {
/**
* 值类型
*/
private CellValueType cellType;
/**
* 值
*/
private Object value;
public SaxReadCellEntity(CellValueType cellType, Object value) {
this.cellType = cellType;
this.value = value;
}
public CellValueType getCellType() {
return cellType;
}
public void setCellType(CellValueType cellType) {
this.cellType = cellType;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
@Override
public String toString() {
return "[type=" + cellType.toString() + ",value=" + value + "]";
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/entity/vo/PoiBaseConstants.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.entity.vo;
/**
* 基础常量 Created by jue on 14-4-21.
*/
public interface PoiBaseConstants {
/**
* 字段属性对应方法
*/
public static String GET = "get";
/**
* 字段属性对应方法
*/
public static String SET = "set";
/**
* 字段属性对应方法
*/
public static String IS = "is";
/**
* 是否增加属性列
*/
public static String IS_ADD_INDEX = "isAddIndex";
/**
* 字段属性对应convert方法
*/
public static String CONVERT = "convert";
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelBatchExportServer.java
================================================
package org.jeecgframework.poi.excel.export;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.entity.vo.PoiBaseConstants;
import org.jeecgframework.poi.excel.export.styler.IExcelExportStyler;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
import org.jeecgframework.poi.handler.inter.IExcelExportServer;
import org.jeecgframework.poi.handler.inter.IExcelExportServerEnhanced;
import org.jeecgframework.poi.handler.inter.IWriter;
import org.jeecgframework.poi.util.PoiExcelGraphDataUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.*;
import static org.jeecgframework.poi.excel.ExcelExportUtil.USE_SXSSF_LIMIT;
/**
* 提供批次插入服务
* @author liusq
* @date 2022年1月4日
*/
public class ExcelBatchExportServer extends ExcelExportServer implements IWriter {
private final static Logger LOGGER = LoggerFactory.getLogger(ExcelBatchExportServer.class);
private Workbook workbook;
private Sheet sheet;
private List excelParams;
private ExportParams entity;
private int titleHeight;
private Drawing patriarch;
private short rowHeight;
private int index;
public void init(ExportParams entity, Class> pojoClass) {
List excelParams = createExcelExportEntityList(entity, pojoClass);
init(entity, excelParams);
}
/**
* 初始化数据
* @param entity 导出参数
* @param excelParams
*/
public void init(ExportParams entity, List excelParams) {
LOGGER.debug("ExcelBatchExportServer only support SXSSFWorkbook");
entity.setType(ExcelType.XSSF);
workbook = new SXSSFWorkbook();
this.entity = entity;
this.excelParams = excelParams;
super.type = entity.getType();
createSheet(workbook, entity, excelParams);
if (entity.getMaxNum() == 0) {
entity.setMaxNum(USE_SXSSF_LIMIT);
}
insertDataToSheet(workbook, entity, excelParams, null, sheet);
}
public List createExcelExportEntityList(ExportParams entity, Class> pojoClass) {
try {
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
// 得到所有字段
Field[] fileds = PoiPublicUtil.getClassFields(pojoClass);
ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
String targetId = etarget == null ? null : etarget.value();
getAllExcelField(entity.getExclusions(), targetId, fileds, excelParams, pojoClass,
null);
sortAllParams(excelParams);
return excelParams;
} catch (Exception e) {
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
public void createSheet(Workbook workbook, ExportParams entity, List excelParams) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Excel export start ,List is {}", excelParams);
LOGGER.debug("Excel version is {}",
entity.getType().equals(ExcelType.HSSF) ? "03" : "07");
}
if (workbook == null || entity == null || excelParams == null) {
throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
}
try {
try {
sheet = workbook.createSheet(entity.getSheetName());
} catch (Exception e) {
// 重复遍历,出现了重名现象,创建非指定的名称Sheet
sheet = workbook.createSheet();
}
} catch (Exception e) {
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
@Override
protected void insertDataToSheet(Workbook workbook, ExportParams entity,
List entityList, Collection extends Map, ?>> dataSet,
Sheet sheet) {
try {
dataHanlder = entity.getDataHanlder();
if (dataHanlder != null && dataHanlder.getNeedHandlerFields() != null) {
needHanlderList = Arrays.asList(dataHanlder.getNeedHandlerFields());
}
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) entity.getStyle()
.getConstructor(Workbook.class).newInstance(workbook));
patriarch = PoiExcelGraphDataUtil.getDrawingPatriarch(sheet);
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
excelParams.addAll(entityList);
sortAllParams(excelParams);
this.index = entity.isCreateHeadRows()
? createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
titleHeight = index;
setCellWith(excelParams, sheet);
setColumnHidden(excelParams, sheet);
rowHeight = getRowHeight(excelParams);
setCurrentIndex(1);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e.getCause());
}
}
public Workbook exportBigExcel(IExcelExportServer server, Object queryParams) {
int page = 1;
List list = server
.selectListForExcelExport(queryParams, page++);
while (list != null && list.size() > 0) {
write(list);
list = server.selectListForExcelExport(queryParams, page++);
}
return close();
}
/**
* 大数据导出 - 游标分页方式
* 推荐用于大数据量(20万+)导出,避免深分页性能问题
* for [QQYUN-13964]演示系统数据量大,点击没反应
*
* 实现原理:
* 1. 使用上一批次的最后一条记录作为查询起点
* 2. 避免 LIMIT offset, size 造成的性能衰减
* 3. 查询速度恒定,不会随着数据量增加而变慢
*
* @param server 增强的查询服务
* @param queryParams 查询参数
* @return Workbook
*/
public Workbook exportBigExcelEnhanced(IExcelExportServerEnhanced server, Object queryParams) {
int pageSize = server.getPageSize();
T lastRecord = null;
int totalCount = 0;
List list = server.selectListForExcelExport(queryParams, lastRecord, pageSize);
while (list != null && list.size() > 0) {
write(list);
totalCount += list.size();
// 记录最后一条记录,用于下次查询
lastRecord = list.get(list.size() - 1);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("已导出 {} 条数据", totalCount);
}
// 如果返回的数据少于pageSize,说明已经是最后一批了
if (list.size() < pageSize) {
break;
}
list = server.selectListForExcelExport(queryParams, lastRecord, pageSize);
}
LOGGER.info("大数据导出完成,共导出 {} 条数据", totalCount);
return close();
}
@Override
public Workbook get() {
return this.workbook;
}
@Override
public IWriter write(Collection data) {
if (sheet.getLastRowNum() + data.size() > entity.getMaxNum()) {
sheet = workbook.createSheet();
index = 0;
}
Iterator> its = data.iterator();
while (its.hasNext()) {
Object t = its.next();
try {
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight, 0)[0];
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
return this;
}
@Override
public Workbook close() {
if (entity.getFreezeCol() != 0) {
sheet.createFreezePane(entity.getFreezeCol(), titleHeight, entity.getFreezeCol(), titleHeight);
}
mergeCells(sheet, excelParams, titleHeight);
// 创建合计信息
addStatisticsRow(getExcelExportStyler().getStyles(true, null), sheet);
return workbook;
}
/**
* 添加Index列
*/
@Override
public ExcelExportEntity indexExcelEntity(ExportParams entity) {
ExcelExportEntity exportEntity = new ExcelExportEntity();
//保证是第一排
exportEntity.setOrderNum(Integer.MIN_VALUE);
exportEntity.setNeedMerge(true);
exportEntity.setName(entity.getIndexName());
exportEntity.setWidth(10);
exportEntity.setFormat(PoiBaseConstants.IS_ADD_INDEX);
return exportEntity;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelExportServer.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export;
import java.lang.reflect.Field;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.entity.vo.PoiBaseConstants;
import org.jeecgframework.poi.excel.export.base.ExcelExportBase;
import org.jeecgframework.poi.excel.export.styler.IExcelExportStyler;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
import org.jeecgframework.poi.util.PoiExcelGraphDataUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Excel导出服务
*
* @author JEECG
* @date 2014年6月17日 下午5:30:54
*/
public class ExcelExportServer extends ExcelExportBase {
private final static Logger LOGGER = LoggerFactory.getLogger(ExcelExportServer.class);
// 最大行数,超过自动多Sheet
private int MAX_NUM = 60000;
protected int createHeaderAndTitle(ExportParams entity, Sheet sheet, Workbook workbook, List excelParams) {
int rows = 0, feildWidth = getFieldWidth(excelParams);
if (entity.getTitle() != null) {
rows += createHeaderRow(entity, sheet, workbook, feildWidth);
}
rows += createTitleRow(entity, sheet, workbook, rows, excelParams);
//update-begin---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
if (entity.isFixedTitle()) {
sheet.createFreezePane(0, rows, 0, rows);
}
//update-begin---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
return rows;
}
/**
* 创建 表头改变
*
* @param entity
* @param sheet
* @param workbook
* @param feildWidth
*/
public int createHeaderRow(ExportParams entity, Sheet sheet, Workbook workbook, int feildWidth) {
Row row = sheet.createRow(0);
row.setHeight(entity.getTitleHeight());
createStringCell(row, 0, entity.getTitle(), getExcelExportStyler().getHeaderStyle(entity.getHeaderColor()), null);
for (int i = 1; i <= feildWidth; i++) {
createStringCell(row, i, "", getExcelExportStyler().getHeaderStyle(entity.getHeaderColor()), null);
}
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try {
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, feildWidth));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
if (entity.getSecondTitle() != null) {
row = sheet.createRow(1);
row.setHeight(entity.getSecondTitleHeight());
//update-begin-author:liusq date:20230407 for:[issue/4342]autopoi导出带副标题的数据表,副标题缺左边框
CellStyle style = getExcelExportStyler().getHeaderStyle(entity.getHeaderColor());
style.setAlignment(HorizontalAlignment.RIGHT);
//update-end-author:liusq date:20230407 for:[issue/4342]autopoi导出带副标题的数据表,副标题缺左边框
createStringCell(row, 0, entity.getSecondTitle(), style, null);
for (int i = 1; i <= feildWidth; i++) {
createStringCell(row, i, "", getExcelExportStyler().getHeaderStyle(entity.getHeaderColor()), null);
}
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try{
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, feildWidth));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
return 2;
}
return 1;
}
public void createSheet(Workbook workbook, ExportParams entity, Class> pojoClass, Collection> dataSet, String[] exportFields) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Excel export start ,class is {}", pojoClass);
LOGGER.debug("Excel version is {}", entity.getType().equals(ExcelType.HSSF) ? "03" : "07");
}
if (workbook == null || entity == null || pojoClass == null || dataSet == null) {
throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
}
super.type = entity.getType();
if (type.equals(ExcelType.XSSF)) {
MAX_NUM = 1000000;
}
Sheet sheet = null;
try {
sheet = workbook.createSheet(entity.getSheetName());
} catch (Exception e) {
// 重复遍历,出现了重名现象,创建非指定的名称Sheet
sheet = workbook.createSheet();
}
try {
dataHanlder = entity.getDataHanlder();
if (dataHanlder != null) {
String[] needHandlerFields = dataHanlder.getNeedHandlerFields();
if(needHandlerFields!=null && needHandlerFields.length>0){
needHanlderList = Arrays.asList(dataHanlder.getNeedHandlerFields());
}
}
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) entity.getStyle().getConstructor(Workbook.class).newInstance(workbook));
Drawing patriarch = sheet.createDrawingPatriarch();
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
// 得到所有字段
Field fileds[] = PoiPublicUtil.getClassFields(pojoClass);
//---update-begin-----autor:scott------date:20191016-------for:导出字段支持自定义--------
//支持自定义导出字段
if (exportFields != null) {
List list = new ArrayList(Arrays.asList(fileds));
for (int i = 0; i < list.size(); i++) {
if (!Arrays.asList(exportFields).contains(list.get(i).getName())) {
list.remove(i);
i--;
}
}
if (list != null && list.size() > 0) {
fileds = list.toArray(new Field[0]);
} else {
fileds = null;
}
}
//---update-end-----autor:scott------date:20191016-------for:导出字段支持自定义--------
ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
String targetId = etarget == null ? null : etarget.value();
getAllExcelField(entity.getExclusions(), targetId, fileds, excelParams, pojoClass, null);
//update-begin-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
rebuildDynamicColumns(dataSet, excelParams);
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
//update-begin-author:taoyan date:20200304 for:在此方法循环内设置一下图片磁盘目录,便于导出
reConfigExcelExportParams(excelParams,entity);
//update-end-author:taoyan date:20200304 for:在此方法循环内设置一下图片磁盘目录,便于导出
int index = entity.isCreateHeadRows() ? createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
int titleHeight = index;
setCellWith(excelParams, sheet);
//update-begin-author:liusq date:20210723 for:设置隐藏列
setColumnHidden(excelParams, sheet);
//update-end-author:liusq date:20210723 for:设置隐藏列
short rowHeight = getRowHeight(excelParams);
setCurrentIndex(1);
Iterator> its = dataSet.iterator();
List tempList = new ArrayList();
while (its.hasNext()) {
Object t = its.next();
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight);
tempList.add(t);
if (index >= MAX_NUM)
break;
}
mergeCells(sheet, excelParams, titleHeight);
if (entity.getFreezeCol() != 0) {
sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
}
its = dataSet.iterator();
for (int i = 0, le = tempList.size(); i < le; i++) {
its.next();
its.remove();
}
// 创建合计信息
addStatisticsRow(getExcelExportStyler().getStyles(true, null), sheet);
// 发现还有剩余list 继续循环创建Sheet
if (dataSet.size() > 0) {
createSheet(workbook, entity, pojoClass, dataSet,exportFields);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
public void createSheetForMap(Workbook workbook, ExportParams entity, List entityList, Collection extends Map, ?>> dataSet) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Excel version is {}", entity.getType().equals(ExcelType.HSSF) ? "03" : "07");
}
if (workbook == null || entity == null || entityList == null || dataSet == null) {
throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
}
super.type = entity.getType();
if (type.equals(ExcelType.XSSF)) {
MAX_NUM = 1000000;
}
Sheet sheet = null;
try {
sheet = workbook.createSheet(entity.getSheetName());
} catch (Exception e) {
// 重复遍历,出现了重名现象,创建非指定的名称Sheet
sheet = workbook.createSheet();
}
try {
dataHanlder = entity.getDataHanlder();
if (dataHanlder != null) {
needHanlderList = Arrays.asList(dataHanlder.getNeedHandlerFields());
}
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) entity.getStyle().getConstructor(Workbook.class).newInstance(workbook));
Drawing patriarch = sheet.createDrawingPatriarch();
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
excelParams.addAll(entityList);
//update-begin-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
rebuildDynamicColumns(dataSet, excelParams);
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
sortAllParams(excelParams);
int index = entity.isCreateHeadRows() ? createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
int titleHeight = index;
setCellWith(excelParams, sheet);
//update-begin-author:liusq date:20210723 for:设置隐藏列
setColumnHidden(excelParams, sheet);
//update-end-author:liusq date:20210723 for:设置隐藏列
short rowHeight = getRowHeight(excelParams);
setCurrentIndex(1);
Iterator> its = dataSet.iterator();
List tempList = new ArrayList();
while (its.hasNext()) {
Object t = its.next();
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight);
tempList.add(t);
if (index >= MAX_NUM)
break;
}
if (entity.getFreezeCol() != 0) {
sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
}
mergeCells(sheet, excelParams, titleHeight);
its = dataSet.iterator();
for (int i = 0, le = tempList.size(); i < le; i++) {
its.next();
its.remove();
}
// 发现还有剩余list 继续循环创建Sheet
if (dataSet.size() > 0) {
createSheetForMap(workbook, entity, entityList, dataSet);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
e.printStackTrace(); // 添加打印完整堆栈信息
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
/**
* 创建表头
*
* @param title
* @param index
*/
private int createTitleRow(ExportParams title, Sheet sheet, Workbook workbook, int index, List excelParams) {
Row row = sheet.createRow(index);
int rows = getRowNums(excelParams);
row.setHeight((short) 450);
Row listRow = null;
if (rows == 2) {
listRow = sheet.createRow(index + 1);
listRow.setHeight((short) 450);
}
int cellIndex = 0;
CellStyle titleStyle = getExcelExportStyler().getTitleStyle(title.getColor());
for (int i = 0, exportFieldTitleSize = excelParams.size(); i < exportFieldTitleSize; i++) {
ExcelExportEntity entity = excelParams.get(i);
//update-begin-author:taoyan date:20200319 for:建议autoPoi升级,优化数据返回List Map格式下的复合表头导出excel的体验 #873
if(entity.isColspan()){
List subList = entity.getSubColumnList();
if(subList==null || subList.size()==0){
continue;
}else{
entity.initSubExportEntity(excelParams);
}
}
//update-end-author:taoyan date:20200319 for:建议autoPoi升级,优化数据返回List Map格式下的复合表头导出excel的体验 #873
if (StringUtils.isNotBlank(entity.getName())) {
createStringCell(row, cellIndex, entity.getName(), titleStyle, entity);
}
if (entity.getList() != null) {
List sTitel = entity.getList();
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
if (StringUtils.isNotBlank(entity.getName())) {
try {
sheet.addMergedRegion(new CellRangeAddress(index, index, cellIndex, cellIndex + sTitel.size() - 1));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
}
for (int j = 0, size = sTitel.size(); j < size; j++) {
createStringCell(rows == 2 ? listRow : row, cellIndex, sTitel.get(j).getName(), titleStyle, entity);
cellIndex++;
}
cellIndex--;
} else if (rows == 2) {
createStringCell(listRow, cellIndex, "", titleStyle, entity);
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try{
sheet.addMergedRegion(new CellRangeAddress(index, index + 1, cellIndex, cellIndex));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
}
cellIndex++;
}
return rows;
}
/**
* 判断表头是只有一行还是两行
*
* @param excelParams
* @return
*/
private int getRowNums(List excelParams) {
for (int i = 0; i < excelParams.size(); i++) {
//update-begin-author:taoyan date:20200319 for:建议autoPoi升级,优化数据返回List Map格式下的复合表头导出excel的体验 #873
ExcelExportEntity temp = excelParams.get(i);
if ((temp.getList() != null || temp.isColspan()) && StringUtils.isNotBlank(temp.getName())) {
return 2;
}
//update-end-author:taoyan date:20200319 for:建议autoPoi升级,优化数据返回List Map格式下的复合表头导出excel的体验 #873
}
return 1;
}
protected ExcelExportEntity indexExcelEntity(ExportParams entity) {
ExcelExportEntity exportEntity = new ExcelExportEntity();
exportEntity.setOrderNum(0);
exportEntity.setName(entity.getIndexName());
exportEntity.setWidth(10);
exportEntity.setFormat(PoiBaseConstants.IS_ADD_INDEX);
return exportEntity;
}
//update-begin---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
/**
* 添加数据到sheet
* @param workbook
* @param entity 导出参数
* @param entityList
* @param dataSet 导出数据
* @param sheet
* @date 2022年1月4号
*/
protected void insertDataToSheet(Workbook workbook, ExportParams entity,
List entityList,Collection extends Map, ?>> dataSet,
Sheet sheet) {
try {
dataHanlder = entity.getDataHanlder();
if (dataHanlder != null && dataHanlder.getNeedHandlerFields() != null) {
needHanlderList = Arrays.asList(dataHanlder.getNeedHandlerFields());
}
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) entity.getStyle()
.getConstructor(Workbook.class).newInstance(workbook));
Drawing patriarch = PoiExcelGraphDataUtil.getDrawingPatriarch(sheet);
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
excelParams.addAll(entityList);
//update-begin-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
rebuildDynamicColumns(dataSet, excelParams);
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
sortAllParams(excelParams);
int index = entity.isCreateHeadRows()
? createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
int titleHeight = index;
setCellWith(excelParams, sheet);
setColumnHidden(excelParams, sheet);
short rowHeight = entity.getHeight() != 0 ? entity.getHeight() : getRowHeight(excelParams);
setCurrentIndex(1);
Iterator> its = dataSet.iterator();
List tempList = new ArrayList();
while (its.hasNext()) {
Object t = its.next();
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight, 0)[0];
tempList.add(t);
if (index >= MAX_NUM) {
break;
}
}
if (entity.getFreezeCol() != 0) {
sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
}
mergeCells(sheet, excelParams, titleHeight);
its = dataSet.iterator();
for (int i = 0, le = tempList.size(); i < le; i++) {
its.next();
its.remove();
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("List data more than max ,data size is {}",
dataSet.size());
}
// 发现还有剩余list 继续循环创建Sheet
if (dataSet.size() > 0) {
createSheetForMap(workbook, entity, entityList, dataSet);
} else {
// 创建合计信息
addStatisticsRow(getExcelExportStyler().getStyles(true, null), sheet);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
e.printStackTrace(); // 添加打印完整堆栈信息
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
//update-end---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExcelExportBase.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.base;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.entity.vo.PoiBaseConstants;
import org.jeecgframework.poi.excel.export.styler.IExcelExportStyler;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
import org.jeecgframework.poi.util.MyX509TrustManager;
import org.jeecgframework.poi.util.PoiMergeCellUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.util.*;
/**
* 提供POI基础操作服务
*
* @author JEECG
* @date 2014年6月17日 下午6:15:13
*/
public abstract class ExcelExportBase extends ExportBase {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelExportBase.class);
private int currentIndex = 0;
protected ExcelType type = ExcelType.HSSF;
private Map statistics = new HashMap();
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/**
* 常规格式的内置格式标识符
* for [issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248
*/
private static final short GENERAL_FORMAT = (short)BuiltinFormats.getBuiltinFormat("General");
/**
* 单元格样式缓存
* for [issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248
*/
private final Map cellStyleMap = new HashMap<>();
//update-begin-author:liusq---date:20220527--for: 修改成protected,列循环时继承类需要用到 ---
protected IExcelExportStyler excelExportStyler;
//update-end-author:liusq---date:20220527--for: 修改成protected,列循环时继承类需要用到 ---
/**
* 创建 最主要的 Cells
*
* @param styles
* @param rowHeight
* @throws Exception
*/
public int createCells(Drawing patriarch, int index, Object t, List excelParams, Sheet sheet, Workbook workbook, short rowHeight) throws Exception {
ExcelExportEntity entity;
Row row = sheet.createRow(index);
DataFormat df = workbook.createDataFormat();
row.setHeight(rowHeight);
int maxHeight = 1, cellNum = 0;
int indexKey = createIndexCell(row, index, excelParams.get(0));
cellNum += indexKey;
for (int k = indexKey, paramSize = excelParams.size(); k < paramSize; k++) {
entity = excelParams.get(k);
//update-begin-author:taoyan date:20200319 for:建议autoPoi升级,优化数据返回List Map格式下的复合表头导出excel的体验 #873
if(entity.isSubColumn()){
continue;
}
if(entity.isMergeColumn()){
Map subColumnMap = new HashMap<>();
List mapKeys = entity.getSubColumnList();
for (String subKey : mapKeys) {
Object subKeyValue = null;
if (t instanceof Map) {
subKeyValue = ((Map, ?>) t).get(subKey);
}else{
subKeyValue = PoiPublicUtil.getParamsValue(subKey,t);
}
subColumnMap.put(subKey,subKeyValue);
}
createListCells(patriarch, index, cellNum, subColumnMap, entity.getList(), sheet, workbook);
cellNum += entity.getSubColumnList().size();
//update-end-author:taoyan date:20200319 for:建议autoPoi升级,优化数据返回List Map格式下的复合表头导出excel的体验 #873
} else if (entity.getList() != null) {
Collection> list = getListCellValue(entity, t);
int listC = 0;
for (Object obj : list) {
createListCells(patriarch, index + listC, cellNum, obj, entity.getList(), sheet, workbook);
listC++;
}
cellNum += entity.getList().size();
if (list != null && list.size() > maxHeight) {
maxHeight = list.size();
}
} else {
Object value = getCellValue(entity, t);
//update-begin--Author:xuelin Date:20171018 for:TASK #2372 【excel】AutoPoi 导出类型,type增加数字类型--------------------
if (entity.getType() == 1) {
createStringCell(row, cellNum++, value == null ? "" : value.toString(), index % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity), entity);
} else if (entity.getType() == 4){
createNumericCell(row, cellNum++, value == null ? "" : value.toString(), getNumberCellStyle(index, df, entity), entity);
} else if (entity.getType() == 0) {
//update-begin---author:chenrui ---date:20250604 for:[issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248------------
createStringCell(row, cellNum++, value == null ? "" : value.toString(), getGeneralCellStyle(index, workbook,entity), entity);
//update-end---author:chenrui ---date:20250604 for:[issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248------------
} else {
createImageCell(patriarch, entity, row, cellNum++, value == null ? "" : value.toString(), t);
}
//update-end--Author:xuelin Date:20171018 for:TASK #2372 【excel】AutoPoi 导出类型,type增加数字类型--------------------
//update-begin-author:liusq---date:20220728--for:[issues/I5I840] @Excel注解中不支持超链接,但文档中支持 ---
if (entity.isHyperlink()) {
row.getCell(cellNum - 1)
.setHyperlink(dataHanlder.getHyperlink(
row.getSheet().getWorkbook().getCreationHelper(), t,
entity.getName(), value));
}
//update-end-author:liusq---date:20220728--for:[issues/I5I840] @Excel注解中不支持超链接,但文档中支持 ---
}
}
// 合并需要合并的单元格
cellNum = 0;
for (int k = indexKey, paramSize = excelParams.size(); k < paramSize; k++) {
entity = excelParams.get(k);
if (entity.getList() != null) {
cellNum += entity.getList().size();
} else if (entity.isNeedMerge()) {
for (int i = index + 1; i < index + maxHeight; i++) {
sheet.getRow(i).createCell(cellNum);
sheet.getRow(i).getCell(cellNum).setCellStyle(getStyles(false, entity));
}
//update-begin-author:wangshuai date:20201116 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try {
if (maxHeight > 1) {
sheet.addMergedRegion(new CellRangeAddress(index, index + maxHeight - 1, cellNum, cellNum));
}
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201116 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
cellNum++;
}
}
return maxHeight;
}
/**
* 获取数值单元格样式
* @param index
* @param df
* @param entity
* @return
*/
private CellStyle getNumberCellStyle(int index,DataFormat df, ExcelExportEntity entity) {
//update-begin-author:liusq---date:2023-12-07--for: [issues/5538]导出表格设置了数字格式导出之后仍然是文本格式,并且无法进行计算
CellStyle cellStyle = index % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity);
String numFormat = StringUtils.isNotBlank(entity.getNumFormat())? entity.getNumFormat():"0.00_ ";
cellStyle.setDataFormat(df.getFormat(numFormat));
return cellStyle;
//update-end-author:liusq---date:2023-12-07--for:[issues/5538]导出表格设置了数字格式导出之后仍然是文本格式,并且无法进行计算
}
/**
* 获取常规单元格样式
* for [issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248
* @param index
* @param workbook
* @param entity
* @return
* @author chenrui
* @date 2025/6/4 17:40
*/
private CellStyle getGeneralCellStyle(int index, Workbook workbook, ExcelExportEntity entity) {
String cellStyleKey = index % 2 == 0 ? "twoGeneral" : "oneGeneral";
if (this.cellStyleMap.containsKey(cellStyleKey)) {
return this.cellStyleMap.get(cellStyleKey);
}
CellStyle cellStyle = index % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity);
CellStyle newStyle = workbook.createCellStyle();
newStyle.cloneStyleFrom(cellStyle);
newStyle.setDataFormat(GENERAL_FORMAT);
this.cellStyleMap.put(cellStyleKey, newStyle);
return newStyle;
}
/**
* 通过https地址获取图片数据
* @param imagePath
* @return
* @throws Exception
*/
private byte[] getImageDataByHttps(String imagePath) throws Exception {
SSLContext sslcontext = SSLContext.getInstance("SSL","SunJSSE");
sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new SecureRandom());
URL url = new URL(imagePath);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslcontext.getSocketFactory());
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
InputStream inStream = conn.getInputStream();
byte[] value = readInputStream(inStream);
return value;
}
/**
* 通过http地址获取图片数据
* @param imagePath
* @return
* @throws Exception
*/
private byte[] getImageDataByHttp(String imagePath) throws Exception {
URL url = new URL(imagePath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
InputStream inStream = conn.getInputStream();
byte[] value = readInputStream(inStream);
return value;
}
/**
* 图片类型的Cell
*
* @param patriarch
* @param entity
* @param row
* @param i
* @param imagePath
* @param obj
* @throws Exception
*/
public void createImageCell(Drawing patriarch, ExcelExportEntity entity, Row row, int i, String imagePath, Object obj) throws Exception {
row.setHeight((short) (50 * entity.getHeight()));
row.createCell(i);
ClientAnchor anchor;
if (type.equals(ExcelType.HSSF)) {
anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) i, row.getRowNum(), (short) (i + 1), row.getRowNum() + 1);
} else {
anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) i, row.getRowNum(), (short) (i + 1), row.getRowNum() + 1);
}
if (StringUtils.isEmpty(imagePath)) {
return;
}
//update-beign-author:taoyan date:20200302 for:【多任务】online 专项集中问题 LOWCOD-159
int imageType = entity.getExportImageType();
byte[] value = null;
if(imageType == 2){
//原来逻辑 2
value = (byte[]) (entity.getMethods() != null ? getFieldBySomeMethod(entity.getMethods(), obj) : entity.getMethod().invoke(obj, new Object[] {}));
} else if(imageType==4 || imagePath.startsWith("http")){
//新增逻辑 网络图片4
try {
if (imagePath.indexOf(",") != -1) {
if(imagePath.startsWith(",")){
imagePath = imagePath.substring(1);
}
String[] images = imagePath.split(",");
imagePath = images[0];
}
if(imagePath.startsWith("https")){
value = getImageDataByHttps(imagePath);
}else{
value = getImageDataByHttp(imagePath);
}
} catch (Exception exception) {
LOGGER.warn(exception.getMessage());
//exception.printStackTrace();
}
} else {
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
BufferedImage bufferImg;
String path = null;
if(imageType == 1){
//原来逻辑 1
path = PoiPublicUtil.getWebRootPath(imagePath);
LOGGER.debug("--- createImageCell getWebRootPath ----filePath--- "+ path);
path = path.replace("WEB-INF/classes/", "");
path = path.replace("file:/", "");
}else if(imageType==3){
//新增逻辑 本地图片3
//begin-------author:liusq---data:2021-01-27----for:本地图片ImageBasePath为空报错的问题
if(StringUtils.isNotBlank(entity.getImageBasePath())){
if(!entity.getImageBasePath().endsWith(File.separator) && !imagePath.startsWith(File.separator)){
path = entity.getImageBasePath()+File.separator+imagePath;
}else{
path = entity.getImageBasePath()+imagePath;
}
}else{
path = imagePath;
}
//end-------author:liusq---data:2021-01-27----for:本地图片ImageBasePath为空报错的问题
}
try {
bufferImg = ImageIO.read(new File(path));
//update-begin-author:taoYan date:20211203 for: Excel 导出图片的文件带小数点符号 导出报错 https://gitee.com/jeecg/jeecg-boot/issues/I4JNHR
ImageIO.write(bufferImg, imagePath.substring(imagePath.lastIndexOf(".") + 1, imagePath.length()), byteArrayOut);
//update-end-author:taoYan date:20211203 for: Excel 导出图片的文件带小数点符号 导出报错 https://gitee.com/jeecg/jeecg-boot/issues/I4JNHR
value = byteArrayOut.toByteArray();
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
}
if (value != null) {
patriarch.createPicture(anchor, row.getSheet().getWorkbook().addPicture(value, getImageType(value)));
}
//update-end-author:taoyan date:20200302 for:【多任务】online 专项集中问题 LOWCOD-159
}
/**
* inStream读取到字节数组
* @param inStream
* @return
* @throws Exception
*/
private byte[] readInputStream(InputStream inStream) throws Exception {
if(inStream==null){
return null;
}
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
//每次读取的字符串长度,如果为-1,代表全部读取完毕
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
private int createIndexCell(Row row, int index, ExcelExportEntity excelExportEntity) {
if (excelExportEntity.getName().equals("序号") && PoiBaseConstants.IS_ADD_INDEX.equals(excelExportEntity.getFormat())) {
createStringCell(row, 0, currentIndex + "", index % 2 == 0 ? getStyles(false, null) : getStyles(true, null), null);
currentIndex = currentIndex + 1;
return 1;
}
return 0;
}
/**
* 创建List之后的各个Cells
* @param patriarch
* @param index
* @param cellNum
* @param obj
* @param excelParams
* @param sheet
* @param workbook
* @throws Exception
*/
public void createListCells(Drawing patriarch, int index, int cellNum, Object obj, List excelParams, Sheet sheet, Workbook workbook) throws Exception {
ExcelExportEntity entity;
Row row;
DataFormat df = workbook.createDataFormat();
if (sheet.getRow(index) == null) {
row = sheet.createRow(index);
row.setHeight(getRowHeight(excelParams));
} else {
row = sheet.getRow(index);
}
for (int k = 0, paramSize = excelParams.size(); k < paramSize; k++) {
entity = excelParams.get(k);
Object value = getCellValue(entity, obj);
//update-begin--Author:xuelin Date:20171018 for:TASK #2372 【excel】AutoPoi 导出类型,type增加数字类型--------------------
if (entity.getType() == 1) {
createStringCell(row, cellNum++, value == null ? "" : value.toString(), row.getRowNum() % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity), entity);
//update-begin-author:liusq---date:20220728--for: 新增isHyperlink属性 ---
if (entity.isHyperlink()) {
row.getCell(cellNum - 1)
.setHyperlink(dataHanlder.getHyperlink(
row.getSheet().getWorkbook().getCreationHelper(), obj, entity.getName(),
value));
}
//update-end-author:liusq---date:20220728--for: 新增isHyperlink属性 ---
} else if (entity.getType() == 4){
createNumericCell(row, cellNum++, value == null ? "" : value.toString(), getNumberCellStyle(index, df, entity), entity);
//update-begin-author:liusq---date:20220728--for: 新增isHyperlink属性 ---
if (entity.isHyperlink()) {
row.getCell(cellNum - 1)
.setHyperlink(dataHanlder.getHyperlink(
row.getSheet().getWorkbook().getCreationHelper(), obj, entity.getName(),
value));
}
//update-end-author:liusq---date:20220728--for: 新增isHyperlink属性 ---
} else if (entity.getType() == 0) {
//update-begin---author:chenrui ---date:20250604 for:[issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248------------
createStringCell(row, cellNum++, value == null ? "" : value.toString(), getGeneralCellStyle(index, workbook, entity), entity);
if (entity.isHyperlink()) {
row.getCell(cellNum - 1)
.setHyperlink(dataHanlder.getHyperlink(
row.getSheet().getWorkbook().getCreationHelper(), obj, entity.getName(),
value));
}
//update-end---author:chenrui ---date:20250604 for:[issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248------------
} else{
createImageCell(patriarch, entity, row, cellNum++, value == null ? "" : value.toString(), obj);
}
//update-end--Author:xuelin Date:20171018 for:TASK #2372 【excel】AutoPoi 导出类型,type增加数字类型--------------------
}
}
//update-begin--Author:xuelin Date:20171018 for:TASK #2372 【excel】AutoPoi 导出类型,type增加数字类型--------------------
public void createNumericCell (Row row, int index, String text, CellStyle style, ExcelExportEntity entity) {
Cell cell = row.createCell(index);
if (style != null) {
cell.setCellStyle(style);
}
if(StringUtils.isEmpty(text)){
cell.setCellValue("");
cell.setCellType(CellType.BLANK);
}else{
cell.setCellValue(Double.parseDouble(text));
cell.setCellType(CellType.NUMERIC);
}
addStatisticsData(index, text, entity);
}
/**
* 创建文本类型的Cell
*
* @param row
* @param index
* @param text
* @param style
* @param entity
*/
public void createStringCell(Row row, int index, String text, CellStyle style, ExcelExportEntity entity) {
Cell cell = row.createCell(index);
if (style != null && style.getDataFormat() > 0 && style.getDataFormat() < 12) {
cell.setCellValue(Double.parseDouble(text));
cell.setCellType(CellType.NUMERIC);
}else{
RichTextString Rtext;
if (type.equals(ExcelType.HSSF)) {
Rtext = new HSSFRichTextString(text);
} else {
Rtext = new XSSFRichTextString(text);
}
cell.setCellValue(Rtext);
}
if (style != null) {
cell.setCellStyle(style);
}
addStatisticsData(index, text, entity);
}
/**
* 设置字段下划线
* @param row
* @param index
* @param text
* @param style
* @param entity
* @param workbook
*/
/*public void createStringCell(Row row, int index, String text, CellStyle style, ExcelExportEntity entity, Workbook workbook) {
Cell cell = row.createCell(index);
if (style != null && style.getDataFormat() > 0 && style.getDataFormat() < 12) {
cell.setCellValue(Double.parseDouble(text));
cell.setCellType(CellType.NUMERIC);
}else{
RichTextString Rtext;
if (type.equals(ExcelType.HSSF)) {
Rtext = new HSSFRichTextString(text);
} else {
Rtext = new XSSFRichTextString(text);
}
cell.setCellValue(Rtext);
}
if (style != null) {
Font font = workbook.createFont();
font.setUnderline(Font.U_SINGLE);
style.setFont(font);
cell.setCellStyle(style);
}
addStatisticsData(index, text, entity);
}*/
//update-end--Author:xuelin Date:20171018 for:TASK #2372 【excel】AutoPoi 导出类型,type增加数字类型----------------------
/**
* 创建统计行
*
* @param styles
* @param sheet
*/
public void addStatisticsRow(CellStyle styles, Sheet sheet) {
if (statistics.size() > 0) {
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
Set keys = statistics.keySet();
createStringCell(row, 0, "合计", styles, null);
for (Integer key : keys) {
createStringCell(row, key, DOUBLE_FORMAT.format(statistics.get(key)), styles, null);
}
statistics.clear();
}
}
/**
* 合计统计信息
*
* @param index
* @param text
* @param entity
*/
private void addStatisticsData(Integer index, String text, ExcelExportEntity entity) {
if (entity != null && entity.isStatistics()) {
Double temp = 0D;
if (!statistics.containsKey(index)) {
statistics.put(index, temp);
}
try {
temp = Double.valueOf(text);
} catch (NumberFormatException e) {
}
statistics.put(index, statistics.get(index) + temp);
}
}
/**
* 获取导出报表的字段总长度
*
* @param excelParams
* @return
*/
public int getFieldWidth(List excelParams) {
int length = -1;// 从0开始计算单元格的
for (ExcelExportEntity entity : excelParams) {
//update-begin---author:liusq Date:20200909 for:AutoPoi多表头导出,会多出一列空白列 #1513------------
if(entity.getGroupName()!=null){
continue;
}else if (entity.getSubColumnList()!=null&&entity.getSubColumnList().size()>0){
length += entity.getSubColumnList().size();
}else{
length += entity.getList() != null ? entity.getList().size() : 1;
}
//update-end---author:liusq Date:20200909 for:AutoPoi多表头导出,会多出一列空白列 #1513------------
}
return length;
}
/**
* 获取图片类型,设置图片插入类型
*
* @param value
* @return
* @Author JEECG
* @date 2013年11月25日
*/
public int getImageType(byte[] value) {
String type = PoiPublicUtil.getFileExtendName(value);
if (type.equalsIgnoreCase("JPG")) {
return Workbook.PICTURE_TYPE_JPEG;
} else if (type.equalsIgnoreCase("PNG")) {
return Workbook.PICTURE_TYPE_PNG;
}
return Workbook.PICTURE_TYPE_JPEG;
}
private Map getMergeDataMap(List excelParams) {
Map mergeMap = new HashMap();
// 设置参数顺序,为之后合并单元格做准备
int i = 0;
for (ExcelExportEntity entity : excelParams) {
if (entity.isMergeVertical()) {
mergeMap.put(i, entity.getMergeRely());
}
if (entity.getList() != null) {
for (ExcelExportEntity inner : entity.getList()) {
if (inner.isMergeVertical()) {
mergeMap.put(i, inner.getMergeRely());
}
i++;
}
} else {
i++;
}
}
return mergeMap;
}
/**
* 获取样式
*
* @param entity
* @param needOne
* @return
*/
public CellStyle getStyles(boolean needOne, ExcelExportEntity entity) {
return excelExportStyler.getStyles(needOne, entity);
}
/**
* 合并单元格
*
* @param sheet
* @param excelParams
* @param titleHeight
*/
public void mergeCells(Sheet sheet, List excelParams, int titleHeight) {
Map mergeMap = getMergeDataMap(excelParams);
PoiMergeCellUtil.mergeCells(sheet, mergeMap, titleHeight);
}
public void setCellWith(List excelParams, Sheet sheet) {
int index = 0;
for (int i = 0; i < excelParams.size(); i++) {
if (excelParams.get(i).getList() != null) {
List list = excelParams.get(i).getList();
for (int j = 0; j < list.size(); j++) {
sheet.setColumnWidth(index, (int) (256 * list.get(j).getWidth()));
index++;
}
} else {
sheet.setColumnWidth(index, (int) (256 * excelParams.get(i).getWidth()));
index++;
}
}
}
/**
* 设置隐藏列
* @param excelParams
* @param sheet
*/
public void setColumnHidden(List excelParams, Sheet sheet) {
int index = 0;
for (int i = 0; i < excelParams.size(); i++) {
if (excelParams.get(i).getList() != null) {
List list = excelParams.get(i).getList();
for (int j = 0; j < list.size(); j++) {
sheet.setColumnHidden(index, list.get(j).isColumnHidden());
index++;
}
} else {
sheet.setColumnHidden(index, excelParams.get(i).isColumnHidden());
index++;
}
}
}
public void setCurrentIndex(int currentIndex) {
this.currentIndex = currentIndex;
}
public void setExcelExportStyler(IExcelExportStyler excelExportStyler) {
this.excelExportStyler = excelExportStyler;
}
public IExcelExportStyler getExcelExportStyler() {
return excelExportStyler;
}
//update-begin---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
/**
*创建单元格,返回最大高度和单元格数
* @param patriarch
* @param index
* @param t
* @param excelParams
* @param sheet
* @param workbook
* @param rowHeight 行高
* @param cellNum 格数
* @return
*/
public int[] createCells(Drawing patriarch, int index, Object t,
List excelParams, Sheet sheet, Workbook workbook,
short rowHeight, int cellNum) {
try {
ExcelExportEntity entity;
Row row = sheet.getRow(index) == null ? sheet.createRow(index) : sheet.getRow(index);
DataFormat df = workbook.createDataFormat();
if (rowHeight != -1) {
row.setHeight(rowHeight);
}
int maxHeight = 1, listMaxHeight = 1;
// 合并需要合并的单元格
int margeCellNum = cellNum;
int indexKey = 0;
if (excelParams != null && !excelParams.isEmpty()) {
indexKey = createIndexCell(row, index, excelParams.get(0));
}
cellNum += indexKey;
for (int k = indexKey, paramSize = excelParams.size(); k < paramSize; k++) {
entity = excelParams.get(k);
//不论数据是否为空都应该把该列的数据跳过去
if (entity.getList() != null) {
Collection> list = getListCellValue(entity, t);
int tmpListHeight = 0;
if (list != null && list.size() > 0) {
int tempCellNum = 0;
for (Object obj : list) {
int[] temp = createCells(patriarch, index + tmpListHeight, obj, entity.getList(), sheet, workbook, rowHeight, cellNum);
tempCellNum = temp[1];
tmpListHeight += temp[0];
}
cellNum = tempCellNum;
listMaxHeight = Math.max(listMaxHeight, tmpListHeight);
} else {
cellNum = cellNum + getListCellSize(entity.getList());
}
} else {
Object value = getCellValue(entity, t);
if (entity.getType() == 1) {
createStringCell(row, cellNum++, value == null ? "" : value.toString(),
index % 2 == 0 ? getStyles(false, entity) : getStyles(true, entity),
entity);
} else if (entity.getType() == 4) {
createNumericCell(row, cellNum++, value == null ? "" : value.toString(),
getNumberCellStyle(index, df, entity),
entity);
} else if (entity.getType() == 0) {
//update-begin---author:chenrui ---date:20250604 for:[issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248------------
createStringCell(row, cellNum++, value == null ? "" : value.toString(),
getGeneralCellStyle(index, workbook, entity), entity);
//update-end---author:chenrui ---date:20250604 for:[issues/8248]AutoPOI导出的单元格格式建议加一个常规类型 #8248------------
} else {
createImageCell(patriarch, entity, row, cellNum++,
value == null ? "" : value.toString(), t);
}
//update-begin-author:liusq---date:20220728--for: 新增isHyperlink属性 ---
if (entity.isHyperlink()) {
row.getCell(cellNum - 1)
.setHyperlink(dataHanlder.getHyperlink(
row.getSheet().getWorkbook().getCreationHelper(), t,
entity.getName(), value));
}
//update-end-author:liusq---date:20220728--for: 新增isHyperlink属性 ---
}
}
maxHeight += listMaxHeight - 1;
if (indexKey == 1 && excelParams.get(1).isNeedMerge()) {
excelParams.get(0).setNeedMerge(true);
}
for (int k = indexKey, paramSize = excelParams.size(); k < paramSize; k++) {
entity = excelParams.get(k);
if (entity.getList() != null) {
margeCellNum += entity.getList().size();
} else if (entity.isNeedMerge() && maxHeight > 1) {
for (int i = index + 1; i < index + maxHeight; i++) {
if (sheet.getRow(i) == null) {
sheet.createRow(i);
}
sheet.getRow(i).createCell(margeCellNum);
sheet.getRow(i).getCell(margeCellNum).setCellStyle(getStyles(false, entity));
}
PoiMergeCellUtil.addMergedRegion(sheet, index, index + maxHeight - 1, margeCellNum, margeCellNum);
margeCellNum++;
}
}
return new int[]{maxHeight, cellNum};
} catch (Exception e) {
LOGGER.error("excel cell export error ,data is :{}", ReflectionToStringBuilder.toString(t));
LOGGER.error(e.getMessage(), e);
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e);
}
}
/**
* 获取集合的宽度
*
* @param list
* @return
*/
protected int getListCellSize(List list) {
int cellSize = 0;
for (ExcelExportEntity ee : list) {
if (ee.getList() != null) {
cellSize += getListCellSize(ee.getList());
} else {
cellSize++;
}
}
return cellSize;
}
//update-end---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExportBase.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.base;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.jeecgframework.dict.service.AutoPoiDictServiceI;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.handler.inter.IExcelDataHandler;
import org.jeecgframework.poi.handler.inter.IExcelDictHandler;
import org.jeecgframework.poi.util.JsonParser;
import org.jeecgframework.poi.util.PoiPublicUtil;
/**
* 导出基础处理,不设计POI,只设计对象,保证复用性
*
* @author JEECG
* @date 2014年8月9日 下午11:01:32
*/
public class ExportBase {
protected IExcelDataHandler dataHanlder;
//update-begin-author:liusq---date:20220527--for: 增加列循环功能时中用到 ---
protected IExcelDictHandler dictHandler;
//update-end-author:liusq---date:20220527--for: be 增加列循环功能时中用到---
protected List needHanlderList;
/**
* 创建导出实体对象
*
* @param field
* @param targetId
* @param pojoClass
* @param getMethods
* @return
* @throws Exception
*/
private ExcelExportEntity createExcelExportEntity(Field field, String targetId, Class> pojoClass, List getMethods) throws Exception {
Excel excel = field.getAnnotation(Excel.class);
ExcelExportEntity excelEntity = new ExcelExportEntity();
excelEntity.setType(excel.type());
getExcelField(targetId, field, excelEntity, excel, pojoClass);
if (getMethods != null) {
List newMethods = new ArrayList();
newMethods.addAll(getMethods);
newMethods.add(excelEntity.getMethod());
excelEntity.setMethods(newMethods);
}
return excelEntity;
}
private Object formatValue(Object value, ExcelExportEntity entity) throws Exception {
Date temp = null;
//update-begin-author:wangshuai date:20201118 for:Excel导出错误原因,value为""字符串,gitee I249JF
if("".equals(value)){
value= null;
}
//update-begin-author:wangshuai date:20201118 for:Excel导出错误原因,value为""字符串,gitee I249JF
if (value instanceof String && entity.getDatabaseFormat()!=null) {
SimpleDateFormat format = new SimpleDateFormat(entity.getDatabaseFormat());
temp = format.parse(value.toString());
} else if (value instanceof Date) {
temp = (Date) value;
//update-begin-author:taoyan date:2022-5-17 for: mybatis-plus升级 时间字段变成了jdk8的LocalDateTime,导致格式化失败
} else if (value instanceof LocalDateTime) {
LocalDateTime ldt = (LocalDateTime) value;
DateTimeFormatter format = DateTimeFormatter.ofPattern(entity.getFormat());
return format.format(ldt);
} else if (value instanceof LocalDate) {
LocalDate ld = (LocalDate) value;
DateTimeFormatter format = DateTimeFormatter.ofPattern(entity.getFormat());
return format.format(ld);
}
//update-end-author:taoyan date:2022-5-17 for: mybatis-plus升级 时间字段变成了jdk8的LocalDateTime,导致格式化失败
if (temp != null) {
SimpleDateFormat format = new SimpleDateFormat(entity.getFormat());
value = format.format(temp);
}
return value;
}
/**
* 获取需要导出的全部字段
*
* @param exclusions
* @param targetId
* 目标ID
* @param fields
* @throws Exception
*/
public void getAllExcelField(String[] exclusions, String targetId, Field[] fields, List excelParams, Class> pojoClass, List getMethods) throws Exception {
List exclusionsList = exclusions != null ? Arrays.asList(exclusions) : null;
ExcelExportEntity excelEntity;
// 遍历整个filed
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 先判断是不是collection,在判断是不是java自带对象,之后就是我们自己的对象了
if (PoiPublicUtil.isNotUserExcelUserThis(exclusionsList, field, targetId)) {
continue;
}
// 首先判断Excel 可能一下特殊数据用户回自定义处理
if (field.getAnnotation(Excel.class) != null) {
excelParams.add(createExcelExportEntity(field, targetId, pojoClass, getMethods));
} else if (PoiPublicUtil.isCollection(field.getType())) {
ExcelCollection excel = field.getAnnotation(ExcelCollection.class);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class> clz = (Class>) pt.getActualTypeArguments()[0];
List list = new ArrayList();
getAllExcelField(exclusions, StringUtils.isNotEmpty(excel.id()) ? excel.id() : targetId, PoiPublicUtil.getClassFields(clz), list, clz, null);
excelEntity = new ExcelExportEntity();
excelEntity.setName(getExcelName(excel.name(), targetId));
excelEntity.setOrderNum(getCellOrder(excel.orderNum(), targetId));
excelEntity.setMethod(PoiPublicUtil.getMethod(field.getName(), pojoClass));
excelEntity.setList(list);
excelParams.add(excelEntity);
} else {
List newMethods = new ArrayList();
if (getMethods != null) {
newMethods.addAll(getMethods);
}
newMethods.add(PoiPublicUtil.getMethod(field.getName(), pojoClass));
ExcelEntity excel = field.getAnnotation(ExcelEntity.class);
//update-begin-author:taoyan date:20210531 for:excel导出支持 注解@ExcelEntity显示合并表头
if(excel.show()==true){
List list = new ArrayList();
// 这里有个设计的坑,导出的时候最后一个参数是null, 即getgetMethods获取的是空,导入的时候需要设置层级getmethod
getAllExcelField(exclusions, StringUtils.isNotEmpty(excel.id()) ? excel.id() : targetId, PoiPublicUtil.getClassFields(field.getType()), list, field.getType(), null);
excelEntity = new ExcelExportEntity();
excelEntity.setName(getExcelName(excel.name(), targetId));
excelEntity.setMethod(PoiPublicUtil.getMethod(field.getName(), pojoClass));
excelEntity.setList(list);
excelParams.add(excelEntity);
}else{
getAllExcelField(exclusions, StringUtils.isNotEmpty(excel.id()) ? excel.id() : targetId, PoiPublicUtil.getClassFields(field.getType()), excelParams, field.getType(), newMethods);
}
//update-end-author:taoyan date:20210531 for:excel导出支持 注解@ExcelEntity显示合并表头
}
}
}
/**
* 获取这个字段的顺序
*
* @param orderNum
* @param targetId
* @return
*/
public int getCellOrder(String orderNum, String targetId) {
if (isInteger(orderNum) || targetId == null) {
return Integer.valueOf(orderNum);
}
String[] arr = orderNum.split(",");
String[] temp;
for (String str : arr) {
temp = str.split("_");
if (targetId.equals(temp[1])) {
return Integer.valueOf(temp[0]);
}
}
return 0;
}
/**
* 获取填如这个cell的值,提供一些附加功能
*
* @param entity
* @param obj
* @return
* @throws Exception
*/
public Object getCellValue(ExcelExportEntity entity, Object obj) throws Exception {
Object value;
//update-begin---author:chenrui ---date:20250819 for:[issues/8699]AutoPoi在使用@ExcelEntity当设置show=true并且该项为null时报错------------
if(null == obj){
return "";
}
//update-end---author:chenrui ---date:20250819 for:[issues/8699]AutoPoi在使用@ExcelEntity当设置show=true并且该项为null时报错------------
//update-begin-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
if (entity.isDynamic()) {
value = getDynamicCellValue(entity, obj);
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
}else if (obj instanceof Map) {
value = ((Map, ?>) obj).get(entity.getKey());
} else {
value = entity.getMethods() != null ? getFieldBySomeMethod(entity.getMethods(), obj) : entity.getMethod().invoke(obj, new Object[] {});
}
//update-begin-author:scott date:20200831 for:导出excel实体反射,时间格式转换错误 #1573
value = Optional.ofNullable(value).orElse("");
if (StringUtils.isEmpty(value.toString())) {
return "";
}
//update-end-author:scott date:20200831 for:导出excel实体反射,时间格式转换错误 #1573
//update-begin-author:taoyan date:2020319 for:Excel注解的numFormat方法似乎未实现 #970
if (StringUtils.isNotEmpty(entity.getNumFormat()) && value!=null) {
value = new DecimalFormat(entity.getNumFormat()).format(value);
}
//update-end-author:taoyan date:2020319 for:Excel注解的numFormat方法似乎未实现 #970
if (StringUtils.isNotEmpty(entity.getDict()) && dictHandler != null) {
value = dictHandler.toName(entity.getDict(), obj, entity.getName(), value);
}
if (StringUtils.isNotEmpty(entity.getFormat())) {
value = formatValue(value, entity);
}
if (entity.getReplace() != null && entity.getReplace().length > 0) {
//update-begin-author:taoyan date:20180731 for:TASK #3038 【bug】Excel 导出多个值(逗号隔开的情况下,导出字典值是ID值)
if(value == null){
value = "";//String.valueOf(value) 如果value为null 则返回"null"
}
String oldVal=value.toString();
if(entity.isMultiReplace()){
value = multiReplaceValue(entity.getReplace(), String.valueOf(value));
}else{
value = replaceValue(entity.getReplace(), String.valueOf(value));
}
//update-end-author:taoyan date:20180731 for:TASK #3038 【bug】Excel 导出多个值(逗号隔开的情况下,导出字典值是ID值)
//update-begin-author:liusq date:20210127 for: 两个数值相等,就证明处理翻译失败的情况
if(oldVal.equals(value)){
}
//update-end-author:liusq date:20210127 for: 两个数值相等,就证明处理翻译失败的情况
}
if (needHanlderList != null && needHanlderList.contains(entity.getName())) {
value = dataHanlder.exportHandler(obj, entity.getName(), value);
}
if (StringUtils.isNotEmpty(entity.getSuffix()) && value != null) {
value = value + entity.getSuffix();
}
return value == null ? "" : value.toString();
}
/**
* 获取集合的值
*
* @param entity
* @param obj
* @return
* @throws Exception
*/
public Collection> getListCellValue(ExcelExportEntity entity, Object obj) throws Exception {
Object value;
if (obj instanceof Map) {
value = ((Map, ?>) obj).get(entity.getKey());
} else {
value = entity.getMethod().invoke(obj, new Object[] {});
if(value instanceof Collection){
return (Collection>)value;
}else{
List list = new ArrayList();
list.add(value);
return list;
}
}
return (Collection>) value;
}
/**
* 注解到导出对象的转换
*
* @param targetId
* @param field
* @param excelEntity
* @param excel
* @param pojoClass
* @throws Exception
*/
private void getExcelField(String targetId, Field field, ExcelExportEntity excelEntity, Excel excel, Class> pojoClass) throws Exception {
excelEntity.setName(getExcelName(excel.name(), targetId));
excelEntity.setWidth(excel.width());
excelEntity.setHeight(excel.height());
excelEntity.setNeedMerge(excel.needMerge());
excelEntity.setMergeVertical(excel.mergeVertical());
excelEntity.setMergeRely(excel.mergeRely());
excelEntity.setReplace(excel.replace());
excelEntity.setHyperlink(excel.isHyperlink());
if(StringUtils.isNotEmpty(excel.dicCode())){
AutoPoiDictServiceI jeecgDictService = null;
try {
jeecgDictService = ApplicationContextUtil.getContext().getBean(AutoPoiDictServiceI.class);
} catch (Exception e) {
}
if(jeecgDictService!=null){
String[] dictReplace = jeecgDictService.queryDict(excel.dictTable(), excel.dicCode(), excel.dicText());
if(excelEntity.getReplace()!=null && dictReplace!=null && dictReplace.length!=0){
excelEntity.setReplace(dictReplace);
}
}
}
excelEntity.setOrderNum(getCellOrder(excel.orderNum(), targetId));
excelEntity.setWrap(excel.isWrap());
excelEntity.setExportImageType(excel.imageType());
excelEntity.setSuffix(excel.suffix());
excelEntity.setDatabaseFormat(excel.databaseFormat());
excelEntity.setFormat(StringUtils.isNotEmpty(excel.exportFormat()) ? excel.exportFormat() : excel.format());
excelEntity.setStatistics(excel.isStatistics());
String fieldname = field.getName();
//update-begin-author:taoyan date:20200319 for:autopoi 双表头问题 #862 基于注解的解决方案
excelEntity.setKey(fieldname);
//update-end-author:taoyan date:20200319 for:autopoi 双表头问题 #862 基于注解的解决方案
//update-begin-author:taoyan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
excelEntity.setNumFormat(excel.numFormat());
//update-end-author:taoyan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
// 动态列配置
excelEntity.setDynamic(excel.dynamic());
excelEntity.setDynamicField(excel.dynamicField());
excelEntity.setDynamicValue(excel.dynamicVal());
excelEntity.setDynamicKeepSelf(excel.dynamicKeepSelf());
//update-begin-author:liusq date:202010723 for:Excel注解的isColumnHidden方法未实现
excelEntity.setColumnHidden(excel.isColumnHidden());
//update-end-author:liusq date:202010723 for:Excel注解的isColumnHidden方法未实现
//update-begin-author:taoyan date:20180615 for:TASK #2798 【例子】导入扩展方法,支持自定义导入字段转换规则
excelEntity.setMethod(PoiPublicUtil.getMethod(fieldname, pojoClass,excel.exportConvert()));
//update-end-author:taoyan date:20180615 for:TASK #2798 【例子】导入扩展方法,支持自定义导入字段转换规则
//update-begin-author:taoyan date:20180801 for:TASK #3038 【bug】Excel 导出多个值(逗号隔开的情况下,导出字典值是ID值)
excelEntity.setMultiReplace(excel.multiReplace());
//update-end-author:taoyan date:20180801 for:TASK #3038 【bug】Excel 导出多个值(逗号隔开的情况下,导出字典值是ID值)
//update-begin-author:taoyan date:20200319 for:autopoi 双表头问题 #862 基于实体注解的解决方案
if(StringUtils.isNotEmpty(excel.groupName())){
excelEntity.setGroupName(excel.groupName());
excelEntity.setColspan(true);
}
//update-end-author:taoyan date:20200319 for:autopoi 双表头问题 #862 基于实体注解的解决方案
}
/**
* 判断在这个单元格显示的名称
*
* @param exportName
* @param targetId
* @return
*/
public String getExcelName(String exportName, String targetId) {
if (exportName.indexOf(",") < 0 || targetId==null) {
return exportName;
}
String[] arr = exportName.split(",");
for (String str : arr) {
if (str.indexOf(targetId) != -1) {
return str.split("_")[0];
}
}
return null;
}
/**
* 多个反射获取值
*
* @param list
* @param t
* @return
* @throws Exception
*/
public Object getFieldBySomeMethod(List list, Object t) throws Exception {
for (Method m : list) {
if (t == null) {
t = "";
break;
}
t = m.invoke(t, new Object[] {});
}
return t;
}
/**
* 根据注解获取行高
*
* @param excelParams
* @return
*/
public short getRowHeight(List excelParams) {
double maxHeight = 0;
for (int i = 0; i < excelParams.size(); i++) {
maxHeight = maxHeight > excelParams.get(i).getHeight() ? maxHeight : excelParams.get(i).getHeight();
if (excelParams.get(i).getList() != null) {
for (int j = 0; j < excelParams.get(i).getList().size(); j++) {
maxHeight = maxHeight > excelParams.get(i).getList().get(j).getHeight() ? maxHeight : excelParams.get(i).getList().get(j).getHeight();
}
}
}
return (short) (maxHeight * 50);
}
/**
* 判断字符串是否是整数
*/
public boolean isInteger(String value) {
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private Object replaceValue(String[] replace, String value) {
String[] temp;
for (String str : replace) {
//temp = str.split("_"); {'男_sheng_1','女_2'}
//update-begin-author:liusq date:20210127 for:字符串截取修改
temp = getValueArr(str);
//update-end-author:liusq date:20210127 for:字符串截取修改
//update-begin---author:scott Date:20211220 for:[issues/I4MBB3]@Excel dicText字段的值有下划线时,导入功能不能正确解析---
if (value.equals(temp[1]) || value.replace("_","---").equals(temp[1])) {
value = temp[0];
break;
}
//update-end---author:scott Date:20211220 for:[issues/I4MBB3]@Excel dicText字段的值有下划线时,导入功能不能正确解析---
}
return value;
}
//update-begin-author:taoyan date:20180731 for:TASK #3038 【bug】Excel 导出多个值(逗号隔开的情况下,导出字典值是ID值)
/**
* 如果需要被替换的值是多选项,则每一项之间有逗号隔开,走以下方法
* @author taoYan
* @since 2018年7月31日
*/
private Object multiReplaceValue(String[] replace, String value) {
if(value.indexOf(",")>0){
String[] radioVals = value.split(",");
String[] temp;
String result = "";
for(int i =0;i excelParams) {
Collections.sort(excelParams);
for (ExcelExportEntity entity : excelParams) {
if (entity.getList() != null) {
Collections.sort(entity.getList());
}
}
}
/**
* 循环ExcelExportEntity集合 附加配置信息
* 1.列排序
* 2.读取图片根路径设置(如果有字段是图片类型 并且存储在本地 则设置磁盘路径获取全地址导出)
* 3.多表头配置(仅限于单表 会走这个逻辑处理)
*/
public void reConfigExcelExportParams(List excelParams, ExportParams exportParams) {
Set NameSet = new HashSet();
Map> groupAndColumnList = new HashMap>();
Map groupOrder = new HashMap<>();
int index = -99;
for (ExcelExportEntity entity : excelParams) {
if(entity.getOrderNum()==0){
entity.setOrderNum(index++);
}
if(entity.getExportImageType()==3){
entity.setImageBasePath(exportParams.getImageBasePath());
}
if (entity.getList() != null) {
Collections.sort(entity.getList());
//update-begin---author:chenrui ---date:20240402 for:生成代码后子表图片无法导出(流)------------
this.reConfigExcelExportParams(entity.getList(), exportParams);
//update-end---author:chenrui ---date:20240402 for:生成代码后子表图片无法导出(流)------------
}
String groupName = entity.getGroupName();
if(StringUtils.isNotEmpty(groupName)){
List ls = groupAndColumnList.get(groupName);
if(ls==null){
ls = new ArrayList();
groupAndColumnList.put(groupName,ls);
}
ls.add(entity.getKey().toString());
Integer order = groupOrder.get(groupName);
if(order==null || entity.getOrderNum() dataList = getDynamicListValue(entity, obj);
if (dataList == null) {
return "";
}
String header = entity.getDynamicColumnName();
String titleField = StringUtils.defaultIfBlank(entity.getDynamicField(), "name");
String valueField = StringUtils.defaultIfBlank(entity.getDynamicValue(), "value");
for (Object item : dataList) {
Object nameVal = PoiPublicUtil.getParamsValue(titleField, item);
if (nameVal != null && header != null && header.equals(nameVal.toString())) {
Object result = PoiPublicUtil.getParamsValue(valueField, item);
return result == null ? "" : result;
}
}
return "";
}
/**
* 获取动态列数据集合
* @param entity
* @param obj
* @return
* @throws Exception
*/
protected Collection> getDynamicListValue(ExcelExportEntity entity, Object obj) throws Exception {
Object value;
if (obj instanceof Map) {
value = ((Map, ?>) obj).get(entity.getKey());
} else {
value = entity.getMethods() != null ? getFieldBySomeMethod(entity.getMethods(), obj) : entity.getMethod().invoke(obj, new Object[] {});
}
if (value == null) {
return null;
}
if (value instanceof String) {
Collection> parsed = parseJsonArrayToList((String) value);
if (parsed != null) {
return parsed;
}
}
if (value instanceof Collection) {
return (Collection>) value;
}
if (value.getClass().isArray()) {
return Arrays.asList((Object[]) value);
}
return Collections.singletonList(value);
}
/**
* 解析 JSON 数组字符串为集合(使用 JDK ScriptEngine,避免额外依赖)
*/
private Collection> parseJsonArrayToList(String json) {
if (StringUtils.isBlank(json)) {
return null;
}
String trim = json.trim();
if (!trim.startsWith("[") || !trim.endsWith("]")) {
return null;
}
try {
List objects = JsonParser.parseJsonArrayToList(json);
return objects;
} catch (Exception e) {
return null;
}
}
/**
* 处理动态列,根据数据动态扩充表头
* @param dataSet
* @param excelParams
*/
protected void rebuildDynamicColumns(Collection> dataSet, List excelParams) throws Exception {
if (excelParams == null || excelParams.isEmpty() || dataSet == null || dataSet.isEmpty()) {
return;
}
List result = new ArrayList();
for (ExcelExportEntity entity : excelParams) {
if (!entity.isDynamic()) {
result.add(entity);
continue;
}
List dynamicList = buildDynamicEntities(entity, dataSet);
if (dynamicList.isEmpty() && !entity.isDynamicKeepSelf()) {
// 没有动态数据时仍然保留原列避免列缺失
result.add(entity);
continue;
}
if (entity.isDynamicKeepSelf()) {
result.add(copyKeepSelfEntity(entity));
}
result.addAll(dynamicList);
}
excelParams.clear();
excelParams.addAll(result);
}
private ExcelExportEntity copyKeepSelfEntity(ExcelExportEntity source){
ExcelExportEntity target = copyDynamicBase(source);
target.setDynamic(false);
target.setDynamicField(null);
target.setDynamicValue(null);
target.setDynamicColumnName(null);
target.setDynamicKeepSelf(false);
target.setName(source.getName());
return target;
}
private List buildDynamicEntities(ExcelExportEntity entity, Collection> dataSet) throws Exception {
LinkedHashSet headers = new LinkedHashSet();
for (Object data : dataSet) {
Collection> list = getDynamicListValue(entity, data);
if (list == null) {
continue;
}
for (Object item : list) {
Object header = PoiPublicUtil.getParamsValue(StringUtils.defaultIfBlank(entity.getDynamicField(), "name"), item);
if (header != null && StringUtils.isNotBlank(header.toString())) {
headers.add(header.toString());
}
}
}
List dynamicEntities = new ArrayList();
for (String header : headers) {
ExcelExportEntity copy = copyDynamicBase(entity);
copy.setName(header);
copy.setDynamicColumnName(header);
copy.setOrderNum(entity.getOrderNum());
dynamicEntities.add(copy);
}
return dynamicEntities;
}
private ExcelExportEntity copyDynamicBase(ExcelExportEntity source) {
ExcelExportEntity target = new ExcelExportEntity();
target.setType(source.getType());
target.setName(source.getName());
target.setKey(source.getKey());
target.setWidth(source.getWidth());
target.setHeight(source.getHeight());
target.setExportImageType(source.getExportImageType());
target.setImageBasePath(source.getImageBasePath());
target.setOrderNum(source.getOrderNum());
target.setWrap(source.isWrap());
target.setNeedMerge(source.isNeedMerge());
target.setMergeVertical(source.isMergeVertical());
target.setMergeRely(source.getMergeRely());
target.setSuffix(source.getSuffix());
target.setStatistics(source.isStatistics());
target.setColspan(source.isColspan());
target.setSubColumnList(source.getSubColumnList());
target.setGroupName(source.getGroupName());
target.setColumnHidden(source.isColumnHidden());
target.setReplace(source.getReplace());
target.setMethod(source.getMethod());
target.setMethods(source.getMethods());
target.setMultiReplace(source.isMultiReplace());
target.setNumFormat(source.getNumFormat());
target.setDatabaseFormat(source.getDatabaseFormat());
target.setFormat(source.getFormat());
target.setFixedIndex(source.getFixedIndex());
target.setDict(source.getDict());
target.setHyperlink(source.isHyperlink());
target.setMergeVertical(source.isMergeVertical());
// 动态配置
target.setDynamic(true);
target.setDynamicField(source.getDynamicField());
target.setDynamicValue(source.getDynamicValue());
target.setDynamicKeepSelf(source.isDynamicKeepSelf());
return target;
}
/**
* 字典文本中含多个下划线横岗,取最后一个(解决空值情况)
*
* @param val
* @return
*/
public String[] getValueArr(String val) {
int i = val.lastIndexOf("_");//最后一个分隔符的位置
String[] c=new String[2];
c[0]=val.substring(0, i); //label
c[1]=val.substring(i+1); //key
return c;
}
//update-end-author:liusq date:20251211 for:JHHB-1212【AutoPoi】导出时,支持动态生成Excel的列
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/AbstractExcelExportStyler.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.styler;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.entity.params.ExcelForEachParams;
/**
* 抽象接口提供两个公共方法
*
* @author JEECG
* @date 2015年1月9日 下午5:48:55
*/
public abstract class AbstractExcelExportStyler implements IExcelExportStyler {
// 单行
protected CellStyle stringNoneStyle;
protected CellStyle stringNoneWrapStyle;
// 间隔行
protected CellStyle stringSeptailStyle;
protected CellStyle stringSeptailWrapStyle;
protected Workbook workbook;
protected static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
protected void createStyles(Workbook workbook) {
this.stringNoneStyle = stringNoneStyle(workbook, false);
this.stringNoneWrapStyle = stringNoneStyle(workbook, true);
this.stringSeptailStyle = stringSeptailStyle(workbook, false);
this.stringSeptailWrapStyle = stringSeptailStyle(workbook, true);
this.workbook = workbook;
}
@Override
public CellStyle getStyles(boolean noneStyler, ExcelExportEntity entity) {
if (noneStyler && (entity == null || entity.isWrap())) {
return stringNoneWrapStyle;
}
if (noneStyler) {
return stringNoneStyle;
}
if (noneStyler == false && (entity == null || entity.isWrap())) {
return stringSeptailWrapStyle;
}
return stringSeptailStyle;
}
public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
return null;
}
public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
return null;
}
/**
* 获取模板样式(列循环时用到)
* @param isSingle
* @param excelForEachParams
* @return
*/
@Override
public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
return null;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerBorderImpl.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.styler;
import org.apache.poi.ss.usermodel.*;
/**
* 带有边框的Excel样式
*
* @author JEECG
* @date 2015年1月9日 下午5:55:29
*/
public class ExcelExportStylerBorderImpl extends AbstractExcelExportStyler implements IExcelExportStyler {
public ExcelExportStylerBorderImpl(Workbook workbook) {
super.createStyles(workbook);
}
@Override
public CellStyle getHeaderStyle(short color) {
CellStyle titleStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontHeightInPoints((short) 12);
titleStyle.setFont(font);
titleStyle.setBorderLeft(BorderStyle.THIN); // 左边框
titleStyle.setBorderRight(BorderStyle.THIN); // 右边框
titleStyle.setBorderBottom(BorderStyle.THIN);
titleStyle.setBorderTop(BorderStyle.THIN);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return titleStyle;
}
@Override
public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setBorderLeft(BorderStyle.THIN); // 左边框
style.setBorderRight(BorderStyle.THIN); // 右边框
style.setBorderBottom(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
if (isWarp) {
style.setWrapText(true);
}
return style;
}
@Override
public CellStyle getTitleStyle(short color) {
CellStyle titleStyle = workbook.createCellStyle();
titleStyle.setBorderLeft(BorderStyle.THIN); // 左边框
titleStyle.setBorderRight(BorderStyle.THIN); // 右边框
titleStyle.setBorderBottom(BorderStyle.THIN);
titleStyle.setBorderTop(BorderStyle.THIN);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
titleStyle.setWrapText(true);
return titleStyle;
}
@Override
public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
return isWarp ? stringNoneWrapStyle : stringNoneStyle;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerColorImpl.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.styler;
import org.apache.poi.ss.usermodel.*;
/**
* 带有样式的导出服务
*
* @author JEECG
* @date 2015年1月9日 下午4:54:15
*/
public class ExcelExportStylerColorImpl extends AbstractExcelExportStyler implements IExcelExportStyler {
public ExcelExportStylerColorImpl(Workbook workbook) {
super.createStyles(workbook);
}
@Override
public CellStyle getHeaderStyle(short headerColor) {
CellStyle titleStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontHeightInPoints((short) 24);
titleStyle.setFont(font);
titleStyle.setFillForegroundColor(headerColor);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return titleStyle;
}
@Override
public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setBorderLeft(BorderStyle.THIN); // 左边框
style.setBorderRight(BorderStyle.THIN); // 右边框
style.setBorderBottom(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
if (isWarp) {
style.setWrapText(true);
}
return style;
}
@Override
public CellStyle getTitleStyle(short color) {
CellStyle titleStyle = workbook.createCellStyle();
titleStyle.setFillForegroundColor(color); // 填充的背景颜色
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充图案
titleStyle.setWrapText(true);
return titleStyle;
}
@Override
public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setBorderLeft(BorderStyle.THIN); // 左边框
style.setBorderRight(BorderStyle.THIN); // 右边框
style.setBorderBottom(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setFillForegroundColor((short) 41); // 填充的背景颜色
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充图案
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
if (isWarp) {
style.setWrapText(true);
}
return style;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerDefaultImpl.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.styler;
import org.apache.poi.ss.usermodel.*;
/**
* 样式的默认实现
*
* @author JEECG
* @date 2015年1月9日 下午5:36:08
*/
public class ExcelExportStylerDefaultImpl extends AbstractExcelExportStyler implements IExcelExportStyler {
public ExcelExportStylerDefaultImpl(Workbook workbook) {
super.createStyles(workbook);
}
@Override
public CellStyle getTitleStyle(short color) {
CellStyle titleStyle = workbook.createCellStyle();
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
titleStyle.setWrapText(true);
return titleStyle;
}
@Override
public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setAlignment( HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
if (isWarp) {
style.setWrapText(true);
}
return style;
}
@Override
public CellStyle getHeaderStyle(short color) {
CellStyle titleStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontHeightInPoints((short) 12);
titleStyle.setFont(font);
titleStyle.setAlignment( HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return titleStyle;
}
@Override
public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
if (isWarp) {
style.setWrapText(true);
}
return style;
}
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/IExcelExportStyler.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.styler;
import org.apache.poi.ss.usermodel.CellStyle;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.entity.params.ExcelForEachParams;
/**
* Excel导出样式接口
*
* @author JEECG
* @date 2015年1月9日 下午5:32:30
*/
public interface IExcelExportStyler {
/**
* 列表头样式
*
* @param headerColor
* @return
*/
public CellStyle getHeaderStyle(short headerColor);
/**
* 标题样式
*
* @param color
* @return
*/
public CellStyle getTitleStyle(short color);
/**
* 获取样式方法
*
* @param noneStyler
* @param entity
* @return
*/
public CellStyle getStyles(boolean noneStyler, ExcelExportEntity entity);
/**
* 模板使用的样式设置
*/
public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams);
}
================================================
FILE: autopoi/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java
================================================
/**
* Copyright 2013-2015 JEECG (jeecgos@163.com)
*
* 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.jeecgframework.poi.excel.export.template;
import java.lang.reflect.Field;
import java.util.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.poi.cache.ExcelCache;
import org.jeecgframework.poi.cache.ImageCache;
import org.jeecgframework.poi.consts.ImageScaleMode;
import org.jeecgframework.poi.entity.ImageEntity;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
import org.jeecgframework.poi.excel.entity.TemplateExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.excel.entity.params.ExcelForEachParams;
import org.jeecgframework.poi.excel.entity.params.ExcelTemplateParams;
import org.jeecgframework.poi.excel.export.base.ExcelExportBase;
import org.jeecgframework.poi.excel.export.styler.IExcelExportStyler;
import org.jeecgframework.poi.excel.html.helper.MergedRegionHelper;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
import static org.jeecgframework.poi.util.PoiElUtil.*;
import org.jeecgframework.poi.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Excel 导出根据模板导出
*
* @author JEECG
* @date 2013-10-17
* @version 1.0
*/
public final class ExcelExportOfTemplateUtil extends ExcelExportBase {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelExportOfTemplateUtil.class);
/**
* 缓存TEMP 的for each创建的cell ,跳过这个cell的模板语法查找,提高效率
*/
private Set tempCreateCellSet = new HashSet();
/**
* 模板参数,全局都用到
*/
private TemplateExportParams teplateParams;
/**
* 单元格合并信息
*/
private MergedRegionHelper mergedRegionHelper;
/**
* 往Sheet 填充正常数据,根据表头信息 使用导入的部分逻辑,坐对象映射
*
* @param teplateParams
* @param pojoClass
* @param dataSet
* @param workbook
*/
private void addDataToSheet(Class> pojoClass, Collection> dataSet, Sheet sheet, Workbook workbook) throws Exception {
if (workbook instanceof XSSFWorkbook) {
super.type = ExcelType.XSSF;
}
// 获取表头数据
Map titlemap = getTitleMap(sheet);
Drawing patriarch = sheet.createDrawingPatriarch();
// 得到所有字段
Field[] fileds = PoiPublicUtil.getClassFields(pojoClass);
ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
String targetId = null;
if (etarget != null) {
targetId = etarget.value();
}
// 获取实体对象的导出数据
List excelParams = new ArrayList();
getAllExcelField(null, targetId, fileds, excelParams, pojoClass, null);
// 根据表头进行筛选排序
sortAndFilterExportField(excelParams, titlemap);
short rowHeight = getRowHeight(excelParams);
int index = teplateParams.getHeadingRows() + teplateParams.getHeadingStartRow(), titleHeight = index;
// 下移数据,模拟插入
sheet.shiftRows(teplateParams.getHeadingRows() + teplateParams.getHeadingStartRow(), sheet.getLastRowNum(), getShiftRows(dataSet, excelParams), true, true);
if (excelParams.size() == 0) {
return;
}
Iterator> its = dataSet.iterator();
while (its.hasNext()) {
Object t = its.next();
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight);
}
// 合并同类项
mergeCells(sheet, excelParams, titleHeight);
}
/**
* 下移数据
*
* @param its
* @param excelParams
* @return
*/
private int getShiftRows(Collection> dataSet, List excelParams) throws Exception {
int size = 0;
Iterator> its = dataSet.iterator();
while (its.hasNext()) {
Object t = its.next();
size += getOneObjectSize(t, excelParams);
}
return size;
}
/**
* 获取单个对象的高度,主要是处理一堆多的情况
*
* @param styles
* @param rowHeight
* @throws Exception
*/
public int getOneObjectSize(Object t, List excelParams) throws Exception {
ExcelExportEntity entity;
int maxHeight = 1;
for (int k = 0, paramSize = excelParams.size(); k < paramSize; k++) {
entity = excelParams.get(k);
if (entity.getList() != null) {
Collection> list = (Collection>) entity.getMethod().invoke(t, new Object[] {});
if (list != null && list.size() > maxHeight) {
maxHeight = list.size();
}
}
}
return maxHeight;
}
public Workbook createExcleByTemplate(TemplateExportParams params, Class> pojoClass, Collection> dataSet, Map map) {
// step 1. 判断模板的地址
if (params == null || map == null || (StringUtils.isEmpty(params.getTemplateUrl()) && params.getTemplateWb() == null)) {
throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
}
Workbook wb = null;
// step 2. 判断模板的Excel类型,解析模板
try {
this.teplateParams = params;
//update-begin-author:liusq---date:2024-09-03--for: [issues/7048]TemplateExportParams类建议增加传入模板文件InputStream的方式
if (params.getTemplateWb() != null) {
wb = params.getTemplateWb();
} else {
wb = getCloneWorkBook();
}
//update-end-author:liusq---date:2024-09-03--for: [issues/7048]TemplateExportParams类建议增加传入模板文件InputStream的方式
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) teplateParams.getStyle().getConstructor(Workbook.class).newInstance(wb));
// step 3. 解析模板
//update-begin---author:chenrui ---date:20240801 for:[issues/6925]xlsx模版导出图片------------
if (wb instanceof XSSFWorkbook) {
super.type = ExcelType.XSSF;
}
//update-end---author:chenrui ---date:20240801 for:[issues/6925]xlsx模版导出图片------------
for (int i = 0, le = params.isScanAllsheet() ? wb.getNumberOfSheets() : params.getSheetNum().length; i < le; i++) {
if (params.getSheetName() != null && params.getSheetName().length > i && StringUtils.isNotEmpty(params.getSheetName()[i])) {
wb.setSheetName(i, params.getSheetName()[i]);
}
tempCreateCellSet.clear();
parseTemplate(wb.getSheetAt(i), map, params.isColForEach());
}
if (dataSet != null) {
// step 4. 正常的数据填充
dataHanlder = params.getDataHanlder();
if (dataHanlder != null) {
needHanlderList = Arrays.asList(dataHanlder.getNeedHandlerFields());
}
addDataToSheet(pojoClass, dataSet, wb.getSheetAt(params.getDataSheetNum()), wb);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
return null;
}
return wb;
}
/**
* 克隆excel防止操作原对象,workbook无法克隆,只能对excel进行克隆
*
* @param teplateParams
* @throws Exception
* @Author JEECG
* @date 2013-11-11
*/
private Workbook getCloneWorkBook() throws Exception {
//update-begin-author:wangshuai date:20200730 for:jar 包上传到服务器后 autopoi 读取不到excel模版文件 #1505
return ExcelCache.getWorkbookByTemplate(teplateParams.getTemplateUrl(), teplateParams.getSheetNum(), teplateParams.isScanAllsheet());
//update-end-author:wangshuai date:20200730 for:jar 包上传到服务器后 autopoi 读取不到excel模版文件 #1505
}
/**
* 获取表头数据,设置表头的序号
*
* @param teplateParams
* @param sheet
* @return
*/
private Map getTitleMap(Sheet sheet) {
Row row = null;
Iterator cellTitle;
Map titlemap = new HashMap();
for (int j = 0; j < teplateParams.getHeadingRows(); j++) {
row = sheet.getRow(j + teplateParams.getHeadingStartRow());
cellTitle = row.cellIterator();
int i = row.getFirstCellNum();
while (cellTitle.hasNext()) {
Cell cell = cellTitle.next();
String value = cell.getStringCellValue();
if (!StringUtils.isEmpty(value)) {
titlemap.put(value, i);
}
i = i + 1;
}
}
return titlemap;
}
private void parseTemplate(Sheet sheet, Map map, boolean colForeach) throws Exception {
deleteCell(sheet, map);
//update-begin-author:liusq---date:20220527--for: 模板导出列循环核心代码 ---
mergedRegionHelper = new MergedRegionHelper(sheet);
if (colForeach) {
colForeach(sheet, map);
}
//update-end-author:liusq---date:20220527--for: 模板导出列循环核心代码 ---
Row row = null;
int index = 0;
while (index <= sheet.getLastRowNum()) {
row = sheet.getRow(index++);
if (row == null) {
continue;
}
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
if (row.getCell(i) != null && !tempCreateCellSet.contains(row.getRowNum() + "_" + row.getCell(i).getColumnIndex())) {
setValueForCellByMap(row.getCell(i), map);
}
}
}
}
/**
* 先判断删除,省得影响效率
*
* @param sheet
* @param map
* @throws Exception
*/
private void deleteCell(Sheet sheet, Map map) throws Exception {
Row row = null;
Cell cell = null;
int index = 0;
while (index <= sheet.getLastRowNum()) {
row = sheet.getRow(index++);
if (row == null) {
continue;
}
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
cell = row.getCell(i);
if (row.getCell(i) != null && (cell.getCellType() == CellType.STRING || cell.getCellType() == CellType.NUMERIC)) {
cell.setCellType(CellType.STRING);
String text = cell.getStringCellValue();
if (text.contains(IF_DELETE)) {
if (Boolean.valueOf(eval(text.substring(text.indexOf(START_STR) + 2, text.indexOf(END_STR)).trim(), map).toString())) {
PoiSheetUtility.deleteColumn(sheet, i);
}
cell.setCellValue("");
}
}
}
}
}
/**
* 给每个Cell通过解析方式set值
*
* @param cell
* @param map
*/
private void setValueForCellByMap(Cell cell, Map map) throws Exception {
CellType cellType = cell.getCellType();
if (cellType != CellType.STRING && cellType != CellType.NUMERIC) {
return;
}
String oldString;
cell.setCellType(CellType.STRING);
oldString = cell.getStringCellValue();
if (oldString != null && oldString.indexOf(START_STR) != -1 && !oldString.contains(FOREACH)) {
// step 2. 判断是否含有解析函数
String params = null;
boolean isNumber = false;
if (isNumber(oldString)) {
isNumber = true;
oldString = oldString.replace(NUMBER_SYMBOL, "");
}
while (oldString.indexOf(START_STR) != -1) {
params = oldString.substring(oldString.indexOf(START_STR) + 2, oldString.indexOf(END_STR));
//update-begin-author:liusq---date:2025-06-04--for: [issues/8230] autopoi使用模板导出时,如果传入的map中存在值为null时会导致异常出错,导出失败
oldString = oldString.replace(START_STR + params + END_STR, ObjectUtils.isNotEmpty(eval(params, map))?eval(params, map).toString():"");
//update-end-author:liusq---date:2025-06-04--for:[issues/8230] autopoi使用模板导出时,如果传入的map中存在值为null时会导致异常出错,导出失败
}
// 如何是数值 类型,就按照数值类型进行设置
if (isNumber && StringUtils.isNotBlank(oldString)) {
cell.setCellValue(Double.parseDouble(oldString));
cell.setCellType(CellType.NUMERIC);
} else {
cell.setCellValue(oldString);
}
}
// 判断foreach 这种方法
if (oldString != null && oldString.contains(FOREACH)) {
addListDataToExcel(cell, map, oldString.trim());
}
}
private boolean isNumber(String text) {
return text.startsWith(NUMBER_SYMBOL) || text.contains("{" + NUMBER_SYMBOL) || text.contains(" " + NUMBER_SYMBOL);
}
/**
* 利用foreach循环输出数据
*
* @param cell
* @param map
* @param oldString
* @throws Exception
*/
private void addListDataToExcel(Cell cell, Map map, String name) throws Exception {
boolean isCreate = !name.contains(FOREACH_NOT_CREATE);
boolean isShift = name.contains(FOREACH_AND_SHIFT);
name = name.replace(FOREACH_NOT_CREATE, EMPTY).replace(FOREACH_AND_SHIFT, EMPTY).replace(FOREACH, EMPTY).replace(START_STR, EMPTY);
String[] keys = name.replaceAll("\\s{1,}", " ").trim().split(" ");
Collection> datas = (Collection>) PoiPublicUtil.getParamsValue(keys[0], map);
//update-begin-author:liusq---date:20220609--for: [issues/3328]autopoi模板导出Excel功能,$fe: 遍历不好用 ---
Object[] columnsInfo = getAllDataColumns(cell, name.replace(keys[0], EMPTY),
mergedRegionHelper);
int rowspan = (Integer) columnsInfo[0], colspan = (Integer) columnsInfo[1];
@SuppressWarnings("unchecked")
List columns = (List) columnsInfo[2];
if (datas == null) {
return;
}
Iterator> its = datas.iterator();
Row row;
int rowIndex = cell.getRow().getRowNum() + 1;
//处理当前行
int loopSize = 0;
if (its.hasNext()) {
Object t = its.next();
cell.getRow().setHeight(columns.get(0).getHeight());
loopSize = setForeachRowCellValue(isCreate, cell.getRow(), cell.getColumnIndex(), t, columns, map,
rowspan, colspan, mergedRegionHelper)[0];
rowIndex += rowspan - 1 + loopSize - 1;
}
//修复不论后面有没有数据,都应该执行的是插入操作
if (isShift && datas.size() * rowspan > 1 && cell.getRowIndex() + rowspan <= cell.getRow().getSheet().getLastRowNum()) {
int lastRowNum = cell.getRow().getSheet().getLastRowNum();
int shiftRows = lastRowNum - cell.getRowIndex() - rowspan;
cell.getRow().getSheet().shiftRows(cell.getRowIndex() + rowspan, lastRowNum, (datas.size() - 1) * rowspan, true, true);
//update-begin-author:liusq---date:20221103--for: [issues/4142]exlce模板导出如果模板中有多个合并单元格的循环表格,第二个表格读取错误 ---
mergedRegionHelper.shiftRows(cell.getSheet(), cell.getRowIndex() + rowspan, (datas.size() - 1) * rowspan, shiftRows);
PoiExcelTempUtil.reset(cell.getSheet(), cell.getRowIndex() + rowspan + (datas.size() - 1) * rowspan, cell.getRow().getSheet().getLastRowNum());
//update-end-author:liusq---date:20221103--for: [issues/4142]exlce模板导出如果模板中有多个合并单元格的循环表格,第二个表格读取错误 ---
}
while (its.hasNext()) {
Object t = its.next();
row = createRow(rowIndex, cell.getSheet(), isCreate, rowspan);
row.setHeight(columns.get(0).getHeight());
loopSize = setForeachRowCellValue(isCreate, row, cell.getColumnIndex(), t, columns, map, rowspan,
colspan, mergedRegionHelper)[0];
rowIndex += rowspan + loopSize - 1;
}
//update-end-author:liusq---date:20220609--for: [issues/3328]autopoi模板导出Excel功能,$fe: 遍历不好用 ---
}
private void setForEeachCellValue(boolean isCreate, Row row, int columnIndex, Object t, List columns, Map map) throws Exception {
for (int i = 0, max = columnIndex + columns.size(); i < max; i++) {
if (row.getCell(i) == null)
row.createCell(i);
}
for (int i = 0, max = columns.size(); i < max; i++) {
boolean isNumber = false;
String tempStr = new String(columns.get(i).getName());
if (isNumber(tempStr)) {
isNumber = true;
tempStr = tempStr.replace(NUMBER_SYMBOL, "");
}
map.put(teplateParams.getTempParams(), t);
String val = eval(tempStr, map).toString();
if (isNumber && StringUtils.isNotEmpty(val)) {
row.getCell(i + columnIndex).setCellValue(Double.parseDouble(val));
row.getCell(i + columnIndex).setCellType(CellType.NUMERIC);
} else {
row.getCell(i + columnIndex).setCellValue(val);
}
row.getCell(i + columnIndex).setCellStyle(columns.get(i).getCellStyle());
tempCreateCellSet.add(row.getRowNum() + "_" + (i + columnIndex));
}
}
/**
* 获取迭代的数据的值
*
* @param cell
* @param name
* @return
*/
private List getAllDataColumns(Cell cell, String name) {
List columns = new ArrayList();
cell.setCellValue("");
if (name.contains(END_STR)) {
columns.add(new ExcelTemplateParams(name.replace(END_STR, EMPTY).trim(), cell.getCellStyle(), cell.getRow().getHeight()));
return columns;
}
columns.add(new ExcelTemplateParams(name.trim(), cell.getCellStyle(), cell.getRow().getHeight()));
int index = cell.getColumnIndex();
//列数
int lastCellNum = cell.getRow().getLastCellNum();
Cell tempCell;
while (true) {
tempCell = cell.getRow().getCell(++index);
//--begin--date:2020/09/18---for:增加列数判断,防止提前跳出
if (tempCell == null&&index>=lastCellNum) {
break;
}
String cellStringString;
try {// 允许为空,单表示已经完结了,因为可能被删除了
cellStringString = tempCell.getStringCellValue();
if (StringUtils.isBlank(cellStringString)&&index>=lastCellNum) {
break;
}
} catch (Exception e) {
throw new ExcelExportException("for each 当中存在空字符串,请检查模板");
}
//--end--date:2020/09/18---for:增加列数判断,防止提前跳出
// 把读取过的cell 置为空
tempCell.setCellValue("");
if (cellStringString.contains(END_STR)) {
columns.add(new ExcelTemplateParams(cellStringString.trim().replace(END_STR, ""), tempCell.getCellStyle(), tempCell.getRow().getHeight()));
break;
} else {
if (cellStringString.trim().contains(teplateParams.getTempParams())) {
columns.add(new ExcelTemplateParams(cellStringString.trim(), tempCell.getCellStyle(), tempCell.getRow().getHeight()));
}else if(cellStringString.trim().equals(EMPTY)){
//可能是合并的单元格,允许空数据的设置
columns.add(new ExcelTemplateParams(EMPTY, tempCell.getCellStyle(), tempCell.getRow().getHeight()));
} else {
// 最后一行被删除了
break;
}
}
}
return columns;
}
/**
* 对导出序列进行排序和塞选
*
* @param excelParams
* @param titlemap
* @return
*/
private void sortAndFilterExportField(List excelParams, Map titlemap) {
for (int i = excelParams.size() - 1; i >= 0; i--) {
if (excelParams.get(i).getList() != null && excelParams.get(i).getList().size() > 0) {
sortAndFilterExportField(excelParams.get(i).getList(), titlemap);
if (excelParams.get(i).getList().size() == 0) {
excelParams.remove(i);
} else {
excelParams.get(i).setOrderNum(i);
}
} else {
if (titlemap.containsKey(excelParams.get(i).getName())) {
excelParams.get(i).setOrderNum(i);
} else {
excelParams.remove(i);
}
}
}
sortAllParams(excelParams);
}
//-----------------update-begin-author:liusq---date:20220527--for: 以下方法是模板导出列循环功能新增的方法 ---
/**
* 先进行列的循环,因为涉及很多数据
*
* @param sheet
* @param map
*/
private void colForeach(Sheet sheet, Map map) throws Exception {
Row row = null;
Cell cell = null;
int index = 0;
while (index <= sheet.getLastRowNum()) {
row = sheet.getRow(index++);
if (row == null) {
continue;
}
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
cell = row.getCell(i);
if (row.getCell(i) != null && (cell.getCellType() == CellType.STRING
|| cell.getCellType() == CellType.NUMERIC)) {
String text = PoiCellUtil.getCellValue(cell);
if (text.contains(FOREACH_COL) || text.contains(FOREACH_COL_VALUE)) {
foreachCol(cell, map, text);
}
}
}
}
}
/**
* 循环列表
*
* @param cell
* @param map
* @param name
* @throws Exception
*/
private void foreachCol(Cell cell, Map map, String name) throws Exception {
boolean isCreate = name.contains(FOREACH_COL_VALUE);
name = name.replace(FOREACH_COL_VALUE, EMPTY).replace(FOREACH_COL, EMPTY).replace(START_STR,
EMPTY);
String[] keys = name.replaceAll("\\s{1,}", " ").trim().split(" ");
Collection> datas = (Collection>) PoiPublicUtil.getParamsValue(keys[0], map);
Object[] columnsInfo = getAllDataColumns(cell, name.replace(keys[0], EMPTY),
mergedRegionHelper);
if (datas == null) {
return;
}
Iterator> its = datas.iterator();
int rowspan = (Integer) columnsInfo[0], colspan = (Integer) columnsInfo[1];
@SuppressWarnings("unchecked")
List | |