Commit 9bae4a21 by 刘泽志

批量异常导出

parent be7c11ba
...@@ -9,6 +9,7 @@ import com.tbyf.his.common.annotation.IgnoreWebSecurity; ...@@ -9,6 +9,7 @@ import com.tbyf.his.common.annotation.IgnoreWebSecurity;
import com.tbyf.his.common.core.domain.AjaxResult; import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo; import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.common.core.text.StrFormatter; import com.tbyf.his.common.core.text.StrFormatter;
import com.tbyf.his.common.exception.base.BaseException;
import com.tbyf.his.common.utils.StringUtils; import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.common.utils.bean.BeanUtils; import com.tbyf.his.common.utils.bean.BeanUtils;
import com.tbyf.his.web.dataImport.DataImportUtils; import com.tbyf.his.web.dataImport.DataImportUtils;
...@@ -65,6 +66,9 @@ public class DataFieldController { ...@@ -65,6 +66,9 @@ public class DataFieldController {
private MetaFieldService metaFieldService; private MetaFieldService metaFieldService;
@Autowired @Autowired
private DataRuleService dataRuleService;
@Autowired
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
@IgnoreWebSecurity @IgnoreWebSecurity
...@@ -136,15 +140,14 @@ public class DataFieldController { ...@@ -136,15 +140,14 @@ public class DataFieldController {
@ApiOperation("根据基础模板重置字段") @ApiOperation("根据基础模板重置字段")
public AjaxResult resetField(@RequestParam String excelId, @RequestParam(required = false) String year) { public AjaxResult resetField(@RequestParam String excelId, @RequestParam(required = false) String year) {
final ExcelData excelData = excelDataService.getById(excelId); final ExcelData excelData = excelDataService.getById(excelId);
// 获取元字段列表
final List<MetaField> metaFields = metaFieldService.list();
// 获取需要同步的字段列表 // 获取需要同步的字段列表
List<DataField> fieldMatchList = null; List<DataField> fieldMatchList = null;
if (StringUtils.isNotBlank(year)) { if (StringUtils.isNotBlank(year)) {
DataTemplate template = dataTemplateService.getOne(Wrappers.lambdaQuery(DataTemplate.class) DataTemplate template = dataTemplateService.getOne(Wrappers.lambdaQuery(DataTemplate.class)
.eq(DataTemplate::getYear, year).eq(DataTemplate::getOrgName, excelData.getOrgName()), false); .eq(DataTemplate::getYear, year).eq(DataTemplate::getOrgName, excelData.getOrgName()), false);
fieldMatchList = dataFieldService.list(Wrappers.lambdaQuery(DataField.class) fieldMatchList = dataFieldService.list(Wrappers.lambdaQuery(DataField.class)
.eq(DataField::getTemplateId, template.getId()).isNotNull(DataField::getField)); .eq(DataField::getTemplateId, template.getId()).isNotNull(DataField::getField)
.ne(DataField::getField, ""));
} }
// 删除掉之前的模板信息 // 删除掉之前的模板信息
final LambdaQueryWrapper<DataField> wrapper = Wrappers.lambdaQuery(DataField.class).eq(DataField::getTemplateId, excelData.getTemplateId()); final LambdaQueryWrapper<DataField> wrapper = Wrappers.lambdaQuery(DataField.class).eq(DataField::getTemplateId, excelData.getTemplateId());
...@@ -152,6 +155,12 @@ public class DataFieldController { ...@@ -152,6 +155,12 @@ public class DataFieldController {
if (!CollectionUtils.isEmpty(list)) { if (!CollectionUtils.isEmpty(list)) {
final List<String> fieldIdList = list.stream().map(DataField::getId).collect(Collectors.toList()); final List<String> fieldIdList = list.stream().map(DataField::getId).collect(Collectors.toList());
bindRuleService.remove(Wrappers.lambdaQuery(BindRule.class).in(BindRule::getDataId, fieldIdList)); bindRuleService.remove(Wrappers.lambdaQuery(BindRule.class).in(BindRule::getDataId, fieldIdList));
// 模板规则也要删除
List<BindRule> templateRuleList = bindRuleService.list(Wrappers.lambdaQuery(BindRule.class).eq(BindRule::getDataId, excelData.getTemplateId()));
if (!CollectionUtils.isEmpty(templateRuleList)) {
dataRuleService.remove(Wrappers.lambdaQuery(DataRule.class).in(DataRule::getId, templateRuleList.stream().map(BindRule::getRuleId).collect(Collectors.toList())));
}
bindRuleService.remove(Wrappers.lambdaQuery(BindRule.class).in(BindRule::getDataId, Collections.singletonList(excelData.getTemplateId())));
} }
dataFieldService.remove(Wrappers.lambdaQuery(DataField.class).eq(DataField::getTemplateId, excelData.getTemplateId())); dataFieldService.remove(Wrappers.lambdaQuery(DataField.class).eq(DataField::getTemplateId, excelData.getTemplateId()));
try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) { try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) {
...@@ -177,8 +186,8 @@ public class DataFieldController { ...@@ -177,8 +186,8 @@ public class DataFieldController {
// TODO 这里坐标修改为i+1是因为excel文件中展示的第一行号是1,符合直觉 // TODO 这里坐标修改为i+1是因为excel文件中展示的第一行号是1,符合直觉
dataField.setCoordinate("F," + (i + 1)); dataField.setCoordinate("F," + (i + 1));
dataField.setSort(i + 1); dataField.setSort(i + 1);
// 字段绑定需要进行模糊匹配 // 字段绑定确定进行精确匹配
dataFieldService.fieldMatch(metaFields, dataField, fieldMatchList); dataFieldService.fieldMatch(dataField, fieldMatchList);
fieldList.add(dataField); fieldList.add(dataField);
} }
dataFieldService.saveBatch(fieldList); dataFieldService.saveBatch(fieldList);
...@@ -289,20 +298,20 @@ public class DataFieldController { ...@@ -289,20 +298,20 @@ public class DataFieldController {
@ApiOperation("相同字段检查") @ApiOperation("相同字段检查")
public AjaxResult sameFieldCheck(@RequestParam String templateId) { public AjaxResult sameFieldCheck(@RequestParam String templateId) {
List<CreateFieldVO> fieldList = dataFieldService.getCreateFields(templateId); List<CreateFieldVO> fieldList = dataFieldService.getCreateFields(templateId);
if (CollectionUtils.isEmpty(fieldList)){ if (CollectionUtils.isEmpty(fieldList)) {
return AjaxResult.success(Collections.emptyList()); return AjaxResult.success(Collections.emptyList());
} }
Map<String, Integer> map = new HashMap<>(); Map<String, Integer> map = new HashMap<>();
List<CreateFieldVO> list = new ArrayList<>(); List<CreateFieldVO> list = new ArrayList<>();
for (CreateFieldVO field : fieldList){ for (CreateFieldVO field : fieldList) {
if (map.containsKey(field.getFieldName())){ if (map.containsKey(field.getFieldName())) {
map.put(field.getFieldName(),map.get(field.getFieldName())+1); map.put(field.getFieldName(), map.get(field.getFieldName()) + 1);
}else { } else {
map.put(field.getFieldName(),1); map.put(field.getFieldName(), 1);
} }
} }
map.forEach((key,value)->{ map.forEach((key, value) -> {
if (value > 1){ if (value > 1) {
Optional<CreateFieldVO> first = fieldList.stream().filter(item -> StringUtils.equals(item.getFieldName(), key)).findFirst(); Optional<CreateFieldVO> first = fieldList.stream().filter(item -> StringUtils.equals(item.getFieldName(), key)).findFirst();
first.ifPresent(list::add); first.ifPresent(list::add);
} }
......
...@@ -182,26 +182,33 @@ public class DataRuleController { ...@@ -182,26 +182,33 @@ public class DataRuleController {
@GetMapping("/sync/year") @GetMapping("/sync/year")
@ApiOperation("根据年份同步规则") @ApiOperation("根据年份同步规则")
public AjaxResult syncRuleByYear(@RequestParam String templateId, @RequestParam String year) { public AjaxResult syncRuleByYear(@RequestParam String templateId, @RequestParam String year) {
// 查询两个模板 // 查询两个模板 source-本模板 target-对比同步的模板
DataTemplate sourceTemplate = dataTemplateService.getById(templateId); DataTemplate sourceTemplate = dataTemplateService.getById(templateId);
DataTemplate targetTemplate = dataTemplateService.getOne(Wrappers.lambdaQuery(DataTemplate.class).eq(DataTemplate::getYear, year).eq(DataTemplate::getOrgName, sourceTemplate.getOrgName()), false); DataTemplate targetTemplate = dataTemplateService.getOne(Wrappers.lambdaQuery(DataTemplate.class).eq(DataTemplate::getYear, year).eq(DataTemplate::getOrgName, sourceTemplate.getOrgName()), false);
// 查询本模板的字段
List<DataField> fieldList = dataFieldService.list(Wrappers.lambdaQuery(DataField.class) List<DataField> fieldList = dataFieldService.list(Wrappers.lambdaQuery(DataField.class)
.eq(DataField::getTemplateId, sourceTemplate.getId()) .eq(DataField::getTemplateId, sourceTemplate.getId())
.isNotNull(DataField::getField) .isNotNull(DataField::getField)
.select(DataField::getField, DataField::getId)); .select(DataField::getField, DataField::getId));
// 查询被同步的模板的字段
List<DataField> targetFieldList = dataFieldService.list(Wrappers.lambdaQuery(DataField.class) List<DataField> targetFieldList = dataFieldService.list(Wrappers.lambdaQuery(DataField.class)
.eq(DataField::getTemplateId, targetTemplate.getId()) .eq(DataField::getTemplateId, targetTemplate.getId())
.isNotNull(DataField::getField) .isNotNull(DataField::getField)
.select(DataField::getField, DataField::getId)); .select(DataField::getField, DataField::getId));
Set<String> fieldNameSet = fieldList.stream().map(DataField::getField).collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(fieldList)) { if (!CollectionUtils.isEmpty(fieldList)) {
List<BindRule> rules = new ArrayList<>(); List<BindRule> rules = new ArrayList<>();
// 查询两个模板各自的字段规则
List<BindRule> sourceBindList = bindRuleService.queryRuleList(sourceTemplate.getId()); List<BindRule> sourceBindList = bindRuleService.queryRuleList(sourceTemplate.getId());
List<BindRule> targetBindList = bindRuleService.queryRuleList(targetTemplate.getId()); List<BindRule> targetBindList = bindRuleService.queryRuleList(targetTemplate.getId());
// 字段规则同步 // 字段规则同步
if (!CollectionUtils.isEmpty(targetBindList)) { if (!CollectionUtils.isEmpty(targetBindList)) {
// 遍历字段规则
for (BindRule targetRule : targetBindList) { for (BindRule targetRule : targetBindList) {
// 匹配此规则对应的字段ID是否在本模板中存在
Optional<DataField> first = fieldList.stream().filter(df -> StringUtils.equals(df.getField(), targetRule.getDataId())).findFirst(); Optional<DataField> first = fieldList.stream().filter(df -> StringUtils.equals(df.getField(), targetRule.getDataId())).findFirst();
if (first.isPresent()) { if (first.isPresent()) {
// 判断本模板是否存在相同的字段及规则
boolean match = sourceBindList.stream() boolean match = sourceBindList.stream()
.anyMatch(br -> StringUtils.equals(br.getDataId(), targetRule.getDataId()) && StringUtils.equals(br.getRuleId(), targetRule.getRuleId())); .anyMatch(br -> StringUtils.equals(br.getDataId(), targetRule.getDataId()) && StringUtils.equals(br.getRuleId(), targetRule.getRuleId()));
if (!match) { if (!match) {
...@@ -218,39 +225,30 @@ public class DataRuleController { ...@@ -218,39 +225,30 @@ public class DataRuleController {
root: root:
for (DataRule targetRule : targetRules) { for (DataRule targetRule : targetRules) {
String[] split = targetRule.getContent().split("="); String[] split = targetRule.getContent().split("=");
String[] split1 = split[0].split(","); // 查询出对应的两边的字段ID
String[] split2 = split[1].split(","); List<String> list1 = Arrays.asList(split[0].split(","));
for (int i = 0; i < split1.length; i++) { List<String> list2 = Arrays.asList(split[1].split(","));
int finalI = i; // 先判断其中的每个字段是否在源表中存在
Optional<DataField> first = targetFieldList.stream().filter(item -> StringUtils.equals(item.getId(), split1[finalI])).findFirst(); boolean match1 = fieldNameSet.containsAll(list1);
if (first.isPresent()) { boolean match2 = fieldNameSet.containsAll(list2);
Optional<DataField> first1 = fieldList.stream().filter(item -> StringUtils.equals(item.getField(), first.get().getField())).findFirst(); if (!match1 || !match2){
if (first1.isPresent()) { continue root;
split1[i] = first1.get().getId();
} else {
continue root;
}
} else {
continue root;
}
} }
for (int j = 0; j < split2.length; j++) { // 再判断此规则是否已经在本模板中存在
int finalI = j; boolean match = sourceRules.stream().anyMatch(item -> {
Optional<DataField> first = targetFieldList.stream().filter(item -> StringUtils.equals(item.getId(), split2[finalI])).findFirst(); String[] temp = item.getContent().split("=");
if (first.isPresent()) { // 查询出对应的两边的字段ID
Optional<DataField> first1 = fieldList.stream().filter(item -> StringUtils.equals(item.getField(), first.get().getField())).findFirst(); List<String> temp1 = Arrays.asList(temp[0].split(","));
if (first1.isPresent()) { List<String> temp2 = Arrays.asList(temp[1].split(","));
split2[j] = first1.get().getId(); if (temp1.containsAll(list1) && temp2.containsAll(list2)){
} else { return true;
continue root;
}
} else {
continue root;
} }
return temp1.containsAll(list2) && temp2.containsAll(list1);
});
if (!match){
targetRule.setId(null);
datas.add(targetRule);
} }
targetRule.setId(null);
targetRule.setContent(String.join(",", split1) + "=" + String.join(",", split2));
datas.add(targetRule);
} }
if (!CollectionUtils.isEmpty(datas)) { if (!CollectionUtils.isEmpty(datas)) {
dataRuleService.saveBatch(datas); dataRuleService.saveBatch(datas);
......
...@@ -25,6 +25,7 @@ import org.apache.poi.ss.usermodel.*; ...@@ -25,6 +25,7 @@ import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -95,6 +96,7 @@ public class ExcelDataController { ...@@ -95,6 +96,7 @@ public class ExcelDataController {
@SneakyThrows @SneakyThrows
@IgnoreWebSecurity @IgnoreWebSecurity
@PostMapping("/upload") @PostMapping("/upload")
//@Transactional(rollbackFor = Exception.class)
@ApiOperation("文件导入") @ApiOperation("文件导入")
public AjaxResult bindRule(UploadExcelParam param) { public AjaxResult bindRule(UploadExcelParam param) {
if (StringUtils.equals(param.getType(), "1")) { if (StringUtils.equals(param.getType(), "1")) {
...@@ -110,6 +112,8 @@ public class ExcelDataController { ...@@ -110,6 +112,8 @@ public class ExcelDataController {
} }
excelData.setFile(param.getFile().getBytes()); excelData.setFile(param.getFile().getBytes());
excelData.setFileName(param.getFile().getOriginalFilename()); excelData.setFileName(param.getFile().getOriginalFilename());
// 保存后导入文件数据
excelDataService.importData(excelData);
excelDataService.saveOrUpdate(excelData); excelDataService.saveOrUpdate(excelData);
} else if (StringUtils.equals(param.getType(), "2")) { } else if (StringUtils.equals(param.getType(), "2")) {
ExcelData excelData = excelDataService.getOne(Wrappers.lambdaQuery(ExcelData.class) ExcelData excelData = excelDataService.getOne(Wrappers.lambdaQuery(ExcelData.class)
...@@ -203,7 +207,7 @@ public class ExcelDataController { ...@@ -203,7 +207,7 @@ public class ExcelDataController {
final int rowStart = Integer.parseInt(orgCodeCo.split(",")[1]); final int rowStart = Integer.parseInt(orgCodeCo.split(",")[1]);
try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) { try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) {
final Sheet sheet = workbook.getSheetAt(0); final Sheet sheet = workbook.getSheetAt(0);
String sql = "SELECT ORG_CODE,ORG_NAME,MAILING_ADDRESS,AREA_NUMBER_CODE FROM {} WHERE YEAROOFDATARECORD='{}年'"; String sql = "SELECT ORG_CODE,ORG_NAME,MAILING_ADDRESS,AREA_NUMBER_CODE FROM {} WHERE YEAROOFDATARECORD='{}年' ORDER BY ROWCODE";
try { try {
DataSourceService.switchDb(template.getDataSourceId()); DataSourceService.switchDb(template.getDataSourceId());
final List<Map<String, Object>> mapList = jdbcTemplate.queryForList( final List<Map<String, Object>> mapList = jdbcTemplate.queryForList(
......
package com.tbyf.his.web.dataImport.core;
import com.tbyf.his.common.annotation.Excel;
import com.tbyf.his.common.annotation.Excels;
import com.tbyf.his.common.config.RuoYiConfig;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.text.Convert;
import com.tbyf.his.common.exception.UtilException;
import com.tbyf.his.common.utils.DateUtils;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.common.utils.file.FileTypeUtils;
import com.tbyf.his.common.utils.file.FileUtils;
import com.tbyf.his.common.utils.file.ImageUtils;
import com.tbyf.his.common.utils.poi.ExcelHandlerAdapter;
import com.tbyf.his.common.utils.reflect.ReflectUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* Excel相关处理
*
* @author guopx
*/
public class ExcelUtil<T>
{
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/**
* Excel sheet最大行数,默认65536
*/
public static final int sheetSize = 65536;
/**
* 工作表名称
*/
private String sheetName;
/**
* 导出类型(EXPORT:导出数据;IMPORT:导入模板)
*/
private Excel.Type type;
/**
* 工作薄对象
*/
private Workbook wb;
/**
* 工作表对象
*/
private Sheet sheet;
/**
* 样式列表
*/
private Map<String, CellStyle> styles;
/**
* 导入导出数据列表
*/
private List<T> list;
/**
* 注解列表
*/
private List<Object[]> fields;
/**
* 当前行号
*/
private int rownum;
/**
* 标题
*/
private String title;
/**
* 最大高度
*/
private short maxHeight;
/**
* 统计列表
*/
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/**
* 实体对象
*/
public Class<T> clazz;
public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
}
public void init(List<T> list, String sheetName, String title, Excel.Type type)
{
if (list == null)
{
list = new ArrayList<T>();
}
this.list = list;
this.sheetName = sheetName;
this.type = type;
this.title = title;
createExcelField();
createWorkbook();
createTitle();
}
/**
* 创建excel第一行标题
*/
public void createTitle()
{
if (StringUtils.isNotEmpty(title))
{
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(),
this.fields.size() - 1));
}
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @return 转换后集合
*/
public List<T> importExcel(InputStream is) throws Exception
{
return importExcel(is, 0);
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
}
/**
* 对excel表单指定表格索引名转换成list
*
* @param sheetName 表格索引名
* @param titleNum 标题占用行数
* @param is 输入流
* @return 转换后集合
*/
public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
{
this.type = Excel.Type.IMPORT;
this.wb = WorkbookFactory.create(is);
List<T> list = new ArrayList<T>();
// 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet
Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
if (sheet == null)
{
throw new IOException("文件sheet不存在");
}
boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
Map<String, PictureData> pictures;
if (isXSSFWorkbook)
{
pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
}
else
{
pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
}
// 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
int rows = sheet.getLastRowNum();
if (rows > 0)
{
// 定义一个map用于存放excel列的序号和field.
Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头
Row heard = sheet.getRow(titleNum);
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
{
Cell cell = heard.getCell(i);
if (StringUtils.isNotNull(cell))
{
String value = this.getCellValue(heard, i).toString();
cellMap.put(value, i);
}
else
{
cellMap.put(null, i);
}
}
// 有数据时才处理 得到类的所有field.
List<Object[]> fields = this.getFields();
Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
for (Object[] objects : fields)
{
Excel attr = (Excel) objects[1];
Integer column = cellMap.get(attr.name());
if (column != null)
{
fieldsMap.put(column, objects);
}
}
for (int i = titleNum + 1; i <= rows; i++)
{
// 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i);
// 判断当前行是否是空行
if (isRowEmpty(row))
{
continue;
}
T entity = null;
for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
{
Object val = this.getCellValue(row, entry.getKey());
// 如果不存在实例则新建.
entity = (entity == null ? clazz.newInstance() : entity);
// 从map中得到对应列的field.
Field field = (Field) entry.getValue()[0];
Excel attr = (Excel) entry.getValue()[1];
// 取得类型,并根据对象类型设置值.
Class<?> fieldType = field.getType();
if (String.class == fieldType)
{
String s = Convert.toStr(val);
if (StringUtils.endsWith(s, ".0"))
{
val = StringUtils.substringBefore(s, ".0");
}
else
{
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
if (StringUtils.isNotEmpty(dateFormat))
{
val = DateUtils.parseDateToStr(dateFormat, (Date) val);
}
else
{
val = Convert.toStr(val);
}
}
}
else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
{
val = Convert.toInt(val);
}
else if (Long.TYPE == fieldType || Long.class == fieldType)
{
val = Convert.toLong(val);
}
else if (Double.TYPE == fieldType || Double.class == fieldType)
{
val = Convert.toDouble(val);
}
else if (Float.TYPE == fieldType || Float.class == fieldType)
{
val = Convert.toFloat(val);
}
else if (BigDecimal.class == fieldType)
{
val = Convert.toBigDecimal(val);
}
else if (Date.class == fieldType)
{
if (val instanceof String)
{
val = DateUtils.parseDate(val);
}
else if (val instanceof Double)
{
val = DateUtil.getJavaDate((Double) val);
}
}
else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
{
val = Convert.toBool(val, false);
}
if (StringUtils.isNotNull(fieldType))
{
String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.targetAttr()))
{
propertyName = field.getName() + "." + attr.targetAttr();
}
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
{
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
val = dataFormatHandlerAdapter(val, attr);
}
else if (Excel.ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
if (image == null)
{
val = "";
}
else
{
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
}
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
}
list.add(entity);
}
}
return list;
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
*/
public AjaxResult exportExcel(List<T> list, String sheetName)
{
return exportExcel(list, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public AjaxResult exportExcel(List<T> list, String sheetName, String title)
{
this.init(list, sheetName, title, Excel.Type.EXPORT);
return exportExcel();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param response 返回数据
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
* @throws IOException
*/
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
{
exportExcel(response, list, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param response 返回数据
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
* @throws IOException
*/
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
this.init(list, sheetName, title, Excel.Type.EXPORT);
exportExcel(response);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @return 结果
*/
public AjaxResult importTemplateExcel(String sheetName)
{
return importTemplateExcel(sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public AjaxResult importTemplateExcel(String sheetName, String title)
{
this.init(null, sheetName, title, Excel.Type.IMPORT);
return exportExcel();
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @return 结果
*/
public void importTemplateExcel(HttpServletResponse response, String sheetName)
{
importTemplateExcel(response, sheetName, StringUtils.EMPTY);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
this.init(null, sheetName, title, Excel.Type.IMPORT);
exportExcel(response);
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @return 结果
*/
public void exportExcel(HttpServletResponse response)
{
try
{
writeSheet();
wb.write(response.getOutputStream());
}
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
}
finally
{
IOUtils.closeQuietly(wb);
}
}
public Workbook getWb() {
return wb;
}
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @return 结果
*/
public AjaxResult exportExcel()
{
OutputStream out = null;
try
{
writeSheet();
String filename = encodingFilename(sheetName);
out = new FileOutputStream(getAbsoluteFile(filename));
wb.write(out);
return AjaxResult.success(filename);
}
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
throw new UtilException("导出Excel失败,请联系网站管理员!");
}
finally
{
IOUtils.closeQuietly(wb);
IOUtils.closeQuietly(out);
}
}
/**
* 创建写入数据到Sheet
*/
public void writeSheet()
{
// 取出一共有多少个sheet.
int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
for (int index = 0; index < sheetNo; index++)
{
createSheet(sheetNo, index);
// 产生一行
Row row = sheet.createRow(rownum);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
}
if (Excel.Type.EXPORT.equals(type))
{
fillExcelData(index, row);
addStatisticsRow();
}
}
}
/**
* 填充excel数据
*
* @param index 序号
* @param row 单元格行
*/
public void fillExcelData(int index, Row row)
{
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
for (int i = startNo; i < endNo; i++)
{
row = sheet.createRow(i + 1 + rownum - startNo);
// 得到导出对象.
T vo = (T) list.get(i);
int column = 0;
for (Object[] os : fields)
{
Field field = (Field) os[0];
Excel excel = (Excel) os[1];
this.addCell(excel, row, vo, field, column++);
}
}
}
/**
* 创建表格样式
*
* @param wb 工作薄对象
* @return 样式列表
*/
private Map<String, CellStyle> createStyles(Workbook wb)
{
// 写入各条记录,每条记录对应excel表中的一行
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
CellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font titleFont = wb.createFont();
titleFont.setFontName("Arial");
titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true);
style.setFont(titleFont);
styles.put("title", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
style.setFont(dataFont);
styles.put("data", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font totalFont = wb.createFont();
totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10);
style.setFont(totalFont);
styles.put("total", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.LEFT);
styles.put("data1", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
styles.put("data2", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.RIGHT);
styles.put("data3", style);
return styles;
}
/**
* 创建单元格
*/
public Cell createCell(Excel attr, Row row, int column)
{
// 创建列
Cell cell = row.createCell(column);
// 写入列信息
cell.setCellValue(attr.name());
setDataValidation(attr, row, column);
cell.setCellStyle(styles.get("header"));
return cell;
}
/**
* 设置单元格信息
*
* @param value 单元格值
* @param attr 注解相关
* @param cell 单元格信息
*/
public void setCellVo(Object value, Excel attr, Cell cell)
{
if (Excel.ColumnType.STRING == attr.cellType())
{
String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
if (StringUtils.containsAny(cellValue, FORMULA_STR))
{
cellValue = StringUtils.replaceEach(cellValue, FORMULA_STR, new String[] { "\t=", "\t-", "\t+", "\t@" });
}
cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
}
else if (Excel.ColumnType.NUMERIC == attr.cellType())
{
if (StringUtils.isNotNull(value))
{
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
}
}
else if (Excel.ColumnType.IMAGE == attr.cellType())
{
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
String imagePath = Convert.toStr(value);
if (StringUtils.isNotEmpty(imagePath))
{
byte[] data = ImageUtils.getImage(imagePath);
getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
}
}
}
/**
* 获取画布
*/
public static Drawing<?> getDrawingPatriarch(Sheet sheet)
{
if (sheet.getDrawingPatriarch() == null)
{
sheet.createDrawingPatriarch();
}
return sheet.getDrawingPatriarch();
}
/**
* 获取图片类型,设置图片插入类型
*/
public int getImageType(byte[] value)
{
String type = FileTypeUtils.getFileExtendName(value);
if ("JPG".equalsIgnoreCase(type))
{
return Workbook.PICTURE_TYPE_JPEG;
}
else if ("PNG".equalsIgnoreCase(type))
{
return Workbook.PICTURE_TYPE_PNG;
}
return Workbook.PICTURE_TYPE_JPEG;
}
/**
* 创建表格样式
*/
public void setDataValidation(Excel attr, Row row, int column)
{
if (attr.name().indexOf("注:") >= 0)
{
sheet.setColumnWidth(column, 6000);
}
else
{
// 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
}
// 如果设置了提示信息则鼠标放上去提示.
if (StringUtils.isNotEmpty(attr.prompt()))
{
// 这里默认设了2-101列提示.
setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
}
// 如果设置了combo属性则本列只能选择不能输入
if (attr.combo().length > 0)
{
// 这里默认设了2-101列只能选择不能输入.
setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
}
}
/**
* 添加单元格
*/
public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
{
Cell cell = null;
try
{
// 设置行高
row.setHeight(maxHeight);
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
if (attr.isExport())
{
// 创建cell
cell = row.createCell(column);
int align = attr.align().value();
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
String dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp();
String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
}
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
}
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
{
cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
}
else if (value instanceof BigDecimal && -1 != attr.scale())
{
cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
cell.setCellValue(dataFormatHandlerAdapter(value, attr));
}
else
{
// 设置列类型
setCellVo(value, attr, cell);
}
addStatisticsData(column, Convert.toStr(value), attr);
}
}
catch (Exception e)
{
log.error("导出Excel失败{}", e);
}
return cell;
}
/**
* 设置 POI XSSFSheet 单元格提示
*
* @param sheet 表单
* @param promptTitle 提示标题
* @param promptContent 提示内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
*/
public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
int firstCol, int endCol)
{
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
DataValidation dataValidation = helper.createValidation(constraint, regions);
dataValidation.createPromptBox(promptTitle, promptContent);
dataValidation.setShowPromptBox(true);
sheet.addValidationData(dataValidation);
}
/**
* 设置某些列的值只能输入预制的数据,显示下拉框.
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
*/
public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol)
{
DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容
DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
DataValidation dataValidation = helper.createValidation(constraint, regions);
// 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation)
{
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
}
else
{
dataValidation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(dataValidation);
}
/**
* 解析导出值 0=男,1=女,2=未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String convertByExp(String propertyValue, String converterExp, String separator)
{
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
{
for (String value : propertyValue.split(separator))
{
if (itemArray[0].equals(value))
{
propertyString.append(itemArray[1] + separator);
break;
}
}
}
else
{
if (itemArray[0].equals(propertyValue))
{
return itemArray[1];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 反向解析值 男=0,女=1,未知=2
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String reverseByExp(String propertyValue, String converterExp, String separator)
{
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource)
{
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue))
{
for (String value : propertyValue.split(separator))
{
if (itemArray[1].equals(value))
{
propertyString.append(itemArray[0] + separator);
break;
}
}
}
else
{
if (itemArray[1].equals(propertyValue))
{
return itemArray[0];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 解析字典值
*
* @param dictValue 字典值
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典标签
*/
public static String convertDictByExp(String dictValue, String dictType, String separator)
{
// return DictUtils.getDictLabel(dictType, dictValue, separator);
return "";
}
/**
* 反向解析值字典值
*
* @param dictLabel 字典标签
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典值
*/
public static String reverseDictByExp(String dictLabel, String dictType, String separator)
{
// return DictUtils.getDictValue(dictType, dictLabel, separator);
return "";
}
/**
* 数据处理器
*
* @param value 数据值
* @param excel 数据注解
* @return
*/
public String dataFormatHandlerAdapter(Object value, Excel excel)
{
try
{
Object instance = excel.handler().newInstance();
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class });
value = formatMethod.invoke(instance, value, excel.args());
}
catch (Exception e)
{
log.error("不能格式化数据 " + excel.handler(), e.getMessage());
}
return Convert.toStr(value);
}
/**
* 合计统计信息
*/
private void addStatisticsData(Integer index, String text, Excel entity)
{
if (entity != null && entity.isStatistics())
{
Double temp = 0D;
if (!statistics.containsKey(index))
{
statistics.put(index, temp);
}
try
{
temp = Double.valueOf(text);
}
catch (NumberFormatException e)
{
}
statistics.put(index, statistics.get(index) + temp);
}
}
/**
* 创建统计行
*/
public void addStatisticsRow()
{
if (statistics.size() > 0)
{
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
Set<Integer> keys = statistics.keySet();
Cell cell = row.createCell(0);
cell.setCellStyle(styles.get("total"));
cell.setCellValue("合计");
for (Integer key : keys)
{
cell = row.createCell(key);
cell.setCellStyle(styles.get("total"));
cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
}
statistics.clear();
}
}
/**
* 编码文件名
*/
public String encodingFilename(String filename)
{
filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx";
return filename;
}
/**
* 获取下载路径
*
* @param filename 文件名称
*/
public String getAbsoluteFile(String filename)
{
String downloadPath = RuoYiConfig.getDownloadPath() + filename;
File desc = new File(downloadPath);
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
return downloadPath;
}
/**
* 获取bean中的属性值
*
* @param vo 实体对象
* @param field 字段
* @param excel 注解
* @return 最终的属性值
* @throws Exception
*/
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{
Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr()))
{
String target = excel.targetAttr();
if (target.contains("."))
{
String[] targets = target.split("[.]");
for (String name : targets)
{
o = getValue(o, name);
}
}
else
{
o = getValue(o, target);
}
}
return o;
}
/**
* 以类的属性的get方法方法形式获取值
*
* @param o
* @param name
* @return value
* @throws Exception
*/
private Object getValue(Object o, String name) throws Exception
{
if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
{
Class<?> clazz = o.getClass();
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
o = field.get(o);
}
return o;
}
/**
* 得到所有定义字段
*/
private void createExcelField()
{
this.fields = getFields();
this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
this.maxHeight = getRowHeight();
}
/**
* 获取字段注解信息
*/
public List<Object[]> getFields()
{
List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
for (Field field : tempFields)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
}
}
return fields;
}
/**
* 根据注解获取最大行高
*/
public short getRowHeight()
{
double maxHeight = 0;
for (Object[] os : this.fields)
{
Excel excel = (Excel) os[1];
maxHeight = Math.max(maxHeight, excel.height());
}
return (short) (maxHeight * 20);
}
/**
* 创建一个工作簿
*/
public void createWorkbook()
{
this.wb = new SXSSFWorkbook(500);
this.sheet = wb.createSheet();
wb.setSheetName(0, sheetName);
this.styles = createStyles(wb);
}
/**
* 创建工作表
*
* @param sheetNo sheet数量
* @param index 序号
*/
public void createSheet(int sheetNo, int index)
{
// 设置工作表的名称.
if (sheetNo > 1 && index > 0)
{
this.sheet = wb.createSheet();
this.createTitle();
wb.setSheetName(index, sheetName + index);
}
}
/**
* 获取单元格值
*
* @param row 获取的行
* @param column 获取单元格列号
* @return 单元格值
*/
public Object getCellValue(Row row, int column)
{
if (row == null)
{
return row;
}
Object val = "";
try
{
Cell cell = row.getCell(column);
if (StringUtils.isNotNull(cell))
{
if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
{
val = cell.getNumericCellValue();
if (DateUtil.isCellDateFormatted(cell))
{
val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
}
else
{
if ((Double) val % 1 != 0)
{
val = new BigDecimal(val.toString());
}
else
{
val = new DecimalFormat("0").format(val);
}
}
}
else if (cell.getCellType() == CellType.STRING)
{
val = cell.getStringCellValue();
}
else if (cell.getCellType() == CellType.BOOLEAN)
{
val = cell.getBooleanCellValue();
}
else if (cell.getCellType() == CellType.ERROR)
{
val = cell.getErrorCellValue();
}
}
}
catch (Exception e)
{
return val;
}
return val;
}
/**
* 判断是否是空行
*
* @param row 判断的行
* @return
*/
private boolean isRowEmpty(Row row)
{
if (row == null)
{
return true;
}
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
{
Cell cell = row.getCell(i);
if (cell != null && cell.getCellType() != CellType.BLANK)
{
return false;
}
}
return true;
}
/**
* 获取Excel2003图片
*
* @param sheet 当前sheet对象
* @param workbook 工作簿对象
* @return Map key:图片单元格索引(1_1)String,value:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
List<HSSFPictureData> pictures = workbook.getAllPictures();
if (!pictures.isEmpty())
{
for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
{
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
if (shape instanceof HSSFPicture)
{
HSSFPicture pic = (HSSFPicture) shape;
int pictureIndex = pic.getPictureIndex() - 1;
HSSFPictureData picData = pictures.get(pictureIndex);
String picIndex = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(anchor.getCol1());
sheetIndexPicMap.put(picIndex, picData);
}
}
return sheetIndexPicMap;
}
else
{
return sheetIndexPicMap;
}
}
/**
* 获取Excel2007图片
*
* @param sheet 当前sheet对象
* @param workbook 工作簿对象
* @return Map key:图片单元格索引(1_1)String,value:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
for (POIXMLDocumentPart dr : sheet.getRelations())
{
if (dr instanceof XSSFDrawing)
{
XSSFDrawing drawing = (XSSFDrawing) dr;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes)
{
if (shape instanceof XSSFPicture)
{
XSSFPicture pic = (XSSFPicture) shape;
XSSFClientAnchor anchor = pic.getPreferredSize();
CTMarker ctMarker = anchor.getFrom();
String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
sheetIndexPicMap.put(picIndex, pic.getPictureData());
}
}
}
}
return sheetIndexPicMap;
}
}
...@@ -22,7 +22,7 @@ public class ExcelVO { ...@@ -22,7 +22,7 @@ public class ExcelVO {
@Excel(name = "机构类型") @Excel(name = "机构类型")
private String orgType; private String orgType;
@Excel(name = "医疗机构名称", width = 20) @Excel(name = "医疗机构名称", width = 30)
private String orgName; private String orgName;
@Excel(name = "医疗机构代码") @Excel(name = "医疗机构代码")
...@@ -43,6 +43,9 @@ public class ExcelVO { ...@@ -43,6 +43,9 @@ public class ExcelVO {
@Excel(name = "错误原因", width = 30) @Excel(name = "错误原因", width = 30)
private String message; private String message;
@Excel(isExport=false)
private String areaCode;
public ExcelVO(String message, String value) { public ExcelVO(String message, String value) {
this.message = message; this.message = message;
this.value = value; this.value = value;
......
...@@ -38,6 +38,9 @@ public class VerifyVO { ...@@ -38,6 +38,9 @@ public class VerifyVO {
@ApiModelProperty(value = "排序字段") @ApiModelProperty(value = "排序字段")
private Integer sort; private Integer sort;
@ApiModelProperty(value = "元字段ID")
private String metaFieldId;
@ApiModelProperty(value = "数据库字段名") @ApiModelProperty(value = "数据库字段名")
private String fieldName; private String fieldName;
......
...@@ -29,11 +29,10 @@ public interface DataFieldService extends IService<DataField> { ...@@ -29,11 +29,10 @@ public interface DataFieldService extends IService<DataField> {
/** /**
* 字段匹配 * 字段匹配
* *
* @param list
* @param field * @param field
* @param fieldMatchList * @param fieldMatchList
*/ */
void fieldMatch(List<MetaField> list, DataField field, List<DataField> fieldMatchList); void fieldMatch(DataField field, List<DataField> fieldMatchList);
/** /**
* 获取待匹配的字段 * 获取待匹配的字段
......
...@@ -20,4 +20,9 @@ public interface ExcelDataService extends IService<ExcelData> { ...@@ -20,4 +20,9 @@ public interface ExcelDataService extends IService<ExcelData> {
*/ */
void analyzeExport(ExcelData excelData, HttpServletResponse response); void analyzeExport(ExcelData excelData, HttpServletResponse response);
/**
* 导入文件数据
* @param excelData
*/
void importData(ExcelData excelData);
} }
...@@ -18,6 +18,7 @@ import com.tbyf.his.web.dataImport.mapper.DataFieldMapper; ...@@ -18,6 +18,7 @@ import com.tbyf.his.web.dataImport.mapper.DataFieldMapper;
import com.tbyf.his.web.dataImport.service.DataFieldService; import com.tbyf.his.web.dataImport.service.DataFieldService;
import com.tbyf.his.web.dataImport.service.DataTemplateService; import com.tbyf.his.web.dataImport.service.DataTemplateService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RegExUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
...@@ -59,63 +60,22 @@ public class DataFieldServiceImpl extends ServiceImpl<DataFieldMapper, DataField ...@@ -59,63 +60,22 @@ public class DataFieldServiceImpl extends ServiceImpl<DataFieldMapper, DataField
} }
@Override @Override
public void fieldMatch(List<MetaField> list, DataField field, List<DataField> fieldMatchList) { public void fieldMatch(DataField field, List<DataField> fieldMatchList) {
if (StringUtils.isBlank(field.getTitle())) { if (StringUtils.isBlank(field.getTitle())) {
return; return;
} }
MetaField metaField = null; Optional<DataField> fieldOptional = fieldMatchList.stream().filter(item -> {
DataField dataField = null; // 1.先判断两个是否相等
if (!CollectionUtils.isEmpty(list)) { if (StringUtils.equals(item.getTitle().trim(), field.getTitle().trim())) {
list.forEach(item -> { return true;
if (StringUtils.isNotBlank(item.getFieldComment())) {
item.setRatio(DataImportUtils.getSimilarityRatio(field.getTitle(), item.getFieldComment()));
} else {
item.setRatio(0);
}
});
Optional<MetaField> max = list.stream().max(Comparator.comparing(MetaField::getRatio));
if (max.isPresent()) {
metaField = max.get();
} }
} // 去除五角星号再判断
if (!CollectionUtils.isEmpty(fieldMatchList)) { return StringUtils.equals(item.getTitle().replaceAll("★","").replaceAll(":","").trim(),
fieldMatchList.forEach(item -> { field.getTitle().replaceAll("★","").replaceAll(":","").trim());
if (StringUtils.isNotBlank(item.getTitle())) { }).findFirst();
item.setRatio(DataImportUtils.getSimilarityRatio(field.getTitle(), item.getTitle())); fieldOptional.ifPresent(f ->{
} else { field.setField(f.getField());
item.setRatio(0); });
}
});
Optional<DataField> max = fieldMatchList.stream().max(Comparator.comparing(DataField::getRatio));
if (max.isPresent()) {
dataField = max.get();
}
}
if (metaField == null) {
if (dataField != null && dataField.getRatio() >= 0.5) {
log.debug("title:[{}],匹配指标名称:[{}],达成字段:[{}],相似度:[{}]",
field.getTitle(), dataField.getTitle(), dataField.getField(), dataField.getRatio());
field.setField(dataField.getField());
}
} else {
if (dataField == null) {
if (metaField.getRatio() >= 0.5) {
log.debug("title:[{}],匹配指标名称:[{}],达成字段:[{}],相似度:[{}]",
field.getTitle(), metaField.getFieldComment(), metaField.getFieldName(), metaField.getRatio());
field.setField(metaField.getId());
}
} else {
if (dataField.getRatio() >= metaField.getRatio() && dataField.getRatio() >= 0.5) {
log.debug("title:[{}],匹配指标名称:[{}],达成字段:[{}],相似度:[{}]",
field.getTitle(), dataField.getTitle(), dataField.getField(), dataField.getRatio());
field.setField(dataField.getField());
} else if (metaField.getRatio() >= 0.5) {
log.debug("title:[{}],匹配指标名称:[{}],达成字段:[{}],相似度:[{}]",
field.getTitle(), metaField.getFieldComment(), metaField.getFieldName(), metaField.getRatio());
field.setField(metaField.getId());
}
}
}
} }
@Override @Override
......
package com.tbyf.his.web.dataImport.service.impl; package com.tbyf.his.web.dataImport.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.adapter.task.StringColumnRowMapper;
import com.tbyf.his.common.annotation.DataSource; import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.annotation.Excel;
import com.tbyf.his.common.core.text.StrFormatter; import com.tbyf.his.common.core.text.StrFormatter;
import com.tbyf.his.common.enums.DataSourceType; import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.common.utils.StringUtils; import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.common.utils.poi.ExcelUtil;
import com.tbyf.his.web.dataImport.DataImportUtils; import com.tbyf.his.web.dataImport.DataImportUtils;
import com.tbyf.his.web.dataImport.core.DiConfig; import com.tbyf.his.web.dataImport.core.*;
import com.tbyf.his.web.dataImport.core.DiConstants;
import com.tbyf.his.web.dataImport.core.RuleVO;
import com.tbyf.his.web.dataImport.core.RuleValidator;
import com.tbyf.his.web.dataImport.domain.vo.ExcelVO; import com.tbyf.his.web.dataImport.domain.vo.ExcelVO;
import com.tbyf.his.web.dataImport.domain.vo.VerifyVO; import com.tbyf.his.web.dataImport.domain.vo.VerifyVO;
import com.tbyf.his.web.dataImport.entity.DataRule; import com.tbyf.his.web.dataImport.entity.DataRule;
...@@ -21,23 +19,28 @@ import com.tbyf.his.web.dataImport.service.DataSourceService; ...@@ -21,23 +19,28 @@ import com.tbyf.his.web.dataImport.service.DataSourceService;
import com.tbyf.his.web.dataImport.service.DataTemplateService; import com.tbyf.his.web.dataImport.service.DataTemplateService;
import com.tbyf.his.web.dataImport.service.ExcelDataService; import com.tbyf.his.web.dataImport.service.ExcelDataService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.statement.select.Select;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -55,9 +58,196 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData ...@@ -55,9 +58,196 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData
@Autowired @Autowired
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
@Override @Override
public void analyzeExport(ExcelData excelData, HttpServletResponse response) { public void analyzeExport(ExcelData excelData, HttpServletResponse response) {
// 查询出所有字段配置
final DataTemplate template = dataTemplateService.getById(excelData.getTemplateId());
List<VerifyVO> verifyList = dataTemplateService.getVerify(template.getId());
// 拼接sql查询数据
String sqlTemplate = "SELECT {} FROM {} WHERE YEAROOFDATARECORD = '{}' ORDER BY ROWCODE";
String fieldSql = verifyList.stream().map(VerifyVO::getFieldName).collect(Collectors.joining(","));
List<Map<String, String>> dataList;
ExcelVO[] excels;
try {
DataSourceService.switchDb(template.getDataSourceId());
// 需要先清空临时表的数据,按照年份
dataList = jdbcTemplate.query(StrFormatter.format(sqlTemplate, fieldSql, template.getTableName(), template.getYear() + "年"), new StringColumnRowMapper());
// 解析数据到values里面
for (VerifyVO verifyVO : verifyList) {
dataList.forEach(map -> {
String s = map.get(verifyVO.getFieldName());
verifyVO.addValue(StringUtils.isBlank(s) ? StringUtils.EMPTY : s);
});
}
// 获取每一步的核心机构等信息
excels = new ExcelVO[dataList.size()];
for (int e = 0; e < dataList.size(); e++) {
excels[e] = new ExcelVO();
excels[e].setOrgType(template.getOrgName());
String orgName = dataList.get(e).get("ORG_NAME");
String orgCode = dataList.get(e).get("ORG_CODE");
String uniformCreditNumber = dataList.get(e).get("UNIFORM_CREDIT_NUMBER");
String areaNumberCode = dataList.get(e).get("AREA_NUMBER_CODE");
excels[e].setOrgName(StringUtils.isBlank(orgName) ? StringUtils.EMPTY : orgName);
excels[e].setOrgCode(StringUtils.isBlank(orgCode) ? StringUtils.EMPTY : orgCode);
excels[e].setUnifiedCode(StringUtils.isBlank(uniformCreditNumber) ? StringUtils.EMPTY : uniformCreditNumber);
excels[e].setAreaCode(StringUtils.isBlank(areaNumberCode) ? StringUtils.EMPTY : areaNumberCode);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
DataSourceService.switchDefault();
}
// 第二步进行数据校验
verifyList.stream()
.filter(item -> !CollectionUtils.isEmpty(item.getValues()) && !CollectionUtils.isEmpty(item.getRules()))
.forEach(item -> {
for (int i = 0; i < item.getValues().size(); i++) {
for (int j = 0; j < item.getRules().size(); j++) {
final RuleVO vo = item.getRules().get(j);
vo.setValue(item.getValues().get(i));
// 置空错误信息
vo.setResult(null);
// TODO 特殊数据无需做错误校验
if (DiConstants.WHITE.contains(vo.getValue())) {
break;
}
final RuleValidator validator = DiConfig.getValidator(vo.getMode());
validator.validate(vo);
if (StringUtils.isNotBlank(vo.getResult())) {
ExcelVO excelVO = new ExcelVO();
BeanUtils.copyProperties(excels[i], excelVO);
excelVO.setCode(item.getCode())
.setTitle(item.getTitle())
.setValue(item.getValues().get(i))
.setMessage(vo.getResult());
item.addError(excelVO);
}
}
}
});
List<ExcelVO> list = new ArrayList<>();
verifyList.forEach(item -> {
if (!CollectionUtils.isEmpty(item.getErrors())) {
list.addAll(item.getErrors());
}
});
// 模板规则的数据校验
final List<DataRule> allRule = dataTemplateService.getAllRule(template.getId());
for (DataRule rule : allRule) {
if (StringUtils.isNotBlank(rule.getContent())) {
if (StringUtils.equals(rule.getMode(), "逻辑相加")) {
final String[] split = rule.getContent().split("=");
if (split.length == 2) {
String[] leftIds = split[0].split(",");
String[] rightIds = split[1].split(",");
final List<String> leftList = Arrays.stream(leftIds).filter(StringUtils::isNotBlank).collect(Collectors.toList());
final List<String> rightList = Arrays.stream(rightIds).filter(StringUtils::isNotBlank).collect(Collectors.toList());
if (leftList.size() > 0 && rightList.size() > 0) {
for (int r = 0; r < dataList.size(); r++) {
final List<VerifyVO> leftObjs = verifyList.stream().filter(v -> leftList.contains(v.getMetaFieldId())).collect(Collectors.toList());
final List<VerifyVO> rightObjs = verifyList.stream().filter(v -> rightList.contains(v.getMetaFieldId())).collect(Collectors.toList());
try {
BigDecimal left = new BigDecimal("0");
BigDecimal right = new BigDecimal("0");
for (VerifyVO leftVo : leftObjs) {
try {
left = left.add(new BigDecimal(leftVo.getValues().get(r)));
} catch (Exception ignore) {
}
}
for (VerifyVO rightVo : rightObjs) {
try {
right = right.add(new BigDecimal(rightVo.getValues().get(r)));
} catch (Exception ignore) {
}
}
// 这里需要进行四舍五入的精确位数处理
if (StringUtils.isNotBlank(rule.getRemarks())) {
int scale = Integer.parseInt(rule.getRemarks());
left = left.setScale(scale, RoundingMode.UP);
right = right.setScale(scale, RoundingMode.UP);
}
if (left.compareTo(right) != 0) {
ExcelVO excelVO = new ExcelVO();
BeanUtils.copyProperties(excels[r], excelVO);
excelVO.setMessage("逻辑验证错误,正确公式为:" + getFormula(leftObjs, rightObjs));
leftObjs.addAll(rightObjs);
int finalR = r;
final List<ExcelVO> errList = leftObjs.stream().map(item -> {
final ExcelVO temp = new ExcelVO();
temp.setCode(item.getCode())
.setAreaCode(excelVO.getAreaCode())
.setTitle(item.getTitle())
.setValue(item.getValues().get(finalR));
return temp;
}).collect(Collectors.toList());
final ExcelVO firstVo = errList.get(0);
firstVo.setMessage(excelVO.getMessage()).setOrgName(excelVO.getOrgName())
.setOrgType(excelVO.getOrgType()).setOrgCode(excelVO.getOrgCode())
.setUnifiedCode(excelVO.getUnifiedCode());
list.addAll(errList);
}
} catch (Exception e) {
ExcelVO excelVO = new ExcelVO();
BeanUtils.copyProperties(excels[r], excelVO);
excelVO.setMessage("逻辑验证错误,正确公式为:" + getFormula(leftObjs, rightObjs));
leftObjs.addAll(rightObjs);
int finalR = r;
final List<ExcelVO> errList = leftObjs.stream().map(item -> {
final ExcelVO temp = new ExcelVO();
temp.setCode(item.getCode())
.setAreaCode(excelVO.getAreaCode())
.setTitle(item.getTitle())
.setValue(item.getValues().get(finalR));
return temp;
}).collect(Collectors.toList());
final ExcelVO firstVo = errList.get(0);
firstVo.setMessage(excelVO.getMessage()).setOrgName(excelVO.getOrgName())
.setOrgType(excelVO.getOrgType()).setOrgCode(excelVO.getOrgCode())
.setUnifiedCode(excelVO.getUnifiedCode());
list.addAll(errList);
}
}
}
}
}
}
}
// 第四步导出异常excel
Map<String, List<ExcelVO>> areaMap = list.stream().collect(Collectors.groupingBy(ExcelVO::getAreaCode));
try (ZipArchiveOutputStream zous = new ZipArchiveOutputStream(response.getOutputStream())) {
zous.setUseZip64(Zip64Mode.AsNeeded);
areaMap.forEach((code,excelList)->{
String fileName = code + ".xlsx";
ExcelUtil<ExcelVO> util = new ExcelUtil<>(ExcelVO.class);
util.init(excelList,"异常数据分析","", Excel.Type.EXPORT);
util.writeSheet();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
util.getWb().write(baos);
IOUtils.closeQuietly(util.getWb());
byte[] bytes = baos.toByteArray();
ArchiveEntry entry = new ZipArchiveEntry(fileName);
zous.putArchiveEntry(entry);
zous.write(bytes);
zous.closeArchiveEntry();
if (baos != null) {
baos.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
}
}
public void analyzeExportOld(ExcelData excelData, HttpServletResponse response) {
final DataTemplate template = dataTemplateService.getById(excelData.getTemplateId()); final DataTemplate template = dataTemplateService.getById(excelData.getTemplateId());
List<VerifyVO> verifyList = dataTemplateService.getVerify(template.getId()); List<VerifyVO> verifyList = dataTemplateService.getVerify(template.getId());
try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) { try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) {
...@@ -159,8 +349,8 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData ...@@ -159,8 +349,8 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData
final List<String> rightList = Arrays.stream(rightIds).filter(StringUtils::isNotBlank).collect(Collectors.toList()); final List<String> rightList = Arrays.stream(rightIds).filter(StringUtils::isNotBlank).collect(Collectors.toList());
if (leftList.size() > 0 && rightList.size() > 0) { if (leftList.size() > 0 && rightList.size() > 0) {
for (int r = 0; r < length; r++) { for (int r = 0; r < length; r++) {
final List<VerifyVO> leftObjs = verifyList.stream().filter(v -> leftList.contains(v.getFieldId())).collect(Collectors.toList()); final List<VerifyVO> leftObjs = verifyList.stream().filter(v -> leftList.contains(v.getMetaFieldId())).collect(Collectors.toList());
final List<VerifyVO> rightObjs = verifyList.stream().filter(v -> rightList.contains(v.getFieldId())).collect(Collectors.toList()); final List<VerifyVO> rightObjs = verifyList.stream().filter(v -> rightList.contains(v.getMetaFieldId())).collect(Collectors.toList());
try { try {
BigDecimal left = new BigDecimal("0"); BigDecimal left = new BigDecimal("0");
BigDecimal right = new BigDecimal("0"); BigDecimal right = new BigDecimal("0");
...@@ -177,7 +367,7 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData ...@@ -177,7 +367,7 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData
} }
} }
// 这里需要进行四舍五入的精确位数处理 // 这里需要进行四舍五入的精确位数处理
if(StringUtils.isNotBlank(rule.getRemarks())) { if (StringUtils.isNotBlank(rule.getRemarks())) {
int scale = Integer.parseInt(rule.getRemarks()); int scale = Integer.parseInt(rule.getRemarks());
left = left.setScale(scale, RoundingMode.UP); left = left.setScale(scale, RoundingMode.UP);
right = right.setScale(scale, RoundingMode.UP); right = right.setScale(scale, RoundingMode.UP);
...@@ -260,6 +450,74 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData ...@@ -260,6 +450,74 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData
} }
} }
@Override
public void importData(ExcelData excelData) {
final DataTemplate template = dataTemplateService.getById(excelData.getTemplateId());
// 获取元字段与所有校验对象
List<VerifyVO> verifyList = dataTemplateService.getVerify(template.getId());
try (InputStream is = new ByteArrayInputStream(excelData.getFile()); Workbook workbook = WorkbookFactory.create(is)) {
final Sheet sheet = workbook.getSheetAt(0);
final Optional<VerifyVO> first = verifyList.stream()
.filter(item -> StringUtils.isNotBlank(item.getCoordinate()))
.findFirst();
// 获取第一个有详细坐标的数据
// 数据长度/条数 根据这一列的数据来判断一共有多少条数据,并且有数据的列的x轴坐标在哪里
final List<Integer> columnList = DiConfig.getLength(first.get(), sheet);
final int length = columnList.size();
// 第一步解析数据到values
for (final VerifyVO vo : verifyList) {
if (StringUtils.isBlank(vo.getCoordinate())) {
final String s = DiConfig.getCoordinate(vo, sheet);
if (StringUtils.isBlank(s)) {
vo.addError(new ExcelVO("没有符合代码与指标名称的字段行", ""));
continue;
}
vo.setCoordinate(s);
}
final String[] coords = vo.getCoordinate().split(",");
// TODO 这里减1的原因是excel表名的行号1实际上的下标为0
int rowStart = Integer.parseInt(coords[1]) - 1;
final Row row = sheet.getRow(rowStart);
for (Integer column : columnList) {
try {
final Cell cell = row.getCell(column, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
vo.addValue(DiConfig.getValue(cell));
} catch (Exception ignore) {
}
}
}
// 直接导入临时表
String insertSql = "INSERT INTO {}(" + verifyList.stream()
.map(VerifyVO::getFieldName).collect(Collectors.joining(","))
+ ",DORDER,YEAROOFDATARECORD,ROWCODE ) VALUES ({})";
String[] sqlArr = new String[length];
for (int i = 0; i < length; i++) {
StringBuilder sb = new StringBuilder();
for (VerifyVO v : verifyList) {
sb.append(DataImportUtils.getInsertContent(v, i)).append(",");
}
sb.append("'").append(DataImportUtils.getNextId()).append("','")
.append(template.getYear()).append("年").append("','")
.append(DataImportUtils.getNextId()).append("'");
sqlArr[i] = StrFormatter.format(insertSql, template.getTableName() + "_TEMP", sb);
}
try {
DataSourceService.switchDb(template.getDataSourceId());
// 需要先清空临时表的数据,按照年份
jdbcTemplate.execute(StrFormatter.format("DELETE FROM {} WHERE YEAROOFDATARECORD = '{}'"
, template.getTableName() + "_TEMP", template.getYear() + "年"));
jdbcTemplate.batchUpdate(sqlArr);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
DataSourceService.switchDefault();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/** /**
* 获取逻辑校验公式 * 获取逻辑校验公式
* *
...@@ -290,6 +548,6 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData ...@@ -290,6 +548,6 @@ public class ExcelDataServiceImpl extends ServiceImpl<ExcelDataMapper, ExcelData
public static void main(String[] args) { public static void main(String[] args) {
BigDecimal bigDecimal = new BigDecimal("1234567.123"); BigDecimal bigDecimal = new BigDecimal("1234567.123");
System.out.println(bigDecimal.setScale(5,BigDecimal.ROUND_DOWN).intValue()); System.out.println(bigDecimal.setScale(5, BigDecimal.ROUND_DOWN).intValue());
} }
} }
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
<result property="sort" column="sort"/> <result property="sort" column="sort"/>
<result property="fieldName" column="fieldName"/> <result property="fieldName" column="fieldName"/>
<result property="fieldType" column="fieldType"/> <result property="fieldType" column="fieldType"/>
<result property="metaFieldId" column="metaFieldId"/>
<collection property="rules" ofType="com.tbyf.his.web.dataImport.core.RuleVO"> <collection property="rules" ofType="com.tbyf.his.web.dataImport.core.RuleVO">
<id property="id" column="ruleId"/> <id property="id" column="ruleId"/>
<result property="name" column="name"/> <result property="name" column="name"/>
...@@ -66,6 +67,7 @@ ...@@ -66,6 +67,7 @@
df.unit as unit, df.unit as unit,
df.coordinate as coordinate, df.coordinate as coordinate,
df.sort as sort, df.sort as sort,
df.field as metaFieldId,
mf.field_name as fieldName, mf.field_name as fieldName,
mf.field_type as fieldType, mf.field_type as fieldType,
dr.id as ruleId, dr.id as ruleId,
......
...@@ -52,6 +52,11 @@ ...@@ -52,6 +52,11 @@
<artifactId>pinyin4j</artifactId> <artifactId>pinyin4j</artifactId>
<version>2.5.0</version> <version>2.5.0</version>
</dependency> </dependency>
<!--<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.12</version>
</dependency>-->
</dependencies> </dependencies>
</project> </project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment