You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Docs表格插入富文本时多余空格问题:富文本适配困境

Google Apps Script表格富文本排版与多余换行符问题

如Stack Overflow相关帖子所述,Google Apps Script会向表格这类元素添加随机换行符(对应字符为\10)。针对普通文本的解决方法能正常生效,但处理带富格式的文本时出现适配问题。

我的使用场景是创建N×2表格,左列显示英文文本,右列显示希伯来语文本。为设置希伯来语的从右到左排版,必须通过insertParagraph()动态插入内容,但这个操作会引入上述多余换行符。尝试沿用原有解决方法后,第一行没有任何效果,第二列反而重新出现换行符,只有排版方向的设置符合预期。

以下是接近实际使用的代码(已整合@Tanaike的建议,但仍未达到预期效果):

function insertReference() {
  let reference = "Shemot 12:2-4";
  let url = 'http://www.sefaria.org/api/texts/'+reference+'?commentary=0&context=0';
  let response = UrlFetchApp.fetch(url);
  let json = response.getContentText();
  let data = JSON.parse(json);
  let doc = DocumentApp.getActiveDocument().getBody();
  let index = DocumentApp.getActiveDocument().getBody().getNumChildren()-1;

    let cells = [
      ["", ""],
      ["", ""]
    ];
    let tableStyle = {};
        tableStyle[DocumentApp.Attribute.BOLD] = false;
    let table = doc.insertTable(index, cells)

    table.setAttributes(tableStyle);

    let engTitle = table.getCell(0, 0)
      .setText("")
      .insertParagraph(0, "")
      .setLeftToRight(true)
      .editAsText();
    insertRichTextFromHTML(engTitle, data.ref);

    let hebTitle = table.getCell(0, 1)
      .setText("")
      .insertParagraph(0, "")
      .setLeftToRight(false)
      .editAsText();
    insertRichTextFromHTML(hebTitle, data.heRef);

    let engText = table.getCell(1, 0)
      .setText("")
      .insertParagraph(0, "")
      .setLeftToRight(true)
      .editAsText();
    insertRichTextFromHTML(engText, data.text);

    let hebText = table.getCell(1, 1)
      .setText("")
      .insertParagraph(0, "")
      .setLeftToRight(false)
      .editAsText();
    insertRichTextFromHTML(hebText, data.he);
}
function insertRichTextFromHTML(element, htmlString) {
  let buf = [];
  let index = 0, italicsFnCount = 0, textLength = element.editAsText().getText().length;
  let bolded = false, italicized = false, inFootnote = false;
  if (Array.isArray(htmlString)) {
    htmlString = htmlString.join("");
  }
  let iterableString = htmlString.split(/(<\/?[a-zA-Z]+[a-zA-Z'"0-9= \-/]*>)/g);

  let inserterFn = (textModification) => {
    //grab all words in the buffer and join
    let snippet = buf.join("");

    //index of snippet needs to be zero-indexed. This is how we keep track of which words/phrases/sentences to bold/italicize
    let snippetLength = snippet.length;
    let snippetIndex = snippetLength - 1;

    if (snippet != "") {
      element.insertText(textLength, snippet);

      //set rich text settings
      element.setBold(textLength, textLength+snippetIndex, bolded); 
      element.setItalic(textLength, textLength+snippetIndex, italicized);

      textLength += snippetLength;
    }

    switch(textModification) {
      case "bold":
        bolded = !bolded;
        break;
      case "italic":
        italicized = !italicized;
        break;
      case "linebreak":
        element.insertText(textLength, "\n");
        textLength += 1;
        break;
    }
  }

  for (let i = 0; i < iterableString.length; i++) {
    let word = iterableString[i];

    /* example format of footnotes in the text: -----‘Do not let me see your faces<sup class="footnote-marker">*</sup><i class="footnote"><b>Do not let me see your faces </b>See note at v. 3.</i> unless----*/
    if (inFootnote) {
      if ( word == "<i class=\"footnote\">" || word == "<i>") {
        italicsFnCount++;
      } else if ( word == "</i>") {
        italicsFnCount--;
        if (italicsFnCount == 0) {
          inFootnote = false;
          continue;
        }
      }

    }

    else if (word[0] == "<") {
      //we have a tag; grab the name of the tag
      let tagName = /<\/?([a-zA-Z]+)([a-zA-Z'"0-9= \-/])*>/.exec(word)[1];

      switch (tagName) {
        case "b":
          inserterFn("bold");
          buf = [];
          index = 0;
          break;
        case "strong":
          inserterFn("bold");
          buf = [];
          index = 0;
          break;
        case "i":
          inserterFn("italic");
          buf = [];
          index = 0;
          break;
        case "br":
          inserterFn("linebreak");
          buf = [];
          index = 0;
          break;
        case "sup":
          inFootnote = true;
          // yes, this fires even at </sup>, but that is of no consequence for the logic
          italicsFnCount = 0;
          break;
        default:
          break;
      }
      continue;
    }

    if (!inFootnote) {
      buf[index++] = word;
    }
  }

  // add in the last words, if the text snippet does not end with a tag
  let snippet = buf.join("");
  if ( snippet != "" ) {
    element.insertText(textLength, snippet);
    let snippetIndex = snippet.length - 1;
    element.setBold(textLength, textLength+snippetIndex, false); 
    element.setItalic(textLength, textLength+snippetIndex, false);
  }
}

效果对比

  • 当前输出效果:当前输出效果
  • 期望输出效果:期望输出效果

内容的提问来源于stack exchange,提问作者shman613

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:22:00