This commit is contained in:
ls
2025-02-23 12:03:06 +08:00
parent d69092f729
commit a5697c2ba8
130 changed files with 16414 additions and 0 deletions

73
autopoi/autopoi/pom.xml Normal file
View File

@@ -0,0 +1,73 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>autopoi-parent</artifactId>
<version>3.7.0</version>
</parent>
<artifactId>autopoi</artifactId>
<dependencies>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<exclusions>
<exclusion>
<artifactId>xml-apis</artifactId>
<groupId>xml-apis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.poi</groupId>-->
<!-- <artifactId>poi-ooxml-schemas</artifactId>-->
<!-- </dependency>-->
<!-- Sax 读入的时候使用 -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</dependency>
<!-- Word 时候用到 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
</dependency>
<!-- google 工具类 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--日志 -->
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<optional>true</optional>
</dependency>
<!--spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,25 @@
package org.jeecgframework.core.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
*
* @author 张代浩
*
*/
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext context)
throws BeansException {
this.context = context;
}
public static ApplicationContext getContext() {
return context;
}
}

View File

@@ -0,0 +1,23 @@
package org.jeecgframework.dict.service;
/**
* 描述:
* @authorscott
* @since2017-4-12 下午04:58:15
* @version:1.0
*/
public interface AutoPoiDictServiceI{
/**
* 方法描述: 查询数据字典
* 作 者: yiming.zhang
* 日 期: 2014年5月11日-下午4:22:42
* @param dicTable
* @param dicCode
* @param dicText
* @return
* 返回类型: List<DictEntity>
*/
public String[] queryDict(String dicTable,String dicCode, String dicText);
}

View File

@@ -0,0 +1,99 @@
/**
* 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 org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.jeecgframework.poi.cache.manager.POICacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
/**
* Excel类型的缓存
*
* @author JEECG
* @date 2014年2月11日
* @version 1.0
*/
public final class ExcelCache {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelCache.class);
public static Workbook getWorkbook(String url, Integer[] sheetNums, boolean needAll) {
InputStream is = null;
List<Integer> sheetList = Arrays.asList(sheetNums);
try {
is = POICacheManager.getFile(url);
Workbook wb = WorkbookFactory.create(is);
// 删除其他的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 {
is.close();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
return null;
}
//update-begin-author:wangshuai date:20200730 for:jar 包上传到服务器后 autopoi 读取不到excel模版文件 #1505
public static Workbook getWorkbookByTemplate(String url, Integer[] sheetNums, boolean needAll) {
List<Integer> 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
}

View File

@@ -0,0 +1,99 @@
/**
* Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com)
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<String, byte[]> loadingCache;
static {
loadingCache = CacheBuilder.newBuilder().expireAfterWrite(7, TimeUnit.DAYS).maximumSize(50).build(new CacheLoader<String, byte[]>() {
@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;
}
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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<ExcelExportEntity> 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<Map<String, Object>> list, ExcelType type) {
Workbook workbook;
if (ExcelType.HSSF.equals(type)) {
workbook = new HSSFWorkbook();
} else {
workbook = new XSSFWorkbook();
}
for (Map<String, Object> 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<String, Object> map) {
return new ExcelExportOfTemplateUtil().createExcleByTemplate(params, pojoClass, dataSet, map);
}
/**
* 导出文件通过模板解析只有模板,没有集合
*
* @param params
* 导出参数类
* @param map
* 模板集合
* @return
*/
public static Workbook exportExcel(TemplateExportParams params, Map<String, Object> 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<Workbook> 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<Workbook> exportBigExcel(ExportParams entity, List<ExcelExportEntity> 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<ExcelExportEntity> 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]大数据导出方法【全局】----
}

View File

@@ -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.880%)即可通过验证
*/
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<Row> 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<Integer, String> titlemap = null;
try {
titlemap = getTitleMap(sheet, params);
} catch (Exception e) {
e.printStackTrace();
}
Set<Integer> 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<String, ExcelImportEntity> excelParams = new HashMap<String, ExcelImportEntity>();
List<ExcelCollectionParams> excelCollection = new ArrayList<ExcelCollectionParams>();
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(successNum<errorNum){
return false;
}else if(successNum>errorNum){
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<screenRate){
return false;
}else{
return true;
}
}else{
return true;
}
}else if(successNum==errorNum){
return false;
}else{
return false;
}
} catch (ExcelImportException e) {
if (!e.getType().equals(ExcelImportEnum.VERIFY_ERROR)) {
throw new ExcelImportException(e.getType(), e);
}
}
}
}
return null;
}
/**
* 获取文件名称标题
* @Author JEECG
* @date 20201023
* @throws Exception
*/
private static Map<Integer, String> getTitleMap(Sheet sheet, ImportParams params) throws Exception {
Map<Integer, String> titlemap = new HashMap<Integer, String>();
Iterator<Cell> 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<String, ExcelImportEntity> excelParams, List<ExcelCollectionParams> excelCollection, Class<?> pojoClass, List<Method> 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<String, ExcelImportEntity> 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<Method> newMethods = new ArrayList<Method>();
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<String, ExcelImportEntity> temp, List<Method> 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<Method> 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<String> 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<Method> getMethods, Map<String, ExcelImportEntity> 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<Method> newMethods = new ArrayList<Method>();
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;
}
}

View File

@@ -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 <T> List<T> importExcel(File file, Class<?> pojoClass, ImportParams params) {
FileInputStream in = null;
List<T> 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 <T> List<T> 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 <T> ExcelImportResult<T> 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 <T> ExcelImportResult<T> 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 <T> List<T> 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 <T> List<T> importExcelBySax(InputStream inputstream, ISaxRowRead rowRead) {
return new SaxReadExcel().readExcel(inputstream, null, null, rowRead, null);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 {
}

View File

@@ -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();
}

View File

@@ -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 "数据不符合规范";
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<String> ignoreHeaderList;
/**
* 指定导入的sheetName
*/
private String sheetName;
/**
* 图片列 集合
*/
private List<String> 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<String> getImageList() {
return imageList;
}
public void setImageList(List<String> imageList) {
this.imageList = imageList;
}
public List<String> getIgnoreHeaderList() {
return ignoreHeaderList;
}
public void setIgnoreHeaderList(List<String> 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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<Method> methods;
public String getDatabaseFormat() {
return databaseFormat;
}
public String getFormat() {
return format;
}
public Method getMethod() {
return method;
}
public List<Method> 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<Method> 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;
}
}

View File

@@ -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<String, ExcelImportEntity> excelParams;
public Map<String, ExcelImportEntity> getExcelParams() {
return excelParams;
}
public String getName() {
return name;
}
public Class<?> getType() {
return type;
}
public void setExcelParams(Map<String, ExcelImportEntity> 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;
}
}

View File

@@ -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<ExcelExportEntity> {
/**
* 如果是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<String> subColumnList;
/**
* 父表头的名称
*/
private String groupName;
/**
* 是否隐藏列
*/
private boolean isColumnHidden;
private List<ExcelExportEntity> 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<ExcelExportEntity> 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<ExcelExportEntity> 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<String> getSubColumnList() {
return subColumnList;
}
public void setSubColumnList(List<String> 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<ExcelExportEntity> initSubExportEntity(List<ExcelExportEntity> all){
List<ExcelExportEntity> sub = new ArrayList<ExcelExportEntity>();
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();
}
}

View File

@@ -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<String> 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<String> getTempName() {
return tempName;
}
public void setTempName(Stack<String> tempName) {
this.tempName = tempName;
}
}

View File

@@ -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<ExcelImportEntity> list;
public String getClassType() {
return classType;
}
public String getCollectionName() {
return collectionName;
}
public List<ExcelImportEntity> 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<ExcelImportEntity> 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<String> 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<String> 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<String> relyList) {
this.relyList = relyList;
}
public void setStartRow(int startRow) {
this.startRow = startRow;
}
public void setText(String text) {
this.text = text;
}
}

View File

@@ -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<T> {
/**
* 结果集
*/
private List<T> list;
/**
* 是否存在校验失败
*/
private boolean verfiyFail;
/**
* 数据源
*/
private Workbook workbook;
public ExcelImportResult() {
}
public ExcelImportResult(List<T> list, boolean verfiyFail, Workbook workbook) {
this.list = list;
this.verfiyFail = verfiyFail;
this.workbook = workbook;
}
public List<T> getList() {
return list;
}
public Workbook getWorkbook() {
return workbook;
}
public boolean isVerfiyFail() {
return verfiyFail;
}
public void setList(List<T> list) {
this.list = list;
}
public void setVerfiyFail(boolean verfiyFail) {
this.verfiyFail = verfiyFail;
}
public void setWorkbook(Workbook workbook) {
this.workbook = workbook;
}
}

View File

@@ -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;
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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";
}

View File

