1

再会。

我必须生成包含许多数学公式的 docx 或 odt 文件。我尝试在 Apashe POI 和 ODFtoolkit 中找到解决方案,但我无法做到。谷歌没有帮助。(

可能有人可以帮助我解决此任务吗?(有什么例子吗?)

谢谢。

4

2 回答 2

3

您可以使用docx4j库。这是入门文档。

我建议您首先创建一个模板文件,其中包含所有格式和尽可能多的结构。然后你应该把内容控件放在你想要你的文本去的地方。内容控件可以包含其他内容,您可以使用这些内容来重复某些常见结构。

在 Word 中,可以在主功能区的“开发人员”选项卡中找到“内容控件”。它们被命名为富文本内容控件纯文本内容控件。不过,您可能需要先启用开发人员选项卡。在选项中,在自定义功能区下,选中开发人员

要更改内容控件的标记,请在页面上单击其句柄以将其选中,然后按功能区上的控件属性按钮。然后,您将看到一个对话框,您可以在其中设置标题和标签。

在 Java 中,内容控件将在对象模型中表示为SdtBlockSdtRun。处理模板时,应将其替换为所需的内容。

org.docx4j.math包包含用于创建数学公式的类。


这是一个例子:

import java.*;
import java.io.*;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.namespace.*;
import org.docx4j.wml.*;
import org.docx4j.math.*;
import org.docx4j.openpackaging.packages.*;
import org.docx4j.openpackaging.parts.WordprocessingML.*;

public class Processor
{
    public static void main(String[] args) throws Exception
    {
        File inFile = new File(args[0]);
        File outFile = new File(args[1]);

        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(inFile);
        MainDocumentPart mdp = wordMLPackage.getMainDocumentPart();

        Processor processor = new Processor();
        processor.processContent(mdp.getContent());

        wordMLPackage.save(outFile);
    }

    private Stack<String> tags = new Stack<String>();
    private void pushTag(String tag)
    {
        tags.push(tag);
    }
    private String getTag()
    {
        return tags.peek();
    }
    private void popTag()
    {
        tags.pop();
    }

    private static final org.docx4j.wml.ObjectFactory wmlFactory = new org.docx4j.wml.ObjectFactory();
    private static final org.docx4j.math.ObjectFactory mathFactory = new org.docx4j.math.ObjectFactory();

    public void processContent(List<Object> content)
    {
        for (Object child : content)
        {
            if (child instanceof SdtBlock)
            {
                processBlock((SdtBlock) child);
            }
            else if (child instanceof P)
            {
                processP((P) child);
            }
            else if (child instanceof JAXBElement)
            {
                JAXBElement<?> elem = (JAXBElement<?>) child;
                Class<?> elemType = elem.getDeclaredType();
                if (elemType.equals(CTOMath.class))
                {
                    processOMath((CTOMath) elem.getValue());
                }
            }
        }
    }

    public void processP(P p)
    {
        processContent(p.getContent());
    }

    public void processBlock(SdtBlock block)
    {
        String tag = block.getSdtPr().getTag().getVal();
        pushTag(tag);
        processContent(block.getSdtContent().getContent());
        popTag();
    }

    public void processOMath(CTOMath oMath)
    {
        String tag = getTag(); // tag of innermost <w:sdt>
        if (getTag().equals("MyEquation"))
        {
            List<Object> content = oMath.getEGOMathElements();
            content.clear();

            content.add(makeRun("A=\u03c0"));

            content.add(makeSSup(makeRun("r"), makeRun("2")));
        }
    }

    private JAXBElement<CTR> makeRun(String text)
    {
        // <m:r>
        CTR run = mathFactory.createCTR();
        List<Object> content = run.getContent();

        // <w:rPr><w:rFonts>
        RPr pr = wmlFactory.createRPr();
        RFonts rFonts = wmlFactory.createRFonts();
        rFonts.setAscii("Cambria Math");
        rFonts.setHAnsi("Cambria Math");
        pr.setRFonts(rFonts);
        content.add(wmlFactory.createSdtPrRPr(pr));

        // <m:t>
        CTText ctText = mathFactory.createCTText();
        ctText.setValue(text);
        content.add(mathFactory.createCTRTMath(ctText));

        return mathFactory.createCTOMathArgR(run);
    }

    private JAXBElement<CTSSup> makeSSup(Object expr, Object exp)
    {
        // <m:ssup>
        CTSSup ssup = mathFactory.createCTSSup();

        // <m:e>
        CTOMathArg eArg = mathFactory.createCTOMathArg();
        eArg.getEGOMathElements().add(expr);
        ssup.setE(eArg);

        // <m:sup>
        CTOMathArg supArg = mathFactory.createCTOMathArg();
        supArg.getEGOMathElements().add(exp);
        ssup.setSup(supArg);

        return mathFactory.createCTOMathArgSSup(ssup);
    }
}

它将查找名为“MyEquation”的块级内容控件,并将其中的数学表达式替换为.A=πr2

具体来说,它将寻找

<w:sdt>
    <w:sdtPr>
        <w:tag w:val="MyEquation"/>
    </w:sdtPr>
    <w:sdtContent>
        <w:p>
            <m:oMath>
            </m:oMath>
        </w:p>
    </w:sdtContent>
</w:sdt>

并将其替换为

<w:p>
    <m:oMath>
        <m:r>
            <w:rPr>
                <w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
            </w:rPr>
            <m:t>A=π</m:t>
        </m:r>
        <m:sSup>
            <m:sSupPr>
                <m:ctrlPr>
                    <w:rPr>
                        <w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
                    </w:rPr>
                </m:ctrlPr>
            </m:sSupPr>
            <m:e>
                <m:r>
                    <w:rPr>
                        <w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
                    </w:rPr>
                    <m:t>r</m:t>
                </m:r>
            </m:e>
            <m:sup>
                <m:r>
                    <w:rPr>
                        <w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
                    </w:rPr>
                    <m:t>2</m:t>
                </m:r>
            </m:sup>
        </m:sSup>
    </m:oMath>
</w:p>

您可以在 Word 中制作方程式,然后查看 docx 文件。它们以 zip 文件的形式存储,其中包含大量 XML。具体来说,您要查看word/document.xml文件。

于 2013-05-28T06:29:29.063 回答
0

您也可以使用 Fmath 库生成 OOXML 代码,然后通过 doc4j 库将其推送到 docx 文件。

这里有一些很好的例子。

http://www.fmath.info/java/latex-mathml-converter/

于 2016-02-28T08:21:52.867 回答