Создайте гиперссылку между документами с помощью Apache POI в Java - PullRequest
0 голосов
/ 06 декабря 2018

Я создаю XWPFDocument с Apache POI (никогда ранее не использовал его), и я хотел бы связать один абзац с другим абзацем в том же документе .docx.Возможно ли это, используя встроенную функциональность POI, или мне нужно углубиться в классы-оболочки XML Bean (например, CTP), чтобы заткнуть руку, или мне не повезло?Каждый раз, когда я встречал вопрос о гиперссылках и POI, ссылки создавали либо гиперссылку внешнего типа, либо ссылку между листами книги Excel.На данный момент я могу только генерировать «гиперссылку» в том смысле, что при нажатии клавиши Ctrl щелкает абзац внутри готового документа, и он, по-видимому, просто выполняет текстовый поиск, начиная с верхней части документа.Вот код, который я сейчас использую для достижения этой цели.Заранее спасибо!

public static void addInternalHyperlink(XWPFParagraph origin, String text, XWPFParagraph target) {

        if (target != null) {

        // Create the hyperlink itself
        CTHyperlink link = origin.getCTP().addNewHyperlink();       
        link.setAnchor(target.getText());

        // Create hyperlink text
        CTText linkText = CTText.Factory.newInstance();
        linkText.setStringValue(text);      
        CTR ctr = CTR.Factory.newInstance();
        ctr.setTArray(new CTText[] {linkText});

        // Format hyperlink text
        CTFonts fonts = CTFonts.Factory.newInstance();
        fonts.setAscii("Times New Roman");
        CTRPr rpr = ctr.addNewRPr();
        CTColor color = CTColor.Factory.newInstance();
        color.setVal("0000FF");
        rpr.setColor(color);
        CTRPr rpr1 = ctr.addNewRPr();
        rpr1.addNewU().setVal(STUnderline.SINGLE);

        // Insert formatted text into link
        link.setRArray(new CTR[] {ctr});
        }
    }

Обратите внимание, что я хотел бы использовать аргумент 'origin' в качестве абзаца, содержащего фактическую ссылку, аргумент 'text' в качестве текста ссылки и 'target'аргумент в качестве фактического назначения ссылки.

ОБНОВЛЕНИЕ: Вот фрагмент кода XML, содержащий образец абзаца, который я связал с заголовком раздела через графический интерфейс Word.

<w:p w14:paraId="5B1C3A0C" w14:textId="659E388D" w:rsidR="00A4419C" w:rsidRDefault="00A4419C" w:rsidP="00A4419C"><w:hyperlink w:anchor="_Another_Heading" w:history="1"><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>Here is some stuff that could b</w:t></w:r><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>e</w:t></w:r><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t xml:space="preserve"> the link</w:t></w:r></w:hyperlink></w:p><w:p w14:paraId="19996B78" w14:textId="5C39B081" w:rsidR="00A4419C" w:rsidRPr="00A4419C" w:rsidRDefault="00A4419C" w:rsidP="00A4419C"><w:pPr><w:pStyle w:val="Heading1"/></w:pPr><w:bookmarkStart w:id="0" w:name="_Another_Heading"/><w:bookmarkEnd w:id="0"/><w:r><w:t>Another Heading</w:t></w:r><w:bookmarkStart w:id="1" w:name="_GoBack"/><w:bookmarkEnd w:id="1"/></w:p>

1 Ответ

0 голосов
/ 07 декабря 2018

Раствор делится на две части.

Сначала нам нужен XWPFHyperlinkRun, целью которого является якорь в документе.

Во-вторых, нам нужен этот целевой якорь, который, например, может быть закладкой в ​​документе.Поэтому нам нужно создать такую ​​закладку в документе.

К сожалению, оба не поддерживаются с использованием только классов высокого уровня apache poi до сих пор.Поэтому нам нужны классы низкого уровня и для ooxml-schemas.

Следующий код работает с использованием apache poi 4.0.0 вместе с ooxml-schemas-1.4 .

import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;

import java.math.BigInteger;

public class CreateWordHyperlinkBookmark {

 static XWPFHyperlinkRun createHyperlinkRunToAnchor(XWPFParagraph paragraph, String anchor) throws Exception {
  CTHyperlink cthyperLink=paragraph.getCTP().addNewHyperlink();
  cthyperLink.setAnchor(anchor);
  cthyperLink.addNewR();
  return new XWPFHyperlinkRun(
    cthyperLink,
    cthyperLink.getRArray(0),
    paragraph
   );
 }

 static XWPFParagraph createBookmarkedParagraph(XWPFDocument document, String anchor, int bookmarkId) {
  XWPFParagraph paragraph = document.createParagraph();
  CTBookmark bookmark = paragraph.getCTP().addNewBookmarkStart();
  bookmark.setName(anchor);
  bookmark.setId(BigInteger.valueOf(bookmarkId));
  XWPFRun run = paragraph.createRun();
  paragraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(bookmarkId));
  return paragraph;
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument();

  String anchor = "hyperlink_target"; 
  int bookmarkId = 0;

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run = paragraph.createRun();
  run.setText("This is a text paragraph having ");

  //create hyperlink run
  XWPFHyperlinkRun hyperlinkrun = createHyperlinkRunToAnchor(paragraph, anchor);
  hyperlinkrun.setText("a link to an bookmark anchor");
  hyperlinkrun.setColor("0000FF");
  hyperlinkrun.setUnderline(UnderlinePatterns.SINGLE);

  run = paragraph.createRun();
  run.setText(" in it.");

  //some empty paragraphs
  for (int i = 0; i < 10; i++) {
   paragraph = document.createParagraph();
  }

  //create bookmarked paragraph as the hyperlink target
  paragraph = createBookmarkedParagraph(document, anchor, bookmarkId++);
  run = paragraph.getRuns().get(0);
  run.setText("This is the target.");

  FileOutputStream out = new FileOutputStream("CreateWordHyperlinkBookmark.docx");
  document.write(out);
  out.close();
  document.close();

 }
}
...