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 theText
chunk that has to be Named.This prevent the
NamedRange
to merge when applied to chunk ofText
inside aParagraph
After execution the document is appended with a new paragraph containing three words separated by two blank inline PNGs
And the execution of my
getTextNamedRange()
shows the desired behaviour: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 parentParagraph
usingimage.removeFromParent()
because this causes theText
elements (and theNamedRange
) to be merged again