@@ -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<Workbook> {
private final static Logger LOGGER = LoggerFactory.getLogger(ExcelBatchExportServer.class);
private Workbook workbook;
private Sheet sheet;
private List<ExcelExportEntity> excelParams;
private ExportParams entity;
private int titleHeight;
private Drawing patriarch;
private short rowHeight;
private int index;
public void init(ExportParams entity, Class<?> pojoClass) {
List<ExcelExportEntity> excelParams = createExcelExportEntityList(entity, pojoClass);
init(entity, excelParams);
}
/**
* 初始化数据
* @param entity 导出参数
* @param excelParams
*/
public void init(ExportParams entity, List<ExcelExportEntity> 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<ExcelExportEntity> createExcelExportEntityList(ExportParams entity, Class<?> pojoClass) {
try {
List<ExcelExportEntity> excelParams = new ArrayList<ExcelExportEntity>();
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<ExcelExportEntity> excelParams) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Excel export start ,List<ExcelExportEntity> 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<ExcelExportEntity> 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<ExcelExportEntity> excelParams = new ArrayList<ExcelExportEntity>();
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<Object> 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<Workbook> 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;
}
}

View File

@@ -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<ExcelExportEntity> 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<ExcelExportEntity> excelParams = new ArrayList<ExcelExportEntity>();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
// 得到所有字段
Field fileds[] = PoiPublicUtil.getClassFields(pojoClass);
//---update-begin-----autor:scott------date:20191016-------for:导出字段支持自定义--------
//支持自定义导出字段
if (exportFields != null) {
List<Field> list = new ArrayList<Field>(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<Object> tempList = new ArrayList<Object>();
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<ExcelExportEntity> 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<ExcelExportEntity> excelParams = new ArrayList<ExcelExportEntity>();
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<Object> tempList = new ArrayList<Object>();
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<ExcelExportEntity> 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<String> 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<ExcelExportEntity> 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<ExcelExportEntity> 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<ExcelExportEntity> 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<ExcelExportEntity> excelParams = new ArrayList<ExcelExportEntity>();
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<Object> tempList = new ArrayList<Object>();
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】大数据导出方法【全局】----
}

View File

@@ -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<Integer, Double> statistics = new HashMap<Integer, Double>();
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<ExcelExportEntity> 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<String,Object> subColumnMap = new HashMap<>();
List<String> 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 forTASK #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 forTASK #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-------authorliusq---data2021-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-------authorliusq---data2021-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<ExcelExportEntity> 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 forTASK #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 forTASK #2372 【excel】AutoPoi 导出类型type增加数字类型--------------------
}
}
//update-begin--Author:xuelin Date:20171018 forTASK #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 forTASK #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<Integer> 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<ExcelExportEntity> excelParams) {
int length = -1;// 从0开始计算单元格的
for (ExcelExportEntity entity : excelParams) {
//update-begin---author:liusq Date:20200909 forAutoPoi多表头导出会多出一列空白列 #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 forAutoPoi多表头导出会多出一列空白列 #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<Integer, int[]> getMergeDataMap(List<ExcelExportEntity> excelParams) {
Map<Integer, int[]> mergeMap = new HashMap<Integer, int[]>();
// 设置参数顺序,为之后合并单元格做准备
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<ExcelExportEntity> excelParams, int titleHeight) {
Map<Integer, int[]> mergeMap = getMergeDataMap(excelParams);
PoiMergeCellUtil.mergeCells(sheet, mergeMap, titleHeight);
}
public void setCellWith(List<ExcelExportEntity> excelParams, Sheet sheet) {
int index = 0;
for (int i = 0; i < excelParams.size(); i++) {
if (excelParams.get(i).getList() != null) {
List<ExcelExportEntity> 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<ExcelExportEntity> excelParams, Sheet sheet) {
int index = 0;
for (int i = 0; i < excelParams.size(); i++) {
if (excelParams.get(i).getList() != null) {
List<ExcelExportEntity> 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<ExcelExportEntity> 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<ExcelExportEntity> 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】大数据导出方法【全局】----
}

View File

@@ -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<String> needHanlderList;
/**
* 创建导出实体对象
*
* @param field
* @param targetId
* @param pojoClass
* @param getMethods
* @return
* @throws Exception
*/
private ExcelExportEntity createExcelExportEntity(Field field, String targetId, Class<?> pojoClass, List<Method> 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<Method> newMethods = new ArrayList<Method>();
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<ExcelExportEntity> excelParams,
Class<?> pojoClass, List<Method> getMethods) throws Exception {
List<String> 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<ExcelExportEntity> list = new ArrayList<ExcelExportEntity>();
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<Method> newMethods = new ArrayList<Method>();
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<ExcelExportEntity> list = new ArrayList<ExcelExportEntity>();
// 这里有个设计的坑导出的时候最后一个参数是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 date20180731 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 date20180731 for:TASK #3038 【bug】Excel 导出多个值逗号隔开的情况下导出字典值是ID值
//update-begin-author:liusq date20210127 for: 两个数值相等,就证明处理翻译失败的情况
if (oldVal.equals(value)) {
}
//update-end-author:liusq date20210127 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<Method> 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<ExcelExportEntity> 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 date20210127 for:字符串截取修改
temp = getValueArr(str);
//update-end-author:liusq date20210127 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 date20180731 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 date20210127 for:字符串截取修改
temp = getValueArr(str);
//update-end-author:liusq date20210127 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 date20180731 for:TASK #3038 【bug】Excel 导出多个值逗号隔开的情况下导出字典值是ID值
/**
* 对字段根据用户设置排序
*/
public void sortAllParams(List<ExcelExportEntity> excelParams) {
Collections.sort(excelParams);
for (ExcelExportEntity entity : excelParams) {
if (entity.getList() != null) {
Collections.sort(entity.getList());
}
}
}
/**
* 循环ExcelExportEntity集合 附加配置信息<br>
* 1.列排序<br>
* 2.读取图片根路径设置(如果有字段是图片类型 并且存储在本地 则设置磁盘路径获取全地址导出)<br>
* 3.多表头配置(仅限于单表 会走这个逻辑处理)
*/
public void reConfigExcelExportParams(List<ExcelExportEntity> excelParams, ExportParams exportParams) {
Set<String> NameSet = new HashSet<String>();
Map<String, List<String>> groupAndColumnList = new HashMap<String, List<String>>();
Map<String, Integer> 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<String> ls = groupAndColumnList.get(groupName);
if (ls == null) {
ls = new ArrayList<String>();
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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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<ExcelGraph> 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<ExcelGraphElement> valueList=graph.getValueList();
// List<ChartDataSource<Number>> chartValueList= new ArrayList<>();
// if(valueList!=null&&valueList.size()>0){
// for(ExcelGraphElement ele:valueList){
// ChartDataSource<Number> 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<ExcelGraph> 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;i<len;i++){
// ExcelGraph graph=graphList.get(i);
// ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, drawStart, 15, drawEnd);
// buildExcelChart(drawing, anchor, dataSourceSheet, graph);
// drawStart=drawStart+drawEnd;
// drawEnd=drawEnd+drawEnd;
// }
// }
// }
//
//
//
//
// /**
// * 构建图形对象
// * @param dataSourceSheet
// * @param tragetSheet
// * @param graph
// */
// private static void buildExcelChart(Sheet dataSourceSheet,Sheet tragetSheet,ExcelGraph graph){
// Drawing drawing = PoiExcelGraphDataUtil.getDrawingPatriarch(tragetSheet);
// ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 0, 15, 20);
// buildExcelChart(drawing, anchor, dataSourceSheet, graph);
// }
//
//
//
//
// /**
// * 构建Title
// * @param sheet
// * @param graph
// */
// private static void buildTitle(Sheet sheet,ExcelGraph graph){
// int cellTitleLen=graph.getTitleCell().size();
// int titleLen=graph.getTitle().size();
// if(titleLen>0){
//
// }else{
// for(int i=0;i<cellTitleLen;i++){
// ExcelTitleCell titleCell=graph.getTitleCell().get(i);
// if(titleCell!=null){
// graph.getTitle().add(PoiCellUtil.getCellValue(sheet,titleCell.getRow(),titleCell.getCol()));
// }
// }
// }
// }
//
// /**
// * 构建Title
// * @param sheet
// * @param graphList
// */
// private static void buildTitle(Sheet sheet,List<ExcelGraph> 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<ChartDataSource<Number>> chartValueList,List<String> title){
// if(chartValueList.size()==title.size())
// {
// int len=title.size();
// for(int i=0;i<len;i++){
// //TODO 更新版本
// //data.addSerie(categoryChart, chartValueList.get(i)).setTitle(title.get(i));
// }
// }
// else
// {
// int i=0;
// for(ChartDataSource<Number> source:chartValueList){
// String temp_title=title.get(i);
// if(StringUtils.isNotBlank(temp_title)){
// //data.addSerie(categoryChart, source).setTitle(_title);
// }else{
// //data.addSerie(categoryChart, source);
// }
// }
// }
// }
//
// /**
// *
// * @param data
// * @param categoryChart
// * @param chartValueList
// * @param title
// */
// private static void buildScatterChartData(ScatterChartData data,ChartDataSource categoryChart,List<ChartDataSource<Number>> chartValueList,List<String> title){
// if(chartValueList.size()==title.size())
// {
// int len=title.size();
// for(int i=0;i<len;i++){
// data.addSerie(categoryChart, chartValueList.get(i)).setTitle(title.get(i));
// }
// }
// else
// {
// int i=0;
// for(ChartDataSource<Number> source:chartValueList){
// String temp_title=title.get(i);
// if(StringUtils.isNotBlank(temp_title)){
// data.addSerie(categoryChart, source).setTitle(temp_title);
// }else{
// data.addSerie(categoryChart, source);
// }
// }
// }
// }
//
//
//}

View File

@@ -0,0 +1,15 @@
/**
*
*/
package org.jeecgframework.poi.excel.graph.constant;
/**
* @Description 定义元素类型
* @author liusq
* @date 2022年1月4号
*/
public interface ExcelGraphElementType
{
public static final Integer STRING_TYPE =1;
public static final Integer NUMERIC_TYPE =2;
}

View File

@@ -0,0 +1,16 @@
/**
*
*/
package org.jeecgframework.poi.excel.graph.constant;
/**
* @Description 定义图形类型
* @author liusq
* @date 2022年1月4号
*/
public interface ExcelGraphType
{
public static final Integer LINE_CHART =1;
public static final Integer SCATTER_CHART =2;
}

View File

@@ -0,0 +1,20 @@
/**
*
*/
package org.jeecgframework.poi.excel.graph.entity;
import java.util.List;
/**
* @Description Excel 图形构造服务
* @author liusq
* @date 2022年1月4号
*/
public interface ExcelGraph
{
public ExcelGraphElement getCategory();
public List<ExcelGraphElement> getValueList();
public Integer getGraphType();
public List<ExcelTitleCell> getTitleCell();
public List<String> getTitle();
}

View File

@@ -0,0 +1,74 @@
/**
*
*/
package org.jeecgframework.poi.excel.graph.entity;
import org.jeecgframework.poi.excel.graph.constant.ExcelGraphType;
import java.util.ArrayList;
import java.util.List;
/**
* @Description Excel 图形构造服务
* @author liusq
* @date 2022年1月4号
*/
public class ExcelGraphDefined implements ExcelGraph
{
private ExcelGraphElement category;
public List<ExcelGraphElement> valueList= new ArrayList<>();
public List<ExcelTitleCell> titleCell= new ArrayList<>();
private Integer graphType= ExcelGraphType.LINE_CHART;
public List<String> title= new ArrayList<>();
@Override
public ExcelGraphElement getCategory()
{
return category;
}
public void setCategory(ExcelGraphElement category)
{
this.category = category;
}
@Override
public List<ExcelGraphElement> getValueList()
{
return valueList;
}
public void setValueList(List<ExcelGraphElement> valueList)
{
this.valueList = valueList;
}
@Override
public Integer getGraphType()
{
return graphType;
}
public void setGraphType(Integer graphType)
{
this.graphType = graphType;
}
@Override
public List<ExcelTitleCell> getTitleCell()
{
return titleCell;
}
public void setTitleCell(List<ExcelTitleCell> titleCell)
{
this.titleCell = titleCell;
}
@Override
public List<String> getTitle()
{
return title;
}
public void setTitle(List<String> title)
{
this.title = title;
}
}

View File

@@ -0,0 +1,63 @@
/**
*
*/
package org.jeecgframework.poi.excel.graph.entity;
import org.jeecgframework.poi.excel.graph.constant.ExcelGraphElementType;
/**
* @Description Excel 图形构造服务
* @author liusq
* @date 2022年1月4号
*/
public class ExcelGraphElement
{
private Integer startRowNum;
private Integer endRowNum;
private Integer startColNum;
private Integer endColNum;
private Integer elementType= ExcelGraphElementType.STRING_TYPE;
public Integer getStartRowNum()
{
return startRowNum;
}
public void setStartRowNum(Integer startRowNum)
{
this.startRowNum = startRowNum;
}
public Integer getEndRowNum()
{
return endRowNum;
}
public void setEndRowNum(Integer endRowNum)
{
this.endRowNum = endRowNum;
}
public Integer getStartColNum()
{
return startColNum;
}
public void setStartColNum(Integer startColNum)
{
this.startColNum = startColNum;
}
public Integer getEndColNum()
{
return endColNum;
}
public void setEndColNum(Integer endColNum)
{
this.endColNum = endColNum;
}
public Integer getElementType()
{
return elementType;
}
public void setElementType(Integer elementType)
{
this.elementType = elementType;
}
}

View File

@@ -0,0 +1,43 @@
/**
*
*/
package org.jeecgframework.poi.excel.graph.entity;
/**
* @Description Excel 图形构造服务
* @author liusq
* @date 2022年1月4号
*/
public class ExcelTitleCell
{
private Integer row;
private Integer col;
public ExcelTitleCell(){
}
public ExcelTitleCell(Integer row,Integer col){
this.row=row;
this.col=col;
}
public Integer getRow()
{
return row;
}
public void setRow(Integer row)
{
this.row = row;
}
public Integer getCol()
{
return col;
}
public void setCol(Integer col)
{
this.col = col;
}
}

View File

@@ -0,0 +1,9 @@
/**
*
*/
/**
* @Description Excel 图形构造服务
* @author liusq
* @date 2022年1月4号
*/
package org.jeecgframework.poi.excel.graph;

View File

@@ -0,0 +1,191 @@
package org.jeecgframework.poi.excel.html;
import java.util.Formatter;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecgframework.poi.excel.html.helper.CellValueHelper;
import org.jeecgframework.poi.excel.html.helper.MergedRegionHelper;
import org.jeecgframework.poi.excel.html.helper.StylerHelper;
/**
* Excel转换成Html 服务
*
* @author JEECG
* @date 2015年5月10日 上午11:41:15
*/
public class ExcelToHtmlServer {
private Workbook wb;
private int sheetNum;
private int cssRandom;
/* 是不是完成界面 */
private boolean completeHTML;
private Formatter out;
/* 已经完成范围处理 */
private boolean gotBounds;
private int firstColumn;
private int endColumn;
private static final String COL_HEAD_CLASS = "colHeader";
// private static final String ROW_HEAD_CLASS = "rowHeader";
private static final String DEFAULTS_CLASS = "excelDefaults";
public ExcelToHtmlServer(Workbook wb, boolean completeHTML, int sheetNum) {
this.wb = wb;
this.completeHTML = completeHTML;
this.sheetNum = sheetNum;
cssRandom = (int) Math.ceil(Math.random() * 1000);
}
public String printPage() {
try {
ensureOut();
if (completeHTML) {
out.format("<!DOCTYPE HTML>%n");
out.format("<html>%n");
out.format("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">%n");
out.format("<head>%n");
}
new StylerHelper(wb, out, sheetNum, cssRandom);
if (completeHTML) {
out.format("</head>%n");
out.format("<body>%n");
}
print();
if (completeHTML) {
out.format("</body>%n");
out.format("</html>%n");
}
return out.toString();
} finally {
if (out != null)
out.close();
}
}
private void print() {
printSheets();
}
private void ensureOut() {
if (out == null)
out = new Formatter(new StringBuilder());
}
private void printSheets() {
Sheet sheet = wb.getSheetAt(sheetNum);
printSheet(sheet);
}
private void printSheet(Sheet sheet) {
out.format("<table class='%s' width='%s'>%n", DEFAULTS_CLASS, getTableWidth(sheet));
printCols(sheet);
printSheetContent(sheet);
out.format("</table>%n");
}
private void printCols(Sheet sheet) {
// out.format("<col/>%n");
ensureColumnBounds(sheet);
for (int i = firstColumn; i < endColumn; i++) {
out.format("<col style='width:%spx;' />%n", sheet.getColumnWidth(i) / 32);
}
}
private int getTableWidth(Sheet sheet) {
ensureColumnBounds(sheet);
int width = 0;
for (int i = firstColumn; i < endColumn; i++) {
width = width + (sheet.getColumnWidth(i) / 32);
}
return width;
}
private void ensureColumnBounds(Sheet sheet) {
if (gotBounds)
return;
Iterator<Row> iter = sheet.rowIterator();
firstColumn = (iter.hasNext() ? Integer.MAX_VALUE : 0);
endColumn = 0;
while (iter.hasNext()) {
Row row = iter.next();
short firstCell = row.getFirstCellNum();
if (firstCell >= 0) {
firstColumn = Math.min(firstColumn, firstCell);
endColumn = Math.max(endColumn, row.getLastCellNum());
}
}
gotBounds = true;
}
@SuppressWarnings("unused")
/**本来是用来生成 AB 那个列名称的**/
private void printColumnHeads(Sheet sheet) {
out.format("<thead>%n");
out.format(" <tr class=%s>%n", COL_HEAD_CLASS);
out.format(" <th class=%s>&#x25CA;</th>%n", COL_HEAD_CLASS);
StringBuilder colName = new StringBuilder();
for (int i = firstColumn; i < endColumn; i++) {
colName.setLength(0);
int cnum = i;
do {
colName.insert(0, (char) ('A' + cnum % 26));
cnum /= 26;
} while (cnum > 0);
out.format(" <th class=%s>%s</th>%n", COL_HEAD_CLASS, colName);
}
out.format(" </tr>%n");
out.format("</thead>%n");
}
private void printSheetContent(Sheet sheet) {
// printColumnHeads(sheet);
MergedRegionHelper mergedRegionHelper = new MergedRegionHelper(sheet);
CellValueHelper cellValueHelper = new CellValueHelper(wb, cssRandom);
out.format("<tbody>%n");
Iterator<Row> rows = sheet.rowIterator();
int rowIndex = 1;
while (rows.hasNext()) {
Row row = rows.next();
out.format(" <tr style='height:%spx;'>%n", row.getHeight() / 15);
// out.format(" <td class='%s'>%d</td>%n", ROW_HEAD_CLASS,
// row.getRowNum() + 1);
for (int i = firstColumn; i < endColumn; i++) {
if (mergedRegionHelper.isNeedCreate(rowIndex, i)) {
String content = "&nbsp;";
CellStyle style = null;
if (i >= row.getFirstCellNum() && i < row.getLastCellNum()) {
Cell cell = row.getCell(i);
if (cell != null) {
style = cell.getCellStyle();
content = cellValueHelper.getHtmlValue(cell);
}
}
if (mergedRegionHelper.isMergedRegion(rowIndex, i)) {
Integer[] rowAndColSpan = mergedRegionHelper.getRowAndColSpan(rowIndex, i);
out.format(" <td rowspan='%s' colspan='%s' class='%s' >%s</td>%n", rowAndColSpan[0], rowAndColSpan[1], styleName(style), content);
} else {
out.format(" <td class='%s'>%s</td>%n", styleName(style), content);
}
}
}
out.format(" </tr>%n");
rowIndex++;
}
out.format("</tbody>%n");
}
private String styleName(CellStyle style) {
if (style == null)
return "";
return String.format("style_%02x_%s font_%s_%s", style.getIndex(), cssRandom, style.getFontIndex(), cssRandom);
}
}

View File

@@ -0,0 +1,135 @@
package org.jeecgframework.poi.excel.html.helper;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.google.common.xml.XmlEscapers;
/**
* Cell值帮助类
*
* @author JEECG
* @date 2015年5月9日 下午10:31:32
*/
public class CellValueHelper {
/**
* Excel 格式
*/
private boolean is07;
private int cssRandom;
private Map<String, String> fontCache = new HashMap<String, String>();
public CellValueHelper(Workbook wb, int cssRandom) {
this.cssRandom = cssRandom;
if (wb instanceof HSSFWorkbook)
is07 = false;
else if (wb instanceof XSSFWorkbook) {
is07 = true;
cacheFontInfo(wb);
} else
throw new IllegalArgumentException("unknown workbook type: " + wb.getClass().getSimpleName());
}
/**
* O7 版本坑爹bug
*
* @param wb
*/
private void cacheFontInfo(Workbook wb) {
for (int i = 0, le = wb.getNumberOfFonts(); i < le; i++) {
Font font = wb.getFontAt(i);
fontCache.put(font.getBold() + "_" + font.getItalic() + "_" + font.getFontName() + "_" + font.getFontHeightInPoints() + "_" + font.getColor(), font.getIndex() + "");
}
}
public String getHtmlValue(Cell cell) {
if (CellType.BOOLEAN == cell.getCellType() || CellType.NUMERIC == cell.getCellType()) {
cell.setCellType( CellType.STRING);
return cell.getStringCellValue();
} else if ( CellType.STRING == cell.getCellType()) {
if (cell.getRichStringCellValue().numFormattingRuns() == 0) {
return XmlEscapers.xmlContentEscaper().escape(cell.getStringCellValue());
} else if (is07) {
return getXSSFRichString((XSSFRichTextString) cell.getRichStringCellValue());
} else {
return getHSSFRichString((HSSFRichTextString) cell.getRichStringCellValue());
}
}
return "";
}
/**
* 03版本复杂数据
*
* @param rich
* @return
*/
private String getHSSFRichString(HSSFRichTextString rich) {
int nums = rich.numFormattingRuns();
StringBuilder sb = new StringBuilder();
String text = rich.toString();
int currentIndex = 0;
sb.append(text.substring(0, rich.getIndexOfFormattingRun(0)));
for (int i = 0; i < nums; i++) {
sb.append("<span ");
sb.append("class='font_" + rich.getFontOfFormattingRun(i));
sb.append("_");
sb.append(cssRandom);
sb.append("'>");
currentIndex = rich.getIndexOfFormattingRun(i);
if (i < nums - 1) {
sb.append(XmlEscapers.xmlContentEscaper().escape(text.substring(currentIndex, rich.getIndexOfFormattingRun(i + 1))));
} else {
sb.append(XmlEscapers.xmlContentEscaper().escape(text.substring(currentIndex, text.length())));
}
sb.append("</span>");
}
return sb.toString();
}
/**
* 07版本复杂数据
*
* @param rich
* @return
*/
private String getXSSFRichString(XSSFRichTextString rich) {
int nums = rich.numFormattingRuns();
StringBuilder sb = new StringBuilder();
String text = rich.toString();
int currentIndex = 0, lastIndex = 0;
for (int i = 1; i <= nums; i++) {
sb.append("<span ");
try {
sb.append("class='font_" + getFontIndex(rich.getFontOfFormattingRun(i - 1)));
sb.append("_");
sb.append(cssRandom);
sb.append("'");
} catch (Exception e) {
}
sb.append(">");
currentIndex = rich.getIndexOfFormattingRun(i) == -1 ? text.length() : rich.getIndexOfFormattingRun(i);
sb.append(XmlEscapers.xmlContentEscaper().escape(text.substring(lastIndex, currentIndex)));
sb.append("</span>");
lastIndex = currentIndex;
}
return sb.toString();
}
private String getFontIndex(XSSFFont font) {
return fontCache.get(font.getBold() + "_" + font.getItalic() + "_" + font.getFontName() + "_" + font.getFontHeightInPoints() + "_" + font.getColor());
}
}

View File

@@ -0,0 +1,139 @@
package org.jeecgframework.poi.excel.html.helper;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.poi.ss.usermodel.Sheet;
import org.jeecgframework.poi.util.PoiCellUtil;
import org.jeecgframework.poi.util.PoiMergeCellUtil;
/**
* 合并单元格帮助类
*
* @author JEECG
* @date 2015年5月9日 下午2:13:35
*/
public class MergedRegionHelper {
private Map<String, Integer[]> mergedCache = new HashMap<String, Integer[]>();
private Set<String> notNeedCread = new HashSet<String>();
public MergedRegionHelper(Sheet sheet) {
getAllMergedRegion(sheet);
}
private void getAllMergedRegion(Sheet sheet) {
int nums = sheet.getNumMergedRegions();
for (int i = 0; i < nums; i++) {
handerMergedString(sheet.getMergedRegion(i).formatAsString());
}
}
/**
* 根据合并输出内容,处理合并单元格事情
*
* @param formatAsString
*/
private void handerMergedString(String formatAsString) {
String[] strArr = formatAsString.split(":");
if (strArr.length == 2) {
int startCol = strArr[0].charAt(0) - 65;
if (strArr[0].charAt(1) >= 65) {
startCol = (startCol + 1) * 26 + (strArr[0].charAt(1) - 65);
}
int startRol = Integer.valueOf(strArr[0].substring(strArr[0].charAt(1) >= 65 ? 2 : 1));
int endCol = strArr[1].charAt(0) - 65;
if (strArr[1].charAt(1) >= 65) {
endCol = (endCol + 1) * 26 + (strArr[1].charAt(1) - 65);
}
int endRol = Integer.valueOf(strArr[1].substring(strArr[1].charAt(1) >= 65 ? 2 : 1));
mergedCache.put(startRol + "_" + startCol, new Integer[] { endRol - startRol + 1, endCol - startCol + 1 });
for (int i = startRol; i <= endRol; i++) {
for (int j = startCol; j <= endCol; j++) {
notNeedCread.add(i + "_" + j);
}
}
notNeedCread.remove(startRol + "_" + startCol);
}
}
/**
* 是不是需要创建这个TD
*
* @param row
* @param col
* @return
*/
public boolean isNeedCreate(int row, int col) {
return !notNeedCread.contains(row + "_" + col);
}
/**
* 是不是合并区域
*
* @param row
* @param col
* @return
*/
public boolean isMergedRegion(int row, int col) {
return mergedCache.containsKey(row + "_" + col);
}
/**
* 获取合并区域
*
* @param row
* @param col
* @return
*/
public Integer[] getRowAndColSpan(int row, int col) {
return mergedCache.get(row + "_" + col);
}
/**
* 插入之后还原之前的合并单元格
*
* @param rowIndex
* @param size
*/
public void shiftRows(Sheet sheet, int rowIndex, int size, int shiftRows) {
Set<String> keys = new HashSet<String>();
keys.addAll(mergedCache.keySet());
for (String key : keys) {
String[] temp = key.split("_");
//update-begin---author:chenrui ---date:20240102 for[issue/5167]遍历单元格次行原本的合并缓存未正确删除导致最终输出合并样式有问题------------
if (Integer.parseInt(temp[0]) > rowIndex) {
//update-end---author:chenrui ---date:20240102 for[issue/5167]遍历单元格次行原本的合并缓存未正确删除导致最终输出合并样式有问题------------
Integer[] data = mergedCache.get(key);
String newKey = (Integer.parseInt(temp[0]) + size) + "_" + temp[1];
if (!mergedCache.containsKey(newKey)) {
mergedCache.put(newKey, mergedCache.get(key));
try {
// 还原合并单元格
if (!PoiCellUtil.isMergedRegion(sheet, Integer.parseInt(temp[0]) + size - 1, Integer.parseInt(temp[1]))) {
PoiMergeCellUtil.addMergedRegion(sheet,
Integer.parseInt(temp[0]) + size - 1, Integer.parseInt(temp[0]) + data[0] + size - 2,
Integer.parseInt(temp[1]), Integer.parseInt(temp[1]) + data[1] - 1
);
}
} catch (Exception e) {
}
}
}
}
//删除掉原始的缓存KEY
for (String key : keys) {
String[] temp = key.split("_");
//update-begin---author:chenrui ---date:20240102 for[issue/5167]遍历单元格次行原本的合并缓存未正确删除导致最终输出合并样式有问题------------
if (Integer.parseInt(temp[0]) >= rowIndex && Integer.parseInt(temp[0]) <= rowIndex + size ) {
//update-end---author:chenrui ---date:20240102 for[issue/5167]遍历单元格次行原本的合并缓存未正确删除导致最终输出合并样式有问题------------
mergedCache.remove(key);
}
}
}
}

View File

@@ -0,0 +1,259 @@
package org.jeecgframework.poi.excel.html.helper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Formatter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.poi.util.PoiPublicUtil;
/**
* 样式帮助类
*
* @author JEECG
* @date 2015年5月9日 下午4:04:24
*/
public class StylerHelper {
private static String DEFAULTS_CLASS_CSS = ".excelDefaults {background-color: white;color: black;text-decoration: none;direction: ltr;text-transform: none;text-indent: 0;letter-spacing: 0;word-spacing: 0;white-space: normal;unicode-bidi: normal;vertical-align: 0;text-shadow: none;padding: 0;margin: 0;border-collapse: collapse;white-space: pre-wrap;word-wrap: break-word;word-break: break-all;}.excelDefaults td {padding: 1px 5px;border: 1px solid silver;border-color: #000000;text-align: center;vertical-align: middle;font-size: 12pt;}.excelDefaults .colHeader {background-color: silver;font-weight: bold;border: 1px solid black;text-align: center;padding: 1px 5px;}.excelDefaults .rowHeader {background-color: silver;font-weight: bold;border: 1px solid black;text-align: right;padding: 1px 5px;}";
private static final String DEFAULTS_CLASS = "excelDefaults";
private static final Map<Short, String> ALIGN = PoiPublicUtil.mapFor(HorizontalAlignment.LEFT.getCode(), "left",HorizontalAlignment.CENTER.getCode(), "center",HorizontalAlignment.RIGHT.getCode(), "right", HorizontalAlignment.FILL.getCode(), "left",HorizontalAlignment.JUSTIFY.getCode(), "left",HorizontalAlignment.CENTER_SELECTION.getCode(), "center");
private static final Map<Short, String> VERTICAL_ALIGN = PoiPublicUtil.mapFor(VerticalAlignment.BOTTOM.getCode(), "bottom", VerticalAlignment.CENTER.getCode(), "middle",VerticalAlignment.TOP.getCode(), "top");
private Formatter out;
private Sheet sheet;
private HtmlHelper helper;
private int sheetNum;
private int cssRandom;
public StylerHelper(Workbook wb, Formatter out, int sheetNum, int cssRandom) {
this.out = out;
this.sheetNum = sheetNum;
this.cssRandom = cssRandom;
if (wb instanceof HSSFWorkbook)
helper = new HSSFHtmlHelper((HSSFWorkbook) wb);
else if (wb instanceof XSSFWorkbook)
helper = new XSSFHtmlHelper((XSSFWorkbook) wb);
else
throw new IllegalArgumentException("unknown workbook type: " + wb.getClass().getSimpleName());
printInlineStyle(wb);
}
private void printInlineStyle(Workbook wb) {
out.format("<style type=\"text/css\">%n");
printStyles(wb);
prontFonts(wb);
out.format("</style>%n");
}
private void prontFonts(Workbook wb) {
//update-begin---author:liusq Date:20220228 for[I4I3ZY]issue AutoPOi Workbook对象转HTML字符串 数组下标越界异常----
for (int i = 0, le = wb.getNumberOfFonts(); i < le; i++) {
Font font = wb.getFontAt(i);
out.format(".%s .%s {%n", DEFAULTS_CLASS, "font_" + i + "_" + cssRandom);
fontStyle(font);
out.format("}%n");
}
//update-end---author:liusq Date:20220228 for[I4I3ZY]issue AutoPOi Workbook对象转HTML字符串 数组下标越界异常整----
}
public void printStyles(Workbook wb) {
if (DEFAULTS_CLASS_CSS == null) {
DEFAULTS_CLASS_CSS = getDefaultsClassCss();
}
out.format(DEFAULTS_CLASS_CSS);
Set<CellStyle> seen = new HashSet<CellStyle>();
sheet = wb.getSheetAt(sheetNum);
Iterator<Row> rows = sheet.rowIterator();
while (rows.hasNext()) {
Row row = rows.next();
for (Cell cell : row) {
CellStyle style = cell.getCellStyle();
if (!seen.contains(style)) {
printStyle(style);
seen.add(style);
}
}
}
}
private String getDefaultsClassCss() {
BufferedReader in = null;
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb);
try {
in = new BufferedReader(new InputStreamReader(StylerHelper.class.getResourceAsStream("excelStyle.css")));
String line;
while ((line = in.readLine()) != null) {
formatter.format("%s%n", line);
}
return formatter.toString();
} catch (IOException e) {
throw new IllegalStateException("Reading standard css", e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
throw new IllegalStateException("Reading standard css", e);
}
}
formatter.close();
}
}
private void printStyle(CellStyle style) {
out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style));
styleContents(style);
out.format("}%n");
}
private void styleContents(CellStyle style) {
if (style.getAlignment().getCode() != 2) {
styleOut("text-align", style.getAlignment().getCode(), ALIGN);
styleOut("vertical-align", style.getAlignment().getCode(), VERTICAL_ALIGN);
}
helper.colorStyles(style, out);
}
private void fontStyle(Font font) {
if (font.getBold())
out.format(" font-weight: bold;%n");
if (font.getItalic())
out.format(" font-style: italic;%n");
out.format(" font-family: %s;%n", font.getFontName());
int fontheight = font.getFontHeightInPoints();
if (fontheight == 9) {
fontheight = 10;
}
out.format(" font-size: %dpt;%n", fontheight);
helper.styleColor(out, "color", getColor(font));
}
private Color getColor(Font font) {
if (helper instanceof HSSFHtmlHelper) {
return ((HSSFWorkbook) sheet.getWorkbook()).getCustomPalette().getColor(font.getColor());
} else {
return ((XSSFFont) font).getXSSFColor();
}
}
private String styleName(CellStyle style) {
if (style == null)
return "";
return String.format("style_%02x_%s", style.getIndex(), cssRandom);
}
private <K> void styleOut(String attr, K key, Map<K, String> mapping) {
String value = mapping.get(key);
if (value != null) {
out.format(" %s: %s;%n", attr, value);
}
}
private interface HtmlHelper {
/**
* Outputs the appropriate CSS style for the given cell style.
*
* @param style
* The cell style.
* @param out
* The place to write the output.
*/
void colorStyles(CellStyle style, Formatter out);
void styleColor(Formatter out, String attr, Color color);
}
private class HSSFHtmlHelper implements HtmlHelper {
private final HSSFWorkbook wb;
private final HSSFPalette colors;
//-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
private HSSFColor HSSF_AUTO = new HSSFColor(0x40, -1, java.awt.Color.black);
//-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
public HSSFHtmlHelper(HSSFWorkbook wb) {
this.wb = wb;
colors = wb.getCustomPalette();
}
public void colorStyles(CellStyle style, Formatter out) {
HSSFCellStyle cs = (HSSFCellStyle) style;
out.format(" /* fill pattern = %d */%n", cs.getFillPattern());
styleColor(out, "background-color", cs.getFillForegroundColor());
styleColor(out, "color", colors.getColor(cs.getFont(wb).getColor()));
}
private void styleColor(Formatter out, String attr, short index) {
HSSFColor color = colors.getColor(index);
if (index == HSSF_AUTO.getIndex() || color == null) {
out.format(" /* %s: index = %d */%n", attr, index);
} else {
short[] rgb = color.getTriplet();
out.format(" %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0], rgb[1], rgb[2], index);
}
}
public void styleColor(Formatter out, String attr, Color color) {
if (color == null) {
return;
}
HSSFColor hSSFColor = (HSSFColor) color;
short[] rgb = hSSFColor.getTriplet();
out.format(" %s: #%02x%02x%02x; %n", attr, rgb[0], rgb[1], rgb[2]);
}
}
/**
* Implementation of {@link HtmlHelper} for XSSF files.
*
* @author Ken Arnold, Industrious Media LLC
*/
private class XSSFHtmlHelper implements HtmlHelper {
public XSSFHtmlHelper(XSSFWorkbook wb) {
}
public void colorStyles(CellStyle style, Formatter out) {
XSSFCellStyle cs = (XSSFCellStyle) style;
styleColor(out, "background-color", cs.getFillForegroundXSSFColor());
styleColor(out, "color", cs.getFont().getXSSFColor());
}
public void styleColor(Formatter out, String attr, Color color) {
XSSFColor xSSFColor = (XSSFColor) color;
if (color == null || xSSFColor.isAuto())
return;
byte[] rgb = xSSFColor.getRGB();
if (rgb == null) {
return;
}
out.format(" %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]);
}
}
}

View File

@@ -0,0 +1,45 @@
.excelDefaults {
background-color: white;
color: black;
text-decoration: none;
direction: ltr;
text-transform: none;
text-indent: 0;
letter-spacing: 0;
word-spacing: 0;
white-space: normal;
unicode-bidi: normal;
vertical-align: 0;
text-shadow: none;
padding: 0;
margin: 0;
border-collapse: collapse;
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-all;
}
.excelDefaults td {
padding: 1px 5px;
border: 1px solid silver;
border-color: #000000;
text-align: center;
vertical-align: middle;
font-size: 12pt;
}
.excelDefaults .colHeader {
background-color: silver;
font-weight: bold;
border: 1px solid black;
text-align: center;
padding: 1px 5px;
}
.excelDefaults .rowHeader {
background-color: silver;
font-weight: bold;
border: 1px solid black;
text-align: right;
padding: 1px 5px;
}

View File

@@ -0,0 +1,387 @@
/**
* 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.imports;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.jeecgframework.poi.excel.entity.params.ExcelImportEntity;
import org.jeecgframework.poi.excel.entity.sax.SaxReadCellEntity;
import org.jeecgframework.poi.exception.excel.ExcelImportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelImportEnum;
import org.jeecgframework.poi.handler.inter.IExcelDataHandler;
import org.jeecgframework.poi.util.ExcelUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Cell 取值服务 判断类型处理数据 1.判断Excel中的类型 2.根据replace替换值 3.handler处理数据 4.判断返回类型转化数据返回
*
* @author JEECG
* @date 2014年6月26日 下午10:42:28
*/
public class CellValueServer {
private static final Logger LOGGER = LoggerFactory.getLogger(CellValueServer.class);
private List<String> hanlderList = null;
/**
* 获取单元格内的值
*
* @param xclass
* @param cell
* @param entity
* @return
*/
private Object getCellValue(String xclass, Cell cell, ExcelImportEntity entity) {
if (cell == null) {
return "";
}
Object result = null;
// 日期格式比较特殊,和cell格式不一致
if ("class java.util.Date".equals(xclass) || ("class java.sql.Time").equals(xclass)) {
if ( CellType.NUMERIC == cell.getCellType()) {
// 日期格式
result = cell.getDateCellValue();
} else {
cell.setCellType( CellType.STRING);
result = getDateData(entity, cell.getStringCellValue());
}
if (("class java.sql.Time").equals(xclass)) {
result = new Time(((Date) result).getTime());
}
} else if ( CellType.NUMERIC == cell.getCellType()) {
result = cell.getNumericCellValue();
} else if ( CellType.BOOLEAN == cell.getCellType()) {
result = cell.getBooleanCellValue();
} else if ( CellType.FORMULA == cell.getCellType() && PoiPublicUtil.isNumber(xclass)) {
//如果单元格是表达式 且 字段是数字类型
double cellValue = cell.getNumericCellValue();
//---author:liusq---date:20221102-----for: [issues/3369]Excel导入 带公式的时候精度丢失---
//setScale方法的第一个参数设置小数点保留位数第二个参数设置进位方法、此处是四舍五入
BigDecimal bigDecimal= new BigDecimal(cellValue).setScale(4, RoundingMode.HALF_UP);
//stripTrailingZeros方法去除末尾的0toPlainString避免输出科学计数法的字符串
result = bigDecimal.stripTrailingZeros().toPlainString();
//---author:liusq---date:20221102-----for:[issues/3369] Excel导入 带公式的时候精度丢失---
} else {
//设置单元格类型
cell.setCellType(CellType.STRING);
result = cell.getStringCellValue();
}
return result;
}
/**
* 获取日期类型数据
*
* @Author JEECG
* @date 2013年11月26日
* @param entity
* @param value
* @return
*/
private Date getDateData(ExcelImportEntity entity, String value) {
if (StringUtils.isNotEmpty(entity.getFormat()) && StringUtils.isNotEmpty(value)) {
SimpleDateFormat format = new SimpleDateFormat(entity.getFormat());
try {
return format.parse(value);
} catch (ParseException e) {
LOGGER.error("时间格式化失败,格式化:{},值:{}", entity.getFormat(), value);
throw new ExcelImportException(ExcelImportEnum.GET_VALUE_ERROR);
}
}
return null;
}
/**
* 获取cell的值
*
* @param object
* @param excelParams
* @param cell
* @param titleString
*/
public Object getValue(IExcelDataHandler dataHanlder, Object object, Cell cell, Map<String, ExcelImportEntity> excelParams, String titleString) throws Exception {
ExcelImportEntity entity = excelParams.get(titleString);
String xclass = "class java.lang.Object";
if (!(object instanceof Map)) {
Method setMethod = entity.getMethods() != null && entity.getMethods().size() > 0 ? entity.getMethods().get(entity.getMethods().size() - 1) : entity.getMethod();
Type[] ts = setMethod.getGenericParameterTypes();
xclass = ts[0].toString();
}
Object result = getCellValue(xclass, cell, entity);
if (entity != null) {
result = hanlderSuffix(entity.getSuffix(), result);
//update-begin-author:taoYan date:20180807 for:多值替换
result = replaceValue(entity.getReplace(), result,entity.isMultiReplace());
//update-end-author:taoYan date:20180807 for:多值替换
}
result = hanlderValue(dataHanlder, object, result, titleString);
return getValueByType(xclass, result, entity);
}
/**
* 获取cell值
*
* @param dataHanlder
* @param object
* @param cellEntity
* @param excelParams
* @param titleString
* @return
*/
public Object getValue(IExcelDataHandler dataHanlder, Object object, SaxReadCellEntity cellEntity, Map<String, ExcelImportEntity> excelParams, String titleString) {
ExcelImportEntity entity = excelParams.get(titleString);
Method setMethod = entity.getMethods() != null && entity.getMethods().size() > 0 ? entity.getMethods().get(entity.getMethods().size() - 1) : entity.getMethod();
Type[] ts = setMethod.getGenericParameterTypes();
String xclass = ts[0].toString();
Object result = cellEntity.getValue();
result = hanlderSuffix(entity.getSuffix(), result);
//update-begin-auhtor:taoyan date:20180807 for:多值替换
result = replaceValue(entity.getReplace(), result,entity.isMultiReplace());
//update-end-auhtor:taoyan date:20180807 for:多值替换
result = hanlderValue(dataHanlder, object, result, titleString);
return getValueByType(xclass, result, entity);
}
/**
* 把后缀删除掉
*
* @param result
* @param suffix
* @return
*/
private Object hanlderSuffix(String suffix, Object result) {
if (StringUtils.isNotEmpty(suffix) && result != null && result.toString().endsWith(suffix)) {
String temp = result.toString();
return temp.substring(0, temp.length() - suffix.length());
}
return result;
}
/**
* 根据返回类型获取返回值
*
* @param xclass
* @param result
* @param entity
* @return
*/
private Object getValueByType(String xclass, Object result, ExcelImportEntity entity) {
try {
//update-begin-author:scott date:20180711 for:TASK #2950 【bug】excel 导入报错,空指针问题
if(result==null || "".equals(String.valueOf(result))){
return null;
}
//update-end-author:scott date:20180711 for:TASK #2950 【bug】excel 导入报错,空指针问题
if ("class java.util.Date".equals(xclass)) {
return result;
}
if ("class java.lang.Boolean".equals(xclass) || "boolean".equals(xclass)) {
//update-begin-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
Boolean temp = Boolean.valueOf(String.valueOf(result));
//if(StringUtils.isNotEmpty(entity.getNumFormat())){
// return Boolean.valueOf(new DecimalFormat(entity.getNumFormat()).format(temp));
//}else{
return temp;
//}
//update-end-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
}
if ("class java.lang.Double".equals(xclass) || "double".equals(xclass)) {
//update-begin-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
Double temp = Double.valueOf(String.valueOf(result));
//if(StringUtils.isNotEmpty(entity.getNumFormat())){
// return Double.valueOf(new DecimalFormat(entity.getNumFormat()).format(temp));
//}else{
return temp;
//}
//update-end-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
}
if ("class java.lang.Long".equals(xclass) || "long".equals(xclass)) {
//update-begin-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
Long temp = Long.valueOf(ExcelUtil.remove0Suffix(String.valueOf(result)));
//if(StringUtils.isNotEmpty(entity.getNumFormat())){
// return Long.valueOf(new DecimalFormat(entity.getNumFormat()).format(temp));
//}else{
return temp;
//}
//update-end-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
}
if ("class java.lang.Float".equals(xclass) || "float".equals(xclass)) {
//update-begin-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
Float temp = Float.valueOf(String.valueOf(result));
//if(StringUtils.isNotEmpty(entity.getNumFormat())){
// return Float.valueOf(new DecimalFormat(entity.getNumFormat()).format(temp));
//}else{
return temp;
//}
//update-end-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
}
if ("class java.lang.Integer".equals(xclass) || "int".equals(xclass)) {
//update-begin-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
Integer temp = Integer.valueOf(ExcelUtil.remove0Suffix(String.valueOf(result)));
//if(StringUtils.isNotEmpty(entity.getNumFormat())){
// return Integer.valueOf(new DecimalFormat(entity.getNumFormat()).format(temp));
//}else{
return temp;
//}
//update-end-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
}
if ("class java.math.BigDecimal".equals(xclass)) {
//update-begin-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
BigDecimal temp = new BigDecimal(String.valueOf(result));
//if(StringUtils.isNotEmpty(entity.getNumFormat())){
// return new BigDecimal(new DecimalFormat(entity.getNumFormat()).format(temp));
//}else{
return temp;
//}
//update-end-author:taoYan date:20200319 for:Excel注解的numFormat方法似乎未实现 #970
}
if ("class java.lang.String".equals(xclass)) {
// 针对String 类型,但是Excel获取的数据却不是String,比如Double类型,防止科学计数法
if (result instanceof String) {
//---update-begin-----autor:scott------date:20191016-------for:excel导入数字类型去掉后缀.0------
return ExcelUtil.remove0Suffix(result);
//---update-end-----autor:scott------date:20191016-------for:excel导入数字类型去掉后缀.0------
}
// double类型防止科学计数法
if (result instanceof Double) {
return PoiPublicUtil.doubleToString((Double) result);
}
//---update-begin-----autor:scott------date:20191016-------for:excel导入数字类型去掉后缀.0------
return ExcelUtil.remove0Suffix(String.valueOf(result));
//---update-end-----autor:scott------date:20191016-------for:excel导入数字类型去掉后缀.0------
}
return result;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException(ExcelImportEnum.GET_VALUE_ERROR);
}
}
/**
* 调用处理接口处理值
*
* @param dataHanlder
* @param object
* @param result
* @param titleString
* @return
*/
private Object hanlderValue(IExcelDataHandler dataHanlder, Object object, Object result, String titleString) {
if (dataHanlder == null || dataHanlder.getNeedHandlerFields() == null || dataHanlder.getNeedHandlerFields().length == 0) {
return result;
}
if (hanlderList == null) {
hanlderList = Arrays.asList(dataHanlder.getNeedHandlerFields());
}
if (hanlderList.contains(titleString)) {
return dataHanlder.importHandler(object, titleString, result);
}
return result;
}
//update-begin-author:taoyan date:20180807 for:导入多值替换--
/**
* 导入支持多值替换
* @param replace 数据库中字典查询出来的数组
* @param result excel单元格获取的值
* @param multiReplace 是否支持多值替换
* @author taoYan
* @since 2018年8月7日
*/
private Object replaceValue(String[] replace, Object result,boolean multiReplace) {
if(result == null){
return "";
}
if(replace == null || replace.length<=0){
return result;
}
String temp = String.valueOf(result);
String backValue = "";
if(temp.indexOf(",")>0 && multiReplace){
//原值中带有逗号,认为他是多值的
String multiReplaces[] = temp.split(",");
for (String str : multiReplaces) {
backValue = backValue.concat(replaceSingleValue(replace, str)+",");
}
if(backValue.equals("")){
backValue = temp;
}else{
backValue = backValue.substring(0, backValue.length()-1);
}
}else{
backValue = replaceSingleValue(replace, temp);
}
//update-begin-author:liusq date:20210204 for:字典替换失败提示日志
if(replace.length>0 && backValue.equals(temp)){
LOGGER.warn("====================字典替换失败,字典值:{},要转换的导入值:{}====================", replace, temp);
}
//update-end-author:liusq date:20210204 for:字典替换失败提示日志
return backValue;
}
/**
* 单值替换 ,若没找到则原值返回
*/
private String replaceSingleValue(String[] replace, String temp){
String[] tempArr;
for (int i = 0; i < replace.length; i++) {
//update-begin---author:scott Date:20211220 for[issues/I4MBB3]@Excel dicText字段的值有下划线时导入功能不能正确解析---
//tempArr = replace[i].split("_");
tempArr = getValueArr(replace[i]);
if (temp.equals(tempArr[0]) || temp.replace("_","---").equals(tempArr[0])) {
//update-begin---author:wangshuai ---date:20220422 for导入字典替换需要将---替换成_不然数据库会存--- ------------
if(tempArr[1].contains("---")){
return tempArr[1].replace("---","_");
}
//update-end---author:wangshuai ---date:20220422 for导入字典替换需要将---替换成_不然数据库会存--- --------------
return tempArr[1];
}
//update-end---author:scott Date:20211220 for[issues/I4MBB3]@Excel dicText字段的值有下划线时导入功能不能正确解析---
}
return temp;
}
//update-end-author:taoyan date:20180807 for:导入多值替换--
/**
* 字典文本中含多个下划线横岗,取最后一个(解决空值情况)
*
* @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;
}
}

View File

@@ -0,0 +1,620 @@
/**
* 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.imports;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
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.result.ExcelImportResult;
import org.jeecgframework.poi.excel.entity.result.ExcelVerifyHanlderResult;
import org.jeecgframework.poi.excel.imports.base.ImportBaseService;
import org.jeecgframework.poi.excel.imports.base.ImportFileServiceI;
import org.jeecgframework.poi.excel.imports.verifys.VerifyHandlerServer;
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.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Excel 导入服务
*
* @author JEECG
* @date 2014年6月26日 下午9:20:51
*/
@SuppressWarnings({ "rawtypes", "unchecked", "hiding" })
public class ExcelImportServer extends ImportBaseService {
private final static Logger LOGGER = LoggerFactory.getLogger(ExcelImportServer.class);
private CellValueServer cellValueServer;
private VerifyHandlerServer verifyHandlerServer;
private boolean verfiyFail = false;
//仅允许字母数字字符的正则表达式
private static final Pattern lettersAndNumbersPattern = Pattern.compile("^[a-zA-Z0-9]+$") ;
/**
* 异常数据styler
*/
private CellStyle errorCellStyle;
public ExcelImportServer() {
this.cellValueServer = new CellValueServer();
this.verifyHandlerServer = new VerifyHandlerServer();
}
/***
* 向List里面继续添加元素
*
* @param object
* @param param
* @param row
* @param titlemap
* @param targetId
* @param pictures
* @param params
*/
private void addListContinue(Object object, ExcelCollectionParams param, Row row, Map<Integer, String> titlemap, String targetId, Map<String, PictureData> pictures, ImportParams params) throws Exception {
Collection collection = (Collection) PoiPublicUtil.getMethod(param.getName(), object.getClass()).invoke(object, new Object[] {});
Object entity = PoiPublicUtil.createObject(param.getType(), targetId);
String picId;
boolean isUsed = false;// 是否需要加上这个对象
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
Cell cell = row.getCell(i);
String titleString = (String) titlemap.get(i);
if (param.getExcelParams().containsKey(titleString)) {
if (param.getExcelParams().get(titleString).getType() == 2) {
picId = row.getRowNum() + "_" + i;
saveImage(object, picId, param.getExcelParams(), titleString, pictures, params);
} else {
saveFieldValue(params, entity, cell, param.getExcelParams(), titleString, row);
}
isUsed = true;
}
}
if (isUsed) {
collection.add(entity);
}
}
/**
* 获取key的值,针对不同类型获取不同的值
*
* @Author JEECG
* @date 2013-11-21
* @param cell
* @return
*/
private 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 excelImportEntity
* @param object
* @return
* @throws Exception
*/
private String getSaveUrl(ExcelImportEntity excelImportEntity, Object object) throws Exception {
String url = "";
if (excelImportEntity.getSaveUrl().equals("upload")) {
if (excelImportEntity.getMethods() != null && excelImportEntity.getMethods().size() > 0) {
object = getFieldBySomeMethod(excelImportEntity.getMethods(), object);
}
url = object.getClass().getName().split("\\.")[object.getClass().getName().split("\\.").length - 1];
return excelImportEntity.getSaveUrl() + "/" + url.substring(0, url.lastIndexOf("Entity"));
}
return excelImportEntity.getSaveUrl();
}
//update-begin--Author:xuelin Date:20171205 forTASK #2098 【excel问题】 Online 一对多导入失败--------------------
private <T> List<T> importExcel(Collection<T> result, Sheet sheet, Class<?> pojoClass, ImportParams params, Map<String, PictureData> pictures) throws Exception {
List collection = new ArrayList();
Map<String, ExcelImportEntity> excelParams = new HashMap<String, ExcelImportEntity>();
List<ExcelCollectionParams> excelCollection = new ArrayList<ExcelCollectionParams>();
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();
}
getAllExcelField(targetId, fileds, excelParams, excelCollection, pojoClass, null);
}
ignoreHeaderHandler(excelParams, params);
Iterator<Row> rows = sheet.rowIterator();
Map<Integer, String> titlemap = getTitleMap(sheet, rows, params, excelCollection);
//update-begin-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndex
Set<String> keys = excelParams.keySet();
for (String key : keys) {
if (key.startsWith("FIXED_")) {
String[] arr = key.split("_");
titlemap.put(Integer.parseInt(arr[1]), key);
}
}
//update-end-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndex
Set<Integer> columnIndexSet = titlemap.keySet();
Integer maxColumnIndex = Collections.max(columnIndexSet);
Integer minColumnIndex = Collections.min(columnIndexSet);
Row row = null;
//跳过表头和标题行
for (int j = 0; j < params.getTitleRows() + params.getHeadRows(); j++) {
row = rows.next();
}
Object object = null;
String picId;
while (rows.hasNext() && (row == null || sheet.getLastRowNum() - row.getRowNum() > params.getLastOfInvalidRow())) {
row = rows.next();
//update-begin--Author:xuelin Date:20171017 forTASK #2373 【bug】表改造问题导致 3.7.1批量导入用户bug-导入不成功--------------------
// 判断是集合元素还是不是集合元素,如果是就继续加入这个集合,不是就创建新的对象
//update-begin--Author:xuelin Date:20171206 forTASK #2451 【excel导出bug】online 一对多导入成功, 但是现在代码生成后的一对多online导入有问题了
Cell keyIndexCell = row.getCell(params.getKeyIndex());
if (excelCollection.size()>0 && StringUtils.isEmpty(getKeyValue(keyIndexCell)) && object != null && !Map.class.equals(pojoClass)) {
//update-end--Author:xuelin Date:20171206 forTASK #2451 【excel导出bug】online 一对多导入成功, 但是现在代码生成后的一对多online导入有问题了
for (ExcelCollectionParams param : excelCollection) {
addListContinue(object, param, row, titlemap, targetId, pictures, params);
}
} else {
object = PoiPublicUtil.createObject(pojoClass, targetId);
try {
//update-begin-author:taoyan date:20200303 for:导入图片
int firstCellNum = row.getFirstCellNum();
if(firstCellNum>minColumnIndex){
firstCellNum = minColumnIndex;
}
int lastCellNum = row.getLastCellNum();
if(lastCellNum<maxColumnIndex+1){
lastCellNum = maxColumnIndex+1;
}
for (int i = firstCellNum, le = lastCellNum; i < le; i++) {
Cell cell = row.getCell(i);
String titleString = (String) titlemap.get(i);
if (excelParams.containsKey(titleString) || Map.class.equals(pojoClass)) {
if (excelParams.get(titleString) != null && excelParams.get(titleString).getType() == 2) {
picId = row.getRowNum() + "_" + i;
saveImage(object, picId, excelParams, titleString, pictures, params);
} else {
if(params.getImageList()!=null && params.getImageList().contains(titleString)){
if (pictures != null) {
picId = row.getRowNum() + "_" + i;
PictureData image = pictures.get(picId);
if(image!=null){
byte[] data = image.getData();
params.getDataHanlder().setMapValue((Map) object, titleString, data);
}
}
}else{
saveFieldValue(params, object, cell, excelParams, titleString, row);
}
//update-end-author:taoyan date:20200303 for:导入图片
}
}
}
for (ExcelCollectionParams param : excelCollection) {
addListContinue(object, param, row, titlemap, targetId, pictures, params);
}
//update-begin-author:taoyan date:20210526 for:autopoi导入excel 如果单元格被设置边框,即使没有内容也会被当做是一条数据导入 #2484
if(isNotNullObject(pojoClass, object)){
collection.add(object);
}
//update-end-author:taoyan date:20210526 for:autopoi导入excel 如果单元格被设置边框,即使没有内容也会被当做是一条数据导入 #2484
} catch (ExcelImportException e) {
if (!e.getType().equals(ExcelImportEnum.VERIFY_ERROR)) {
throw new ExcelImportException(e.getType(), e);
}
}
}
//update-end--Author:xuelin Date:20171017 forTASK #2373 【bug】表改造问题导致 3.7.1批量导入用户bug-导入不成功--------------------
}
return collection;
}
/**
* 判断当前对象不是空
* @param pojoClass
* @param object
* @return
*/
private boolean isNotNullObject(Class pojoClass, Object object){
try {
Method method = pojoClass.getMethod("isNullObject");
if(method!=null){
Object flag = method.invoke(object);
if(flag!=null && true == Boolean.parseBoolean(flag.toString())){
return false;
}
}
} catch (NoSuchMethodException e) {
LOGGER.debug("未定义方法 isNullObject");
} catch (IllegalAccessException e) {
LOGGER.warn("没有权限访问该方法 isNullObject");
} catch (InvocationTargetException e) {
LOGGER.warn("方法调用失败 isNullObject");
}
return true;
}
/**
* 获取忽略的表头信息
* @param excelParams
* @param params
*/
private void ignoreHeaderHandler(Map<String, ExcelImportEntity> excelParams,ImportParams params){
List<String> ignoreList = new ArrayList<>();
for(String key:excelParams.keySet()){
String temp = excelParams.get(key).getGroupName();
if(temp!=null && temp.length()>0){
ignoreList.add(temp);
}
}
params.setIgnoreHeaderList(ignoreList);
}
/**
* 获取表格字段列名对应信息
*
* @param rows
* @param params
* @param excelCollection
* @return
*/
private Map<Integer, String> getTitleMap(Sheet sheet, Iterator<Row> rows, ImportParams params, List<ExcelCollectionParams> excelCollection) throws Exception {
Map<Integer, String> titlemap = new HashMap<Integer, String>();
Iterator<Cell> cellTitle = null;
String collectionName = null;
ExcelCollectionParams collectionParams = null;
Row headRow = null;
int headBegin = params.getTitleRows();
//update_begin-author:taoyan date:2020622 for当文件行数小于代码里设置的TitleRows时headRow一直为空就会出现死循环
int allRowNum = sheet.getPhysicalNumberOfRows();
//找到首行表头每个sheet都必须至少有一行表头
while(headRow == null && headBegin < allRowNum){
headRow = sheet.getRow(headBegin++);
}
if(headRow==null){
throw new Exception("不识别该文件");
}
//update-end-author:taoyan date:2020622 for当文件行数小于代码里设置的TitleRows时headRow一直为空就会出现死循环
//设置表头行数
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{
//update-begin-author:taoyan date:20220112 for: JT640 【online】导入 无论一对一还是一对多 如果子表只有一个字段 则子表无数据
// 上一行不是合并的情况下另有一种特殊的场景: 如果当前单元格和上面的单元格同一列 即子表字段只有一个 所以标题没有出现跨列
String prefixTitle = titlemap.get(cell.getColumnIndex());
if(prefixTitle!=null && !"".equals(prefixTitle)){
titlemap.put(cell.getColumnIndex(), prefixTitle + "_" +value);
}else{
titlemap.put(cell.getColumnIndex(), value);
}
//update-end-author:taoyan date:20220112 for: JT640 【online】导入 无论一对一还是一对多 如果子表只有一个字段 则子表无数据
}
/*int i = cell.getColumnIndex();
// 用以支持重名导入
if (titlemap.containsKey(i)) {
collectionName = titlemap.get(i);
collectionParams = getCollectionParams(excelCollection, collectionName);
titlemap.put(i, collectionName + "_" + value);
} else if (StringUtils.isNotEmpty(collectionName) && collectionParams.getExcelParams().containsKey(collectionName + "_" + value)) {
titlemap.put(i, collectionName + "_" + value);
} else {
collectionName = null;
collectionParams = null;
}
if (StringUtils.isEmpty(collectionName)) {
titlemap.put(i, value);
}*/
}
}
}
return titlemap;
}
//update-end--Author:xuelin Date:20171205 forTASK #2098 【excel问题】 Online 一对多导入失败--------------------
/**
* 获取这个名称对应的集合信息
*
* @param excelCollection
* @param collectionName
* @return
*/
private ExcelCollectionParams getCollectionParams(List<ExcelCollectionParams> excelCollection, String collectionName) {
for (ExcelCollectionParams excelCollectionParams : excelCollection) {
if (collectionName.equals(excelCollectionParams.getExcelName())) {
return excelCollectionParams;
}
}
return null;
}
/**
* Excel 导入 field 字段类型 Integer,Long,Double,Date,String,Boolean
*
* @param inputstream
* @param pojoClass
* @param params
* @return
* @throws Exception
*/
public ExcelImportResult importExcelByIs(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Excel import start ,class is {}", pojoClass);
}
List<T> result = new ArrayList<T>();
Workbook book = null;
boolean isXSSFWorkbook = false;
if (!(inputstream.markSupported())) {
inputstream = new PushbackInputStream(inputstream, 8);
}
//begin-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
//------poi4.x begin----
// FileMagic fm = FileMagic.valueOf(FileMagic.prepareToCheckMagic(inputstream));
// if(FileMagic.OLE2 == fm){
// isXSSFWorkbook=false;
// }
book = WorkbookFactory.create(inputstream);
if(book instanceof XSSFWorkbook){
isXSSFWorkbook=true;
}
LOGGER.info(" >>> poi3升级到4.0兼容改造工作, isXSSFWorkbook = " +isXSSFWorkbook);
//end-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
//begin-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------
//获取导入文本的sheet数
//update-begin-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错
if(params.getSheetNum()==0){
int sheetNum = book.getNumberOfSheets();
if(sheetNum>0){
params.setSheetNum(sheetNum);
}
}
//update-end-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错
//end-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------
createErrorCellStyle(book);
Map<String, PictureData> pictures;
// 获取指定的sheet名称
String sheetName = params.getSheetName();
//update-begin-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数
for (int i = params.getStartSheetIndex(); i < params.getStartSheetIndex()
+ params.getSheetNum(); i++) {
//update-end-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数
//update-begin-author:taoyan date:2023-3-4 for: 导入数据支持指定sheet名称
if(sheetName!=null && !"".equals(sheetName)){
Sheet tempSheet = book.getSheetAt(i);
if(!sheetName.equals(tempSheet.getSheetName())){
continue;
}
}
//update-end-author:taoyan date:2023-3-4 for: 导入数据支持指定sheet名称
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(" start to read excel by is ,startTime is {}", System.currentTimeMillis());
}
if (isXSSFWorkbook) {
pictures = PoiPublicUtil.getSheetPictrues07((XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);
} else {
pictures = PoiPublicUtil.getSheetPictrues03((HSSFSheet) book.getSheetAt(i), (HSSFWorkbook) book);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(" end to read excel by is ,endTime is {}", new Date().getTime());
}
result.addAll(importExcel(result, book.getSheetAt(i), pojoClass, params, pictures));
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(" end to read excel list by pos ,endTime is {}", new Date().getTime());
}
}
if (params.isNeedSave()) {
saveThisExcel(params, pojoClass, isXSSFWorkbook, book);
}
return new ExcelImportResult(result, verfiyFail, book);
}
/**
*
* @param is
* @return
* @throws IOException
*/
public static byte[] getBytes(InputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int len;
byte[] data = new byte[100000];
while ((len = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, len);
}
buffer.flush();
return buffer.toByteArray();
}
/**
* 保存字段值(获取值,校验值,追加错误信息)
*
* @param params
* @param object
* @param cell
* @param excelParams
* @param titleString
* @param row
* @throws Exception
*/
private void saveFieldValue(ImportParams params, Object object, Cell cell, Map<String, ExcelImportEntity> excelParams, String titleString, Row row) throws Exception {
Object value = cellValueServer.getValue(params.getDataHanlder(), object, cell, excelParams, titleString);
if (object instanceof Map) {
if (params.getDataHanlder() != null) {
params.getDataHanlder().setMapValue((Map) object, titleString, value);
} else {
((Map) object).put(titleString, value);
}
} else {
ExcelVerifyHanlderResult verifyResult = verifyHandlerServer.verifyData(object, value, titleString, excelParams.get(titleString).getVerify(), params.getVerifyHanlder());
if (verifyResult.isSuccess()) {
setValues(excelParams.get(titleString), object, value);
} else {
Cell errorCell = row.createCell(row.getLastCellNum());
errorCell.setCellValue(verifyResult.getMsg());
errorCell.setCellStyle(errorCellStyle);
verfiyFail = true;
throw new ExcelImportException(ExcelImportEnum.VERIFY_ERROR);
}
}
}
/**
*
* @param object
* @param picId
* @param excelParams
* @param titleString
* @param pictures
* @param params
* @throws Exception
*/
private void saveImage(Object object, String picId, Map<String, ExcelImportEntity> excelParams, String titleString, Map<String, PictureData> pictures, ImportParams params) throws Exception {
if (pictures == null || pictures.get(picId)==null) {
return;
}
PictureData image = pictures.get(picId);
byte[] data = image.getData();
String fileName = "pic" + Math.round(Math.random() * 100000000000L);
fileName += "." + PoiPublicUtil.getFileExtendName(data);
//update-beign-author:taoyan date:20200302 for:【多任务】online 专项集中问题 LOWCOD-159
int saveType = excelParams.get(titleString).getSaveType();
if ( saveType == 1) {
String path = PoiPublicUtil.getWebRootPath(getSaveUrl(excelParams.get(titleString), object));
File savefile = new File(path);
if (!savefile.exists()) {
savefile.mkdirs();
}
savefile = new File(path + "/" + fileName);
FileOutputStream fos = new FileOutputStream(savefile);
fos.write(data);
fos.close();
setValues(excelParams.get(titleString), object, getSaveUrl(excelParams.get(titleString), object) + "/" + fileName);
} else if(saveType==2) {
setValues(excelParams.get(titleString), object, data);
} else {
ImportFileServiceI importFileService = null;
try {
importFileService = ApplicationContextUtil.getContext().getBean(ImportFileServiceI.class);
} catch (Exception e) {
System.err.println(e.getMessage());
}
if(importFileService!=null){
//update-beign-author:liusq date:20230411 for:【issue/4415】autopoi-web 导入图片字段时无法指定保存路径
String saveUrl = excelParams.get(titleString).getSaveUrl();
String dbPath;
if(StringUtils.isNotBlank(saveUrl)){
LOGGER.debug("图片保存路径saveUrl = "+saveUrl);
Matcher matcher = lettersAndNumbersPattern.matcher(saveUrl);
if(!matcher.matches()){
LOGGER.warn("图片保存路径格式错误,只能设置字母和数字的组合!");
dbPath = importFileService.doUpload(data);
}else{
dbPath = importFileService.doUpload(data,saveUrl);
}
}else{
dbPath = importFileService.doUpload(data);
}
//update-end-author:liusq date:20230411 for:【issue/4415】autopoi-web 导入图片字段时无法指定保存路径
setValues(excelParams.get(titleString), object, dbPath);
}
}
//update-end-author:taoyan date:20200302 for:【多任务】online 专项集中问题 LOWCOD-159
}
private void createErrorCellStyle(Workbook workbook) {
errorCellStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setColor(Font.COLOR_RED);
errorCellStyle.setFont(font);
}
}

