package com.aspose.words.examples.programming_documents.find_replace; import com.aspose.words.*; import com.aspose.words.examples.Utils; import java.text.MessageFormat; import java.util.ArrayList; import java.util.regex.Pattern; public class ReplaceTextWithField { private static final String dataDir = Utils.getSharedDataDir(ReplaceTextWithField.class) + "FindAndReplace/"; public static void main(String[] args) throws Exception { Document doc = new Document(dataDir + "Field.ReplaceTextWithFields.doc"); // Replace any "PlaceHolderX" instances in the document (where X is a number) with a merge field. Pattern regex = Pattern.compile("PlaceHolder(\\d+)", Pattern.CASE_INSENSITIVE); doc.getRange().replace(regex, new ReplaceTextWithFieldHandler("MERGEFIELD"), false); doc.save(dataDir + "Field.ReplaceTextWithFields Out.doc"); System.out.println("Text replaced with field successfully."); } private static class ReplaceTextWithFieldHandler implements IReplacingCallback { public ReplaceTextWithFieldHandler(String name) { mFieldName = name.toUpperCase(); } public int replacing(ReplacingArgs e) throws Exception { ArrayList runs = FindAndSplitMatchRuns(e); // Create DocumentBuilder which is used to insert the field. DocumentBuilder builder = new DocumentBuilder((Document) e.getMatchNode().getDocument()); builder.moveTo((Run) runs.get(runs.size() - 1)); // Insert the field into the document using the specified field type and the match text as the field name. // If the fields you are inserting do not require this extra parameter then it can be removed from the string below. builder.insertField(MessageFormat.format("{0} {1}", mFieldName, e.getMatch().group(0))); // Now remove all runs in the sequence. for (Run run : (Iterable<Run>) runs) run.remove(); // Signal to the replace engine to do nothing because we have already done all what we wanted. return ReplaceAction.SKIP; } /** * Finds and splits the match runs and returns them in an ArrayList. */ public ArrayList FindAndSplitMatchRuns(ReplacingArgs e) throws Exception { // This is a Run node that contains either the beginning or the complete match. Node currentNode = e.getMatchNode(); // The first (and may be the only) run can contain text before the match, // in this case it is necessary to split the run. if (e.getMatchOffset() > 0) currentNode = SplitRun((Run) currentNode, e.getMatchOffset()); // This array is used to store all nodes of the match for further removing. ArrayList runs = new ArrayList(); // Find all runs that contain parts of the match string. int remainingLength = e.getMatch().group().length(); while ((remainingLength > 0) && (currentNode != null) && (currentNode.getText().length() <= remainingLength)) { runs.add(currentNode); remainingLength = remainingLength - currentNode.getText().length(); // Select the next Run node. // Have to loop because there could be other nodes such as BookmarkStart etc. do { currentNode = currentNode.getNextSibling(); } while ((currentNode != null) && (currentNode.getNodeType() != NodeType.RUN)); } // Split the last run that contains the match if there is any text left. if ((currentNode != null) && (remainingLength > 0)) { SplitRun((Run) currentNode, remainingLength); runs.add(currentNode); } return runs; } /** * Splits text of the specified run into two runs. Inserts the new run * just after the specified run. */ private Run SplitRun(Run run, int position) throws Exception { Run afterRun = (Run) run.deepClone(true); afterRun.setText(run.getText().substring(position)); run.setText(run.getText().substring(0, position)); run.getParentNode().insertAfter(afterRun, run); return afterRun; } private String mFieldName; } }