Some test text!

Search
Hamburger Icon

Salesforce / Guides / Replace Text

Replace Document Text in Salesforce

Getting Started

We recommend familiarizing yourself with the Overview page to learn how to correctly use a config.js file. If you are using a version of WebViewer older than 8.0+, you should also learn about readerControl before getting started. Make sure you also understand document search .

WebViewer configuration required for ContentReplacer

In order to use the ContentReplacer class, you need to enable fullAPI. In your Lightning Web Component where you initialize WebViewer (you can check out pdftronWvInstance.js in our sample repository), include fullAPI: true:

//snipped for brevity
const viewerElement = this.template.querySelector('div');

const viewer = new PDFTron.WebViewer({
    path: libUrl,
    custom: JSON.stringify(myObj),
    config: myfilesUrl + '/config_apex.js',
    fullAPI: true // this must be set to true
    // l: 'YOUR_LICENSE_KEY_HERE',
}, viewerElement);

Note: You need to use the pdf_full.zip file in your /staticresources/ folder to access full API, which is required for redaction.

Open a document

To replace content on a document, open it in WebViewer. Check out this link to learn more.

ContentReplacer placeholders

ContentReplacer is used for replacing strings that are wrapped in match strings. An example of this is [Content to be replaced]. This allows the user to build templates with these placeholders, which are then targeted by ContentReplacer and filled with data.

Initializing PDFNet

ContentReplacer is a PDFNet class. Below is a code sample on how to initialize PDFNet:

const docViewer = instance.Core.documentViewer;
const doc = docViewer.getDocument();//get current document from WV
if (!doc) {
    return;
}
const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
await PDFNet.initialize();

PDFdoc.initSecurityHandler();
PDFdoc.lock();

console.log('PDFNet initialized and document locked');
const docViewer = readerControl.docViewer;
const doc = readerControl.docViewer.getDocument();//get current document from WV
if (!doc) {
    return;
}
const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
await PDFNet.initialize();

PDFdoc.initSecurityHandler();
PDFdoc.lock();

console.log('PDFNet initialized and document locked');

Sample replaceContent() method

Place the following function into your config.js file:

async function replaceContent(searchString, replacementString) {
  const docViewer = instance.Core.documentViewer;
  const doc = docViewer.getDocument();//get current document from WV
  if (!doc) {
    return;
  }
  const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
  await PDFNet.initialize();

  PDFdoc.initSecurityHandler();
  PDFdoc.lock();

  // Run PDFNet methods with memory management
  await PDFNet.runWithCleanup(async () => {
    // lock the document before a write operation
    // runWithCleanup will auto unlock when complete
    const replacer = await PDFNet.ContentReplacer.create();
    await replacer.setMatchStrings(searchString.charAt(0), searchString.slice(-1));
    await replacer.addString(searchString.slice(1, -1), replacementString);
    for (var i = 1; i <= docViewer.getPageCount(); ++i) {
      const page = await PDFdoc.getPage(i);
      await replacer.process(page);
    }
  });

  docViewer.refreshAll();
  docViewer.updateView();
  docViewer.getDocument().refreshTextData();
}
async function replaceContent(searchString, replacementString) {
  const docViewer = readerControl.docViewer;
  const doc = readerControl.docViewer.getDocument();//get current document from WV
  if (!doc) {
    return;
  }
  const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
  await PDFNet.initialize();

  PDFdoc.initSecurityHandler();
  PDFdoc.lock();

  // Run PDFNet methods with memory management
  await PDFNet.runWithCleanup(async () => {
    // lock the document before a write operation
    // runWithCleanup will auto unlock when complete
    const replacer = await PDFNet.ContentReplacer.create();
    await replacer.setMatchStrings(searchString.charAt(0), searchString.slice(-1));
    await replacer.addString(searchString.slice(1, -1), replacementString);
    for (var i = 1; i <= docViewer.getPageCount(); ++i) {
      const page = await PDFdoc.getPage(i);
      await replacer.process(page);
    }
  });

  docViewer.refreshAll();
  docViewer.updateView();
  docViewer.getDocument().refreshTextData();
}

To handle posted messages to the WebViewer iFrame, use a receiveMessage() function like below:

//snipped for brevity
function receiveMessage(event) {
    if (event.isTrusted && typeof event.data === 'object') {
        switch (event.data.type) {
            case 'REPLACE_CONTENT':
                const { searchString, replacementString } = event.data.payload;
                replaceContent(searchString, replacementString);
                break;
            default:
                break;
    }
  }
}

In your LWC component that hosts the WebViewer iFrame, you can communicate with the config.js file using this.iframeWindow.postMessage({ type: 'REPLACE_CONTENT', payload }, '*');.

Make sure that the payload you are publishing matches the structure of the event.data.payload object in your receiveMessage() function:

const payload = {
    searchString: this.searchTerm,
    replacementString: this.replaceTerm
}
fireEvent(this.pageRef, 'replace', payload); //fire pub-sub event or use LMS

Sample project

You can review the Salesforce PDF App to showcase an end-to-end example of search, and how you can leverage it for redaction and content replacing on our Github repository.

Live demo

Check out this live demo hosted outside of Salesforce.

Get the answers you need: Chat with us