从 Google Apps 脚本中的表格模板创建 Google 文档
Creating a Google Doc from a template with tables in Google Apps Script
这是一个 Google Apps 脚本,用于从模板和 Google Spreadsheet.
中的值创建 Google 文档
它从您的 Google Spreadsheet(具有突出显示的单元格或行的行)中的活动行中获取字段,并使用 Google 文档模板(由 TEMPLATE_ID) 用这些字段替换模板中的占位符创建一个文档。
占位符通过在它们周围有 % 来标识,例如%姓名%。 运行 使用在 sheet.
中创建的自定义“创建文档”菜单
现在,我的问题是,如果我还有一个带有普通占位符的 table(请参见图片或 link),如果我还放置了占位符 %,我该如何继续Table文档模板中的 1%?
在这种情况下,占位符 %Name%、%Surname%、%Fruit% 必须仅从第二行获取值。占位符 %Table 1% 必须取值直到 table(第 5 行)结束。
https://docs.google.com/spreadsheets/d/1l3bCuyRnz_ylMHMfhbRC-_L5bLkWwEkrzGKgy46Kvnk/edit?usp=sharing
function myfunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var TEMPLATE_ID = 'xxx';
//var TEMPLATE_ID = ss.getRange("TEMPLATEID").getValue();
var ui = SpreadsheetApp.getUi();
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs')
return
}
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId)
var docFile = DriveApp.getFileById(copyFile.getId()); // Get Document as File
var FILE_NAME = ui.prompt('Insert file name:', ui.ButtonSet.OK);
FILE_NAME.getSelectedButton() == ui.ButtonSet.OK
copyDoc.setName(FILE_NAME.getResponseText())
var copyBody = copyDoc.getActiveSection(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRowIndex = activeSheet.getActiveRange().getRowIndex(),
activeRow = activeSheet.getRange(activeRowIndex, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0
for (;columnIndex < headerRow[0].length; columnIndex++) {
var nextValue = formatString(activeRow[0][columnIndex])
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%', nextValue)
}
copyDoc.saveAndClose()
SpreadsheetApp.getUi().alert('File doc created!!')
}
解决方案:
- 定义哪些列对应于 table 数据。在下面的示例中(这是通过下面示例中的
tableColumn
完成的,其中第一个值对应于第一 table 列,第二个值对应于最后一列)。
- 遍历 sheet 列时,检查该列是否对应于 table 值。如果没有,只需执行与原始代码中相同的操作。如果是:
- 获取与这些列 (
tableValues
) 相关的所有值。
- 使用findText(searchPattern)获取存在`%Table 1%占位符的元素。
- 使用 getChildIndex 获取此占位符所在元素的索引,并删除该元素的文本(占位符)。
- 使用 insertTable(childIndex, cells) 在指定索引处插入 table,使用源值。
代码示例:
function myfunction() {
var tableColumn = [3,5]; // Table header is in column C to E
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var TEMPLATE_ID = 'xxx';
var ui = SpreadsheetApp.getUi();
if (TEMPLATE_ID === '') {
ui.alert('TEMPLATE_ID needs to be defined in code.gs')
return
}
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy();
var copyId = copyFile.getId();
var copyDoc = DocumentApp.openById(copyId);
var FILE_NAME = ui.prompt('Insert file name:', ui.ButtonSet.OK);
copyDoc.setName(FILE_NAME.getResponseText());
var copyBody = copyDoc.getBody();
var lastColumn = sheet.getLastColumn();
var activeRowIndex = sheet.getActiveRange().getRowIndex();
var activeRow = sheet.getRange(activeRowIndex, 1, 1, lastColumn).getValues()[0];
var headerRow = sheet.getRange(1, 1, 1, lastColumn).getValues()[0];
for (var columnIndex = 0; columnIndex < headerRow.length; columnIndex++) {
if (columnIndex === tableColumn[0] - 1) { // Check if column corresponds to table data
try {
var tableValues = sheet.getRange(2, tableColumn[0], sheet.getLastRow()-1,tableColumn[1]-tableColumn[0]+1).getValues();
var placeholder = `%${headerRow[tableColumn[0]-1]}%`;
var rangeElement = copyBody.findText(placeholder);
var element = rangeElement.getElement();
console.log(element.asText().getText())
var childIndex = copyBody.getChildIndex(element.getParent());
console.log(childIndex)
const elementText = copyBody.getChild(childIndex).asText().getText();
const [beforeText, afterText] = elementText.split(placeholder);
copyBody.getChild(childIndex).asText().setText('');
copyBody.insertParagraph(childIndex, beforeText);
copyBody.insertTable(childIndex+1, tableValues);
copyBody.insertParagraph(childIndex+2, afterText);
} catch(err) {
continue;
}
} else if (columnIndex < tableColumn[0] - 1 || columnIndex > tableColumn[1] - 1) {
var nextValue = formatString(activeRow[columnIndex]);
copyBody.replaceText('%' + headerRow[columnIndex] + '%', nextValue);
}
}
copyDoc.saveAndClose();
SpreadsheetApp.getUi().alert('File doc created!!')
}
这是一个 Google Apps 脚本,用于从模板和 Google Spreadsheet.
中的值创建 Google 文档它从您的 Google Spreadsheet(具有突出显示的单元格或行的行)中的活动行中获取字段,并使用 Google 文档模板(由 TEMPLATE_ID) 用这些字段替换模板中的占位符创建一个文档。
占位符通过在它们周围有 % 来标识,例如%姓名%。 运行 使用在 sheet.
现在,我的问题是,如果我还有一个带有普通占位符的 table(请参见图片或 link),如果我还放置了占位符 %,我该如何继续Table文档模板中的 1%?
在这种情况下,占位符 %Name%、%Surname%、%Fruit% 必须仅从第二行获取值。占位符 %Table 1% 必须取值直到 table(第 5 行)结束。
https://docs.google.com/spreadsheets/d/1l3bCuyRnz_ylMHMfhbRC-_L5bLkWwEkrzGKgy46Kvnk/edit?usp=sharing
function myfunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var TEMPLATE_ID = 'xxx';
//var TEMPLATE_ID = ss.getRange("TEMPLATEID").getValue();
var ui = SpreadsheetApp.getUi();
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs')
return
}
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId)
var docFile = DriveApp.getFileById(copyFile.getId()); // Get Document as File
var FILE_NAME = ui.prompt('Insert file name:', ui.ButtonSet.OK);
FILE_NAME.getSelectedButton() == ui.ButtonSet.OK
copyDoc.setName(FILE_NAME.getResponseText())
var copyBody = copyDoc.getActiveSection(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRowIndex = activeSheet.getActiveRange().getRowIndex(),
activeRow = activeSheet.getRange(activeRowIndex, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0
for (;columnIndex < headerRow[0].length; columnIndex++) {
var nextValue = formatString(activeRow[0][columnIndex])
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%', nextValue)
}
copyDoc.saveAndClose()
SpreadsheetApp.getUi().alert('File doc created!!')
}
解决方案:
- 定义哪些列对应于 table 数据。在下面的示例中(这是通过下面示例中的
tableColumn
完成的,其中第一个值对应于第一 table 列,第二个值对应于最后一列)。 - 遍历 sheet 列时,检查该列是否对应于 table 值。如果没有,只需执行与原始代码中相同的操作。如果是:
- 获取与这些列 (
tableValues
) 相关的所有值。 - 使用findText(searchPattern)获取存在`%Table 1%占位符的元素。
- 使用 getChildIndex 获取此占位符所在元素的索引,并删除该元素的文本(占位符)。
- 使用 insertTable(childIndex, cells) 在指定索引处插入 table,使用源值。
代码示例:
function myfunction() {
var tableColumn = [3,5]; // Table header is in column C to E
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var TEMPLATE_ID = 'xxx';
var ui = SpreadsheetApp.getUi();
if (TEMPLATE_ID === '') {
ui.alert('TEMPLATE_ID needs to be defined in code.gs')
return
}
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy();
var copyId = copyFile.getId();
var copyDoc = DocumentApp.openById(copyId);
var FILE_NAME = ui.prompt('Insert file name:', ui.ButtonSet.OK);
copyDoc.setName(FILE_NAME.getResponseText());
var copyBody = copyDoc.getBody();
var lastColumn = sheet.getLastColumn();
var activeRowIndex = sheet.getActiveRange().getRowIndex();
var activeRow = sheet.getRange(activeRowIndex, 1, 1, lastColumn).getValues()[0];
var headerRow = sheet.getRange(1, 1, 1, lastColumn).getValues()[0];
for (var columnIndex = 0; columnIndex < headerRow.length; columnIndex++) {
if (columnIndex === tableColumn[0] - 1) { // Check if column corresponds to table data
try {
var tableValues = sheet.getRange(2, tableColumn[0], sheet.getLastRow()-1,tableColumn[1]-tableColumn[0]+1).getValues();
var placeholder = `%${headerRow[tableColumn[0]-1]}%`;
var rangeElement = copyBody.findText(placeholder);
var element = rangeElement.getElement();
console.log(element.asText().getText())
var childIndex = copyBody.getChildIndex(element.getParent());
console.log(childIndex)
const elementText = copyBody.getChild(childIndex).asText().getText();
const [beforeText, afterText] = elementText.split(placeholder);
copyBody.getChild(childIndex).asText().setText('');
copyBody.insertParagraph(childIndex, beforeText);
copyBody.insertTable(childIndex+1, tableValues);
copyBody.insertParagraph(childIndex+2, afterText);
} catch(err) {
continue;
}
} else if (columnIndex < tableColumn[0] - 1 || columnIndex > tableColumn[1] - 1) {
var nextValue = formatString(activeRow[columnIndex]);
copyBody.replaceText('%' + headerRow[columnIndex] + '%', nextValue);
}
}
copyDoc.saveAndClose();
SpreadsheetApp.getUi().alert('File doc created!!')
}