I'm using a Google Script to pull information about Trello cards into a Google Sheet. It was working fine for me, but suddenly today all the cards are pulling in 'Undefined' for each piece of data. But I can't work out why this suddenly stopped working.
The Google Script is as follows:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "Update from Trello", functionName: "main"}];
ss.addMenu("Trello", menuEntries);
}
// trello variables
var api_key = "XXXXX";
var api_token = "XXXXX";
var board_id = "XXXXX";
var url = "https://api.trello.com/1/";
var key_and_token = "key=" + api_key + "&token=" + api_token;
//called by google docs apps
function main() {
var ss = SpreadsheetApp.getActiveSheet().clear();
ss.appendRow(["Date", "Task", "Who", "List", "Link"]);
var response = UrlFetchApp.fetch(url + "boards/" + board_id + "/lists/all/?" + key_and_token);
var lists = JSON.parse((response.getContentText()));
Logger.log(lists);
for (var i = 0; i < lists.length; i++) {
var list = lists[i];
var response = UrlFetchApp.fetch(url + "list/" + list.id + "/cards/all?" + key_and_token);
var cards = JSON.parse(response.getContentText());
if (!cards)
continue;
for (var j = 0; j < cards.length; j++) {
var card = cards[j];
Logger.log(cards);
var response = UrlFetchApp.fetch(url + "cards/" + card.id + "/actions/?" + key_and_token);
var carddetails = JSON.parse(response.getContentText());
if (!carddetails)
continue;
Logger.log(carddetails);
for (var k = 0; k < carddetails.length; k++) {
var dato = carddetails[k].date;
var fullname = carddetails[k].memberCreator.fullName;
var name = card.name;
var link = card.url;
var listname = list.name;
Logger.log(name);
Logger.log(dato);
Logger.log(fullname);
Logger.log(link);
Logger.log(listname);
}
ss.appendRow([dato, name, fullname, listname, link]);
}
}
}
One year after that question i was searching for this code then i realise the Trello Api don't respond with the same way when this code was created. So i fix it...
Here is the code that work for me
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "Update from Trello", functionName: "main"},];
ss.addMenu("Trello", menuEntries);
}
// trello variables
var api_key = "XXXXX";
var api_token = "XXXXX";
var board_id = "XXXXX";
var url = "https://api.trello.com/1/";
var key_and_token = "key="+api_key+"&token="+api_token;
//called by google docs apps
function main() {
var ss = SpreadsheetApp.getActiveSheet().clear();
ss.appendRow(["Date", "Task", "Who", "List", "Link"]);
var response = UrlFetchApp.fetch(url + "boards/" + board_id + "/lists?cards=all&" + key_and_token);
var lists = JSON.parse((response.getContentText()));
Logger.log(lists);
for (var i=0; i < lists.length; i++) {
var list = lists[i];
//if(!list.closed) continue; //ignore open
//Logger.log(list);
var response = UrlFetchApp.fetch(url + "list/" + list.id + "/cards?" + key_and_token);
var cards = JSON.parse(response.getContentText());
if(!cards) continue;
for (var j=0; j < cards.length; j++) {
var card = cards[j];
Logger.log(url + "cards/" + card.id + "/actions?" + key_and_token);
var response = UrlFetchApp.fetch(url + "cards/" + card.id + "/?actions=all&" + key_and_token);
var carddetails = JSON.parse(response.getContentText()).actions;
if(!carddetails) continue;
Logger.log(carddetails);
for (var k=0; k < carddetails.length; k++) {
var dato = carddetails[k].date;
var fullname = carddetails[k].memberCreator.fullName;
var name = card.name;
var link = card.url;
var listname = list.name;
//var labelname = carddetails[k].labeldetails.name;
Logger.log(name);
Logger.log(dato);
Logger.log(fullname);
Logger.log(link);
//Logger.log(labelname);
Logger.log(listname);
}
ss.appendRow([dato, name, fullname, listname, link]);
}
}
}
Related
I have a script that creates forms that need to be filled out for ordering, the onformsubmittrigger places this weird line of text when it comes to the multi choice option [Ljava.lang.Object;#7c2a6e46, if possible I would also like to define where the answer are placed instead of the default of column a,b,c
function snore() {
var sheet = SpreadsheetApp.getActive().getSheetByName('TC');
var value = sheet.getRange("B2").getValue();
var em = sheet.getRange("C2").getValue();
var cos = sheet.getRange("F2").getValue();
var name = sheet.getRange("E2").getValue();
var sup = sheet.getRange("D2").getValue();
var form = FormApp.create(value);
var item = form.addMultipleChoiceItem();
item.setHelpText("Name: " + name +
"\n\nEmail: " + em +
"\n\nQuote No: " + value +
"\n\nProject: " + sup +
"\n\nTotal Cost: " + cos +
"\n\nBy selecting approve you agree to the cost and timeframe specified by the quote and that the details above are correct")
.setChoices([item.createChoice('Approved'), item.createChoice('Denied')]);
var itm = form.addCheckboxItem();
itm.setTitle('What extras would you like to add on? (all prices are Ex-GST)');
itm.setChoices([
itm.createChoice('Watergate Plus 1370mm x 36.5m, 36.5Lm - $109.80'),
itm.createChoice('Watergate Plus 2740mm x 30m, 30Lm - $171.60'),
itm.createChoice('White General Purpose Repair Tape 60mm x 66m, 66Lm - $39.21'),
itm.createChoice('Wall Wrap, Foil Fasteners, 500/box - $39.21'),
itm.createChoice('Super Course 500, 300mm x 0.5 x 50Lm - $29.30'),
itm.createChoice('40mm Metal Top Hat Batten - 3.10/mtr')
])
.showOtherOption(true);
Logger.log('Published URL: ' + form.getPublishedUrl());
Logger.log('Editor URL: ' + form.getEditUrl());
Logger.log('ID: ' + form.getId());
var myDId = DriveApp.getRootFolder().getId();
var rootFolder = DriveApp.getFolderById(myDId);
var archiveFolder = DriveApp.getFolderById("1Rt6xikEpHs-F2cQOTRrvATCZHCFU0bQ6");
var newForms = rootFolder.getFilesByName(value);
while (newForms.hasNext()) {
var newForm = newForms.next();
archiveFolder.addFile(newForm)
rootFolder.removeFile(newForm);
}
//const spreadsheetId = SpreadsheetApp.getActive().getId();
//form.setDestination(FormApp.DestinationType.SPREADSHEET, spreadsheetId);
SpreadsheetApp.getActiveSheet().getRange('J2').setValue('SENT');
var id = "1uw8HAJsuNHses_9XGfNtQ71fp3DXE7q1";
var buildBlob = DriveApp.getFileById(id).getBlob().setName("buildBlob");
var SendTo = "Jonathon.banks#westal.com.au";
var link = form.getId();
var message = "Please follow the link to accept you Quotation " + form.getPublishedUrl();
//set subject line
var body = HtmlService.createTemplateFromFile("email");
body.order = value;
body.overdue = form.getPublishedUrl();
var con = sheet.getRange("A2").getValue();
var file = DriveApp.getFilesByName(con).next()
var Subject = 'Quote' + value + 'Confirmation';
const recipient = em;
const subject = "Confirmation of order"
MailApp.sendEmail({
to: recipient,
attachments: file,
subject: subject,
htmlBody: body.evaluate().getContent(),
inlineImages:
{
build: buildBlob
}
});
//const subect = "confirm for id"
//const rcipient = SendTo;
//var mssage = "please run id confirm " + link;
//GmailApp.sendEmail(rcipient, subect, mssage)
const SOURCE_FORM_ID = link; // Change according to your needs
{
const form = FormApp.openById(SOURCE_FORM_ID);
ScriptApp.newTrigger("onFormSubmitTrigger")
.forForm(form)
.onFormSubmit()
.create();
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var seet = ss.getSheetByName('TC'); //source sheet
var testrange = seet.getRange('J:J'); //range to check
var testvalue = (testrange.getValues());
var csh = ss.getSheetByName('C'); //destination sheet
var data = [];
var j =[];
//Condition check in H:H; If true copy the same row to data array
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] == 'SENT') {
data.push.apply(data,seet.getRange(i+1,1,1,25).getValues());
//Copy matched ROW numbers to j
j.push(i);
}
}
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
//Delete matched rows in the source sheet
for (i=0;i<j.length;i++){
var k = j[i]+1;
sheet.deleteRow(k);
//Alter j to account for deleted rows
if (!(i == j.length-1)) {
j[i+1] = j[i+1]-i-1;
}
}
}
//const TARGET_SPREADSHEET_ID = "1JRhCnS048fhWMifkrD1mqdgFcs3-Cw-kGOzSgpLWfI0"; // Change according to your needs
//const TARGET_SHEET_NAME = "C"; // Change according to your needs
function onFormSubmitTrigger(e) {
const targetSpreadsheet = SpreadsheetApp.openById("1JRhCnS048fhWMifkrD1mqdgFcs3-Cw-kGOzSgpLWfI0");
const targetSheet = targetSpreadsheet.getSheetByName("C");
if (targetSheet.getLastRow() === 0) { // Add headers if they don't exist yet
const itemTitles = e.source.getItems().map(item => item.getTitle()); // Get item titles
itemTitles.unshift("Timestamp"); // Append "Timestamp" to the sheet (if desired)
targetSheet.appendRow(itemTitles); // Append form item titles to the sheet
}
const itemResponses = e.response.getItemResponses();
const responses = itemResponses.map(itemResponse => itemResponse.getResponse()); // Get user responses
responses.unshift(new Date()); // Add today's date to the responses (if desired)
targetSheet.appendRow([JSON.stringify(responses)])
}
After getting interested in a code proposed on Github to get WooCommerce orders in Google Sheets: https://github.com/mithunmanohar/woocommerce-orders-google-sheets-integration
I integrated this code in a sheet with its script but this code has a defect: when updating the status of an order the script adds an extra line instead of changing the status of the line corresponding to the order.
We get a duplicate as you can see here :
Same ID but statut different
You can find the complete code of the script here: https://github.com/mithunmanohar/woocommerce-orders-google-sheets-integration/blob/master/wc-gc-integration.gs
// Updated code to v2 Woocommerce API
function start_syncv2() {
var sheet_name = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
fetch_orders(sheet_name)
}
function fetch_orders(sheet_name) {
var ck = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name).getRange("B4").getValue();
var cs = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name).getRange("B5").getValue();
var website = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name).getRange("B3").getValue();
var manualDate = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name).getRange("B6").getValue(); // Set your order start date in spreadsheet in cell B6
var m = new Date(manualDate).toISOString();
var surl = website + "/wp-json/wc/v2/orders?consumer_key=" + ck + "&consumer_secret=" + cs + "&after=" + m + "&per_page=100";
var url = surl
//Logger.log(url)
var options =
{
"method": "GET",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"muteHttpExceptions": true,
};
var result = UrlFetchApp.fetch(url, options);
Logger.log(result.getResponseCode())
if (result.getResponseCode() == 200) {
var params = JSON.parse(result.getContentText());
//Logger.log(params);
}
var doc = SpreadsheetApp.getActiveSpreadsheet();
var temp = doc.getSheetByName(sheet_name);
var consumption = {};
var arrayLength = params.length;
for (var i = 0; i < arrayLength; i++) {
var a, c, d;
var container = [];
a = container.push(params[i]["billing"]["first_name"]);
a = container.push(params[i]["billing"]["last_name"]);
a = container.push(params[i]["billing"]["address_1"]+ " "+ params[i]["billing"]["postcode"]+ " "+ params[i]["billing"]["city"]);
a = container.push(params[i]["shipping"]["first_name"] + " "+ params[i]["shipping"]["last_name"]+" "+ params[i]["shipping"]["address_2"]+" "+ params[i]["shipping"]["address_1"]+" "+params[i]["shipping"]["postcode"]+" "+params[i]["shipping"]["city"]+" "+params[i]["shipping"]["state"]+" "+params[i]["shipping"]["country"]);
a = container.push(params[i]["billing"]["phone"]);
a = container.push(params[i]["billing"]["email"]);
a = container.push(params[i]["customer_note"]);
a = container.push(params[i]["payment_method_title"]);
c = params[i]["line_items"].length;
var items = "";
var total_line_items_quantity = 0;
for (var k = 0; k < c; k++) {
var item, item_f, qty, meta;
item = params[i]["line_items"][k]["name"];
qty = params[i]["line_items"][k]["quantity"];
item_f = qty + " x " + item;
items = items + item_f + ",\n";
total_line_items_quantity += qty;
}
a = container.push(items);
a = container.push(total_line_items_quantity); // Quantity
a = container.push(params[i]["total"]); //Price
a = container.push(params[i]["discount_total"]); // Discount
d = params[i]["refunds"].length;
var refundItems = "";
var refundValue = 0.0;
for (var r = 0; r < d; r++) {
var item, item_f, value;
item = params[i]["refunds"][r]["reason"];
value = params[i]["refunds"][r]["total"];
refundValue += parseFloat(value);
item_f = value +" - "+ item;
refundItems += item_f + ",\n";
}
a = container.push(refundValue); //Refunded value from order
a = container.push(parseFloat(container[10]) + refundValue); // Total minus refund
a = container.push(refundItems); //Refunded items from order
a = container.push(params[i]["id"]);
a = container.push(params[i]["date_created"]);
a = container.push(params[i]["date_modified"]);
a = container.push(params[i]["status"]);
a = container.push(params[i]["order_key"]);
var doc = SpreadsheetApp.getActiveSpreadsheet();
var temp = doc.getSheetByName(sheet_name);
temp.appendRow(container);
Logger.log(params[i]);
removeDuplicates(sheet_name);
}
}
function removeDuplicates(sheet_name) {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheet = doc.getSheetByName(sheet_name);
var data = sheet.getDataRange().getValues();
var newData = new Array();
for (i in data) {
var row = data[i];
/* TODO feature enhancement in de-duplication
var date_modified =row[row.length-2];
var order_key = row[row.length];
var existingDataSearchParam = order_key + "/" + date_modified;
*/
var duplicate = false;
for (j in newData) {
var rowNewData = newData[j];
var new_date_modified =rowNewData[rowNewData.length-2];
var new_order_key = rowNewData[rowNewData.length];
//var newDataSearchParam = new_order_key + "/" + new_date_modified; // TODO feature enhancement in de-duplication
if(row.join() == newData[j].join()) {
duplicate = true;
}
// TODO feature enhancement in de-duplication
/*if (existingDataSearchParam == newDataSearchParam){
duplicate = true;
}*/
}
if (!duplicate) {
newData.push(row);
}
}
sheet.clearContents();
sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData);
}
Well we have this google form and the details are being added to google sheet with custom g apps scripts. When the details have been appended to the google sheet log, it should send email. If I run the sendmail() manually, it works but when I call it inside onFormSubmit(), it's not working. What could have gone wrong?
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var logSheet = sheet.getSheetByName("Log");
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var newFileName = e.namedValues['Name'][0] + "-" + e.namedValues['Date'][0];
var populatedDocsFolder = DriveApp.getFolderById("1yTSd7W0U4Gcsm6CIw8NtD022F-MA7CPx");
var templateDocID = DocumentApp.openByUrl(templateLink).getId();
var newDocID = DriveApp.getFileById(templateDocID).makeCopy(newFileName, populatedDocsFolder).getId();
var newDocLink = DriveApp.getFileById(newDocID).getUrl();
var newDoc = DocumentApp.openById(newDocID);
var newDocBody = newDoc.getBody();
for (i = 0; i < formResponsesHeader[0].length; i++) {
var thisHeader = formResponsesHeader[0][i];
var thisValue = e.namedValues[thisHeader][0];
newDocBody.replaceText("<<" + thisHeader + ">>", thisValue);
}
//Log
var name = e.namedValues['Name'][0];
var email = e.namedValues['Email'][0];
var date = e.namedValues['Date'][0];
logSheet.appendRow([name,email,date,newDocID]);
//Trigger
ScriptApp.newTrigger("sendEmail").timeBased().after(15000).create();
//sendEmail();
}
function sendEmail() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var logSheet = sheet.getSheetByName("Log");
var logSheetData = logSheet.getDataRange().getDisplayValues();
var templateName = sheet.getSheetByName("Template Name").getRange(1, 1).getValue();
for (i = 1; i < logSheetData.length; i++) {
if (logSheetData[i][4] == "") {
//SEND EMAIL
var name = logSheetData[i][0];
var email = logSheetData[i][1];
var date = logSheetData[i][2];
var id = logSheetData[i][3];
var pdfName = templateName + "-" + name + "-" + date;
//PDF EMAIL
try{
var doc = DriveApp.getFileById(id);
var blob = doc.getBlob().getAs('application/pdf').setName(pdfName + ".pdf");
var subject = 'Document Created';
//GmailApp.sendEmail(email, subject, "This is just a test", {attachments: [blob]});
MailApp.sendEmail(email, subject, "", {attachments: [blob], name: pdfName});
}catch(err){
continue;
}
//Log Sheet Update
logSheet.getRange(i + 1, 5).setValue("Sent");
}
}
}
function onOpen() {
SpreadsheetApp.getUi().createMenu("Custom Menu")
.addItem("Build Form Submit Trigger", "formSubmitTrigger")
.addSeparator()
.addItem("Send Email", "sendEmail")
.addSeparator()
.addItem("Mismatch Check", "mismatchCheck")
.addToUi();
}
function formSubmitTrigger() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger("onFormSubmit").forSpreadsheet(sheet).onFormSubmit().create();
}
function mismatchCheck() {
var result = "";
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var docBody = DocumentApp.openByUrl(templateLink).getBody().getText();
var matches = docBody.match(/<</g); var noOfLessThanMatches = matches.length;
var matches = docBody.match(/>>/g); var noOfMoreThanMatches = matches.length;
var lessThan = docBody.search(/<</g);
var moreThan = docBody.search(/>>/g);
Logger.log([noOfLessThanMatches,noOfMoreThanMatches]);
result += "<b>Less Than Signs:</b> " + noOfLessThanMatches + "<br>";
result += "<b>More Than Signs:</b> " + noOfMoreThanMatches + "<br>";
result += "<br><b>Doc to Form Check</b><br>";
var newDocBody = docBody;
var reverseArray = [];
for (i = 0; i < noOfLessThanMatches; i++) {
var lessThan = newDocBody.search(/<</g);
var moreThan = newDocBody.search(/>>/g);
var subString = newDocBody.substring(lessThan + 2,moreThan);
Logger.log(subString);
var indexOf = formResponsesHeader[0].indexOf(subString);
if (indexOf > -1) {
result += subString + " - FOUND<br>";
} else {
result += subString + " - NOT FOUND<br>";
}
reverseArray.push(subString);
newDocBody = newDocBody.replace("<<" + subString + ">>","XX")
}
result += "<br><b>Form to Doc Check</b><br>";
for (z = 0; z < formResponsesHeader[0].length; z++) {
var thisString = formResponsesHeader[0][z];
var indexOf = reverseArray.indexOf(thisString);
if (indexOf > -1) {
result += thisString + " - FOUND<br>";
} else {
result += thisString + " - NOT FOUND<br>";
}
}
Logger.log(result);
var htmlOutput = HtmlService
.createHtmlOutput('<p>' + result + '</p>')
.setWidth(400)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'RESULT');
}
UPDATE: I have pasted the whole code instead above so you guys can see
You have to register onFormSubmit as the function that handles the form submit trigger. Have you registered the function "onFormSubmit" like this:
ScriptApp.newTrigger('onFormSubmit').forForm(form).onFormSubmit().create();
You might also want to check the registered triggers by clicking on Edit > Current project's trigger from your Apps Script project.
[Edit] Since the trigger is created properly, change the first the line of the trigger code from:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
to this:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.openById(e.source.getDestinationId());
In my spreadsheet I have a file path to an image stored in a sub folder. The image is stored like this because I am making an app for my employer using appsheet.com. They want this app developed using AppSheet, which does not allow images to be stored directly into the spreadsheets that are used to build these app.
The data stored in the spreadsheet must also be extracted and applied to a template and I am making a Google Apps Script to do this. I have a functional script which finds the template and extract the users chosen data row, but I cannot extract the image needed.
I have been trying to make a substring of the file path to get the file name, but I have been unable to do this.
In the block of code where I am trying to create the substring, I am getting an error on the line sig = signature.getText();. The error is TypeError: signature.getText is not a function (line 176, file "Code").
This is what the file path looks like Signatures/FT101.Signed (%SIGNED%).103735.png, and the substring I need would look like this FT101.Signed (%SIGNED%).103735.png
I have tried multiple methods that were provided by other questions asked on stack overflow as well as any potential methods available in the Google Apps Script reference.
The following function takes the users input from a prompt and uses it to find the desired row number. It then takes the data from that row and applies it to a template based on the category the data falls under.
var response = {};
var sign = "";
function chooseRowMethod(templateId){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var data = sheet.getRange(2, 2, 11, 18).getValues();//starting with row 2 and column 1 as our upper-left most column, get values from cells from 1 row down, and 15 columns along - hence (2,1,1,15)
var docTitle = sheet.getRange(2, 2, 11, 1).getValues();//this is grabbing the data in field B2
var docTitleTagNumber = sheet.getRange(2, 3, 11, 1).getValues();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
Logger.log(i);
var row = data[i - 1];
var docId = DriveApp.getFileById(templateId).makeCopy().getId();
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
body.replaceText("%SITEID%", row[0]);
body.replaceText("%TAG%", row[1]);
...
body.replaceText("%SAT%", row[14]);
var signature = sheet.getRange(2, 18, 11, 1).getValues();
var sig;
var sign = {};
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
sig = signature.getText();
sign[i][0] = sig.substring(sig.indexOf("/") + 1);
}
}
}
var sigFolder = DriveApp.getFolderById("1LiJKGjTbpvRZ5RrMTQoyTuAjrozA14FN");
var file = sigFolder.getFilesByName(sign);
var image = file.getId();
body.appendImage(image);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var newFolder = DriveApp.getFolderById("16wRGBVdV0OZ5YfKhqEQSFMsux-ekGCCa");
newFolder.addFile(file);
var newDocTitle = docTitle[i - 1][0];
var newDocTagNumber = docTitleTagNumber[i - 1][0];
doc.setName(newDocTitle + " " + newDocTagNumber + " " + today);
}
}
}
}
This is where I have been attempting to get the image.
var signature = sheet.getRange(2, 18, 11, 1).getValues();
var sig;
var sign = {};
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
sig = signature.getText();
sign[i][0] = sig.substring(sig.indexOf("/") + 1);
}
}
}
var sigFolder = DriveApp.getFolderById("1LiJKGjTbpvRZ5RrMTQoyTuAjrozA14FN");
var file = sigFolder.getFilesByName(sign);
var image = file.getId();
body.appendImage(image);
This next function gives the user the prompt and applies the correct template.
function chooseRow(){
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.prompt('Please enter the Tag number of the row you wish to print.', ui.ButtonSet.OK_CANCEL);
var button = result.getSelectedButton();
response = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK".
ui.alert('Your tag number is' + response + '.');
} else if (button == ui.Button.CANCEL) {
// User clicked X in the title bar.
ui.alert('You closed the dialog.');
return 'the end';
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var category = sheet.getRange(2, 4, 11, 1).getValues();
var templateId = {};
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response && category[i - 1][0] == "Instrument"){
templateId = "1cx2-6ju-o7DaRPnbuYxxdvVVFeGQzpTXaXV3wMuRpqo";
chooseRowMethod(templateId);
return "";
} else if(values[i][j] == response && category[i][0] == "Motor" || values[i][j] == response && category[i][0] == "Valve"){
templateId = "1sYx_JcoDHY-pzjEDlxMMa3dtdzOOE8CyyLGQk8WHg7s";
chooseRowMethod(templateId);
return "";
}
}
}
}
The expected result is a substring of the file path that can be used to retrieve an image that can be appended to the body of a document.
Here is a link to the spreadsheet.
I did several changes to your code, including the edit proposed by Cooper. It's retrieving the substring and adding the image to the file successfully. I hope it works for you:
function chooseRow(){
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.prompt('Please enter the Tag number of the row you wish to print.', ui.ButtonSet.OK_CANCEL);
var button = result.getSelectedButton();
response = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK".
ui.alert('Your tag number is' + response + '.');
} else if (button == ui.Button.CANCEL) {
// User clicked X in the title bar.
ui.alert('You closed the dialog.');
return 'the end';
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var tags = sheet.getRange(2, 4, 11, 1).getValues();
var category = sheet.getRange(2, 3, 11, 1).getValues();
for(var i = 0; i < tags.length; i++){
if(tags[i][0] == response && category[i][0] == "Instrument"){
var templateId = "my_template_id";
chooseRowMethod(templateId, i);
return ""; // You don't need to return empty string, just return null
} else if(tags[i][0] == response && category[i][0] == "Motor" || tags[i][0] == response && category[i][0] == "Valve"){
var templateId = "my_template_id_bis";
chooseRowMethod(templateId, i);
return ""; // You don't need to return empty string, just return null
}
}
}
The function chooseRowMethod gets the row index chosen by the user in chooseRow so that it doesn't have to be looked for again:
function chooseRowMethod(templateId, rowNumber){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var data = sheet.getRange(2, 2, 11, 18).getValues();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
var row = data[rowNumber];
var docTitle = row[1];
var docTitleTagNumber = row[2];
var docId = DriveApp.getFileById(templateId).makeCopy().getId();
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
body.replaceText("%SITEID%", row[0]);
body.replaceText("%TAG%", row[1]);
// ...
body.replaceText("%SAT%", row[14]);
var signature = row[17];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("my_sigfolder_id");
var files=sigFolder.getFilesByName(sign);
var n = 0;
while(files.hasNext()) {
var file=files.next();
n++;
} if(n>1) {
SpreadsheetApp.getUi().alert('There is more than one file with this name: ' + sign);
}
body.appendImage(file);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var newFolder = DriveApp.getFolderById("my_newfolder_id");
newFolder.addFile(file);
doc.setName(docTitle + " " + docTitleTagNumber + " " + today);
}
Trying to get data from Saleforce Analytics API into Google spreadsheet based on this handy script on Github. Except, instead of running entire report, I am trying to pass email filter based on the email list column on a different sheet of the same doc.
// Use the Analytics API to get report data
function runContactsReport() {
var reportId = '';
var sheetName = 'Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v29.0/analytics/reports/" + reportId + "?includeDetails=true"; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
// sheet to insert reports
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
//emails to filter on
var dataSheet = ss1.getSheetByName('DATA');
var emails = getColumnNrByName(dataSheet, 'Email')
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues();
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var filters = queryResult.reportMetadata.reportFilters; //get filters
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
To do this, I need to send back the report metadata object with edited filters.
Here’s some typical metadata that is returned per Salesforce API:
'{reportMetadata":{"name":"MerchandiseReport","id":"00OD0000001ZbP7MAK","developerName":"MerchandiseReport","reportType":{"type":"MerchandiseList","label":"Merchandise"},"reportFormat":"MATRIX","reportBooleanFilter":null,"reportFilters":[{"column": "QUANTITY", "operator":"greaterThan", "value":"12"}],"detailColumns":["MERCHANDISE.NAME","CREATED_DATE","QUANTITY"],"currency":null,"aggregates":["RowCount"],"groupingsDown":[{"name":"CONTACT2.COUNTRY_CODE","sortOrder":"Asc","dateGranularity":"None"}],"groupingsAcross":[{"name":"OWNER","sortOrder":"Asc","dateGranularity":"None"}]}}'
Unfortunately, I don't know how to pass it in Apps Script. Any help is appreciated!
UPDATE: After battling with this code, here are the latest results. Per API instructions, I needed to pass POST request to pass filter parameters. Send a POST request to the Execute Async resource. If you’re passing filters, include them in the POST request metadata. The request returns the instance ID where results of the run are stored.
So here is what I have:
function filterReport(){
var reportId = '00O33000004Dels';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('DATA');
var emailds = getColumnNrByName(dataSheet, 'Email');
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues();
for (var i = 0; i < emailFilters.length; i++) {
var payload = JSON.stringify({
'reportMetadata': {
'reportFilters': [{
'value' : emailFilters[i][0],
'column': 'EMAIL',
'operator': 'equals'
}]
}
});
filter(reportId, payload);
}
}
function filter(reportId, payload) {
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances";
var options = {
'headers': {
'Authorization' : 'Bearer ' + sfService.getAccessToken()
},
'contentType' : 'application/json',
'method' : 'POST',
'payload' : payload
};
var response = UrlFetchApp.fetch(queryUrl, options);
if (response.getResponseCode() == 200) {
var params = JSON.parse(response.getContentText());
//Logger.log(response.getContentText());
var filterId = params.id;
//Logger.log(filterId);
Logger.log(response.getContentText())
}
}
This returns not one instance ID but 4, as I have in my sample spreadsheet... and I need one ID to pass 4 results (per this example).
After that, I need to send GET request with this instance ID, so I can get the data with filters into the spreadsheet.
I have this function, and it sort of works, but I don't know how to pass that Instance id into it from my POST request automatically...
// Use the Analytics API to get report data
// The try-catch can be removed if you do not need to track errors
function runContactsReport() {
var reportId = '00O33000004Dels';
var sheetName = 'Contact Email Validation Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances/0LG33000005ZJdqGAG"; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}
So, I am stuck again.. Please help!
I got it to work at last. Hopefully it will helpful for someone. The only issue I am having is that occasionally when I run runContactsReport(), it comes back with error -" TypeError: Cannot read property "T!T" from null." but then it runs fine - quite puzzling... here is what I got:
//this is POST request to pass filters based on email column into report
function filterContacts() {
var reportId = 'YOUR REPORT ID'; //SF Contacts Report ID
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('DATA');
var emailds = getColumnNrByName(dataSheet, 'Email'); //custom function that finds header name and returns column umber
var emailFilters = dataSheet.getRange(2, emailds, dataSheet.getLastRow() -1).getValues(); //column with emails
//put all emails in one comma separated string, so we get one instance ID
var emails = emailFilters.toString().split(",").join();
var payload = JSON.stringify({
'reportMetadata': {
'reportFilters': [{
'value' : emails,
'column': 'EMAIL',
'operator': 'equals'
}]
}
});
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances";
var options = {
'headers': {
'Authorization' : 'Bearer ' + sfService.getAccessToken()
},
'contentType' : 'application/json',
'method' : 'POST',
'payload': payload
};
//Logger.log(options)
var response = UrlFetchApp.fetch(queryUrl, options);
if (response.getResponseCode() == 200) {
var params = JSON.parse(response.getContentText());
}
//Logger.log("my id is:" + params.id);
return params.id; //return instance ID
}
// use returned instance ID to run report based on email filter
function runContactsReport() {
filterContacts();
var reportId = 'YOUR REPORT ID'; //SF Contact Email Validation Report
Utilities.sleep(200);// pause in the loop for 200 milliseconds
var instanceId = filterContacts();
// Logger.log("And my id is:" + instanceId);
var sheetName = 'Contact Email Validation Report';
var sfService = getSfService();
var userProps = PropertiesService.getUserProperties();
var props = userProps.getProperties();
var name = getSfService().serviceName_;
var obj = JSON.parse(props['oauth2.' + name]);
var instanceUrl = obj.instance_url;
var queryUrl = instanceUrl + "/services/data/v35.0/analytics/reports/" + reportId + "/instances/" + instanceId; // Actual request for report Data
var response = UrlFetchApp.fetch(queryUrl, { method : "GET", headers : { "Authorization" : "OAuth "+sfService.getAccessToken() } });
var queryResult = JSON.parse(response.getContentText());
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(sheetName);
var answer = queryResult.factMap["T!T"].rows; // assumes tabular report
var headers = queryResult.reportExtendedMetadata.detailColumnInfo;
var headname = queryResult.reportMetadata.detailColumns;
var filters = queryResult.reportMetadata.reportFilters;
//Logger.log(filters)
var myArray = [];
var tempArray = [];
for (i = 0 ; i < headname.length ; i++) {
tempArray.push(headers[headname[i]].label);
}
myArray.push(tempArray);
for (i = 0 ; i < answer.length ; i++ ) {
var tempArray = [];
function getData(element,index,array) {
tempArray.push(array[index].label)
}
answer[i].dataCells.forEach(getData);
myArray.push(tempArray);
}
var lastRow = sheet.getLastRow();
if (lastRow < 1) lastRow = 1;
sheet.getRange(1,1,lastRow, myArray[0].length).clearContent();
sheet.getRange(1,1, myArray.length, myArray[0].length).setValues(myArray);
}