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
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/ImageCache.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/ImageCache.java
new file mode 100644
index 0000000..333e07c
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/ImageCache.java
@@ -0,0 +1,99 @@
+/**
+ * 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/WordCache.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/WordCache.java
new file mode 100644
index 0000000..d219f66
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/WordCache.java
@@ -0,0 +1,53 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/manager/FileLoade.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/manager/FileLoade.java
new file mode 100644
index 0000000..c50e217
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/manager/FileLoade.java
@@ -0,0 +1,75 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/manager/POICacheManager.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/manager/POICacheManager.java
new file mode 100644
index 0000000..a08dbbb
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/manager/POICacheManager.java
@@ -0,0 +1,64 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/package-info.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/package-info.java
new file mode 100644
index 0000000..ced2f8d
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/cache/package-info.java
@@ -0,0 +1,11 @@
+/**
+ * 对POI用到的模板进行缓存,进行统一管理,缓存工具暂时使用guava(脱离配置文件)
+ * 缓存方式统一为byte[] 屏蔽文件类型的差异
+ * 缓存获取方式,URL或者URL+index(EXcel的)
+ */
+/**
+ * @author JEECG
+ * @date 2014年2月10日
+ * @version 1.0
+ */
+package org.jeecgframework.poi.cache;
\ No newline at end of file
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/entity/ImageEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/entity/ImageEntity.java
new file mode 100644
index 0000000..a30dd03
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/entity/ImageEntity.java
@@ -0,0 +1,104 @@
+package org.jeecgframework.poi.entity;
+
+/**
+ * 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;
+
+
+ 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelExportUtil.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelExportUtil.java
new file mode 100644
index 0000000..938d80d
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelExportUtil.java
@@ -0,0 +1,243 @@
+/**
+ * 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.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]大数据导出方法【全局】----
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportCheckUtil.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportCheckUtil.java
new file mode 100644
index 0000000..6f13dab
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportCheckUtil.java
@@ -0,0 +1,457 @@
+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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportUtil.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportUtil.java
new file mode 100644
index 0000000..d3aeef7
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelImportUtil.java
@@ -0,0 +1,168 @@
+/**
+ * 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);
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelToHtmlUtil.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelToHtmlUtil.java
new file mode 100644
index 0000000..e9927fd
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/ExcelToHtmlUtil.java
@@ -0,0 +1,67 @@
+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();
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/Excel.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/Excel.java
new file mode 100644
index 0000000..06310c0
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/Excel.java
@@ -0,0 +1,206 @@
+/**
+ * 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";
+
+ /**
+ * 导出类型 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;
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelCollection.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelCollection.java
new file mode 100644
index 0000000..4285e19
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelCollection.java
@@ -0,0 +1,54 @@
+/**
+ * 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;
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelEntity.java
new file mode 100644
index 0000000..6e59673
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelEntity.java
@@ -0,0 +1,49 @@
+/**
+ * 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;
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelIgnore.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelIgnore.java
new file mode 100644
index 0000000..e63791c
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelIgnore.java
@@ -0,0 +1,34 @@
+/**
+ * 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 {
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelTarget.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelTarget.java
new file mode 100644
index 0000000..49191a8
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelTarget.java
@@ -0,0 +1,36 @@
+/**
+ * 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();
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelVerify.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelVerify.java
new file mode 100644
index 0000000..64af075
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/annotation/ExcelVerify.java
@@ -0,0 +1,95 @@
+/**
+ * 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 "数据不符合规范";
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExcelBaseParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExcelBaseParams.java
new file mode 100644
index 0000000..3c84d8a
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExcelBaseParams.java
@@ -0,0 +1,41 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExportParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExportParams.java
new file mode 100644
index 0000000..ef41d25
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ExportParams.java
@@ -0,0 +1,294 @@
+/**
+ * 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,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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ImportParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ImportParams.java
new file mode 100644
index 0000000..599706d
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/ImportParams.java
@@ -0,0 +1,206 @@
+/**
+ * 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java
new file mode 100644
index 0000000..6282389
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/TemplateExportParams.java
@@ -0,0 +1,218 @@
+/**
+ * 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.excel.export.styler.ExcelExportStylerDefaultImpl;
+
+/**
+ * 模板导出参数设置
+ *
+ * @author JEECG
+ * @date 2013-10-17
+ * @version 1.0
+ */
+public class TemplateExportParams extends ExcelBaseParams {
+
+ /**
+ * 输出全部的sheet
+ */
+ private boolean scanAllsheet = false;
+ /**
+ * 模板的路径
+ */
+ private String templateUrl;
+
+ /**
+ * 需要导出的第几个 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;
+ }
+ }
+
+ 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/CellValueType.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/CellValueType.java
new file mode 100644
index 0000000..bbd3ede
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/CellValueType.java
@@ -0,0 +1,28 @@
+/**
+ * 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;
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelStyleType.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelStyleType.java
new file mode 100644
index 0000000..65fbf36
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelStyleType.java
@@ -0,0 +1,48 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelType.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelType.java
new file mode 100644
index 0000000..c4e6b36
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/enmus/ExcelType.java
@@ -0,0 +1,28 @@
+/**
+ * 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 Type
+ *
+ * @author JEECG
+ * @date 2014年12月29日 下午9:08:21
+ */
+public enum ExcelType {
+
+ HSSF, XSSF;
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelBaseEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelBaseEntity.java
new file mode 100644
index 0000000..f67a36e
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelBaseEntity.java
@@ -0,0 +1,184 @@
+/**
+ * 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelCollectionParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelCollectionParams.java
new file mode 100644
index 0000000..fefbc8a
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelCollectionParams.java
@@ -0,0 +1,77 @@
+/**
+ * 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelExportEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelExportEntity.java
new file mode 100644
index 0000000..4d8cc8f
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelExportEntity.java
@@ -0,0 +1,306 @@
+/**
+ * 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;
+
+ 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;
+ }
+
+
+ /**
+ * 获取被合并的子列
+ * @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();
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java
new file mode 100644
index 0000000..449fed2
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelForEachParams.java
@@ -0,0 +1,125 @@
+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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelImportEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelImportEntity.java
new file mode 100644
index 0000000..58d05f5
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelImportEntity.java
@@ -0,0 +1,110 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java
new file mode 100644
index 0000000..619bea6
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelTemplateParams.java
@@ -0,0 +1,66 @@
+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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelVerifyEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelVerifyEntity.java
new file mode 100644
index 0000000..7cdc386
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/ExcelVerifyEntity.java
@@ -0,0 +1,159 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/MergeEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/MergeEntity.java
new file mode 100644
index 0000000..e23b69a
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/params/MergeEntity.java
@@ -0,0 +1,84 @@
+/**
+ * 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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelImportResult.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelImportResult.java
new file mode 100644
index 0000000..835163d
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelImportResult.java
@@ -0,0 +1,79 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelVerifyHanlderResult.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelVerifyHanlderResult.java
new file mode 100644
index 0000000..d24a19d
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/result/ExcelVerifyHanlderResult.java
@@ -0,0 +1,63 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/sax/SaxReadCellEntity.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/sax/SaxReadCellEntity.java
new file mode 100644
index 0000000..36223bb
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/sax/SaxReadCellEntity.java
@@ -0,0 +1,62 @@
+/**
+ * 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 + "]";
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/vo/PoiBaseConstants.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/vo/PoiBaseConstants.java
new file mode 100644
index 0000000..22cf8b8
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/entity/vo/PoiBaseConstants.java
@@ -0,0 +1,43 @@
+/**
+ * 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";
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelBatchExportServer.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelBatchExportServer.java
new file mode 100644
index 0000000..a054b93
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelBatchExportServer.java
@@ -0,0 +1,200 @@
+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.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();
+ }
+
+ @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;
+ }
+}
\ No newline at end of file
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelExportServer.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelExportServer.java
new file mode 100644
index 0000000..67abc39
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/ExcelExportServer.java
@@ -0,0 +1,454 @@
+/**
+ * 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: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.getCause());
+ }
+ }
+
+ 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);
+ 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);
+ throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e.getCause());
+ }
+ }
+
+ /**
+ * 创建表头
+ *
+ * @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);
+ 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);
+ throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e.getCause());
+ }
+ }
+ //update-end---author:liusq Date:20211217 for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExcelExportBase.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExcelExportBase.java
new file mode 100644
index 0000000..e8f8ba8
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExcelExportBase.java
@@ -0,0 +1,768 @@
+/**
+ * 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.ExcelImportUtil;
+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.IOException;
+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");
+
+ //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 {
+ 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]导出表格设置了数字格式导出之后仍然是文本格式,并且无法进行计算
+ }
+ /**
+ * 通过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{
+ 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 {
+ 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】大数据导出方法【全局】----
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExportBase.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExportBase.java
new file mode 100644
index 0000000..5c3bba7
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/base/ExportBase.java
@@ -0,0 +1,552 @@
+/**
+ * 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.jeecgframework.core.util.ApplicationContextUtil;
+import org.jeecgframework.dict.service.AutoPoiDictServiceI;
+import org.jeecgframework.poi.excel.annotation.*;
+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.PoiPublicUtil;
+
+import java.lang.reflect.*;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/**
+ * 导出基础处理,不设计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 {
+ if (Objects.isNull(obj)) {
+ return "";
+ }
+ 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[] {});
+ }
+
+ //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
+
+ //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 < radioVals.length; i++) {
+ String radio = radioVals[i];
+ for (String str : replace) {
+ temp = str.split("_");
+ //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 (radio.equals(temp[1]) || radio.replace("_", "---").equals(temp[1])) {
+ result = result.concat(temp[0]) + ",";
+ break;
+ }
+ //update-end---author:scott Date:20211220 for:[issues/I4MBB3]@Excel dicText字段的值有下划线时,导入功能不能正确解析---
+ }
+ }
+ if (result.equals("")) {
+ result = value;
+ } else {
+ result = result.substring(0, result.length() - 1);
+ }
+ return result;
+ } else {
+ return replaceValue(replace, value);
+ }
+ }
+ //update-end-author:taoyan date:20180731 for:TASK #3038 【bug】Excel 导出多个值(逗号隔开的情况下,导出字典值是ID值)
+
+ /**
+ * 对字段根据用户设置排序
+ */
+ public void sortAllParams(List 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());
+ }
+ 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() < order) {
+ order = entity.getOrderNum();
+ }
+ groupOrder.put(groupName, order);
+ }
+ }
+
+ for (String key : groupAndColumnList.keySet()) {
+ ExcelExportEntity temp = new ExcelExportEntity(key);
+ temp.setColspan(true);
+ temp.setSubColumnList(groupAndColumnList.get(key));
+ temp.setOrderNum(groupOrder.get(key));
+ excelParams.add(temp);
+ }
+ Collections.sort(excelParams);
+ }
+
+ /**
+ * 字典文本中含多个下划线横岗,取最后一个(解决空值情况)
+ *
+ * @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;
+ }
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/AbstractExcelExportStyler.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/AbstractExcelExportStyler.java
new file mode 100644
index 0000000..251f71c
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/AbstractExcelExportStyler.java
@@ -0,0 +1,83 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerBorderImpl.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerBorderImpl.java
new file mode 100644
index 0000000..98b3d5f
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerBorderImpl.java
@@ -0,0 +1,81 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerColorImpl.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerColorImpl.java
new file mode 100644
index 0000000..930f709
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerColorImpl.java
@@ -0,0 +1,89 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerDefaultImpl.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerDefaultImpl.java
new file mode 100644
index 0000000..5052fe8
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/ExcelExportStylerDefaultImpl.java
@@ -0,0 +1,76 @@
+/**
+ * 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;
+ }
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/IExcelExportStyler.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/IExcelExportStyler.java
new file mode 100644
index 0000000..036c6e1
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/styler/IExcelExportStyler.java
@@ -0,0 +1,59 @@
+/**
+ * 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);
+
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java
new file mode 100644
index 0000000..011c065
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/export/template/ExcelExportOfTemplateUtil.java
@@ -0,0 +1,1026 @@
+/**
+ * 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.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.entity.ImageEntity;
+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())) {
+ throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
+ }
+ Workbook wb = null;
+ // step 2. 判断模板的Excel类型,解析模板
+ try {
+ this.teplateParams = params;
+ wb = getCloneWorkBook();
+ // 创建表格样式
+ setExcelExportStyler((IExcelExportStyler) teplateParams.getStyle().getConstructor(Workbook.class).newInstance(wb));
+ // step 3. 解析模板
+ 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));
+
+ oldString = oldString.replace(START_STR + params + END_STR, eval(params, map).toString());
+ }
+ // 如何是数值 类型,就按照数值类型进行设置
+ 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 columns = (List) columnsInfo[2];
+ while (its.hasNext()) {
+ Object t = its.next();
+ setForeachRowCellValue(true, cell.getRow(), cell.getColumnIndex(), t, columns, map,
+ rowspan, colspan, mergedRegionHelper);
+ if (cell.getRow().getCell(cell.getColumnIndex() + colspan) == null) {
+ cell.getRow().createCell(cell.getColumnIndex() + colspan);
+ }
+ cell = cell.getRow().getCell(cell.getColumnIndex() + colspan);
+ }
+ if (isCreate) {
+ cell = cell.getRow().getCell(cell.getColumnIndex() - 1);
+ cell.setCellValue(cell.getStringCellValue() + END_STR);
+ }
+ }
+ /**
+ * 循环迭代创建,遍历row
+ *
+ * @param isCreate
+ * @param row
+ * @param columnIndex
+ * @param t
+ * @param columns
+ * @param map
+ * @param rowspan
+ * @param colspan
+ * @param mergedRegionHelper
+ * @return rowSize, cellSize
+ * @throws Exception
+ */
+ private int[] setForeachRowCellValue(boolean isCreate, Row row, int columnIndex, Object t,
+ List columns, Map map,
+ int rowspan, int colspan,
+ MergedRegionHelper mergedRegionHelper) throws Exception {
+ createRowCellSetStyle(row, columnIndex, columns, rowspan, colspan);
+ //填写数据
+ ExcelForEachParams params;
+ int loopSize = 1;
+ int loopCi = 1;
+ row = row.getSheet().getRow(row.getRowNum() - rowspan + 1);
+ for (int k = 0; k < rowspan; k++) {
+ int ci = columnIndex;
+ row.setHeight(getMaxHeight(k, colspan, columns));
+ for (int i = 0; i < colspan && i < columns.size(); i++) {
+ boolean isNumber = false;
+ params = columns.get(colspan * k + i);
+ tempCreateCellSet.add(row.getRowNum() + "_" + (ci));
+ if (params == null) {
+ continue;
+ }
+ if (StringUtils.isEmpty(params.getName())
+ && StringUtils.isEmpty(params.getConstValue())) {
+ row.getCell(ci).setCellStyle(params.getCellStyle());
+ ci = ci + params.getColspan();
+ continue;
+ }
+ String val;
+ Object obj = null;
+ //是不是常量
+ String tempStr = params.getName();
+ if (StringUtils.isEmpty(params.getName())) {
+ val = params.getConstValue();
+ } else {
+ if (isHasSymbol(tempStr, NUMBER_SYMBOL)) {
+ isNumber = true;
+ tempStr = tempStr.replaceFirst(NUMBER_SYMBOL, "");
+ }
+ map.put(teplateParams.getTempParams(), t);
+ boolean isDict = false;
+ String dict = null;
+ if (isHasSymbol(tempStr, DICT_HANDLER)) {
+ isDict = true;
+ dict = tempStr.substring(tempStr.indexOf(DICT_HANDLER) + 5).split(";")[0];
+ tempStr = tempStr.replaceFirst(DICT_HANDLER, "");
+ tempStr = tempStr.replaceFirst(dict + ";", "");
+ }
+ obj = eval(tempStr, map);
+ if (isDict && !(obj instanceof Collection)) {
+ obj = dictHandler.toName(dict, t, tempStr, obj);
+ }
+ val = obj.toString();
+ }
+ if (obj != null && obj instanceof Collection) {
+ // 需要找到哪一级别是集合 ,方便后面的replace
+ String collectName = evalFindName(tempStr, map);
+ int[] loop = setForEachLoopRowCellValue(row, ci, (Collection) obj, columns,
+ params, map, rowspan, colspan, mergedRegionHelper, collectName);
+ loopSize = Math.max(loopSize, loop[0]);
+ i += loop[1] - 1;
+ ci = loop[2] - params.getColspan();
+ } else if (obj != null && obj instanceof ImageEntity) {
+ ImageEntity img = (ImageEntity) obj;
+ row.getCell(ci).setCellValue("");
+ if (img.getRowspan() > 1 || img.getColspan() > 1) {
+ img.setHeight(0);
+ row.getCell(ci).getSheet().addMergedRegion(new CellRangeAddress(row.getCell(ci).getRowIndex(),
+ row.getCell(ci).getRowIndex() + img.getRowspan() - 1, row.getCell(ci).getColumnIndex(), row.getCell(ci).getColumnIndex() + img.getColspan() - 1));
+ }
+ createImageCell(row.getCell(ci), img.getHeight(), img.getRowspan(), img.getColspan(), img.getUrl(), img.getData());
+ } else if (isNumber && StringUtils.isNotEmpty(val)) {
+ row.getCell(ci).setCellValue(Double.parseDouble(val));
+ } else {
+ try {
+ row.getCell(ci).setCellValue(val);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ if (params.getCellStyle() != null) {
+ row.getCell(ci).setCellStyle(params.getCellStyle());
+ }
+ //如果合并单元格,就把这个单元格的样式和之前的保持一致
+ setMergedRegionStyle(row, ci, params);
+ //合并对应单元格
+ //update-begin-author:liusq---date:20221103--for: [issues/4142]exlce模板导出如果模板中有多个合并单元格的循环表格,第二个表格读取错误 ---
+ boolean isNeedMerge = (params.getRowspan() != 1 || params.getColspan() != 1)
+ && !mergedRegionHelper.isMergedRegion(row.getRowNum() + 1, ci);
+ //update-end-author:liusq---date:20221103--for: [issues/4142]exlce模板导出如果模板中有多个合并单元格的循环表格,第二个表格读取错误 ---
+ if (isNeedMerge) {
+ PoiMergeCellUtil.addMergedRegion(row.getSheet(), row.getRowNum(),
+ row.getRowNum() + params.getRowspan() - 1, ci,
+ ci + params.getColspan() - 1);
+ }
+ ci = ci + params.getColspan();
+ }
+ loopCi = Math.max(loopCi, ci);
+ // 需要把需要合并的单元格合并了 --- 不是集合的栏位合并了
+ if (loopSize > 1) {
+ handlerLoopMergedRegion(row, columnIndex, columns, loopSize);
+ }
+ row = row.getSheet().getRow(row.getRowNum() + 1);
+ }
+ return new int[]{loopSize, loopCi};
+ }
+ /**
+ * 图片类型的Cell
+ */
+ public void createImageCell(Cell cell, double height, int rowspan, int colspan,
+ String imagePath, byte[] data) throws Exception {
+ if (height > cell.getRow().getHeight()) {
+ cell.getRow().setHeight((short) height);
+ }
+ ClientAnchor anchor;
+ if (type.equals(ExcelType.HSSF)) {
+ anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + colspan),
+ cell.getRow().getRowNum() + rowspan);
+ } else {
+ anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + colspan),
+ cell.getRow().getRowNum() + rowspan);
+ }
+ if (StringUtils.isNotEmpty(imagePath)) {
+ data = ImageCache.getImage(imagePath);
+ }
+ if (data != null) {
+ PoiExcelGraphDataUtil.getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
+ cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
+ }
+ }
+ /**
+ * 处理内循环
+ *
+ * @param row
+ * @param columnIndex
+ * @param obj
+ * @param columns
+ * @param params
+ * @param map
+ * @param rowspan
+ * @param colspan
+ * @param mergedRegionHelper
+ * @param collectName
+ * @return [rowNums, columnsNums, ciIndex]
+ * @throws Exception
+ */
+ private int[] setForEachLoopRowCellValue(Row row, int columnIndex, Collection obj, List columns,
+ ExcelForEachParams params, Map map,
+ int rowspan, int colspan,
+ MergedRegionHelper mergedRegionHelper, String collectName) throws Exception {
+
+ //多个一起遍历 -去掉第一层 把所有的数据遍历一遍
+ //STEP 1拿到所有的和当前一样项目的字段
+ List temp = getLoopEachParams(columns, columnIndex, collectName);
+ Iterator> its = obj.iterator();
+ Row tempRow = row;
+ int nums = 0;
+ int ci = columnIndex;
+ while (its.hasNext()) {
+ Object data = its.next();
+ map.put("loop_" + columnIndex, data);
+ int[] loopArr = setForeachRowCellValue(false, tempRow, columnIndex, data, temp, map, rowspan,
+ colspan, mergedRegionHelper);
+ nums += loopArr[0];
+ ci = Math.max(ci, loopArr[1]);
+ map.remove("loop_" + columnIndex);
+ tempRow = createRow(tempRow.getRowNum() + loopArr[0], row.getSheet(), false, rowspan);
+ }
+ for (int i = 0; i < temp.size(); i++) {
+ temp.get(i).setName(temp.get(i).getTempName().pop());
+ //都是集合
+ temp.get(i).setCollectCell(true);
+
+ }
+ return new int[]{nums, temp.size(), ci};
+ }
+ /**
+ * 创建并返回第一个Row
+ *
+ * @param sheet
+ * @param rowIndex
+ * @param isCreate
+ * @param rows
+ * @return
+ */
+ private Row createRow(int rowIndex, Sheet sheet, boolean isCreate, int rows) {
+ for (int i = 0; i < rows; i++) {
+ if (isCreate) {
+ sheet.createRow(rowIndex++);
+ } else if (sheet.getRow(rowIndex++) == null) {
+ sheet.createRow(rowIndex - 1);
+ }
+ }
+ return sheet.getRow(rowIndex - rows);
+ }
+ /**
+ * 根据 当前是集合的信息,把后面整个集合的迭代获取出来,并替换掉集合的前缀方便后面取数
+ *
+ * @param columns
+ * @param columnIndex
+ * @param collectName
+ * @return
+ */
+ private List getLoopEachParams(List columns, int columnIndex, String collectName) {
+ List temp = new ArrayList<>();
+ for (int i = 0; i < columns.size(); i++) {
+ //先置为不是集合
+ columns.get(i).setCollectCell(false);
+ if (columns.get(i) == null || columns.get(i).getName().contains(collectName)) {
+ temp.add(columns.get(i));
+ if (columns.get(i).getTempName() == null) {
+ columns.get(i).setTempName(new Stack<>());
+ }
+ columns.get(i).setCollectCell(true);
+ columns.get(i).getTempName().push(columns.get(i).getName());
+ columns.get(i).setName(columns.get(i).getName().replace(collectName, "loop_" + columnIndex));
+ }
+ }
+ return temp;
+ }
+
+ /**
+ * 设置行样式
+ * @param row
+ * @param columnIndex
+ * @param columns
+ * @param rowspan
+ * @param colspan
+ */
+ private void createRowCellSetStyle(Row row, int columnIndex, List columns,
+ int rowspan, int colspan) {
+ //所有的cell创建一遍
+ for (int i = 0; i < rowspan; i++) {
+ int size = columns.size();
+ for (int j = columnIndex, max = columnIndex + colspan; j < max; j++) {
+ if (row.getCell(j) == null) {
+ row.createCell(j);
+ CellStyle style = row.getRowNum() % 2 == 0
+ ? getStyles(false,
+ size <= j - columnIndex ? null : columns.get(j - columnIndex))
+ : getStyles(true,
+ size <= j - columnIndex ? null : columns.get(j - columnIndex));
+ //返回的styler不为空时才使用,否则使用Excel设置的,更加推荐Excel设置的样式
+ if (style != null) {
+ row.getCell(j).setCellStyle(style);
+ }
+ }
+
+ }
+ if (i < rowspan - 1) {
+ row = row.getSheet().getRow(row.getRowNum() + 1);
+ }
+ }
+ }
+
+ /**
+ * 获取CellStyle
+ * @param isSingle
+ * @param excelForEachParams
+ * @return
+ */
+ private CellStyle getStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
+ return excelExportStyler.getTemplateStyles(isSingle, excelForEachParams);
+ }
+
+ /**
+ * 获取最大高度
+ * @param k
+ * @param colspan
+ * @param columns
+ * @return
+ */
+ private short getMaxHeight(int k, int colspan, List columns) {
+ short high = columns.get(0).getHeight();
+ int n = k;
+ while (n > 0) {
+ if (columns.get(n * colspan).getHeight() == 0) {
+ n--;
+ } else {
+ high = columns.get(n * colspan).getHeight();
+ break;
+ }
+ }
+ return high;
+ }
+
+ private boolean isHasSymbol(String text, String symbol) {
+ return text.startsWith(symbol) || text.contains("{" + symbol)
+ || text.contains(" " + symbol);
+ }
+ /**
+ * 迭代把不是集合的数据都合并了
+ *
+ * @param row
+ * @param columnIndex
+ * @param columns
+ * @param loopSize
+ */
+ private void handlerLoopMergedRegion(Row row, int columnIndex, List columns, int loopSize) {
+ for (int i = 0; i < columns.size(); i++) {
+ if (!columns.get(i).isCollectCell()) {
+ PoiMergeCellUtil.addMergedRegion(row.getSheet(), row.getRowNum(),
+ row.getRowNum() + loopSize - 1, columnIndex,
+ columnIndex + columns.get(i).getColspan() - 1);
+ }
+ columnIndex = columnIndex + columns.get(i).getColspan();
+ }
+ }
+ /**
+ * 设置合并单元格的样式
+ *
+ * @param row
+ * @param ci
+ * @param params
+ */
+ private void setMergedRegionStyle(Row row, int ci, ExcelForEachParams params) {
+ //第一行数据
+ for (int i = 1; i < params.getColspan(); i++) {
+ if (params.getCellStyle() != null) {
+ row.getCell(ci + i).setCellStyle(params.getCellStyle());
+ }
+ }
+ for (int i = 1; i < params.getRowspan(); i++) {
+ for (int j = 0; j < params.getColspan(); j++) {
+ if (params.getCellStyle() != null) {
+ row.getCell(ci + j).setCellStyle(params.getCellStyle());
+ }
+ }
+ }
+ }
+ /**
+ * 获取迭代的数据的值
+ *
+ * @param cell
+ * @param name
+ * @param mergedRegionHelper
+ * @return
+ */
+ private Object[] getAllDataColumns(Cell cell, String name,
+ MergedRegionHelper mergedRegionHelper) {
+ List columns = new ArrayList();
+ cell.setCellValue("");
+ columns.add(getExcelTemplateParams(name.replace(END_STR, EMPTY), cell, mergedRegionHelper));
+ int rowspan = 1, colspan = 1;
+ if (!name.contains(END_STR)) {
+ int index = cell.getColumnIndex();
+ //保存col 的开始列
+ int startIndex = cell.getColumnIndex();
+ Row row = cell.getRow();
+ while (index < row.getLastCellNum()) {
+ int colSpan = columns.get(columns.size() - 1) != null
+ ? columns.get(columns.size() - 1).getColspan() : 1;
+ index += colSpan;
+
+
+ for (int i = 1; i < colSpan; i++) {
+ //添加合并的单元格,这些单元可能不是空,但是没有值,所以也需要跳过
+ columns.add(null);
+ continue;
+ }
+ cell = row.getCell(index);
+ //可能是合并的单元格
+ if (cell == null) {
+ //读取是判断,跳过
+ columns.add(null);
+ continue;
+ }
+ String cellStringString;
+ try {//不允许为空 便利单元格必须有结尾和值
+ cellStringString = cell.getStringCellValue();
+ if (StringUtils.isBlank(cellStringString) && colspan + startIndex <= index) {
+ throw new ExcelExportException("for each 当中存在空字符串,请检查模板");
+ } else if (StringUtils.isBlank(cellStringString)
+ && colspan + startIndex > index) {
+ //读取是判断,跳过,数据为空,但是不是第一次读这一列,所以可以跳过
+ columns.add(new ExcelForEachParams(null, cell.getCellStyle(), (short) 0));
+ continue;
+ }
+ } catch (Exception e) {
+ throw new ExcelExportException(ExcelExportEnum.TEMPLATE_ERROR, e);
+ }
+ //把读取过的cell 置为空
+ cell.setCellValue("");
+ if (cellStringString.contains(END_STR)) {
+ columns.add(getExcelTemplateParams(cellStringString.replace(END_STR, EMPTY),
+ cell, mergedRegionHelper));
+ //补全缺失的cell(合并单元格后面的)
+ int lastCellColspan = columns.get(columns.size() - 1).getColspan();
+ for (int i = 1; i < lastCellColspan; i++) {
+ //添加合并的单元格,这些单元可能不是空,但是没有值,所以也需要跳过
+ columns.add(null);
+ }
+ break;
+ } else if (cellStringString.contains(WRAP)) {
+ columns.add(getExcelTemplateParams(cellStringString.replace(WRAP, EMPTY), cell,
+ mergedRegionHelper));
+ //发现换行符,执行换行操作
+ colspan = index - startIndex + 1;
+ index = startIndex - columns.get(columns.size() - 1).getColspan();
+ row = row.getSheet().getRow(row.getRowNum() + 1);
+ rowspan++;
+ } else {
+ columns.add(getExcelTemplateParams(cellStringString.replace(WRAP, EMPTY), cell,
+ mergedRegionHelper));
+ }
+ }
+ }
+ colspan = 0;
+ for (int i = 0; i < columns.size(); i++) {
+ colspan += columns.get(i) != null ? columns.get(i).getColspan() : 0;
+ }
+ colspan = colspan / rowspan;
+ return new Object[]{rowspan, colspan, columns};
+ }
+ /**
+ * 获取模板参数
+ *
+ * @param name
+ * @param cell
+ * @param mergedRegionHelper
+ * @return
+ */
+ private ExcelForEachParams getExcelTemplateParams(String name, Cell cell,
+ MergedRegionHelper mergedRegionHelper) {
+ name = name.trim();
+ ExcelForEachParams params = new ExcelForEachParams(name, cell.getCellStyle(),
+ cell.getRow().getHeight());
+ //判断是不是常量
+ if (name.startsWith(CONST) && name.endsWith(CONST)) {
+ params.setName(null);
+ params.setConstValue(name.substring(1, name.length() - 1));
+ }
+ //判断是不是空
+ if (NULL.equals(name)) {
+ params.setName(null);
+ params.setConstValue(EMPTY);
+ }
+ //获取合并单元格的数据
+ if (mergedRegionHelper.isMergedRegion(cell.getRowIndex() + 1, cell.getColumnIndex())) {
+ Integer[] colAndrow = mergedRegionHelper.getRowAndColSpan(cell.getRowIndex() + 1,
+ cell.getColumnIndex());
+ params.setRowspan(colAndrow[0]);
+ params.setColspan(colAndrow[1]);
+ }
+ return params;
+ }
+ //-----------------update-end-author:liusq---date:20220527--for: 以上方法是模板导出列循环功能新增的方法 ---
+}
diff --git a/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/graph/builder/ExcelChartBuildService.java b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/graph/builder/ExcelChartBuildService.java
new file mode 100644
index 0000000..0346c55
--- /dev/null
+++ b/autopoi/autopoi/src/main/java/org/jeecgframework/poi/excel/graph/builder/ExcelChartBuildService.java
@@ -0,0 +1,263 @@
+///**
+// *
+// */
+//package org.jeecgframework.poi.excel.graph.builder;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.poi.ss.usermodel.Chart;
+//import org.apache.poi.ss.usermodel.ClientAnchor;
+//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.ss.usermodel.charts.AxisCrosses;
+//import org.apache.poi.ss.usermodel.charts.AxisPosition;
+//import org.apache.poi.ss.usermodel.charts.ChartAxis;
+//import org.apache.poi.ss.usermodel.charts.ChartDataSource;
+//import org.apache.poi.ss.usermodel.charts.ChartLegend;
+//import org.apache.poi.ss.usermodel.charts.DataSources;
+//import org.apache.poi.ss.usermodel.charts.LegendPosition;
+//import org.apache.poi.ss.usermodel.charts.LineChartData;
+//import org.apache.poi.ss.usermodel.charts.ScatterChartData;
+//import org.apache.poi.ss.usermodel.charts.ValueAxis;
+//import org.apache.poi.ss.util.CellRangeAddress;
+//
+//import org.jeecgframework.poi.excel.graph.constant.ExcelGraphElementType;
+//import org.jeecgframework.poi.excel.graph.constant.ExcelGraphType;
+//import org.jeecgframework.poi.excel.graph.entity.ExcelGraph;
+//import org.jeecgframework.poi.excel.graph.entity.ExcelGraphElement;
+//import org.jeecgframework.poi.excel.graph.entity.ExcelTitleCell;
+//import org.jeecgframework.poi.util.PoiCellUtil;
+//import org.jeecgframework.poi.util.PoiExcelGraphDataUtil;
+//
+///**
+// * @Description
+// * @author liusq
+// * @data 2022年1月4号
+// */
+//public class ExcelChartBuildService
+//{
+// /**
+// *
+// * @param workbook
+// * @param graphList
+// * @param build 通过实时数据行来重新计算图形定义
+// * @param append
+// */
+// public static void createExcelChart(Workbook workbook, List graphList, Boolean build, Boolean append)
+// {
+// if(workbook!=null&&graphList!=null){
+// //设定默认第一个sheet为数据项
+// Sheet dataSouce=workbook.getSheetAt(0);
+// if(dataSouce!=null){
+// buildTitle(dataSouce,graphList);
+//
+// if(build){
+// PoiExcelGraphDataUtil.buildGraphData(dataSouce, graphList);
+// }
+// if(append){
+// buildExcelChart(dataSouce, dataSouce, graphList);
+// }else{
+// Sheet sheet=workbook.createSheet("图形界面");
+// buildExcelChart(dataSouce, sheet, graphList);
+// }
+// }
+//
+// }
+// }
+//
+// /**
+// * 构建基础图形
+// * @param drawing
+// * @param anchor
+// * @param dataSourceSheet
+// * @param graph
+// */
+// private static void buildExcelChart(Drawing drawing,ClientAnchor anchor,Sheet dataSourceSheet,ExcelGraph graph){
+// Chart chart = null;
+// // TODO 图表没有成功
+// //drawing.createChart(anchor);
+// ChartLegend legend = chart.getOrCreateLegend();
+// legend.setPosition(LegendPosition.TOP_RIGHT);
+//
+// ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
+// ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
+// leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
+// ExcelGraphElement categoryElement=graph.getCategory();
+//
+// ChartDataSource categoryChart;
+// if(categoryElement!=null&& categoryElement.getElementType().equals(ExcelGraphElementType.STRING_TYPE)){
+// categoryChart=DataSources.fromStringCellRange(dataSourceSheet, new CellRangeAddress(categoryElement.getStartRowNum(),categoryElement.getEndRowNum(),categoryElement.getStartColNum(),categoryElement.getEndColNum()));
+// }else{
+// categoryChart=DataSources.fromNumericCellRange(dataSourceSheet, new CellRangeAddress(categoryElement.getStartRowNum(),categoryElement.getEndRowNum(),categoryElement.getStartColNum(),categoryElement.getEndColNum()));
+// }
+//
+// List valueList=graph.getValueList();
+// List> chartValueList= new ArrayList<>();
+// if(valueList!=null&&valueList.size()>0){
+// for(ExcelGraphElement ele:valueList){
+// ChartDataSource source=DataSources.fromNumericCellRange(dataSourceSheet, new CellRangeAddress(ele.getStartRowNum(),ele.getEndRowNum(),ele.getStartColNum(),ele.getEndColNum()));
+// chartValueList.add(source);
+// }
+// }
+//
+// if(graph.getGraphType().equals(ExcelGraphType.LINE_CHART)){
+// LineChartData data = chart.getChartDataFactory().createLineChartData();
+// buildLineChartData(data, categoryChart, chartValueList, graph.getTitle());
+// chart.plot(data, bottomAxis, leftAxis);
+// }
+// else
+// {
+// ScatterChartData data=chart.getChartDataFactory().createScatterChartData();
+// buildScatterChartData(data, categoryChart, chartValueList,graph.getTitle());
+// chart.plot(data, bottomAxis, leftAxis);
+// }
+// }
+//
+//
+//
+//
+// /**
+// * 构建多个图形对象
+// * @param dataSourceSheet
+// * @param tragetSheet
+// * @param graphList
+// */
+// private static void buildExcelChart(Sheet dataSourceSheet,Sheet tragetSheet,List graphList){
+// int len=graphList.size();
+// if(len==1)
+// {
+// buildExcelChart(dataSourceSheet, tragetSheet, graphList.get(0));
+// }
+// else
+// {
+// int drawStart=0;
+// int drawEnd=20;
+// Drawing drawing = PoiExcelGraphDataUtil.getDrawingPatriarch(tragetSheet);
+// for(int i=0;i0){
+//
+// }else{
+// for(int i=0;i graphList){
+// if(graphList!=null&&graphList.size()>0){
+// for(ExcelGraph graph:graphList){
+// if(graph!=null)
+// {
+// buildTitle(sheet, graph);
+// }
+// }
+// }
+// }
+//
+// /**
+// *
+// * @param data
+// * @param categoryChart
+// * @param chartValueList
+// * @param title
+// */
+// private static void buildLineChartData(LineChartData data,ChartDataSource categoryChart,List | |