md
This commit is contained in:
parent
6ce66ac16e
commit
bb82d920f5
@ -1,50 +0,0 @@
|
|||||||
package com.xdadan.erp.emis.service.billexport;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DynamicDataMapping {
|
|
||||||
|
|
||||||
private String dataId;
|
|
||||||
private List<Map<String, Object>> dataList;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 组装只有一个list类型的动态数据
|
|
||||||
* @param dataId
|
|
||||||
* @param dataList
|
|
||||||
*/
|
|
||||||
public static List<DynamicDataMapping> createOneDataList(String dataId, List<Map<String, Object>> dataList) {
|
|
||||||
if (dataList == null)
|
|
||||||
return null;
|
|
||||||
return Collections.singletonList(getDynamicDataMapping(dataId,dataList));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 组装只有多个list类型的动态数据
|
|
||||||
* @param transMap
|
|
||||||
*/
|
|
||||||
public static List<DynamicDataMapping> createMorDataList(Map<String,List<Map<String, Object>>> transMap) {
|
|
||||||
if (transMap == null)
|
|
||||||
return null;
|
|
||||||
List<DynamicDataMapping> list = new ArrayList<>();
|
|
||||||
transMap.forEach((dataId,dataList)->{
|
|
||||||
list.add(getDynamicDataMapping(dataId,dataList));
|
|
||||||
});
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DynamicDataMapping getDynamicDataMapping(String dataId, List<Map<String, Object>> dataList){
|
|
||||||
DynamicDataMapping dynamicData = new DynamicDataMapping();
|
|
||||||
dynamicData.dataId = dataId;
|
|
||||||
dynamicData.dataList = dataList;
|
|
||||||
return dynamicData;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,250 +0,0 @@
|
|||||||
package com.xdadan.erp.emis.service.billexport;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.poi.ss.usermodel.CellCopyPolicy;
|
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFCell;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFRow;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
||||||
import org.springframework.util.ResourceUtils;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description 根据模版导出Excel程序
|
|
||||||
*/
|
|
||||||
public class ExcelTemplateProc {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param templateFileName
|
|
||||||
* @param exportFilePathAndName
|
|
||||||
* @param staticDataMap
|
|
||||||
* @param dynamicDataMappingList
|
|
||||||
* @return void
|
|
||||||
* @description: 根据模版导出Excel入口
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
public static void doExportExcelByTemplateProc(String templateFileName, String exportFilePathAndName,
|
|
||||||
Map<String, Object> staticDataMap,
|
|
||||||
List<DynamicDataMapping> dynamicDataMappingList) throws IOException {
|
|
||||||
/**
|
|
||||||
* 1. 从resources下加载模板并替换
|
|
||||||
* 使用 ResourceUtils 加载文件
|
|
||||||
*/
|
|
||||||
File file = ResourceUtils.getFile("classpath:"+templateFileName);
|
|
||||||
InputStream inputStream = new FileInputStream(file);
|
|
||||||
|
|
||||||
Workbook workbook = dealFirstSheetByTemplate(inputStream, staticDataMap, dynamicDataMappingList);
|
|
||||||
// 2. 保存到本地
|
|
||||||
saveExportFile(workbook, exportFilePathAndName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param workbook
|
|
||||||
* @param excelFilePath
|
|
||||||
* @return void
|
|
||||||
* @description: 保存导出的Excel文件到服务器
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
public static void saveExportFile(Workbook workbook, String excelFilePath) throws IOException {
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(excelFilePath);
|
|
||||||
executeWorkBookWrite(workbook, outputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param workbook
|
|
||||||
* @param outputStream
|
|
||||||
* @return void
|
|
||||||
* @description: 数据输出
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
public static void executeWorkBookWrite(Workbook workbook, OutputStream outputStream) throws IOException {
|
|
||||||
workbook.write(outputStream);
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
workbook.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param inputStream
|
|
||||||
* @param staticDataMap
|
|
||||||
* @param dynamicDataMappingList
|
|
||||||
* @return org.apache.poi.ss.usermodel.Workbook
|
|
||||||
* @description: 处理只有一个sheet页的模版
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
public static Workbook dealFirstSheetByTemplate(InputStream inputStream,
|
|
||||||
Map<String, Object> staticDataMap,
|
|
||||||
List<DynamicDataMapping> dynamicDataMappingList) throws IOException {
|
|
||||||
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
|
|
||||||
XSSFSheet sheet = workbook.getSheetAt(0);
|
|
||||||
// 按模板处理sheet页
|
|
||||||
dealSheetDataByTemplate(sheet, staticDataMap, dynamicDataMappingList);
|
|
||||||
return workbook;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param sheet
|
|
||||||
* @param staticDataMap
|
|
||||||
* @param dynamicDataMappingList
|
|
||||||
* @return void
|
|
||||||
* @description: 按模板处理sheet页里的数据
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/19
|
|
||||||
*/
|
|
||||||
private static void dealSheetDataByTemplate(XSSFSheet sheet, Map<String, Object> staticDataMap, List<DynamicDataMapping> dynamicDataMappingList) {
|
|
||||||
// 循环sheet里每一行
|
|
||||||
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
|
|
||||||
XSSFRow row = sheet.getRow(i);
|
|
||||||
DynamicDataMapping dynamicDataMapping = getDynamicRowDataByMatch(row, dynamicDataMappingList);
|
|
||||||
if (dynamicDataMapping != null) {
|
|
||||||
i = getTemplateLastRowIndexAfterDealTemplate(sheet, i, dynamicDataMapping);
|
|
||||||
} else {
|
|
||||||
dealTemplateDataRow(row, null, staticDataMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param row
|
|
||||||
* @param dataMap
|
|
||||||
* @param dataPrefix
|
|
||||||
* @return void
|
|
||||||
* @description: 循环处理模版中每行的数据
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
private static void dealTemplateDataRow(XSSFRow row, String dataPrefix, Map<String, Object> dataMap) {
|
|
||||||
if (dataMap == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
|
|
||||||
// XSSFCell cell = row.getCell(i);
|
|
||||||
// fillInTemplateCellDataValue(cell, dataPrefix, dataMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cell
|
|
||||||
* @param dataPrefix
|
|
||||||
* @param dataMap
|
|
||||||
* @return void
|
|
||||||
* @description: 填充模版里单元格的值
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
private static void fillInTemplateCellDataValue(XSSFCell cell, String dataPrefix, Map<String, Object> dataMap) {
|
|
||||||
if (cell == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String cellValue = cell.getStringCellValue();//获取模版里设置的数据
|
|
||||||
if (StringUtils.isEmpty(cellValue)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean flag = false;
|
|
||||||
dataPrefix = StringUtils.isEmpty(dataPrefix) ? "" : (dataPrefix + ".");
|
|
||||||
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
|
|
||||||
// 循环所有,因为可能一行有多个占位符
|
|
||||||
String cellTemplateStr = "{{" + dataPrefix + entry.getKey() + "}}";
|
|
||||||
if (cellValue.contains(cellTemplateStr)) {
|
|
||||||
// 替换模版中单元格的数据
|
|
||||||
cellValue = cellValue.replace(cellTemplateStr, entry.getValue() == null ? "" : entry.getValue().toString());
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flag) {
|
|
||||||
// cell.setCellValue(cellValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param row
|
|
||||||
* @param dynamicDataMappingList
|
|
||||||
* @return com.liu.susu.excel.template.poi.common.DynamicDataMapping
|
|
||||||
* @description: 通过模版sheet中的行数据 与 动态数据匹配,获取此行需要填充的动态数据
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/21
|
|
||||||
*/
|
|
||||||
private static DynamicDataMapping getDynamicRowDataByMatch(XSSFRow row, List<DynamicDataMapping> dynamicDataMappingList) {
|
|
||||||
if (dynamicDataMappingList == null || dynamicDataMappingList.size() < 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
|
|
||||||
// XSSFCell cell = row.getCell(j);
|
|
||||||
// String value = cell.getStringCellValue();
|
|
||||||
// if (value != null) {
|
|
||||||
// for (DynamicDataMapping dynamicData : dynamicDataMappingList) {
|
|
||||||
// if (value.startsWith("{{" + dynamicData.getDataId() + ".")) {
|
|
||||||
// return dynamicData;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param sheet
|
|
||||||
* @param rowIndex
|
|
||||||
* @param dynamicDataMapping
|
|
||||||
* @return int
|
|
||||||
* @description: 根据动态数据的条数动态复制模版行,每处理一个类型的list返回最后的行数,进而处理下一个类型的list
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
private static int getTemplateLastRowIndexAfterDealTemplate(XSSFSheet sheet, int rowIndex, DynamicDataMapping dynamicDataMapping) {
|
|
||||||
if (dynamicDataMapping == null) {
|
|
||||||
return rowIndex;
|
|
||||||
}
|
|
||||||
int dataRows = dynamicDataMapping.getDataList().size();
|
|
||||||
// 需要拷贝的行数(因为模板行本身占1行,所以-1)
|
|
||||||
int copyRows = dataRows - 1;
|
|
||||||
if (copyRows > 0) {
|
|
||||||
/**
|
|
||||||
* shiftRows: 从动态数据模版行(rowIndex)到最后一行,这些全部行都向下移copyRows行
|
|
||||||
* 相当于模版行上面插入n行空行(n=copyRows)
|
|
||||||
*/
|
|
||||||
sheet.shiftRows(rowIndex, sheet.getLastRowNum(), copyRows, true, false);
|
|
||||||
// 拷贝策略
|
|
||||||
CellCopyPolicy cellCopyPolicy = makeCellCopyPolicy();
|
|
||||||
// 因为从模版行开始向下平移了copyRows行,所以这里 模板行=rowIndex + copyRows,
|
|
||||||
int templateDataRow = rowIndex + copyRows;
|
|
||||||
// 因为模版行上新增了空行,所以要把模板所在行的模版 拷贝到上面新增的空行
|
|
||||||
for (int i = 0; i < copyRows; i++) {
|
|
||||||
//templateDataRow-模版行数据 rowIndex + i循环的当前空行
|
|
||||||
sheet.copyRows(templateDataRow, templateDataRow, rowIndex + i, cellCopyPolicy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 循环模版行:动态替换模版行(将模版行里的模版替换成动态数据)
|
|
||||||
for (int j = rowIndex; j < rowIndex + dataRows; j++) {
|
|
||||||
Map<String, Object> dataMap = dynamicDataMapping.getDataList().get(j - rowIndex);
|
|
||||||
dealTemplateDataRow(sheet.getRow(j), dynamicDataMapping.getDataId(), dataMap);
|
|
||||||
}
|
|
||||||
return rowIndex + copyRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param
|
|
||||||
* @return org.apache.poi.ss.usermodel.CellCopyPolicy
|
|
||||||
* @description: 拷贝策略
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
public static CellCopyPolicy makeCellCopyPolicy() {
|
|
||||||
CellCopyPolicy cellCopyPolicy = new CellCopyPolicy();
|
|
||||||
cellCopyPolicy.setCopyCellValue(true);
|
|
||||||
cellCopyPolicy.setCopyCellStyle(true);
|
|
||||||
return cellCopyPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
package com.xdadan.erp.emis.service.billexport;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description 根据模版导出Excel工具类
|
|
||||||
* @Author susu
|
|
||||||
* @Date 2024/2/19
|
|
||||||
*/
|
|
||||||
public class ExportExcelByTemplateUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 根据模版导出Excel入口(单个list数据)
|
|
||||||
* @param templateFileName
|
|
||||||
* @param exportFilePathAndName
|
|
||||||
* @param staticDataMap
|
|
||||||
* @param dataId
|
|
||||||
* @param originDataList
|
|
||||||
* @return void
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/21
|
|
||||||
*/
|
|
||||||
public static void doExportExcelOneListByTemplate(String templateFileName, String exportFilePathAndName,
|
|
||||||
Map<String, Object> staticDataMap,
|
|
||||||
String dataId,
|
|
||||||
List<?> originDataList) throws Exception{
|
|
||||||
|
|
||||||
List<Map<String, Object>> exportDataList = MapObjectUtil.objListToMapList(originDataList);
|
|
||||||
// 只有一个list数据
|
|
||||||
List<DynamicDataMapping> dynamicDataMappingList = DynamicDataMapping.createOneDataList(dataId, exportDataList);
|
|
||||||
// 导出
|
|
||||||
ExcelTemplateProc.doExportExcelByTemplateProc(templateFileName,exportFilePathAndName,staticDataMap,dynamicDataMappingList);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 根据模版导出Excel入口(多个list数据)
|
|
||||||
* @param templateFileName
|
|
||||||
* @param exportFilePathAndName
|
|
||||||
* @param staticSource
|
|
||||||
* @param originDataMapList
|
|
||||||
* @return void
|
|
||||||
* @author susu
|
|
||||||
* @date 2024/2/20
|
|
||||||
*/
|
|
||||||
public static void doExportExcelMoreListByTemplate(String templateFileName,
|
|
||||||
String exportFilePathAndName,
|
|
||||||
Map<String, Object> staticSource,
|
|
||||||
Map<String, List<?>> originDataMapList) throws Exception{
|
|
||||||
|
|
||||||
Map<String,List<Map<String, Object>>> transMap = new HashMap<>();
|
|
||||||
originDataMapList.forEach((dataId,originDataList)->{
|
|
||||||
List<Map<String, Object>> transDataList = MapObjectUtil.objListToMapList(originDataList);
|
|
||||||
transMap.put(dataId,transDataList);
|
|
||||||
});
|
|
||||||
// 多个list类型数据
|
|
||||||
List<DynamicDataMapping> dynamicDataMappingList = DynamicDataMapping.createMorDataList(transMap);
|
|
||||||
// 导出
|
|
||||||
ExcelTemplateProc.doExportExcelByTemplateProc(templateFileName,exportFilePathAndName,staticSource,dynamicDataMappingList);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
package com.xdadan.erp.emis.service.billexport;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.apache.commons.beanutils.BeanMap;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description
|
|
||||||
* @Author susu
|
|
||||||
* @Date 2024/2/19
|
|
||||||
*/
|
|
||||||
public class MapObjectUtil {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 将object的list数据 转换成 map的list(如:List<Map<String, Object>>)
|
|
||||||
* @param objDataList
|
|
||||||
* @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
|
|
||||||
* @author susu
|
|
||||||
*/
|
|
||||||
public static List<Map<String, Object>> objListToMapList(List<?> objDataList){
|
|
||||||
List<Map<String, Object>> dataList = new ArrayList<>();
|
|
||||||
if (objDataList==null || objDataList.size()<1){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
objDataList.forEach(obj->{
|
|
||||||
try {
|
|
||||||
Map<String, Object> map = MapObjectUtil.objectToMap(obj);
|
|
||||||
dataList.add(map);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return dataList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 将object数据转换成map数据
|
|
||||||
* @param obj
|
|
||||||
* @return java.util.Map<java.lang.String,java.lang.Object>
|
|
||||||
* @author susu
|
|
||||||
*/
|
|
||||||
public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
|
|
||||||
Map<String, Object> map = new HashMap();
|
|
||||||
Class<?> cla = obj.getClass();
|
|
||||||
Field[] fields = cla.getDeclaredFields();
|
|
||||||
for (Field field : fields) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
String keyName = field.getName();
|
|
||||||
Object value = field.get(obj);
|
|
||||||
if (value == null)
|
|
||||||
value = "";
|
|
||||||
map.put(keyName, value);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 使用 JSONObject 将object转换成map
|
|
||||||
* @param obj
|
|
||||||
* @return java.util.Map<?,?>
|
|
||||||
* @author susu
|
|
||||||
*/
|
|
||||||
public static Map<?, ?> objectToMap2(Object obj) {
|
|
||||||
if (obj == null)
|
|
||||||
return null;
|
|
||||||
return JSONObject.parseObject(JSONObject.toJSONString(obj),Map.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 使用BeanMap将object转换成map
|
|
||||||
* @param obj
|
|
||||||
* @return java.util.Map<?,?>
|
|
||||||
* @author susu
|
|
||||||
*/
|
|
||||||
public static Map<?, ?> objectToMap3(Object obj) {
|
|
||||||
if (obj == null)
|
|
||||||
return null;
|
|
||||||
return new BeanMap(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
// DogEntity2 dog = new DogEntity2();
|
|
||||||
// dog.setDogId("A-1001");
|
|
||||||
// dog.setDogAge(3);
|
|
||||||
// dog.setDogName("aaa");
|
|
||||||
//// Map map = JSONObject.parseObject(JSONObject.toJSONString(dog),Map.class);
|
|
||||||
// Map map = objectToMap2(dog);
|
|
||||||
// System.out.println(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user