简体   繁体   中英

How to document merge a parent record and all of its child records

I'm creating a document merge (mail merge) from Google App Maker to a Google Document template. I can do so successfully when merging one single record, but how do you merge several records into the one document?

I have an purchase_orders parent record which has several purchase_order_line_items child records but I can't seem to get all of these records into a single document merge.

A similar question ( Document Merge with Google App Maker ) was asked by by Johan W with a comprehensive answer by Markus Malessa and Pavel Shkleinik (thank you!). However, it only caters for cases when you are merging one single record.

I have tried to build on their answer by using a second for loop to get the data of all associated child records. The script runs but only seems to merge the first child record; not all of them.

Here is an example of the server-side code I've tried to use:

function Export(key, key2) {

// Get the parent record by its key, which was passed by the first parameter above
var record = app.models.Purchase_Orders.getRecord(key);

// Get the first child record by its key, which was passed by the second parameter above
var childRecord = app.models.Purchase_Order_Line_Items.getRecord(key2);

// Get the Google Document which will be used as a template for this merge
var templateId = '1Xbt8camqHJYrhBnx0a6G2-RvTvybqU0PclHifcdiLLA';

//Set the filename of the new merge document to be created
var filename = 'Document for Customer ' + new Date();

//Make a copy of the template to use as the merge document
var copyFile = DriveApp.getFileById(templateId).makeCopy(filename);

//Get the Google Docs ID of the newly created merge document
var copyDoc = DocumentApp.openById(copyFile.getId());
var copyBody = copyDoc.getBody();

// Replace the field names in the template with the field data from the parent record
var fields = app.metadata.models.Purchase_Orders.fields;

for (var i in fields) {
  console.log(i);
var text = '<<' + fields[i].name + '>>';
var data = record[fields[i].name];

if (data !== null) {
    copyBody.replaceText(text, data);
    } else {
    // do nothing
    }

  }

// Replace the field names in the template with the field data from the child records
childFields = app.metadata.models.Purchase_Order_Line_Items.fields;

for (i in childFields) {
  console.log(i);
var childtext = '<<' + childFields[i].name + '>>';
var childdata = childRecord[childFields[i].name];

if (childdata !== null) {
    copyBody.replaceText(childtext, childdata);
    } else {
    // do nothing
    }

  }  

}

How can I improve my code so that all associated child records are merged into a single document?

How can I set up my Google Document template to cater for any number of child records?

模板的屏幕截图

Rather than passing in the child record key via a second parameter, I would suggest just passing in the parent key and then changing your function as follows:

function Export(key) {

// Get the parent record by its key, which was passed by the first parameter above
var record = app.models.Purchase_Orders.getRecord(key);

// Get the first child record by its key, which was passed by the second parameter above
var childRecords = record.Purchase_Order_Line_Items;

// Get the Google Document which will be used as a template for this merge
var templateId = '1Xbt8camqHJYrhBnx0a6G2-RvTvybqU0PclHifcdiLLA';

//Set the filename of the new merge document to be created
var filename = 'Document for Customer ' + new Date();

//Make a copy of the template to use as the merge document
var copyFile = DriveApp.getFileById(templateId).makeCopy(filename);

//Get the Google Docs ID of the newly created merge document
var copyDoc = DocumentApp.openById(copyFile.getId());
var copyBody = copyDoc.getBody();

// Replace the field names in the template with the field data from the parent record
var fields = app.metadata.models.Purchase_Orders.fields;

for (var i in fields) {
  console.log(i);
var text = '<<' + fields[i].name + '>>';
var data = record[fields[i].name];

if (data !== null) {
    copyBody.replaceText(text, data);
    } else {
    // do nothing
    }

  }

// Replace the field names in the template with the field data from the child records
var childFields = app.metadata.models.Purchase_Order_Line_Items.fields;
var table = [];
var tableheader = [];

for (i in childFields) {
  console.log(i);  
  tableheader.push(childFields[i].displayName);
}
table.push(tableheader);

for (i in childRecords) {
  var data = [];
  for (var j in childFields) {
    data.push(childRecords[i][childFields[j].name]);
  }
  table.push(data);
}
copyBody.appendTable(table);

The table building is based on a 2D array and the documentation is here https://developers.google.com/apps-script/reference/document/table . But you will also need to remove your prebuilt table in favor of just appending a table instead. This way you are not dependent on the quantity of child records being fixed like they currently are in your document template. Also, the variable for childRecords may or may not work, I have not tested this since I am unsure if prefetch works in conjunction with .getRecord(key) . This may require some additional testing but hopefully this will provide enough guidance.

Thought I would add this as an alternative. Lets say you keep your table but remove all the rows with exception for the header row then you could still use DocumentApp service to add your rows to the table like so:

var tableheaderfieldnames = ['Quantity_for_PO', 'Inventory_Item.id', 'Unit_Price']; //set a fixed table header with the field names, uncertain if the table header for the related inventory item will work or not
    var table = copyBody.getTables()[0];
    for (i in childRecords) {
      var row = table.appendRow();
      for (var j in tableheaderfieldnames) {
        row.appendTableCell(childRecords[i][tableheaderfieldnames[j]]);
      }
    }

Keep in mind that AM does not allow you to use FK references, so for your inventory item that appears to use a fk field you may need to tinker around with setting the proper name reference for when you are trying to fill in the item in your table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM