Is there a way to auto save data in google sheet? - google-apps-script

Is there a way to auto save data entered in a temp area (risk is a calculated value based on the values entered) on google sheet. I have a working space and all my logs is now needing to be saved for later review.
see sample sheet.
Created a sample data screenshot
Thanks

There's two ways to do it. You'll need to create a log of sorts and have the dashboard reference the bottom most entry. If you have App Script experience, that would be the better solution, however without it you could use the a Google Form for editing the dashboard. There wouldn't be any formulas alone that will work for this due to needing to hardcode the inputs, and formulas can only return values as arrays (mirror/change values in other cells).
You can use a Google Form that is linked to the spreadsheet so that someone has to submit the form with the inputs to change the dashboard. You would then use a =Max() function on the timestamp column, and then either Vlookup or Index(match()) to return the variables for the dashboard based off Max(timestamp).
The alternative method would be to create basically set of cells similar to the input table, and add a button that if clicked, takes, the values and updates them in the variables for the dashboard, but also logs them on another sheet. (It would be something like this)

Thank you all for the suggestions. I end up using the below script to accomplish the task.
function FormExec() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sinput = ss.getSheetByName("sheet1");
var soutput = ss.getSheetByName("sheet2");
var input = sinput.getRange(14, 3, 15).getValues();
var flatin = [].concat.apply([], input);
soutput.getRange(soutput.getLastRow()+1, 1,1, 15).setValues([flatin]);
soutput.insertRowAfter(soutput.getLastRow());
Logger.log(input);
}

Related

A fillable table in Google Forms that records data in a specific Google Sheet

I'm trying to create a table with editable cells in a google form that lets people enter their recorded measurements. Then compile that information into a Google Sheet by specified columns.
I have tried the Awesome table but I cannot seem to get the script to work.
Broken Down, I need the Script to be able to:
import a table into google forms
edit the number of columns and rows
allow multiple people to record their measurements individually
Compile the recorded data into a sheet by column.
This may be a simple question that I am overthinking. But I am trying to avoid multiple questions on the same form, and think a table would be way easier.
As talked in the comments, since there is no table item in FormApp, this solution consists in sending a Sheet with a predefined table for users to fill. They will press a button and send the data to a master sheet.
CODE
function sendData() {
//Gets the sheet is being edited
var sprsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = sprsheet.getActiveSheet();
//Gets the data introduced by the user
var range = sheet.getRange("A2:L2");
var values = range.getValues();
//Gets the target sheet
var mainsprsheet = SpreadsheetApp.openById("main sheet id");
var targetSheet = mainsprsheet.getActiveSheet();
//Adds a new row to the target sheet with the collected data
targetSheet.appendRow(values);
//Clear the cells (optional)
range.clearContent();
}
BUTTON
To create the "submit" button to run the function above:
Go to Insert > Drawing
Design your own button
Save and close
Click on the button and then on the 3 dots at the right-top.
Click on "Assign script" and write sendData
You can place the button anywhere and resize it.
NOTES
You might want to send copies of this sheet to the different users to avoid sharing of sensitive data.
REFERENCES
Range Class
Method getValues
Method appendRow

Script in Google Apps Script that copies values in a range to another sheet

