Java word模板以及填充数据

使用的技术:

poi tl : http://deepoove.com/poi-tl/#_why_poi_tl  (数据填充)

poi : http://deepoove.com/poi-tl/apache-poi-guide.html (数据读取)

选择此技术的原因

  • 属于动态数据,数据也不相同、比如:出口订单的模板打印、报关单的合同打印
  • 自定义模板,可以让用户自定义模板,用来显示打印的数据
  • 最开始使用的是 : vue-plugin-hiprint  (后面因模板较复杂,重新调研数据)
    https://ccsimple.gitee.io/vue-plugin-hiprint/
  • 选择了word模板打印了之后,开始调研技术,选了poi-tl,查看了资料以及自己做demo后觉着这个技术还可以

 

遇到的问题:

  1. 最开始的时候可以实现基础数据打印了,图片也可以,问题是图片大小不能调整
    解决办法:
    扩展标签:如 原始的标签为{{@aa}}  将这个标签更改为 {{@aa_150_250}}
    获取到{{@}} 格式的数据  如果没有_150_250类似的数据,不管 如果存在,则在后台对象封装是 增加一个属性 aa_150_250(通过jsonObject) 动态增加属性
  2. 实现了图片自定义大小,模板还是会有问题,位置不能固定,导致模板还不是想要的数据
    解决方案:使用pot-tl中的引用标签信息

    设置图片中的可选文字(Microsoft Office 图片右键即可设置  wps找了半天没有找到) 
    找到之后 后台对应的数据调整一下即可

  3. 表格中使用除表格之外的数据
    比如 订单中存在币别 订单产品中没有币别 模板打印的时候 需要在产品中打印出币别 目前是不支持的  
    解决方案是: 在订单的产品中 冗余币别信息 用于模板打印
  4. 循环获取集合数据(非表格),正常循环
    {{?array}}
      名字{{name}}
    {{/array}}
    

      

 Java poi 获取图片的可选文字代码:

private void readImageInfo(String filepath) throws IOException, InvalidFormatException {
        XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
        for (XWPFParagraph paragraph : doc.getParagraphs()) {
            for (XWPFRun run : paragraph.getRuns()) {
                for (XWPFPicture embeddedPicture : run.getEmbeddedPictures()) {
                    System.out.println(embeddedPicture.getDescription());
                }
            }
        }

        List<XWPFPictureData> allPictures = doc.getAllPictures();
    }

  

附上部分关键性代码:

    @Autowired
    private SysRuleBillService sysRuleBillService;

    @Autowired
    private WmsDeclarationContractService wmsDeclarationContractService;

    @Autowired
    private SysOrganizationService sysOrganizationService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SecurityUserInfoService securityUserInfoService;

    private static Long orgId = 1760164245476425728L;

    private static Long id = 1760233880706789377L;

    private static Long tenantId = 1760164244302020608L;

    @Test
    public void test() throws Exception {

        setLoginUser();

        PrintModel printData = wmsDeclarationContractService.getPrintData(id);
        JSONObject bus = new JSONObject();
        bus.put("contract", printData);

        // 获取列表数据
        List<String> listProperties = Lists.newArrayList();
        getListProperties(bus, StringUtils.EMPTY, listProperties);

        // 流获取
//        java.net.URL url = new java.net.URL("http://192.168.0.210:9000/huake-erp/1760164244302020608/1760164245476425728/PUBLIC_DOCUMENTS/1765359074774605825_safekeeping_contract.docx");
//        URLConnection con = url.openConnection();
//        InputStream inputStream = con.getInputStream();
//        InputStreamCache streamCache = new InputStreamCache(inputStream);
        // 获取图片大小
//        String sourceContext = readByExtractor(streamCache.getInputStream());


        // 文件获取
        String filepath = this.getClass().getClassLoader().getResource("wordtemplates/safekeeping_contract.docx").getPath();
        String sourceContext = readByFileExtractor(filepath);



        List<ImageInfo> imageInfoList = getImages(sourceContext);
//        List<ImageInfo> imageInfoList = Lists.newArrayList();
        if (CollUtil.isNotEmpty(imageInfoList)) {
            getImagesProperties(bus, "", imageInfoList);
        }

        Map map = JSONObject.parseObject(JSONObject.toJSONString(bus), Map.class);

        PrintModel model = new PrintModel();
        model.setPrintOrgId(orgId);
        Object printData1 = sysOrganizationService.getPrintData(model);
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(printData1));
        if (CollUtil.isNotEmpty(imageInfoList)) {
            getImagesProperties(jsonObject, "commonCompany", imageInfoList);
        }


        List<ImageInfo> pictureInfoList = getPictureImageInfo(filepath);
        if (CollUtil.isNotEmpty(pictureInfoList)) {
            getPictureImageProperties(jsonObject, "commonCompany", pictureInfoList);
        }

        JSONObject object = new JSONObject();
        object.put("commonCompany", jsonObject);
        map.putAll(object);



        log.info("传递的参数:{}", JSON.toJSONString(map));

        ConfigureBuilder builder = Configure.builder();
        if (CollUtil.isNotEmpty(listProperties)) {
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
            for (String property : listProperties) {
                builder.bind(property, policy);
            }
        }
        Configure configure = builder.build();
        // 流
