Google表格应用脚本-用于查找RichText粗体/斜体位置的自定义函数

问题描述

我目前正在使用Google表格来跟踪/维护一些文本翻译的项目(实际上是一些元数据,然后是原始文本和翻译的2列)。

最终的应用程序具有一些自动换行的约束和可变宽度的字体,因此我在应用程序脚本中创建了一个自定义函数来应用换行符,以便于可视化外观。

function preview(text)
{
  if(text.startsWith('=')) // Copy of something else,so we don't care
    return text;

  text = text.trimEnd();
  text = text.replace("<4A>","\n\n"); // For the sake of the preview,just treat <4A> as a new box
  text = text.replace(/\<&[a-zA-Z0-9]+\>/g,"────────"); // Assume the longest length (8 * 8)
  text = text.replace(/<\*.>/g,""); // Get rid of exit codes
  text = text.replace(/<S.+?>/g,""); // Get rid of special effects
  
  var output = "";
  var boxes = text.split("\n\n"); // Double newline is a forced new text box
  for (var i = 0; i < boxes.length; i++)
  { // For each intentional text box
    var box = boxes[i];
    box = box.replace("<4E>","\n"); // Will technically forcibly always draw on the second line
    
    var lines = box.split('\n');
    var newboxFlag = false; // Flag to indicate if we draw a new line or new box

    for (var j = 0; j < lines.length; j++)
    { // For each intentional line in this box
      words = lines[j].split(' ');
      var word = "";    
      var currentLineLen = 0;
      for(var k = 0; k < words.length; k++)
      {
        word += words[k];
        
        var wordWidth = 0;
        for (var l = 0; l < word.length; l++)
        {
          var char = word.charAt(l);
          wordWidth += getCharacterWidth(char);
        }

        if(wordWidth + currentLineLen > 0x89)
        { // This word won't fit on this line,so it goes to a new line
          
          // Strip the first space,and just assume we don't have a string longer than 136 characters
          word = word.substr(1);
          wordWidth -= getCharacterWidth(' ');
          
          // Add a new line and flip the newboxFlag
          output += '\n';
          if(newboxFlag) output += '\n';
          newboxFlag ^= 1;
          currentLineLen = 0;
        }
        
        currentLineLen += wordWidth
        output += word;
        word = " ";
      }
      
      if (j != lines.length - 1)
      {
        output += '\n';  // line length is reset at the top
        if(newboxFlag) output += '\n';
        newboxFlag ^= 1;
      }
    }
    if(i != boxes.length - 1) output += '\n\n'; // If we're not on the last box,add the double new line
  }
  return output;
}

我用=preview(<CELL>)来称呼它(getCharacterWidth只是从字符宽度映射中提取一个整数)。

此功能适用于不包含任何粗体或斜体字符的原始文本。

问题在于,粗体和斜体字符通常比普通字符占用更多的空间,并且在某些情况下,会导致预览的输出文本错误地省略应该包含一些换行符的换行符。

例如,原始文本为:

这是斜体。这是粗体。这是 粗体和斜体

=预览(文本) 应该 理想情况是:

这是 italic

这是粗体

这是 粗体

和斜体

但是相反,它可能最终像这样:

这是斜体的。

这是粗体。这个

是粗体和斜体。

由于未考虑粗体/斜体字符的额外宽度,因此该函数认为它有足够的空间来容纳行中的另一个单词。

我不能输出就可以了,但是至少我需要能够识别出什么文本是粗体或斜体。在Google表格中,我该如何编写支持RichText的自定义函数?

解决方法

由于有了TheMaster的评论,所以我可以通过将功能更改为以下内容来创建解决方案:

function preview(startcol,startrow)
{
  var str = String.fromCharCode(64 + startcol) + startrow;
  var richtext = SpreadsheetApp.getActiveSpreadsheet().getRange(str).getRichTextValue();
  var runs = richtext.getRuns();
...

并将我的通话设置为

=preview(COLUMN(<CELL>),ROW(<CELL>))

通过遍历运行getTextStyle()。IsBold()或.IsItalic()的运行,我可以说明RichText属性。

if(runs[i].getTextStyle().IsBold() && runs[i].getTextStyle().IsItalic())
{
  wordWidth += getCharacterWidthBoldItalic(char);
}
else if(runs[i].getTextStyle().IsBold())
{
  wordWidth += getCharacterWidthBold(char);
}
else if(runs[i].getTextStyle().IsItalic())
{
  wordWidth += getCharacterWidthItalic(char);
}
else
{
  wordWidth += getCharacterWidth(char);
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...