Как мне отправить письмо из Google Spreadsheet в Google Document?


20

Microsoft Excel и Microsoft Word позволяют легко объединять строки из электронной таблицы в страницы в файле Word. Это традиционно использовалось для изготовления бумажных рассылок. Как я могу сделать то же самое с Google Drive / Google Docs?

Существует множество шаблонов, предлагающих объединение электронной почты с электронной таблицей. Как мне объединить почту с Gmail? но это не то, что я после.


Вы пытались скопировать / вставить?
Джейкоб Ян Туинстра

4
Копировать / вставить для 10000 строк? Спасибо, не надо. Word / Excel будет хорошо.
Брайс

Ответы:


8

Для этого вам нужно будет написать скрипт Google Apps . Вы можете позволить первой строке электронной таблицы быть именами полей и создать шаблон документа, на который ссылаются поля, как [FIELD].

Так что если ваша таблица выглядит так:

NAME  |  STREET             | ZIP    | TOWN
---------------------------------------------
Vidar | Karl Johans gate 15 | 0200   | Oslo
John  | 3021 Arlington Road | 123456 | Memphis, TN

... вы можете иметь шаблон документа, как

Уважаемый [ИМЯ], живущий в [УЛИЦА], [ГОРОД] [ZIP] ...

Ваш сценарий должен будет создать новый пустой документ, и для каждой строки в вашей электронной таблице добавить новую страницу и найти / заменить заполнители полей значениями строк.

У меня есть несколько рабочая версия, которая может нуждаться в полировке. Это можно вызвать здесь . Это создаст новый документ с именем Результат слияния .

Вы можете использовать его в качестве отправной точки для вашего собственного сценария. Дайте мне знать, если вы в этом заинтересованы, или я могу потратить немного больше времени на завершение сценария.

Содержание скрипта:

var selectedTemplateId = null;
var selectedSpreadsheetId = null;
var spreadsheetDocPicker = null;
var templateDocPicker = null;

function mailMerge(app) {
  var app = UiApp.createApplication().setTitle("Mail Merge");
  templateDocPicker = createFilePicker(app, "Choose template", 
         UiApp.FileType.DOCUMENTS, "templateSelectionHandler"); 
  templateDocPicker.showDocsPicker();
  return app;
};

function createFilePicker(app, title, fileType, selectionHandlerName) {
  Logger.log("Creating file picker for " + fileType);
  var docPicker = app.createDocsListDialog();
  docPicker.setDialogTitle(title);
  docPicker.setInitialView(fileType);
  var selectionHandler = app.createServerHandler(selectionHandlerName);
  docPicker.addSelectionHandler(selectionHandler);
  return docPicker;
}

function templateSelectionHandler(e) {
  var app = UiApp.getActiveApplication();
  selectedTemplateId = e.parameter.items[0].id;
  UserProperties.setProperty("templateId", e.parameter.items[0].id);
  Logger.log("Selected template: " + selectedTemplateId);
  var spreadsheetDocPicker = createFilePicker(app, "Choose spreadsheet", 
        UiApp.FileType.SPREADSHEETS, "spreadsheetSelectionHandler");
  spreadsheetDocPicker.showDocsPicker();
  return app;
}

function spreadsheetSelectionHandler(e) {
  var app = UiApp.getActiveApplication();
  UserProperties.setProperty("spreadsheetId", e.parameter.items[0].id);
  selectedSpreadsheetId = e.parameter.items[0].id;
  Logger.log("Selected spreadsheet: " + selectedSpreadsheetId);
  doMerge();
  return app;
}

function doMerge() {
  var selectedSpreadsheetId = UserProperties.getProperty("spreadsheetId");
  var selectedTemplateId = UserProperties.getProperty("templateId");
  Logger.log("Selected spreadsheet: " + selectedSpreadsheetId);
  var sheet = SpreadsheetApp.openById(selectedSpreadsheetId);
  Logger.log("Spreadsheet opened");
  Logger.log("Opening template: " + selectedTemplateId);
  var template = DocumentApp.openById(selectedTemplateId);
  Logger.log("Template opened");
  var templateFile = DocsList.getFileById(selectedTemplateId);
  var templateDoc = DocumentApp.openById(templateFile.getId());
  //var mergedFile = templateFile.makeCopy();
  var mergedDoc = DocumentApp.create("Result of mail merge");
  var bodyCopy = templateDoc.getActiveSection().copy();
  Logger.log("Copy made");
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var values = rows.getValues();
  var fieldNames = values[0];

  for (var i = 1; i < numRows; i++) {
    var row = values[i];
    Logger.log("Processing row " + i + " " + row);
    var body = bodyCopy.copy();
    for (var f = 0; f < fieldNames.length; f++) {
      Logger.log("Processing field " + f + " " + fieldNames[f]);
      Logger.log("Replacing [" + fieldNames[f] + "] with " + row[f]);
      body.replaceText("\\[" + fieldNames[f] + "\\]", row[f]);
    }
    var numChildren = body.getNumChildren();
    for (var c = 0; c < numChildren; c++) {
      var child = body.getChild(c);
      child = child.copy();
      if (child.getType() == DocumentApp.ElementType.HORIZONTALRULE) {
        mergedDoc.appendHorizontalRule(child);
      } else if (child.getType() == DocumentApp.ElementType.INLINEIMAGE) {
        mergedDoc.appendImage(child);
      } else if (child.getType() == DocumentApp.ElementType.PARAGRAPH) {
        mergedDoc.appendParagraph(child);
      } else if (child.getType() == DocumentApp.ElementType.LISTITEM) {
        mergedDoc.appendListItem(child);
      } else if (child.getType() == DocumentApp.ElementType.TABLE) {
        mergedDoc.appendTable(child);
      } else {
        Logger.log("Unknown element type: " + child);
      }
   }
   Logger.log("Appending page break");
   mergedDoc.appendPageBreak();
   Logger.log("Result is now " + mergedDoc.getActiveSection().getText());
  }
}

