Google Forms response in new sheet with notification - google-apps-script

I've created a order capture form that captures the
1. location (dropdown),
2. delivery date (date)
3. Products (small text)
I have then added a formula to generate a new order no. everytime a new response is added.
=arrayformula( if( len(A2:A), "Order " & text(row(A2:A) - row(A2) + 1, "022"), iferror(1/0) ) )
I need a new sheet to be created with the tab name with the new order no. and the columns transposed along with the response inputs against them.
For example response form
Column B | Column C | Column D |Column E |Column F
Order no. | Location | Delivery Date | Product 1 | Product 2
Order 122 | XYZ | 2/16/2017 | 35kg | 45kg
New sheet generated named "Order 122"
Order no. | Order 122
Location | XYZ
Delivery Date | 2/16/2017
Product 1 | 35kg
Product 2 | 45kg
and a notification to be sent to an email.
Is this possible with google spreadsheets, if so, please do let me know how it can be done. Thank you in advance.
I am using the following to create a new sheet named after the order no. but it doesnt seem to be working based on this article.
function subTheForm(){
Logger.log('submit ran');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var lastRow = sheet.getLastRow();
var colB_Data = sheet.getRange(lastRow, 2).getValue();
ss.insertSheet(colB_Data);
};
I get this error when I run the script
The sheet name cannot be empty. (line 9, file "Code")

Solved.
I used the following code similar as what I'd posted. For some reason I kept getting an error, cleared the responses, deleted and recreated the script and triggers and it worked.
function onSubmit(e){
Logger.log('submit ran');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get last row of data
var lastRow = sheet.getLastRow();
var colB_Data = sheet.getRange(lastRow, 2).getValue();
ss.insertSheet(colB_Data);
};

Related

Circular dependency error in Google Sheets

I have two formulas:
CELL W21:
=IF(AND(TODAY() >= DATE(2022,2,1), TODAY() <= DATE(2022,2,28)), SUM('Master Report'!$B$20:$B$24,'Master report'!$B$31:$B$32), W21)
CELL X21:
=IF(AND(TODAY() >= DATE(2022,3,1), TODAY() <= DATE(2022,3,31)), SUM('Master report'!$B$20:$B$24,'Master report'!$B$31:$B$32), X21)
The first formula works ok, while the second gives a circular dependency error. I want the value in X21 to be populated only between those dates but I want to set up the spreadsheet now for the entire year.
The values in "Master Report" gets updated automatically via API on 1st of every month and I am referencing those value in a table where each month is present. Example as follows:
Master Report (updated automatically every 1st of the month)
| Page | Visits |
| -------- | -------------- |
| Page 1| 20012|
This spreadsheet
| January 2022| March 2022| April 2022|
|:---- |:------:| -----:|
| Visits| Visits| Visits|
I managed to do this in Google App Script as suggested by #TheWizEd.
It's a very primitive script, but I hope it can help people with this problem in future:
function checkDateAndWrite(dateStart,dateEnd,cellFrom,cellTo) {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var reportSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Master Report')
var today = new Date();
var dateOne = new Date(dateStart);
var dateTwo = new Date(dateEnd);
if(today.valueOf() >= dateOne.valueOf() && today.valueOf() <= dateTwo.valueOf()) {
activeSheet.getRange(cellTo).setValue(reportSheet.getRange(cellFrom).getValue());
}
return;
}

How to ignore empty cells and change column order when copying data using Google Apps Script

I'm trying to write a script to paste rows of cells from one sheet to another while ignoring rows with blank cells in Column A. The script would also swap the order of Columns B and C. Here is what I am trying to do:
INPUT Sheet....................................OUTPUT Sheet
A1= ID B1= Last Name C1 = MI A1= ID B1 = MI C1= Last Name
A2= 1 B2= Stewart C2= M................A2= 1 B2= M C2= Stewart
A3= B3= Smith C3= R................A3= 4 B3= V C3= Holland
A4= 4 B4= Holland C4= V................A4= 3 B4= B C4= Young
A5= 3 B5= Young C5= B
Here is what I have:
function removeEmptyRows() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Input");
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Output");
var data = sheet.getRange("A2:D").getValues();
var newData = new Array();
for(i in data){
var row = data[i];
var empty = false;
for(i in data){
if(row[0] == ""){
empty = true;
}
}
if(!empty){
newData.push(row);
}
sheets.getRange(2, 1, newData.length, newData[0].length).setValues(newData);
};}
I have not been able to figure out how to incorporate changing the order of columns.
I was not able to apply previous posts to this problem, although this one came closest.
I would really appreciate any help you can provide. Thank you!

Finding next empty row after a particular "Header" row

