¿Cómo envío correspondencia de la hoja de cálculo de Google a un documento de Google?

20

Con Microsoft Excel y Microsoft Word, es fácil combinar filas de una hoja de cálculo en páginas de un archivo de Word. Esto se usaba tradicionalmente para hacer correos en papel. ¿Cómo puedo hacer lo mismo con Google Drive / Google Docs?

Hay muchas plantillas que ofrecen combinación de correspondencia de hoja de cálculo a correo electrónico: ¿Cómo hago una combinación de correspondencia con Gmail? Pero eso no es lo que busco.

Bryce
fuente
¿Has intentado copiar / pegar?
Jacob Jan Tuinstra
44
Copiar / pegar para 10,000 filas? No, gracias. Word / Excel funcionará bien.
Bryce

Respuestas:

8

Tendrá que escribir un script de Google Apps para eso. Puede dejar que la primera fila de la hoja de cálculo sean nombres de campo y crear un documento de plantilla donde se haga referencia a los campos [FIELD].

Entonces, si su hoja de cálculo se ve así:

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

... podría tener un documento de plantilla como

Estimado [NAME], que vive en [STREET], [TOWN] [ZIP] ...

Su script necesitará crear un documento nuevo y vacío, y para cada fila en su hoja de cálculo, agregar una nueva página y buscar / reemplazar los marcadores de posición de campo con valores de fila.

Tengo una versión algo funcional, que podría necesitar algún pulido. Se puede invocar aquí . Creará un nuevo documento llamado Resultado de la combinación de correspondencia .

Puede usarlo como punto de partida para su propio script. Avíseme si le gusta eso, o puedo pasar más tiempo terminando el guión.

Contenido del guión:

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();
}
Vidar S. Ramdal
fuente
1
¿Por qué elegiste usar una aplicación independiente y no una compilación desde la hoja de cálculo? Eso hará que sea mucho más fácil para el OP. En segundo lugar, ¿por qué hay tantas llamadas de Logger en el script? Hará que el guión sea demasiado denso.
Jacob Jan Tuinstra
El archivo de secuencias de comandos de Google solía tener algunas secuencias de comandos preconstruidas ... ¿hay alguna razón particular para que la suya u otra no se cargue allí?
Bryce
No noté el comentario de Jacob hasta ahora, y como él dice, probablemente debería ser un guión de hoja de cálculo en lugar de independiente. Veré si puedo encontrar tiempo para trabajar en él y enviarlo a la galería de Script.
Vidar S. Ramdal
55
Vidar Esta es una gran respuesta. Lo limpié y actualicé algunos de los métodos obsoletos, eliminé las funciones innecesarias y también lo modifiqué para que se ejecutara desde la hoja de cálculo, como sugirió @JacobJanTuinstra. Luego me di cuenta de que hay un error que rompe las imágenes , y también hice una solución para el error. Siento que ahora es lo suficientemente agradable como para usar Github. Lo publiqué allí y proporcioné un enlace a su respuesta como la versión inicial del trabajo.
hadi
@hadi Buen trabajo!
Vidar S. Ramdal
6

A través de los nuevos complementos de Google Drive , hay varias posibilidades de combinación de correspondencia disponibles, como "Otra combinación de correspondencia".

Para usarlo, debe tener una "nueva" hoja de cálculo de Google e instalar el complemento a través del menú Agregar:

Captura de pantalla de las hojas de cálculo de Google

Busque Mail mergey encontrará varias opciones.

Vidar S. Ramdal
fuente
Tenga en cuenta que está limitado a 100 correos electrónicos por día (gratis).
pixeline
5

La propia publicación de Google explica cómo configurar los datos del feed en una hoja y la plantilla en otra, en lugar de una hoja de cálculo de Google + Google Doc: https://developers.google.com/apps-script/articles/mail_merge

Sin embargo, el resultado final es MailAppenviar un correo electrónico, en lugar del documento "clonado" deseado. Sugeriría combinar el tutorial y la respuesta de @ Vidar, algo similar a reemplazar:

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

con

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?

Referencias aleatorias de AppScripts:

drzaus
fuente
acabo de encontrar este GIST como otro ejemplo gist.github.com/mhawksey/1170597
drzaus
3
La pregunta excluye específicamente la combinación de correo electrónico.
Bryce
3

Recomiendo autoCrat . Es un complemento de Google con una excelente interfaz tipo asistente para ayudarlo a configurar la fusión.

morfático
fuente
1

Tuve el mismo problema y traté de resolverlo con la respuesta de Vidar, pero por desaprobación no funcionó.

La solución real es el enlace de @hadi en el comentario sobre la respuesta de Vidar.

Vidar :
Esta es una gran respuesta. Lo limpié y actualicé algunos de los métodos en desuso, eliminé las funciones innecesarias y también lo modifiqué para que se ejecutara desde la hoja de cálculo, como lo sugirió @ JacobJanTuinstra . Luego me di cuenta de que hay un error que rompe las imágenes, y también hice una solución para el error. Siento que ahora es lo suficientemente agradable como para usar Github. Lo publiqué allí y proporcioné un enlace a su respuesta como la versión inicial del trabajo.
- Hadi Mar 4 '15 a las 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.

Simplemente seguí los pasos Readmey pude crear un documento combinado a partir de una plantilla Google-Doc y una Google-Sheet.

innovaciones de bennett
fuente