Использую этот скрипт для выгрузки документов в .csv в гугл таблицы
/**
* Производит чтение писем из Gmail аккаунта пользователя скрипта,
* после чего выгружает их содержимое в соответствующую таблицу СЦ.
* Большая часть реализации вынесена в другии функции.
*/
function importDataFromGmail() {
var idCollection = {
client1: "pageID",
client2: "pageID",
client3: "pageID",
client4: "pageID",
client5: "pageID",
};
var threads = GmailApp.getInboxThreads(0, 15);
var email = "email@email.email";
var waybills = {};
var services = {
client1: [],
client2: [],
client3: [],
client4: [],
client5: [],
}
for (var i = 0; i < threads.length; i++) {
for (var j = 0; j < threads[i].getMessages().length; j++) {
if (threads[i].getMessages()[j].getFrom().indexOf(email) > 0 &&
threads[i].getMessages()[j].getAttachments()[0].getContentType() == "application/octet-stream" && //почему то данные мне передают именно так
!threads[i].getMessages()[j].isStarred()) {
var message = threads[i].getMessages()[j];
var serviceName = message.getSubject().match(/\w+\s\w+$|\w$|Client\s\(\w*?\s\w*?\)$|М\w+-\w+$|[А-Я]+$/);
var attachment = sanatize(message.getAttachments()[0].getDataAsString());
fillServiceCollection(serviceName.toString(), services, attachment);
threads[i].getMessages()[j].star();//Странное решение, нужно подумать. Отслеживать id письма для того чтобы сделать unStar()
}
}
}
fillWaybillCollection(services, waybills);
deliverWaybills(idCollection, waybills);
}
/**
* Осущствляет выгрузку объектов накладных в соответствующие
* им листы таблиц СЦ, после чего настраивает отображение данных.
*
* @param idCollection объект содержащий в себе id таблиц СЦ
* @param waybills объект содержащий в себе отображения СЦ на объекты накладных
*/
function deliverWaybills(idCollection, waybills) {
var hashIdentityArray = [];
for (var waybillsbBunch in waybills) {
var currentWaybillBunch = waybills[waybillsbBunch];
for (var i = 0; i < currentWaybillBunch.length; i++) {
if (hashIdentityArray.indexOf(currentWaybillBunch[i].hash) < 0) {
if (!checkHashExistence(currentWaybillBunch[i].name, currentWaybillBunch[i].hash)) {
var sheet = null;
try {
sheet = SpreadsheetApp.openById(idCollection[currentWaybillBunch[i].name]).getSheetByName(getCurrentSheetName()).activate();
if (sheet.getMaxRows() - sheet.getLastRow() < 1) {
sheet.insertRowsAfter(sheet.getMaxRows(), 6)
.getRange(sheet.getLastRow() + 1, 14, sheet.getMaxRows() - sheet.getLastRow())
.clear({
validationsOnly: true
});
}
var headerRange = sheet.getRange(sheet.getLastRow() + 3, 3, 1, 1);
var dateRange = sheet.getRange(sheet.getLastRow() + 3, 6, 1, 1);
var estimatingRange = sheet.getRange(sheet.getLastRow() + 3, 9, 1, 1);
var formulaRange = sheet.getRange(sheet.getLastRow() + 3, 10, 1, 1);
var bodyRange = sheet.getRange(sheet.getLastRow() + 6, 3, currentWaybillBunch[i].body.length, 6);
var tableRange = sheet.getRange(sheet.getLastRow() + 6, 3, currentWaybillBunch[i].body.length, 12);
var dataValidationRange = sheet.getRange(sheet.getLastRow() + 6, 14, currentWaybillBunch[i].body.length, 1);
headerRange.setValue("Накладная № " + currentWaybillBunch[i].number + " от")
.setWrap(false)
.setFontSize(14)
.setFontWeight("Bold");
estimatingRange.setValue("Дней в ремонте:")
.setWrap(false)
.setFontSize(14)
.setFontWeight("Bold")
.setBorder(true, true, true, true, true, true);
formulaRange.setFormula("=TODAY()-F" + sheet.getLastRow())
.setWrap(false)
.setFontSize(14)
.setFontWeight("Bold")
.setBorder(true, true, true, true, true, true);
dateRange.setValue(currentWaybillBunch[i].date)
.setWrap(false)
.setFontSize(14)
.setFontWeight("Bold");
bodyRange.setValues(currentWaybillBunch[i].body);
var rule = SpreadsheetApp.newDataValidation()
.requireValueInList(["Готов", "В работе", "Отказ", "Ожидает запчасти", "Выдан"])
.setAllowInvalid(true)
.build();
var realShit = tableRange.getWraps();
var copy = Object.create(currentWaybillBunch[i]); //по какой то причине цикл ниже затирает изначальный объект
for (var i in realShit) {
for (var j in realShit[i]) {
if (!realShit[i][j]) realShit[i][j] = true;
}
}
Logger.log(realShit);
tableRange.setBorder(true, true, true, true, true, true)
.setFontSize(10)
.setFontWeight("Unbold")
.setWraps(realShit);
dataValidationRange.setDataValidation(rule);
checkHashExistence(copy.name, copy.hash, true);
} catch (e) {
SpreadsheetApp.getUi().alert(e);
errorHandler(e, copy);
}
}
hashIdentityArray.push(copy.hash);
}
}
}
}
/**
* Создает объекты представления накладных, и наполняет
* ими объект waybills.
*
* @param services объект, который хранит отображения СЦ на списки почтовых вложений
* @param waybills объект содержащий в себе отображения СЦ на объекты накладных
*/
function fillWaybillCollection(services, waybills) {
for (var service in services) {
for (var i = 0; i < services[service].length; i++) {
var waybill = {};
waybill["body"] = [];
waybill["name"] = service;
waybill["number"] = services[service][i][0][0];
waybill["date"] = services[service][i][0][1];
for (var j = 1; j < services[service][i].length; j++) {
waybill["body"].push(services[service][i][j]);
}
waybill["hash"] = evaluateHash(waybill["body"].toString());
waybills.hasOwnProperty(waybill["name"]) ? waybills[waybill["name"]].push(waybill) : waybills[waybill["name"]] = [waybill];
}
}
}
/**
* Очищает данные почтового вложения от лишних символов,
* производит замену "$|" на ";" для парсинга и последующего преобразования
* в массив.
*
* @param data почтовое вложение в виде строки
* @return data почтовое вложение в виде двумерного массива
*/
function sanatize(data) {
data = data.replace(/[;"\n]/g, '');
data = data.replace(/\$\|/g, ';');
data = data.replace(/\s\s+/g, '');
data = Utilities.parseCsv(data, ';');
return data;
}
/**
* При двух аргументах проверяет наличие хэша текущей накладной
* в хранилище. При трех аргументах добавляет хэш текущей накладной
* в хранилище.
*
* @param service название СЦ для проверки
* @param hash значение хэша для проверки или добавления
* @param withAddition использутся в true только для добавления хэша в хранилище,
* при отсутствии или в false функция проверит существование ключа
* @return true возвращает true в том случае если перадан аргумент withAddition == true
* и хэш был добавлен в хранилище
* @return flag true или false, в зависимости от того, был ли найден хэш в хранилище
*/
function checkHashExistence(service, hash, withAddition) {
var DATA_SS = "pageID";
var ss = SpreadsheetApp.openById(DATA_SS);
var sheet = ss.getSheetByName(service);
sheet = sheet || ss.insertSheet(service);
if (arguments.length > 2) {
if (withAddition) {
sheet.appendRow([hash]);
return true;
}
}
var range = sheet.getRange(1, 1, 1000);
var data = range.getDisplayValues();
var flag = false;
Object.keys(data).map(function(key) {
if (data[key] == hash) flag = true;
}, hash, flag);
return flag;
}
/**
* Вычисляет значение хэша для переданного текста, на основе алгоритма MD5
* Thanks http://stackoverflow.com/questions/16216868/get-back-a-string-representation-from-computedigestalgorithm-value-byte
*
* @param message текст на основе которого, будет вычислятся хэш
* @return signatureStr хэш в виде строки в кодировке UTF-8
*/
function evaluateHash(message) {
var signature = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, message, Utilities.Charset.UTF_8);
var signatureStr = '';
for (i = 0; i < signature.length; i++) {
var byte = signature[i];
if (byte < 0)
byte += 256;
var byteStr = byte.toString(16);
if (byteStr.length == 1) byteStr = '0' + byteStr;
signatureStr += byteStr;
}
return signatureStr;
}
/**
* Вычисляте текущий месяц и год, для определения названия листа
* в таблице СЦ
*
* @return название листа в таблице согласования с СЦ
*/
function getCurrentSheetName() {
var date = new Date();
var monthArray = ["Январь", "Февраль", "Март", "Апрель", "Май",
"Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"
];
return monthArray[date.getMonth()] + " " + date.getFullYear().toString().slice(2, 4);
}
/**
* Обрабатывает ошибки возникшие во время исполнения скрипта
* и добавляет о них в лог-файл
*
* @param e объект ошибки
* @param waybill объект накладной
*/
function errorHandler(e, waybill) {
var DATA_SS = "pageID";
var ss = SpreadsheetApp.openById(DATA_SS);
var sheet = ss.getSheetByName("errors");
Logger.log(e.stack);
sheet.appendRow([new Date(), Session.getActiveUser(), waybill.name + " " + waybill.number + " " + waybill.date, waybill.hash, e, e.stack]);
}
/**
* Наполняет объект services вложениями писем в виде строки
*
* @param serviceName название СЦ
* @param services объект коллекция
* @param attachment вложение письма
*/
function fillServiceCollection(serviceName, services, attachment) {
switch (serviceName) {
case "client1":
services.client1.push(attachment);
break;
case "client2":
services.client2.push(attachment);
break;
case "client3":
services.client3.push(attachment);
break;
case "client4":
services.client4.push(attachment);
break;
case "client5":
services.client5.push(attachment);
break;
}
}