Google Forms Dynamic multiple choice with pictures - google-apps-script

I have a dynamic multiple choice google form that is working fine except for if i add a picture to the option box using the attach picture function in the google form editing screen.
When the form refreshes all the pictures are lost.
below is the code for the dynamic form.
What i need is to be able to assign a picture the the option title.
function updateLists() {
var files = DriveApp.getFolderById("0B-yHzwrw6kldVDVzZlA5bTlScDg").getFiles()
while (files.hasNext()) {
var file = files.next();
var form = FormApp.openById(file.getId())
var items = form.getItems();
for (var i = 0; i < items.length; i += 1){
var item = items[i]
if (item.getTitle() === "Requested Award"){
var agentList = item.asMultipleChoiceItem()
}
}
var ss = SpreadsheetApp.getActive().getSheetByName("Menu");
var agentValues = ss.getRange(1, 15, ss.getMaxRows() - 1).getValues();
var agentNames = [];
for(var i = 0; i < agentValues.length; i++)
if(agentValues[i][0] != "")
agentNames[i] = agentValues[i][0];
agentList.setChoiceValues(agentNames);
}
}

Related

google apps script: get gmail jpg attachments & insert them into google sheets

The code finds all the jpg's from a sender and then creates an array with those images and then is supposed to insert the received images into the cells of the sheet.
Instead, the code inserts the word Blog into the cells instead of the images.
I've tried several methods to solve the problem but have not had any luck.
function importEmailsWithJPGs() {
var sheet = SpreadsheetApp.getActiveSheet();
var emailAddress = "a#gmail.com";
var threads = GmailApp.search("from:" + emailAddress + " filename:jpg");
var attachments;
var date;
var rowData = {};
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
attachments = messages[j].getAttachments();
date = messages[j].getDate();
var dateString = Utilities.formatDate(date, "GMT", "yyyy-MM-dd");
if (!rowData[dateString]) {
rowData[dateString] = [date];
}
for (var k = 0; k < attachments.length; k++) {
if (attachments[k].getContentType().indexOf("image/jpeg") !== -1) {
//var image = attachments[k].getAs('image/jpeg');
// var imageName = attachments[k].getName();
// var blob = new Blob([image], { type: 'image/jpeg' });
// rowData[dateString].push(blob);
//var image = attachments[k].getAs('image/jpeg');
// var imageName = attachments[k].getName();
// var byteArray = image.getBytes();
// var base64EncodedImage = Utilities.base64Encode(byteArray);
// var blob = Utilities.newBlob(base64EncodedImage, 'image/jpeg', imageName);
// rowData[dateString].push(blob);
var image = attachments[k].copyBlob();
var imageName = attachments[k].getName();
var blob = Utilities.newBlob(image.getBytes(), 'image/jpeg', imageName);
rowData[dateString].push(blob);
}
}
}
}
for (var key in rowData) {
sheet.appendRow(rowData[key]);
}
var data = sheet.getDataRange().getValues();
for (var i = 0; i < data.length; i++) {
for (var j = 1; j < data[i].length; j++) {
var cell = sheet.getRange(i + 1, j + 1);
var value = data[i][j];
if (value && value.getBytes) {
//var image = value;
var image = value.getAs('image/jpeg');
//var imageData = new Uint8Array(image.getBytes());
var cellWidth = cell.getWidth();
var cellHeight = cell.getHeight();
var imageWidth = image.getWidth();
var imageHeight = image.getHeight();
var ratio = Math.min(cellWidth / imageWidth, cellHeight / imageHeight);
cell.setValue("");
// cell.setImageData(imageData);
cell.setImageData(image);
}
}
}
}
Modification points:
First, I think that the reason that the text of Blob is put to the cell is due to that appendRow cannot put the image blob to the cell.
After that line of var data = sheet.getDataRange().getValues();, I think that value && value.getBytes is always false. Because, value.getBytes is undefined, and also, there is no method of setImageData in Class Range at cell.setImageData(image);. And, an error occurs at value.getAs('image/jpeg') because value has no method.
Unfortunately, from your reply, I cannot understand the relationship between for (var key in rowData) { sheet.appendRow(rowData[key]); } and the script below var data = sheet.getDataRange().getValues();. But, if you want to just put the image data from the image blob to the cells instead of the text of Blob, how about the following modification?
In this modification, a Google Apps Script library is used. Because in the current stage, unfortunately, the image blob cannot be directly put into a cell. So, I created this library. In order to use the following modified script, please do the following flow.
Usage:
1. Install Google Apps Script library.
You can see how to install it at https://github.com/tanaikech/DocsServiceApp#how-to-install. (Author of this library: me)
2. Enable Drive API.
Please enable Drive API at Advanced Google services.
3. Modified script:
Please modify your script as follows.
From:
for (var key in rowData) {
sheet.appendRow(rowData[key]);
}
var data = sheet.getDataRange().getValues();
for (var i = 0; i < data.length; i++) {
for (var j = 1; j < data[i].length; j++) {
var cell = sheet.getRange(i + 1, j + 1);
var value = data[i][j];
if (value && value.getBytes) {
//var image = value;
var image = value.getAs('image/jpeg');
//var imageData = new Uint8Array(image.getBytes());
var cellWidth = cell.getWidth();
var cellHeight = cell.getHeight();
var imageWidth = image.getWidth();
var imageHeight = image.getHeight();
var ratio = Math.min(cellWidth / imageWidth, cellHeight / imageHeight);
cell.setValue("");
// cell.setImageData(imageData);
cell.setImageData(image);
}
}
}
To:
var lastRow = sheet.getLastRow();
var v = Object.values(rowData);
var values = v.map(([a]) => [a]);
sheet.getRange(lastRow + 1, 1, values.length).setValues(values);
var obj = v.map(([, blob], i) => ({ blob, range: { row: lastRow + i + 1, column: 2 } }));
DocsServiceApp.openBySpreadsheetId(sheet.getParent().getId()).getSheetByName(sheet.getSheetName()).insertImage(obj);
When this script is run, the text value and the image data are put into the columns "A" and "B", respectively.
Reference:
DocsServiceApp (Author: me)

