This commit is contained in:
ls
2025-02-09 19:40:50 +08:00
parent 9248d9c604
commit df96bfecff
14 changed files with 4202 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
<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-web</artifactId>
<dependencies>
<!-- autopoi -->
<dependency>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>autopoi</artifactId>
<version>${autopoi.version}</version>
</dependency>
<!--spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
<!-- servlet -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.11.2</version>
<optional>true</optional>
<scope>test</scope>
</dependency>
</dependencies>
</project>

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

281
autopoi/pom.xml Normal file
View File

@@ -0,0 +1,281 @@
<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>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>autopoi-parent</artifactId>
<version>3.7.0</version>
<packaging>pom</packaging>
<name>autopoi-parent</name>
<url>http://www.jeecg.com</url>
<modules>
<module>autopoi</module>
<module>autopoi-web</module>
</modules>
<description>office 工具类 基于 poi</description>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<scm>
<connection>scm:git:https://github.com/zhangdaiscott/autopoi.git</connection>
<developerConnection>scm:git:https://github.com/zhangdaiscott/autopoi.git</developerConnection>
<url>https://github.com/zhangdaiscott/autopoi</url>
</scm>
<developers>
<developer>
<name>jeecg</name>
<email>jeecgos@163.com</email>
</developer>
</developers>
<properties>
<autopoi.version>3.7.0</autopoi.version>
<poi.version>5.2.2</poi.version>
<xerces.version>2.9.1</xerces.version>
<guava.version>29.0-jre</guava.version>
<commons-lang.version>3.10</commons-lang.version>
<slf4j.version>1.7.30</slf4j.version>
<spring.version>6.0.13</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.poi</groupId>-->
<!-- <artifactId>poi-ooxml-schemas</artifactId>-->
<!-- <version>${poi.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- sax 读取时候用到的 -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>${xerces.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- excel背景
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>-->
<!-- google 工具类 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<!--日志 -->
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<!--spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<optional>true</optional>
</dependency>
<!--servlet -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- 模块版本 -->
<dependency>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>autopoi</artifactId>
<version>${autopoi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<id>jeecg</id>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>jeecg</id>
<name>jeecg Repository</name>
<url>http://maven.jeecg.com:8090/nexus/content/repositories/jeecg</url>
</repository>
<snapshotRepository>
<id>jeecg-snapshots</id>
<name>jeecg Snapshot Repository</name>
<url>http://maven.jeecg.com:8090/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<encoding>UTF-8</encoding>
<additionalJOption>-Xdoclint:none</additionalJOption>
</configuration>
</execution>
</executions>
</plugin>
<!--Maven GPG插件用于使用以下配置对组件进行签名-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!--Nexus Staging Maven插件是将组件部署到OSS并将其发布到Central Repository的推荐方法-->
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<serverId>oss</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>oss</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>