如何在Apache POI Word中为图片添加交叉引用?

时间:2019-05-14 17:23:55

标签: java ms-word apache-poi

我想使用Apache POI创建一个包含文本和图片的文档。文本的某些部分必须与图片交叉引用。我尝试遵循此问题的答案,但未成功将addExternalRelationship方法更改为addRelationship

How to create hyperlinks in Apache POI Word?

编辑:下面是我研究以下代码后的尝试:

Generate Inter-Document Hyperlink with Apache POI in Java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFldCharType;

public class CrossReference {
    public static void main(String[] args) throws InvalidFormatException, FileNotFoundException, IOException {
        XWPFDocument document = new XWPFDocument();
        XWPFParagraph paragraph = document.createParagraph();
        document.createParagraph();

        document.createParagraph().createRun().addBreak(BreakType.PAGE);

        XWPFParagraph pictureParagraph = document.createParagraph();
        pictureParagraph.setSpacingAfter(0);

        XWPFRun pictureRun = pictureParagraph.createRun();
        String imgPath = "img.png";
        pictureRun.addPicture(new FileInputStream(imgPath), 
                XWPFDocument.PICTURE_TYPE_PNG, 
                imgPath, 
                Units.toEMU(288), 
                Units.toEMU(288));

        String anchor = "anchor";

        XWPFParagraph captionParagraph = document.createParagraph();
        XWPFRun captionRun = captionParagraph.createRun();
        captionRun.setText("Figure ");
        CTBookmark bookmark = captionParagraph.getCTP().addNewBookmarkStart();
        bookmark.setName(anchor);
        bookmark.setId(BigInteger.valueOf(0));
        captionParagraph.createRun().getCTR().addNewFldChar().setFldCharType(STFldCharType.BEGIN);
        captionParagraph.getCTP().addNewFldSimple().setInstr("SEQ Figure \\* ARABIC");
        captionParagraph.createRun().getCTR().addNewFldChar().setFldCharType(STFldCharType.END);
        captionParagraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(0));

        CTHyperlink ctHyperlink = paragraph.getCTP().addNewHyperlink();
        ctHyperlink.setAnchor(anchor);
        XWPFHyperlinkRun hyperlinkRun = new XWPFHyperlinkRun(ctHyperlink, 
                ctHyperlink.addNewR(), paragraph);
        hyperlinkRun.setText("Figure 1");
        hyperlinkRun.setUnderline(UnderlinePatterns.SINGLE);

        FileOutputStream out = new FileOutputStream(new File("test.docx"));
        document.write(out);
        out.close();
        document.close();
    }
}

但是,在docx的document.xml中,获得的段落是:

  <w:p>
     <w:hyperlink w:anchor="anchor">
        <w:r>
           <w:rPr>
              <w:u w:val="single" />
           </w:rPr>
           <w:t>Figure 1</w:t>
        </w:r>
     </w:hyperlink>
  </w:p>
  <w:p />

虽然我期望下面提供类似XML的内容(通过使用LibreOffice Writer手动添加引用来获得)。超链接方法的问题在于它的文本是固定的,如果文档被编辑,它将不会被更新。

  <w:p>
     <w:pPr>
        <w:pStyle w:val="Normal" />
        <w:rPr />
     </w:pPr>
     <w:r>
        <w:rPr />
        <w:t xml:space="preserve">Figure </w:t>
     </w:r>
     <w:r>
        <w:rPr />
        <w:fldChar w:fldCharType="begin" />
     </w:r>
     <w:r>
        <w:rPr />
        <w:instrText>REF Ref_Figure0_number_only \h</w:instrText>
     </w:r>
     <w:r>
        <w:rPr />
        <w:fldChar w:fldCharType="separate" />
     </w:r>
     <w:r>
        <w:rPr />
        <w:t>1</w:t>
     </w:r>
     <w:r>
        <w:rPr />
        <w:fldChar w:fldCharType="end" />
     </w:r>
  </w:p>

1 个答案:

答案 0 :(得分:0)

我发现问题的解决方案是通过书签而不是超链接获得的:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFldCharType;

public class CrossReference {
    public static void main(String[] args) throws InvalidFormatException, FileNotFoundException, IOException {
        XWPFDocument document = new XWPFDocument();
        XWPFParagraph paragraph = document.createParagraph();

        document.createParagraph().createRun().addBreak(BreakType.PAGE);

        XWPFParagraph pictureParagraph = document.createParagraph();
        pictureParagraph.setSpacingAfter(0);

        XWPFRun pictureRun = pictureParagraph.createRun();
        String imgPath = "img.png";
        pictureRun.addPicture(new FileInputStream(imgPath), 
                XWPFDocument.PICTURE_TYPE_PNG, 
                imgPath, 
                Units.toEMU(288), 
                Units.toEMU(288));

        XWPFParagraph captionParagraph = document.createParagraph();
        XWPFRun captionRun = captionParagraph.createRun();
        captionRun.setText("Figure ");
        CTBookmark bookmark = captionParagraph.getCTP().addNewBookmarkStart();
        bookmark.setName("Figure-1");
        bookmark.setId(BigInteger.valueOf(0));
        captionParagraph.createRun().getCTR().addNewFldChar().setFldCharType(STFldCharType.BEGIN);
        captionParagraph.getCTP().addNewFldSimple().setInstr("SEQ Figure \\* ARABIC");
        captionParagraph.createRun().getCTR().addNewFldChar().setFldCharType(STFldCharType.END);
        captionParagraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(0));

        paragraph.createRun().setText("Figure ");
        paragraph.createRun().getCTR().addNewFldChar().setFldCharType(STFldCharType.BEGIN);
        paragraph.createRun().getCTR().addNewInstrText().setStringValue("REF " + bookmark.getName() + " \\h");
        paragraph.createRun().getCTR().addNewFldChar().setFldCharType(STFldCharType.END);

        FileOutputStream out = new FileOutputStream(new File("test.docx"));
        document.write(out);
        out.close();
        document.close();
    }
}