View File

@@ -0,0 +1,328 @@
/**
* 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.imports.base;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.jeecgframework.dict.service.AutoPoiDictServiceI;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.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.util.PoiPublicUtil;
/**
* 导入基础和,普通方法和Sax共用
*
* @author JEECG
* @date 2015年1月9日 下午10:25:53
*/
public class ImportBaseService {
/**
* 把这个注解解析放到类型对象中
*
* @param targetId
* @param field
* @param excelEntity
* @param pojoClass
* @param getMethods
* @param temp
* @throws Exception
*/
public void addEntityToMap(String targetId, Field field, ExcelImportEntity excelEntity, Class<?> pojoClass, List<Method> getMethods, Map<String, ExcelImportEntity> 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:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndex
excelEntity.setFixedIndex(excel.fixedIndex());
//update-end-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndex
//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<Method> newMethods = new ArrayList<Method>();
newMethods.addAll(getMethods);
newMethods.add(excelEntity.getMethod());
excelEntity.setMethods(newMethods);
}
//update-begin-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndex
if (excelEntity.getFixedIndex() != -1) {
temp.put("FIXED_" + excelEntity.getFixedIndex(), excelEntity);
} else {
temp.put(excelEntity.getName(), excelEntity);
}
//update-end-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndex
}
/**
* 获取导入校验参数
*
* @param field
* @return
*/
public 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;
}
/**
* 获取需要导出的全部字段
*
* @param targetId
* 目标ID
* @param fields
* @param excelCollection
* @throws Exception
*/
public void getAllExcelField(String targetId, Field[] fields, Map<String, ExcelImportEntity> excelParams, List<ExcelCollectionParams> excelCollection, Class<?> pojoClass, List<Method> 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<String, ExcelImportEntity> temp = new HashMap<String, ExcelImportEntity>();
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> clz = (Class<?>) pt.getActualTypeArguments()[0];
collection.setType(clz);
getExcelFieldList(targetId, PoiPublicUtil.getClassFields(clz), clz, temp, null);
collection.setExcelParams(temp);
collection.setExcelName(field.getAnnotation(ExcelCollection.class).name());
additionalCollectionName(collection);
excelCollection.add(collection);
} else if (PoiPublicUtil.isJavaClass(field)) {
addEntityToMap(targetId, field, excelEntity, pojoClass, getMethods, excelParams);
} else {
List<Method> newMethods = new ArrayList<Method>();
if (getMethods != null) {
newMethods.addAll(getMethods);
}
newMethods.add(PoiPublicUtil.getMethod(field.getName(), pojoClass));
//update-begin-author:taoyan date:20210531 for:excel导入支持 注解@ExcelEntity显示合并表头
ExcelEntity excel = field.getAnnotation(ExcelEntity.class);
if(excel.show()==true){
Map<String, ExcelImportEntity> subExcelParams = new HashMap<>();
// 这里有个设计的坑导出的时候最后一个参数是null, 即getgetMethods获取的是空导入的时候需要设置层级getmethod
getAllExcelField(targetId, PoiPublicUtil.getClassFields(field.getType()), subExcelParams, excelCollection, field.getType(), newMethods);
for(String key: subExcelParams.keySet()){
excelParams.put(excel.name()+"_"+key, subExcelParams.get(key));
}
}else{
getAllExcelField(targetId, PoiPublicUtil.getClassFields(field.getType()), excelParams, excelCollection, field.getType(), newMethods);
}
//update-end-author:taoyan date:20210531 for:excel导入支持 注解@ExcelEntity显示合并表头
}
}
}
/**
* 追加集合名称到前面
*
* @param collection
*/
private void additionalCollectionName(ExcelCollectionParams collection) {
Set<String> keys = new HashSet<String>();
keys.addAll(collection.getExcelParams().keySet());
for (String key : keys) {
collection.getExcelParams().put(collection.getExcelName() + "_" + key, collection.getExcelParams().get(key));
collection.getExcelParams().remove(key);
}
}
public 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());
}
}
public void getExcelFieldList(String targetId, Field[] fields, Class<?> pojoClass, Map<String, ExcelImportEntity> temp, List<Method> 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.isJavaClass(field)) {
addEntityToMap(targetId, field, excelEntity, pojoClass, getMethods, temp);
} else {
List<Method> newMethods = new ArrayList<Method>();
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 exportName
* @param targetId
* @return
*/
public String getExcelName(String exportName, String targetId) {
if (exportName.indexOf("_") < 0) {
return exportName;
}
if (StringUtils.isBlank(targetId)) {
return exportName;
}
String[] arr = exportName.split(",");
for (String str : arr) {
if (str.indexOf(targetId) != -1) {
//update-begin-author:liusq date20210127 for:targetId问题处理
//return str.split("_")[0];
return str.replace("_"+targetId,"");
//update-end-author:liusq date20210127 for:targetId问题处理
}
}
return null;
}
public Object getFieldBySomeMethod(List<Method> list, Object t) throws Exception {
Method m;
for (int i = 0; i < list.size() - 1; i++) {
m = list.get(i);
t = m.invoke(t, new Object[] {});
}
return t;
}
public void saveThisExcel(ImportParams params, Class<?> pojoClass, boolean isXSSFWorkbook, Workbook book) throws Exception {
String path = PoiPublicUtil.getWebRootPath(getSaveExcelUrl(params, pojoClass));
File savefile = new File(path);
if (!savefile.exists()) {
savefile.mkdirs();
}
SimpleDateFormat format = new SimpleDateFormat("yyyMMddHHmmss");
FileOutputStream fos = new FileOutputStream(path + "/" + format.format(new Date()) + "_" + Math.round(Math.random() * 100000) + (isXSSFWorkbook == true ? ".xlsx" : ".xls"));
book.write(fos);
fos.close();
}
/**
* 获取保存的Excel 的真实路径
*
* @param params
* @param pojoClass
* @return
* @throws Exception
*/
public String getSaveExcelUrl(ImportParams params, Class<?> pojoClass) throws Exception {
String url = "";
if (params.getSaveUrl().equals("upload/excelUpload")) {
url = pojoClass.getName().split("\\.")[pojoClass.getName().split("\\.").length - 1];
return params.getSaveUrl() + "/" + url;
}
return params.getSaveUrl();
}
/**
* 多个get 最后再set
*
* @param setMethods
* @param object
*/
public void setFieldBySomeMethod(List<Method> setMethods, Object object, Object value) throws Exception {
Object t = getFieldBySomeMethod(setMethods, object);
setMethods.get(setMethods.size() - 1).invoke(t, value);
}
/**
*
* @param entity
* @param object
* @param value
* @throws Exception
*/
public void setValues(ExcelImportEntity entity, Object object, Object value) throws Exception {
if (entity.getMethods() != null) {
setFieldBySomeMethod(entity.getMethods(), object, value);
} else {
entity.getMethod().invoke(object, value);
}
}
}

