【问题标题】:Adding footnotes to a word document为word文档添加脚注
【发布时间】:2016-10-09 01:27:12
【问题描述】:

如何使用 Apache POI 在 word 文档 (.docx) 中添加脚注? I know how to retrieve footnotes already in the document,但我实际上无法添加更多内容。

【问题讨论】:

    标签: java apache-poi openxml


    【解决方案1】:

    我不确定这是否是向 Word 文档添加脚注的最佳方式,但它确实有效。在查看了使用word添加脚注的文档的Open XML后,我发现不仅需要脚注,而且段落内还需要引用,并且可选但强烈推荐三种样式。

    给文档添加脚注需要CTFtnEdn实例,可以使用CTFtnEdn.Factory.newInstance()来实现。现在要添加脚注的内容,我引用了使用 word 制作的脚注中的内容:

    <xml-fragment w:id="1" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
        <w:p w:rsidR="00B87AAC" w:rsidRDefault="00B87AAC">
            <w:pPr>
                <w:pStyle w:val="FootnoteText"/>
            </w:pPr>
            <w:r>
                <w:rPr>
                    <w:rStyle w:val="FootnoteReference"/>
                </w:rPr>
                <w:footnoteRef/>
            </w:r>
            <w:r>
                <w:t xml:space="preserve">Here is a Footnote</w:t>
            </w:r>
            <w:bookmarkStart w:id="0" w:name="_GoBack"/>
            <w:bookmarkEnd w:id="0"/>
        </w:p>
    </xml-fragment>
    

    这是一个使用 java 制作的例子:

    CTFtnEdn ctfInstance = CTFtnEdn.Factory.newInstance();
    
    BigInteger id = new BigInteger("1");
    
    ctfInstance.setId(id);
    
    CTP ctp = ctfInstance.addNewP();
    
    ctp.addNewPPr().addNewPStyle().setVal("FootnoteText");
    
    CTR ctr = ctp.addNewR();
    ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
    ctr.addNewFootnoteRef();
    
    CTText cttext = ctp.addNewR().addNewT();
    cttext.setStringValue("This is the text in the footnote");
    cttext.setSpace(SpaceAttribute.Space.PRESERVE);
    

    标签添加到CTFtnEdn 实例后,需要使用document.addFootnote() 将其添加到WMPFDocument

    现在添加对文档段落的引用 - 我不相信在没有引用的情况下甚至不会在页面底部看到脚注。供参考的 Open XML 如下所示:

    <w:r w:rsidR="00B87AAC">
        <w:rPr>
            <w:rStyle w:val="FootnoteReference"/>
        </w:rPr>
        <w:footnoteReference w:id="1"/>
    </w:r>
    

    这可以使用下面的代码在 java 中轻松完成:

    ctr = document.getParagraphArray(0).getCTP().addNewR();
    ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
    ctr.addNewFootnoteReference().setId(id);
    

    为了给脚注提供自己的带有上标的样式,需要添加三种样式。以下是所有三个的 Open XML:

    <w:style w:styleId="FootnoteReference" w:type="character">
        <w:name w:val="footnote reference"/>
        <w:basedOn w:val="DefaultParagraphFont"/>
        <w:uiPriority w:val="99"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
        <w:rPr>
          <w:vertAlign w:val="superscript"/>
        </w:rPr>
    </w:style>
    <w:style w:styleId="FootnoteText" w:type="paragraph">
        <w:name w:val="footnote text"/>
        <w:basedOn w:val="Normal"/>
        <w:link w:val="FootnoteTextChar"/>
        <w:uiPriority w:val="99"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
        <w:rPr>
            <w:sz w:val="20"/>
            <w:szCs w:val="20"/>
        </w:rPr>
    </w:style>
    <w:style w:customStyle="1" w:styleId="FootnoteTextChar" w:type="character">
        <w:name w:val="Footnote Text Char"/>
        <w:basedOn w:val="DefaultParagraphFont"/>
        <w:link w:val="FootnoteText"/>
        <w:uiPriority w:val="99"/>
        <w:semiHidden/>
        <w:rPr>
            <w:sz w:val="20"/>
            <w:szCs w:val="20"/>
        </w:rPr>
    </w:style>
    

    并在 java 中添加:

    CTStyle style = CTStyle.Factory.newInstance();
    style.setStyleId("FootnoteReference");
    style.setType(STStyleType.CHARACTER);
    style.addNewName().setVal("footnote reference");
    style.addNewBasedOn().setVal("DefaultParagraphFont");
    style.addNewUiPriority().setVal(new BigInteger("99"));
    style.addNewSemiHidden();
    style.addNewUnhideWhenUsed();
    style.addNewRPr().addNewVertAlign().setVal(STVerticalAlignRun.SUPERSCRIPT);
    
    document.getStyles().addStyle(new XWPFStyle(style));
    
    style = CTStyle.Factory.newInstance();
    style.setType(STStyleType.PARAGRAPH);
    style.setStyleId("FootnoteText");
    style.addNewName().setVal("footnote text");
    style.addNewBasedOn().setVal("Normal");
    style.addNewLink().setVal("FootnoteTextChar");
    style.addNewUiPriority().setVal(new BigInteger("99"));
    style.addNewSemiHidden();
    style.addNewUnhideWhenUsed();
    CTRPr rpr = style.addNewRPr();
    rpr.addNewSz().setVal(new BigInteger("20"));
    rpr.addNewSzCs().setVal(new BigInteger("20"));
    
    document.getStyles().addStyle(new XWPFStyle(style));
    
    style  = CTStyle.Factory.newInstance();
    style.setCustomStyle(STOnOff.X_1);
    style.setStyleId("FootnoteTextChar");
    style.setType(STStyleType.CHARACTER);
    style.addNewName().setVal("Footnote Text Char");
    style.addNewBasedOn().setVal("DefaultParagraphFont");
    style.addNewLink().setVal("FootnoteText");
    style.addNewUiPriority().setVal(new BigInteger("99"));
    style.addNewSemiHidden();
    rpr = style.addNewRPr();
    rpr.addNewSz().setVal(new BigInteger("20"));
    rpr.addNewSzCs().setVal(new BigInteger("20"));
    
    document.getStyles().addStyle(new XWPFStyle(style));
    

    请注意,document.getStyles().addStyle(new XWPFStyle(style)) 用于向文档添加新样式。

    这里是SSCCE(一定要在最后更改输出路径):

    public static void main(String[] args) throws FileNotFoundException, IOException, XmlException{
        // create doc
        XWPFDocument document = new XWPFDocument();
    
        // some sample text
        document.createParagraph().createRun().setText("This is a Test.");
    
        // check to add footnotes in case of empty
        if (document.getFootnotes().isEmpty()){
            document.createFootnotes();
        }
    
        // add footnote
        CTFtnEdn ctfInstance = CTFtnEdn.Factory.newInstance();
    
        BigInteger id = new BigInteger("1");
    
        ctfInstance.setId(id);
        CTP ctp = ctfInstance.addNewP();
    
        ctp.addNewPPr().addNewPStyle().setVal("FootnoteText");
    
        CTR ctr = ctp.addNewR();
        ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
        ctr.addNewFootnoteRef();
    
        CTText cttext = ctp.addNewR().addNewT();
        cttext.setStringValue("This should be a footnote");
        cttext.setSpace(SpaceAttribute.Space.PRESERVE);
    
        // add footnote to document
        document.addFootnote(ctfInstance);
    
        // add reference to footnote at end of first paragraph
        ctr = document.getParagraphArray(0).getCTP().addNewR();
        ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
        ctr.addNewFootnoteReference().setId(id);
    
        // styles
    
        // if styles dont already exist then create them
        if (document.getStyles()==null){
            document.createStyles();
        }
    
        CTStyle style = CTStyle.Factory.newInstance();
        style.setStyleId("FootnoteReference");
        style.setType(STStyleType.CHARACTER);
        style.addNewName().setVal("footnote reference");
        style.addNewBasedOn().setVal("DefaultParagraphFont");
        style.addNewUiPriority().setVal(new BigInteger("99"));
        style.addNewSemiHidden();
        style.addNewUnhideWhenUsed();
        style.addNewRPr().addNewVertAlign().setVal(STVerticalAlignRun.SUPERSCRIPT);
    
        // add style
        document.getStyles().addStyle(new XWPFStyle(style));
    
        style = CTStyle.Factory.newInstance();
        style.setType(STStyleType.PARAGRAPH);
        style.setStyleId("FootnoteText");
        style.addNewName().setVal("footnote text");
        style.addNewBasedOn().setVal("Normal");
        style.addNewLink().setVal("FootnoteTextChar");
        style.addNewUiPriority().setVal(new BigInteger("99"));
        style.addNewSemiHidden();
        style.addNewUnhideWhenUsed();
        CTRPr rpr = style.addNewRPr();
        rpr.addNewSz().setVal(new BigInteger("20"));
        rpr.addNewSzCs().setVal(new BigInteger("20"));
    
        // add style
        document.getStyles().addStyle(new XWPFStyle(style));
    
        style  = CTStyle.Factory.newInstance();
        style.setCustomStyle(STOnOff.X_1);
        style.setStyleId("FootnoteTextChar");
        style.setType(STStyleType.CHARACTER);
        style.addNewName().setVal("Footnote Text Char");
        style.addNewBasedOn().setVal("DefaultParagraphFont");
        style.addNewLink().setVal("FootnoteText");
        style.addNewUiPriority().setVal(new BigInteger("99"));
        style.addNewSemiHidden();
        rpr = style.addNewRPr();
        rpr.addNewSz().setVal(new BigInteger("20"));
        rpr.addNewSzCs().setVal(new BigInteger("20"));
    
        // add style
        document.getStyles().addStyle(new XWPFStyle(style));
    
        // save document
        FileOutputStream out = new FileOutputStream(new File("yourPathHere.docx"));
        document.write(out);
        out.close();
    }
    

    【讨论】:

      【解决方案2】:

      这样其他人就不必像我一样做同样的研究:)!这是 POI 4.1.0 代码的更新版本,使用 XWPFFootnote 类(不幸的是,它还没有完成所有工作)。

      首先,初始化文档以接收脚注。 doc 是您的 XWPFDocument(我总是从模板文档开始,带有预制样式,包括所需的脚注样式:FootnoteText、FootnoteReference)。这基本上创建了两个“虚拟”脚注,我认为它们仅用于显示目的——但如果它们不存在,Word 会认为文档已损坏。

      doc.createFootnotes();
      
      // Create the first two "dummy" footnotes.
      
      { // <w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator/></w:r></w:p></w:footnote>
          XWPFFootnote footnote = doc.createFootnote();
          footnote.getCTFtnEdn().setId(BigInteger.ZERO.subtract(BigInteger.ONE)); // -1
          footnote.getCTFtnEdn().setType(STFtnEdn.SEPARATOR);
          footnote.getCTFtnEdn().addNewP();
          footnote.getCTFtnEdn().getPArray(0).addNewR();
          footnote.getCTFtnEdn().getPArray(0).getRArray(0).addNewSeparator();
      }
      
      { // <w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator/></w:r></w:p></w:footnote>
          XWPFFootnote footnote = doc.createFootnote();
          footnote.getCTFtnEdn().setId(BigInteger.ZERO);
          footnote.getCTFtnEdn().setType(STFtnEdn.CONTINUATION_SEPARATOR);
          footnote.getCTFtnEdn().addNewP();
          footnote.getCTFtnEdn().getPArray(0).addNewR();
          footnote.getCTFtnEdn().getPArray(0).getRArray(0).addNewContinuationSeparator();
      }
      

      然后,您可以在文本中的某个位置继续添加脚注。创建段落并照常运行,直到您希望出现脚注的引用(通常是指数中的数字)。

      footnote = doc.createFootnote();
      paragraph.addFootnoteReference(footnote); // Creates a new run in the current paragraph to hold the reference.
      
      XWPFParagraph footnoteParagraph;
      { // Create a low-level paragraph and add it to the footnote with the right style. 
          CTP ctp = footnote.getCTFtnEdn().addNewP();
          footnoteParagraph = new XWPFParagraph(ctp, footnote);
          footnoteParagraph.setStyle("FootnoteText");
      }
      
      { // Create a run within this paragraph 
          XWPFRun run = paragraph.getLast().createRun();
          run.setStyle("FootnoteReference");
          run.getCTR().addNewFootnoteRef(); // Not addNewFootnoteReference, this is not recognised by Word!
      }
      
      { // Add a space after the footnote number (like Word). 
          XWPFRun run = footnoteParagraph.createRun();
          run.setText(" ");
      }
      
      { // Add your own text in the footnote, as in any paragraph. 
          XWPFRun run = footnoteParagraph.createRun();
      }
      

      【讨论】:

        猜你喜欢
        • 2013-03-09
        • 2011-09-27
        • 2021-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多