Метод .filter() последовательно сравнивает все элементы массива с условием фильтра, указанным в callback функции (функции обратного вызова). То есть метод, по сути, представляет собой цикл for, внутри которого callback функция последовательно обрабатывает все элементы массива.
Метод .filter() может передавать в callback функцию три параметра:
Для того, чтобы элемент, удовлетворяющий условию фильтра, был выбран, callback функция должна вернуть значение true.
Все элементы, для которых callback функция вернула знечение true, собираются в отдельный массив, который может быть сохранён в новом массива (в примерах ниже это массив result2).
В трёх вариантов примера, представленных ниже (examples #1, #2, #3) рассмотрено одно и то же условие фильтра - отобрать все элементы массива со значением > 3.
В последнем примере (наиболее оптимальным с точки зрения краткости кода) логическое выражение, вместо оператора if , поставлено непосредственно в return . Поскольку, как известно, логическое выражение может принимать только 2 значения: true или false.
const arr = [1, 2, 9, 4, 1, 6, 5];
let result = arr.filter((item, idx, arr) => console.log(item, idx, arr));
// [20-06-15 14:53:21:082 EEST] 1 0 [ 1, 2, 9, 4, 1, 6, 5 ]
// [20-06-15 14:53:21:084 EEST] 2 1 [ 1, 2, 9, 4, 1, 6, 5 ]
// [20-06-15 14:53:21:085 EEST] 9 2 [ 1, 2, 9, 4, 1, 6, 5 ]
// [20-06-15 14:53:21:086 EEST] 4 3 [ 1, 2, 9, 4, 1, 6, 5 ]
// [20-06-15 14:53:21:087 EEST] 1 4 [ 1, 2, 9, 4, 1, 6, 5 ]
// [20-06-15 14:53:21:089 EEST] 6 5 [ 1, 2, 9, 4, 1, 6, 5 ]
// [20-06-15 14:53:21:090 EEST] 5 6 [ 1, 2, 9, 4, 1, 6, 5 ]
console.log(result);
// [20-06-15 14:53:21:091 EEST] []
// variant #1
let result2 = arr.filter(item => {
if (item > 3) {
return true;
} else {
return false;
};
});
// variant #2
result2 = arr.filter(item => {
return item > 3;
});
// variant #3
result2 = arr.filter(item => item > 3);
console.log(result2); // [ 9, 4, 6, 5 ]
var sf = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
let data = sf.getDataRange().getValues().slice(1);
console.log(data);
// [ [ '', false, 'apples', 5 ],
// [ '', true, 'carrots', 12 ],
// [ '', false, 'grapes', 4 ],
// [ '', false, 'plums', 3 ],
// [ '', true, 'strawberry', 9 ],
// [ '', false, 'perches', 4 ],
// [ '', false, 'bananas', 1 ] ]
let newData = data.filter(item => item[1]);
console.log(newData);
// [ [ '', true, 'carrots', 12 ],
// [ '', true, 'strawberry', 9 ] ]
И ещё одни полезный скрипт, который не вошёл в это видео - скрипт, который фильтрует ТОЛЬКО уникальные значения.
Идея очень проста: для каждого элемента массива находится его индекс и сравнивается с текущим индексом значения этого элемента в массиве. Если элемент не встретился ранее, то значения индексов будут равны, и функция uniqValue вернёт true .
В первом примере, для лучшего понимания алгоритма, функция uniqValue написана отдельно. Во втором - непосредственно "встроена" в метод .filter
let arrayNotUniq = [1, 5, 9, 5];
//variant #1
function uniqValues(item, index, arr) {
return arr.indexOf(item) === index;
}
let arrayUniq = arrayNotUniq.filter(uniqValues) // [1, 5, 9]
//variant #2
let arrayUniq = arrayNotUniq.filter((item, index, arr) => {
return arr.indexOf(item) === index;
}); // [1, 5, 9]
Дополнительную информацию вы можете найти в этом видео:
Метод .map() последовательно перебирает все элементы массива. То есть, по сути, представляет из себя цикл for, где переменная цикла изменяется от индекса первого элемента до последнего.
Этот метод может передавать в callback функцию 3 элемента:
В примере #1 приводится умножение кажного элемента массива на 2. То есть callback функция каждый раз возвращает элемент массива, умноженный на 2.
В примере #2 проводится исследования параметров метода. Поэтому callback функция ничего не возращет, а только выводит на печать передаваемые её параметры. В каждом цикле это: значение элемента массива, его индекс и сам массив.
var arr = [1, 2, 3];
// example #1
var arr2 = arr.map(x => x * 2); // [ 2, 4, 6 ]
// example #2
var arr2 = arr.map((x, y, z) => {
console.log(x + "|" + y + "|" + z);
});
// 1|0|1,2,3
// 2|1|1,2,3
// 3|2|1,2,3
Скрипты, представленные ниже, обрабатывают один и тот же массив двумя способами:
1.) с помощью цикла for
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var arrM = ss.getRange(1, 1, 10).getValues(); // [[10. Will Smith: $35 million], [9. Paul Rudd: $41 million], [8. Chris
var arrW = ss.getRange(14, 1, 10).getValues(); // [[10. Ellen Pompeo: $22 million], [9. Charlize Theron: $23 million], [8.
var arr = arrM.concat(arrW);
for (var i = 0; i < arr.length; i++) {
arr[i][0] = arr[i][0].replace(":", "").replace("$", "").replace(" (tie)", "(tie)").replace(" Jr", "Jr"); //
arr[i] = arr[i][0].split(' '); // [10., Will, Smith, 35, million]
arr[i][1] = arr[i][1] + " " + arr[i][2]; // [10., Will Smith, Smith, 35, million]
arr[i].splice(2, 1); // [10., Will Smith, 35, million]
if (i < 10) {
arr[i][3] = 'man';
} else {
arr[i][3] = 'woman';
};
};
arr.sort(function(a, b) {
return b[2] - a[2];
});
for (var i = 0; i < arr.length; i++) {
arr[i][0] = i + 1;
Logger.log(arr[i]);
};
ss.getRange(2, 6, arr.length, arr[0].length).setValues(arr);
2.) и с помощью метода .map():
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var arrM = ss.getRange(1, 1, 10).getValues(); // [[10. Will Smith: $35 million], [9. Paul Rudd: $41 million], [8. Chris
var arrW = ss.getRange(14, 1, 10).getValues(); // [[10. Ellen Pompeo: $22 million], [9. Charlize Theron: $23 million], [8.
var arr = arrM.concat(arrW);
var arr2 = arr.map(x => x[0].replace(":", "").replace("$", "")
.replace(" (tie)", "(tie)").replace(" Jr", "Jr")
.split(' ')); // [ [ '10.', 'Will', 'Smith', '35', 'million' ],
arr = arr2.map(x => [x[2], x[1] + ' ' + x[2], x[3], x[4]]);
arr = arr.map((x, i) => {
(i < 10) ? x[3] = 'man' : x[3] = 'woman' ;
return x;
}); // [ [ 'Smith', 'Will Smith', '35', 'man' ],
arr.sort((a, b) => a[0].localeCompare(b[0])); // [ [ '1.', 'Dwayne Johnson', '89.4', 'man' ],
arr = arr.map((x, i) => {
x[0] = i + 1;
return x;
});
console.log(arr);
ss.getRange(2, 6, arr.length, arr[0].length).setValues(arr);
Дополнительную информацию вы можете найти в этом видео:
Прежде чем перейти к рассмотрению метода .sort, необходимо хотябы несколько слов сказать о функциях, используемых в JavaScript и Google Apps Script.
Higher-order functions (Функции более высокого порядка) - называются функции, использующие в качестве аргументов и/или возвращаемых объектов функции первого класса. (Пример - функция .sort)
First-class functions (Функции первого класса) используются в качестве аргументов и/или возвращаемых объектов для функций более высокого порядка. (Пример - функции, являющиеся аргументами для функции .sort)
const arr = [1, 2, 3, 10, 20];
// ========== Higher-order functions ===============
//arr.sort(sortFunction)
// ========== First-class functions ================
// function definition
function twoTimes(x) {
return x * 2;
};
// another function definition
var twice;
twice = function(x) {return x * 2};
// arrow function
twice = (x) => x * 2;
// arrow function with 1 argument
twice = x => x * 2;
console.log(twice(3));
console.log(typeof twice);
// 1.) function as argument another function
var fourTimes = (x, twice) => twice(x);
console.log(fourTimes(3, twice)); // 6
// 2.) return function
var fourTimes = (x) => x * 4;
var xTimes = (x, order) => {
if (x / order == 4) {
return fourTimes;
} else if (x / order == 2) {
return twice;
};
};
var y = xTimes(12, 3); // 8
console.log(y(2)); // =6
console.log('y is ' + typeof y); // y is function
// numbers sorting
const arr = [1, 2, 10, 20];
arr.sort((a, b) => a - b); // [ 20, 10, 2, 1 ]
arr.sort((a, b) => b - a); // [ 1, 2, 10, 20 ]
// string sorting
const arr1 = ['a', 'b', 'A', 'B', 'г', 'Г', 'д', 'Д'];
arr1.sort(); // [ 'A', 'B', 'a', 'b', 'Г', 'Д', 'г', 'д' ]
arr1.sort((a, b) => a.localeCompare(b)); // [ 'a', 'A', 'b', 'B', 'г', 'Г', 'д', 'Д' ]
arr1.sort((a, b) => b.localeCompare(a)); // [ 'Д', 'д', 'Г', 'г', 'B', 'b', 'A', 'a' ]
// 2-dimensional array
var arr_2 = [[1, 5, 6],
[3, 7, 9],
[9, 2, 1]];
arr_2.sort((a, b) => b[1] - a[1]); // [ [ 3, 7, 9 ],
// [ 1, 5, 6 ],
// [ 9, 2, 1 ] ]
// JSON objects
var actors = [
{name: 'Dwayne Johnson', income: 89.4},
{name: 'Chris Hemsworth', income: 76.4},
{name: 'Robert DowneyJr.', income: 66},
{name: 'Akshay Kumar', income: 65},
{name: 'Jackie Chan', income: 58},
];
actors.sort((a, b) => a.income - b.income);
//[ { name: 'Jackie Chan', income: 58 },
// { name: 'Akshay Kumar', income: 65 },
// { name: 'Robert DowneyJr.', income: 66 },
// { name: 'Chris Hemsworth', income: 76.4 },
// { name: 'Dwayne Johnson', income: 89.4 } ]
actors.sort((a, b) => a.name.localeCompare(b.name));
// [ { name: 'Akshay Kumar', income: 65 },
// { name: 'Chris Hemsworth', income: 76.4 },
// { name: 'Dwayne Johnson', income: 89.4 },
// { name: 'Jackie Chan', income: 58 },
// { name: 'Robert DowneyJr.', income: 66 } ]
Дополнительную информацию вы можете найти в этом видео:
Массивы в Apps Script можно создать несколькими способами:
function createArray() {
// ======== HOW TO CREATE ARRAY? ===========
// 1.) Write
var arr = [1, 2, 3];
// 2.) Read from spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var arr1 = ss.getDataRange().getValues(); // [[1.0, 2.0, 3.0]]
// 3.) Using string splitting
var string = 'I am learning Google Spreadsheet';
var arr2 = string.split(' '); // [I, am, learning, Google, Spreadsheet]
// 4.) Using string splitting
var arr3 = 'word'.split(''); // [w, o, r, d]
}
Добавлять элементы в массив можно разными способами:
Если максимальное значение индекса будет превышено более, чем на единицу, то всем элементы между старым и новым максимальными индексами автоматически присваивается значение null.
Значение удаляемого элемнта можно при этом присвоить новой переменной.
function addDeleteItems() {
// ================ ADD ITEMS =======================
// 1.) [index]
var arr4 = [1, 2, 3];
arr4[3] = 4; // [1.0, 2.0, 3.0, 4.0]
arr4[5] = 6; // [1.0, 2.0, 3.0, 4.0, null, 6.0]
arr4[-1] = 0; // [1.0, 2.0, 3.0, 4.0, null, 6.0]
// 2.) .push(value)
arr4.push(7); // [1.0, 2.0, 3.0, 4.0, null, 6.0, 7.0]
// 3.) .unshift(value)
arr4.unshift(0) // [0.0, 1.0, 2.0, 3.0, 4.0, null, 6.0, 7.0]
// ================= DEL ITEMS ======================
// 4.) .pop()
var x = arr4.pop(); // [0.0, 1.0, 2.0, 3.0, 4.0, null, 6.0]
// 5.) .shift()
var x = arr4.shift(); // [1.0, 2.0, 3.0, 4.0, null, 6.0]
// ===== ADD (INSERT), DELETE, CAHGE =================
// 6.) .splice(index, hawManyDelete, whatInsert)
arr4.splice(4, 0, 5); // [1.0, 2.0, 3.0, 4.0, 5.0, null, 6.0]
arr4.splice(5, 1); // [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
// ============ CHANGE ORDER =========================
// 7.) .reverse()
arr4.reverse(); // [6.0, 5.0, 4.0, 3.0, 2.0, 1.0]
// 8.) .sort()
arr4 = [6.0, 5.0, 404.0, 41.0, 4.0, 3.0, 2.0, 1.0];
arr4.sort();
}
Больше информации и примеров вы сможете найти в этом видео:
Данная статья является продолжением статьи Бесконечные Зависимые Выпадающие Списки в Google Sheets.
Здесь описаны изменения изменения и дополнения кода, а именно:
function onEdit(e) {
var row = e.range.getRow();
var col = e.range.getColumn();
var list_name = e.source.getActiveSheet().getName();
var name = e.value;
var oldName = e.oldValue;
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Home');
var mask = JSON.stringify(sh.getRange(row, 1, 1, col).getValues()[0]);
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Home');
var colMax = sh.getLastColumn();
if(list_name === "Home" && name !== oldName && col < colMax) {
fillColumn(row, col, mask);
}
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Custom Menu')
.addItem('Create sheets', 'createSheets')
.addToUi();
}
function fillColumn(row, col, mask) {
// clear dataVal and Value
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Home');
var colMax = sh.getLastColumn();
sh.getRange(row, col + 1, 1, colMax).clearDataValidations().clearContent();
// find date
var sd = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
var arrData = sd.getDataRange().getValues();
var arrData_2 = [];
arrData_2.push(arrData[0]);
var iMax = arrData.length - 1;
for(var i=1; i<=iMax; i++) {
if(JSON.stringify(arrData[i].slice(0, col)) == mask) {
arrData_2.push(arrData[i]);
}
}
// clear Data_2
var sd_2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data_2");
sd_2.getDataRange().clearContent();
// insert data
sd_2.getRange(1, 1, arrData_2.length, arrData_2[0].length).setValues(arrData_2);
// add dataVal
col++;
var list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'];
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Home');
sh.getRange(row, col).setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(false)
.requireValueInRange(sh.getRange('Data_2!$' + list[col - 1] + '$2:$' + list[col - 1] + '$1000'), true)
.build());
}
function createSheets() {
// is exist Home?
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sd = ss.getSheetByName('Data')
// create if not exist
if(!ss.getSheetByName('Home')) {
ss.insertSheet('Home', 0);
// create Data Val
var sh = ss.getSheetByName('Home');
sh.getRange('Home!A2:A20').setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(false)
.requireValueInRange(sh.getRange('Data!$A$2:$A'), true)
.build());
sh.getRange(1, 1, 1, 10).setValues(sd.getRange(1, 1, 1, 10).getValues()).setFontWeight('bold');
};
// is exist Data_2?
if(!ss.getSheetByName('Data_2')) {
// create if not exist
var k = ss.getNumSheets();
ss.insertSheet('Data_2', k + 1);
var sd_2 = ss.getSheetByName('Data_2');
sd_2.getRange(1, 1, 1, 10).setValues(sd.getRange(1, 1, 1, 10).getValues()).setFontWeight('bold');
};
}
Теперь, в этой версии программы появилась возможность по нажатию всего лишь одной(!) кнопки из пользовательского меню автоматически создавать все листы файла, необходимые для работы скрипта (включая форматирование и валидацию данных).
Всё что для этого нужно:
Дополнительную информацию вы можете получить из этого видео:
ВНИМАНИЕ!
У этой статьи есть продолжение: Бесконечные Зависимые Выпадающие Списки в Google Sheets (часть 3)
В статье рассмотрен вариант создания на листе Google Spreadsheet связанных выпадающего списков, практически не ограниченных ни по числу связанных элементов, ни по количству сток на листе.
Скрипт программы представлен ниже:
function onEdit(e) {
let col = e.range.getColumn();
let list_name = e.source.getActiveSheet().getName();
let name = e.value;
if(list_name=="Home") {
fillColumn(col, name);
}
}
function fillColumn(col, name) {
// find date
var sd = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
var iMax = sd.getLastRow();
var col_data = [];
for(var i=2; i<=iMax; i++) {
var x = sd.getRange(i, col).getValue();
if(x == name) {
col_data.push(sd.getRange(i, col+1).getValue());
}
}
// clear Data_2
var sd_2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data_2");
sd_2.getRange(2, col+1, sd_2.getLastRow(), sd_2.getLastColumn()).clearContent();
// insert data
iMax = col_data.length;
for(var i=2; i<=iMax+1; i++) {
sd_2.getRange(i, col+1).setValue(col_data.shift());
}
}
Обратите внимание: имена листов должно ТОЧНО соответствовать именам, указанным в скрипте!
Главный лист: "Home"
лист данных: "Data",лист промежуточных данных: "Data_2"
Эти имена в скрипте выделены красным цветом, поэтому, при желании, их будет не трудно найти, чтобы заменить на имена свои листов.
У этой статьи есть продолжение: Бесконечные Зависимые Выпадающие Списки в Google Sheets (часть 2)
Теперь, в новой версии программы появилась возможность по нажатию всего лишь одной(!) кнопки из пользовательского меню автоматически создавать все листы файла, необходимые для работы скрипта (включая форматирование и валидацию данных).
Эта статья является продолжением другой, более ранней статьи Как автоматически вставлять данные в Google Docs, используя Google Apps Script?, в который описывается алгоритм создания копии шаблона документа Google Doc и вставки в него новых данных, полученных из листа Google Spreadsheet.
Здесь мы рассмотрим новую версию программы генерации документов, которая претерпела ряд существенных изменений.
В первую очередь изменения связаны с тем, что в любом мало-мальски приличном делопроизводстве рано или поздно неизбежно встаёт вопрос об учёте созданных документов. Поэтому в новой редакции программы был добавлен журнал регистрации созданных (сгенерированных) документов, где появилось 2 новых поля: номер документа {document_id} и дата документа {document_date}. (В этой версии программы данные новых полей изменяются вручную). Разумеется, при желании этот список может быть существенно дополнен. Главное, не забывать аккуратно копировать уникальные символы новых полей в соответствующие места вставки шаблонов Google Docs.
Журнал регистрации было решено сделать на главном листе ("Main"). Что существенно изменило интерфейс программы. Данные контрагентов переместились на новый лист "Clients":
А поля с чек-боксами для выбора "ОТ КОГО" (FROM) и "КОМУ" (TO) были заменены полями со списком контрагентов, связанным с листом "Clients".
Добавлен также ещё один вариант запуска скрипта - из пользовательского меню (My menu), которое создаётся автоматически при открытии документа.
Перед запуском скрипта теперь необходимо выбрать в новой строке контрагентов FROM и TO, наименование шаблона Google Docs, номер документа и дату документа. И самое главное помнить, что в новом скрипте генерируется тот документ, в строке которого находится активная ячейки.
Полностью обновлённый скрипт программы представлен ниже:
//create user's menu
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("My menu")
.addItem('Create Document', 'DocGenerator')
.addToUi()
}
//main function
function DocGenerator() {
var sm = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Main");
//find clients info
var row_active = sm.getActiveCell().getRow();
var principal_shart_name = sm.getRange(row_active, 1).getValue();
var attorney_shart_name = sm.getRange(row_active, 2).getValue();
var principal = getClientData(principal_shart_name);
var attorney = getClientData(attorney_shart_name);
//find documents info
var document = {
id:sm.getRange(row_active, 4).getValue(),
date:sm.getRange(row_active, 5).getValue(),
}
// find template
var docName = sm.getRange(row_active, 3).getValue();
var docID = getTemlateID(docName);
var docNameCopy = docName +"_" + document.id +"_" + document.date + "_" + principal.name + "_" + attorney.name;
var file = DriveApp.getFileById(docID);
file.makeCopy(docNameCopy);
var fileCopy = DriveApp.getFilesByName(docNameCopy).next();
var fileCopyID = fileCopy.getId();
// replacement
var body = DocumentApp.openById(fileCopyID).getBody();
body.replaceText('{document_id}', document.id);
body.replaceText('{document_date}', document.date);
body.replaceText('{principal_name}', principal.name);
body.replaceText('{principal_id}', principal.id);
body.replaceText('{principal_id_dateOfIssue}', principal.id_dateOfIssue);
body.replaceText('{attorney_name}', attorney.name);
body.replaceText('{attorney_id}', attorney.id);
body.replaceText('{attorney_id_dateOfIssue}', attorney.id_dateOfIssue);
Browser.msgBox("Completed!");
}
function getClientData(sh_name) {
var sc = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Clients");
var iMax = sc.getLastRow();
for(var i=2; i <= iMax; i++) {
if(sc.getRange(i, 1).getValue() == sh_name) {
break;
}
}
var client = {
short_name: sc.getRange(i, 1).getValue(),
name: sc.getRange(i, 2).getValue(),
id: sc.getRange(i, 3).getValue(),
id_dateOfIssue: sc.getRange(i, 4).getValue(),
};
return client;
}
function getTemlateID(docName) {
var st = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Templates');
var iMax = st.getLastRow();
for(var i=2; i <= iMax; i++) {
if(st.getRange(i, 1).getValue() == docName) {
var docId = st.getRange(i, 2).getValue();
return docId;
}
}
}
Более подробные объяснения о работе скрипта Вы сможете получить, ознакомившись с данным видео:
Этот скрипт будет очень полезен, если необходимо распаковать большое количество zip-файлов.
где folder_with_zip_files - имя папки с zip-файлами.
Результат (распакованные файлы) будет размещён в той же папке.
#!/usr/bin/env python3
from zipfile import ZipFile
import glob, os
zfiles = []
folder_with_zip_files = "/home/su/Downloads/unzipping"
os.chdir(folder_with_zip_files )
for file in glob.glob("*.zip"):
zfiles.append(file)
for zfile in zfiles:
with ZipFile(zfile, 'r') as zipObj:
zipObj.extractall()
Очень часто возникает необходимость создавать однотипные документы, в которых изменяются только данные контрагентов: договора, доверенности, коммерческие предложения и т.д.
Совершенно логичное решение в подобной ситуации:
Сама идея определения места вставки и последующей вставки на это место нужного значения заключается в создании на листе Google Doc уникального набора символов, который можно было бы однозначно идентифицировать и заменить с помощью метода замены текста replaceText:
body.replaceText("{unique label}", "klient data");
Начнём с таблицы. В нашем примере мы сделали три "информационных столбца": имя клиента, номер ID, дата издания ID. Чтобы облегчить редактирование шаблона имена столбцов мы назовем их также, как и имена меток в Google Docs. И, поскольку это - метки (места вставок), то сразу определим для себя, что метки мы всегда будем заключать в фигурные скобки.
Помимо информационных столбцов здесь также находятся "вспомогательные столбцы", с помощью которых реализован интерфейс нашей программы: КТО выдаёт (кто заключает договор), КОМУ выдаёт (с кем заключает договор) и какой ШАБЛОН документа при этом используется.
В качестве шаблона документа, к которому обращается скрипт, был использован следующий вариант доверенности.
Для того, чтобы различить метки доверителя и поверенного, к меткам доверителя был добавлен элемент текста - [principal_], а к меткам поверенного - [attorney_].
Скрипт, представленный ниже, реализует следующие задачи:
function DocGenerator() {
var sc = SpreadsheetApp.getActiveSheet();
//find clients info
var principalIndex = getClientIndx(1);
var attorneyIndex = getClientIndx(2);
var principal = getClientData(principalIndex);
var attorney = getClientData(attorneyIndex);
// find template
var docName = sc.getRange(principalIndex, 3).getValue();
var docID = getTemlateID(docName);
var docNameCopy = docName + "_" + principal.name + "_" + attorney.name;
var file = DriveApp.getFileById(docID);
file.makeCopy(docNameCopy);
var fileCopy = DriveApp.getFilesByName(docNameCopy).next();
var fileCopyID = fileCopy.getId();
// replacement
var body = DocumentApp.openById(fileCopyID).getBody();
body.replaceText('{principal_name}', principal.name);
body.replaceText('{principal_id}', principal.id);
body.replaceText('{principal_id_dateOfIssue}', principal.id_dateOfIssue);
body.replaceText('{attorney_name}', attorney.name);
body.replaceText('{attorney_id}', attorney.id);
body.replaceText('{attorney_id_dateOfIssue}', attorney.id_dateOfIssue);
Browser.msgBox("Completed!");
}
function getClientIndx(col) {
var sc = SpreadsheetApp.getActiveSheet();
var iMax = sc.getLastRow();
var found = false;
for(var i=2; i <= iMax; i++) {
if(sc.getRange(i, col).getValue() == true) {
found = true;
break;
}
}
if(found == true) {
return i;
} else {
Browser.msgBox("Please select at least one client!")
}
}
function getClientData(indx) {
var sc = SpreadsheetApp.getActiveSheet();
var client = {
name: sc.getRange(indx, 4).getValue(),
id: sc.getRange(indx, 5).getValue(),
id_dateOfIssue: sc.getRange(indx, 6).getValue(),
};
return client;
}
function getTemlateID(docName) {
var st = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Templates');
var iMax = st.getLastRow();
for(var i=2; i <= iMax; i++) {
if(st.getRange(i, 1).getValue() == docName) {
var docId = st.getRange(i, 2).getValue();
return docId;
}
}
}
Более подробные объяснения о работе скрипта Вы сможете получить, ознакомившись с данным видео:
Продолжнение смотрите в статье:
Генератор документов Google Apps Script с журналом учёта созданных документов.