如何使用java中的数学公式生成docx / odt文件

时间:2013-05-28 06:04:15

标签: java math docx formulas odt

美好的一天。

我必须在内部使用许多数学公式生成docx或odt文件。 我试图在Apashe POI& amp; ODFtoolkit但我不能。 谷歌没有帮助。 (

任何人都可以帮我解决这个问题吗? (任何一个例子?)

感谢。

2 个答案:

答案 0 :(得分:3)

您可以使用docx4j库。以下是Getting started的文档。

我建议您首先创建一个模板文件,包含所有格式,以及尽可能多的结构。然后,您应该将内容控件放在您希望文本移动的位置。内容控件可以包含其他内容,您可以使用这些内容重复一些常见的结构。

在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文件。

答案 1 :(得分:0)

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

以下是一些很好的例子。

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