基于word模板打印word原创
金蝶云社区-Lento
Lento
0人赞赏了该文章 67次浏览 未经作者许可,禁止转载编辑于2024年07月05日 10:07:54

这个代理里面的内容,大部分是我通过和chatGPT生成的,我验证了一下,基本的功能还是没问题,能写入图片,替换变量这种。
模板在附件中

package digi.alm.plugin.prjimportexport;

import digi.alm.orm.util.AlmBusinessDataServiceHelper;
import kd.bos.cache.CacheFactory;
import kd.bos.cache.TempFileCache;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.datamodel.ListSelectedRow;
import kd.bos.entity.datamodel.ListSelectedRowCollection;
import kd.bos.exception.KDException;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.form.control.events.ItemClickEvent;
import kd.bos.list.IListView;
import kd.bos.list.plugin.AbstractListPlugin;
import lombok.SneakyThrows;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WordExportListPlugin extends AbstractListPlugin {
    /**
     * 列表菜单点击事件
     *
     * @param evt
     */
    @SneakyThrows
    @Override
    public void itemClick(ItemClickEvent evt) {
        super.itemClick(evt);
        IListView listView = (IListView) this.getView();
        ListSelectedRowCollection selectedRows = listView.getSelectedRows();
        if (StringUtils.equals("digi_baritemap", evt.getItemKey())) {
            if (selectedRows.size() > 0) {
                ListSelectedRow selectedRow = selectedRows.get(0);
                Object contractId = selectedRow.getPrimaryKeyValue();
                DynamicObject loadOptional = AlmBusinessDataServiceHelper.loadSingle(contractId, "digi_lwt_test");
                // 导出对应的报告
                String url = annualReportWord(loadOptional);
                // 下载
                getView().download(url);
            }
        }
    }

    public static String annualReportWord(DynamicObject dynamicObject) {
        String path = "D:\\PROJECT\\DIGI\\digi-project\\src\\main\\java\\digi\\alm\\plugin\\prjimportexport\\template.docx";

        try (FileInputStream is = new FileInputStream(path);
             XWPFDocument doc = new XWPFDocument(is)) {
            //部建一/wond/的
            replaceWord(doc, dynamicObject);
            // 输出相对路径,和绝对路径
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            doc.write(outputStream);
            //reportword方法里面是组装数据,可以视情况而定
            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

            TempFileCache tfc = CacheFactory.getCommonCacheFactory().getTempFileCache();
            // 设置临时文件有效时间
            return tfc.saveAsUrl("fileName.docx", inputStream, 60 * 60 * 2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new KDException("word棋板文档读取有误,请联系管理员");
        } catch (IOException e) {
            e.printStackTrace();
            throw new KDException("word文档导出失败,请联系管理员");
        }
    }


    public static void replaceWord(XWPFDocument document, DynamicObject dynamicObject) {
        // 定义正则表达式来匹配${variable}模式
        Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}");

        // 处理段落中的变量替换
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            replaceInParagraph(paragraph, pattern, dynamicObject);
        }

        // 处理表格中的变量替换
        for (XWPFTable table : document.getTables()) {
            table.setCellMargins(0,0,0,1);
            processTable(table, dynamicObject);
        }

    }

    /**
     * 在段落中替换变量
     *
     * @param paragraph     要处理的段落
     * @param pattern       匹配${variable}的正则表达式
     * @param dynamicObject 包含变量及其替换值
     */
    private static void replaceInParagraph(XWPFParagraph paragraph, Pattern pattern, DynamicObject dynamicObject) {
        // 连接段落中的所有run文本
        StringBuilder paragraphText = new StringBuilder();
        for (XWPFRun run : paragraph.getRuns()) {
            paragraphText.append(run.getText(0));
        }

        // 使用正则表达式找到并替换所有的占位符
        Matcher matcher = pattern.matcher(paragraphText.toString());
        StringBuffer stringBuffer = new StringBuffer();
        while (matcher.find()) {
            String variable = matcher.group(1);
            String replacement = dynamicObject.getString(variable);
            if (replacement != null) {
                matcher.appendReplacement(stringBuffer, replacement);
            }
        }
        matcher.appendTail(stringBuffer);

        // 获取替换后的文本
        String replacedText = stringBuffer.toString();
        int pos = 0;

        // 按照run的长度分割替换后的文本,并重新设置回段落中,同时保留格式
        for (XWPFRun run : paragraph.getRuns()) {
            String runText = run.getText(0);
            if (runText != null) {
                int runLength = runText.length();
                if (pos + runLength <= replacedText.length()) {
                    // 设置当前run的文本为替换后的相应部分
                    run.setText(replacedText.substring(pos, pos + runLength), 0);
                    pos += runLength;
                } else {
                    // 设置当前run的文本为替换后的剩余部分
                    run.setText(replacedText.substring(pos), 0);
                    pos = replacedText.length();
                }
            }
        }

        // 如果替换后的文本比原始run文本长,创建一个新的run来保存剩余的文本
        if (pos < replacedText.length()) {
            XWPFRun newRun = paragraph.createRun();
            newRun.setText(replacedText.substring(pos));
        }
    }

    /**
     * 处理表格中的变量替换
     *
     * @param table 要处理的表格
     * @param dynamicObject 包含变量及其替换值的JSONObject
     */
    private static void processTable(XWPFTable table, DynamicObject dynamicObject) {
        DynamicObjectCollection dyEntry = dynamicObject.getDynamicObjectCollection("digi_lwt_entry");

        int initialRowCount = table.getNumberOfRows();

        for (int i = 0; i < dyEntry.size(); i++) {
            DynamicObject entry = dyEntry.get(i);

            XWPFTableRow textRow;
            XWPFTableRow imageRow;

            // 动态增加行
            if (i >= initialRowCount / 2) {
                textRow = table.createRow();
                imageRow = table.createRow();
            } else {
                textRow = table.getRow(i * 2);
                imageRow = table.getRow(i * 2 + 1);
            }

            // 填充第一列的数据
            XWPFTableCell textCell1 = textRow.getCell(0);
            XWPFTableCell imageCell1 = imageRow.getCell(0);

            if (textCell1 == null) {
                textCell1 = textRow.createCell();
            }
            if (imageCell1 == null) {
                imageCell1 = imageRow.createCell();
            }

            replaceTextInParagraph(textCell1.getParagraphArray(0), entry.getString("digi_textfield"));
            insertImage(imageCell1.getParagraphArray(0).createRun(), entry.getString("digi_picturefield"));

            // 填充第二列的数据,确保不重复
            if ((i + 1) < dyEntry.size()) {
                DynamicObject nextEntry = dyEntry.get(i + 1);

                XWPFTableCell textCell2 = textRow.getCell(1);
                XWPFTableCell imageCell2 = imageRow.getCell(1);

                if (textCell2 == null) {
                    textCell2 = textRow.createCell();
                }
                if (imageCell2 == null) {
                    imageCell2 = imageRow.createCell();
                }

                replaceTextInParagraph(textCell2.getParagraphArray(0), nextEntry.getString("digi_textfield"));
                insertImage(imageCell2.getParagraphArray(0).createRun(), nextEntry.getString("digi_picturefield"));

                i++; // 跳过已处理的下一行数据
            }
        }
    }

    /**
     * 在段落中替换文本内容
     *
     * @param paragraph 要处理的段落
     * @param text 要替换的文本内容
     */
    private static void replaceTextInParagraph(XWPFParagraph paragraph, String text) {
        List<XWPFRun> runs = paragraph.getRuns();
        if (runs.isEmpty()) {
            XWPFRun run = paragraph.createRun();
            run.setText(text);
        } else {
            runs.get(0).setText(text, 0);
            for (int i = 1; i < runs.size(); i++) {
                runs.get(i).setText("", 0);  // 清空多余的runs
            }
        }
    }

    /**
     * 在XWPFRun中插入图片
     *
     * @param run 需要插入图片的XWPFRun
     * @param imageUrl 图片路径
     */
    private static void insertImage(XWPFRun run, String imageUrl) {
        try {
            run.setText("");
            InputStream is = FileServiceFactory.getImageFileService().getInputStream(imageUrl);
            run.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, imageUrl, Units.toEMU(200), Units.toEMU(200)); // 插入图片,调整大小
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


template.docx(10.63KB)

赞 0