Commit 55bd8d70 authored by 郝旭阳's avatar 郝旭阳

结算物料导出

parent a0086b84
package com.maintain.business.controller; package com.maintain.business.controller;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
import com.maintain.business.domain.vo.ErpMaterialPickingExportVo;
import com.maintain.common.utils.poi.SheetPO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*; import javax.validation.constraints.*;
...@@ -62,8 +65,9 @@ public class ErpMaterialPickingController extends BaseController { ...@@ -62,8 +65,9 @@ public class ErpMaterialPickingController extends BaseController {
@Log(title = "物料出库", businessType = BusinessType.EXPORT) @Log(title = "物料出库", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(ErpMaterialPickingBo bo, HttpServletResponse response) { public void export(ErpMaterialPickingBo bo, HttpServletResponse response) {
List<ErpMaterialPickingVo> list = iErpMaterialPickingService.queryList(bo); iErpMaterialPickingService.export(bo,response);
ExcelUtil.exportExcel(list, "物料出库", ErpMaterialPickingVo.class, response); // List<ErpMaterialPickingVo> list = iErpMaterialPickingService.queryList(bo);
// ExcelUtil.exportExcel(list, "物料出库", ErpMaterialPickingVo.class, response);
} }
/** /**
......
...@@ -131,4 +131,14 @@ public class ErpMaterialPickingBo extends BaseEntity { ...@@ -131,4 +131,14 @@ public class ErpMaterialPickingBo extends BaseEntity {
private List<ErpMaterialPickingInfoAddBo> materialList; private List<ErpMaterialPickingInfoAddBo> materialList;
/**
* 导出IDs
*/
private List<Long> ids;
/**
* 单位IDS
*/
private List<Long> deptIds;
} }
package com.maintain.business.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.alibaba.excel.annotation.write.style.HeadStyle;
import com.alibaba.excel.enums.poi.BorderStyleEnum;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.alibaba.excel.enums.poi.VerticalAlignmentEnum;
import com.maintain.common.annotation.ExcelDictFormat;
import com.maintain.common.convert.ExcelDictConvert;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Author haoxuyang
* @Date 2026/4/2 9:24
*/
@Data
@HeadRowHeight(value = 35)
@ContentRowHeight(value = 22)
/** 金黄表头、黑字、细边框(与 IndexedColors 调色板接近 #FFC107/#FFB800 效果) */
@HeadStyle(
fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND,
fillForegroundColor = 51,
horizontalAlignment = HorizontalAlignmentEnum.CENTER,
verticalAlignment = VerticalAlignmentEnum.CENTER,
borderLeft = BorderStyleEnum.THIN,
borderRight = BorderStyleEnum.THIN,
borderTop = BorderStyleEnum.THIN,
borderBottom = BorderStyleEnum.THIN,
leftBorderColor = 8,
rightBorderColor = 8,
topBorderColor = 8,
bottomBorderColor = 8
)
@HeadFontStyle(color = 8)
public class ErpMaterialPickingExportVo {
/**
* 序号
*/
@ColumnWidth(15)
@ExcelProperty(index = 0, value = {"title", "序号"})
private String index;
/**
* 分公司
*/
@ColumnWidth(15)
@ExcelProperty(index = 1, value = {"title", "分公司"})
private String branchOffice;
/**
* 车间
*/
@ColumnWidth(15)
@ExcelProperty(index = 2, value = {"title", "车间"})
private String workshopName;
/**
* 仓库
*/
@ColumnWidth(15)
@ExcelProperty(index = 3, value = {"title", "仓库"})
private String warehouseName;
/**
* 领料人
*/
@ColumnWidth(15)
@ExcelProperty(index = 4, value = {"title", "领料人"})
private String receiveUserName;
/**
* 领料时间
*/
@ColumnWidth(25)
@ExcelProperty(index = 5, value = {"title", "领料时间"})
private Date receiveTime;
/**
* 材料编码
*/
@ColumnWidth(15)
@ExcelProperty(index = 6, value = {"title", "材料编码"})
private String materialCode;
/**
* 物资名称
*/
@ColumnWidth(15)
@ExcelProperty(index = 7, value = {"title", "物资名称"})
private String materialName;
/**
* 规格
*/
@ColumnWidth(15)
@ExcelProperty(index = 8, value = {"title", "规格"})
private String materialSpecifications;
/**
* 单位
*/
@ColumnWidth(15)
@ExcelProperty(index = 9, value = {"title", "单位"}, converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "material_unit")
private String materialUnit;
/**
* 入库价格
*/
@ColumnWidth(15)
@ExcelProperty(index = 10, value = {"title", "入库价格"})
private BigDecimal putawayPrice;
/**
* 数量
*/
@ColumnWidth(15)
@ExcelProperty(index = 11, value = {"title", "数量"})
private BigDecimal collectNumber;
/**
* 合计(元)
*/
@ColumnWidth(15)
@ExcelProperty(index = 12, value = {"title", "合计(元)"})
private BigDecimal money;
}
...@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.toolkit.Constants; ...@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.maintain.business.domain.ErpMaterialPickingInfo; import com.maintain.business.domain.ErpMaterialPickingInfo;
import com.maintain.business.domain.ErpMaterialReturnsInfo; import com.maintain.business.domain.ErpMaterialReturnsInfo;
import com.maintain.business.domain.bo.ErpMaterialPickingBo;
import com.maintain.business.domain.vo.ErpMaterialPickingExportVo;
import com.maintain.business.domain.vo.ErpMaterialPickingInfoVo; import com.maintain.business.domain.vo.ErpMaterialPickingInfoVo;
import com.maintain.business.domain.vo.ErpMaterialReturnsInfoVo; import com.maintain.business.domain.vo.ErpMaterialReturnsInfoVo;
import com.maintain.common.core.mapper.BaseMapperPlus; import com.maintain.common.core.mapper.BaseMapperPlus;
...@@ -35,4 +37,10 @@ public interface ErpMaterialPickingInfoMapper extends BaseMapperPlus<ErpMaterial ...@@ -35,4 +37,10 @@ public interface ErpMaterialPickingInfoMapper extends BaseMapperPlus<ErpMaterial
*/ */
List<ErpMaterialPickingInfoVo> customQueryList(@Param(Constants.WRAPPER) Wrapper<ErpMaterialPickingInfo> queryWrapper); List<ErpMaterialPickingInfoVo> customQueryList(@Param(Constants.WRAPPER) Wrapper<ErpMaterialPickingInfo> queryWrapper);
/**
* 获取导出列表
* @param bo 参数
* @return 结果
*/
List<ErpMaterialPickingExportVo> getExportList(ErpMaterialPickingBo bo);
} }
...@@ -6,6 +6,7 @@ import com.maintain.business.domain.bo.ErpMaterialPickingBo; ...@@ -6,6 +6,7 @@ import com.maintain.business.domain.bo.ErpMaterialPickingBo;
import com.maintain.common.core.page.TableDataInfo; import com.maintain.common.core.page.TableDataInfo;
import com.maintain.common.core.domain.PageQuery; import com.maintain.common.core.domain.PageQuery;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
...@@ -63,4 +64,9 @@ public interface IErpMaterialPickingService { ...@@ -63,4 +64,9 @@ public interface IErpMaterialPickingService {
* 新增物料出库退料 * 新增物料出库退料
*/ */
Boolean insertReturnByBo(ErpMaterialPickingBo bo); Boolean insertReturnByBo(ErpMaterialPickingBo bo);
/**
* 导出物料出库列表
*/
void export(ErpMaterialPickingBo bo, HttpServletResponse response);
} }
package com.maintain.business.service.impl; package com.maintain.business.service.impl;
import java.util.Date;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.maintain.business.domain.*; import com.maintain.business.domain.*;
import com.maintain.business.domain.bo.ErpMaterialPickingInfoAddBo; import com.maintain.business.domain.bo.ErpMaterialPickingInfoAddBo;
import com.maintain.business.domain.bo.ErpMaterialPickingInfoBo; import com.maintain.business.domain.bo.ErpMaterialPickingInfoBo;
...@@ -22,6 +24,9 @@ import com.maintain.common.core.domain.PageQuery; ...@@ -22,6 +24,9 @@ import com.maintain.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.maintain.common.utils.poi.ExcelUtil;
import com.maintain.common.utils.poi.MergeCellModel;
import com.maintain.common.utils.poi.SheetPO;
import com.maintain.common.utils.redis.RedisUtils; import com.maintain.common.utils.redis.RedisUtils;
import com.maintain.system.mapper.SysDeptMapper; import com.maintain.system.mapper.SysDeptMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -30,6 +35,7 @@ import com.maintain.business.domain.bo.ErpMaterialPickingBo; ...@@ -30,6 +35,7 @@ import com.maintain.business.domain.bo.ErpMaterialPickingBo;
import com.maintain.business.service.IErpMaterialPickingService; import com.maintain.business.service.IErpMaterialPickingService;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -446,4 +452,58 @@ public class ErpMaterialPickingServiceImpl implements IErpMaterialPickingService ...@@ -446,4 +452,58 @@ public class ErpMaterialPickingServiceImpl implements IErpMaterialPickingService
} }
return flag; return flag;
} }
@Override
public void export(ErpMaterialPickingBo bo, HttpServletResponse response) {
String sheetName ="供应商材料消耗明细表";
String title ="供应商铺货结算表";
List<SysDept> sysDeptList = deptMapper.selectChildrenDeptById(LoginHelper.getDeptId(), null);
if (!sysDeptList.isEmpty()){
bo.setDeptIds(sysDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList()));
}
List<ErpMaterialPickingExportVo> list = pickingInfoMapper.getExportList(bo);
//生成合并单元格信息
List<MergeCellModel> mergeCellList = new ArrayList<>();
Integer centerMergedAnchorExcelRowIndex = null;
if (CollectionUtils.isNotEmpty(list)){
list.forEach(item -> {
item.setIndex(String.valueOf(list.indexOf(item) + 1));
});
//合计统计
ErpMaterialPickingExportVo erpMaterialPickingExportVo1 = new ErpMaterialPickingExportVo();
// 合计文案须落在合并区域左上角列:index=0 为序号(Integer),合并 0~10 时左上角为空会“吃掉”7、8 列的合计文字
erpMaterialPickingExportVo1.setIndex("合计");
list.add(erpMaterialPickingExportVo1);
// 双行表头:第 0 行为大标题,第 1 行为列名;合计行 Excel 行号 = list.size() + 1
int totalExcelRowIndex = list.size() + 1;
centerMergedAnchorExcelRowIndex = totalExcelRowIndex;
mergeCellList.add(MergeCellModel.createMergeCellModel(sheetName, totalExcelRowIndex, totalExcelRowIndex, 0, 10));
//计算数量总和
BigDecimal collectNumber = list.stream().map(ErpMaterialPickingExportVo::getCollectNumber).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
erpMaterialPickingExportVo1.setCollectNumber(collectNumber);
//计算价格总和
BigDecimal money = list.stream().map(ErpMaterialPickingExportVo::getMoney).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
erpMaterialPickingExportVo1.setMoney(money);
//签名地方
ErpMaterialPickingExportVo erpMaterialPickingExportVo2 = new ErpMaterialPickingExportVo();
erpMaterialPickingExportVo2.setWorkshopName("车间仓库员签名:");
erpMaterialPickingExportVo2.setMaterialSpecifications("车间负责人签名:");
list.add(erpMaterialPickingExportVo2);
}
List<SheetPO> sheetPOList = new ArrayList<>();
SheetPO<ErpMaterialPickingExportVo> sheetPO = new SheetPO<>();
sheetPOList.add(sheetPO);
Map<String, String> titleMap = new HashMap<>();
titleMap.put("title", title);
sheetPO.setData(list);
sheetPO.setTitleMap(titleMap);
sheetPO.setClazz(ErpMaterialPickingExportVo.class);
sheetPO.setSheetNo(1);
sheetPO.setMergeCellList(mergeCellList);
sheetPO.setSheetName(sheetName);
sheetPO.setWhiteFirstHeadRow(true);
sheetPO.setCenterMergedAnchorExcelRowIndex(centerMergedAnchorExcelRowIndex);
ExcelUtil.exportSheetSetTitle(response, title, sheetPOList);
}
} }
...@@ -49,5 +49,62 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -49,5 +49,62 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
${ew.getCustomSqlSegment} ${ew.getCustomSqlSegment}
</select> </select>
<select id="getExportList" resultType="com.maintain.business.domain.vo.ErpMaterialPickingExportVo">
SELECT
ec.branch_office AS branchOffice,
empi.warehouse_name AS warehouseName,
emp.receive_user_name AS receiveUserName,
emp.receive_time AS receiveTime,
empi.material_code AS materialCode,
empi.material_name AS materialName,
empi.material_specifications AS materialSpecifications,
empi.material_unit AS materialUnit,
empi.putaway_price AS putawayPrice,
empi.collect_number AS collectNumber,
empi.`money` AS money
FROM
erp_material_picking_info empi
LEFT JOIN erp_material_picking emp ON empi.picking_id = emp.id
LEFT JOIN erp_car ec ON ec.id = emp.car_id
<where>
<if test="repairNumber != null">
and emp.repair_number like CONCAT('%',#{repairNumber},'%')
</if>
<if test="outNumber != null">
and emp.out_number like CONCAT('%',#{outNumber},'%')
</if>
<if test="plateNumber != null">
and emp.plate_number like CONCAT('%',#{plateNumber},'%')
</if>
<if test="settlementState != null">
and emp.settlement_state = #{settlementState}
</if>
<if test="type != null">
and emp.type = #{type}
</if>
<if test="plateNumber != null">
and emp.plate_number like CONCAT('%',#{plateNumber},'%')
</if>
<if test="ids != null and ids.size()>0">
AND emp.id in
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
#{id}
</foreach>
</if>
<if test="stateList != null and stateList.size()>0">
AND emp.state in
<foreach item="state" collection="stateList" separator="," open="(" close=")" index="">
#{state}
</foreach>
</if>
<if test="deptIds != null and deptIds.size()>0">
AND emp.create_dept_id in
<foreach item="deptId" collection="deptIds" separator="," open="(" close=")" index="">
#{deptId}
</foreach>
</if>
</where>
GROUP BY empi.id
ORDER BY emp.receive_time DESC
</select>
</mapper> </mapper>
package com.maintain.common.utils.poi;
import org.apache.commons.lang3.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
/**
* 注解工具类
*/
public class AnnotationUtils {
/**
* 变更注解的属性值再处理业务,处理完业务之后恢复类的属性
*
* @param clazz 注解所在的实体类
* @param tClass 注解类
* @param attrName 要修改的注解属性名
* @param attrTypeEnum 要修改的注解属性的类型
* @param valueMap 要设置的属性值
*/
public static <A extends Annotation> void changeAnnotationValueToDealProcess(
Class<?> clazz,
Class<A> tClass,
String attrName,
AttrTypeEnum attrTypeEnum,
Map<String, String> valueMap,
DealProcess dealProcess) {
try {
Map<String, Object> fieldAnnotationValueMap = new HashMap<>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
A annotation = field.getAnnotation(tClass);
if (annotation == null) continue;
Object value = setAnnotationValue(annotation, attrName, attrTypeEnum, valueMap);
String fieldName = field.getName();
fieldAnnotationValueMap.put(fieldName, value);
}
// 处理业务逻辑
dealProcess.deal();
// 恢复
for (Field field : fields) {
A annotation = field.getAnnotation(tClass);
String fieldName = field.getName();
if (annotation == null) continue;
Object value = fieldAnnotationValueMap.get(fieldName);
InvocationHandler handler = Proxy.getInvocationHandler(annotation);
Field memberValuesField = handler.getClass().getDeclaredField("memberValues");
memberValuesField.setAccessible(true);
@SuppressWarnings("all")
Map<String, Object> memberValues = (Map) memberValuesField.get(handler);
memberValues.put(attrName, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置注解中的字段值
*
* @param annotation 要修改的注解实例
* @param attrName 要修改的注解属性名
* @param attrTypeEnum 要修改的注解属性的类型
* @param valueMap 替换属性集的map
*/
@SuppressWarnings("all")
private static Object setAnnotationValue(Annotation annotation, String attrName,
AttrTypeEnum attrTypeEnum, Map<String, String> valueMap) throws NoSuchFieldException, IllegalAccessException {
InvocationHandler handler = Proxy.getInvocationHandler(annotation);
Field field = handler.getClass().getDeclaredField("memberValues");
field.setAccessible(true);
Map memberValues = (Map) field.get(handler);
Object value = memberValues.get(attrName);
switch (attrTypeEnum) {
case STRING: {
String oldValue = (String) value;
String newValue = valueMap.get(oldValue);
if (StringUtils.isNotBlank(newValue)) {
memberValues.put(attrName, newValue);
}
}
break;
case STRING_ARR: {
String[] oldValue = (String[]) value;
String[] newValue = new String[oldValue.length];
for (int i = 0; i < oldValue.length; i++) {
String replace = valueMap.get(oldValue[i]);
newValue[i] = replace != null ? replace : oldValue[i];
}
memberValues.put(attrName, newValue);
}
break;
}
return value;
}
public enum AttrTypeEnum {
STRING,
STRING_ARR
}
public interface DealProcess {
void deal() throws Exception;
}
}
package com.maintain.common.utils.poi;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义合并单元格处理器
* 每次合并需要sheet页名称、指定开始行号、开始列号、结束行号、结束列号
* 支持批量合并单元格
*
* @author weibaoting
*/
public class CustomMergeCellHandler implements SheetWriteHandler {
/**
* 合并单元格信息
*/
private List<MergeCellModel> mergeCellList;
/**
* sheet页名称列表
*/
private List<String> sheetNameList;
public CustomMergeCellHandler(List<MergeCellModel> mergeCellList) {
if (CollUtil.isEmpty(mergeCellList)) {
return;
}
this.mergeCellList = mergeCellList.stream().filter(x ->
StrUtil.isNotBlank(x.getSheetName()) && x.getStartRowIndex() >= 0 && x.getEndRowIndex() >= 0
&& x.getStartColumnIndex() >= 0 && x.getEndColumnIndex() >= 0).collect(Collectors.toList());
List<String> sheetNameList = this.mergeCellList.stream().map(x -> x.getSheetName()).distinct().collect(Collectors.toList());
if (CollUtil.isEmpty(sheetNameList)) {
return;
}
this.sheetNameList = sheetNameList;
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
/**
* sheet页创建之后调用
*
* @param writeWorkbookHolder
* @param writeSheetHolder
*/
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
Sheet sheet = writeSheetHolder.getSheet();
//不需要合并单元格信息,或者当前sheet页不需要合并单元格信息
if (CollUtil.isEmpty(mergeCellList) || sheetNameList.contains(sheet.getSheetName()) == false) {
return;
}
List<MergeCellModel> sheetMergeCellList = mergeCellList.stream().filter(x ->
StrUtil.equals(x.getSheetName(), sheet.getSheetName())).collect(Collectors.toList());
for (MergeCellModel mergeCellModel : sheetMergeCellList) {
//开始行号
int startRowIndex = mergeCellModel.getStartRowIndex();
//结束行号
int endRowIndex = mergeCellModel.getEndRowIndex();
//开始列号
int startColumnIndex = mergeCellModel.getStartColumnIndex();
//结束列号
int endColumnIndex = mergeCellModel.getEndColumnIndex();
//行号和列号非法(<0)
if (startColumnIndex < 0 || endColumnIndex < 0 || startRowIndex < 0 || endRowIndex < 0) {
continue;
}
//合并单元格区域只有一个单元格时,不合并
if (endRowIndex == startRowIndex && endColumnIndex == startColumnIndex) {
continue;
}
//开始行号大于结束行号,或者开始列号大于结束列号
if (startColumnIndex > endColumnIndex || startRowIndex > endRowIndex) {
continue;
}
//添加合并单元格区域
CellRangeAddress cellRangeAddress = new CellRangeAddress(startRowIndex, endRowIndex, startColumnIndex, endColumnIndex);
sheet.addMergedRegionUnsafe(cellRangeAddress);
}
//删除合并单元格信息
mergeCellList.removeAll(sheetMergeCellList);
sheetNameList = mergeCellList.stream().map(x -> x.getSheetName()).distinct().collect(Collectors.toList());
}
}
...@@ -5,10 +5,15 @@ import cn.hutool.core.io.resource.ClassPathResource; ...@@ -5,10 +5,15 @@ import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.maintain.common.convert.ExcelBigNumberConvert; import com.maintain.common.convert.ExcelBigNumberConvert;
import com.maintain.common.excel.*; import com.maintain.common.excel.*;
...@@ -16,6 +21,9 @@ import com.maintain.common.utils.StringUtils; ...@@ -16,6 +21,9 @@ import com.maintain.common.utils.StringUtils;
import com.maintain.common.utils.file.FileUtils; import com.maintain.common.utils.file.FileUtils;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.springframework.http.HttpHeaders;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -23,6 +31,9 @@ import java.io.IOException; ...@@ -23,6 +31,9 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -32,6 +43,7 @@ import java.util.Map; ...@@ -32,6 +43,7 @@ import java.util.Map;
* *
* @author Lion Li * @author Lion Li
*/ */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExcelUtil { public class ExcelUtil {
...@@ -377,4 +389,54 @@ public class ExcelUtil { ...@@ -377,4 +389,54 @@ public class ExcelUtil {
return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
} }
/**
* 载Excel格式的数据-带自定义标题
*
* @param response
* @param fileName
* @param sheetPOList
* @param <T>
*/
public static <T> void exportSheetSetTitle(HttpServletResponse response, String fileName, List<SheetPO> sheetPOList) {
//导出
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
try {
// 这里URLEncoder.encode可以防止中文乱码
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
//新建ExcelWriter
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
for (SheetPO sheetPO : sheetPOList) {
AnnotationUtils.changeAnnotationValueToDealProcess(
sheetPO.getClazz(), ExcelProperty.class, "value", AnnotationUtils.AttrTypeEnum.STRING_ARR, sheetPO.getTitleMap(), new AnnotationUtils.DealProcess() {
@Override
public void deal() {
ExcelWriterSheetBuilder sheetBuilder = EasyExcel.writerSheet(sheetPO.getSheetNo(), sheetPO.getSheetName())
.head(sheetPO.getClazz())
.registerWriteHandler(new CustomMergeCellHandler(sheetPO.getMergeCellList()));
if (Boolean.TRUE.equals(sheetPO.getWhiteFirstHeadRow())) {
sheetBuilder.registerWriteHandler(new HeadTitleRowWhiteStyleHandler());
}
if (sheetPO.getCenterMergedAnchorExcelRowIndex() != null) {
sheetBuilder.registerWriteHandler(
new MergedAnchorCellCenterStyleHandler(sheetPO.getCenterMergedAnchorExcelRowIndex(), 0));
}
WriteSheet mainSheet = sheetBuilder.build();
excelWriter.write(sheetPO.getData(), mainSheet);
}
}
);
}
excelWriter.finish();
log.info("数据导出完成");
} catch (Exception e) {
// 重置response
log.error("文件下载失败" + e.getMessage());
throw new RuntimeException("下载文件失败", e);
}
}
} }
package com.maintain.common.utils.poi;
import com.alibaba.excel.constant.OrderConstant;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
/**
* 多行表头时,仅将第一行(大标题行,relativeRowIndex=0)设为白底,其余表头行保持实体类上的 {@code @HeadStyle}。
*/
public class HeadTitleRowWhiteStyleHandler implements CellWriteHandler {
private CellStyle whiteTitleRowStyle;
/**
* 在注解 {@code @HeadStyle} 等样式写入之后再执行(EasyExcel:order 越小越早)。
*/
@Override
public int order() {
return OrderConstant.FILL_STYLE + 10000;
}
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
if (!Boolean.TRUE.equals(context.getHead())) {
return;
}
Integer relativeRowIndex = context.getRelativeRowIndex();
if (relativeRowIndex == null || relativeRowIndex != 0) {
return;
}
Cell cell = context.getCell();
if (cell == null) {
return;
}
Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
if (whiteTitleRowStyle == null) {
whiteTitleRowStyle = workbook.createCellStyle();
whiteTitleRowStyle.cloneStyleFrom(cell.getCellStyle());
whiteTitleRowStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
whiteTitleRowStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
}
cell.setCellStyle(whiteTitleRowStyle);
}
}
package com.maintain.common.utils.poi;
import lombok.Getter;
/**
* @Author weibaoting
* @Date 2023/2/2 0002 15:53
* @Description
*/
@Getter
public class MergeCellModel {
/**
* sheet名称
*/
private String sheetName;
/**
* 开始行号
*/
private int startRowIndex;
/**
* 开始列号
*/
private int startColumnIndex;
/**
* 结束行号
*/
private int endRowIndex;
/**
* 结束列号
*/
private int endColumnIndex;
private void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
private void setStartRowIndex(int startRowIndex) {
this.startRowIndex = startRowIndex;
}
private void setStartColumnIndex(int startColumnIndex) {
this.startColumnIndex = startColumnIndex;
}
private void setEndRowIndex(int endRowIndex) {
this.endRowIndex = endRowIndex;
}
private void setEndColumnIndex(int endColumnIndex) {
this.endColumnIndex = endColumnIndex;
}
public MergeCellModel() {
}
/**
* 生成合并列单元格信息
*
* @param sheetName sheet页名称
* @param rowIndex 行号
* @param startColumnIndex 开始列号
* @param endColumnIndex 结束列号
* @return
*/
public static MergeCellModel createMergeColumnCellModel(String sheetName, int rowIndex, int startColumnIndex
, int endColumnIndex) {
return createMergeCellModel(sheetName, rowIndex, rowIndex, startColumnIndex, endColumnIndex);
}
/**
* 生成合并单元格信息
*
* @param sheetName sheet页名称
* @param startRowIndex 开始行号
* @param endRowIndex 结束行号
* @param columnIndex 列号
* @return
*/
public static MergeCellModel createMergeRowCellModel(String sheetName, int startRowIndex, int endRowIndex, int columnIndex) {
return createMergeCellModel(sheetName, startRowIndex, endRowIndex, columnIndex, columnIndex);
}
/**
* 生成合并单元格信息
*
* @param sheetName sheet页名称
* @param startRowIndex 开始行号
* @param endRowIndex 结束行号
* @param startColumnIndex 开始列号
* @param endColumnIndex 结束列号
* @return
*/
public static MergeCellModel createMergeCellModel(String sheetName, int startRowIndex, int endRowIndex, int startColumnIndex
, int endColumnIndex) {
MergeCellModel mergeCellModel = new MergeCellModel();
//sheet页名称
mergeCellModel.setSheetName(sheetName);
//开始行号
mergeCellModel.setStartRowIndex(startRowIndex);
//结束行号
mergeCellModel.setEndRowIndex(endRowIndex);
//开始列号
mergeCellModel.setStartColumnIndex(startColumnIndex);
//结束列号
mergeCellModel.setEndColumnIndex(endColumnIndex);
return mergeCellModel;
}
}
package com.maintain.common.utils.poi;
import com.alibaba.excel.constant.OrderConstant;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
/**
* 将指定数据行、指定列(一般为合并区域左上角)的单元格设为水平、垂直居中,用于合并后「合计」等文案居中显示。
*/
public class MergedAnchorCellCenterStyleHandler implements CellWriteHandler {
private final int excelRowIndex;
private final int columnIndex;
public MergedAnchorCellCenterStyleHandler(int excelRowIndex, int columnIndex) {
this.excelRowIndex = excelRowIndex;
this.columnIndex = columnIndex;
}
@Override
public int order() {
return OrderConstant.FILL_STYLE + 15000;
}
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
if (Boolean.TRUE.equals(context.getHead())) {
return;
}
Cell cell = context.getCell();
if (cell == null) {
return;
}
if (cell.getRowIndex() != excelRowIndex || cell.getColumnIndex() != columnIndex) {
return;
}
Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
CellStyle style = workbook.createCellStyle();
style.cloneStyleFrom(cell.getCellStyle());
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
cell.setCellStyle(style);
}
}
package com.maintain.common.utils.poi;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author weibaoting
* @Date 2023/2/2 0002 17:00
* @Description
*/
@Data
public class SheetPO<T> {
/**
* sheetNo
*/
private Integer sheetNo;
/**
* sheet名称
*/
private String sheetName;
/**
* 标题替换
*/
private Map<String, String> titleMap = new HashMap<>();
/**
* 数据
*/
private List<T> data;
/**
* 表头
*/
private Class<T> clazz;
/**
* 需要合并的数据
*/
private List<MergeCellModel> mergeCellList;
/**
* 多行表头时是否将第一行(大标题行)设为白底;第二行仍用实体类上的表头样式。默认 false。
*/
private Boolean whiteFirstHeadRow;
/**
* 若设置:对该 Excel 行号(0-based)、第 0 列锚点单元格水平垂直居中(用于合并单元格内文字居中,如合计行)。
*/
private Integer centerMergedAnchorExcelRowIndex;
}
...@@ -525,7 +525,7 @@ export default { ...@@ -525,7 +525,7 @@ export default {
handleUpdate(row) { handleUpdate(row) {
getCar(row.id).then(res =>{ getCar(row.id).then(res =>{
this.form = res.data this.form = res.data
this.form.clientType = row.clientType this.form.clientType = row.clientType+''
this.open = true; this.open = true;
this.title = "修改车辆信息"; this.title = "修改车辆信息";
this.getCode() this.getCode()
......
...@@ -43,6 +43,15 @@ ...@@ -43,6 +43,15 @@
v-hasPermi="['business:settlementMaterial:add']" v-hasPermi="['business:settlementMaterial:add']"
>结算</el-button> >结算</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
...@@ -447,6 +456,7 @@ export default { ...@@ -447,6 +456,7 @@ export default {
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
// 如果没有选中任何项,直接禁用按钮 // 如果没有选中任何项,直接禁用按钮
if (selection.length === 0) { if (selection.length === 0) {
this.multiple = true; // 禁用按钮 this.multiple = true; // 禁用按钮
...@@ -593,8 +603,9 @@ export default { ...@@ -593,8 +603,9 @@ export default {
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
this.download('business/materialPicking/export', { this.download('business/materialPicking/export', {
...this.queryParams ...this.queryParams,
}, `materialPicking_${new Date().getTime()}.xlsx`) ids: this.ids
}, `供应商铺货结算.xlsx`)
} }
} }
}; };
......
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