【问题标题】:Apply text syle to a regex pattern in google sheet cells将文本样式应用于谷歌工作表单元格中的正则表达式模式
【发布时间】:2021-06-23 19:34:15
【问题描述】:

我想将部分字符串(通过正则表达式)转换为特定的文本样式,但我无法管理循环并且总是出错。请你帮助我好吗 ?非常感谢。

第一行是原始文本(用逗号分隔的字符串),第二行是所需的文本样式。

这是表格(法语参数)https://docs.google.com/spreadsheets/d/1vq0Ai_wEr3MamEQ-kMsXW7ZGg3RxrrkE5lITcYjO-rU/edit?usp=sharing

function NomsStyleBotanique(){
  const classeur = SpreadsheetApp.getActive();  // var Feuille = classeur.getSheetByName('Feuille 1'); 
  var ligne = classeur.getCurrentCell().getRow();
  var colonne = classeur.getCurrentCell().getColumn();
  var range = classeur.getActiveRange();

  var richTextValues = range.getRichTextValues().map(([a]) => {
  var text = a.getText();
  var pos = 0;
  
  var myregEx = /,/g;
  var Noms = text.split(myregEx);
  
  var textStyleNomPlante = SpreadsheetApp.newTextStyle()
        .setFontSize(10)
        .setForegroundColor("black")
        .setFontFamily("Times New Roman")
        .setItalic(false)
        .build();

    var textStyleNomAuteur = SpreadsheetApp.newTextStyle()
        .setFontSize(10)
        .setForegroundColor("#616399")     // ("grey")
        .setFontFamily("Times New Roman")
        .setItalic(true)
        .build();

  var nbPhrases = [];
  var i =0;
 
  while (Noms){ i++; nbPhrases.push(Noms[i]); // SpreadsheetApp.getUi().alert(Noms[i]); 
  
  for (var i=0;i<nbPhrases.length;i++){
  
  var myarr = Noms[i].split(" ");
  var Espace1 = myarr[0].length+1;
  var Espace2 = myarr[1].length+1;

  if (Noms[i]){
    if ((Noms[i].indexOf("subsp") > 1) || (Noms[i].indexOf("var.") > 1)){
    var Espace3 = myarr[2].length+1;
    var Espace4 = myarr[3].length+1;
    pos = Espace1+Espace2+Espace3+Espace4; }

  else {   pos = Espace1+Espace2;  } // pos = text.match(new RegExp(/\\s/, 'g'))[2]; 

  var position = pos;

  if (position > -1){
      var temp = a.getTextStyle(0, position - 1);

    return [
        SpreadsheetApp.newRichTextValue()
        .setText(Noms[i])
        .setTextStyle(0, position - 1, textStyleNomPlante)
        .setTextStyle(position, Noms[i].length, textStyleNomAuteur)
        .build()
      ];
    }
    return [SpreadsheetApp.newRichTextValue().setText(Noms[i]).setTextStyle(Noms[i].getTextStyle()).build()];
   }
  }
 }
} // fin boucle
);
range.setRichTextValues(richTextValues);
}

【问题讨论】:

  • 很遗憾,我无法理解您的示例图片。我为此道歉。可以问一下具体情况吗?
  • 感谢您回复并添加更多信息。我有个问题。当我看到Desired style 的值时,我无法理解(Griseb.) Briq 不是红色字体颜色的逻辑。我为此道歉。我能问你实现目标的逻辑细节吗?
  • 感谢您的回复。不幸的是,我仍然无法理解实现目标的逻辑。我为我的理解不佳道歉。我能问你实现目标的逻辑细节吗?
  • 嗨@Nad,这里的问题是您的作者姓名有时用逗号分隔,有时作者姓名没有用逗号分隔。参见Ten., Benth., Swart,(Ten.) Kerguélen。您的代码没有考虑到这一点。我不知道是否有一种方法可以创建一种模式来识别植物名称之间的中断与作者姓名之间的中断。我需要查看更多数据以确定我们是否可以使用其他模式。
  • 感谢您的回复。现在我注意到你的问题已经解决了。我很高兴。

标签: google-sheets script textstyle


【解决方案1】:

这里的一个问题是作者姓名有时用逗号分隔,有时仅用空格分隔。请参阅 Ten., Benth., Swart,(Ten.) Kerguélen。但是,在您的评论中,您说这种情况并不经常发生,您可以手动处理,所以我们现在假设作者姓名从不使用逗号分隔。