//        XWPFTemplate template = XWPFTemplate.compile(streamCache.getInputStream(), configure).render(map);
////        输出到流
//        String file="D:\\safekeeping_contract.doc";
//        template.writeAndClose(new FileOutputStream(file));
//        if (streamCache != null) {
//            streamCache.destroyCache();
//        }

        // 文件
        XWPFTemplate template = XWPFTemplate.compile(filepath, configure).render(map);
//        输出到流
        String file="D:\\safekeeping_contract.doc";
        template.writeAndClose(new FileOutputStream(file));
        clearLoginUser();
    }

    private List<ImageInfo> getPictureImageInfo(String filepath) {
        List<ImageInfo> result = Lists.newArrayList();
        Pattern P = Pattern.compile("\\{\\{[^}]*}}");
        try {
            XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
            for (XWPFParagraph paragraph : doc.getParagraphs()) {
                for (XWPFRun run : paragraph.getRuns()) {
                    for (XWPFPicture embeddedPicture : run.getEmbeddedPictures()) {
                        Matcher matcher = P.matcher(embeddedPicture.getDescription());
                        while (matcher.find()) {
                            String source = matcher.group();
                            ImageInfo imageInfo = new ImageInfo();
                            imageInfo.setSource(source);
                            imageInfo.setImageField(getPictureImageField(imageInfo.getSource()));
                            imageInfo.setFiled(getField(imageInfo.getSource()));
                            result.add(imageInfo);
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    public List<ImageInfo> getImages(String content) {
        List<ImageInfo> result = Lists.newArrayList();
        Pattern P = Pattern.compile("\\{\\{@[^}]*}}");
        Matcher matcher = P.matcher(content);
        while (matcher.find()) {
            ImageInfo imageInfo = new ImageInfo();
            imageInfo.setSource(matcher.group());
            imageInfo.setImageField(getImageField(imageInfo.getSource()));
            imageInfo.setFiled(getField(imageInfo.getSource()));
            result.add(imageInfo);
        }
        return result;
    }

    private String getField(String source) {
        Pattern p = Pattern.compile("\\{\\{[@]?(.*)}}");
        Matcher matcher = p.matcher(source);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    private String getImageField(String source) {
        Pattern p = Pattern.compile("\\{\\{@([^_]*)(_)?.*}}");
        Matcher matcher = p.matcher(source);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    private String getPictureImageField(String source) {
        Pattern p = Pattern.compile("\\{\\{([^_]*)(_)?.*}}");
        Matcher matcher = p.matcher(source);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    private void getListProperties(Object bus, String prefix, List<String> listProperties) {
        String jsonString = JSONObject.toJSONString(bus);

        if (JSON.isValidArray(jsonString)) {
            JSONArray array = JSONArray.parseArray(jsonString);
            listProperties.add(prefix);
            getListProperties(array.get(0), prefix, listProperties);
        }

        if (JSON.isValidObject(jsonString)) {
            JSONObject parse = JSONObject.parse(jsonString);
            for (Map.Entry<String, Object> entry : parse.entrySet()) {
                String newPrefix = getPrefix(prefix, entry.getKey());
                getListProperties(entry.getValue(), newPrefix, listProperties);
            }
        }
    }

    /**
     * 设置新的前缀
     *
     * @param prefix 前缀
     * @param key    新的key
     * @return 新的前缀
     */
    private String getPrefix(String prefix, String key) {
        if (StringUtils.isBlank(prefix)) {
            return key;
        }
        return String.join(".", prefix, key);
    }


    private void getImagesProperties(JSONObject vo, String prefix,
                                     List<ImageInfo> imageInfos) throws IOException {
        String jsonString = JSONObject.toJSONString(vo);

        if (JSON.isValidArray(jsonString)) {
            JSONArray array = JSONArray.parseArray(jsonString);
            getImagesProperties((JSONObject) array.get(0), prefix, imageInfos);
        }

        if (JSON.isValidObject(jsonString)) {
            JSONObject parse = JSONObject.parse(jsonString);
            for (Map.Entry<String, Object> entry : parse.entrySet()) {
                String newPrefix = getPrefix(prefix, entry.getKey());

                for (ImageInfo imageInfo : imageInfos) {
                    if (!StringUtils.equals(imageInfo.getImageField(), newPrefix)) {
                        continue;
                    }
                    imageInfo.setImagePath((String) entry.getValue());
                    if (!StringUtils.equals(imageInfo.getFiled(), imageInfo.getImageField())) {
                        String newFiled = imageInfo.getFiled().substring(imageInfo.getFiled().lastIndexOf(".") + 1);
                        String[] split = newFiled.split("_");
                        if (split.length != 3) {
                            continue;
                        }
                        vo.put(newFiled, Pictures.ofUrl(imageInfo.getImagePath(), PictureType.PNG)
                                .size(Integer.parseInt(split[1]), Integer.parseInt(split[2]))
                                .create());
                    }
                }
                if (entry.getValue() instanceof JSONObject) {
                    getImagesProperties((JSONObject) entry.getValue(), newPrefix, imageInfos);
                }
            }
        }
    }

    private void getPictureImageProperties(JSONObject vo, String prefix, List<ImageInfo> imageInfos) {
        String jsonString = JSONObject.toJSONString(vo);

        if (JSON.isValidArray(jsonString)) {
            JSONArray array = JSONArray.parseArray(jsonString);
            getPictureImageProperties((JSONObject) array.get(0), prefix, imageInfos);
        }

        if (JSON.isValidObject(jsonString)) {
            JSONObject parse = JSONObject.parse(jsonString);
            for (Map.Entry<String, Object> entry : parse.entrySet()) {
                String newPrefix = getPrefix(prefix, entry.getKey());

                for (ImageInfo imageInfo : imageInfos) {
                    if (!StringUtils.equals(imageInfo.getImageField(), newPrefix)) {
                        continue;
                    }
                    imageInfo.setImagePath((String) entry.getValue());
                    if (!StringUtils.equals(imageInfo.getFiled(), imageInfo.getImageField())) {
                        String newFiled = imageInfo.getFiled().substring(imageInfo.getFiled().lastIndexOf(".") + 1);
                        String[] split = newFiled.split("_");
                        if (split.length != 3) {
                            continue;
                        }
                        vo.put(newFiled, Pictures.ofUrl(imageInfo.getImagePath(), PictureType.PNG)
                                .size(Integer.parseInt(split[1]), Integer.parseInt(split[2]))
                                .create());
                    } else {
                        vo.put(entry.getKey(), Pictures.ofUrl(imageInfo.getImagePath()).create());
                    }
                }
                if (entry.getValue() instanceof JSONObject) {
                    getPictureImageProperties((JSONObject) entry.getValue(), newPrefix, imageInfos);
                }
            }
        }
    }

    /**
     * 通过XWPFWordExtractor访问XWPFDocument的内容
     * @throws Exception
     */
    public String readByExtractor(InputStream is) throws Exception {
        XWPFDocument doc = new XWPFDocument(is);
        XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
        String text = extractor.getText();
//        List<String> result = Lists.newArrayList();
//        result.add(text);
        /**
         * 打印文档信息
         */
//        POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
//        printCoreProperties(coreProps);
//        close(is);
        return text;
    }

    private String readByFileExtractor(String filepath) throws IOException {
        XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
        XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
        String text = extractor.getText();
//        List<String> result = Lists.newArrayList();
//        result.add(text);
        /**
         * 打印文档信息
         */
//        POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
//        printCoreProperties(coreProps);
//        close(is);
        return text;
    }
//    /**
//     * 通过XWPFWordExtractor访问XWPFDocument的内容
//     * @throws Exception
//     */
//    public String readByExtractor(String path) throws Exception {
//        InputStream is = new FileInputStream(path);
//        XWPFDocument doc = new XWPFDocument(is);
//        XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
//        String text = extractor.getText();
////        List<String> result = Lists.newArrayList();
////        result.add(text);
//        /**
//         * 打印文档信息
//         */
////        POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
////        printCoreProperties(coreProps);
//        close(is);
//        return text;
//    }

    /**
     * 关闭输入流
     * @param is
     */
    private void close(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    private void clearLoginUser() {
        HuakeSecurityContextHolder.clearContext();
    }

    private void setLoginUser() {

        List<Long> userIds = sysUserService.getBaseMapper().selectIngoreLoginUserList();
        List<SecurityUserInfo> securityUserInfos = securityUserInfoService.getSecurityUserByUserIds(Sets.newHashSet(userIds));
        if (CollUtil.isEmpty(securityUserInfos)) {
            return;
        }
        SecurityUserInfo securityUserInfo = securityUserInfos.get(NumberConstants.ZERO);

        securityUserInfo.setDefaultOrgId(orgId);
        securityUserInfo.setTenantId(tenantId);
        HuakeSecurityContextHolder.setContext(securityUserInfo);
        Thread.currentThread().setName("MAIL_VIR_POOL_CRMJOB");
    }

  

 

 
posted @ 2025-05-27 08:49  译林  阅读(79)  评论(0)    收藏  举报