Commit 2430f82b authored by wei's avatar wei 🎱

启动流程,生成附件

parent 7648f6b5
...@@ -20,6 +20,11 @@ public class Constants { ...@@ -20,6 +20,11 @@ public class Constants {
*/ */
public static final String PDF_FILE = "DOC_PDF_FILE"; public static final String PDF_FILE = "DOC_PDF_FILE";
/**
* app 内部名称
*/
public static final String APPLICATION_INNER_NAME="dcs-plan";
/** /**
* minio桶名称 * minio桶名称
*/ */
......
package com.yonde.dcs.plan.common.constants;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
* @author xfchai
* @ClassName SignConstants.java
* @Description 常量属性
* @createTime 2021/09/02 14:42:00
*/
public final class SignConstants {
//签名取值
public static final String SIGN_KEY_PREPARED = "编制";
public static final String SIGN_KEY_TSSH = "同室审核";
public static final String SIGN_KEY_FXTZSSH = "分系统总师审核";
public static final String SIGN_KEY_GY = "工艺";
public static final String SIGN_KEY_QF = "签发";
public static final String SIGN_KEY_ZTSSH = "总体室审核";
public static final String SIGN_KEY_APPROVED = "批准";
public static final String SIGN_KEY_STANDARD = "标准化";
public static final String SIGN_KEY_ZTS = "总体室";
public static final String SIGN_KEY_ZTSQS = "总体室签审";
public static final String SIGN_KEY_TZSH = "提资审核";
public static final String SIGN_KEY_SH = "审核";
public static final String SIGN_KEY_CLJD = "编制不符合项处理单处理决定任务";
public static final String SIGN_KEY_SWYZ = "编制不符合项处理单实物验证项任务";
public static final String SIGN_KEY_SQSH = "申请审核";
public static final String SIGN_KEY_CHECKER = "校核";
public static final String SIGN_KEY_SD = "审定";
public static final String SIGN_KEY_JKHQ = "接口会签";
public static final String SIGN_KEY_CGB = "采购部会签";
public static final String SIGN_KEY_SCB = "市场部会签";
public static final String SIGN_KEY_CPYF = "产品研发部复核";
public static final String SIGN_KEY_PBB = "品保部";
public static final String SIGN_ZBB = "质保部签审";
public static final String SIGN_SJX = "设计项签审";
public static final String SIGN_ZTS = "总体室签审";
public static final String SIGN_GCB = "工程部签审";
public static final String SIGN_SD = "审定";
public static final String SIGN_KEY_ZTSJKSC = "总体室接口审查";
public static final String SIGN_KEY_ZXSC = "专项审查";
public static final String SIGN_KEY_JKHQSC = "接口会签审查";
//NCR审查单模板变量(质保部签审)
public static final String ZBBprocessName = "ZBBprocessName";
public static final String ZBBremark = "ZBBremark";
public static final String ZBBfzr_photo = "ZBBfzr_photo";
public static final String ZBBfzr_date = "ZBBfzr_date";
//NCR审查单模板变量(设计项签审)
public static final String SJXprocessName = "SJXprocessName";
public static final String SJXremark = "SJXremark";
public static final String SJXfzr_photo = "SJXfzr_photo";
public static final String SJXfzr_date = "SJXfzr_date";
//NCR审查单模板变量(总体室签审)
public static final String ZTSprocessName = "ZTSprocessName";
public static final String ZTSremark = "ZTSremark";
public static final String ZTSfzr_photo = "ZTSfzr_photo";
public static final String ZTSfzr_date = "ZTSfzr_date";
//NCR审查单模板变量(工程部签审)
public static final String GCBprocessName = "GCBprocessName";
public static final String GCBremark = "GCBremark";
public static final String GCBfzr_photo = "GCBfzr_photo";
public static final String GCBfzr_date = "GCBfzr_date";
/**
* 定义流程判断节点常量
*/
public final static List WfResultList = Arrays.asList("通过", "提交签审", "提交审阅", "提交", "提交提资审阅", "不需要总体室会签", "外协采购单位(过工程部)", "设计协同单位及其他");
/**
* 定义总体室签审节点名称
*/
public final static List ZTSSignTaskList = Arrays.asList(SIGN_KEY_ZTS, SIGN_ZTS, SIGN_KEY_ZTSJKSC);
/**
* 定义流程路由常量
*/
public final static List WfRoutingList = Arrays.asList("通过", "提交");
/**
* 流程 节点名称
*/
public static final HashMap<String, String> SignNodeMap = new HashMap() {{
put("编制", "BKBZ");
put("校对", "BKJD");
put("审定", "BKSD");
put("标检", "BKBJ");
put("数据审核", "BKSJ");
put("管理审核", "BKGL");
put("资料员审核", "BKZL");
put("标审", "BKBS");
put("会签", "BKHQ");
put("工艺室分发辅制会签", "BKFZ");
put("工艺主制会签", "BKZZ");
put("审核", "BKSH");
put("批准", "BKPZ");
put("待审阅", "BKDS");
put("设总签审", "BKSZ");
put("总体室签审", "BKZT");
put("总体室接口工程师签审设总综合检查人", "BKJK");
put("综合检查", "BKZH");
}};
/**
* 流程 节点名称
*/
public static final HashMap<String, String> InterfaceSignNodeMap = new HashMap() {
{
put("审核", "TKSK");
put("提资方设总签审", "TKSZ");
put("提资中", "TKTJ");
put("总体室接口工程师签审", "TKZT");
}
};
}
\ No newline at end of file
...@@ -74,6 +74,16 @@ ...@@ -74,6 +74,16 @@
<groupId>com.yonde.dex</groupId> <groupId>com.yonde.dex</groupId>
<artifactId>dex-secretcode-plugin-core</artifactId> <artifactId>dex-secretcode-plugin-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
package com.yonde.dcs.plan.core.controller; package com.yonde.dcs.plan.core.controller;
import org.springframework.stereotype.Controller;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import java.util.List;
import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO; import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO;
import org.springframework.beans.factory.annotation.Qualifier; import com.yonde.dcs.plan.core.controller.shadow.ExtExpenditureContractControllerShadow;
import org.springframework.beans.factory.annotation.Autowired; import com.yonde.dcs.plan.core.service.AutoTaskService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
import com.yonde.dcs.plan.core.service.ExtExpenditureContractService; import com.yonde.dcs.plan.core.service.ExtExpenditureContractService;
import com.yonde.dex.basedata.entity.api.ApiResult; import com.yonde.dex.basedata.entity.api.ApiResult;
import com.yonde.dcs.plan.core.controller.shadow.ExtExpenditureContractControllerShadow; import io.swagger.annotations.Api;
import javax.annotation.Resource; import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/** /**
* @description: ExtExpenditureContract-Controller * @description: ExtExpenditureContract-Controller
* @author: dexadmin * @author: dexadmin
* @version: V * @version: V
* @date: 2024-9-24 16:48:59 * @date: 2024-9-24 16:48:59
**/ **/
@Api(tags = "ExtExpenditureContract管理服务") @Api(tags = "ExtExpenditureContract管理服务")
@RequestMapping("/ExtExpenditureContract") @RequestMapping("/ExtExpenditureContract")
@ResponseBody() @ResponseBody()
@Controller(ExtExpenditureContractController.BEAN_NAME) @Controller(ExtExpenditureContractController.BEAN_NAME)
public class ExtExpenditureContractController<V extends ExtExpenditureContractVO, S extends ExtExpenditureContractService<V>> extends ExtExpenditureContractControllerShadow<V, S> { public class ExtExpenditureContractController<V extends ExtExpenditureContractVO, S extends ExtExpenditureContractService<V>> extends ExtExpenditureContractControllerShadow<V, S> {
@Autowired
private ExtExpenditureContractService extExpenditureContractService;
@Autowired
private AutoTaskService autoTaskService;
@ApiOperation("发起审批流程")
@PostMapping({"startWorkflow"})
public ApiResult startWorkflow(@RequestParam("id") Long id) {
return ApiResult.ok(extExpenditureContractService.startWorkflow(id), "操作完成");
}
@ApiOperation(value = "生成word签字", notes = "生成word签字", httpMethod = "POST")
@PostMapping(value = "/generateContractWordSign")
public void generateContractWordSign(@RequestParam("documentId") Long contractId,
@RequestParam("fileName") String fileName) {
autoTaskService.generateContractWordSign(contractId, fileName);
}
} }
......
package com.yonde.dcs.plan.core.factory;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.yonde.dcs.plan.common.constants.Constants;
import com.yonde.dcs.plan.common.constants.SignConstants;
import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO;
import com.yonde.dcs.plan.core.service.ExtExpenditureContractService;
import com.yonde.dcs.plan.core.word.ImportWordService;
import com.yonde.dex.wfc.common.vo.DxWfProcessInfoVO;
import com.yonde.dex.wfc.common.vo.DxWfProcessTaskVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @author weihongda
* @ClassName ContractUtils.java
* @Description 合同
* @createTime 2022/02/22 14:35:00
*/
@Component
public class ContractUtils {
@Autowired
private ExtExpenditureContractService extExpenditureContractService;
@Autowired
private ImportWordService importWordService;
/**
* 填充评审会议资料数据
*
* @param
* @return
*/
public JSONObject settingDocData(ExtExpenditureContractVO expenditureContractVO, DxWfProcessInfoVO wfProcessInfoVO) {
String path = Constants.MTEMPLATE_ABSOLUTE_PATH;
String file = expenditureContractVO.getSubTypeName();
String outFilePath = Constants.MERGER_FILE_ABSOLUTE_PATH + expenditureContractVO.getSubTypeName()
+ "\\" + expenditureContractVO.getNumber() + "\\";
//生成特定的文档目录,保存生成的word文件
FileUtil.mkdir(outFilePath);
//获取动态属性
/*Map<String, Object> dynamicAttrs = expenditureContractVO.getDynamicAttrs();
String content = Objects.isNull(dynamicAttrs.get("content")) ? "" : (String) dynamicAttrs.get("content");
String designPhase = Objects.isNull(dynamicAttrs.get("designPhase")) ? "" : (String) dynamicAttrs.get("designPhase");*/
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(expenditureContractVO);
//项目代号
/*String projectCode = ObjectUtils.isEmpty(v.getDxDocumentExpand().getProjectCode()) ? "" : v.getDxDocumentExpand().getProjectCode();
jsonObject.put("projectCode", extDocService.searchDictDataByDictCode(Constants.PROJECT_CODE, projectCode));
jsonObject.put("projectCode", projectCode);*/
//合同名称
//合同乙方
//合同编号
//合同金额
//合同密级
//合同乙方保密资质等级
//合同类型
//学校/院归口管理部门
//合同成果形式
//成果交付地点(样机存放地方)
//起止时间
//承办部门
//经办人
//
//页数
//jsonObject.put("pages",v.getDxDocumentExpand().getAttachPages());
//获取参与者
List<DxWfProcessTaskVO> activities = wfProcessInfoVO.getHistoryInfo();
if (!CollectionUtils.isEmpty(activities)) {
//写入签名数据
jsonObject.put("bz_photo", extExpenditureContractService.getSignImage(activities, SignConstants.SIGN_KEY_PREPARED));
jsonObject.put("bz_date", extExpenditureContractService.getEndDate(activities, SignConstants.SIGN_KEY_PREPARED));
jsonObject.put("sh_photo", extExpenditureContractService.getSignImage(activities, SignConstants.SIGN_KEY_SH));
jsonObject.put("sh_date", extExpenditureContractService.getEndDate(activities, SignConstants.SIGN_KEY_SH));
//总体室审核
jsonObject.put("zts_photo", extExpenditureContractService.getSignImage(activities, SignConstants.SIGN_KEY_ZTSSH));
jsonObject.put("zts_date", extExpenditureContractService.getEndDate(activities, SignConstants.SIGN_KEY_ZTSSH));
jsonObject.put("pz_photo", extExpenditureContractService.getSignImage(activities, SignConstants.SIGN_KEY_APPROVED));
jsonObject.put("pz_date", extExpenditureContractService.getEndDate(activities, SignConstants.SIGN_KEY_APPROVED));
}
//模板名称
importWordService.getWordAllTable(jsonObject, path + file + ".docx", outFilePath + "outFile.docx");
return jsonObject;
}
}
...@@ -2,9 +2,7 @@ package com.yonde.dcs.plan.core.service; ...@@ -2,9 +2,7 @@ package com.yonde.dcs.plan.core.service;
import com.yonde.dex.user.common.vo.DxOrganizationVO; import com.yonde.dex.user.common.vo.DxOrganizationVO;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @program: inet-pdm-service * @program: inet-pdm-service
...@@ -16,4 +14,11 @@ public interface AutoTaskService { ...@@ -16,4 +14,11 @@ public interface AutoTaskService {
List<DxOrganizationVO> searchOrgNameByUserId(Long userId, String code); List<DxOrganizationVO> searchOrgNameByUserId(Long userId, String code);
/**
* 生成word签字
*
* @param contractId
* @param fileName
*/
void generateContractWordSign(Long contractId, String fileName);
} }
package com.yonde.dcs.plan.core.service; package com.yonde.dcs.plan.core.service;
import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO; import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO;
import com.yonde.dcs.plan.core.factory.ContractUtils;
import com.yonde.dcs.plan.core.service.shadow.ExtExpenditureContractServiceShadow; import com.yonde.dcs.plan.core.service.shadow.ExtExpenditureContractServiceShadow;
import com.yonde.dex.wfc.common.vo.DxWfProcessInfoVO;
import com.yonde.dex.wfc.common.vo.DxWfProcessTaskVO;
import java.util.List;
/** /**
* @description: ExtExpenditureContract-service * @description: ExtExpenditureContract-service
* @author: dexadmin * @author: dexadmin
...@@ -10,4 +16,32 @@ import com.yonde.dcs.plan.core.service.shadow.ExtExpenditureContractServiceShado ...@@ -10,4 +16,32 @@ import com.yonde.dcs.plan.core.service.shadow.ExtExpenditureContractServiceShado
**/ **/
public interface ExtExpenditureContractService<V extends ExtExpenditureContractVO> extends ExtExpenditureContractServiceShadow<V> { public interface ExtExpenditureContractService<V extends ExtExpenditureContractVO> extends ExtExpenditureContractServiceShadow<V> {
ExtExpenditureContractVO startWorkflow(Long id);
void print(int contractType);
ExtExpenditureContractVO findExpenditureContractObjFileLinks(Long contractId);
void generateContractWordSign(ExtExpenditureContractVO expenditureContractVO, Class<ContractUtils> contractUtilsClass,
DxWfProcessInfoVO wfProcessInfoVO, String fileName);
/**
* 获取签名图片(4.1新)
*
* @param dxWfProcessTaskVO
* @param activityName
* @return
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
String getSignImage(List<DxWfProcessTaskVO> dxWfProcessTaskVO, String activityName);
/**
* 获取签名日期(4.1新)
*
* @param dxWfProcessTaskVO
* @param activityName
* @return
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
String getEndDate(List<DxWfProcessTaskVO> dxWfProcessTaskVO, String activityName);
} }
package com.yonde.dcs.plan.core.service.impl; package com.yonde.dcs.plan.core.service.impl;
import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO;
import com.yonde.dcs.plan.core.factory.ContractUtils;
import com.yonde.dcs.plan.core.service.AutoTaskService; import com.yonde.dcs.plan.core.service.AutoTaskService;
import com.yonde.dcs.plan.core.service.ExtExpenditureContractService;
import com.yonde.dcs.plan.core.service.ExtPlanService; import com.yonde.dcs.plan.core.service.ExtPlanService;
import com.yonde.dcs.plan.core.util.WorkFlowUtil;
import com.yonde.dex.user.common.vo.DxOrganizationVO; import com.yonde.dex.user.common.vo.DxOrganizationVO;
import com.yonde.dex.wfc.common.vo.DxWfProcessInfoVO;
import com.yonde.dex.wfc.common.vo.DxWfProcessVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -23,6 +29,12 @@ public class AutoTaskServiceImpl implements AutoTaskService { ...@@ -23,6 +29,12 @@ public class AutoTaskServiceImpl implements AutoTaskService {
@Autowired @Autowired
private ExtPlanService extPlanService; private ExtPlanService extPlanService;
@Autowired
private WorkFlowUtil workFlowUtil;
@Autowired
private ExtExpenditureContractService extExpenditureContractService;
/** /**
* 通过userId获取组织名 * 通过userId获取组织名
* *
...@@ -34,4 +46,20 @@ public class AutoTaskServiceImpl implements AutoTaskService { ...@@ -34,4 +46,20 @@ public class AutoTaskServiceImpl implements AutoTaskService {
return extPlanService.searchOrgNameByUserId(userId, code); return extPlanService.searchOrgNameByUserId(userId, code);
} }
@Override
public void generateContractWordSign(Long contractId, String fileName) {
//深度查询展开ObjLink
ExtExpenditureContractVO expenditureContractVO = extExpenditureContractService.findExpenditureContractObjFileLinks(contractId);
log.info("自动任务======生成word签名开始");
DxWfProcessVO wfProcessInstVO = workFlowUtil.getWfProcessInst(expenditureContractVO);
DxWfProcessInfoVO wfProcessInfoVO = workFlowUtil.getProcessInstDetail(wfProcessInstVO);
String subTypeName = expenditureContractVO.getSubTypeName();
log.info("自动任务======生成word签名进行中,文档SubTypeName:{}", subTypeName);
extExpenditureContractService.generateContractWordSign(expenditureContractVO, ContractUtils.class, wfProcessInfoVO, fileName);
//保存附件
extExpenditureContractService.saveRecursion(expenditureContractVO);
log.info("自动任务======生成word签名完成");
}
} }
package com.yonde.dcs.plan.core.service.impl; package com.yonde.dcs.plan.core.service.impl;
import org.springframework.stereotype.Service;
import io.swagger.annotations.ApiOperation; import cn.hutool.core.io.FileUtil;
import java.util.List; import cn.hutool.extra.spring.SpringUtil;
import com.yonde.dcs.plan.common.constants.Constants;
import com.yonde.dcs.plan.common.constants.SignConstants;
import com.yonde.dcs.plan.common.utils.FileUtils;
import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO; import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO;
import org.springframework.beans.factory.annotation.Qualifier; import com.yonde.dcs.plan.core.factory.ContractUtils;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import com.yonde.dcs.plan.core.service.ExtExpenditureContractService;
import com.yonde.dcs.plan.core.repository.ExtExpenditureContractRepository; import com.yonde.dcs.plan.core.repository.ExtExpenditureContractRepository;
import com.yonde.dcs.plan.core.service.ExtExpenditureContractService;
import com.yonde.dcs.plan.core.util.CommonUtils;
import com.yonde.dcs.plan.entity.po.ExtExpenditureContract; import com.yonde.dcs.plan.entity.po.ExtExpenditureContract;
import javax.annotation.Resource; import com.yonde.dex.basedata.data.search.SearchItem;
import com.yonde.dex.basedata.data.search.SearchItems;
import com.yonde.dex.basedata.data.search.SearchQueryCondition;
import com.yonde.dex.basedata.entity.data.DxPageImpl;
import com.yonde.dex.basedata.entity.data.OperatorType;
import com.yonde.dex.basedata.exception.DxBusinessException;
import com.yonde.dex.dao.service.util.DxPageUtils;
import com.yonde.dex.dfs.feign.FileManagerFeignService;
import com.yonde.dex.dfs.objfilelink.plugin.core.util.DxObjFileUtils;
import com.yonde.dex.dfs.vo.ObjFileLinkVO;
import com.yonde.dex.dfs.vo.RepoFileVO;
import com.yonde.dex.feign.info.DxApplicationFeignService;
import com.yonde.dex.user.common.vo.DxUserInfoVO;
import com.yonde.dex.user.feign.DxUserInfoFeign;
import com.yonde.dex.vo.info.DxApplicationVO;
import com.yonde.dex.wfc.common.enums.TaskStateEnum;
import com.yonde.dex.wfc.common.vo.DxWfProcessInfoVO;
import com.yonde.dex.wfc.common.vo.DxWfProcessTaskVO;
import com.yonde.dex.wfc.feign.api.WfcProcessFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/** /**
* @description: ExtExpenditureContract-ServiceImpl * @description: ExtExpenditureContract-ServiceImpl
* @author: dexadmin * @author: dexadmin
* @version: V * @version: V
* @date: 2024-9-24 16:48:59 * @date: 2024-9-24 16:48:59
**/ **/
@Slf4j @Slf4j
@Service(ExtExpenditureContractServiceImpl.BEAN_NAME) @Service(ExtExpenditureContractServiceImpl.BEAN_NAME)
public class ExtExpenditureContractServiceImpl<V extends ExtExpenditureContractVO> implements ExtExpenditureContractService<V>{ public class ExtExpenditureContractServiceImpl<V extends ExtExpenditureContractVO> implements ExtExpenditureContractService<V> {
public static final String BEAN_NAME = "extExpenditureContractServiceImpl"; public static final String BEAN_NAME = "extExpenditureContractServiceImpl";
...@@ -29,6 +67,217 @@ public class ExtExpenditureContractServiceImpl<V extends ExtExpenditureContractV ...@@ -29,6 +67,217 @@ public class ExtExpenditureContractServiceImpl<V extends ExtExpenditureContractV
@Autowired @Autowired
ExtExpenditureContractRepository<ExtExpenditureContract> extExpenditureContractRepository; ExtExpenditureContractRepository<ExtExpenditureContract> extExpenditureContractRepository;
@Autowired
private WfcProcessFeign wfcProcessFeign;
@Autowired
DxApplicationFeignService feignService;
@Autowired
private FileManagerFeignService fileManagerService;
@Autowired
private FileManagerFeignService fileManagerFeignService;
@Autowired
private DxUserInfoFeign userService;
@Autowired
private ContractUtils contractUtils;
@Override
public ExtExpenditureContractVO startWorkflow(Long id) {
ExtExpenditureContractVO extExpenditureContractVO = this.get(id);
if (extExpenditureContractVO == null) {
throw new DxBusinessException("500", "获取不到对象");
}
if (!extExpenditureContractVO.getState().equals("edit")) {
throw new DxBusinessException("500", "该对象不是编制状态");
}
wfcProcessFeign.startProcessByKey("ExtExpenditureContractWF", extExpenditureContractVO);
return this.changeStatus(extExpenditureContractVO.getId(), "submitReviewing", true);
}
public void generateContractWordSign(ExtExpenditureContractVO expenditureContractVO, Class classType,
DxWfProcessInfoVO wfProcessInfoVO, String fileName) {
try {
Class<?> clazz = Class.forName("com.yonde.dcs.plan.core.factory.ContractUtils");
Method settingDataMethod = clazz.getMethod("settingData", ExtExpenditureContractVO.class, DxWfProcessInfoVO.class);
settingDataMethod.invoke(SpringUtil.getBean(classType), expenditureContractVO, wfProcessInfoVO);
log.info("签名----生成word文件内容结束====");
//按照目录获取生成的pdf和word
String outFilePath = Constants.MERGER_FILE_ABSOLUTE_PATH + expenditureContractVO.getSubTypeName() + "\\" + expenditureContractVO.getNumber() + "\\";
//获取文件夹的所有文件--绝对路径
List<String> fileList = new ArrayList<>();
File[] files = FileUtil.ls(outFilePath);
Arrays.stream(files).forEach(item -> {
fileList.add(item.getAbsolutePath());
});
if (CollectionUtils.isEmpty(fileList)) {
log.error("签名----生成的word文件目录内容为空====");
} else {
String pdfFilePath = fileList.stream().filter(item -> item.endsWith(".pdf")).findFirst().get();
this.extractedAttachFile(expenditureContractVO, new FileInputStream(pdfFilePath), fileName, Constants.ATTACH_FILE);
log.info("签名----获取生成的word文件内容结束====");
}
//删除生成后的临时文件
FileUtils.deleteDirectory(Constants.MERGER_FILE_ABSOLUTE_PATH + expenditureContractVO.getSubTypeName() + "\\" + expenditureContractVO.getNumber());
} catch (Exception e) {
log.error("签名----通过不同的合同类型生成不同word错误:{}" + e.getMessage());
}
}
/**
* 上传附件(事件专用上传附件)
*
* @param expenditureContractVO
* @param inputStreamPdf
* @param fileName
* @throws IOException
*/
public void extractedAttachFile(ExtExpenditureContractVO expenditureContractVO, InputStream inputStreamPdf,
String fileName, String docFileType) throws IOException {
String originalFileName = StringUtils.isEmpty(fileName) ? expenditureContractVO.getName() : fileName;
String secretCode = CommonUtils.getSecretCode(expenditureContractVO.getSecretCode());
originalFileName = originalFileName + "(" + secretCode + ")";
//上传文件到文件服务器
MultipartFile multipartFile = null;
multipartFile = new MockMultipartFile("file", originalFileName + ".pdf", Constants.CONTENT_TYPE_PDF, inputStreamPdf);
// if (StringUtils.isEmpty(fileName)) {
// //如果等于空,默认文件名称为getName.pdf
// multipartFile = new MockMultipartFile("file", documentVo.getName() + ".pdf",
// Constants.CONTENT_TYPE_PDF, inputStreamPdf);
// } else {
// //如果不等于空,默认文件名称为name.pdf
// multipartFile = new MockMultipartFile("file", fileName + ".pdf",
// Constants.CONTENT_TYPE_PDF, inputStreamPdf);
// }
RepoFileVO field = fileManagerService.uploadFile(multipartFile, getBucketId());
if (field == null) {
log.error("文件上传失败!");
} else {
log.info("文件上传成功:" + field);
}
//根据docId查询文件对象
RepoFileVO fileVO = fileManagerFeignService.findFileInfoById(field.getId());
//上传到DOC_PDF_FILE为了浏览(Constants.PDF_FILE)
this.doProcessContract(expenditureContractVO, fileVO, docFileType);
}
/**
* 更新主内容或附件
*
* @param expenditureContractVO
* @param fileVO
* @param fileType
*/
private void doProcessContract(ExtExpenditureContractVO expenditureContractVO, RepoFileVO fileVO, String fileType) {
// DxObjFileUtils.removeFile(documentVo, fileType);
List<ObjFileLinkVO> objFileLinks = expenditureContractVO.getObjFileLinks();
//删除逻辑
if (!CollectionUtils.isEmpty(objFileLinks)) {
objFileLinks.stream().forEach(item -> {
if (item.getContentType().equals(fileType) && item.getTarget().getOriginalFileName().equals(fileVO.getOriginalFileName())) {
item.setOperator(OperatorType.REMOVE);
}
});
}
DxObjFileUtils.addFile(expenditureContractVO, fileVO, fileType);
}
public Long getBucketId() {
DxApplicationVO applicationVO = feignService.findApplicationByInnerName(Constants.APPLICATION_INNER_NAME);
if (!ObjectUtils.isEmpty(applicationVO)) {
return Long.valueOf(applicationVO.getBucketId());
}
return null;
}
@Override
public void print(int contractType) {
}
@Override
public ExtExpenditureContractVO findExpenditureContractObjFileLinks(Long id) {
SearchQueryCondition query = SearchQueryCondition.builder()
.openProp(SearchQueryCondition.builder().name("creator").build())
.openProp(SearchQueryCondition.builder().name("modifier").build())
.openProp(SearchQueryCondition.builder().name("objFileLinks").openProp(SearchQueryCondition.builder().name("target").build()).build())
.searchItems(SearchItems.builder().item(new SearchItem("id", SearchItem.Operator.EQ,
id, null)).item(new SearchItem("latest", SearchItem.Operator.EQ,
true, null)).operator(SearchItems.BooleanOperator.AND).build()).build();
//通过id查询文档
DxPageImpl<V> dexPage = this.findRecursion(query);
if (!org.apache.commons.collections.CollectionUtils.isEmpty(dexPage.getContent())) {
return DxPageUtils.getFirst(dexPage);
}
return null;
}
/**
* 获取图片名称 (4.1新)
*
* @param activities
* @param activityName
* @return
*/
@Override
public String getSignImage(List<DxWfProcessTaskVO> activities, String activityName) {
for (DxWfProcessTaskVO wf : activities) {
if (wf.getName().equals(activityName)) {
return getActivityUserName(wf);
}
}
return " ";
}
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
@Override
public String getEndDate(List<DxWfProcessTaskVO> activities, String activityName) {
for (DxWfProcessTaskVO wf : activities) {
if (wf.getName().equals(activityName)) {
return Optional.ofNullable(getActiveEndDate(wf)).orElse("");
}
}
return " ";
}
/**
* 获取用户名称及用户id(4.1新)
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
public String getActivityUserName(DxWfProcessTaskVO wf) {
String str = " ";
if (wf.getState().equals(TaskStateEnum.COMPLETE.name()) && (SignConstants.WfResultList.contains(wf.getResult()))) {
//获取用户名称和id
String userName = wf.getAssigneeName();
String userId = wf.getAssignee();
DxUserInfoVO userVO = (DxUserInfoVO) userService.get(Long.parseLong(userId));
str = userVO.getUserAccount() + ".png";
}
return str;
}
/**
* 修改后的处理获取日期(4.1新)
*
* @param wf
* @return
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
private String getActiveEndDate(DxWfProcessTaskVO wf) {
String date = "";
SimpleDateFormat dateFm = new SimpleDateFormat("yyyy-MM-dd");
if (wf.getState().equals(TaskStateEnum.COMPLETE.name()) && (SignConstants.WfResultList.contains(wf.getResult()))) {
return dateFm.format(wf.getEndTime()).replace(".", "-");
}
return date;
}
} }
...@@ -4,12 +4,15 @@ import com.yonde.dex.dao.service.util.ApplicationContextUtil; ...@@ -4,12 +4,15 @@ import com.yonde.dex.dao.service.util.ApplicationContextUtil;
import com.yonde.dex.dict.feign.DictDataFeignService; import com.yonde.dex.dict.feign.DictDataFeignService;
import com.yonde.dex.dict.service.vo.DictDataVO; import com.yonde.dex.dict.service.vo.DictDataVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Slf4j @Slf4j
...@@ -98,4 +101,23 @@ public class CommonUtils { ...@@ -98,4 +101,23 @@ public class CommonUtils {
return true; return true;
} }
/**
* 获取字典中文密级
*
* @param key
* @return
*/
public static String getSecretCode(String key) {
if (Strings.isEmpty(key)) {
return "";
}
DictDataFeignService dictService = ApplicationContextUtil.getBean(DictDataFeignService.class);
String secretKey = "SecretCode";
List<DictDataVO> dictData = dictService.getDictDatas(secretKey);
Map<String, String> dictMap = new HashMap<>();
for (DictDataVO dict : dictData) {
dictMap.put(dict.getDictKey(), dict.getDictValue());
}
return dictMap.get(key);
}
} }
\ No newline at end of file
package com.yonde.dcs.plan.core.util;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.yonde.dcs.plan.core.word.DocumentDispatch;
import lombok.extern.slf4j.Slf4j;
/**
* @author xfchai
* @ClassName Word2PdfJacobUtil.java
* @Description word转pdf
* @createTime 2021/12/28 11:31:00
*/
@Slf4j
public class Word2PdfJacobUtil {
/* 转PDF格式值 */
private static final int wdFormatPDF = 17;
/**
* word转pdf
*
* @param fileAbsolutePath
* @param toAddress
* @throws Exception
*/
public static void wordToPDF(String fileAbsolutePath, String toAddress) throws Exception {
DocumentDispatch documentDispatch = new DocumentDispatch();
documentDispatch.init(fileAbsolutePath);
documentDispatch.wordToPdf(toAddress);
documentDispatch.close();
}
/**
* Word文档转换
*
* @param inputFile
* @param pdfFile
*/
public static boolean word2PDF(String inputFile, String pdfFile) {
ComThread.InitMTA(true);
long start = System.currentTimeMillis();
ActiveXComponent app = null;
Dispatch doc = null;
try {
// 创建一个word对象
app = new ActiveXComponent("Word.Application");
// 不可见打开word
app.setProperty("Visible", new Variant(false));
// 禁用宏
app.setProperty("AutomationSecurity", new Variant(3));
// 获取文挡属性
Dispatch docs = app.getProperty("Documents").toDispatch();
log.info("打开文档 >>> " + inputFile);
// Object[]第三个参数是表示“是否只读方式打开”
// 调用Documents对象中Open方法打开文档,并返回打开的文档对象Document
doc = Dispatch.call(docs, "Open", inputFile, false, true).toDispatch();
log.info("转换文档 [" + inputFile + "] >>> [" + pdfFile + "]");
// 调用Document对象的SaveAs方法,将文档保存为pdf格式
// word保存为pdf格式宏,值为17
Dispatch.call(doc, "SaveAs", pdfFile, wdFormatPDF);
long end = System.currentTimeMillis();
log.info("用时:" + (end - start) + "ms.");
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("========Error:文档转换失败:" + e.getMessage());
} finally {
Dispatch.call(doc, "Close", false);
log.info("关闭文档");
if (app != null)
app.invoke("Quit", new Variant[]{});
// 如果没有这句话,winword.exe进程将不会关闭
ComThread.Release();
ComThread.quitMainSTA();
}
return false;
}
}
package com.yonde.dcs.plan.core.util;
import com.yonde.dcs.document.common.entity.vo.DxDocumentVO;
import com.yonde.dcs.plan.common.constants.SignConstants;
import com.yonde.dcs.plan.common.vo.ExtExpenditureContractVO;
import com.yonde.dex.user.common.vo.DxUserInfoVO;
import com.yonde.dex.user.feign.DxUserInfoFeign;
import com.yonde.dex.version.plugin.common.entity.DxIterationVOHolder;
import com.yonde.dex.wfc.common.enums.TaskStateEnum;
import com.yonde.dex.wfc.common.vo.*;
import com.yonde.dex.wfc.feign.api.WfcActivityFeign;
import com.yonde.dex.wfc.feign.api.WfcProcessFeign;
import com.yonde.dex.wfc.feign.api.WfcTaskFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @program: inet-pdm-service
* @description: 工作流工具类
* @author: dang wei
* @create: 2022-03-07 16:47
*/
@Component
public class WorkFlowUtil {
@Autowired
private WfcProcessFeign wfcProcessFeign;
@Autowired
private WfcActivityFeign wfcActivityFeign;
@Autowired
private WfcTaskFeign wfcTaskFeign;
@Autowired
private DxUserInfoFeign userService;
/**
* 获取流程实例
*
* @param iterationVO
* @return
*/
// TODO: xpc WfProcessInstVO不存在改为DxWfProcessVO,DxIterationVO不存在改为DxIterationVOHolder
public DxWfProcessVO getWfProcessInst(DxIterationVOHolder iterationVO) {
// TODO: getProcessInstList方法不存在改为getProcessList
// DxWfProcessSearchVO wfProcessInstSearchVO = new DxWfProcessSearchVO();
// wfProcessInstSearchVO.setPboClass(iterationVO.getClass().getName());
// wfProcessInstSearchVO.setPboId(iterationVO.getVersionId());
// Page<WfProcessInstVO> wfProcessInstVOPage = this.instanceService.getProcessList(wfProcessInstSearchVO, 1, 10);
DxWfProcessSearchVO dxWfProcessSearchVO = new DxWfProcessSearchVO();
dxWfProcessSearchVO.setPboClass(iterationVO.getClass().getName());
dxWfProcessSearchVO.setPboId(iterationVO.getVersionId());
Page<DxWfProcessVO> processList = wfcProcessFeign.getProcessList(dxWfProcessSearchVO, 1, 10);
if (!CollectionUtils.isEmpty(processList.getContent())) {
return processList.getContent().get(0);
}
return null;
}
/**
* 获取流程实例
*
* @param expenditureContract
* @return
*/
// TODO: xpc WfProcessInstVO不存在改为DxWfProcessVO
public DxWfProcessVO getWfProcessInst(ExtExpenditureContractVO expenditureContract) {
// TODO: getProcessInstList方法不存在改为getProcessList
// WfProcessInstSearchVO wfProcessInstSearchVO = new WfProcessInstSearchVO();
// wfProcessInstSearchVO.setPboClass(DxDocumentVO.class.getName());
// wfProcessInstSearchVO.setPboId(doc.getVersionId());
// Page<WfProcessInstVO> wfProcessInstVOPage = this.instanceService.getProcessInstList(wfProcessInstSearchVO, 1, 10);
DxWfProcessSearchVO dxWfProcessSearchVO = new DxWfProcessSearchVO();
dxWfProcessSearchVO.setPboClass(ExtExpenditureContractVO.class.getName());
dxWfProcessSearchVO.setPboId(expenditureContract.getVersionId());
Page<DxWfProcessVO> processList = wfcProcessFeign.getProcessList(dxWfProcessSearchVO, 1, 10);
if (!CollectionUtils.isEmpty(processList.getContent())) {
return processList.getContent().get(0);
}
return null;
}
/**
* 获取流程实例
*
* @param doc
* @return
*/
// TODO: xpc WfProcessInstVO不存在改为DxWfProcessVO
public DxWfProcessVO getWfProcessInst(DxDocumentVO doc) {
// TODO: getProcessInstList方法不存在改为getProcessList
// WfProcessInstSearchVO wfProcessInstSearchVO = new WfProcessInstSearchVO();
// wfProcessInstSearchVO.setPboClass(DxDocumentVO.class.getName());
// wfProcessInstSearchVO.setPboId(doc.getVersionId());
// Page<WfProcessInstVO> wfProcessInstVOPage = this.instanceService.getProcessInstList(wfProcessInstSearchVO, 1, 10);
DxWfProcessSearchVO dxWfProcessSearchVO = new DxWfProcessSearchVO();
dxWfProcessSearchVO.setPboClass(DxDocumentVO.class.getName());
dxWfProcessSearchVO.setPboId(doc.getVersionId());
Page<DxWfProcessVO> processList = wfcProcessFeign.getProcessList(dxWfProcessSearchVO, 1, 10);
if (!CollectionUtils.isEmpty(processList.getContent())) {
return processList.getContent().get(0);
}
return null;
}
/**
* 通过pbo获取流程实例签审详情信息
*
* @param doc
*/
public Map<String, List<DxWfProcessTaskVO>> getWfInfo(DxDocumentVO doc) {
// TODO: WfProcessInstVO不存在改为DxWfProcessVO
DxWfProcessVO wfProcessInstVO = getWfProcessInst(doc);
if (!ObjectUtils.isEmpty(wfProcessInstVO)) {
// TODO: xpc getProcessInstList方法不存在,根据逻辑改为getHisTaskList
// WfProcessInfoVO wfProcessInfo = this.instanceService.getProcessInstSimpleDetailById(wfProcessInstVO.getId());
// List<DxWfProcessTaskVO> historyInfoList = wfProcessInfo.getHistoryInfo();
List<DxWfProcessTaskVO> taskList = wfcTaskFeign.getHisTaskList(wfProcessInstVO.getId(), null, 1, Integer.MAX_VALUE).getContent();
List<String> checkResult = Arrays.asList("提交", "通过");
Map<String, List<DxWfProcessTaskVO>> wfHistoryMap = taskList.stream().filter(p -> TaskStateEnum.COMPLETE.name().equals(p.getState()) && checkResult.contains(p.getResult()))
.sorted(Comparator.comparing(DxWfProcessTaskVO::getEndTime).reversed())
.collect(Collectors.groupingBy(DxWfProcessTaskVO::getName));
return wfHistoryMap;
}
return null;
}
/**
* 根据任务名称获取处理人
*
* @param wfHistoryMap
* @param taskName
* @return
*/
public String getHandler(Map<String, List<DxWfProcessTaskVO>> wfHistoryMap, String taskName) {
String str = "";
if (wfHistoryMap.containsKey(taskName) && !ObjectUtils.isEmpty(wfHistoryMap.get(taskName).get(0))) {
String userId = wfHistoryMap.get(taskName).get(0).getAssignee();
DxUserInfoVO userVO = (DxUserInfoVO) userService.get(Long.parseLong(userId));
str = userVO.getUserAccount() + ".png";
return str;
}
return str;
}
/**
* 技术文件签字
*
* @param wfHistoryMap
* @param taskName
* @return
*/
public String getHandlerUser(Map<String, List<DxWfProcessTaskVO>> wfHistoryMap, String taskName) {
if (wfHistoryMap.containsKey(taskName) && !ObjectUtils.isEmpty(wfHistoryMap.get(taskName).get(0))) {
return wfHistoryMap.get(taskName).get(0).getAssigneeName();
}
return "";
}
/**
* 通过taskName获取签名图片,(目前过时文件通知单使用)
*
* @param activities
* @param activityName
* @return
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
public String getSignImage(List<DxWfActivityVO> activities, List<String> activityName) {
for (DxWfActivityVO wf : activities) {
if (activityName.contains(wf.getTaskName())) {
return getActivityUserName(wf);
}
}
return " ";
}
/**
* 获取用户名称及用户id
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
public String getActivityUserName(DxWfActivityVO activity) {
String str = " ";
List<DxWfProcessTaskVO> taskList = activity.getTaskList();
for (DxWfProcessTaskVO wf : taskList) {
if (wf.getState().equals(TaskStateEnum.COMPLETE.name()) && (SignConstants.WfResultList.contains(wf.getResult()))) {
//获取用户名称和id
String userName = wf.getAssigneeName();
String userId = wf.getAssignee();
DxUserInfoVO userVO = (DxUserInfoVO) userService.get(Long.parseLong(userId));
str = userVO.getUserAccount() + ".png";
}
}
return str;
}
/**
* 获取某个环节结束时间
*
* @param activities
* @param activityName
* @return
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
public String getEndDate(List<DxWfActivityVO> activities, List<String> activityName) {
for (DxWfActivityVO wf : activities) {
if (activityName.contains(wf.getTaskName())) {
return Optional.ofNullable(getActiveEndDate(wf)).orElse("");
}
}
return " ";
}
/**
* 修改后的处理获取日期
*
* @param activity
* @return
*/
// TODO: xpc 将WfTaskDefinitionVO改为DxWfActivityVO
private String getActiveEndDate(DxWfActivityVO activity) {
List<DxWfProcessTaskVO> taskList = activity.getTaskList();
String date = "";
SimpleDateFormat dateFm = new SimpleDateFormat("yyyy-MM-dd");
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(taskList)) {
for (DxWfProcessTaskVO wf : taskList) {
if (wf.getState().equals(TaskStateEnum.COMPLETE.name()) && (SignConstants.WfResultList.contains(wf.getResult()))) {
return dateFm.format(wf.getEndTime()).replace(".", "-");
}
}
}
return date;
}
//根据流程实例id获取组装信息
public DxWfProcessInfoVO getProcessInstDetail(DxWfProcessVO dxWfProcessVO) {
DxWfProcessInfoVO processInfoVO = new DxWfProcessInfoVO();
processInfoVO.setProcessVO(wfcProcessFeign.getProcessDetail(dxWfProcessVO.getId()));
processInfoVO.setActivityInfo(wfcActivityFeign.getActivities(dxWfProcessVO.getId(),dxWfProcessVO.getProcDefId()));
processInfoVO.setHistoryInfo(wfcTaskFeign.getHisTaskList(dxWfProcessVO.getId(),null, 1, Integer.MAX_VALUE).getContent());
return processInfoVO;
}
}
package com.yonde.dcs.plan.core.word;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlToken;
import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//import static org.apache.poi.POIXMLDocumentPart.DEFAULT_XML_OPTIONS;
/**
* @author xfchai
* @ClassName ImportWordService.java
* @Description 通用word类
* @createTime 2022/01/11 11:30:00
*/
public class CommonWord {
/* 检查文本中是否包含指定的字符(此处为“#”),并返回值 */
public static String checkText(String text) {
String check = "0";
//主表
if (text.contains("#")) {
check = "#";
}
//子表
if (text.contains("@")) {
check = "@";
}
//子表
if (text.contains("&")) {
check = "&";
}
return check;
}
/**
* 检查文本中是否包含指定的字符(此处为“#”),并返回值
*
* @param text
* @return
*/
public static String checkCellText(String text) {
String check = "0";
//主表
if (text.contains("#")) {
check = "#";
}
//子表
if (text.contains("$")) {
check = "$";
}
return check;
}
/**
* 检查文本中是否包含页数
*
* @param text
* @return
*/
public static String checkCellPages(String text) {
String check = "0";
//主表
if (text.contains("pages")) {
check = "#";
}
return check;
}
/**
* 检查文本中是否包含指定的字符(此处为“#”),并返回值
*
* @param text
* @return
*/
public static String checkDetailCellText(String text) {
String check = "0";
//主表
if (text.contains("#")) {
check = "#";
}
//子表
if (text.contains("$")) {
check = "$";
}
return check;
}
/**
* 去除所有特殊符号
*
* @param str
* @return
*/
public static String filterChinese(String str) {
String regEx = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?-]";
Pattern p = Pattern.compile(regEx);
Matcher matcher = p.matcher(str);
return matcher.replaceAll("").trim();
}
/**
* 去除所有特殊符号
*
* @param str
* @return
*/
public static String filterChinese2(String str) {
return str.split("@")[1].split("]")[0];
}
// 去除所有特殊符号
public static String filterChinese3(String str) {
return str.split("&")[1].split("]")[0];
}
/**
* 从 map 中 取对应的值
*
* @param value
* @param textMap
* @return
*/
public static Object changeValue(String value, HashMap<String, Object> textMap) {
Object res = null;
value = myFilterChinese(value);
// if ("pages".equals(value)) {
// return "[#pages]";
// }
try {
res = PropertyUtils.getProperty(textMap, value);
} catch (Exception e) {
System.out.println("属性未找到");
e.printStackTrace();
}
return res;
}
// 从 map 中 取对应的值
public static Object changePages(String value, HashMap<String, Object> textMap) {
Object res = null;
value = myFilterChinese(value);
try {
res = PropertyUtils.getProperty(textMap, value);
} catch (Exception e) {
System.out.println("属性未找到");
e.printStackTrace();
}
return res;
}
// 去除所有特殊符号
public static String myFilterChinese(String str) {
String regEx = "[`~!@#$%^&*()+=|{}':;',\\[\\]<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?-]";
Pattern p = Pattern.compile(regEx);
Matcher matcher = p.matcher(str);
return matcher.replaceAll("").trim();
}
/**
* 对象转map
*
* @param obj
* @return
*/
private static HashMap<String, Object> objToMap(Object obj) {
HashMap<String, Object> map = new HashMap<String, Object>();
// 获取f对象对应类中的所有属性域
Field[] fields = obj.getClass().getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++) {
String varName = fields[i].getName();
// 将key置为小写,默认为对象的属性
varName = varName.toLowerCase();
try {
// 获取原来的访问控制权限
boolean accessFlag = fields[i].isAccessible();
// 修改访问控制权限
fields[i].setAccessible(true);
// 获取在对象f中属性fields[i]对应的对象中的变量
Object o = fields[i].get(obj);
if (o != null) {
map.put(varName, o.toString());
}
// 恢复访问控制权限
fields[i].setAccessible(accessFlag);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
return map;
}
// 复制单元格
public static void copyTableRow(XWPFTableRow target, XWPFTableRow source, Integer index) {
// 复制样式
if (source.getCtRow() != null) {
target.getCtRow().setTrPr(source.getCtRow().getTrPr());
}
// 复制单元格
for (int i = 0; i < source.getTableCells().size(); i++) {
XWPFTableCell cell1 = target.getCell(i);
XWPFTableCell cell2 = source.getCell(i);
if (cell1 == null) {
cell1 = target.addNewTableCell();
}
copyTableCell(cell1, cell2, index);
}
}
public static void copyTableCell(XWPFTableCell target, XWPFTableCell source, Integer index) {
// 列属性
if (source.getCTTc() != null) {
target.getCTTc().setTcPr(source.getCTTc().getTcPr());
}
// 删除段落
for (int pos = 0; pos < target.getParagraphs().size(); pos++) {
target.removeParagraph(pos);
}
// 添加段落
for (XWPFParagraph sp : source.getParagraphs()) {
XWPFParagraph targetP = target.addParagraph();
copyParagraph(targetP, sp, index);
}
}
public static void copyParagraph(XWPFParagraph target, XWPFParagraph source, Integer index) {
// 设置段落样式
target.getCTP().setPPr(source.getCTP().getPPr());
// 移除所有的run
for (int pos = target.getRuns().size() - 1; pos >= 0; pos--) {
target.removeRun(pos);
}
// copy 新的run
for (XWPFRun s : source.getRuns()) {
XWPFRun targetrun = target.createRun();
copyRun(targetrun, s, index);
}
}
/**
* 功能描述:复制RUN,从source到target
*
* @param target
* @param source
* @param index
*/
public static void copyRun(XWPFRun target, XWPFRun source, Integer index) {
// 设置run属性
target.getCTR().setRPr(source.getCTR().getRPr());
// 设置文本
String tail = "";
if (index != null) {
tail = index.toString();
}
target.setText(source.toString());
}
public void addPicture(final String fileName, final int id, int width, int height, final XWPFRun run) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(fileName);
final String blipId = run.getDocument().addPictureData(fileInputStream, Document.PICTURE_TYPE_JPEG);
final int EMU = 9525;
width *= EMU;
height *= EMU;
//String blipId = getAllPictures().get(id).getPackageRelationship().getId();
CTDrawing drawing = run.getCTR().addNewDrawing();
// final CTInline inline = run.getCTR().addNewDrawing().addNewInline();
String xml = "<wp:anchor allowOverlap=\"0\" layoutInCell=\"1\" locked=\"0\" behindDoc=\"0\" relativeHeight=\"0\" simplePos=\"0\" distR=\"0\" distL=\"0\" distB=\"0\" distT=\"0\" " +
" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"" +
" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\"" +
" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" >" +
"<wp:simplePos y=\"0\" x=\"0\"/>" +
"<wp:positionH relativeFrom=\"column\">" +
"<wp:align>center</wp:align>" +
"</wp:positionH>" +
"<wp:positionV relativeFrom=\"paragraph\">" +
"<wp:posOffset>0</wp:posOffset>" +
"</wp:positionV>" +
"<wp:extent cy=\"" + height + "\" cx=\"" + width + "\"/>" +
"<wp:effectExtent b=\"0\" r=\"0\" t=\"0\" l=\"0\"/>" +
"<wp:wrapTopAndBottom/>" +
"<wp:docPr descr=\"Picture Alt\" name=\"Picture Hit\" id=\"0\"/>" +
"<wp:cNvGraphicFramePr>" +
"<a:graphicFrameLocks noChangeAspect=\"true\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" />" +
"</wp:cNvGraphicFramePr>" +
"<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
"<a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
"<pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
"<pic:nvPicPr>" +
"<pic:cNvPr name=\"Picture Hit\" id=\"1\"/>" +
"<pic:cNvPicPr/>" +
"</pic:nvPicPr>" +
"<pic:blipFill>" +
"<a:blip r:embed=\"" + blipId + "\"/>" +
"<a:stretch>" +
"<a:fillRect/>" +
"</a:stretch>" +
"</pic:blipFill>" +
"<pic:spPr>" +
"<a:xfrm>" +
"<a:off y=\"0\" x=\"0\"/>" +
"<a:ext cy=\"" + height + "\" cx=\"" + width + "\"/>" +
"</a:xfrm>" +
"<a:prstGeom prst=\"rect\">" +
"<a:avLst/>" +
"</a:prstGeom>" +
"</pic:spPr>" +
"</pic:pic>" +
"</a:graphicData>" +
"</a:graphic>" +
"<wp14:sizeRelH relativeFrom=\"margin\">" +
"<wp14:pctWidth>0</wp14:pctWidth>" +
"</wp14:sizeRelH>" +
"<wp14:sizeRelV relativeFrom=\"margin\">" +
"<wp14:pctHeight>0</wp14:pctHeight>" +
"</wp14:sizeRelV>" +
"</wp:anchor>";
final String picXml = ""
+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"" +
" >"
// +" allowOverlap=\"1\" layoutInCell=\"0\" locked=\"1\" behindDoc=\"1\" relativeHeight=\"1\" "
// +" simplePos=\"1\" distR=\"1\" distL=\"1\" distB=\"1\" distT=\"1\" />"
+ " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
" <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ " <pic:nvPicPr>" + " <pic:cNvPr id=\""
+ id
+ "\" name=\"Generated\"/>"
+ " <pic:cNvPicPr/>"
+ " </pic:nvPicPr>"
+ " <pic:blipFill>"
+ " <a:blip r:embed=\""
+ blipId
+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
+ " <a:stretch>"
+ " <a:fillRect/>"
+ " </a:stretch>"
+ " </pic:blipFill>"
+ " <pic:spPr>"
+ " <a:xfrm>"
+ " <a:off x=\"0\" y=\"0\"/>"
+ " <a:ext cx=\""
+ width
+ "\" cy=\""
+ height
+ "\"/>"
+ " </a:xfrm>"
+ " <a:prstGeom prst=\"rect\">"
+ " <a:avLst/>"
+ " </a:prstGeom>"
+ " </pic:spPr>"
+ " </pic:pic>" + " </a:graphicData>" + "</a:graphic>";
//CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
drawing.set(XmlToken.Factory.parse(xml));
List<CTPicture> pictures = new ArrayList<>();
XmlObject[] picts = drawing.selectPath("declare namespace pic='"
+ CTPicture.type.getName().getNamespaceURI() + "' .//pic:pic");
for (XmlObject pict : picts) {
if (pict instanceof XmlAnyTypeImpl) {
try {
pict = CTPicture.Factory.parse(pict.toString());
} catch (XmlException e) {
e.printStackTrace();
}
}
if (pict instanceof CTPicture) {
pictures.add((CTPicture) pict);
}
}
CTPicture pic = pictures.get(0);
XWPFPicture xwpfPicture = new XWPFPicture(pic, run);
run.getEmbeddedPictures().add(xwpfPicture);
// XmlToken xmlToken = null;
// xmlToken = XmlToken.Factory.parse(xml);
// xmlToken = XmlToken.Factory.parse(anchorXML);
// inline.set(xmlToken);
//graphicData.set(xmlToken);
// inline.setDistT(0);
// inline.setDistB(0);
// inline.setDistL(0);
// inline.setDistR(0);
// final CTPositiveSize2D extent = inline.addNewExtent();
// extent.setCx(width);
// extent.setCy(height);
// final CTNonVisualDrawingProps docPr = inline.addNewDocPr();
// docPr.setId(id);
// docPr.setName("Picture " + id);
// docPr.setDescr("Generated");
} catch (final Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//close streams
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (final IOException ioEx) {
//can be ignored
}
}
}
}
public static void joinRuns(XWPFParagraph paragraph) {
List<XWPFRun> runs = paragraph.getRuns();
// 合并逻辑
for (int i = 0; i < runs.size(); i++) {
String text0 = runs.get(i).getText(runs.get(i).getTextPosition());
if (text0 != null && text0.contains("[")) {
int startIndex = text0.lastIndexOf("[");
int endIndex = 1;
if (startIndex != -1) {
endIndex = text0.substring(startIndex).indexOf("]");
}
if (endIndex < 0) {
// 记录分隔符中间跨越的runs数量,用于字符串拼接和替换
int num = 0;
int j = i + 1;
for (; j < runs.size(); j++) {
String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
if (text1 != null && text1.contains("]")) {
num = j - i;
break;
}
}
if (num != 0) {
// num!=0说明找到了@@配对,需要替换
StringBuilder newText = new StringBuilder();
for (int s = i; s <= i + num; s++) {
String text2 = runs.get(s).getText(runs.get(s).getTextPosition());
String replaceText = text2;
if (s == i && text2.contains("[") && text2.contains("]")) {
newText.append(text2);
} else if (s == i && text2.contains("[")) {
replaceText = text2.substring(0, text2.indexOf("["));
newText.append(text2.substring(text2.indexOf("[")));
} else if (text2.contains("]")) {
replaceText = text2.substring(replaceText.indexOf("]") + 1);
newText.append(text2.substring(0, text2.indexOf("]") + 1));
} else {
replaceText = "";
newText.append(text2);
}
runs.get(s).setText(replaceText, 0);
}
runs.get(i).setText(newText.toString(), 0);
i = i - 1;
}
}
}
}
}
/**
* json转map
*
* @param j
* @return
*/
public static HashMap<String, Object> JsonToMap(JSONObject j) {
HashMap<String, Object> map = new HashMap<>();
for (String key : j.keySet()) {
Object value = j.get(key);
if (value instanceof String) {
String a = String.valueOf(value);
if (a.contains("\n") && !"\n".equals(a)) {
value = a.replace("\n", "$*$");
}
}
map.put(key, value);
}
return map;
}
}
package com.yonde.dcs.plan.core.word;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
/**
* @author xfchai
* @ClassName ImportWordService.java
* @Description 文本字体
* @createTime 2022/01/11 11:30:00
*/
@Data
public class DocFont {
/**
* 是否加粗
*/
private String bold;
/**
* 字体大小
*/
private String size;
/**
* 字体名称
*/
private String name;
public boolean notEqualsFont(String bold, String size, String name) {
return !StringUtils.equals(this.bold, bold)
|| !StringUtils.equals(this.size, size)
|| !StringUtils.equals(this.name, name);
}
}
package com.yonde.dcs.plan.core.word;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
/**
* @author xfchai
* @ClassName ImportWordService.java
* @Description
* @createTime 2022/01/11 11:30:00
*/
@Slf4j
public class DocumentDispatch {
@Getter
private String filepath;
@Getter
private String path;
@Getter
private ActiveXComponent wordApp;
@Getter
private Dispatch document;
Dispatch documents;
@Getter
private Dispatch table;
/**
* word打开是否显示
*/
@Getter
final boolean Word_Visible = false;
final int wdFormatPDF = 17;// PDF 格式
public void init(String fileAbsolutePath) throws IOException {
File file = new File(fileAbsolutePath);
filepath = file.getParentFile().getPath();
path = fileAbsolutePath;
log.info("[Word操作] >>>>> {}", path);
log.info("[Word操作({})] >>>>>> 初始化COM");
ComThread.InitMTA(true);
log.info("[Word操作({})] >>>>>> 初始化ActiveX");
wordApp = new ActiveXComponent("Word.Application");
Dispatch wordObject = wordApp.getObject();
Dispatch.put(wordObject, "Visible", new Variant(Word_Visible));
documents = wordApp.getProperty("Documents").toDispatch();
log.info("[Word操作({})] >>>>>> 打开文件", path);
document = Dispatch.call(documents, "Open", path).toDispatch();
}
private void filePathExist(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
file.mkdirs();
}
}
private void copyAndCloseStream(InputStream is, OutputStream os)
throws IOException {
try {
IOUtils.copy(is, os);
} catch (Exception e) {
log.warn("copyAndCloseStream error:", e);
} finally {
is.close();
os.close();
}
}
public void release() {
close(wordApp, document);
deleteDocFile(path, filepath, null);
}
public String getCellStr(int x, int y) {
Dispatch cell = Dispatch.call(table, "cell", x, y).toDispatch();
Dispatch range = Dispatch.get(cell, "Range").toDispatch();
return Dispatch.get(range, "Text").getString();
}
public DocFont getFont(int x, int y, int row) {
Dispatch cell = Dispatch.call(table, "cell", x, y).toDispatch();
Dispatch range = Dispatch.get(cell, "Range").toDispatch();
if (row > 0) {
Dispatch paragraphs = Dispatch.get(range, "Paragraphs").toDispatch();
Dispatch item = Dispatch.call(paragraphs, "Item", new Variant(row)).toDispatch();
range = Dispatch.get(item, "Range").toDispatch();
}
Dispatch font = Dispatch.get(range, "Font").toDispatch();
DocFont docFont = new DocFont();
docFont.setBold(Dispatch.get(font, "Bold").toString());
docFont.setSize(Dispatch.get(font, "Size").toString());
docFont.setName(Dispatch.get(font, "Name").toString());
return docFont;
}
public DocFont getFont(int x, int y) {
return getFont(x, y, -1);
}
public int getPageCount() {
Dispatch selection = Dispatch.get(wordApp, "Selection").toDispatch();
String count = Dispatch.call(selection, "Information", new Variant(4)).toString();
return Integer.parseInt(count);
}
private void close(ActiveXComponent objWord, Dispatch document) {
if (Objects.nonNull(document)) {
Dispatch.call(document, "Close", new Variant(0));
document = null;
}
if (Objects.nonNull(objWord)) {
log.info("release->{}", objWord);
objWord.invoke("Quit", new Variant[]{});
objWord = null;
}
}
public void close() {
if (Objects.nonNull(document)) {
Dispatch.call(document, "Close", new Variant(0));
document = null;
}
if (Objects.nonNull(wordApp)) {
log.info("release->{}", wordApp);
wordApp.invoke("Quit", new Variant[]{});
wordApp = null;
}
}
private void deleteDocFile(String path, String filePath, String pathXml) {
File file;
if (StringUtils.isNotEmpty(path)) {
file = new File(path);
file.delete();
}
if (StringUtils.isNotEmpty(filePath)) {
file = new File(filePath);
file.delete();
}
if (StringUtils.isNotEmpty(pathXml)) {
file = new File(pathXml);
file.delete();
}
}
/**
* word转pdf
*
* @param toAddress 新文件地址
*/
public void wordToPdf(String toAddress) {
long start = System.currentTimeMillis();
File tofile = new File(toAddress);
if (tofile.exists()) {
tofile.delete();
}
//word文件另存为pdf文件
Dispatch.call(document,//
"SaveAs", //
toAddress, // FileName
wdFormatPDF);
long end = System.currentTimeMillis();
log.info("转换完成..用时:" + (end - start) + "ms.");
}
public static void main(String[] args) throws Exception {
/* DocumentDispatch documentDispatch=new DocumentDispatch();
// documentDispatch.init("word源文件路径");
// documentDispatch.wordToPdf("目标pdf路径");
documentDispatch.init("C://Users//ASUS//Desktop//中航//施工图研究设计输入new.doc");
documentDispatch.wordToPdf("C://Users//ASUS//Desktop//中航//xxx.pdf");
documentDispatch.close();*/
wordToPDF("D:/Demo/123.docx", "D:/Demo/Demo.pdf");
}
public static void wordToPDF(String fileAbsolutePath, String toAddress) throws Exception {
DocumentDispatch documentDispatch = new DocumentDispatch();
documentDispatch.init(fileAbsolutePath);
documentDispatch.wordToPdf(toAddress);
documentDispatch.close();
}
}
package com.yonde.dcs.plan.core.word;
import org.springframework.stereotype.Service;
/**
* @author xfchai
* @ClassName DownloadPictures.java
* @Description 下载图片
* @createTime 2022/01/11 11:53:00
*/
@Service
public class DownloadPictures {
public static final String tempPath = "D:/SignService/SignImages/";
/**
* 获取签名图片地址
*
* @param img
* @return
*/
public String GetAddress(String img) {
//签名图片保存到指定目录下(D:/SignService/SignImages/)
StringBuffer tempPathImgs = new StringBuffer();
boolean contains = img.contains(",");
if ((contains)) {
String[] split = img.split(",");
for (String s : split) {
if (tempPathImgs.length() > 0) {
tempPathImgs.append(",");
}
tempPathImgs.append(tempPath + s);
}
} else {
tempPathImgs.append(tempPath + img);
}
return tempPathImgs.toString();
}
}
package com.yonde.dcs.plan.core.word;
import com.alibaba.fastjson.JSONObject;
import com.yonde.dcs.plan.core.util.Word2PdfJacobUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author xfchai
* @ClassName ImportWordService.java
* @Description 生成word服务
* @createTime 2022/01/11 11:30:00
*/
@Service
@Slf4j
public class ImportWordService {
@Autowired
private UpdateWordText updateWordText;
public int getWordAllTable(JSONObject data, String srcPath, String outPath) {
XWPFDocument document = null;
FileInputStream is = null;
FileOutputStream out = null;
int pages = 0;
try {
is = new FileInputStream(srcPath);
document = new XWPFDocument(is);
updateWordText.changeTable(document, data, "all");
out = new FileOutputStream(outPath);
document.write(out);
} catch (Exception e) {
log.error(e.toString());
} finally {
try {
out.close();
is.close();
} catch (IOException e) {
log.error(e.toString());
}
}
log.info("第一次替换word文件内容结束====文件目录:{}" + outPath);
String pdfPath = outPath.split("\\.")[0] + ".pdf";
FileInputStream isPDF = null;
FileOutputStream outPdf = null;
FileInputStream isWord = null;
XWPFDocument document2 = null;
try {
log.info("开始转换pdf获取页数====临时pdf模板:{}" + pdfPath);
// DocumentDispatch.wordToPDF(outPath, pdfPath);
Word2PdfJacobUtil.word2PDF(outPath, pdfPath);
isPDF = new FileInputStream(pdfPath);
pages = getPdfPages(isPDF);
isWord = new FileInputStream(outPath);
document2 = new XWPFDocument(isWord);
//获取Word总页数
// pages = document2.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
pages = updateWordText.changeTablePages(document2, data, "all", pages);
outPdf = new FileOutputStream(outPath);
document2.write(outPdf);
log.info("update pages: {}", outPath);
} catch (Exception e) {
log.error("获取页数失败", e);
} finally {
try {
if (isPDF != null) {
isPDF.close();
}
if (isWord != null) {
isWord.close();
}
if (outPdf != null) {
outPdf.close();
}
} catch (IOException e) {
log.error("关闭文档失败", e);
}
}
return pages;
}
/**
* 获取pdf页数
*
* @param is
* @return
*/
public int getPdfPages(FileInputStream is) {
int page = 0;
//todo
// PDDocument pdDocument = null;
// try {
// pdDocument = PDDocument.load(is);
// int pdfPages = pdDocument.getNumberOfPages();
// page = page + pdfPages;
// } catch (Exception e) {
// log.error(e.toString());
// } finally {
// if (pdDocument != null) {
// try {
// pdDocument.close();
// } catch (IOException e) {
// log.error(e.toString());
// }
// }
// }
return page;
}
public int generateWord(JSONObject data, String srcPath, String outPath) {
XWPFDocument document = null;
FileInputStream is = null;
FileOutputStream out = null;
int pages = 0;
try {
is = new FileInputStream(srcPath);
document = new XWPFDocument(is);
updateWordText.changeTable(document, data, "all");
out = new FileOutputStream(outPath);
document.write(out);
} catch (Exception e) {
log.error(e.toString());
} finally {
try {
out.close();
is.close();
} catch (IOException e) {
log.error(e.toString());
}
}
return pages;
}
}
package com.yonde.dcs.plan.core.word;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author xfchai
* @ClassName UpdateWordText.java
* @Description 更新word文字
* @createTime 2022/01/11 11:31:00
*/
@Service
@Slf4j
public class UpdateWordText {
@Autowired
DownloadPictures downloadPictures;
public void changeTable(XWPFDocument document, JSONObject data, String type) {
log.info("word替换表格->>>>>>>开始");
List<Integer> rmDocPages = new ArrayList<>();
// 获取文件的表格
List<XWPFTable> tableList = document.getTables();
// 循环所有需要进行替换的表格
for (int i = 0; i < tableList.size(); i++) {
XWPFTable table = tableList.get(i);
// 循环所有行
eachTableRow(document, table, data, type, rmDocPages);
}
Object subTypeName = data.get("subTypeName");
boolean flag = false;
if ("DEN".equals(subTypeName)) {
flag = true;
}
log.info("要删除的表格数量{}个", rmDocPages.size());
if (rmDocPages.size() > 0) {
removeTables(document, rmDocPages);
rmDocPages.clear();
}
//循环所有 页眉页脚
List<XWPFHeader> headerList = document.getHeaderList();
List<XWPFFooter> footerList = document.getFooterList();
for (XWPFHeader xwpfHeader : headerList) {
//页眉
System.out.println(xwpfHeader.getText());
updateHeaderText(xwpfHeader.getParagraphs(), data);
// xwpfHeader.getp
}
for (XWPFFooter xwpfFooter : footerList) {
//页眉
System.out.println(xwpfFooter.getText());
updateHeaderText(xwpfFooter.getParagraphs(), data);
// xwpfHeader.getp
}
}
/**
* 更新标题文本
*
* @param paragraphs
* @param data
*/
public void updateHeaderText(List<XWPFParagraph> paragraphs, JSONObject data) {
//取主表信息
// JSONObject mainTable = data.getJSONObject("mainTable");
HashMap<String, Object> hmap = CommonWord.JsonToMap(data);
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
CommonWord.joinRuns(paragraph);
if (run.toString().contains("[#")) {
Object ob = CommonWord.changeValue(run.toString(), hmap);
if (ob instanceof String || ob instanceof Integer || ob instanceof Date) {
if (ob instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
ob = sdf.format(ob);
}
System.out.println("run:" + run.toString() + "替换为" + ob);
run.setText(String.valueOf(ob), 0);
} else {
System.out.println("run:" + run.toString() + "替换为空");
run.setText("", 0);
}
}
}
}
}
/**
* 删除页面上的空表和多余的分页符
*
* @param docx
* @param removeIndexs
*/
private void removeTables(XWPFDocument docx, List<Integer> removeIndexs) {
List<IBodyElement> eles = docx.getBodyElements();
int size = eles.size();
for (int i = size - 1; i >= 0; i--) {
if (removeIndexs.contains(i)) {
continue;
}
IBodyElement element = eles.get(i);
if (element instanceof XWPFParagraph) {
XWPFParagraph paragraph = (XWPFParagraph) element;
if (isEmpTy(paragraph)) {
boolean upRemoved = true;
for (int j = i - 1; j >= 0; j--) {
if (!(eles.get(j) instanceof XWPFParagraph) && !removeIndexs.contains(j)) {
upRemoved = false;
break;
}
if ((eles.get(j) instanceof XWPFParagraph) && isEmpTy((XWPFParagraph) eles.get(j))) {
break;
}
}
if (upRemoved) {
System.out.println("通过上方判断可以删除 " + i);
removeIndexs.add(i);
}
} else {
System.out.println("第" + i + "项不为空");
}
}
}
removeIndexs.sort(Integer::compareTo);
//若最后一个元素是段落,把它修改为不分页
boolean lastFlag = true;
for (int i = size - 1; i >= 0; i--) {
if (!removeIndexs.contains(i)) {
if (lastFlag) {
if (eles.get(i) instanceof XWPFParagraph) {
log.info("处理文件末尾的段落:{}", i);
XWPFParagraph paragraph = (XWPFParagraph) eles.get(i);
CTP ctp = paragraph.getCTP();
ctp.setPPr(ctp.addNewPPr());
CTSpacing spacing = ctp.getPPr().addNewSpacing();
spacing.setLine(BigInteger.valueOf(0));
spacing.setLineRule(STLineSpacingRule.Enum.forInt(3));
CTParaRPr rPr = ctp.getPPr().addNewRPr();
rPr.addNewSzCs().setVal(BigInteger.valueOf(2));
rPr.addNewSz().setVal(BigInteger.valueOf(2));
} else {
lastFlag = false;
}
}
}
}
for (int i = removeIndexs.size() - 1; i >= 0; i--) {
System.out.println("删除第" + removeIndexs.get(i) + "项...");
docx.removeBodyElement(removeIndexs.get(i));
}
}
/**
* 判断段落是否为空(包括分页符)
*
* @param paragraph
* @return
*/
boolean isEmpTy(XWPFParagraph paragraph) {
return paragraph.isEmpty() || paragraph.isPageBreak() || (paragraph.getRuns().isEmpty() && paragraph.getIRuns().isEmpty());
}
public void eachTableRow(XWPFDocument document, XWPFTable table, JSONObject data, String type, List<Integer> rmDocPages) {
//取主表信息
// JSONObject mainTable = data.getJSONObject("mainTable");
HashMap<String, Object> hmap = CommonWord.JsonToMap(data);
boolean falg = false;
List<XWPFTableRow> rows = table.getRows();
//修改list签图片
// for (int i = rows.size() - 1; i >= 0; i--) {
for (int i = 0; i < rows.size(); i++) {
XWPFTableRow row = rows.get(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
//如果 是从表 则特殊处理
String text = cell.getText();
if (cell.getText().contains("@")) {
String detailTag = cell.getText();
String config = detailTag.split("@")[1].split("]")[0];
String[] configs = config.split(",");
if (configs.length == 4) {
// 去除标识符
deleteFlag(document, cell);
falg = insertDetailTable(document, table, row, data, type, detailTag, i);
}
}
List<XWPFTable> tableList = cell.getTables();
if (tableList.size() > 0) {
System.out.println("第二层表格");
//循环所有需要进行替换的表格
for (int j = 0; j < tableList.size(); j++) {
eachMainTable1(document, tableList.get(j), hmap, type);
}
} else {
//获取单元格中 占位符 格式
String CellType = CommonWord.checkCellText(cell.getText());
// 判断单元格是否需要替换
if ("#".equals(CellType)) {
updateText(cell, hmap);
}
if ("$".equals(CellType)) {
updatePic(document, cell, hmap, type);
}
}
}
}
if (falg) {
CTBody body = document.getDocument().getBody();
if (body.isSetSectPr()) {
CTSectPr sectPr = body.getSectPr();
if (sectPr.isSetPgSz()) {
CTPageSz pageSz = sectPr.getPgSz();
if (pageSz.getW().compareTo(pageSz.getH()) > 0) {
pageSz.setOrient(STPageOrientation.PORTRAIT);
BigInteger testW = pageSz.getW();
pageSz.setW(pageSz.getH());
pageSz.setH(testW);
if (sectPr.isSetPgMar()) {
CTPageMar pageMar = sectPr.getPgMar();
BigInteger tempI = pageMar.getTop();
pageMar.setTop(pageMar.getLeft());
pageMar.setLeft(pageMar.getBottom());
pageMar.setBottom(pageMar.getRight());
pageMar.setRight(tempI);
}
}
}
}
List<IBodyElement> eles = document.getBodyElements();
for (int i = 0; i < eles.size(); i++) {
IBodyElement element = eles.get(i);
if (element.equals(table)) {
rmDocPages.add(i);
}
}
}
}
public void eachMainTable1(XWPFDocument document, XWPFTable table, HashMap<String, Object> textMap, String type) {
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
List<XWPFTable> tableList = cell.getTables();
if (tableList.size() > 0) {
System.out.println("第二层表格");
// 循环所有需要进行替换的表格
for (int i = 0; i < tableList.size(); i++) {
eachMainTable2(document, tableList.get(i), textMap, type);
}
} else {
//获取单元格中 占位符 格式
String CellType = CommonWord.checkCellText(cell.getText());
// 判断单元格是否需要替换
if ("#".equals(CellType)) {
updateText(cell, textMap);
} else if ("$".equals(CellType)) {
updatePic(document, cell, textMap, type);
}
}
}
}
}
/**
* 更新文本
*
* @param cell
* @param textMap
*/
public void updateText(XWPFTableCell cell, HashMap<String, Object> textMap) {
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
CommonWord.joinRuns(paragraph);
if (run.toString().contains("[#")) {
Object ob = CommonWord.changeValue(run.toString(), textMap);
if (ob instanceof String || ob instanceof Integer || ob instanceof Date) {
if (ob instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
ob = sdf.format(ob);
}
String obj = String.valueOf(ob);
if (obj.contains("$*$")) {
String[] split = obj.split("\\$\\*\\$");
run.setText(split[0], 0);
for (int i = 1; i < split.length; i++) {
run.addBreak();
run.setText(split[i]);
}
} else {
// System.out.println("run:" + run.toString() + "替换为" + ob);
run.setText(obj, 0);
}
} else {
// System.out.println("run:"+ run.toString()+"替换为空");
run.setText("", 0);
}
}
}
}
}
/**
* 更新签名图片
*
* @param document
* @param cell
* @param textMap
* @param type
*/
public void updatePic(XWPFDocument document, XWPFTableCell cell, HashMap<String, Object> textMap, String type) {
Map<String, String> tablePicSizeMap = null;
try {
Object subTypeName = textMap.get("subTypeName");
Map<String, Map<String, String>> signPictureSizeMap = (Map<String, Map<String, String>>) textMap.get("signPictureSize");
tablePicSizeMap = signPictureSizeMap.get(subTypeName);
} catch (Exception e) {
}
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
CommonWord.joinRuns(paragraph);
if (run.toString().contains("[#") || run.toString().contains("[$")) {
Object ob = CommonWord.changeValue(run.toString(), textMap);
if (ob instanceof String || ob instanceof Integer || ob instanceof Date) {
if (ob instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
ob = sdf.format(ob);
}
String cellText = CommonWord.filterChinese(run.toString());
// System.out.println("run:" + "'" + run.toString() + "'");
if ("all".equals(type)) {
run.setText("", 0);
CommonWord cxd = new CommonWord();
try {
String path = downloadPictures.GetAddress(ob.toString());
log.info("----------------下载签字图片:{}后的图片路径:{}", ob.toString(), path);
// 默认图片大小
Integer heigth = 50;
Integer width = 20;
if (tablePicSizeMap != null) {
String picSize = tablePicSizeMap.get(cellText);
if (StringUtils.isNotBlank(picSize)) {
String[] split = picSize.split(",");
heigth = Integer.valueOf(split[0]);
width = Integer.valueOf(split[1]);
}
}
if (path.contains(",")) {
String[] paths = path.split(",");
for (String s : paths) {
XWPFRun newRun = paragraph.createRun();
// System.out.println("run:" + cellText + "替换为图片:"+ob.toString());
cxd.addPicture(s, document.getNextPicNameNumber(Document.PICTURE_TYPE_PNG), heigth, width, newRun);
}
} else {
// System.out.println("run:" + cellText + "替换为图片:"+ob.toString());
cxd.addPicture(path, document.getNextPicNameNumber(Document.PICTURE_TYPE_PNG), heigth
, width, run);
}
} catch (InvalidFormatException e) {
e.printStackTrace();
}
} else {
// System.out.println("run:" + cellText + "替换为空");
run.setText("", 0);
}
} else {
run.setText("", 0);
// System.out.println("'" + run.toString() + "'不匹配");
}
}
}
}
}
public void eachMainTable2(XWPFDocument document, XWPFTable table, HashMap<String, Object> textMap, String type) {
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
List<XWPFTable> tableList = cell.getTables();
if (tableList.size() > 0) {
System.out.println("第三层表格");
} else {
//获取单元格中 占位符 格式
String CellType = CommonWord.checkCellText(cell.getText());
// 判断单元格是否需要替换
if ("#".equals(CellType)) {
updateText(cell, textMap);
} else if ("$".equals(CellType)) {
updatePic(document, cell, textMap, type);
}
}
}
}
}
/**
* 去除标识符
*
* @param document
* @param cell
*/
public void deleteFlag(XWPFDocument document, XWPFTableCell cell) {
String text = cell.getText();
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (int i = paragraphs.size() - 1; i >= 0; i--) {
cell.removeParagraph(i);
}
cell.addParagraph();
XWPFParagraph paragraph = cell.getParagraphs().get(0);
XWPFRun run = paragraph.createRun();
String[] title = text.split("]");
if (title.length > 1) {
run.setText(text.split("]")[1], 0);
}
}
/**
* 插入表格详情
*
* @param document
* @param table
* @param row
* @param data
* @param type
* @param detailTag
* @param lineNumber
* @return
*/
public boolean insertDetailTable(XWPFDocument document, XWPFTable table, XWPFTableRow row, JSONObject data,
String type, String detailTag, int lineNumber) {
// List<XWPFTableRow> rows = table.getRows();
//int rowNums = rows.size();
//复制单元格
String config = detailTag.split("@")[1].split("]")[0];
String[] configs = config.split(",");
String tableName = configs[0];
val contains = tableName.contains(",");
//空数据是否删除表格
int deleteFlag = Integer.parseInt(configs[1]);
//标题列数量
int titleCount = Integer.parseInt(configs[2]);
// 数据占用行数
int dataRowCount = Integer.parseInt(configs[3]);
List<HashMap<String, Object>> detailDatas = new ArrayList<HashMap<String, Object>>();
JSONArray jar = data.getJSONArray(tableName);
if (jar != null) {
for (int k = 0; k < jar.size(); k++) {
JSONObject j = jar.getJSONObject(k);
HashMap<String, Object> map = CommonWord.JsonToMap(j);
detailDatas.add(map);
}
}
if (detailDatas.size() == 0 && deleteFlag == 1) {
return true;
}
for (int i = detailDatas.size() - 1; i > 0; i--) {
for (int k = 0; k < dataRowCount; k++) {
XWPFTableRow newRow = table.insertNewTableRow(lineNumber + titleCount + dataRowCount + k);
CommonWord.copyTableRow(newRow, table.getRow(lineNumber + titleCount + k), null);
List<XWPFTableCell> cells = newRow.getTableCells();
HashMap<String, Object> textMap = detailDatas.get(i);
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
// String CellType = CommonWord.checkCellText();
if (cell.getText().contains("&")) {
updateDetailText(cell, textMap);
}
if (cell.getText().contains("$")) {
updatePic(document, cell, textMap, type);
}
}
}
}
//处理首行
for (int k = 0; k < dataRowCount; k++) {
XWPFTableRow firstRow = table.getRow(lineNumber + titleCount + k);
List<XWPFTableCell> cells = firstRow.getTableCells();
HashMap<String, Object> textMap = null;
if (detailDatas.size() > 0) {
textMap = detailDatas.get(0);
}
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
// String CellType = CommonWord.checkCellText();
if (cell.getText().contains("&")) {
updateDetailText(cell, textMap);
}
if (cell.getText().contains("$")) {
updatePic(document, cell, textMap, type);
}
}
}
if (configs.length > 4) {
//合并行,或 列
int cellOrRow = Integer.parseInt(configs[4]);
// 合并起始位置
int startPos = Integer.parseInt(configs[5]);
//合并终止位置
int endPos = Integer.parseInt(configs[6]);
if ("1".equals(cellOrRow)) {
//(XWPFTable table, int col, int fromRow, int toRow)
if (-1 == endPos) {
mergeCellsVertically(table, cellOrRow, startPos + lineNumber + titleCount,
detailDatas.size() + lineNumber + titleCount - 1);
} else {
mergeCellsVertically(table, cellOrRow, startPos + lineNumber + titleCount, endPos + lineNumber + titleCount - 1);
}
}
}
return false;
}
/**
* 更新文本详情
*
* @param cell
* @param textMap
*/
public void updateDetailText(XWPFTableCell cell, HashMap<String, Object> textMap) {
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
CommonWord.joinRuns(paragraph);
if (run.toString().contains("[&")) {
Object ob = CommonWord.changeValue(run.toString(), textMap);
if (ob instanceof String || ob instanceof Integer || ob instanceof Date) {
if (ob instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
ob = sdf.format(ob);
}
String obj = String.valueOf(ob);
if (obj.contains("$*$")) {
String[] split = obj.split("\\$\\*\\$");
run.setText(split[0], 0);
for (int i = 1; i < split.length; i++) {
run.addBreak();
run.setText(split[i]);
}
} else {
run.setText(obj, 0);
}
// run.setText(String.valueOf(ob), 0);
} else {
run.setText("", 0);
}
}
}
}
}
/**
* word跨行并单元格
*
* @param table
* @param col
* @param fromRow
* @param toRow
*/
public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
if (rowIndex == fromRow) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
}
}
/**
* pdf页数
*
* @param document
* @param data
* @param type
* @param wordPages
* @return
*/
public int changeTablePages(XWPFDocument document, JSONObject data, String type, int wordPages) {
int pages = wordPages;
if (data.containsKey("pages")) {
if (data.getInteger("pages") != null) {
pages = wordPages + data.getInteger("pages");
data.put("pages", wordPages + data.getInteger("pages"));
} else {
data.put("pages", wordPages);
}
}
// 获取文件的表格
List<XWPFTable> tableList = document.getTables();
for (int i = 0; i < tableList.size(); i++) {
XWPFTable table = tableList.get(i);
// 循环所有行
}
return pages;
}
}
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