I have created a Google form that is linked to a Google spreadsheet containing two sheets. I have also created a function in Google Scripts, called "handleFormSubmission", that when triggered (on submission of the linked form):
creates a variable containing the values of this submission from sheet one: var s0Row = s0.getRange("A"+(s0Last)+":J"+(s0Last)).getValues();
then, if a matching ID condition is met on both sheets, sets those values from sheet one into the appropriate range on sheet two: s1Row.setValues(s0Row);
There's probably a better way to do this, but for now the function works fine when run from Google Scripts and the form is returning submissions to sheet one.
The problem I'm having is getting this function to trigger when the linked form has been submitted. I've attempted to set this trigger up as you'll see in the screen shot below.
Code
function handleFormSubmission() {
var ss = SpreadsheetApp.openById("1FmArzo50IV2Wmykgsa89l_EARjzkiyeFDoPaCjGyBZM");
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActive();
var s0 = sheet.getSheets()[0];
var s0Last = s0.getLastRow();
var s1 = sheet.getSheets()[1];
var s1Last = s1.getLastRow();
var s0Bid = s0.getRange(s0Last, 10).getValue();
var s0Row = s0.getRange("A"+(s0Last)+":J"+(s0Last)).getValues();
for (var i = 2; i < s1Last + 1; i++) {
var s1Bid = s1.getRange(i, 10).getValue();
var s1First = s1.getRange(i, 2).getValue();
var s1LastName = s1.getRange(i, 3).getValue();
var s1Row = s1.getRange("A"+(i)+":J"+(i));
if (s0Bid === s1Bid) {
Logger.log(i + " " + s1First + s1LastName);
Logger.log("s0: " + s0Bid);
Logger.log("s1: " + s1Bid);
Logger.log("Match!");
s1Row.setValues(s0Row);
Logger.log("----------------------");
break;
} else {
Logger.log(i + " " + s1First + s1LastName);
Logger.log("s0: " + s0Bid);
Logger.log("s1: " + s1Bid);
Logger.log("Nope...");
Logger.log("----------------------");
}
};
};`
Current Project's Triggers
It's definitely an event on the spreadsheet that you're intercepting, although that may seem counter-intuitive.
I had the same problem & solved it by deleting the trigger, creating a new version of the script, then recreating the trigger. Don't know why it works -- perhaps a GAppsScript expert could explain it to us.
Also, why not get your form submission values out of the event object? So, instead of hunting down the last row of sheet[0] (which could, in an extreme case, not be the submission you're looking for, but the next one), you can access the field you want from the event object using either of:
e.values (an array of the form values in the order they appear in the spreadsheet)
e.namedValues (a dictionary/hash of the form values)
I think the event should be "From form" not "From spreadsheet". That is because you are working on script editor opened from the spreadsheet. It populates when you open the script editor from the form and write the function in that editor. Hope that helps!
Related
This is the flow I created through Google Apps Script.
Someone writes their information in google form
The information is stored into spreadsheet
Invoice is created within spreadsheet with the newest information received
The invoice is turned into PDF format automatically
The newest invoice is attached to the auto sending email
The person receives an auto-email with the invoice attached as soon as they submit the google form
The problem is that, when someone submits the google form, they receive an invoice but what they receive is the invoice from the information one before. This then repeats. When someone submits, the information inside the invoice is from the person one before.
I am a starter at Google Script so I have no idea why this is happening.
This is the code I use to send the auto email. I have minimized the code.
function for_users2() {
var title = "【お問い合わせありがとうございます】";
var name = '名前';
var mail = 'メールアドレス';
var address = "";
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getLastRow();
var column = sheet.getLastColumn();
var range = sheet.getDataRange();
var TIMESTAMP_LABEL = 'タイムスタンプ';
for (var i = 1; i <= column; i++ ) {
var item = range.getCell(1, i).getValue();
var value = range.getCell(row, i).getValue();
if ( item === TIMESTAMP_LABEL ) {
item = 'お問い合わせ日時';
}
if ( item === 'お問い合わせ日時' ) {
value = Utilities.formatDate(value, 'Asia/Tokyo',"YYYY'年'MM'月'dd'日'HH'時'mm'分'ss'秒'");
}
body += "■"+item+"\n";
body += value + "\n\n";
if ( item === name ) {
body = value+" 様\n\n"+body;
}
if ( item === mail ) {
address = value;
}
}
body += body2;
var token = ScriptApp.getOAuthToken();
var pdf = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO/export?exportFormat=pdf&format=pdf&size=A4&portrait=true&fitw=true&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&fzr=false&gid=00000000000", {headers: {'Authorization': 'Bearer ' + token}}).getBlob().setName('請求書');
GmailApp.sendEmail(
address,
title,
body,
{
attachments: [pdf],
name: 'Automatic Emailer Script'
}
);
}
There is no error. It's just that the invoice attached is from one previous customer.
Thank you to the people who have answered my question. Special thanks to Tanaike who have suggested a workaround where I was able to use as a starter to GAS.
As I used Utilities.sleep(5000), whenever someone submits google form, the invoice produced (PDF format) is updated to the newest info. Since the program I created isn't aimed for very heavy processes, it may be the reason why it worked perfectly fine.
If SpreasheetApp.flush() doesn't seem to be working then you should certainly move to the onFormSubmit - Installable Trigger.
Triggers - Form Submit
This way you can process the exact values from the form and use the same function you are using now. Instead of fetching the last row values, you can fetch the values from the form submission using this.
var name = e.namedValues['Name'][0]; var email = e.namedValues['Email'][0];
I have a set of scripts that I'm using that interact with each other. I use a client, user event and suitelet script to create a button that, when pressed, opens a popup with a list of items filtered by vendor.
It works fine when I'm in edit however when I use it while creating a record problems arise. Since the record to be created has no vendor or id I can't retrieve an item by vendor. What I'm trying to do is to have the Suitelet retrieve the info from the vendor field that is entered prior to it being saved. Therefore I can filter all the items by vendor and add the necessary items in one go. Is this possible? Am I able to access the info before it is submitted.
Below are the Client and Suitelet. The User Event is just a call to the suitelet so for the sake of brevity I left it out.
Client Script
function addItemButtonCallback(data){
nlapiSelectNewLineItem('item');
nlapiSetCurrentLineItemValue('item', 'item', data);
nlapiCommitLineItem('inventoryitem');
}
function addItemButton() {
var id = nlapiGetFieldValue('id');
if (id != "") {
var url = nlapiResolveURL('SUITELET', 'customscript_val', 'customdeploy1') + '&poId='+id;
window.open(url, '_blank', 'width=500,height=500');
}
}
Suitelet
function suitelet(request, response){
if(request.getMethod() == 'GET') {
var form = nlapiCreateForm('Add Item');
form.addSubmitButton('Submit');
var itemfield = form.addField('custpage_val', 'select', 'Item');
var id = request.getParameter('id');
var rec = nlapiLoadRecord('purchaseorder', id);
var vend = rec.getFieldValue('entity');
var search = nlapiSearchRecord(...search parameters...);
for (result in search){
if (search[result].getValue('vendor') == vend){
itemfield.addSelectOption(search[result].id, nlapiLookupField('inventoryitem', search[result].id, 'itemid'));
}
}
response.writePage(form);
} else {
var data = request.getParameter('custpage_item');
response.write('<html><body><script>window.opener.addItemButtonCallback("'+data+'"); window.close();</script></body></html>');
}
}
Use nlapiGetFieldValue('entity') on the clientscript and pass it to the Suitelet using a query parameter just like you are doing with poId (if you do this you might not even need poId after all + no need to load the record on the suitelet).
Also, you might want to optimize your code by running one search passing an array of itemids instead of calling nlapiLookupField for each item.
You might need to modify your beforeLoad so the entity is inserted dynamically when the button is pressed (I cant remember if clientscript button does this) . Something like this:
var suiteletURL = nlapiResolveURL('SUITELET', 'customscript_val', 'customdeploy1');
var script = "var entity = nlapiGetFieldValue('entity'); var url = '" + suiteletURL + "'&entityId=' + entity;window.open(url, '_blank', 'width=500,height=500')";
var button = form.addButton('custpage_addItemButton', 'Add Item', script);
I am using Google Scripts UiApp in order to gather availability information. I want to send this information to a spreadsheet. I have used the example here: http://www.googleappsscript.org/advanced-examples/insert-data-in-sheet-using-ui-forms
to get me started in the right direction.
The Web App looks good and when clicking submit, the appropriate message displays. However, the values that are transferred to the spreadsheet say "undefined" for all of the entries.
How can I convince it to link the textbox entered data to the variables so that I can transfer to the spreadsheet?
Thanks!!
Here is some code:
var submissioSSKey = // Key removed
function doGet() {
var rows = 15
var columns = 15
var mygrid = UiApp.createApplication().setTitle("MLC Walk Ins Scheduling")
var panel = mygrid.createSimplePanel();
// Define the grid layout
var grid = mygrid.createGrid(rows, columns).setCellPadding(2).setCellSpacing(8)
// Create the text at the top
var Title = mygrid.createLabel("Walk-In Scheduling")
grid.setWidget(1, 1, Title)
(snip) - creating various checkboxes and textboxes
var text1 = mygrid.createTextBox().setName('name1')
grid.setWidget(3,9,text1)
var text6 = mygrid.createTextBox().setName('message1')
grid.setWidget(4,9,text6)
// Create the "submit" button
var submit_button = mygrid.createButton("Submit")
grid.setWidget(12,9,submit_button)
var infoLabel = mygrid.createLabel('Availability inserted successfully.').setVisible(false).setId('info');
grid.setWidget(13,9,infoLabel)
var handler = mygrid.createServerClickHandler('insertInSS');
handler.addCallbackElement(panel);
submit_button.addClickHandler(handler);
panel.add(grid);
mygrid.add(panel);
mygrid.add(grid);
return mygrid
}
Then the function call for the button:
//Function to insert data in the sheet on clicking the submit button
function insertInSS(e){
var mygrid = UiApp.getActiveApplication()
var name1 = e.parameter.name1
var message1 = e.parameter.message1
mygrid.getElementById('info').setVisible(true).setStyleAttribute('color','blue')
var sheet = SpreadsheetApp.openById(submissioSSKey).getActiveSheet()
var lastRow = sheet.getLastRow()
var targetRange = sheet.getRange(lastRow+1, 1, 1, 2).setValues([[name1,message1]])
return mygrid
}
Ahh! A simple fix for a big headache.
I had an extra line:
mygrid.add(grid);
that was breaking it.
this is my first time here as a poster, please be gentle! I have zero knowledge of JS (yet, working on it) but am required to do some JS anyway. Here's my problem. I got some code (not mine) allowing a user to select multiple choices. I found the function that gathers these choices and store them
function getProductAttribute()
{
// get product attribute id
product_attribute_id = $('#idCombination').val();
product_id = $('#product_page_product_id').val();
// get every attributes values
request = '';
//create a temporary 'tab_attributes' array containing the choices of the customer
var tab_attributes = [];
$('#attributes select, #attributes input[type=hidden], #attributes input[type=radio]:checked').each(function(){
tab_attributes.push($(this).val());
});
// build new request
for (var i in attributesCombinations)
for (var a in tab_attributes)
if (attributesCombinations[i]['id_attribute'] === tab_attributes[a])
request += '/'+attributesCombinations[i]['group'] + '-' + attributesCombinations[i]['attribute'];
$('#[attsummary]').html($('#[attsummary]').html() + attributesCombinations[i]['group']+': '+attributesCombinations[i]['attribute']+'<br/>')// DISPLAY ATTRIBUTES SUMMARY
request = request.replace(request.substring(0, 1), '#/');
url = window.location + '';
// redirection
if (url.indexOf('#') != -1)
url = url.substring(0, url.indexOf('#'));
// set ipa to the customization form
$('#customizationForm').attr('action', $('#customizationForm').attr('action') + request);
window.location = url + request;
}
I need to make a simple display summary of these choices. After quite a bit of searching and findling, I came with the line with the DISPLAY SUMMARY comment, this one:
$('#[attsummary]').html($('#[attsummary]').html() + attributesCombinations[i]['group']+': '+attributesCombinations[i]['attribute']+'<br/>')
In the page where I want those options, I added an empty div with the same ID (attsummary):
<div id="attsummary"></div>
Obviously, it is not working. I know I don't know JS, but naively I really thought this would do the trick. May you share with me some pointers as to where I went wrong?
Thank you very much.
Correct form of the line it isn't working for you:
$('#attsummary').html($('#attsummary').html() + attributesCombinations[i]['group']+': '+attributesCombinations[i]['attribute']+'<br/>')
I need to generate two type of fields, with a specific tags <form:input> and <form:hidden> dynamically from JS.
The first one <form:input> should be an input field the second, must be hidden.
The problem is that <form:input> is not recognized as an input and it's not shown at all. But it can be seen from the page source code.
if (bank != null) {
var fields = bank.additionalFields;
var additionalRows = document.getElementById("additionalRows");
for (i = 0; i < fields.length; i++) {
//from here generates jsp inputs:
//1 - <form:input>
//2 - <form:hidden> for each element from fields
var formInput = document.createElement("form:input");
var formHidden = document.createElement("form:hidden");
formInput.setAttribute("path", "paymentInfo.fields[" + i + "].value");
formHidden.setAttribute("path", "paymentInfo.fields[" + i + "].id");
formInput.setAttribute("type", "text");
formHidden.setAttribute("type", "text");
formInput.setAttribute("value", "");
formHidden.setAttribute("value", fields[i].id);
additionalRows.appendChild(formInput);
additionalRows.appendChild(formHidden);
}
}
Other <form:input> fields generated from JSP are appearing properly on the page.
Link to the generated page source code >> https://dl.dropboxusercontent.com/u/106355152/form_input.PNG
How can it be resolved?
What you are trying to do likely cannot be done. <form:input> and <form:hidden> appear to be server side tags - this is why they are only working from the java end.
You can generate regular and tags using javascript in a way similar to your current approach:
var formInput = document.createElement("input");
var formHidden = document.createElement("input");
formInput.setAttribute("type", "text");
formHidden.setAttribute("type", "hidden");
and then append them to your form.