Google 스프레드 시트에서 Google 문서로 편지 병합을 어떻게합니까?


20

Microsoft Excel 및 Microsoft Word를 사용하면 스프레드 시트의 행을 Word 파일의 페이지로 쉽게 병합 할 수 있습니다. 이것은 전통적으로 종이 우편물을 만드는 데 사용되었습니다. Google 드라이브 / Google 문서 도구에서 동일한 작업을 수행하려면 어떻게해야하나요?

스프레드 시트에서 이메일로 편지 병합을 제공하는 템플릿이 많이 있습니다. Gmail과 편지를 병합하려면 어떻게해야합니까? 그러나 그것은 내가 추구하는 것이 아닙니다.


복사 / 붙여 넣기를 시도 했습니까?
Jacob Jan Tuinstra

4
10,000 행 복사 / 붙여 넣기? 괜찮습니다. Word / Excel은 잘 작동합니다.
브라이스

답변:


8

이를 위해 Google Apps Script 를 작성해야 합니다. 스프레드 시트의 첫 번째 행을 필드 이름으로하고 필드가 다음과 같이 참조되는 템플릿 문서를 만들 수 있습니다 [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가 훨씬 쉬워집니다. 둘째, 왜 스크립트에 로거 호출이 그렇게 많은가? 스크립트가 너무 조밀하게 만들어집니다.
Jacob Jan Tuinstra

Google 스크립트 아카이브에 사전 빌드 된 스크립트가있었습니다. 귀하 또는 다른 스크립트가 업로드되지 않은 특별한 이유가 있습니까?
브라이스

지금까지 야곱의 의견은 눈치 채지 못했지만, 독립형이 아닌 스프레드 시트 스크립트 여야합니다. 작업 할 시간을 찾아서 스크립트 갤러리에 제출할 수 있는지 살펴 보겠습니다.
Vidar S. Ramdal 2013

5
Vidar 이것은 훌륭한 답변입니다. 나는 그것을 정리하고 더 이상 사용되지 않는 메소드를 업데이트하고 불필요한 기능을 제거했으며 @JacobJanTuinstra가 제안한대로 스프레드 시트 내에서 실행되도록 수정했습니다. 그런 다음 이미지를 손상 시키는 버그 가 있음을 깨달았으며 버그에 대한 해결 방법도 만들었습니다. 나는 그것이 지금 Github에 올려 질 정도로 충분히 좋다고 생각합니다. 나는 거기에 그것을 게시 하고 작업의 시작 버전으로 귀하의 답변에 대한 링크를 제공했습니다.
hadi

@hadi 잘 했어!
Vidar S. Ramdal 2014 년

6

새로운 Google 드라이브 추가 기능을 통해 "Yet Another Mail Merge"와 같은 여러 가지 편지 병합 가능성이 있습니다.

사용하려면 "새로운"Google 스프레드 시트가 있어야하며 추가 기능 메뉴를 통해 추가 기능을 설치해야합니다.

Google 스프레드 시트 스크린 샷

를 검색 Mail merge하면 몇 가지 옵션이 있습니다.


하루에 100 개의 이메일로 제한됩니다 (무료).
pixeline

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?

임의의 AppScript 참조 :



3
이 질문은 특히 이메일 편지 병합을 제외합니다.
브라이스


1

나는 같은 문제가 있었고 Vidar의 답변으로 해결하려고했지만 사용 중단으로 인해 작동하지 않았습니다.

실제 솔루션은 Vidar의 답변에 대한 의견에서 @hadi의 링크입니다.

Vidar :
대단한 답변입니다. 나는 그것을 정리하고 더 이상 사용되지 않는 메소드를 업데이트하고 불필요한 기능을 제거했으며 @ JacobJanTuinstra가 제안한 대로 스프레드 시트 내에서 실행되도록 수정했습니다 . 그런 다음 이미지를 손상시키는 버그가 있음을 깨달았으며 버그에 대한 해결 방법도 만들었습니다. 나는 그것이 지금 Github에 올려 질 정도로 충분히 좋다고 생각합니다. 나는 거기에 그것을 게시하고 작업의 시작 버전으로 귀하의 답변에 대한 링크를 제공했습니다.
hadi Mar 4 '15 at 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.