一、引入依赖
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>2.12.0</version>
</dependency>
二、准备解析的数据封装
package com.dst.modules.business.after.sale.parts.sparepartsprocurepo.service;
import com.dst.common.util.ConvertCNMoneyUtils;
import com.dstcar.common.utils.date.DateUtil;
import com.dstcar.common.utils.spring.BeanUtil;
import com.dstcar.entitys.sparepartsprocurepo.*;
import lombok.extern.slf4j.Slf4j;
import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@Slf4j
@Component
public class SparePartsProcurePoQuoteTemplateRender {
private Resource spTemplate;
@PostConstruct
protected void init() {
ResourceLoader resourceLoader = new DefaultResourceLoader();
spTemplate = resourceLoader.getResource("classpath:/templates/excelTemp/SparePartsProcurePoQuoteTemplate.xlsx");
}
/**
* 渲染
* @param os 输出流
*/
public void render(SparePartsProcurePoDTO procurePoDTO, OutputStream os) {
try (InputStream is = spTemplate.getInputStream()) {
Context context = new Context();
context.putVar("data", buildData(procurePoDTO));
JxlsHelper.getInstance().processTemplate(is, os, context);
} catch (Exception e) {
log.error("采购订单模版渲染异常", e);
}
}
private SpareParsProcurePoQuoteTemplateData buildData(SparePartsProcurePoDTO procurePoDTO) {
final SpareParsProcurePoQuoteTemplateData templateData = new SpareParsProcurePoQuoteTemplateData();
SparePartsProcurePo sparePartsProcurePo = procurePoDTO.getSparePartsProcurePo();
BeanUtil.copyProperties(sparePartsProcurePo,templateData);
List<SparePartsProcurePoDetail> procurePoDetailList = procurePoDTO.getProcurePoDetailList();
AtomicReference<Integer> i = new AtomicReference<>(1);
final List<SpareParsProcurePoQuoteSkuTemplateData> skuTemplateData = procurePoDetailList.stream().map(pro -> {
final SpareParsProcurePoQuoteSkuTemplateData quoteSkuTemplateData = new SpareParsProcurePoQuoteSkuTemplateData();
quoteSkuTemplateData.setSequence(i.getAndSet(i.get() + 1));
BeanUtil.copyProperties(pro, quoteSkuTemplateData);
return quoteSkuTemplateData;
}).sorted(Comparator.comparing(SpareParsProcurePoQuoteSkuTemplateData::getSequence)).collect(Collectors.toList());
//大小写金额转换
templateData.setTotalAmountStr(ConvertCNMoneyUtils.toChinese(String.valueOf(templateData.getTotalAmount())));
templateData.setTotalPurchaseQuantity(skuTemplateData.stream().map(SpareParsProcurePoQuoteSkuTemplateData::getPurchaseQuantity)
.reduce(BigDecimal.ZERO, BigDecimal::add));
templateData.setOrderTime(DateUtil.convert2String(sparePartsProcurePo.getOrderTime(), DateUtil.DATEFORMAT));
templateData.setContractCode(procurePoDetailList.get(0).getContractCode());
templateData.setDetails(skuTemplateData);
return templateData;
}
}
三、对应导出excel数据的实体类
1.订单主档
package com.dstcar.entitys.sparepartsprocurepo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class SpareParsProcurePoQuoteTemplateData {
/** 采购订单号 规则:CGDD+日期+流水号,按日期累加 **/
private String orderCode;
/** 订单日期 **/
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private String orderTime;
/** 甲方名称 **/
private String partyAName;
/** 乙方名称 **/
private String partyBName;
/** 需方授权代表 **/
private String demandAgent;
/** 供方授权代表 **/
private String supplierAgent;
/** 需方地址 **/
private String demandAddress;
/** 供方地址 **/
private String supplierAddress;
/** 需方联系方式 **/
private String demandContactsStyle;
/** 供方联系方式 **/
private String supplierContactsStyle;
/** 结算方式:1月结30天|2月结60天|3月结90天|4先款后货(字典:spare_parts_payment_method) **/
private String paymentMethodName;
/** 发票类型:1增值税发票2普通发票(字典:spare_parts_po_invoice_type) **/
private String invoiceTypeName;
/** 订单总额(产品明细含税总额合计【含税总额(含税单价unitPriceIncludeTax * 采购数量purchaseQuantity)】) **/
private BigDecimal totalAmount;
/**
* 订单总额大写文字
*/
private String totalAmountStr;
/**
* 总的采购数量
*/
private BigDecimal totalPurchaseQuantity;
/** 备注 **/
private String remark;
/** 关联合同号 **/
private String contractCode;
/** po订单明细 */
private List<SpareParsProcurePoQuoteSkuTemplateData> details;
}
2.订单明细实体
package com.dstcar.entitys.sparepartsprocurepo;
import com.dstcar.common.translation.Translation;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class SpareParsProcurePoQuoteSkuTemplateData {
/**
* 序号
*/
private Integer sequence;
/** 零配件编码,逗号分割 **/
@Translation(convertName = "partsMaterialNameBatchConvert", convertTo = {"materialCodes-materialName"})
private String materialCodes;
/**
* 物料名称
*/
private String materialName;
/** 零配件规格 */
private String specs;
/** 计量单位 */
private String productUnitName;
/** 采购数量 **/
private BigDecimal purchaseQuantity;
/** 含税单价 **/
private BigDecimal unitPriceIncludeTax;
/** 税率 **/
private BigDecimal taxRate;
/** 含税总额(含税单价*采购数量) **/
private BigDecimal includeTotalAmount;
/** 收货人 **/
private String receivedPerson;
/** 收货人联系电话 **/
private String receivedPhone;
/** 收货人地址 **/
private String receivedAddress;
/** 备注 **/
private String remark;
}
3.转化为导出url路径
/**
* 下载po订单模板接口
* @param id
* @return
*/
public Results downloadOrder(String id,SSOUser ssoUser) {
SparePartsProcurePoDTO procurePoDTO = this.getProcurePoDetailById(id);
Integer priceSource = procurePoDTO.getProcurePoDetailList().get(0).getPriceSource();
// 渲染
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (SparePartsFirmConstant.PRICE_SOURCE_2.equals(priceSource) ||
SparePartsFirmConstant.PRICE_SOURCE_1.equals(priceSource) ||
SparePartsFirmConstant.PRICE_SOURCE_4.equals(priceSource)) {
sparePartsProcurePoCatalogTemplateRender.render(procurePoDTO, outputStream);
} else if (SparePartsFirmConstant.PRICE_SOURCE_3.equals(priceSource) ||
SparePartsFirmConstant.PRICE_SOURCE_5.equals(priceSource) ){
sparePartsProcurePoQuoteTemplateRender.render(procurePoDTO, outputStream);
} else {
log.error("价格来源类型不存在:{}",priceSource);
sparePartsProcurePoQuoteTemplateRender.render(procurePoDTO, outputStream);
}
// 上传
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
String fileName = getFileName();
final String aliObjName = genAliObjName(fileName);
final String fileUrl = aliOSSStoreClient.uploadFile(inputStream, aliObjName, fileName);
log.info("渲染采购订单模板并上传路径:{}, 文件名:{}", aliObjName, fileName);
uploadExcel(AliOSSHelper.getAccessUrl(fileUrl),fileName,ssoUser);
return succeed();
}
/**
* 生成订单附件文件
* @return
*/
private String getFileName() {
return "易维&供应商名称-采购订单" + ".xlsx";
}
/**
* 生成文件上传路径
* @return
*/
private String genAliObjName(String FileName) {
return "/operate/spare/parts/procure/po/template/"+dstIdUtils.getPrimaryKey()+"/" + FileName;
}
/**
*
* @param url
* @param fileName
*/
public void uploadExcel(String url, String fileName, SSOUser ssoUser){
Date date = new Date();
ExportRecord exportRecord = new ExportRecord();
exportRecord.setFileUrl(url);
exportRecord.setFileName(fileName);
exportRecord.setModule(10);
exportRecord.setModuleName("零配件采购订单");
//处理完成
exportRecord.setStatus(2);
exportRecord.setSource(0);
exportRecord.setFileClassification(0);
exportRecord.setRequestMethod("GET");
exportRecord.setServerName("dst-operate-basic-api");
exportRecord.setFileType(FileTypeConstant.EXCEL_2007);
exportRecord.setCreateUserId(ssoUser.getId());
exportRecord.setCreateUserName(ssoUser.getRealname());
exportRecord.setCreateTime(date);
exportRecord.setUpdateUserId(ssoUser.getId());
exportRecord.setUpdateUserName(ssoUser.getRealname());
exportRecord.setUpdateTime(date);
exportRecordService.save(exportRecord);
}
4.导出订单模板填充
采 购 订 单 签订时间:${data.orderTime} 订单编号:${data.orderCode} 需方(甲方):${data.partyAName} 供方(乙方):${data.partyBName} 授权代表:${data.demandAgent} 授权代表:${data.supplierAgent} 地址:${data.demandAddress} 地址:${data.supplierAddress} 联系方式:${data.demandContactsStyle} 联系方式:${data.supplierContactsStyle} 经双方友好协议确认,根据下列条款订立本合同: 一、内容:(甲方向乙方订购以下货物): 序号 物料名称 物料编码 物料规格及描述 单位 数量 单价(元) 含税 税率(%) 金额(元) 含税 收货人 收货人联系方式 收货地址 备注(交期) ${detail.sequence} ${detail.materialName} ${detail.materialCodes} ${detail.specs} ${detail.productUnitName} ${detail.purchaseQuantity} ${detail.unitPriceIncludeTax} ${detail.taxRate} ${detail.includeTotalAmount} ${detail.receivedPerson} ${detail.receivedPhone} ${detail.receivedAddress} ${detail.remark} 货款合计(大写):(含税费及运费) ${data.totalAmountStr} ${data.totalPurchaseQuantity} 小写合计 ${data.totalAmount} 备注 交付时间由甲乙双方书面确认。 二、结算方式:${data.paymentMethodName} 三、订单有效期: 四、质保期: 五、包装标准和要求:物品的包装除可靠保护内存物品外,必须整洁完好,并符合国内各地常规仓储条件的包装要求;外标识清晰正确,并与送货单所示内容一致,乙方应按照包装要求进行包装,并承担运费。甲方应自收到上述物料之日起【2】个工作日内完成上述物料的清点及验收。甲方对乙方上述物料的验收仅视为对其数量、规格、外包装等确认,不代表对物料质量的确认。 六、质量要求与交付期限要求:乙方保证货品质量和品质符合甲方要求,按甲方技术要求、图纸成封样为准,产品封样后未经甲方书面许可,乙方不可擅自更改任何材料和生产工艺、否则导致所供产品质量下降,最终使产品质量下降而需蒙受重大损失(包括:人员全检损失、特采损失,返工更换等待损失、甲方客户退货损失等),乙方要承担造成甲方损失的全部责任,质量不满足要求的,甲方有权要求乙方免费退换物料,乙方需按照本订单约定的交付时间完成物料交付,如因乙方未正常交货影响甲方整个项目进程的,乙方需承担本订单总金额50%的违约责任,违约金不足以弥补甲方损失的,乙方还应继续承担损害赔偿责任。 七、其他约定: 1)甲乙任何一方因不可抗力原因不能履行合同,应及时向对方通报并提供证明,以减轻可能给对方造成的损失。 2)产品交付前产品所有权由乙方保留,产品灭失及损坏风险由乙方承担。产品交付后产品所有权由甲方保留,产品灭失和损坏风险由甲方承担。但所有权和风险转移并不免除乙方对由于其自身原因其或产品固有缺陷导致的产品故障、损坏或灭失所应承担的责任。 3)乙方同意若甲方购买产品后质保期内因产量质量本身问题所产生的需要进行售后或者维修等事项,乙方应积极响应,并应免费为甲方退还或进行维修售后处理。 4)甲乙双方因履行本订单如发生纠纷,当事人双方应当及时协商解决,如协商不成,任何一方均有权向需方所在地人民有管辖权的人民法院提起诉讼。 5)本订单自甲乙双方签字盖章之日起生效,本订单执行期内,甲乙双方均不得随意变更或解除本订单,如有未尽事宜,须经双方共同协商,作出补充规定,补充规定与本订单具有同等法律效力。 6)本订单正本一式两份,甲乙双方各执一份,经双方盖章生效,传真件与原件同等有效,手写或更改无效。 甲 方 乙 方 甲 方(盖章): ${data.partyAName} 乙 方(盖章): ${data.partyBName} 授权代表(签字): 授权代表(签字):
四、效果预览