在假设的情况下,我们可以将每个单元格的内容按, 拆分,分别处理每个植物名称/作者:

const plants = text.split(', ')

for (const plant of plants) {
  // Find start/end of authors substring.
}

我们需要的是找到“植物作者”子字符串开始和结束的索引。

找到植物作者子字符串的结束索引很容易;它只是整个植物字符串的结尾:

const end = plant.length

要查找植物作者子字符串的开头,我们可以查找空格' ' 的索引。 (您需要为此编写自己的getIndices() 方法。)如果植物包含subsp.var.,则起始索引是第4 个空格;否则,它是第二个空格:

let start
spaceIndices = getIndices(plant, ' ')
if (plant.includes('subsp.') || plant.includes('var.')) start = spaceIndices[3] + 1  // Add 1 to not include the space itself
else start = spaceIndices[1] + 1  // Add 1 to not include the space itself

一旦我们有了开始/结束索引,我们可以将它们放入一个数组offsets,我们将使用它来查找setTextStyle() 方法的startOffsetendOffset 值。

所以现在我们有:

const plants = text.split(', ')
let offsets = []
for (const plant of plants) {
  const end = plant.length
  
  let start
  spaceIndices = getIndices(plant, ' ')
  if (plant.includes('subsp.') || plant.includes('var.')) start = spaceIndices[3] + 1
  else start = spaceIndices[1] + 1

  offsets.push({
    start,
    end
  })
}

接下来,我们必须启动 RichTextValueBuilder 对象并循环遍历 offsets 数组以确定 startOffsetendOffset 值应该是什么 setTextStyles() 方法通过添加 where start 和 @ 987654342@ 我们之前找到的索引值

let richText = SpreadsheetApp.newRichTextValue()
  .setText(text)
let authorTextStyle = SpreadsheetApp.newTextStyle()
  .setBold(true)
  .build()

let plantStartIndex = 0
for (const offset of offsets) {
  const startOffset = plantStartIndex + offset.start
  const endOffset = plantStartIndex + offset.end
  richText = richText.setTextStyle(startOffset, endOffset, authorTextStyle)
  plantStartIndex = plantStartIndex + offset.end + 2  // Add 2 to not include the ", " separator
}

最后,构建RichTextValue 对象:

richText = richText.build()

…并将其与您的其余代码联系在一起:

function stylePlantNames() {

  const ss = SpreadsheetApp.getActive()
  const range = ss.getActiveRange()
  const values = range.getValues()

  let richTextValues = []

  for (const row of values) {
    let text = row[0]

    const plants = text.split(', ')

    let offsets = []
    for (const plant of plants) {
      const end = plant.length

      let start
      spaceIndices = getIndices(plant, ' ')
      if (plant.includes('subsp.') || plant.includes('var.')) start = spaceIndices[3] + 1
      else start = spaceIndices[1] + 1

      offsets.push({
        start,
        end
      })
    }

    let richText = SpreadsheetApp.newRichTextValue()
      .setText(text)
    let authorTextStyle = SpreadsheetApp.newTextStyle()
      .setBold(true)
      .build()

    let plantStartIndex = 0
    for (const offset of offsets) {
      const startOffset = plantStartIndex + offset.start
      const endOffset = plantStartIndex + offset.end
      richText = richText.setTextStyle(startOffset, endOffset, authorTextStyle)
      plantStartIndex = plantStartIndex + offset.end + 2
    }

    richText = richText.build()
    richTextValues.push([richText])

  }

  range.setRichTextValues(richTextValues)

}

function getIndices(str, char) {
  let indices = [];
  for (var i = 0; i < str.length; i++) {
    if (str[i] === char) indices.push(i);
  }
  return indices;
}

我跳过了有关 Apps 脚本 API 如何用于电子表格和富文本格式的许多细节。您需要设置自己的样式,但从您的代码看来,您似乎已经知道如何做到这一点。您问题的棘手部分是弄清楚如何识别作者子字符串,所以这就是我回答的重点。

【讨论】:

  • 非常感谢@Adam,你已经完全理解了我的需要!我对那个 .map 循环感到很生气,并且阅读了一些旧的 stackoverflow 帖子,我不确定它是否可以实现。生活保佑你,我现在可以节省几个小时的打字时间,而且你还教了我一些我什至不知道的功能:-)
猜你喜欢
  • 1970-01-01
  • 2019-02-14
  • 2022-11-21
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
相关资源
最近更新 更多