function testMerge() {
  UserProperties.setProperty("templateId", 
    "1pAXWE0uklZ8z-O_Tejuv3pWSTiSv583ptUTGPt2Knm8");
  UserProperties.setProperty("spreadsheetId", 
    "0Avea1NXBTibYdFo5QkZzWWlMYUhkclNSaFpRWUZOTUE");
  doMerge();
}


function doGet() {
  return mailMerge();
}

1
Почему вы решили использовать автономное приложение, а не одну сборку из таблицы? Это сделает это намного проще для ОП. Во-вторых, почему в скрипте так много вызовов Logger? Это сделает скрипт слишком плотным.
Джейкоб Ян Туинстра

В архиве скриптов Google раньше были какие-то предварительно собранные скрипты ... есть ли какая-то конкретная причина, по которой ваша или другая не будет загружена туда?
Брайс

До сих пор не замечал комментария Джейкоба, и, как он говорит, это, вероятно, должен быть сценарий для электронных таблиц, а не отдельный. Я посмотрю, смогу ли я найти время, чтобы поработать над этим, и отправлю его в галерею скриптов.
Видар С. Рамдал

5
Видар Это отличный ответ. Я очистил его, обновил некоторые устаревшие методы и избавился от ненужных функций, а также изменил его для запуска из электронной таблицы, как предложила @JacobJanTuinstra. Затем я понял, что есть ошибка, которая нарушает работу изображений , и я также сделал обходной путь для этой ошибки. Я чувствую, что теперь это достаточно хорошо, чтобы надеть Github. Я разместил его там и в нем предоставил ссылку на ваш ответ в качестве стартовой версии работы.
хади

@hadi Хорошая работа!
Видар С. Рамдал

6

С помощью новых надстроек на Google Диске доступно несколько возможностей слияния, например «Ещё одно слияние».

Чтобы использовать его, вы должны иметь «новую» таблицу Google и установить надстройку через меню надстроек:

Снимок экрана из таблиц Google

Ищите Mail merge, и вы найдете несколько вариантов.


Обратите внимание, что он ограничен 100 электронными письмами в день (бесплатно).
пиксель

5

В собственном посте Google объясняется, как настроить данные фида на одном листе, а шаблон - на другом, а не как таблицу Google + Документ Google: https://developers.google.com/apps-script/articles/mail_merge.

Однако конечным результатом является MailAppотправка электронного письма, а не требуемый «клонированный» документ. Я бы предложил объединить учебник и ответ @ Vidar, что-то вроде замены:

MailApp.sendEmail(rowData.emailAddress, emailSubject, emailText);

с

var mergedDoc, bodyContent,
    // you'd have to make the DocumentTitle column for the following
    newTitle = rowData.DocumentTitle /* or set to a static title, etc */;

// make a copy of the template document -- see http://stackoverflow.com/a/13243070/1037948
// or start a new one if you aren't using the template, but rather text from a template field
if( usingTemplateFile ) {
    mergedDoc = templateDoc.makeCopy(newTitle)
    bodyContent = mergedDoc.getBody();
} else {
    mergedDoc = DocumentApp.create(newTitle);
    bodyContent = mergedDoc.getBody();
    bodyContent.setText(templateFieldContents);
}

// tweak the fillInTemplateFromObject to accept a document Body and use .replaceText() instead of .match as in mailmerge example
// .replaceText see https://developers.google.com/apps-script/reference/document/body#replaceText(String,String)
fillInTemplateFromObject(bodyContent, rowData);

// no append needed?

Случайные ссылки на AppScripts:


просто наткнулся на этот GIST в качестве другого примера gist.github.com/mhawksey/1170597
drzaus

3
Этот вопрос специально исключает слияние электронной почты.
Брайс

3

Я рекомендую AutoCrat . Это надстройка Google с отличным волшебным интерфейсом, который поможет вам настроить слияние.


1

У меня была такая же проблема, и я пытался решить ее с помощью ответа Видара, но из-за устаревшего решения это не сработало.

Фактическое решение - ссылка @hadi в комментарии к ответу Видара.

Видар :
Это отличный ответ. Я очистил его, обновил некоторые устаревшие методы и избавился от ненужных функций, а также изменил его для запуска из электронной таблицы, как предложено @ JacobJanTuinstra . Затем я понял, что есть ошибка, которая нарушает работу изображений, и я также сделал обходной путь для этой ошибки. Я чувствую, что теперь это достаточно хорошо, чтобы надеть Github. Я разместил его там и в нем предоставил ссылку на ваш ответ в качестве стартовой версии работы.
- хади 4 марта '15 в 19:24 "

https://github.com/hadaf/SheetsToDocsMerge :

  A Google Apps Script that merges information from a Google Sheet into a 
  Template created by Google Docs. The result is a new Google Docs file 
  that is populated by the Sheet data.

Просто следуйте инструкциям на Readmeи я смог создать объединенный документ из шаблона Google-Doc и Google-Sheet.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.