View File

@@ -0,0 +1,20 @@
package org.jeecgframework.poi.excel.imports.base;
public interface ImportFileServiceI {
/**
* 上传文件 返回文件地址字符串
* @param data
* @return
*/
String doUpload(byte[] data);
/**
* 上传文件 返回文件地址字符串
* @param data
* @param saveUrl 保存路径
* @return
*/
String doUpload(byte[] data,String saveUrl);
}

View File

@@ -0,0 +1,6 @@
/**
* 导入类
* @author JEECG
* @date 2014年6月23日 下午11:05:59
*/
package org.jeecgframework.poi.excel.imports;

View File

@@ -0,0 +1,91 @@
/**
* 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.imports.sax;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.imports.sax.parse.ISaxRowRead;
import org.jeecgframework.poi.excel.imports.sax.parse.SaxRowRead;
import org.jeecgframework.poi.exception.excel.ExcelImportException;
import org.jeecgframework.poi.handler.inter.IExcelReadRowHanlder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* 基于SAX Excel大数据读取,读取Excel 07版本,不支持图片读取
*
* @author JEECG
* @date 2014年12月29日 下午9:41:38
* @version 1.0
*/
@SuppressWarnings("rawtypes")
public class SaxReadExcel {
private static final Logger LOGGER = LoggerFactory.getLogger(SaxReadExcel.class);
public <T> List<T> readExcel(InputStream inputstream, Class<?> pojoClass, ImportParams params, ISaxRowRead rowRead, IExcelReadRowHanlder hanlder) {
try {
OPCPackage opcPackage = OPCPackage.open(inputstream);
return readExcel(opcPackage, pojoClass, params, rowRead, hanlder);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException(e.getMessage());
}
}
private <T> List<T> readExcel(OPCPackage opcPackage, Class<?> pojoClass, ImportParams params, ISaxRowRead rowRead, IExcelReadRowHanlder hanlder) {
try {
XSSFReader xssfReader = new XSSFReader(opcPackage);
SharedStringsTable sst = (SharedStringsTable) xssfReader.getSharedStringsTable();
if (rowRead == null) {
rowRead = new SaxRowRead(pojoClass, params, hanlder);
}
XMLReader parser = fetchSheetParser(sst, rowRead);
Iterator<InputStream> sheets = xssfReader.getSheetsData();
int sheetIndex = 0;
while (sheets.hasNext() && sheetIndex < params.getSheetNum()) {
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
return rowRead.getList();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException("SAX导入数据失败");
}
}
private XMLReader fetchSheetParser(SharedStringsTable sst, ISaxRowRead rowRead) throws SAXException {
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
ContentHandler handler = new SheetHandler(sst, rowRead);
parser.setContentHandler(handler);
return parser;
}
}

View File

@@ -0,0 +1,136 @@
/**
* 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.imports.sax;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.jeecgframework.poi.excel.entity.enmus.CellValueType;
import org.jeecgframework.poi.excel.entity.sax.SaxReadCellEntity;
import org.jeecgframework.poi.excel.imports.sax.parse.ISaxRowRead;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.google.common.collect.Lists;
/**
* 回调接口
*
* @author JEECG
* @date 2014年12月29日 下午9:50:09
*/
public class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
// 当前行
private int curRow = 0;
// 当前列
private int curCol = 0;
private CellValueType type;
private ISaxRowRead read;
// 存储行记录的容器
private List<SaxReadCellEntity> rowlist = Lists.newArrayList();
public SheetHandler(SharedStringsTable sst, ISaxRowRead rowRead) {
this.sst = sst;
this.read = rowRead;
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
// 置空
lastContents = "";
// c => 单元格
if ("c".equals(name)) {
// 如果下一个元素是 SST 的索引则将nextIsString标记为true
String cellType = attributes.getValue("t");
if ("s".equals(cellType)) {
type = CellValueType.String;
return;
}
// 日期格式
cellType = attributes.getValue("s");
if ("1".equals(cellType)) {
type = CellValueType.Date;
} else if ("2".equals(cellType)) {
type = CellValueType.Number;
}
} else if ("t".equals(name)) {// 当元素为t时
type = CellValueType.TElement;
}
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
// 根据SST的索引值的到单元格的真正要存储的字符串
// 这时characters()方法可能会被调用多次
if (CellValueType.String.equals(type)) {
try {
int idx = Integer.parseInt(lastContents);
lastContents = sst.getItemAt(idx).getString();
} catch (Exception e) {
}
}
// t元素也包含字符串
if (CellValueType.TElement.equals(type)) {
String value = lastContents.trim();
rowlist.add(curCol, new SaxReadCellEntity(CellValueType.String, value));
curCol++;
type = CellValueType.None;
// v => 单元格的值如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中在这之前先去掉字符串前后的空白符
} else if ("v".equals(name)) {
String value = lastContents.trim();
value = value.equals("") ? " " : value;
if (CellValueType.Date.equals(type)) {
Date date = DateUtil.getJavaDate(Double.valueOf(value));
rowlist.add(curCol, new SaxReadCellEntity(CellValueType.Date, date));
} else if (CellValueType.Number.equals(type)) {
BigDecimal bd = new BigDecimal(value);
rowlist.add(curCol, new SaxReadCellEntity(CellValueType.Number, bd));
} else if (CellValueType.String.equals(type)) {
rowlist.add(curCol, new SaxReadCellEntity(CellValueType.String, value));
}
curCol++;
} else if (name.equals("row")) {// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
read.parse(curRow, rowlist);
rowlist.clear();
curRow++;
curCol = 0;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 得到单元格内容的值
lastContents += new String(ch, start, length);
}
}

View File

@@ -0,0 +1,39 @@
/**
* 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.imports.sax.parse;
import java.util.List;
import org.jeecgframework.poi.excel.entity.sax.SaxReadCellEntity;
public interface ISaxRowRead {
/**
* 获取返回数据
*
* @param <T>
* @return
*/
public <T> List<T> getList();
/**
* 解析数据
*
* @param index
* @param datas
*/
public void parse(int index, List<SaxReadCellEntity> datas);
}

