我想将部分字符串(通过正则表达式)转换为特定的文本样式,但我无法管理循环。我总是遇到错误。
第一行是原始文本(以逗号分隔的字符串),第二行是所需的文本样式。
这是表格(法国参数)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
中,我们将用它来查找 startOffset
和 endOffset
> 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
数组以确定 startOffset
和 endOffset
值应该用于 setTextStyles()
方法,通过添加我们之前找到的 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 // 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/