如何将命名范围添加到 Google 应用程序脚本中的子段落元素

Lau*_*nt' 5 google-docs named-ranges google-apps-script

我想实现一个“HTML跨度样”功能谷歌文档内,但每当我尝试将添加NamedRange到谷歌文档中的文本的子串,范围是合并的同款以前的文本。

结果,NamedRange应用于整个段落。

这是我的测试用例:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后我在这个函数中显示NamedRangeusingLogger类的内容:

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 +'"');
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我假设得到{NamedText}作为输出,但日志窗口告诉这一点:

Text with namedRange (myNamedRange) : "{NotNamed}{NamedText}"
Run Code Online (Sandbox Code Playgroud)

可以看出,范围被应用于未标记的和命名的文本。

我在下面找到了一个详细的解决方法,但这绝对不合我的口味:它包括在.appendText()调用之间添加空的内联图像。这样 Text 元素就不会合并。

我仍在寻找更好的解决方案。

Lau*_*nt' 5

以下仅用于解决方法但似乎有效。

它依赖于InlineImage之前和之后的插入Text必须命名块。

这可以防止NamedRange在应用于Text内部块时进行合并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);
}
Run Code Online (Sandbox Code Playgroud)

执行后,文档会附加一个包含三个单词的新段落,由两个空白的内联 PNG 分隔

{NotNamed}{NamedText1}{NamedText2}
Run Code Online (Sandbox Code Playgroud)

我的执行getTextNamedRange()显示了所需的行为:

Text with namedRange (Range1) : "{NamedText1}"
Text with namedRange (Range2) : "{NamedText2}"
Run Code Online (Sandbox Code Playgroud)

重要通知:

  • 命名范围必须在最后一次Text插入后全部应用,否则之前的 NamedRanges 会采用新的插入和追加。

  • InlineImages不能从父Paragraph使用中删除,image.removeFromParent()因为这会导致Text元素(和NamedRange)再次合并