I have just started trying out the script editor of the Google Sheets.
Here is what I am trying to do:
I have a few "headers" in Sheet A. I will name them Header A, B, and C.
1 | Header A
2 | text 1
3 | text 2
4 | (empty row)
5 | Header B
6 | text 1
7 | text 2
8 | (empty row)
9 | Header C
10 | text 1
11 | text 2
Sheet B
1 | text 1 | date | Header A
2 | text 2 | date | Header B
3 | text 3 | date | Header B
4 | text 4 | date | Header C
5 | text 5 | date | Header A
When I update my data on Sheet B, it will be automatically be updated on Sheet A based on my custom attributes in Sheet B. I need it to be able to update the data on Sheet B onto Sheet A's empty row after the specific Headers.
Currently I am stuck at getting the next empty row in Sheet A. I am able to get the row that my Headers are in but I couldn't find any help online finding the next empty row after each specific Headers.
I could not find any classes that is provided. All I can see is getLastRow which is not what I want. I wonder can this be done?
Below is my current code:
function getScheduleStatus(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var name = ss.getSheetByName("Production Schedule");
var rng = name.getDataRange();
var last_row = rng.getLastRow();
var data = rng.getValues();
var str_upcoming = "upcoming"
var rows = [];
for (var i=0; i < data.length; i++) {
if (data[i][0].toLowerCase() == str_upcoming) {
Logger.log("true");
rows.push(i);
}
}
var row = Number(rows)+Number(rng.getRow());
Logger.log(row);
}
Currently I am able to find the Header as well as getting the row number.
Hope you guys can understand.
Take a look at Faster way to find the first empty row; the answers there can be adapted to your situation.
The fastest solution there was Don Kirby's, and since you have a single column of data, it is ideal. We just need to change it to start searching from a particular headerRow!
/**
* Search column A starting at the given row, to find
* the first following empty row. Uses spreadsheet row numbers.
* From: https://stackoverflow.com/a/38194740/1677912
*
* #param {Number} headerRow Row number to start search at.
*
* #returns {Number} Target empty row.
*/
function getFirstEmptyRowAfter(headerRow) {
var spr = SpreadsheetApp.getActiveSpreadsheet();
var column = spr.getRange('A:A');
var values = column.getValues(); // get all data in one call
var ct = headerRow; // Start at row after headerRow (0-adjusted)
while ( values[ct][0] != "" ) {
ct++;
}
return (ct + 1); // (1-adjusted)
}

Copy row into new sheet(s) if two different cell values are within a defined range

I would like to create a Google Spreadsheets document that maintains:
Sheet 1 (All Entries): Unfiltered
Sheet 2 (1st Level Filter): Copies rows from Sheet 1 that Column B >/= 5000 OR Column C >/= 50000
Sheet 3 (2nd Level Filter): Copies rows from Sheet 1 that Column B >/= 5000 AND Column C >/= 50000
I created a sample doc for reference that's editable here.
Fairly limited programming/script experience.
In case you were looking for a script. This is what it'll look like although you'll have to do the mapping yourself. I haven't opened your doc but this will make it work if you need a script to do your bidding.
function sheetMaintain()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("Sheet1");
var s2 = ss.getSheetByName("Sheet2");
var s3 = ss.getSheetByName("Sheet3");
var r1 = s1.getDataRange();
var r2 = s2.getDataRange();
var r3 = s3.getDataRange();
var data1 = r1.getValues();
for (var i=0; i<r1.getLastRow(); i++)
{
if (data1[i][1]>=5000 || data[i][2]>=50000)
{
var colB = data[i][1];
var colC = data[i][2];
var lr2 = r2.getLastRow();
s2.getRange(lr2+1, 1).setValue(colB); //Mapping Col B value to Col A of Sheet 2
s2.getRange(lr2+1, 2).setValue(colC); //Mapping Col C value to Col B of Sheet 2
}
if (data1[i][1]>=5000 && data[i][2]>=50000)
{
var colB = data[i][1];
var colC = data[i][2];
var lr3 = r3.getLastRow();
s3.getRange(lr3+1, 1).setValue(colB); //Mapping Col B value to Col A of Sheet 3
s3.getRange(lr3+1, 2).setValue(colC); //Mapping Col C value to Col B of Sheet 3
}
}
}
if you'd like to not have any duplicates (from running the function time and again) in Sheet2 or Sheet3 I would also suggest you look into using the clear() function and set your Sheet2 and Sheet3 to clear before you parse through Sheet1 again.
I have added a formula to both sheets to achieve something like you may want
i.e. the first one below is the OR and the second is the AND
=filter('Sheet 1 - All Entries'!A:C,(('Sheet 1 - All Entries'!B:B>=5000) + ( 'Sheet 1 - All Entries'!C:C >=5000)))
=filter('Sheet 1 - All Entries'!A:C,(('Sheet 1 - All Entries'!B:B>=5000) * ( 'Sheet 1 - All Entries'!C:C >=5000)))
PS... I am not sure if a formula is sufficient for you or if you wanted this done through script

Search Google Spreadsheet for same value and append in next column in GAS

I've got a Google Spreadsheet which looks like this:
ID | winkelName | 26/05/2015 |
1 | Foo | |
2 | Bar | |
3 | Foo2 | |
4 | Bar2 | |
I'm trying to read and write an array of objects with the following structure:
history[i].storeName
history[i].checkIns
What I would like to do is to write all the number of checkins (with the same winkelName) on the same row under the column date (26/05/2015). But I'm still stuck what is the best way to achieve this?
This is my first attempt:
function writeHistory(history) {
var sheet = historySheet.getSheets()[0];
historySheet.setActiveSheet(sheet);
var nextRow = sheet.getLastRow(); // get next row
var rows = sheet.getDataRange().getValues();
var lastColumn = sheet.getLastColumn();
sheet.insertColumnAfter(lastColumn);
lastColumn++;
sheet.getRange(1, lastColumn).setValue(new Date());
var column = sheet.getLastColumn();
for(i in rows) {
if(i != 0) {
if(rows[i][1] == history[i].winkelName) {
sheet.getRange(i, column).setValue(history[i].checkIns); // this is not fully working
}
}
}
}
In a Google spreadsheet you can write a range of cells at once. To do so, create a multi dimensional array with one column and for each row another dimension and within each row a dimension for each cell you want to write.
Loop through your checkings, set the cell values in your array and write the values using sheet.getRange(1,column-index).setValue([your array]);
Also check: Google's best practices on dealing with range values