Section:

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:

JavaScript

1//snipped for brevity
2const viewerElement = this.template.querySelector('div');
3
4const viewer = new PDFTron.WebViewer({
5 path: libUrl,
6 custom: JSON.stringify(myObj),
7 config: myfilesUrl + '/config_apex.js',
8 fullAPI: true // this must be set to true
9 // l: 'YOUR_LICENSE_KEY_HERE',
10}, 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:

JavaScript (v8.0+)

1const docViewer = instance.Core.documentViewer;
2const doc = docViewer.getDocument();//get current document from WV
3if (!doc) {
4 return;
5}
6const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
7await PDFNet.initialize();
8
9PDFdoc.initSecurityHandler();
10PDFdoc.lock();
11
12console.log('PDFNet initialized and document locked');

JavaScript (v7.0+)

1const docViewer = readerControl.docViewer;
2const doc = readerControl.docViewer.getDocument();//get current document from WV
3if (!doc) {
4 return;
5}
6const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
7await PDFNet.initialize();
8
9PDFdoc.initSecurityHandler();
10PDFdoc.lock();
11
12console.log('PDFNet initialized and document locked');

Sample replaceContent() method

Place the following function into your config.js file:

JavaScript (v8.0+)

1async function replaceContent(searchString, replacementString) {
2 const docViewer = instance.Core.documentViewer;
3 const doc = docViewer.getDocument();//get current document from WV
4 if (!doc) {
5 return;
6 }
7 const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
8 await PDFNet.initialize();
9
10 PDFdoc.initSecurityHandler();
11 PDFdoc.lock();
12
13 // Run PDFNet methods with memory management
14 await PDFNet.runWithCleanup(async () => {
15 // lock the document before a write operation
16 // runWithCleanup will auto unlock when complete
17 const replacer = await PDFNet.ContentReplacer.create();
18 await replacer.setMatchStrings(searchString.charAt(0), searchString.slice(-1));
19 await replacer.addString(searchString.slice(1, -1), replacementString);
20 for (var i = 1; i <= docViewer.getPageCount(); ++i) {
21 const page = await PDFdoc.getPage(i);
22 await replacer.process(page);
23 }
24 });
25
26 docViewer.refreshAll();
27 docViewer.updateView();
28 docViewer.getDocument().refreshTextData();
29}

JavaScript (v7.0+)

1async function replaceContent(searchString, replacementString) {
2 const docViewer = readerControl.docViewer;
3 const doc = readerControl.docViewer.getDocument();//get current document from WV
4 if (!doc) {
5 return;
6 }
7 const PDFdoc = await doc.getPDFDoc(); //pass WV Doc to PDFNet
8 await PDFNet.initialize();
9
10 PDFdoc.initSecurityHandler();
11 PDFdoc.lock();
12
13 // Run PDFNet methods with memory management
14 await PDFNet.runWithCleanup(async () => {
15 // lock the document before a write operation
16 // runWithCleanup will auto unlock when complete
17 const replacer = await PDFNet.ContentReplacer.create();
18 await replacer.setMatchStrings(searchString.charAt(0), searchString.slice(-1));
19 await replacer.addString(searchString.slice(1, -1), replacementString);
20 for (var i = 1; i <= docViewer.getPageCount(); ++i) {
21 const page = await PDFdoc.getPage(i);
22 await replacer.process(page);
23 }
24 });
25
26 docViewer.refreshAll();
27 docViewer.updateView();
28 docViewer.getDocument().refreshTextData();
29}

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

JavaScript

1//snipped for brevity
2function receiveMessage(event) {
3 if (event.isTrusted && typeof event.data === 'object') {
4 switch (event.data.type) {
5 case 'REPLACE_CONTENT':
6 const { searchString, replacementString } = event.data.payload;
7 replaceContent(searchString, replacementString);
8 break;
9 default:
10 break;
11 }
12 }
13}

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:

JavaScript

1const payload = {
2 searchString: this.searchTerm,
3 replacementString: this.replaceTerm
4}
5fireEvent(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 to replace content (hosted outside of Salesforce).

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales