ฉันจะรวมจดหมายจาก Google Spreadsheet ไปยังเอกสาร Google ได้อย่างไร


20

ด้วย Microsoft Excel และ Microsoft Word ทำให้ง่ายต่อการรวมแถวจากสเปรดชีตเข้ากับหน้าในไฟล์ Word นี่เป็นประเพณีที่ใช้ในการส่งจดหมาย ฉันจะทำเช่นเดียวกันกับ Google ไดรฟ์ / Google เอกสารได้อย่างไร

มีเทมเพลตมากมายที่ให้จดหมายเวียนสเปรดชีตต่ออีเมล: ฉันจะทำจดหมายเวียนกับ Gmail ได้อย่างไร แต่นั่นไม่ใช่สิ่งที่ฉันตามมา


คุณพยายามคัดลอก / วางหรือไม่
จาค็อบ ม.ค. Tuinstra

4
คัดลอก / วาง 10,000 แถว? ไม่เป็นไรขอบคุณ. Word / Excel จะทำได้ดี
ไบรซ์

คำตอบ:


8

คุณจะต้องเขียนสคริปต์ Google Appsสำหรับการที่ คุณสามารถปล่อยให้แถวแรกของสเปรดชีตเป็นชื่อฟิลด์และสร้างเอกสารแม่แบบที่มีการอ้างอิงฟิลด์ดัง[FIELD]กล่าว

ดังนั้นหากสเปรดชีตของคุณมีลักษณะดังนี้:

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

... คุณอาจมีเอกสารแม่แบบเช่น

เรียน [NAME] อาศัยอยู่ที่ [STREET], [TOWN] [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
ทำไมคุณถึงเลือกที่จะใช้แอพแบบสแตนด์อะโลนและไม่ใช่หนึ่งบิลด์จากภายในสเปรดชีต นั่นจะทำให้มันง่ายขึ้นสำหรับ OP ประการที่สองเหตุใดจึงมีการโทร Logger จำนวนมากในสคริปต์? มันจะทำให้สคริปต์มีความหนาแน่นมากเกินไป
จาค็อบ ม.ค. Tuinstra

ที่เก็บถาวรสคริปต์ของ Google เคยมีสคริปต์ที่สร้างไว้ล่วงหน้าบางส่วน ... มีเหตุผลเฉพาะของคุณหรือที่อื่นจะไม่ถูกอัปโหลดที่นั่นหรือไม่
ไบรซ์

ไม่ได้สังเกตความคิดเห็นของยาโคบจนกระทั่งตอนนี้และอย่างที่เขาพูดมันน่าจะเป็นสคริปต์สเปรดชีตแทนที่จะเป็นแบบสแตนด์อโลน ฉันจะดูว่าฉันสามารถหาเวลาทำงานได้หรือไม่และส่งไปที่แกลเลอรีสคริปต์
Vidar S. Ramdal

5
Vidar นี่เป็นคำตอบที่ดีมาก ฉันล้างมันและอัปเดตวิธีการที่เลิกใช้แล้วและกำจัดฟังก์ชั่นที่ไม่จำเป็นออกไปและยังแก้ไขให้เรียกใช้จากภายในสเปรดชีตตามที่ @JacobJanTuinstra แนะนำ จากนั้นฉันก็รู้ว่ามีข้อผิดพลาดที่ทำให้ภาพแตกและฉันก็หาวิธีแก้ไขข้อผิดพลาด ฉันรู้สึกว่าตอนนี้มันดีพอที่จะสวม Github ฉันได้โพสต์ไว้ที่นี่และมีลิงก์ไปยังคำตอบของคุณเป็นเวอร์ชันเริ่มต้นของงาน
hadi

@hadi ทำได้ดีมาก!
Vidar S. Ramdal

6

ผ่านAdd-on ของ Google Driveใหม่มีความเป็นไปได้ในการรวมจดหมายหลายอย่างเช่น "Yet Another Mail Merge"

ในการใช้งานคุณต้องมี Google Spreadsheet "ใหม่" และติดตั้งส่วนเสริมผ่านทางเมนูส่วนเสริม:

ภาพหน้าจอจาก Google Spreadsheets

ค้นหาMail mergeและคุณจะพบตัวเลือกมากมาย


โปรดทราบว่ามัน จำกัด 100 อีเมลต่อวัน (ฟรี)
pixeline

5

โพสต์ของ Google อธิบายถึงวิธีการตั้งค่าข้อมูลฟีดในหนึ่งแผ่นและเทมเพลตในอีกแผ่นหนึ่งแทนที่จะเป็น Google Spreadsheet + Google Doc: 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

ผมขอแนะนำให้ผู้มีอำนาจเด็ดขาด เป็น Google Add-On ที่มีอินเทอร์เฟซคล้ายตัวช่วยสร้างที่ยอดเยี่ยมสำหรับช่วยคุณตั้งค่าการผสาน


1

ฉันมีปัญหาเดียวกันและพยายามแก้ไขด้วยคำตอบของ Vidar แต่เนื่องจากการคัดค้านมันไม่ทำงาน

ทางออกที่แท้จริงคือลิงค์โดย @hadi ในความคิดเห็นต่อคำตอบของ Vidar

Vidar :
นี่เป็นคำตอบที่ดีมาก ฉันล้างมันและอัปเดตวิธีการที่เลิกใช้แล้วและกำจัดฟังก์ชั่นที่ไม่จำเป็นออกไปและยังแก้ไขมันเพื่อเรียกใช้จากภายในสเปรดชีตตามที่ @ JacobJanTuinstra แนะนำ จากนั้นฉันก็รู้ว่ามีข้อผิดพลาดที่ทำให้ภาพแตกและฉันก็หาวิธีแก้ไขข้อผิดพลาดด้วย ฉันรู้สึกว่าตอนนี้มันดีพอที่จะสวม Github ฉันได้โพสต์ไว้ที่นี่และมีลิงก์ไปยังคำตอบของคุณเป็นเวอร์ชันเริ่มต้นของงาน
- hadi 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.