update
This commit is contained in:
43
autopoi/autopoi-web/pom.xml
Normal file
43
autopoi/autopoi-web/pom.xml
Normal 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
73
autopoi/autopoi/pom.xml
Normal 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>
|
||||
@@ -0,0 +1,457 @@
|
||||
package org.jeecgframework.poi.excel;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.jeecgframework.core.util.ApplicationContextUtil;
|
||||
import org.jeecgframework.dict.service.AutoPoiDictServiceI;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
|
||||
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
|
||||
import org.jeecgframework.poi.excel.annotation.ExcelVerify;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.jeecgframework.poi.excel.entity.params.ExcelCollectionParams;
|
||||
import org.jeecgframework.poi.excel.entity.params.ExcelImportEntity;
|
||||
import org.jeecgframework.poi.excel.entity.params.ExcelVerifyEntity;
|
||||
import org.jeecgframework.poi.excel.imports.ExcelImportServer;
|
||||
import org.jeecgframework.poi.exception.excel.ExcelImportException;
|
||||
import org.jeecgframework.poi.exception.excel.enums.ExcelImportEnum;
|
||||
import org.jeecgframework.poi.util.ExcelUtil;
|
||||
import org.jeecgframework.poi.util.PoiPublicUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* EXCEL INCLUE CHECK
|
||||
* 验证excel标题是否存在,当前默认有0.8(80%)即可通过验证
|
||||
*/
|
||||
public class ExcelImportCheckUtil {
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(ExcelImportCheckUtil.class);
|
||||
|
||||
/**当有标题到达多少可以通过验证*/
|
||||
public static final Double defScreenRate = 0.8;
|
||||
|
||||
/**
|
||||
* check inclue filed match rate
|
||||
* @param inputstream
|
||||
* @param pojoClass
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public static Boolean check(InputStream inputstream, Class<?> pojoClass, ImportParams params) {
|
||||
return check(inputstream,pojoClass,params,defScreenRate);
|
||||
}
|
||||
/**
|
||||
* check inclue filed match rate
|
||||
* @param inputstream
|
||||
* @param pojoClass
|
||||
* @param params
|
||||
* @param screenRate field match rate (defalut:0.8)
|
||||
* @return
|
||||
*/
|
||||
public static Boolean check(InputStream inputstream, Class<?> pojoClass, ImportParams params, Double screenRate) {
|
||||
Workbook book = null;
|
||||
int errorNum = 0;
|
||||
int successNum = 0;
|
||||
if (!(inputstream.markSupported())) {
|
||||
inputstream = new PushbackInputStream(inputstream, 8);
|
||||
}
|
||||
try {
|
||||
// if (POIFSFileSystem.hasPOIFSHeader(inputstream)) {
|
||||
// book = new HSSFWorkbook(inputstream);
|
||||
// } else if (POIXMLDocument.hasOOXMLHeader(inputstream)) {
|
||||
// book = new XSSFWorkbook(OPCPackage.open(inputstream));
|
||||
// }
|
||||
book = WorkbookFactory.create(inputstream);
|
||||
LOGGER.info(" >>> poi3升级到4兼容改造工作, pojoClass="+pojoClass);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
for (int i = 0; i < params.getSheetNum(); i++) {
|
||||
Row row = null;
|
||||
//跳过表头和标题行
|
||||
Iterator<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;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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方法去除末尾的0,toPlainString避免输出科学计数法的字符串
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 for:TASK #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 for:TASK #2373 【bug】表改造问题,导致 3.7.1批量导入用户bug-导入不成功--------------------
|
||||
// 判断是集合元素还是不是集合元素,如果是就继续加入这个集合,不是就创建新的对象
|
||||
//update-begin--Author:xuelin Date:20171206 for:TASK #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 for:TASK #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 for:TASK #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 for:TASK #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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
281
autopoi/pom.xml
Normal 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>
|
||||
Reference in New Issue
Block a user