POI操作word文档-添加上标下标

本文介绍了如何在Java后端使用Easypoi库处理Word模板时,针对特定文本(如上标)进行格式转换。通过识别并替换特殊语法,然后利用Apache POI的接口设置上标格式,成功解决了前端数据传递限制导致的格式不符问题。详细步骤包括文本处理、段落遍历、内容解析和自定义语法解析,确保导出的Word文档符合预期格式。
摘要由CSDN通过智能技术生成

背景:

接了新需求,前端提供一个大概的word模板,包含通用信息,用户在前端填写可修改内容至模板完善,然后将整个数据传递给后端进行保存,后端提供导出word的功能。

数据中包含1.37m^{-1}这种类型,由于前端输出框不是富文本编辑框所以无法填写。最终传递到后端的数据格式是1.37m-1,如此一来在导出word的时候格式就变得不符合预期。

现在代码中导出word使用的库是easypoi,easypoi仅仅提供了,指定项目路径下的word文档模板,然后在其中添加占位符,再通过代码设置key-value的方式给其赋值。没有提供特殊文本的处理方法,所以只能设置数据,无法添加上标。但是easypoi本质是通过继承对poi实现了封装,其对象仍然具备poi对象的方法。所以可以使用poi的接口设置这种文本。

解决过程:

1.在接口导出数据到word的时候,硬编码识别m-1这个特殊字符,然后在其前后添加自定义语法,后续可通过该自定义语法针对性的对一些特殊的格式进行处理。这里的m代表的普通字符,后面的{[和]}框起来的内容代表需要解析的内容,:前的SUPERSCRIPT代表上标的意思,:后的-1代表上标的值

"m{[SUPERSCRIPT:-1]}"

String[] split = fifthRecord.split("m-1");
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
    if (i != split.length - 1){
        stringBuilder.append(split[i]).append("m{[SUPERSCRIPT:-1]}");
    } else {
        stringBuilder.append(split[i]);
    }
}

例如:
fifthRecord="光吸收系数为1.37m-1"
stringBuilder="光吸收系数为1.37m{[SUPERSCRIPT:-1]}"

 2.

判断文本是否包含需要解析的文本,如果包含的话,进行特殊处理,

XWPFParagraph对象是对应poi每个段落的对象,包含一段文字,表格的格式和内容。
 private static final String START_STR = "{[";


    public static void parseParagraph(XWPFParagraph paragraph) {

        List<XWPFRun> runs = paragraph.getRuns();
        List<XWPFRun> copyRuns = new ArrayList<>(runs);
        for (int i = 0; i < copyRuns.size(); i++) {
            XWPFRun v = copyRuns.get(i);
            String text = v.getText(0);
            if (text.contains(START_STR)) {
                ArrayList<String> strings = parseContent(text);
                paragraph.removeRun(i);
                strings.forEach(s -> {
                    if (s.contains(START_STR)) {
                        XWPFRun run = paragraph.createRun();
                        parseSubscript(s, run, 16);
                    } else {
                        XWPFRun paragraphOneRunTwo = paragraph.createRun();
                        paragraphOneRunTwo.setFontSize(16);
                        paragraphOneRunTwo.setBold(false);
                        paragraphOneRunTwo.setText(s);
                        paragraphOneRunTwo.setUnderline(UnderlinePatterns.SINGLE);
                        paragraphOneRunTwo.setFontFamily("仿宋");
                    }
                });
            }
        }
    }

3.识别{[符号,并切分,例如
content="光吸收系数为1.37m{[SUPERSCRIPT:-1]}"
return=["光吸收系数为1.37m","{[SUPERSCRIPT:-1]}"]

这样我们就可以单独处理这个上标-1

public static ArrayList<String> parseContent(String content) {

        int length = content.length();
        ArrayList<String> strings = new ArrayList<>();

        int startIndex = 0;
        for (int i = 0; i < length - 1; i++) {
            char c1 = content.charAt(i);
            char c2 = content.charAt(i + 1);
            if (c1 == '{' && c2 == '[') {
                if (i != 0) {
                    strings.add(content.substring(startIndex, i));
                    startIndex = i;
                }
            }
            if (c1 == ']' && c2 == '}') {
                strings.add(content.substring(startIndex, i + 2));
                startIndex = i + 2;
            }
            if (i == length - 2 && startIndex != i + 2) {
                strings.add(content.substring(startIndex, i + 1));
            }
        }
        return strings;
    }
例如
content="光吸收系数为1.37m{[SUPERSCRIPT:-1]}"
return=["光吸收系数为1.37m","{[SUPERSCRIPT:-1]}"]

4.最终解析自定义的语法并通过poi的方法添加一个上标或者下标的文本,当然这里只是用到了上标和下标,可以使用类似的方式,去做更多的自定义格式的处理。

 public static XWPFRun parseSubscript(String msg, XWPFRun xwpfRun, Integer fontSize) {
        String substring = msg.substring(2, msg.length() - 2);
        String[] split = substring.split(":");
        if (split[0].equals(VerticalAlign.SUPERSCRIPT.toString())) {
            xwpfRun.setFontSize(fontSize);
            xwpfRun.setBold(false);
            xwpfRun.setSubscript(VerticalAlign.SUPERSCRIPT);
            xwpfRun.setText(split[1]);
            xwpfRun.setUnderline(UnderlinePatterns.SINGLE);
            xwpfRun.setFontFamily("仿宋");
            return xwpfRun;
        }
        if (split[0].equals(VerticalAlign.SUBSCRIPT.toString())) {
            xwpfRun.setFontSize(fontSize);
            xwpfRun.setBold(false);
            xwpfRun.setSubscript(VerticalAlign.SUBSCRIPT);
            xwpfRun.setText(split[1]);
            xwpfRun.setUnderline(UnderlinePatterns.SINGLE);
            xwpfRun.setFontFamily("仿宋");
            return xwpfRun;
        }
        return null;
    }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值