I am working on a tool that will allow my company to track its financial investments.
I need to create a simple data entry form for users to input transaction data, which will then populate a master sheet which is the basis for the analyses the tool does. I cannot do this via Google Forms because the data entry form uses a lot of conditional formatting based on other data in the sheet.
I have uploaded a very simplified sheet to illustrate what I need: this
What I am looking for is a script that, upon clicking Submit in the Data Entry sheet, copies the values (NOT the formulas) in B12:E12 to the first empty row (in this case, row 8) in the "Master Table" sheet. Ideally, clicking "Submit" will also clear the data entry fields in C4:C7 in the "Data Entry" sheet.
I have looked through various forums for a solution but have not found anything that does exactly that. I am sorry to say I am a complete newbie at Google Apps Script, therefore I could not write my own code to share, which I am aware is customary when asking a question here.
If anyone could point me in the right direction regardless, it would be much appreciated. I am currently trying to learn JavaScript and Google Apps Script using online resources, but for this specific project, it would take too long for me to reach a level where I could help myself.
Thank you very much, GEOWill!
Your answer solved my problem and thanks to your comments, I was able to understand exactly what your code does. I changed the code only to remove the Menu (but thank you very much for showing me how that is done anyway) - I tied the function to a Submit button inserted as a drawing. I also added some code to clear the contents of the entry range after clicking the button (this was suggested by someone else).
The final code that I used is:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var entry_sheet = ss.getSheetByName("Data Entry");
var master_sheet = ss.getSheetByName("Master Table");
function mySubmit() {
var entry_range = entry_sheet.getRange("B12:E12")
var val = entry_sheet.getRange("B12:E12").getDisplayValues().reduce(function (a, b) {
return a.concat(b);
});
Logger.log(val);
master_sheet.appendRow(val);
entry_sheet.getRange("C4:C7").clearContent()
}
I hope this helps others with a similar problem! Love how supportive this community is. Thanks for helping out.
I would begin by using a menu function to run your code in (rather than a cell button). You could use a cell button, but I believe you need to insert an image and assign a javascript function to that image anyways.
Basically, you begin by going to tools, script editor. Create an onOpen function and create a trigger that runs the onOpen() function each time the spreadsheet is opened. Inside the onOpen() function, we create a menu into which a physical menu item (a kind of button) exists (called 'Submit'). Finally, we associate a function to this button (I called it mySubmit()).
Inside of the mySubmit() function is where most of the functionality you are looking for exists. At this point, it is just a matter of copying from one range of cells and pasting them to another range of cells. For this, you'll notice that I had to setup a few variables ahead of time (ss, entry_sheet, master_sheet, entry_range, and master_row).
One last thing, you may want to protect the Master table sheet because if someone accidentally edits a cell beyond the last one edited, the input row would be copied to that row (due to how the getLastRow() function operates).
Hope this helps!
var ss = SpreadsheetApp.getActiveSpreadsheet();
var entry_sheet = ss.getSheetByName("Data Entry");
var master_sheet = ss.getSheetByName("Master Table");
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('MyMenu')
.addItem('Submit', 'mySubmit')
.addToUi();
}
function mySubmit() {
var entry_range = entry_sheet.getRange("B12:E12");
var master_row = (master_sheet.getLastRow() + 1);
entry_range.copyValuesToRange(master_sheet, 1, 3, master_row, master_row);
}

Create a new sheet in an existing spreadsheet for EACH RESPONSE from a Google Form

I have created a Google form, and I need to create a new sheet in an existing spreadsheet for each response I receive from this form - each respondent generates a new sheet within the spreadsheet. Is this possible with some kind of onSubmit command? I'm completely new to Javascript but willing to learn. Thanks so much for your help.
You can't intercept a Google Form submission before the data is written into the spreadsheet. All you can do is manipulate the data after it's already been inserted into the spreadsheet. So, your responses will get put into the spreadsheet, all in one sheet to start with. You can't change that.
Now the question is, do you want to manipulate the data from code bound to the form or bound to the sheet? You'll want to use a project bound to the sheet.
This is some sample code:
This code assumes that the value you want to name your sheet is in column A
function subTheForm() {
Logger.log('submit ran');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get last row of data
var lastRow = sheet.getLastRow();
var colA_Data = sheet.getRange(lastRow, 1).getValue();
//var thisUser = 'theUserName';
ss.insertSheet(colA_Data);
};
Old answer:
You'll need to generate some kind of unique string every time a new form is submitted. I have no idea what you want. You could get the user name, then add the date/time to it, then name each new sheet the user name with the time. The basic code will look like this:
function submit(){
Logger.log('submit ran');
var thisUser = 'theUserName';
var ss = SpreadsheetApp.getActive().insertSheet(thisUser);
};
Note the Logger.log(); statement. That prints something to the LOG. Inside the code editor, you can select the VIEW menu, and the LOGS menu item to show the LOG.
You can also run the code "manually" from the code editor by selecting the function name and clicking the run arrow icon. That way you can run the code without submitting a form every time. Get the code to work, then wire it up to the onsubmit trigger.
For this you can get the Spreadsheet using this command(getActiveSpreadsheet()) and then create a new sheet based on the parameters you require from this page. you can add this lines of code in your onSubmit trigger.
Hope that helps!

Google Spreadsheets with Form Vinculated copy

