将文本样式应用于 google sheet 单元格中的正则表达式模式
Apply text syle to a regex pattern in google sheet cells
我想将部分字符串(通过正则表达式)转换为特定的文本样式,但我无法管理循环并且总是出错。请你帮助我好吗 ?非常感谢。
第一行是原文(字符串用逗号隔开),第二行是想要的文字样式。
这里是sheet(法语参数)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);
}
这里的一个问题是作者姓名有时用逗号分隔,有时只用 space 分隔。参见 Ten., Benth., Swart,
和 (Ten.) Kerguélen
。但是,在您的评论中,您说这种情况不会经常发生,您可以手动处理,所以我们现在假设作者姓名永远不会用逗号分隔。
有了假设,我们可以将每个单元格的内容按,
拆分,对每个植物name/author分别处理:
const plants = text.split(', ')
for (const plant of plants) {
// Find start/end of authors substring.
}
我们需要找到“plant author”子字符串开始和结束的索引。
找到植物作者子字符串的结束索引很容易;它只是整个植物字符串的结尾:
const end = plant.length
要找到植物作者子串的开始,我们可以查找 spaces ' '
的索引。 (您需要为此编写自己的 getIndices()
方法。)如果植物包含 subsp.
或 var.
,则起始索引是第 4 个 space;否则,它是第二个 space:
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
一旦我们有了 start/end 索引,我们就可以将它们放入一个数组 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 如何处理电子表格和富文本格式的许多细节。您需要设置自己的样式,但从您的代码来看,您似乎已经知道如何执行此操作。你的问题中棘手的部分是弄清楚如何识别作者子字符串,所以这就是我回答的重点。
我想将部分字符串(通过正则表达式)转换为特定的文本样式,但我无法管理循环并且总是出错。请你帮助我好吗 ?非常感谢。
第一行是原文(字符串用逗号隔开),第二行是想要的文字样式。
这里是sheet(法语参数)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);
}
这里的一个问题是作者姓名有时用逗号分隔,有时只用 space 分隔。参见 Ten., Benth., Swart,
和 (Ten.) Kerguélen
。但是,在您的评论中,您说这种情况不会经常发生,您可以手动处理,所以我们现在假设作者姓名永远不会用逗号分隔。
有了假设,我们可以将每个单元格的内容按,
拆分,对每个植物name/author分别处理:
const plants = text.split(', ')
for (const plant of plants) {
// Find start/end of authors substring.
}
我们需要找到“plant author”子字符串开始和结束的索引。
找到植物作者子字符串的结束索引很容易;它只是整个植物字符串的结尾:
const end = plant.length
要找到植物作者子串的开始,我们可以查找 spaces ' '
的索引。 (您需要为此编写自己的 getIndices()
方法。)如果植物包含 subsp.
或 var.
,则起始索引是第 4 个 space;否则,它是第二个 space:
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
一旦我们有了 start/end 索引,我们就可以将它们放入一个数组 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 如何处理电子表格和富文本格式的许多细节。您需要设置自己的样式,但从您的代码来看,您似乎已经知道如何执行此操作。你的问题中棘手的部分是弄清楚如何识别作者子字符串,所以这就是我回答的重点。