how to set bookmark for XWPFRun object in word by poi

122 Views Asked by At

I am using Word to create templates that contain many variables. I will read and parse the Word document to set bookmarks for the variables. Each variable is a XWPFRun object. How can I set a bookmark for a XWPFRun object? Below is the response from chatgpt, but CTR doesn't have addNewBookmarkStart and addNewBookmarkEnd.

for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
    // Check if the run meets your criteria
    if (/* condition */) {
        // Create a bookmark for the run
        run.getCTR().addNewBookmarkStart().setName("bookmark_name");
        run.getCTR().addNewBookmarkEnd();
    }
}

}

1

There are 1 best solutions below

0
Axel Richter On BEST ANSWER

In java poi XWPF word - create bookmark in new document I have shown how to create bookmarks in a new XWPFDocument.

If you look at the document.xml created, you will find:

<w:p>
 ...
 <w:bookmarkStart w:name="testing_string" w:id="1"/>
 <w:r>
  <w:t xml:space="preserve">testing string </w:t>
 </w:r>
 <w:bookmarkEnd w:id="1"/>
 ...
</w:p>

The bookmarkStart is immediately before the text run and the bookmarkEnd is immediately after the text run in paragraph. All elements are children of the paragraph elements on same level.

If the need is to bookmark already existent XWPFRuns, then one need to insert the bookmarkStart immediately before and bookmarkEnd immediately after the XWPFRun in XWPFParagraph. This only is possible using a XmlCursor.

Example:

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.apache.xmlbeans.XmlCursor;
import java.math.BigInteger;

public class WordBookmarkXWPFRun {
    
 static void bookmarkXWPFRun(XWPFRun run, String name, int id) {
  // insert bookmarkStart immediately before the run
  XmlCursor cursor = run.getCTR().newCursor();
  String uri = CTBookmark.type.getName().getNamespaceURI();
  String localPart = "bookmarkStart";
  cursor.beginElement(localPart, uri);
  cursor.toParent();
  CTBookmark bookmarkStart = (CTBookmark)cursor.getObject();
  bookmarkStart.setName(name);
  bookmarkStart.setId(BigInteger.valueOf(id));
  
  // insert bookmarkEnd immediately after the run
  cursor = run.getCTR().newCursor();
  if (!cursor.toNextSibling()) { // is there a next sibling?
   // if not, go to end of parent element to insert bookmarkEnd there
   cursor.toParent();
   cursor.toEndToken();   
  }
  localPart = "bookmarkEnd";
  cursor.beginElement(localPart, uri);
  cursor.insertAttributeWithValue("id", uri, String.valueOf(id));
 }

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

  XWPFDocument document = new XWPFDocument(new FileInputStream("./WordDocument.docx"));
  
  int id = 1;
  for (XWPFParagraph paragraph : document.getParagraphs()) {
   for (XWPFRun run : paragraph.getRuns()) {
    // Check if the run meets your criteria
    if (/* condition */ true ) { // this will bookmark every single tect run in document
     // Create a bookmark for the run
     bookmarkXWPFRun(run, "bookmark_name_" + id, id++);
    }
   }
  }

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

 }
}