javascript - 将文本样式应用于谷歌工作表单元格中的正则表达式模式

标签 javascript google-sheets textstyle

我想将部分字符串(通过正则表达式)转换为特定的文本样式,但我无法管理循环。我总是遇到错误。

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

这是表格(法国参数)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);
}

最佳答案

这里的一个问题是作者姓名有时用逗号分隔,有时仅用空格分隔。请参阅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 中,我们将用它来查找 startOffsetendOffset > setTextStyle() 方法的值。

现在我们有:

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() 方法,通过添加我们之前找到的 startend 值来索引

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 如何处理电子表格和富文本格式的许多细节。您需要设置自己的样式,但从您的代码来看,您似乎已经知道如何执行此操作。你的问题的棘手部分是弄清楚如何识别作者子字符串,所以这就是我的答案的重点。

关于javascript - 将文本样式应用于谷歌工作表单元格中的正则表达式模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66825970/

相关文章:

google-apps-script - 从工作表中自动填充 Google 文档的当前日期

flutter - 如何在flutter中设置Cupertino应用程序的textStyle

javascript - 如何在具有 contenteditable 属性的 div 中应用文本样式

javascript - 在 JavaScript 中是否有一种简单的方法可以用空字符串替换 NaN?

google-sheets - ARRAYFORMULA COUNTIF 每行分别

javascript - 打印选项打不开

android - Android 中漂亮的描边文字

javascript - Accordion 菜单不可点击

javascript - 如何在单个 .yaml 文件中设置 yaml 引用?

javascript - 是否可以在图层中切出文本形状的孔?