【问题标题】:Google Sheets App Script - Custom Function to find RichText (Bold/Italic) locationsGoogle Sheets App Script - 用于查找 RichText(粗体/斜体)位置的自定义函数
【发布时间】:2020-08-14 07:22:56
【问题描述】:

我目前正在开展一个项目,该项目使用 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(&lt;CELL&gt;) 调用它(getCharacterWidth 只是从字符 宽度映射中提取一个整数)。

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

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

例如,原文是:

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

=preview(text) 应该理想情况下是这样的:

这是斜体

这是粗体

这是粗体

和斜体

但是,它最终可能会变成这样:

这是斜体。

这是粗体。这个

是粗体和斜体。

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

不能输出也没关系,但我至少需要能够识别哪些文本是粗体还是斜体。在 Google 表格中,我如何编写能够识别 RichText 的自定义函数?

【问题讨论】:

  • 为了正确理解您的问题,您能否提供您期望的示例输入和输出?
  • @Tanaike 我添加了一个示例。让我知道这是否有意义。
  • 您是否在活动范围上尝试过 getRichText?你能展示完整的preview 函数吗?
  • 感谢您回复并添加更多信息。当我看到它时,我可以理解This is italic.This is bold.。但我无法理解检索This is boldand italic. 的逻辑。可以问一下它的详细信息吗?
  • @TheMaster 不,我没有,我不确定这到底是怎么做到的......我可以向您展示完整的预览功能,但除了一些 javascript 文本处理之外,它真的没什么。我真的让它返回 'typeof(text)' 以验证它是否将其视为一个字符串,我不确定如何准确地获得活动范围。

标签: google-apps-script google-sheets google-sheets-formula custom-function


【解决方案1】:

感谢 TheMaster 的 cmets,我能够通过将函数更改为以下内容来创建解决方案:

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

【讨论】:

  • 你能补充一下你遇到这些粗体字的逻辑吗?
  • @TheMaster 当然,虽然它只是一个 if-else 块,我在其中检查 IsBold 和 IsItalic 是否同时处于活动状态并相应地使用字符宽度。
猜你喜欢
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多