【问题标题】:How generate docx/odt file with math formulas from java如何使用 java 中的数学公式生成 docx/odt 文件
【发布时间】:2013-05-28 06:04:15
【问题描述】:

美好的一天。

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

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

谢谢。

【问题讨论】:

  • 我想它会帮助你,见 [THIS][1] [1]: stackoverflow.com/questions/1222951/…
  • 感谢您的回答。你是说开放式办公室UNO?我也无法找到如何在 OO UNO 中创建数学公式的信息。 (((

标签: java math docx formulas odt


【解决方案1】:

您可以使用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=πr<sup>2</sup>

具体来说,它会寻找

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

【讨论】:

  • 我正在阅读 docx4j 手册。添加文本和表格非常容易。但我找不到任何示例如何将 docx 对象添加到文档中。我尝试了 org.docx4j.math 类,但我没有成功。也许你可以给我一些添加简单公式对象到文档的例子?
  • 感谢您的示例!你能说我如何像你的例子一样添加到 docx 模板文件内容控件吗?在功能区一词中,我只看到指定的内容控件(图片、文本、格式化文本...),但我可以找到这样我可以设置名称。 (
  • 感谢您的帮助!我使用一个内容控件创建 docx 文件并将其提供给您的代码。执行后我得到了没有任何公式的相同文件。这是 document.xml 文件的代码:link。这是我的测试 docx 文件的链接:link
  • 我的测试文档中已经有一个空的数学方程。代码只是改变了它所说的内容。 &lt;w:sdt&gt;&lt;w:sdtContent&gt;&lt;w:p&gt;&lt;m:oMath&gt;。如果需要,您可以更改代码以实际创建 &lt;w:p&gt;&lt;m:oMath&gt;。但我建议在模板文件中创建尽可能多的结构。
  • 我明白我的错误。我应该添加到 word 文档富文本内容控件(不是平面文本),设置指定标签名称并将任何数学公式对象添加到此内容控件。在这种情况下,您的代码可以正常工作。谢谢你的好例子和评论!!!你很棒!!! :)
【解决方案2】:

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

这里有一些很好的例子。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 2023-02-25
    • 2019-12-01
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多