View File

@@ -0,0 +1,213 @@
/**
* 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.imports.sax.parse;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
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.sax.SaxReadCellEntity;
import org.jeecgframework.poi.excel.imports.CellValueServer;
import org.jeecgframework.poi.excel.imports.base.ImportBaseService;
import org.jeecgframework.poi.exception.excel.ExcelImportException;
import org.jeecgframework.poi.handler.inter.IExcelReadRowHanlder;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
/**
* 当行读取数据
*
* @author JEECG
* @param <T>
* @date 2015年1月1日 下午7:59:39
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class SaxRowRead extends ImportBaseService implements ISaxRowRead {
private static final Logger LOGGER = LoggerFactory.getLogger(SaxRowRead.class);
/** 需要返回的数据 **/
private List list;
/** 导出的对象 **/
private Class<?> pojoClass;
/** 导入参数 **/
private ImportParams params;
/** 列表头对应关系 **/
private Map<Integer, String> titlemap = new HashMap<Integer, String>();
/** 当前的对象 **/
private Object object = null;
private Map<String, ExcelImportEntity> excelParams = new HashMap<String, ExcelImportEntity>();
private List<ExcelCollectionParams> excelCollection = new ArrayList<ExcelCollectionParams>();
private String targetId;
private CellValueServer cellValueServer;
private IExcelReadRowHanlder hanlder;
public SaxRowRead(Class<?> pojoClass, ImportParams params, IExcelReadRowHanlder hanlder) {
list = Lists.newArrayList();
this.params = params;
this.pojoClass = pojoClass;
cellValueServer = new CellValueServer();
this.hanlder = hanlder;
initParams(pojoClass, params);
}
private void initParams(Class<?> pojoClass, ImportParams params) {
try {
Field fileds[] = PoiPublicUtil.getClassFields(pojoClass);
ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
if (etarget != null) {
targetId = etarget.value();
}
getAllExcelField(targetId, fileds, excelParams, excelCollection, pojoClass, null);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException(e.getMessage());
}
}
@Override
public <T> List<T> getList() {
return list;
}
@Override
public void parse(int index, List<SaxReadCellEntity> datas) {
try {
if (datas == null || datas.size() == 0) {
return;
}
// 标题行跳过
if (index < params.getTitleRows()) {
return;
}
// 表头行
if (index < params.getTitleRows() + params.getHeadRows()) {
addHeadData(datas);
} else {
addListData(datas);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException(e.getMessage());
}
}
/**
* 集合元素处理
*
* @param datas
*/
private void addListData(List<SaxReadCellEntity> datas) throws Exception {
// 判断是集合元素还是不是集合元素,如果是就继续加入这个集合,不是就创建新的对象
if ((datas.get(params.getKeyIndex()) == null || StringUtils.isEmpty(String.valueOf(datas.get(params.getKeyIndex()).getValue()))) && object != null) {
for (ExcelCollectionParams param : excelCollection) {
addListContinue(object, param, datas, titlemap, targetId, params);
}
} else {
if (object != null && hanlder != null) {
hanlder.hanlder(object);
}
object = PoiPublicUtil.createObject(pojoClass, targetId);
SaxReadCellEntity entity;
for (int i = 0, le = datas.size(); i < le; i++) {
entity = datas.get(i);
String titleString = (String) titlemap.get(i);
if (excelParams.containsKey(titleString)) {
saveFieldValue(params, object, entity, excelParams, titleString);
}
}
for (ExcelCollectionParams param : excelCollection) {
addListContinue(object, param, datas, titlemap, targetId, params);
}
if (hanlder == null) {
list.add(object);
}
}
}
/***
* 向List里面继续添加元素
*
* @param exclusions
* @param object
* @param param
* @param datas
* @param titlemap
* @param targetId
* @param params
*/
private void addListContinue(Object object, ExcelCollectionParams param, List<SaxReadCellEntity> datas, Map<Integer, String> titlemap, String targetId, ImportParams params) throws Exception {
Collection collection = (Collection) PoiPublicUtil.getMethod(param.getName(), object.getClass()).invoke(object, new Object[] {});
Object entity = PoiPublicUtil.createObject(param.getType(), targetId);
boolean isUsed = false;// 是否需要加上这个对象
for (int i = 0; i < datas.size(); i++) {
String titleString = (String) titlemap.get(i);
if (param.getExcelParams().containsKey(titleString)) {
saveFieldValue(params, entity, datas.get(i), param.getExcelParams(), titleString);
isUsed = true;
}
}
if (isUsed) {
collection.add(entity);
}
}
/**
* 设置值
*
* @param params
* @param object
* @param entity
* @param excelParams
* @param titleString
* @throws Exception
*/
private void saveFieldValue(ImportParams params, Object object, SaxReadCellEntity entity, Map<String, ExcelImportEntity> excelParams, String titleString) throws Exception {
Object value = cellValueServer.getValue(params.getDataHanlder(), object, entity, excelParams, titleString);
setValues(excelParams.get(titleString), object, value);
}
/**
* put 表头数据
*
* @param datas
*/
private void addHeadData(List<SaxReadCellEntity> datas) {
for (int i = 0; i < datas.size(); i++) {
if (StringUtils.isNotEmpty(String.valueOf(datas.get(i).getValue()))) {
titlemap.put(i, String.valueOf(datas.get(i).getValue()));
}
}
}
}

View File

@@ -0,0 +1,145 @@
/**
* 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.imports.verifys;
import java.util.regex.Pattern;
import org.jeecgframework.poi.excel.entity.result.ExcelVerifyHanlderResult;
/**
* 基础校验工具类
*
* @author JEECG
* @date 2014年6月23日 下午11:10:12
*/
public class BaseVerifyHandler {
private static String NOT_NULL = "不允许为空";
private static String IS_MOBILE = "不是手机号";
private static String IS_TEL = "不是电话号码";
private static String IS_EMAIL = "不是邮箱地址";
private static String MIN_LENGHT = "小于规定长度";
private static String MAX_LENGHT = "超过规定长度";
private static Pattern mobilePattern = Pattern.compile("^[1][3,4,5,8,7][0-9]{9}$");
private static Pattern telPattern = Pattern.compile("^([0][1-9]{2,3}-)?[0-9]{5,10}$");
private static Pattern emailPattern = Pattern.compile("^([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$");
/**
* email校验
*
* @param name
* @param val
* @return
*/
public static ExcelVerifyHanlderResult isEmail(String name, Object val) {
if (!emailPattern.matcher(String.valueOf(val)).matches()) {
return new ExcelVerifyHanlderResult(false, name + IS_EMAIL);
}
return new ExcelVerifyHanlderResult(true);
}
/**
* 手机校验
*
* @param name
* @param val
* @return
*/
public static ExcelVerifyHanlderResult isMobile(String name, Object val) {
if (!mobilePattern.matcher(String.valueOf(val)).matches()) {
return new ExcelVerifyHanlderResult(false, name + IS_MOBILE);
}
return new ExcelVerifyHanlderResult(true);
}
/**
* 电话校验
*
* @param name
* @param val
* @return
*/
public static ExcelVerifyHanlderResult isTel(String name, Object val) {
if (!telPattern.matcher(String.valueOf(val)).matches()) {
return new ExcelVerifyHanlderResult(false, name + IS_TEL);
}
return new ExcelVerifyHanlderResult(true);
}
/**
* 最大长度校验
*
* @param name
* @param val
* @return
*/
public static ExcelVerifyHanlderResult maxLength(String name, Object val, int maxLength) {
if (notNull(name, val).isSuccess() && String.valueOf(val).length() > maxLength) {
return new ExcelVerifyHanlderResult(false, name + MAX_LENGHT);
}
return new ExcelVerifyHanlderResult(true);
}
/**
* 最小长度校验
*
* @param name
* @param val
* @param minLength
* @return
*/
public static ExcelVerifyHanlderResult minLength(String name, Object val, int minLength) {
if (notNull(name, val).isSuccess() && String.valueOf(val).length() < minLength) {
return new ExcelVerifyHanlderResult(false, name + MIN_LENGHT);
}
return new ExcelVerifyHanlderResult(true);
}
/**
* 非空校验
*
* @param name
* @param val
* @return
*/
public static ExcelVerifyHanlderResult notNull(String name, Object val) {
if (val == null || val.toString().equals("")) {
return new ExcelVerifyHanlderResult(false, name + NOT_NULL);
}
return new ExcelVerifyHanlderResult(true);
}
/**
* 正则表达式校验
*
* @param name
* @param val
* @param regex
* @param regexTip
* @return
*/
public static ExcelVerifyHanlderResult regex(String name, Object val, String regex, String regexTip) {
Pattern pattern = Pattern.compile(regex);
if (!pattern.matcher(String.valueOf(val)).matches()) {
return new ExcelVerifyHanlderResult(false, name + regexTip);
}
return new ExcelVerifyHanlderResult(true);
}
}

View File

@@ -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.imports.verifys;
import org.apache.commons.lang3.StringUtils;
import org.jeecgframework.poi.excel.entity.params.ExcelVerifyEntity;
import org.jeecgframework.poi.excel.entity.result.ExcelVerifyHanlderResult;
import org.jeecgframework.poi.handler.inter.IExcelVerifyHandler;
/**
* 校验服务
*
* @author JEECG
* @date 2014年6月29日 下午4:37:56
*/
public class VerifyHandlerServer {
private final static ExcelVerifyHanlderResult DEFAULT_RESULT = new ExcelVerifyHanlderResult(true);
private void addVerifyResult(ExcelVerifyHanlderResult hanlderResult, ExcelVerifyHanlderResult result) {
if (!hanlderResult.isSuccess()) {
result.setSuccess(false);
result.setMsg((StringUtils.isEmpty(result.getMsg()) ? "" : result.getMsg() + " , ") + hanlderResult.getMsg());
}
}
/**
* 校驗數據
*
* @param object
* @param value
* @param titleString
* @param verify
* @param excelVerifyHandler
*/
public ExcelVerifyHanlderResult verifyData(Object object, Object value, String name, ExcelVerifyEntity verify, IExcelVerifyHandler excelVerifyHandler) {
if (verify == null) {
return DEFAULT_RESULT;
}
ExcelVerifyHanlderResult result = new ExcelVerifyHanlderResult(true, "");
if (verify.isNotNull()) {
addVerifyResult(BaseVerifyHandler.notNull(name, value), result);
}
if (verify.isEmail()) {
addVerifyResult(BaseVerifyHandler.isEmail(name, value), result);
}
if (verify.isMobile()) {
addVerifyResult(BaseVerifyHandler.isMobile(name, value), result);
}
if (verify.isTel()) {
addVerifyResult(BaseVerifyHandler.isTel(name, value), result);
}
if (verify.getMaxLength() != -1) {
addVerifyResult(BaseVerifyHandler.maxLength(name, value, verify.getMaxLength()), result);
}
if (verify.getMinLength() != -1) {
addVerifyResult(BaseVerifyHandler.minLength(name, value, verify.getMinLength()), result);
}
if (StringUtils.isNotEmpty(verify.getRegex())) {
addVerifyResult(BaseVerifyHandler.regex(name, value, verify.getRegex(), verify.getRegexTip()), result);
}
if (verify.isInterHandler()) {
addVerifyResult(excelVerifyHandler.verifyHandler(object, name, value), result);
}
return result;
}
}

View File

@@ -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.exception.excel;
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
/**
* 导出异常
*
* @author JEECG
* @date 2014年6月19日 下午10:56:18
*/
public class ExcelExportException extends RuntimeException {
private static final long serialVersionUID = 1L;
private ExcelExportEnum type;
public ExcelExportException() {
super();
}
public ExcelExportException(ExcelExportEnum type) {
super(type.getMsg());
this.type = type;
}
public ExcelExportException(ExcelExportEnum type, Throwable cause) {
super(type.getMsg(), cause);
}
public ExcelExportException(String message) {
super(message);
}
public ExcelExportException(String message, ExcelExportEnum type) {
super(message);
this.type = type;
}
public ExcelExportEnum getType() {
return type;
}
public void setType(ExcelExportEnum type) {
this.type = type;
}
}

View File