Closed: vanishing data in Google Form after refreshing the page

I wrote a google script, which is creating form, using data from google spreadsheet. I'm using drop-down answer options. The code works normally, all data appears, but sometimes ( 3 times of 5 attempts), after refreshing browser page, some questions disappeared. Everytime it's different question, so it isn't problem with specific question.
What is the problem and how can i fix it?
UPD: Solved. Problem was in opened Google Form while code was compiled.
function myFunk(){
var SHEET_ID = FormApp.getActiveForm().getDestinationId();
var ss = SpreadsheetApp.openById(SHEET_ID);
var form = FormApp.getActiveForm();
var sheets = ss.getSheets();
var numb = sheets[1].getLastRow();
var TypeSelect = form.addListItem()
.setRequired(true);
var TypeChoices = getData(TypeSelect,sheets[1],1,numb)
TypeSelect.setChoices(TypeChoices);
var ClientSelect = form.addListItem()
.setRequired(true)
var ClientChoices = getData(ClientSelect, sheets[1],2,numb)
ClientSelect.setChoices(ClientChoices);
var phases = ["Start","End"];
var PhasesChoices=[];
var PhaseSelect = form.addMultipleChoiceItem()
.setRequired(true);
for (var t=0;t<phases.length; t++){
PhasesChoices.push(PhaseSelect.createChoice(phases[t]));
}
PhaseSelect.setChoiceValues(phases);
}
function getData(DataSelect,sheet,numbColumn,lRow){
var DataChoices = [];
var DataValues = sheet.getRange(2,numbColumn,lRow,1).getValues()
.filter(CheckFull);
var data = [];
for(var i = 0; i < DataValues.length; i++) {
data.push(DataValues[i]);
}
for(var j =0; j < data.length; j++) {
DataChoices.push(DataSelect.createChoice(data[j]));
}
return DataChoices;
}
function CheckFull(value){
return value != '';
}

Script to change options in MULTIPLE google forms by means of a column in a google spreadsheet

This question is similar to the last one I presented, but this time, I need to change the options in MULTIPLE google forms with the same title: WHAT IS YOUR NAME (in every single form, the question title is the same, but I have to change the options to hundreds of forms under this question). All the forms must change based on one column in a Google Spreadsheet. The Code below almost works, and I get no errors, but for some reason, it will only change one form instead of changing all of them in the folder. Any help would be appreciated.
function updateLists() {
var files = DriveApp.getFolderById("ID HERE").getFiles()
while (files.hasNext()) {
var file = files.next();
var form = FormApp.openById(file.getId());
continue;
}
var items = form.getItems();
for (var i = 0; i < items.length; i += 1){
var item = items[i]
if (item.getTitle() === "WHAT IS YOUR NAME"){
var agentList = item.asListItem()
}
}
var ss = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var agentValues = ss.getRange(2, 1, ss.getMaxRows() - 1).getValues();
var agentNames = [];
for(var i = 0; i < agentValues.length; i++)
if(agentValues[i][0] != "")
agentNames[i] = agentValues[i][0];
agentList.setChoiceValues(agentNames);
}
Consider logging custom messages to find out why it's not looking at multiple forms. Likely because .setChoiceValues() and some other lines needed aren't inside the while loop. agentNames could get created once before the while too.
That continue statement isn't really doing anything either. The form var will only contain the last one looked at. As is, all the form files before the last one are each being placed in the var form then replaced with the next one found.
In accordance with what Bryan P mentioned above, I changed the script slightly and it finally worked. The modified and working script is below for those who want to copy and paste. Just a quick note: make sure you have nothing else but forms in the folder or an error will be produced.
function updateLists() {
var files = DriveApp.getFolderById("FOLDER ID HERE").getFiles()
while (files.hasNext()) {
var file = files.next();
var form = FormApp.openById(file.getId())
var items = form.getItems();
for (var i = 0; i < items.length; i += 1){
var item = items[i]
if (item.getTitle() === "QUESTION TITLE HERE"){
var agentList = item.asListItem()
}
}
var ss = SpreadsheetApp.getActive().getSheetByName("SHEET NAME HERE");
var agentValues = ss.getRange(2, 1, ss.getMaxRows() - 1).getValues();
var agentNames = [];
for(var i = 0; i < agentValues.length; i++)
if(agentValues[i][0] != "")
agentNames[i] = agentValues[i][0];
agentList.setChoiceValues(agentNames);
}
}

