I would like to implement a 'html-span-like' feature inside Google Documents but whenever I try to add a NamedRange
to a substring of text inside a Google Document, the range is merged with previous text in the same paragraph.
In result, the NamedRange
is applied to the whole paragraph.
Here's my test case :
function createTextNamedRange(){
// Retrieve the current document's body
var doc = DocumentApp.getActiveDocument();
var docBody = doc.getBody();
// Add a new paragraph with text {NotNamed}
var para = docBody.appendParagraph('{NotNamed}');
// Append some text that will be named ( .appendText() method returns a Text element )
var textElem = para.appendText('{NamedText}');
// Build a range for the Text element
var range=doc.newRange().addElement(textElem).build();
// Name the range and append it to the document
doc.addNamedRange('myNamedRange',range);
}
I then display the content of the NamedRange
using the Logger
class in this function:
function getTextNamedRange(){
// Retrieve the named range
var namedRanges = DocumentApp.getActiveDocument().getNamedRanges();
// Iterate through each instance of name 'myNamedRange' (there's only one)
for (var nr in namedRanges){
var namedRange = namedRanges[nr];
// A range may contain several RangeElements, iterate through them
var rangeElements = namedRange.getRange().getRangeElements();
for(var re in rangeElements) {
// Get the text of each RangeElement and display it in the logger
var text = rangeElements[re].getElement().asText().getText();
Logger.log('Text with namedRange (' + namedRange.getName() + ') : "' + text +'"');
}
}
}
I would assume to get {NamedText}
as an output but the Log Window tells this:
Text with namedRange (myNamedRange) : "{NotNamed}{NamedText}"
As it can be seen, the range was applied to the unmarked as well as the named text.
I found a workaround detailed below but it's definitely not to my taste: it consists of adding empty inline images between the .appendText()
calls. This way the Text elements are not merged.
I'm still looking for a better solution.
The following is for WORKAROUND ONLY but appears to work.
It relies on InlineImage
insertion before and after the Text
chunk that has to be Named.
This prevent the NamedRange
to merge when applied to chunk of Text
inside a Paragraph
function createTextNamedRangeWorkaround(){
// WORKAROUND: prevent the Text Merging (and hence the NamedRange merging)
// by separating Text Elements with blank Inline Images
// Import a blank PNG file
// NOTE: This shouldn't be fetched each time
// but only once and passed as an argument
var blankImage = UrlFetchApp.fetch('http://upload.wikimedia.org/wikipedia/commons/d/d2/Blank.png');
// Retrieve the current document's body
var doc = DocumentApp.getActiveDocument();
var docBody = doc.getBody();
// Add a new paragraph with text {NotNamed}
var para = docBody.appendParagraph('{NotNamed}');
// WORKAROUND HERE :
para.appendInlineImage(blankImage.getBlob());
// Append some text
var textElem1 = para.appendText('{NamedText1}');
// WORKAROUND HERE :
para.appendInlineImage(blankImage.getBlob());
// Append some text
var textElem2 = para.appendText('{NamedText2}');
// Build Named ranges after text insertion (see notice below)
var range1=doc.newRange().addElement(textElem1).build();
// Name the range and append it to the document
doc.addNamedRange('Range1',range1);
var range2=doc.newRange().addElement(textElem2).build();
// Name the range and append it to the document
doc.addNamedRange('Range2',range2);
}
After execution the document is appended with a new paragraph containing three words separated by two blank inline PNGs
{NotNamed}{NamedText1}{NamedText2}
And the execution of my getTextNamedRange()
shows the desired behaviour:
Text with namedRange (Range1) : "{NamedText1}"
Text with namedRange (Range2) : "{NamedText2}"
Important notices:
Named ranges must be applied alltogether after the last Text
insertion, otherwise, previous NamedRanges adopt new insertions and appendings.
InlineImages
can't be removed from parent Paragraph
using image.removeFromParent()
because this causes the Text
elements (and the NamedRange
) to be merged again
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With