@@ -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.exception.excel;
import org.jeecgframework.poi.exception.excel.enums.ExcelImportEnum;
/**
* 导入异常
*
* @author JEECG
* @date 2014年6月29日 下午2:23:43
*/
public class ExcelImportException extends RuntimeException {
private static final long serialVersionUID = 1L;
private ExcelImportEnum type;
public ExcelImportException() {
super();
}
public ExcelImportException(ExcelImportEnum type) {
super(type.getMsg());
this.type = type;
}
public ExcelImportException(ExcelImportEnum type, Throwable cause) {
super(type.getMsg(), cause);
}
public ExcelImportException(String message) {
super(message);
}
public ExcelImportException(String message, ExcelImportEnum type) {
super(message);
this.type = type;
}
public ExcelImportEnum getType() {
return type;
}
public void setType(ExcelImportEnum type) {
this.type = type;
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.exception.excel.enums;
/**
* 导出异常类型枚举
*
* @author JEECG
* @date 2014年6月19日 下午10:59:51
*/
public enum ExcelExportEnum {
PARAMETER_ERROR("Excel 导出 参数错误"), EXPORT_ERROR("Excel导出错误"),TEMPLATE_ERROR ("Excel 模板错误");;
private String msg;
ExcelExportEnum(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.exception.excel.enums;
/**
* 导出异常类型枚举
*
* @author JEECG
* @date 2014年6月19日 下午10:59:51
*/
public enum ExcelImportEnum {
GET_VALUE_ERROR("Excel 值获取失败"), VERIFY_ERROR("值校验失败");
private String msg;
ExcelImportEnum(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.exception.word;
import org.jeecgframework.poi.exception.word.enmus.WordExportEnum;
/**
* word导出异常
*
* @author JEECG
* @date 2014年8月9日 下午10:32:51
*/
public class WordExportException extends RuntimeException {
private static final long serialVersionUID = 1L;
public WordExportException() {
super();
}
public WordExportException(String msg) {
super(msg);
}
public WordExportException(WordExportEnum exception) {
super(exception.getMsg());
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.exception.word.enmus;
/**
* 导出异常枚举
*
* @author JEECG
* @date 2014年8月9日 下午10:34:58
*/
public enum WordExportEnum {
EXCEL_PARAMS_ERROR("Excel 导出 参数错误"), EXCEL_HEAD_HAVA_NULL("Excel 表头 有的字段为空"), EXCEL_NO_HEAD("Excel 没有表头");
private String msg;
WordExportEnum(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

View File

@@ -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.handler.impl;
import java.util.Map;
import org.jeecgframework.poi.handler.inter.IExcelDataHandler;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink;
/**
* 数据处理默认实现,返回空
*
* @author JEECG
* @date 2014年6月20日 上午12:11:52
*/
public abstract class ExcelDataHandlerDefaultImpl implements IExcelDataHandler {
/**
* 需要处理的字段
*/
private String[] needHandlerFields;
@Override
public Object exportHandler(Object obj, String name, Object value) {
return value;
}
@Override
public String[] getNeedHandlerFields() {
return needHandlerFields;
}
@Override
public Object importHandler(Object obj, String name, Object value) {
return value;
}
@Override
public void setNeedHandlerFields(String[] needHandlerFields) {
this.needHandlerFields = needHandlerFields;
}
@Override
public void setMapValue(Map<String, Object> map, String originKey, Object value) {
map.put(originKey, value);
}
@Override
public Hyperlink getHyperlink(CreationHelper creationHelper, Object obj, String name, Object value) {
return null;
}
}

View File

@@ -0,0 +1,6 @@
/**
* 对接口的抽象的默认实现,避免用户实现过多方法
* @author JEECG
* @date 2014年6月20日 上午12:09:27
*/
package org.jeecgframework.poi.handler.impl;

View File

@@ -0,0 +1,87 @@
/**
* 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.handler.inter;
import java.util.Map;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink;
/**
* Excel 导入导出 数据处理接口
*
* @author JEECG
* @date 2014年6月19日 下午11:59:45
*/
public interface IExcelDataHandler {
/**
* 导出处理方法
*
* @param obj
* 当前对象
* @param name
* 当前字段名称
* @param value
* 当前值
* @return
*/
public Object exportHandler(Object obj, String name, Object value);
/**
* 获取需要处理的字段,导入和导出统一处理了, 减少书写的字段
*
* @return
*/
public String[] getNeedHandlerFields();
/**
* 导入处理方法 当前对象,当前字段名称,当前值
*
* @param obj
* 当前对象
* @param name
* 当前字段名称
* @param value
* 当前值
* @return
*/
public Object importHandler(Object obj, String name, Object value);
/**
* 设置需要处理的属性列表
*
* @param fields
*/
public void setNeedHandlerFields(String[] fields);
/**
* 设置Map导入,自定义 put
*
* @param map
* @param originKey
* @param value
*/
public void setMapValue(Map<String, Object> map, String originKey, Object value);
/**
* 获取这个字段的 Hyperlink ,07版本需要,03版本不需要
* @param creationHelper
* @param obj
* @param name
* @param value
* @return
*/
public Hyperlink getHyperlink(CreationHelper creationHelper, Object obj, String name, Object value);
}

View File

@@ -0,0 +1,32 @@
package org.jeecgframework.poi.handler.inter;
/**
* 字典翻译处理
* @author liusq
* @date 2022-05-27
*/
public interface IExcelDictHandler {
/**
* 从值翻译到名称
*
* @param dict 字典Key
* @param obj 对象
* @param name 属性名称
* @param value 属性值
* @return
*/
public String toName(String dict, Object obj, String name, Object value);
/**
* 从名称翻译到值
*
* @param dict 字典Key
* @param obj 对象
* @param name 属性名称
* @param value 属性值
* @return
*/
public String toValue(String dict, Object obj, String name, Object value);
}

View File

@@ -0,0 +1,21 @@
package org.jeecgframework.poi.handler.inter;
import java.util.List;
/**
* 导出数据接口
* @Description [LOWCOD-2521]【autopoi】大数据导出方法【全局】
* @author liusq
* @date 2022年1月4号
*/
public interface IExcelExportServer {
/**
* 查询数据接口
*
* @param queryParams 查询条件
* @param page 当前页数从1开始
* @data 2022年1月4号
* @return
*/
public List<Object> selectListForExcelExport(Object queryParams, int page);
}

View File

@@ -0,0 +1,33 @@
/**
* 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.handler.inter;
/**
* 接口自定义处理类
*
* @author JEECG
* @date 2015年1月16日 下午8:06:26
* @param <T>
*/
public interface IExcelReadRowHanlder<T> {
/**
* 处理解析对象
*
* @param t
*/
public void hanlder(T t);
}

View File

@@ -0,0 +1,55 @@
/**
* 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.handler.inter;
import org.jeecgframework.poi.excel.entity.result.ExcelVerifyHanlderResult;
/**
* 导入校验接口
*
* @author JEECG
* @date 2014年6月23日 下午11:08:21
*/
public interface IExcelVerifyHandler {
/**
* 获取需要处理的字段,导入和导出统一处理了, 减少书写的字段
*
* @return
*/
public String[] getNeedVerifyFields();
/**
* 获取需要处理的字段,导入和导出统一处理了, 减少书写的字段
*
* @return
*/
public void setNeedVerifyFields(String[] arr);
/**
* 导出处理方法
*
* @param obj
* 当前对象
* @param name
* 当前字段名称
* @param value
* 当前值
* @return
*/
public ExcelVerifyHanlderResult verifyHandler(Object obj, String name, Object value);
}

View File

@@ -0,0 +1,35 @@
package org.jeecgframework.poi.handler.inter;
import java.util.Collection;
/**
* 大数据写出服务接口
*
* @Description [LOWCOD-2521]【autopoi】大数据导出方法【全局】
* @author liusq
* @date 2022年1月4号
*/
public interface IWriter<T> {
/**
* 获取输出对象
*
* @return
*/
default public T get() {
return null;
}
/**
* 写入数据
*
* @param data
* @return
*/
public IWriter<T> write(Collection data);
/**
* 关闭流,完成业务
*
* @return
*/
public T close();
}

View File

@@ -0,0 +1,6 @@
/**
* 数据处理中心,对导入导出进行数据处理
* @author JEECG
* @date 2014年6月20日 上午12:08:09
*/
package org.jeecgframework.poi.handler;

View File

@@ -0,0 +1,13 @@
/**
* @author JEECG
* @date 2014年2月10日
* @version 1.0
* 对POI进行封装,通过注解的使用,完成POI的简易重复操作
* 通过模板完成较为复杂的操作
* 进阶步骤:<br/>
* <p>1.了解注解,图片类</p>
* <p>2.模板语言</p>
* <p>3.模板组合</p>
*
*/
package org.jeecgframework.poi;

View File

@@ -0,0 +1,327 @@
package org.jeecgframework.poi.util;
/**
* @author Link Xue
* @version 20171025
* POI对EXCEL操作工具
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.util.CellRangeAddress;
public class ExcelUtil {
public static void main(String[] args){
//读取excel数据
ArrayList<Map<String,String>> result = ExcelUtil.readExcelToObj("D:\\上传表.xlsx");
for(Map<String,String> map:result){
System.out.println(map);
}
}
/**
* 读取excel数据
* @param path
*/
public static ArrayList<Map<String,String>> readExcelToObj(String path) {
Workbook wb = null;
ArrayList<Map<String,String>> result = null;
try {
wb = WorkbookFactory.create(new File(path));
result = readExcel(wb, 0, 2, 0);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 读取excel文件
* @param wb
* @param sheetIndex sheet页下标从0开始
* @param startReadLine 开始读取的行:从0开始
* @param tailLine 去除最后读取的行
*/
public static ArrayList<Map<String,String>> readExcel(Workbook wb,int sheetIndex, int startReadLine, int tailLine) {
Sheet sheet = wb.getSheetAt(sheetIndex);
Row row = null;
ArrayList<Map<String,String>> result = new ArrayList<Map<String,String>>();
for(int i=startReadLine; i<sheet.getLastRowNum()-tailLine+1; i++) {
row = sheet.getRow(i);
Map<String,String> map = new HashMap<String,String>();
for(Cell c : row) {
String returnStr = "";
boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex());
//判断是否具有合并单元格
if(isMerge) {
String rs = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex());
// System.out.print(rs + "------ ");
returnStr = rs;
}else {
// System.out.print(c.getRichStringCellValue()+"++++ ");
returnStr = c.getRichStringCellValue().getString();
}
if(c.getColumnIndex()==0){
map.put("id",returnStr);
}else if(c.getColumnIndex()==1){
map.put("base",returnStr);
}else if(c.getColumnIndex()==2){
map.put("siteName",returnStr);
}else if(c.getColumnIndex()==3){
map.put("articleName",returnStr);
}else if(c.getColumnIndex()==4){
map.put("mediaName",returnStr);
}else if(c.getColumnIndex()==5){
map.put("mediaUrl",returnStr);
}else if(c.getColumnIndex()==6){
map.put("newsSource",returnStr);
}else if(c.getColumnIndex()==7){
map.put("isRecord",returnStr);
}else if(c.getColumnIndex()==8){
map.put("recordTime",returnStr);
}else if(c.getColumnIndex()==9){
map.put("remark",returnStr);
}
}
result.add(map);
// System.out.println();
}
return result;
}
/**
* 获取合并单元格的值
* @param sheet
* @param row
* @param column
* @return
*/
public static String getMergedRegionValue(Sheet sheet ,int row , int column){
int sheetMergeCount = sheet.getNumMergedRegions();
for(int i = 0 ; i < sheetMergeCount ; i++){
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell) ;
}
}
}
return null ;
}
/**
* 判断合并了行
* @param sheet
* @param row
* @param column
* @return
*/
public static boolean isMergedRow(Sheet sheet,int row ,int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if(row == firstRow && row == lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}
/**
* 判断指定的单元格是否是合并单元格
* @param sheet
* @param row 行下标
* @param column 列下标
* @return
*/
public static boolean isMergedRegion(Sheet sheet,int row ,int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}
/**
* 判断sheet页中是否含有合并单元格
* @param sheet
* @return
*/
public static boolean hasMerged(Sheet sheet) {
return sheet.getNumMergedRegions() > 0 ? true : false;
}
/**
* 合并单元格
* @param sheet
* @param firstRow 开始行
* @param lastRow 结束行
* @param firstCol 开始列
* @param lastCol 结束列
*/
public static void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try{
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
}catch (IllegalArgumentException e){
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
}
/**
* 获取单元格的值
* @param cell
* @return
*/
public static String getCellValue(Cell cell){
if(cell == null) {
return "";
}
if(cell.getCellType() == CellType.STRING){
return cell.getStringCellValue();
}else if(cell.getCellType() == CellType.BOOLEAN){
return String.valueOf(cell.getBooleanCellValue());
}else if(cell.getCellType() == CellType.FORMULA){
return cell.getCellFormula() ;
}else if(cell.getCellType() == CellType.NUMERIC){
return String.valueOf(cell.getNumericCellValue());
}
return "";
}
/**
* 数字值,去掉.0后缀
* @param cell
* @return
*/
public static String remove0Suffix(Object value){
if(value!=null) {
// update-begin-author:taoyan date:20210526 for:对于特殊的字符串 V1.0 也进行了去.0操作 这是不合理的
String val = value.toString();
if(val.endsWith(".0") && isNumberString(val)) {
val = val.replace(".0", "");
}
// update-end-author:taoyan date:20210526 for:对于特殊的字符串 V1.0 也进行了去.0操作 这是不合理的
return val;
}
return null;
}
/**
* 判断给定的字符串是不是只有数字
* @param str
* @return
*/
private static boolean isNumberString(String str){
String regex = "^[0-9]+\\.0+$";
Pattern pattern = Pattern.compile(regex);
Matcher m = pattern.matcher(str);
if (m.find()) {
return true;
}
return false;
}
/**
* 从excel读取内容
*/
public static void readContent(String fileName) {
boolean isE2007 = false; //判断是否是excel2007格式
if(fileName.endsWith("xlsx"))
isE2007 = true;
try {
InputStream input = new FileInputStream(fileName); //建立输入流
Workbook wb = null;
//根据文件格式(2003或者2007)来初始化
if(isE2007)
wb = new XSSFWorkbook(input);
else
wb = new HSSFWorkbook(input);
Sheet sheet = wb.getSheetAt(0); //获得第一个表单
Iterator<Row> rows = sheet.rowIterator(); //获得第一个表单的迭代器
while (rows.hasNext()) {
Row row = rows.next(); //获得行数据
System.out.println("Row #" + row.getRowNum()); //获得行号从0开始
Iterator<Cell> cells = row.cellIterator(); //获得第一行的迭代器
while (cells.hasNext()) {
Cell cell = cells.next();
System.out.println("Cell #" + cell.getColumnIndex());
switch (cell.getCellType()) { //根据cell中的类型来输出数据
case NUMERIC:
System.out.println(cell.getNumericCellValue());
break;
case STRING:
System.out.println(cell.getStringCellValue());
break;
case BOOLEAN:
System.out.println(cell.getBooleanCellValue());
break;
case FORMULA:
System.out.println(cell.getCellFormula());
break;
default:
System.out.println("unsuported sell type======="+cell.getCellType());
break;
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

View File

@@ -0,0 +1,30 @@
package org.jeecgframework.poi.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* https请求用到
*/
public class MyX509TrustManager implements X509TrustManager{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -0,0 +1,134 @@
/**
*
*/
package org.jeecgframework.poi.util;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* 处理单元格的数值
* @Description [LOWCOD-2521]【autopoi】大数据导出方法【全局】
* @author liusq
* @date 2022年1月4号
*/
public class PoiCellUtil {
/**
* 读取单元格的值
*
* @param sheet
* @param row
* @param column
* @return
*/
public static String getCellValue(Sheet sheet, int row, int column) {
String value = null;
if (isMergedRegion(sheet, row, column)) {
value = getMergedRegionValue(sheet, row, column);
} else {
Row rowData = sheet.getRow(row);
Cell cell = rowData.getCell(column);
value = getCellValue(cell);
}
return value;
}
/**
* 获取合并单元格的值
*
* @param sheet
* @param row
* @param column
* @return
*/
public static String getMergedRegionValue(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell);
}
}
}
return null;
}
/**
* 判断指定的单元格是否是合并单元格
*
* @param sheet
* @param row
* @param column
* @return
*/
public static boolean isMergedRegion(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
return true;
}
}
}
return false;
}
/**
* 获取单元格的值
* _NONE(-1),
* NUMERIC(0),
* STRING(1),
* FORMULA(2),
* BLANK(3),
* BOOLEAN(4),
* ERROR(5);
* @param cell
* @return
*/
public static String getCellValue(Cell cell) {
if (cell == null) {
return "";
}
if (cell.getCellType() == CellType.STRING) {
return cell.getStringCellValue();
} else if (cell.getCellType() == CellType.BOOLEAN) {
return String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellType() == CellType.FORMULA) {
try {
return cell.getCellFormula();
} catch (Exception e) {
return String.valueOf(cell.getNumericCellValue());
}
} else if (cell.getCellType() == CellType.NUMERIC) {
return String.valueOf(cell.getNumericCellValue());
} else if (cell.getCellType() == CellType.ERROR) {
return String.valueOf(cell.getErrorCellValue());
}
return "";
}
}

View File

@@ -0,0 +1,278 @@
/**
* 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.util;
import java.util.Collection;
import java.util.Map;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
/**
* AutoPoi的el 表达式支持工具类
*
* @author JEECG
* @date 2015年4月25日 下午12:13:21
*/
public final class PoiElUtil {
public static final String LENGTH = "le:";
public static final String FOREACH = "fe:";
public static final String FOREACH_NOT_CREATE = "!fe:";
public static final String FOREACH_AND_SHIFT = "$fe:";
public static final String FOREACH_COL = "#fe:";
public static final String FOREACH_COL_VALUE = "v_fe:";
public static final String START_STR = "{{";
public static final String END_STR = "}}";
public static final String WRAP = "]]";
public static final String NUMBER_SYMBOL = "n:";
public static final String FORMAT_DATE = "fd:";
public static final String FORMAT_NUMBER = "fn:";
public static final String IF_DELETE = "!if:";
public static final String EMPTY = "";
public static final String CONST = "'";
public static final String NULL = "&NULL&";
public static final String LEFT_BRACKET = "(";
public static final String RIGHT_BRACKET = ")";
public static final String DICT_HANDLER = "dict:";
private PoiElUtil() {
}
/**
* 解析字符串,支持 le,fd,fn,!if,三目
*
* @param obj
* @param map
* @return
* @throws Exception
*/
public static Object eval(String text, Map<String, Object> map) throws Exception {
String tempText = new String(text);
Object obj = innerEval(text, map);
// 如果没有被处理而且这个值找map中存在就处理这个值
if (tempText.equals(obj.toString()) && map.containsKey(tempText.split("\\.")[0])) {
return PoiPublicUtil.getParamsValue(tempText, map);
}
return obj;
}
/**
* 解析字符串,支持 le,fd,fn,!if,三目
*
* @param obj
* @param map
* @return
* @throws Exception
*/
public static Object innerEval(String text, Map<String, Object> map) throws Exception {
if (text.indexOf("?") != -1 && text.indexOf(":") != -1) {
return trinocular(text, map);
}
if (text.indexOf(LENGTH) != -1) {
return length(text, map);
}
if (text.indexOf(FORMAT_DATE) != -1) {
return formatDate(text, map);
}
if (text.indexOf(FORMAT_NUMBER) != -1) {
return formatNumber(text, map);
}
if (text.indexOf(IF_DELETE) != -1) {
return ifDelete(text, map);
}
if (text.startsWith("'")) {
return text.replace("'", "");
}
return text;
}
/**
* 是不是删除列
*
* @param text
* @param map
* @return
* @throws Exception
*/
private static Object ifDelete(String text, Map<String, Object> map) throws Exception {
// 把多个空格变成一个空格
text = text.replaceAll("\\s{1,}", " ").trim();
String[] keys = getKey(IF_DELETE, text).split(" ");
text = text.replace(IF_DELETE, EMPTY);
return isTrue(keys, map);
}
/**
* 是不是真
* 这个方法两个地方用到
* 1.三目表达式的判断,表达式需要设置空格 {{field == 1? field1:field2 }} 或者 {{field?field1:field2 }}
* 2.取非表达式判断为真则当前excel的一整列会被干掉 {{!if:(field == 1)}} 或者 {{!if:(field)}}
*
* 如果字段field本身就能判断true或者false 他会走len==1的逻辑处理
* 如果字段field需要结合其他固定值来判断true或者false 那么记住一定要再表达式里打空格 然后他会split空格 走len==3的逻辑处理
* @param keys
* @param map
* @return
* @throws Exception
*/
private static Boolean isTrue(String[] keys, Map<String, Object> map) throws Exception {
//update-author:taoyan date:20200622 for:此处判断len当为1
if (keys.length == 1) {
String constant = null;
if ((constant = isConstant(keys[0])) != null) {
return Boolean.valueOf(constant);
}
return Boolean.valueOf(PoiPublicUtil.getParamsValue(keys[0], map).toString());
}
if (keys.length == 3) {
if(keys[0]==null || keys[2]==null){
return false;
}
Object first = String.valueOf(eval(keys[0], map));
Object second = String.valueOf(eval(keys[2], map));
return PoiFunctionUtil.isTrue(first, keys[1], second);
}
throw new ExcelExportException("判断参数不对");
}
/**
* 判断是不是常量
*
* @param string
* @return
*/
private static String isConstant(String param) {
if (param.indexOf("'") != -1) {
return param.replace("'", "");
}
return null;
}
/**
* 格式化数字
*
* @param text
* @param map
* @return
* @throws Exception
*/
private static Object formatNumber(String text, Map<String, Object> map) throws Exception {
String[] key = getKey(FORMAT_NUMBER, text).split(";");
text = text.replace(FORMAT_NUMBER, EMPTY);
return innerEval(replacinnerEvalue(text, PoiFunctionUtil.formatNumber(PoiPublicUtil.getParamsValue(key[0], map), key[1])), map);
}
/**
* 格式化时间
*
* @param text
* @param map
* @return
* @throws Exception
*/
private static Object formatDate(String text, Map<String, Object> map) throws Exception {
String[] key = getKey(FORMAT_DATE, text).split(";");
text = text.replace(FORMAT_DATE, EMPTY);
return innerEval(replacinnerEvalue(text, PoiFunctionUtil.formatDate(PoiPublicUtil.getParamsValue(key[0], map), key[1])), map);
}
/**
* 计算这个的长度
*
* @param text
* @param map
* @throws Exception
*/
private static Object length(String text, Map<String, Object> map) throws Exception {
String key = getKey(LENGTH, text);
text = text.replace(LENGTH, EMPTY);
Object val = PoiPublicUtil.getParamsValue(key, map);
return innerEval(replacinnerEvalue(text, PoiFunctionUtil.length(val)), map);
}
private static String replacinnerEvalue(String text, Object val) {
StringBuilder sb = new StringBuilder();
sb.append(text.substring(0, text.indexOf(LEFT_BRACKET)));
sb.append(" ");
sb.append(val);
sb.append(" ");
sb.append(text.substring(text.indexOf(RIGHT_BRACKET) + 1, text.length()));
return sb.toString().trim();
}
private static String getKey(String prefix, String text) {
int leftBracket = 1, rigthBracket = 0, position = 0;
int index = text.indexOf(prefix) + prefix.length();
while (text.charAt(index) == " ".charAt(0)) {
text = text.substring(0, index) + text.substring(index + 1, text.length());
}
for (int i = text.indexOf(prefix + LEFT_BRACKET) + prefix.length() + 1; i < text.length(); i++) {
if (text.charAt(i) == LEFT_BRACKET.charAt(0)) {
leftBracket++;
}
if (text.charAt(i) == RIGHT_BRACKET.charAt(0)) {
rigthBracket++;
}
if (leftBracket == rigthBracket) {
position = i;
break;
}
}
return text.substring(text.indexOf(prefix + LEFT_BRACKET) + 1 + prefix.length(), position).trim();
}
public static void main(String[] args) {
System.out.println(getKey(IF_DELETE, "测试 " + IF_DELETE + " (小明)"));
}
/**
* 三目运算
*
* @return
* @throws Exception
*/
private static Object trinocular(String text, Map<String, Object> map) throws Exception {
// 把多个空格变成一个空格
text = text.replaceAll("\\s{1,}", " ").trim();
String testText = text.substring(0, text.indexOf("?"));
text = text.substring(text.indexOf("?") + 1, text.length()).trim();
text = innerEval(text, map).toString();
String[] keys = text.split(":");
Object first = eval(keys[0].trim(), map);
Object second = eval(keys[1].trim(), map);
return isTrue(testText.split(" "), map) ? first : second;
}
/**
* 解析字符串, 不支持 le,fd,fn,!if,三目 ,获取是集合的字段前缀
*
* @param text
* @param map
* @return
* @throws Exception
*/
public static String evalFindName(String text, Map<String, Object> map) throws Exception {
String[] keys = text.split("\\.");
StringBuilder sb = new StringBuilder().append(keys[0]);
for (int i = 1; i < keys.length; i++) {
sb.append(".").append(keys[i]);
if (eval(sb.toString(), map) instanceof Collection) {
return sb.toString();
}
}
return null;
}
}

View File

@@ -0,0 +1,58 @@
package org.jeecgframework.poi.util;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import org.jeecgframework.poi.excel.graph.entity.ExcelGraph;
import org.jeecgframework.poi.excel.graph.entity.ExcelGraphElement;
import java.util.List;
/**
* 构建特殊数据结构
* @Description [LOWCOD-2521]【autopoi】大数据导出方法【全局】
* @author liusq
* @date 2022年1月4号
*/
public class PoiExcelGraphDataUtil {
/**
* 构建获取数据最后行数 并写入到定义对象中
* @param dataSourceSheet
* @param graph
*/
public static void buildGraphData(Sheet dataSourceSheet, ExcelGraph graph) {
if (graph != null && graph.getCategory() != null && graph.getValueList() != null
&& graph.getValueList().size() > 0) {
graph.getCategory().setEndRowNum(dataSourceSheet.getLastRowNum());
for (ExcelGraphElement e : graph.getValueList()) {
if (e != null) {
e.setEndRowNum(dataSourceSheet.getLastRowNum());
}
}
}
}
/**
* 构建多个图形对象
* @param dataSourceSheet
* @param graphList
*/
public static void buildGraphData(Sheet dataSourceSheet, List<ExcelGraph> graphList) {
if (graphList != null && graphList.size() > 0) {
for (ExcelGraph graph : graphList) {
buildGraphData(dataSourceSheet, graph);
}
}
}
/**
* 获取画布,没有就创建一个
* @param sheet
* @return
*/
public static Drawing getDrawingPatriarch(Sheet sheet){
if(sheet.getDrawingPatriarch() == null){
sheet.createDrawingPatriarch();
}
return sheet.getDrawingPatriarch();
}
}

View File

@@ -0,0 +1,102 @@
package org.jeecgframework.poi.util;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* poi 4.0 07版本在 shift操作下有bug,不移动了单元格以及单元格样式,没有移动cell
* cell还是复用的原理的cell,导致wb输出的时候没有输出值
* 等待修复的时候删除这个问题
*
* @author by jueyue on 19-6-17.
*/
public class PoiExcelTempUtil {
/**
* 把这N行的数据,cell重新设置下,修复因为shift的浅复制问题,导致文本不显示的错误
*
* @param sheet
* @param startRow
* @param endRow
*/
public static void reset(Sheet sheet, int startRow, int endRow) {
if (sheet.getWorkbook() instanceof HSSFWorkbook) {
return;
}
for (int i = startRow; i <= endRow; i++) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
int cellNum = row.getLastCellNum();
for (int j = 0; j < cellNum; j++) {
if (row.getCell(j) == null) {
continue;
}
Map<String, Object> map = copyCell(row.getCell(j));
row.removeCell(row.getCell(j));
Cell cell = row.createCell(j);
cell.setCellStyle((CellStyle) map.get("cellStyle"));
if ((boolean) map.get("isDate")) {
cell.setCellValue((Date) map.get("value"));
} else {
CellType cellType = (CellType) map.get("cellType");
switch (cellType) {
case NUMERIC:
cell.setCellValue((double) map.get("value"));
break;
case STRING:
cell.setCellValue((String) map.get("value"));
case FORMULA:
break;
case BLANK:
break;
case BOOLEAN:
cell.setCellValue((boolean) map.get("value"));
case ERROR:
break;
}
}
}
}
}
private static Map copyCell(Cell cell) {
Map<String, Object> map = new HashMap<>();
map.put("cellType", cell.getCellType());
map.put("isDate", CellType.NUMERIC == cell.getCellType() && DateUtil.isCellDateFormatted(cell));
map.put("value", getValue(cell));
map.put("cellStyle", cell.getCellStyle());
return map;
}
private static Object getValue(Cell cell) {
if (CellType.NUMERIC == cell.getCellType() && DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue();
}
switch (cell.getCellType()) {
case _NONE:
return null;
case NUMERIC:
return cell.getNumericCellValue();
case STRING:
return cell.getStringCellValue();
case FORMULA:
return cell.getCellFormula();
case BLANK:
break;
case BOOLEAN:
return cell.getBooleanCellValue();
case ERROR:
break;
}
return null;
}
}

View File

@@ -0,0 +1,167 @@
/**
* 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.util;
import java.lang.reflect.Array;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Map;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
/**
* if else,length,for each,fromatNumber,formatDate 满足模板的 el 表达式支持
*
* @author JEECG
* @date 2015年4月24日 下午8:04:02
*/
public final class PoiFunctionUtil {
private static final String TWO_DECIMAL_STR = "###.00";
private static final String THREE_DECIMAL_STR = "###.000";
private static final DecimalFormat TWO_DECIMAL = new DecimalFormat(TWO_DECIMAL_STR);
private static final DecimalFormat THREE_DECIMAL = new DecimalFormat(THREE_DECIMAL_STR);
private static final String DAY_STR = "yyyy-MM-dd";
private static final String TIME_STR = "yyyy-MM-dd HH:mm:ss";
private static final String TIME__NO_S_STR = "yyyy-MM-dd HH:mm";
private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat(DAY_STR);
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat(TIME_STR);
private static final SimpleDateFormat TIME__NO_S_FORMAT = new SimpleDateFormat(TIME__NO_S_STR);
private PoiFunctionUtil() {
}
/**
* 获取对象的长度
*
* @param obj
* @return
*/
@SuppressWarnings("rawtypes")
public static int length(Object obj) {
if (obj == null) {
return 0;
}
if (obj instanceof Map) {
return ((Map) obj).size();
}
if (obj instanceof Collection) {
return ((Collection) obj).size();
}
if (obj.getClass().isArray()) {
return Array.getLength(obj);
}
return String.valueOf(obj).length();
}
/**
* 格式化数字
*
* @param obj
* @throws NumberFormatException
* @return
*/
public static String formatNumber(Object obj, String format) {
if (obj == null || obj.toString() == "") {
return "";
}
double number = Double.valueOf(obj.toString());
DecimalFormat decimalFormat = null;
if (TWO_DECIMAL.equals(format)) {
decimalFormat = TWO_DECIMAL;
} else if (THREE_DECIMAL_STR.equals(format)) {
decimalFormat = THREE_DECIMAL;
} else {
decimalFormat = new DecimalFormat(format);
}
return decimalFormat.format(number);
}
/**
* 格式化时间
*
* @param obj
* @return
*/
public static String formatDate(Object obj, String format) {
if (obj == null || obj.toString() == "") {
return "";
}
SimpleDateFormat dateFormat = null;
if (DAY_STR.equals(format)) {
dateFormat = DAY_FORMAT;
} else if (TIME_STR.equals(format)) {
dateFormat = TIME_FORMAT;
} else if (TIME__NO_S_STR.equals(format)) {
dateFormat = TIME__NO_S_FORMAT;
} else {
dateFormat = new SimpleDateFormat(format);
}
return dateFormat.format(obj);
}
/**
* 判断是不是成功
*
* @param first
* @param operator
* @param second
* @return
*/
public static boolean isTrue(Object first, String operator, Object second) {
if (">".endsWith(operator)) {
return isGt(first, second);
} else if ("<".endsWith(operator)) {
return isGt(second, first);
} else if ("==".endsWith(operator)) {
if (first != null && second != null) {
return first.equals(second);
}
return first == second;
} else if ("!=".endsWith(operator)) {
if (first != null && second != null) {
return !first.equals(second);
}
return first != second;
} else {
throw new ExcelExportException("占不支持改操作符");
}
}
/**
* 前者是不是大于后者
*
* @param first
* @param second
* @return
*/
private static boolean isGt(Object first, Object second) {
if (first == null || first.toString() == "") {
return false;
}
if (second == null || second.toString() == "") {
return true;
}
double one = Double.valueOf(first.toString());
double two = Double.valueOf(second.toString());
return one > two;
}
}

View File

@@ -0,0 +1,238 @@
package org.jeecgframework.poi.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.jeecgframework.poi.excel.entity.params.MergeEntity;
import org.jeecgframework.poi.exception.excel.ExcelExportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 纵向合并单元格工具类
*
* @author JEECG
* @date 2015年6月21日 上午11:21:40
*/
public final class PoiMergeCellUtil {
private final static Logger LOGGER = LoggerFactory.getLogger(PoiMergeCellUtil.class);
private PoiMergeCellUtil() {
}
/**
* 纵向合并相同内容的单元格
*
* @param sheet
* @param startRow
* 开始行
* @param columns
* 需要处理的列
*/
public static void mergeCells(Sheet sheet, int startRow, Integer... columns) {
if (columns == null) {
throw new ExcelExportException("至少需要处理1列");
}
Map<Integer, int[]> mergeMap = new HashMap<Integer, int[]>();
for (int i = 0; i < columns.length; i++) {
mergeMap.put(columns[i], null);
}
mergeCells(sheet, mergeMap, startRow, sheet.getLastRowNum());
}
/**
* 纵向合并相同内容的单元格
*
* @param sheet
* @param mergeMap
* key--列,value--依赖的列,没有传空
* @param startRow
* 开始行
*/
public static void mergeCells(Sheet sheet, Map<Integer, int[]> mergeMap, int startRow) {
mergeCells(sheet, mergeMap, startRow, sheet.getLastRowNum());
}
/**
* 纵向合并相同内容的单元格
*
* @param sheet
* @param mergeMap
* key--列,value--依赖的列,没有传空
* @param startRow
* 开始行
* @param endRow
* 结束行
*/
public static void mergeCells(Sheet sheet, Map<Integer, int[]> mergeMap, int startRow, int endRow) {
Map<Integer, MergeEntity> mergeDataMap = new HashMap<Integer, MergeEntity>();
if (mergeMap.size() == 0) {
return;
}
Row row;
Set<Integer> sets = mergeMap.keySet();
String text;
for (int i = startRow; i <= endRow; i++) {
row = sheet.getRow(i);
for (Integer index : sets) {
if (row == null || row.getCell(index) == null) {
if (mergeDataMap.get(index) == null) {
continue;
}
if (mergeDataMap.get(index).getEndRow() == 0) {
mergeDataMap.get(index).setEndRow(i - 1);
}
} else {
text = row.getCell(index).getStringCellValue();
if (StringUtils.isNotEmpty(text)) {
hanlderMergeCells(index, i, text, mergeDataMap, sheet, row.getCell(index), mergeMap.get(index));
} else {
mergeCellOrContinue(index, mergeDataMap, sheet);
}
}
}
}
if (mergeDataMap.size() > 0) {
for (Integer index : mergeDataMap.keySet()) {
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try{
sheet.addMergedRegion(new CellRangeAddress(mergeDataMap.get(index).getStartRow(), mergeDataMap.get(index).getEndRow(), index, index));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
}
}
}
/**
* 处理合并单元格
*
* @param index
* @param rowNum
* @param text
* @param mergeDataMap
* @param sheet
* @param cell
* @param delys
*/
private static void hanlderMergeCells(Integer index, int rowNum, String text, Map<Integer, MergeEntity> mergeDataMap, Sheet sheet, Cell cell, int[] delys) {
if (mergeDataMap.containsKey(index)) {
if (checkIsEqualByCellContents(mergeDataMap.get(index), text, cell, delys, rowNum)) {
mergeDataMap.get(index).setEndRow(rowNum);
} else {
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try{
sheet.addMergedRegion(new CellRangeAddress(mergeDataMap.get(index).getStartRow(), mergeDataMap.get(index).getEndRow(), index, index));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
mergeDataMap.put(index, createMergeEntity(text, rowNum, cell, delys));
}
} else {
mergeDataMap.put(index, createMergeEntity(text, rowNum, cell, delys));
}
}
/**
* 字符为空的情况下判断
*
* @param index
* @param mergeDataMap
* @param sheet
*/
private static void mergeCellOrContinue(Integer index, Map<Integer, MergeEntity> mergeDataMap, Sheet sheet) {
if (mergeDataMap.containsKey(index) && mergeDataMap.get(index).getEndRow() != mergeDataMap.get(index).getStartRow()) {
//update-begin-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
try{
sheet.addMergedRegion(new CellRangeAddress(mergeDataMap.get(index).getStartRow(), mergeDataMap.get(index).getEndRow(), index, index));
}catch (IllegalArgumentException e){
LOGGER.error("合并单元格错误日志:"+e.getMessage());
e.fillInStackTrace();
}
//update-end-author:wangshuai date:20201118 for:一对多导出needMerge 子表数据对应数量小于2时报错 github#1840、gitee I1YH6B
mergeDataMap.remove(index);
}
}
private static MergeEntity createMergeEntity(String text, int rowNum, Cell cell, int[] delys) {
MergeEntity mergeEntity = new MergeEntity(text, rowNum, rowNum);
// 存在依赖关系
if (delys != null && delys.length != 0) {
List<String> list = new ArrayList<String>(delys.length);
mergeEntity.setRelyList(list);
for (int i = 0; i < delys.length; i++) {
list.add(getCellNotNullText(cell, delys[i], rowNum));
}
}
return mergeEntity;
}
private static boolean checkIsEqualByCellContents(MergeEntity mergeEntity, String text, Cell cell, int[] delys, int rowNum) {
// 没有依赖关系
if (delys == null || delys.length == 0) {
return mergeEntity.getText().equals(text);
}
// 存在依赖关系
if (mergeEntity.getText().equals(text)) {
for (int i = 0; i < delys.length; i++) {
if (!getCellNotNullText(cell, delys[i], rowNum).equals(mergeEntity.getRelyList().get(i))) {
return false;
}
}
return true;
}
return false;
}
/**
* 获取一个单元格的值,确保这个单元格必须有值,不然向上查询
*
* @param cell
* @param index
* @param rowNum
* @return
*/
private static String getCellNotNullText(Cell cell, int index, int rowNum) {
String temp = cell.getRow().getCell(index).getStringCellValue();
while (StringUtils.isEmpty(temp)) {
temp = cell.getRow().getSheet().getRow(--rowNum).getCell(index).getStringCellValue();
}
return temp;
}
//update-begin---author:liusq Date:20220104 for[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
/**
*处理合并的单元格区域
* @param sheet
* @param firstRow 开始行
* @param lastRow 结束行
* @param firstCol 开始列
* @param lastCol 结束列
* @date 2022年1月4号
*/
public static void addMergedRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
try {
//添加合并的单元格区域
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
} catch (Exception e) {
LOGGER.debug("发生了一次合并单元格错误,{},{},{},{}", new Integer[]{
firstRow, lastRow, firstCol, lastCol
});
// 忽略掉合并的错误,不打印异常
LOGGER.debug(e.getMessage(), e);
}
}
//update-end---author:liusq Date:20220104 for[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
}

View File

@@ -0,0 +1,561 @@
/**
* 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.util;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.util.*;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.annotation.ExcelIgnore;
import org.jeecgframework.poi.excel.entity.vo.PoiBaseConstants;
import org.jeecgframework.poi.word.entity.WordImageEntity;
import org.jeecgframework.poi.word.entity.params.ExcelListEntity;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
/**
* AutoPoi 的公共基础类
*
* @author JEECG
* @date 2015年4月5日 上午12:59:22
*/
public final class PoiPublicUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(PoiPublicUtil.class);
private PoiPublicUtil() {
}
@SuppressWarnings({ "unchecked" })
public static <K, V> Map<K, V> mapFor(Object... mapping) {
Map<K, V> map = new HashMap<K, V>();
for (int i = 0; i < mapping.length; i += 2) {
map.put((K) mapping[i], (V) mapping[i + 1]);
}
return map;
}
/**
* 彻底创建一个对象
*
* @param clazz
* @return
*/
public static Object createObject(Class<?> clazz, String targetId) {
Object obj = null;
Method setMethod;
try {
if (clazz.equals(Map.class)) {
return new LinkedHashMap<String, Object>();
}
obj = clazz.newInstance();
Field[] fields = getClassFields(clazz);
for (Field field : fields) {
if (isNotUserExcelUserThis(null, field, targetId)) {
continue;
}
if (isCollection(field.getType())) {
ExcelCollection collection = field.getAnnotation(ExcelCollection.class);
setMethod = getMethod(field.getName(), clazz, field.getType());
setMethod.invoke(obj, collection.type().newInstance());
} else if (!isJavaClass(field)) {
setMethod = getMethod(field.getName(), clazz, field.getType());
setMethod.invoke(obj, createObject(field.getType(), targetId));
}
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new RuntimeException("创建对象异常");
}
return obj;
}
/**
* 获取class的 包括父类的
*
* @param clazz
* @return
*/
public static Field[] getClassFields(Class<?> clazz) {
List<Field> list = new ArrayList<Field>();
Field[] fields;
do {
fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
list.add(fields[i]);
}
clazz = clazz.getSuperclass();
} while (clazz != Object.class && clazz != null);
return list.toArray(fields);
}
/**
* @param photoByte
* @return
*/
public static String getFileExtendName(byte[] photoByte) {
String strFileExtendName = "JPG";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
strFileExtendName = "GIF";
} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
strFileExtendName = "JPG";
} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
strFileExtendName = "BMP";
} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
strFileExtendName = "PNG";
}
return strFileExtendName;
}
/**
* 获取GET方法
*
* @param name
* @param pojoClass
* @return
* @throws Exception
*/
public static Method getMethod(String name, Class<?> pojoClass) throws Exception {
StringBuffer getMethodName = new StringBuffer(PoiBaseConstants.GET);
getMethodName.append(name.substring(0, 1).toUpperCase());
getMethodName.append(name.substring(1));
Method method = null;
try {
method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
} catch (Exception e) {
method = pojoClass.getMethod(getMethodName.toString().replace(PoiBaseConstants.GET, PoiBaseConstants.IS), new Class[] {});
}
return method;
}
/**
* 获取SET方法
*
* @param name
* @param pojoClass
* @param type
* @return
* @throws Exception
*/
public static Method getMethod(String name, Class<?> pojoClass, Class<?> type) throws Exception {
StringBuffer getMethodName = new StringBuffer(PoiBaseConstants.SET);
getMethodName.append(name.substring(0, 1).toUpperCase());
getMethodName.append(name.substring(1));
return pojoClass.getMethod(getMethodName.toString(), new Class[] { type });
}
//update-begin-author:taoyan date:20180615 for:TASK #2798 导入扩展方法,支持自定义导入字段转换规则
/**
* 获取get方法 通过EXCEL注解exportConvert判断是否支持值的转换
* @param name
* @param pojoClass
* @param convert
* @return
* @throws Exception
*/
public static Method getMethod(String name, Class<?> pojoClass,boolean convert) throws Exception {
StringBuffer getMethodName = new StringBuffer();
if(convert){
getMethodName.append(PoiBaseConstants.CONVERT);
}
getMethodName.append(PoiBaseConstants.GET);
getMethodName.append(name.substring(0, 1).toUpperCase());
getMethodName.append(name.substring(1));
Method method = null;
try {
method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
} catch (Exception e) {
method = pojoClass.getMethod(getMethodName.toString().replace(PoiBaseConstants.GET, PoiBaseConstants.IS), new Class[] {});
}
return method;
}
/**
* 获取set方法 通过EXCEL注解importConvert判断是否支持值的转换
* @param name
* @param pojoClass
* @param type
* @param convert
* @return
* @throws Exception
*/
public static Method getMethod(String name, Class<?> pojoClass, Class<?> type,boolean convert) throws Exception {
StringBuffer setMethodName = new StringBuffer();
if(convert){
setMethodName.append(PoiBaseConstants.CONVERT);
}
setMethodName.append(PoiBaseConstants.SET);
setMethodName.append(name.substring(0, 1).toUpperCase());
setMethodName.append(name.substring(1));
return pojoClass.getMethod(setMethodName.toString(), new Class[] { type });
}
//update-end-author:taoyan date:20180615 for:TASK #2798 导入扩展方法,支持自定义导入字段转换规则
/**
* 获取Excel2003图片
*
* @param sheet
* 当前sheet对象
* @param workbook
* 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictrues03(HSSFSheet sheet, HSSFWorkbook workbook) {
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
List<HSSFPictureData> pictures = workbook.getAllPictures();
if (!pictures.isEmpty()) {
for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
if (shape instanceof HSSFPicture) {
HSSFPicture pic = (HSSFPicture) shape;
int pictureIndex = pic.getPictureIndex() - 1;
HSSFPictureData picData = pictures.get(pictureIndex);
String picIndex = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(anchor.getCol1());
sheetIndexPicMap.put(picIndex, picData);
}
}
return sheetIndexPicMap;
} else {
return null;
}
}
/**
* 获取Excel2007图片
*
* @param sheet
* 当前sheet对象
* @param workbook
* 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictrues07(XSSFSheet sheet, XSSFWorkbook workbook) {
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
for (POIXMLDocumentPart dr : sheet.getRelations()) {
if (dr instanceof XSSFDrawing) {
XSSFDrawing drawing = (XSSFDrawing) dr;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes) {
XSSFPicture pic = (XSSFPicture) shape;
XSSFClientAnchor anchor = pic.getPreferredSize();
CTMarker ctMarker = anchor.getFrom();
String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
sheetIndexPicMap.put(picIndex, pic.getPictureData());
}
}
}
return sheetIndexPicMap;
}
public static String getWebRootPath(String filePath) {
try {
String path = null;
try {
path = PoiPublicUtil.class.getClassLoader().getResource("").toURI().getPath();
} catch (URISyntaxException e) {
//e.printStackTrace();
//update-begin-author:taoyan date:20211116 for: JAR包分离 发布出空指针 https://gitee.com/jeecg/jeecg-boot/issues/I4CMHK
}catch (NullPointerException e) {
path = PoiPublicUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();
}
//update-end-author:taoyan date:20211116 for: JAR包分离 发布出空指针 https://gitee.com/jeecg/jeecg-boot/issues/I4CMHK
//update-begin--Author:zhangdaihao Date:20190424 for解决springboot 启动模式,上传路径获取为空问题---------------------
if (path == null || path == "") {
//解决springboot 启动模式,上传路径获取为空问题
path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
}
//update-end--Author:zhangdaihao Date:20190424 for解决springboot 启动模式,上传路径获取为空问题----------------------
LOGGER.debug("--- getWebRootPath ----filePath--- " + path);
path = path.replace("WEB-INF/classes/", "");
path = path.replace("file:/", "");
LOGGER.debug("--- path--- " + path);
LOGGER.debug("--- filePath--- " + filePath);
return path + filePath;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 判断是不是集合的实现类
*
* @param clazz
* @return
*/
public static boolean isCollection(Class<?> clazz) {
return Collection.class.isAssignableFrom(clazz);
}
/**
* 是不是java基础类
*
* @param field
* @return
*/
public static boolean isJavaClass(Field field) {
Class<?> fieldType = field.getType();
boolean isBaseClass = false;
if (fieldType.isArray()) {
isBaseClass = false;
} else if (fieldType.isPrimitive() || fieldType.getPackage() == null || fieldType.getPackage().getName().equals("java.lang") || fieldType.getPackage().getName().equals("java.math") || fieldType.getPackage().getName().equals("java.sql") || fieldType.getPackage().getName().equals("java.util")) {
isBaseClass = true;
}
return isBaseClass;
}
/**
* 判断是否不要在这个excel操作中
*
* @param
* @param field
* @param targetId
* @return
*/
public static boolean isNotUserExcelUserThis(List<String> exclusionsList, Field field, String targetId) {
boolean boo = true;
if (field.getAnnotation(ExcelIgnore.class) != null) {
boo = true;
} else if (boo && field.getAnnotation(ExcelCollection.class) != null && isUseInThis(field.getAnnotation(ExcelCollection.class).name(), targetId) && (exclusionsList == null || !exclusionsList.contains(field.getAnnotation(ExcelCollection.class).name()))) {
boo = false;
} else if (boo && field.getAnnotation(Excel.class) != null && isUseInThis(field.getAnnotation(Excel.class).name(), targetId) && (exclusionsList == null || !exclusionsList.contains(field.getAnnotation(Excel.class).name()))) {
boo = false;
} else if (boo && field.getAnnotation(ExcelEntity.class) != null && isUseInThis(field.getAnnotation(ExcelEntity.class).name(), targetId) && (exclusionsList == null || !exclusionsList.contains(field.getAnnotation(ExcelEntity.class).name()))) {
boo = false;
}
return boo;
}
/**
* 判断是不是使用
*
* @param exportName
* @param targetId
* @return
*/
private static boolean isUseInThis(String exportName, String targetId) {
return targetId == null || exportName.equals("") || exportName.indexOf("_") < 0 || exportName.indexOf(targetId) != -1;
}
private static Integer getImageType(String type) {
if (type.equalsIgnoreCase("JPG") || type.equalsIgnoreCase("JPEG")) {
return XWPFDocument.PICTURE_TYPE_JPEG;
}
if (type.equalsIgnoreCase("GIF")) {
return XWPFDocument.PICTURE_TYPE_GIF;
}
if (type.equalsIgnoreCase("BMP")) {
return XWPFDocument.PICTURE_TYPE_GIF;
}
if (type.equalsIgnoreCase("PNG")) {
return XWPFDocument.PICTURE_TYPE_PNG;
}
return XWPFDocument.PICTURE_TYPE_JPEG;
}
/**
* 返回流和图片类型
*
* @Author JEECG
* @date 2013-11-20
* @param entity
* @return (byte[]) isAndType[0],(Integer)isAndType[1]
* @throws Exception
*/
public static Object[] getIsAndType(WordImageEntity entity) throws Exception {
Object[] result = new Object[2];
String type;
if (entity.getType().equals(WordImageEntity.URL)) {
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
BufferedImage bufferImg;
String path = Thread.currentThread().getContextClassLoader().getResource("").toURI().getPath() + entity.getUrl();
path = path.replace("WEB-INF/classes/", "");
path = path.replace("file:/", "");
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, entity.getUrl().substring(entity.getUrl().lastIndexOf(".") + 1, entity.getUrl().length()), byteArrayOut);
//update-end-author:taoYan date:20211203 for: Excel 导出图片的文件带小数点符号 导出报错 https://gitee.com/jeecg/jeecg-boot/issues/I4JNHR
result[0] = byteArrayOut.toByteArray();
type = entity.getUrl().split("/.")[entity.getUrl().split("/.").length - 1];
} else {
result[0] = entity.getData();
type = PoiPublicUtil.getFileExtendName(entity.getData());
}
result[1] = getImageType(type);
return result;
}
/**
* 获取参数值
*
* @param params
* @param map
* @return
*/
@SuppressWarnings("rawtypes")
public static Object getParamsValue(String params, Object object) throws Exception {
if (params.indexOf(".") != -1) {
String[] paramsArr = params.split("\\.");
return getValueDoWhile(object, paramsArr, 0);
}
if (object instanceof Map) {
return ((Map) object).get(params);
}
return getMethod(params, object.getClass()).invoke(object, new Object[] {});
}
/**
* 解析数据
*
* @Author JEECG
* @date 2013-11-16
* @return
*/
public static Object getRealValue(String currentText, Map<String, Object> map) throws Exception {
String params = "";
while (currentText.indexOf("{{") != -1) {
params = currentText.substring(currentText.indexOf("{{") + 2, currentText.indexOf("}}"));
Object obj = getParamsValue(params.trim(), map);
// 判断图片或者是集合
// update-begin-author:taoyan date:20210914 for:autopoi模板导出赋值的方法建议增加空判断或抛出异常说明。 /issues/3005
if(obj==null){
obj = "";
}
// update-end-author:taoyan date:20210914 for:autopoi模板导出赋值的方法建议增加空判断或抛出异常说明。/issues/3005
if (obj instanceof WordImageEntity || obj instanceof List || obj instanceof ExcelListEntity) {
return obj;
} else {
currentText = currentText.replace("{{" + params + "}}", obj.toString());
}
}
return currentText;
}
/**
* 通过遍历过去对象值
*
* @param object
* @param paramsArr
* @param index
* @return
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static Object getValueDoWhile(Object object, String[] paramsArr, int index) throws Exception {
if (object == null) {
return "";
}
if (object instanceof WordImageEntity) {
return object;
}
if (object instanceof Map) {
object = ((Map) object).get(paramsArr[index]);
} else {
object = getMethod(paramsArr[index], object.getClass()).invoke(object, new Object[] {});
}
return (index == paramsArr.length - 1) ? (object == null ? "" : object) : getValueDoWhile(object, paramsArr, ++index);
}
/**
* double to String 防止科学计数法
*
* @param value
* @return
*/
public static String doubleToString(Double value) {
String temp = value.toString();
if (temp.contains("E")) {
BigDecimal bigDecimal = new BigDecimal(temp);
temp = bigDecimal.toPlainString();
}
//---update-begin-----autor:scott------date:20191016-------for:excel导入数字类型去掉后缀.0------
return ExcelUtil.remove0Suffix(temp);
//---update-end-----autor:scott------date:20191016-------for:excel导入数字类型去掉后缀.0------
}
/**
* 判断是否是数值类型
* @param xclass
* @return
*/
public static boolean isNumber(String xclass){
if(xclass==null){
return false;
}
String temp = xclass.toLowerCase();
if(temp.indexOf("int")>=0 || temp.indexOf("double")>=0 || temp.indexOf("decimal")>=0){
return true;
}
return false;
}
//update-begin---author:liusq Date:20211217 for[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
/**
* 统一 key的获取规则
* @param key
* @param targetId
* @date 2022年1月4号
* @return
*/
public static String getValueByTargetId(String key, String targetId, String defalut) {
if (StringUtils.isEmpty(targetId) || key.indexOf("_") < 0) {
return key;
}
String[] arr = key.split(",");
String[] tempArr;
for (String str : arr) {
tempArr = str.split("_");
if (tempArr == null || tempArr.length < 2) {
return defalut;
}
if (targetId.equals(tempArr[1])) {
return tempArr[0];
}
}
return defalut;
}
//update-end---author:liusq Date:20211217 for[LOWCOD-2521]【autopoi】大数据导出方法【全局】----
}

View File

@@ -0,0 +1,374 @@
package org.jeecgframework.poi.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ReflectPermission;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 反射工具类,缓存读取的class信息,省的一直获取
* @Description [LOWCOD-2521]【autopoi】大数据导出方法【全局】
* @author liusq
* @date 2022年1月4号
*/
public final class PoiReflectorUtil {
private static final Map<Class<?>, PoiReflectorUtil> CACHE_REFLECTOR = new ConcurrentHashMap<Class<?>, PoiReflectorUtil>();
private Map<String, Method> getMethods = new HashMap<String, Method>();
private Map<String, Method> setMethods = new HashMap<String, Method>();
private Map<String, Method> enumMethods = new HashMap<String, Method>();
private List<Field> fieldList = new ArrayList<Field>();
private Class<?> type;
private PoiReflectorUtil(Class<?> clazz) {
this.type = clazz;
addGetMethods(clazz);
addFields(clazz);
addSetMethods(clazz);
}
public static PoiReflectorUtil forClass(Class<?> clazz) {
return new PoiReflectorUtil(clazz);
}
public static PoiReflectorUtil fromCache(Class<?> clazz) {
if (!CACHE_REFLECTOR.containsKey(clazz)) {
CACHE_REFLECTOR.put(clazz, new PoiReflectorUtil(clazz));
}
return CACHE_REFLECTOR.get(clazz);
}
private void addGetMethods(Class<?> cls) {
Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();
Method[] methods = getClassMethods(cls);
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("get") && name.length() > 3) {
if (method.getParameterTypes().length == 0) {
name = methodToProperty(name);
addMethodConflict(conflictingGetters, name, method);
}
} else if (name.startsWith("is") && name.length() > 2) {
if (method.getParameterTypes().length == 0) {
name = methodToProperty(name);
addMethodConflict(conflictingGetters, name, method);
}
}
}
resolveGetterConflicts(conflictingGetters);
}
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
for (String propName : conflictingGetters.keySet()) {
List<Method> getters = conflictingGetters.get(propName);
Iterator<Method> iterator = getters.iterator();
Method firstMethod = iterator.next();
if (getters.size() == 1) {
addGetMethod(propName, firstMethod);
} else {
Method getter = firstMethod;
Class<?> getterType = firstMethod.getReturnType();
while (iterator.hasNext()) {
Method method = iterator.next();
Class<?> methodType = method.getReturnType();
if (methodType.equals(getterType)) {
throw new RuntimeException(
"Illegal overloaded getter method with ambiguous type for property "
+ propName + " in class "
+ firstMethod.getDeclaringClass()
+ ". This breaks the JavaBeans "
+ "specification and can cause unpredicatble results.");
} else if (methodType.isAssignableFrom(getterType)) {
// OK getter type is descendant
} else if (getterType.isAssignableFrom(methodType)) {
getter = method;
getterType = methodType;
} else {
throw new RuntimeException(
"Illegal overloaded getter method with ambiguous type for property "
+ propName + " in class "
+ firstMethod.getDeclaringClass()
+ ". This breaks the JavaBeans "
+ "specification and can cause unpredicatble results.");
}
}
addGetMethod(propName, getter);
}
}
}
private void addGetMethod(String name, Method method) {
if (isValidPropertyName(name)) {
getMethods.put(name, method);
}
}
private void addSetMethods(Class<?> cls) {
Map<String, List<Method>> conflictingSetters = new HashMap<String, List<Method>>();
Method[] methods = getClassMethods(cls);
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("set") && name.length() > 3) {
if (method.getParameterTypes().length == 1) {
name = methodToProperty(name);
addMethodConflict(conflictingSetters, name, method);
}
}
}
resolveSetterConflicts(conflictingSetters);
}
private static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
name = name.substring(3);
} else {
throw new RuntimeException("Error parsing property name '" + name
+ "'. Didn't start with 'is', 'get' or 'set'.");
}
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name,
Method method) {
List<Method> list = conflictingMethods.get(name);
if (list == null) {
list = new ArrayList<Method>();
conflictingMethods.put(name, list);
}
list.add(method);
}
private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {
for (String propName : conflictingSetters.keySet()) {
List<Method> setters = conflictingSetters.get(propName);
Method firstMethod = setters.get(0);
if (setters.size() == 1) {
addSetMethod(propName, firstMethod);
} else {
Iterator<Method> methods = setters.iterator();
Method setter = null;
while (methods.hasNext()) {
Method method = methods.next();
if (method.getParameterTypes().length == 1) {
setter = method;
break;
}
}
if (setter == null) {
throw new RuntimeException(
"Illegal overloaded setter method with ambiguous type for property "
+ propName + " in class "
+ firstMethod.getDeclaringClass()
+ ". This breaks the JavaBeans "
+ "specification and can cause unpredicatble results.");
}
addSetMethod(propName, setter);
}
}
}
private void addSetMethod(String name, Method method) {
if (isValidPropertyName(name)) {
setMethods.put(name, method);
}
}
private void addFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (canAccessPrivateMethods()) {
try {
field.setAccessible(true);
} catch (Exception e) {
// Ignored. This is only a final precaution, nothing we can do.
}
}
if (field.isAccessible() && !"serialVersionUID".equalsIgnoreCase(field.getName())) {
this.fieldList.add(field);
}
}
if (clazz.getSuperclass() != null) {
addFields(clazz.getSuperclass());
}
}
private boolean isValidPropertyName(String name) {
return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
}
/*
* This method returns an array containing all methods
* declared in this class and any superclass.
* We use this method, instead of the simpler Class.getMethods(),
* because we want to look for private methods as well.
*
* @param cls The class
* @return An array containing all methods in this class
*/
private Method[] getClassMethods(Class<?> cls) {
HashMap<String, Method> uniqueMethods = new HashMap<String, Method>();
Class<?> currentClass = cls;
while (currentClass != null) {
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// we also need to look for interface methods -
// because the class may be abstract
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
currentClass = currentClass.getSuperclass();
}
Collection<Method> methods = uniqueMethods.values();
return methods.toArray(new Method[methods.size()]);
}
private void addUniqueMethods(HashMap<String, Method> uniqueMethods, Method[] methods) {
for (Method currentMethod : methods) {
if (!currentMethod.isBridge()) {
String signature = getSignature(currentMethod);
// check to see if the method is already known
// if it is known, then an extended class must have
// overridden a method
if (!uniqueMethods.containsKey(signature)) {
if (canAccessPrivateMethods()) {
try {
currentMethod.setAccessible(true);
} catch (Exception e) {
// Ignored. This is only a final precaution, nothing we can do.
}
}
uniqueMethods.put(signature, currentMethod);
}
}
}
}
private String getSignature(Method method) {
StringBuilder sb = new StringBuilder();
Class<?> returnType = method.getReturnType();
if (returnType != null) {
sb.append(returnType.getName()).append('#');
}
sb.append(method.getName());
Class<?>[] parameters = method.getParameterTypes();
for (int i = 0; i < parameters.length; i++) {
if (i == 0) {
sb.append(':');
} else {
sb.append(',');
}
sb.append(parameters[i].getName());
}
return sb.toString();
}
private boolean canAccessPrivateMethods() {
try {
SecurityManager securityManager = System.getSecurityManager();
if (null != securityManager) {
securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
} catch (SecurityException e) {
return false;
}
return true;
}
public Method getGetMethod(String propertyName) {
Method method = getMethods.get(propertyName);
if (method == null) {
throw new RuntimeException(
"There is no getter for property named '" + propertyName + "' in '" + type + "'");
}
return method;
}
public Method getSetMethod(String propertyName) {
Method method = setMethods.get(propertyName);
if (method == null) {
throw new RuntimeException(
"There is no setter for property named '" + propertyName + "' in '" + type + "'");
}
return method;
}
/**
* 获取field 值
*
* @param obj
* @param property
* @return
*/
public Object getValue(Object obj, String property) {
Object value = null;
Method m = getMethods.get(property);
if (m != null) {
try {
value = m.invoke(obj, new Object[]{});
} catch (Exception ex) {
}
}
return value;
}
/**
* 设置field值
*
* @param obj 对象
* @param property
* @param object 属性值
* @return
*/
public boolean setValue(Object obj, String property, Object object) {
Method m = setMethods.get(property);
if (m != null) {
try {
m.invoke(obj, object);
return true;
} catch (Exception ex) {
return false;
}
}
return false;
}
public Map<String, Method> getGetMethods() {
return getMethods;
}
public List<Field> getFieldList() {
return fieldList;
}
public Object execEnumStaticMethod(String staticMethod, Object params) {
if (!enumMethods.containsKey(setMethods)) {
try {
enumMethods.put(staticMethod,type.getMethod(staticMethod,params.getClass()));
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"There is no enum for property named '" + staticMethod + "' in '" + type + "'");
}
}
try {
return enumMethods.get(staticMethod).invoke(null,params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,104 @@
/**
* 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.util;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
/**
* 国外高手的,不过也不好,慎用,效率不行 Helper functions to aid in the management of sheets
*/
public class PoiSheetUtility extends Object {
/**
* Given a sheet, this method deletes a column from a sheet and moves all
* the columns to the right of it to the left one cell.
*
* Note, this method will not update any formula references.
*
* @param sheet
* @param column
*/
public static void deleteColumn(Sheet sheet, int columnToDelete) {
int maxColumn = 0;
for (int r = 0; r < sheet.getLastRowNum() + 1; r++) {
Row row = sheet.getRow(r);
// if no row exists here; then nothing to do; next!
if (row == null)
continue;
// if the row doesn't have this many columns then we are good; next!
int lastColumn = row.getLastCellNum();
if (lastColumn > maxColumn)
maxColumn = lastColumn;
if (lastColumn < columnToDelete)
continue;
for (int x = columnToDelete + 1; x < lastColumn + 1; x++) {
Cell oldCell = row.getCell(x - 1);
if (oldCell != null)
row.removeCell(oldCell);
Cell nextCell = row.getCell(x);
if (nextCell != null) {
Cell newCell = row.createCell(x - 1, nextCell.getCellType());
cloneCell(newCell, nextCell);
}
}
}
// Adjust the column widths
for (int c = 0; c < maxColumn; c++) {
sheet.setColumnWidth(c, sheet.getColumnWidth(c + 1));
}
}
/*
* Takes an existing Cell and merges all the styles and forumla into the new
* one
*/
private static void cloneCell(Cell cNew, Cell cOld) {
cNew.setCellComment(cOld.getCellComment());
cNew.setCellStyle(cOld.getCellStyle());
switch (cNew.getCellType()) {
case BOOLEAN: {
cNew.setCellValue(cOld.getBooleanCellValue());
break;
}
case NUMERIC: {
cNew.setCellValue(cOld.getNumericCellValue());
break;
}
case STRING: {
cNew.setCellValue(cOld.getStringCellValue());
break;
}
case ERROR: {
cNew.setCellValue(cOld.getErrorCellValue());
break;
}
case FORMULA: {
cNew.setCellFormula(cOld.getCellFormula());
break;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More