populating dropdown list values from google spreadsheet using HTML service

Hi I am trying to get a dropdown list using html and google script.
The values for the list should be populated from a google spreadsheet. After searching a lot on stackoverflow I managed the below code. But I am still not able to get the data from spreadsheet as dropdown option. There is no error but i am just getting a blank dropbox as output
Spreadsheet link:https://docs.google.com/spreadsheets/d/1qaxzTWRf4_xDhfkf-_S9Zr2m-M-9blOcpFBt4JyT5do/edit#gid=0
code.gs
function doGet() {
var template = HtmlService.createTemplateFromFile('Index');
var htmlOutput = template.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return htmlOutput;
}
html code
< select id = "something" > < option > Choose a option < /option>
</select > < body onload = "addList()" > < /body>
<script>
function addList(){
var sheet = SpreadsheetApp.openById('1qaxzTWRf4_xDhfkf-_S9Zr2m-M-9blOcpFBt4JyT5do').getSheetByName('Sheet1');
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("C2:C" + lastRow);
var options = new Array()
var select = document.getElementById("something");
var data = myRange.getValues();
for(var i = 0; i < lastRow; i++) {
options.push(data[i]);
}
for(var i = 0; i < options.length; i++) {
var opt = options[i];
var el = document.createElement("option");
var el = document
el.text = opt;
el.value = opt;
select.appendChild(el);
}
</script >

Duplicating a page of a document and replacing text on each page

I am trying to create a script that will take a Google Doc template document, make a copy, replace certain text with information from a row on my spreadsheet, append another page, replace the text with information from the next row on the spreadsheet, append another page, etc.
Here is what I have so far:
// Global variables
var templateDocID = ScriptProperties.getProperty("backRxRequestDocID");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var activeSheetName = sheet.getName();
var user = Session.getUser().getEmail();
function requestGen3() {
var physName = ["doc john", "doc evan", "doc jane"];
var physAddr1 = ["fake st.", "faker st.", "fakest st."];
var physAddr2 = ["ste 100", "", "ste 209"];
var physCity = ["SLC", "Provo", "Orem"];
var physState = ["UT", "AZ", "NV"];
var physZip = ["84049", "84044", "84601"];
var physPhone = ["8015555555", "7206666666", "4803333333"];
var ptName = ["ed", "sue", "izzy"];
var ptDOB = ["12/10/1979", "1/1/2001", "45/94/4561"];
// Get document template, copy it as a new temp doc, and save the Doc’s id
var docID = DocsList.getFileById(templateDocID).makeCopy().getId();
var doc = DocumentApp.openById(docID);
var body = doc.getActiveSection();
var pars = doc.getParagraphs();
var bodyCopy = body;
for (var i = 0; i < physName.length; ++i) {
// Replace place holder keys,
body.replaceText('%PHYS_NAME%', physName[i]);
body.replaceText('%PHYS_ADDR1%', physAddr1[i]);
body.replaceText('%PHYS_ADDR2%', physAddr2[i]);
body.replaceText('%PHYS_CITY%', physCity[i]);
body.replaceText('%PHYS_STATE%', physState[i]);
body.replaceText('%PHYS_ZIP%', physZip[i]);
body.replaceText('%PHYS_PHONE%', physPhone[i]);
body.replaceText('%PT_NAME%', ptName[i]);
body.replaceText('%PT_DOB%', ptDOB[i]);
doc.appendPageBreak();
for (var j = 0; j < pars.length; ++j) {
doc.appendParagraph(pars[j].copy());
}
}
// Save and close the document
doc.saveAndClose();
}
I went through the tutorial on reading from the spreadsheet but I couldn't seem to make getRowsData() and getObjects() to work properly. My script above is creating the document properly but is not inserting the second set of info into the second page and third set into the third page, etc.
You have to replace the text only after you copied the paragraphs, because if you do it after, the placeholders will be already replaced and will not be present for the next copies. You can do it like this:
//...
var pars = doc.getParagraphs();
for( var i in pars ) //loop to keep a copy of the original paragraphs
pars[i] = pars[i].copy();
for( var i = 0; i < physName.length; ++i ) {
body.replaceText('%PHYS_NAME%', physName[i]);
//do all your replaces...
if( i != physName.length-1 ) { //has next?
doc.appendPageBreak();
for( var j in pars )
doc.appendParagraph(pars[j].copy());
}
}
doc.saveAndClose();
The following code will read your spreadsheet and create a matrix called data.
var sh = SpreadsheetApp.getActive().getActiveSheet();
var lastRow = sh.getLastRow();
var lastCol = sh.getLastColumn();
var data = sh.getRange(1, 1, lastRow, lastCol).getValues();