I'm trying to copy a spreadsheet with the responses of a form thought drive API.
https://developers.google.com/drive/v2/reference/files/copy
All files from my drive are working fine but only this spreadsheet that persist my form answers that create a duplicate form instead of only copying the spreadsheet itself.
You can try to reproduce the problem using the given Id. After copying you will notice that both spread sheet and form will be copied. This should not be a problem if I could erase the form but in the response of the copy procedure I don't get any advice about the form that is being copied together.
File id: 0Aqq-9JjR-lUydHRKVEJ2SThGMjJlVjVqczkyWlVCWUE
Please, help me. I'm desperate.
If you are only trying to copy the spreadsheet of the form, try this:
var fromSheet = ***whatever***;//this is the sheet attached to your form
var toSheet = ***whatever***;//this will be the sheet that you are copying to
var range = **whatever***;//this is the range you are copying over. If you are using dynamic ranges (ie varying number of rows), you may want to **getDataRange()** and **getLastRow** to build a more flexible range
function myCopyCat(){
myValues = fromSheet.getRange(range).getValues();//'copies' all of your data within range from fromSheet to an array
toSheet.getRange(range).setValues(myValues);//'pastes' all of your data into cells on toSheet
}

Google script FIlter issue

I am programming a help desk system using google script, forms and spreadsheet.
To filter the queries the submissions are placed into different sheets depending on category, this is done through the FILTER function. however every time a new submission is made the filter function does not update, (it uses the CONTINUE function to cover the other cells)
instead the cell with the FILTER function must be selected and crtl+shift+E must be entered
is there a way around this?
I have tried two methods
the first was looking to have a function to enter the shortcut, but is this possible?
the second is auto entering the continue function everytime a new submission is made, I have this working however google sheets does not recognise the named range, (the continue function has the set up CONTINUE(original cell, rows away, columns away) its the original cell that it does not identify, instead I must manually select the cell and re-write the exact same cell reference.
Thank you for your help, if you need to see my code please ask :)
This is the code for the second option where I try to enter the function manually to the cells.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var numEntry = ss.getSheetByName('Home').getRange("B8").getValue() + 2;
var cat = ss.getSheetByName('Software problem').getRange(numEntry, 4, 1, 9);
cat.getCell(1, 1).setValue('=CONTINUE(D2, '+(numEntry-1)+', 1)');
Your option 1: Have a script enter keystrokes automatically? Not supported in apps-script.
Your Option 2: It shouldn't be necessary to programmatically insert CONTINUE, as the required CONTINUEs for your FILTER should be automatic, when rows in your filter range match the expressed criteria. Something else is wrong, so don't get caught up with this red herring.
You mention "google sheets does not recognise the named range" - I'd like to know what you mean by that, because I suspect this is where your solution will be. You can use named ranges within FILTER statements. You can also use open-ended ranges, like FormInput!A1:X or FormInput!E1:E.
If you're trying to manipulate named ranges using scripts, then you may have run into a known issue, "removeNamedRange() only removes named ranges that were created via Apps Script". (To get around that, manually delete the named range, then create it only from script.)
Here's a function I use to create a named range for all data on a sheet. You could adapt this to your situation. (I use this with QUERY functions instead of FILTER, you might want to consider that as an alternative.)
function setNamedRangeFromSheet(sheetName) {
// Cannot remove a named range that was added via UI - http://code.google.com/p/google-apps-script-issues/issues/detail?id=1041
var ss = SpreadsheetApp.getActiveSpreadsheet();
try { ss.removeNamedRange(sheetName) } catch (error) {};
var sheet = ss.getSheetByName(sheetName);
var range = sheet.getDataRange();
ss.setNamedRange(sheetName,range);
}
Using FILTER, you need to match the length of your sourceArray (which can be a named range) and any criteria arrays you use. To programmatically create a named range for a single-column criteria within your sourceArray, and of the same length, use getNumRows() on the sourceArray range.
Now, within your submission handling function, triggered on form submit, you'd have something like this. (I assume your trouble reports are coming into a single sheet, "FormInput" - adjust as necessary.)
...
var ss = SpreadsheetApp.getActiveSpreadsheet();
try { ss.removeNamedRange("FormInput") } catch (error) {};
var sheet = ss.getSheetByName("FormInput");
var inputRange = sheet.getDataRange();
ss.setNamedRange("FormInput",inputRange);
try { ss.removeNamedRange("Criteria") } catch (error) {};
var criteriaCol = 4; // Another guess, that Column E contains our criteria
var criteriaRange = sheet.getRange(0,criteriaCol,inputRange.getNumRows(),1);
ss.setNamedRange("Criteria",criteriaRange);
...
And with that in place, the content of A1 on your "Software problem" sheet just needs to contain the following. (Assuming that you're looking for "Bug"s.):
=FILTER(FormInput,Criteria="Bug")
I mentioned open-ended ranges earlier. If you aren't doing enough manipulation of data to justify named ranges, you could set up your filter like this, and not have to change it as new input came in:
=FILTER(FormInput!A1:X,FormInput!E1:E="Bug")