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);
}