Automatically Delete rows in Google sheet script - google-apps-script

I'm trying to write a google script that will updates the sensor data google sheet.This part is ok.
And I try to add a function clearRange(), when the data updated to 100 rows and delete the first 100 rows and reupdate the data. Is there something that I'm missing here?
function doGet(e) {
Logger.log( JSON.stringify(e) );
var sheet_id = 'XXXXXXXXXXXXXXXXXXXXX'; // Spreadsheet ID
var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
var Curr_Date = new Date();
var result = 'Ok';
if (e.parameter == 'undefined') {
result = 'No Parameters';
}
else if(e.parameter != 'undefined'){
rowData[0] = Curr_Date; // Date in column A
var Curr_Time = Utilities.formatDate(Curr_Date, "GMT+8", 'HH:mm:ss');
rowData[1] = Curr_Time; // Time in column B
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'temperature':
rowData[2] = value; // Temperature in column C
result = 'Temperature Written on column C';
break;
case 'humidity':
rowData[3] = value; // Humidity in column D
result += ' ,Humidity Written on column D';
break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
else if (newRow==100)
{
clearRange();
}
return ContentService.createTextOutput(result);
}
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}
function clearRange() {
sheet.deleteRows(1,100);
}

Try this:
function doGet(e) {
var sheet_id = 'XXXXXXXXXXXXXXXXXXXXX'; // Spreadsheet ID
var sh = SpreadsheetApp.openById(sheet_id).getActiveSheet();
var newRow = sh.getLastRow() + 1;
var rowData = [];
var Curr_Date = new Date();
var result = 'Ok';
if (e.parameter == 'undefined') {
result = 'No Parameters';
}
else if (e.parameter != 'undefined') {
rowData[0] = Curr_Date; // Date in column A
var Curr_Time = Utilities.formatDate(Curr_Date, "GMT+8", 'HH:mm:ss');
rowData[1] = Curr_Time; // Time in column B
for (var param in e.parameter) {
var value = e.parameter[param].replace(/['"]+/g, '');
switch (param) {
case 'temperature':
rowData[2] = value; // Temperature in column C
result = 'Temperature Written on column C';
break;
case 'humidity':
rowData[3] = value; // Humidity in column D
result += ' ,Humidity Written on column D';
break;
default:
result = "unsupported parameter";
}
}
var newRange = sh.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
else if (newRow == 100) {
sh.deleteRows(1, 100);
}
return ContentService.createTextOutput(result);
}

Related

Exception: The number of rows in the data does not match the number of rows in the range. The data has 1 but the range has 8. Google Script

I am having troubles in
Exception: The number of rows in the data does not match the number of rows in the range. The data has 1 but the range has 8. Google Script
function myFunction() {
var s1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Staging');
var s2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var values1 = s1.getDataRange().getValues();
var values2 = s2.getDataRange().getValues();
var Avals = s2.getRange("A1:A").getValues();
var Alast = Avals.filter(String).length;
var resultArray = [];
for(var n=0; n < values1.length ; n++)
{
var keep = false;
var counter = 0;
for(var p=0; p < values2.length ; p++)
{
if( values1[n][1] == values2[p][1])
{
keep = true;
break ;
}
}
if(keep == false)
{
resultArray.push([values1[n]]);
//s2.appendRow( values1[n] );
s2.getRange(Alast + 1, 1, values1[n].length, values1[n].length).setValues([values1[n]]);
//s2.getRange(s2.getLastRow() + 1, 1, values1.length, values1[0].length).appendRow( values1[n] );
resultArray = [];
keep = false
}
}
}
I believe you are trying to keep appending a new row to the end of the data on "Final". You should revise you script as shown below. Use resultArray to collect all new rows and save it to spreadsheet once.
function myFunction() {
var s1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Staging');
var s2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var values1 = s1.getDataRange().getValues();
var values2 = s2.getDataRange().getValues();
// s2.getDataRange() will get up to the last row of data
var Alast = values2.length;
var resultArray = [];
for(var n=0; n < values1.length ; n++)
{
var keep = false;
var counter = 0;
for(var p=0; p < values2.length ; p++)
{
if( values1[n][1] == values2[p][1])
{
keep = true;
break ;
}
}
if(keep == false)
{
resultArray.push(values1[n]);
keep = false
}
}
if( resultArray.length > 0 ) {
s2.getRange(Alast+1,1,resultArray.length,resultArray[0].length).setValues(resultArray);
}
}

Insert timestamp when value paste/edits in whole row in google sheets, only insert to blank cell

I'm trying to insert a timestamp into a cell in the "timestamp" column with the same row index as the edited or pasted value in the "status" column, only insert a timestamp in to an empty cell in "timestamp" column, while skipping the cell that already has a value in the "timestamp" column.
I'd also like to convert the date to a number, such as yymmddHHmmss*1000 + seri number column "No." Exp: If the timestamp is 22:01:20 14:08:05 and the sequence number in column "No." is 678, then value I want to insert into column "ID" is 2201201408050678.
I need to use the column header as a reference in this code to ensure that the function works correctly when the column index changes.
Issue: When changing many rows, this code simply repeats the original function for each selected cell. It gets the job done, but not too quickly.
How can I improve code speed when a multi-row update occurs?
No.
Timestamp
ID
Status
20
24:01:22 15:01:30
2201241501300020
Approved
17
Process
16
24:01:22 15:59:10
2201241559100016
Approved
16
function neworder2_onEdit(e) {
var sheet = e.range.getSheet();
if ((sheet.getSheetName() == 'RETAIL_ORDER') || (sheet.getSheetName() == 'HAMPER_ORDER') || (sheet.getSheetName() == 'SEA FOOD_ORDER') || (sheet.getSheetName() == 'GARDEN_ORDER'))
{
var col = e.range.columnStart;
var col_header = sheet.getRange(1,col).getValue();
if (col_header != 'Status') return;
var headers = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0];
var timestamp_col = headers.indexOf('Timestamp') + 1;
var num_col = headers.indexOf('No.') + 1;
var id_col = headers.indexOf('ID') + 1;
var row_start = e.range.rowStart;
var row_end = e.range.rowEnd;
if (sheet.getRange(row_start,col).getValue() != 'Approved') return;
var tz = SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone();
var timestamp = Utilities.formatDate(new Date(), tz, 'yy-MM-dd HH:mm:ss');
for (let row = row_start; row <= row_end; row++) {
var timestamp_cell = sheet.getRange(row, timestamp_col);
if (timestamp_cell.getValue() !== '') continue;
timestamp_cell.setValue(timestamp).setNumberFormat('yy:MM:dd HH:mm:ss');
var num = sheet.getRange(row,num_col).getValue().toString().padStart(4,'0');
var id = timestamp.replace(/\D/g,'') + num;
var id_cell = sheet.getRange(row,id_col);
id_cell.setValue(id);
}
}
}
I believe your goal is as follows.
Your script works fine. You want to reduce the process cost of the script.
In this case, how about the following modification?
Modified script:
function neworder2_onEdit(e) {
var sheet = e.range.getSheet();
if (['RETAIL_ORDER', 'HAMPER_ORDER', 'SEA FOOD_ORDER', 'GARDEN_ORDER'].includes(sheet.getSheetName())) { // Modified
var col = e.range.columnStart;
var col_header = sheet.getRange(1, col).getValue();
if (col_header != 'Status') return;
var row_start = e.range.rowStart;
var row_end = e.range.rowEnd;
// I modified below script.
var values = sheet.getRange(row_start, 1, row_end - row_start + 1, 4).getValues();
if (!values.some(r => r[3] == 'Approved')) return;
var tz = e.source.getSpreadsheetTimeZone();
var timestamp = Utilities.formatDate(new Date(), tz, 'yy-MM-dd HH:mm:ss');
var res = values.map(([a, b, c]) => (a == "" || b != "") ? [b, c] : [timestamp, timestamp.replace(/\D/g, '') + a.toString().padStart(4, '0')]);
sheet.getRange(row_start, 2, row_end - row_start + 1, 2).setValues(res);
sheet.getRange(row_start, 2, row_end - row_start + 1, 1).setNumberFormat('yy:MM:dd HH:mm:ss');
}
}
In this modification, after the array was created using the script in your for loop, the array was put to the sheet.
Reference:
map()
Added 1:
From your following replying,
When "status", "ID" or "timstamp" column index change, in case I want to insert column then our code not working. Can we use column header (status, timestamp, ID, No.) as pramameter for my cript? Can you give suggestion to do this?
In this case, how about the following sample script?
Sample script:
function onEdit(e) {
var sheet = e.range.getSheet();
if (['RETAIL_ORDER', 'HAMPER_ORDER', 'SEA FOOD_ORDER', 'GARDEN_ORDER'].includes(sheet.getSheetName())) { // Modified
var col = e.range.columnStart;
var header = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].map(h => h.toLowerCase()); // Added
var obj = header.reduce((o, e, i) => (o[e] = i, o), {});
var col_header = header[col - 1]; // Modified
if (col_header != 'status') return;
var row_start = e.range.rowStart;
var row_end = e.range.rowEnd;
// I modified below script.
var values = sheet.getRange(row_start, 1, row_end - row_start + 1, header.length).getValues();
if (!values.some(r => r[obj["status"]] == 'Approved')) return;
var tz = e.source.getSpreadsheetTimeZone();
var timestamp = Utilities.formatDate(new Date(), tz, 'yy-MM-dd HH:mm:ss');
var res = values.map(r => {
if (!(r[obj["no."]] == "" || r[obj["timestamp"]] != "")) {
r[obj["timestamp"]] = timestamp;
r[obj["id"]] = timestamp.replace(/\D/g, '') + r[obj["no."]].toString().padStart(4, '0');
}
return r;
});
sheet.getRange(row_start, 1, row_end - row_start + 1, res[0].length).setValues(res);
sheet.getRange(row_start, [obj["timestamp"]] + 1, row_end - row_start + 1).setNumberFormat('yy:MM:dd HH:mm:ss');
}
}
In this script, from your question, it supposes that the header values are No.,Timestamp,ID,Status. Please be careful this.
Added 2:
From your following new issue,
It's working but there is some issue with my sheet. when scipt ran that paste value to all column, some of theme using arrayformula so all column use arrayformula will get error "#REF!" Can we just paste value to column timestame, id.
In this case, how about the following sample script?
Sample script:
function onEdit(e) {
var sheet = e.range.getSheet();
if (['RETAIL_ORDER', 'HAMPER_ORDER', 'SEA FOOD_ORDER', 'GARDEN_ORDER'].includes(sheet.getSheetName())) { // Modified
var col = e.range.columnStart;
var header = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].map(h => h.toLowerCase()); // Added
var obj = header.reduce((o, e, i) => (o[e] = i, o), {});
var col_header = header[col - 1]; // Modified
if (col_header != 'status') return;
var row_start = e.range.rowStart;
var row_end = e.range.rowEnd;
// I modified below script.
var values = sheet.getRange(row_start, 1, row_end - row_start + 1, header.length).getValues();
if (!values.some(r => r[obj["status"]] == 'Approved')) return;
var tz = e.source.getSpreadsheetTimeZone();
var timestamp = Utilities.formatDate(new Date(), tz, 'yy-MM-dd HH:mm:ss');
var res = values.map(r => {
if (r[obj["no."]] != "" && r[obj["timestamp"]] == "" && r[obj["status"]] == "Approved") {
r[obj["timestamp"]] = timestamp;
r[obj["id"]] = timestamp.replace(/\D/g, '') + r[obj["no."]].toString().padStart(4, '0');
}
r.shift();
return r;
});
sheet.getRange(row_start, 2, row_end - row_start + 1, res[0].length).setValues(res);
sheet.getRange(row_start, [obj["timestamp"]] + 2, row_end - row_start + 1).setNumberFormat('yy:MM:dd HH:mm:ss');
}
}

Want to add Email sent function incase my temps are more than 8 appsscript

I have a code that I use to log temperatures into Google sheets..Code written in Appsscript. In this code, i want to add a function in the case 'temperature' that can send mail in case the incoming temperature to be logged is more than 8.. How can I do that? Someone help in that kind of code?
function doGet(e) {
Logger.log( JSON.stringify(e) );
var result = 'Ok';
if (e.parameter == 'undefined') {
result = 'No Parameters';
}
else {
var sheet_id = '1hKXZEIx160TwXi5yUztGBDijNaGgAOjKWSmY-Mowo9M'; // Spreadsheet ID
//var sheetActive = SpreadsheetApp.openById("ID");
//var sheet = sheetActive.getSheetByName("Name");
var sheetActive = SpreadsheetApp.openById(sheet_id);
var sheet = sheetActive.getSheetByName("Theatre");
//var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet().getSheetByName("Sheet3");
var newRow = sheet.getLastRow() + 1;
var rowData = [];
var Curr_Date = new Date();
rowData[0] = Curr_Date; // Date in column A
var Curr_Time = Utilities.formatDate(Curr_Date, "Africa/Nairobi", 'HH:mm:ss');
rowData[1] = Curr_Time; // Time in column B
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'temperature':
rowData[2] = value; // Temperature in column C
result = 'Temperature Written on column C';
// if(){
// }
break;
// case 'humidity':
// rowData[3] = value; // Humidity in column D
// result += ' ,Humidity Written on column D';
// break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
return ContentService.createTextOutput(result);
}
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}
Email Sent if value greater than 8
function doGet(e) {
Logger.log( JSON.stringify(e) );
var result = 'Ok';
if (e.parameter == 'undefined') {
result = 'No Parameters';
}
else {
var sheet_id = '1hKXZEIx160TwXi5yUztGBDijNaGgAOjKWSmY-Mowo9M'; // Spreadsheet ID
//var sheetActive = SpreadsheetApp.openById("ID");
//var sheet = sheetActive.getSheetByName("Name");
var sheetActive = SpreadsheetApp.openById(sheet_id);
var sheet = sheetActive.getSheetByName("Theatre");
//var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet().getSheetByName("Sheet3");
var newRow = sheet.getLastRow() + 1;
var rowData = [];
var Curr_Date = new Date();
rowData[0] = Curr_Date; // Date in column A
var Curr_Time = Utilities.formatDate(Curr_Date, "Africa/Nairobi", 'HH:mm:ss');
rowData[1] = Curr_Time; // Time in column B
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'temperature':
Logger.log(
rowData[2] = value; // Temperature in column C
result = 'Temperature Written on column C';
Logger.log(`Date: ${new Date()} Value:${value}`);//Please add this
if(parseInt(value) > 8){
GmailApp.sendEmail('recipient emal','Subject',"message");
}
break;
// case 'humidity':
// rowData[3] = value; // Humidity in column D
// result += ' ,Humidity Written on column D';
// break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
return ContentService.createTextOutput(result);
}
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}
GmailApp.sendEmail()

JDBC Connection from MySQL database to Spreadsheet very slow

I have created this script to push the data from my MySQL database to google spreadsheet.
Now, to be updated, I have created a trigger every 5 minutes to run the script, but strangely when I see the executions of the trigger, it run approximately every 40 minutes.
The run of the script is approximately 2 minutes and so after this it push the data in the spreadsheet.
Is there something wrong with the script?
And how can I enforce the update duration that I have established in the trigger?
var MAXROWS = 100000
var SEEKWELL_J_SHORT_DATES = { day: "yyyy-MM-dd", month: "yyyy-MM", year: "yyyy", dayNum: "dd", monthNum: "MM", yearNum: "yyyy", week: "W" }
var SEEKWELL_J_TIMEZONE = "UTC"
var HOST = 'xxx'
var PORT = 'xxx'
var USERNAME = 'xxx'
var PASSWORD = 'xxx'
var DATABASE = 'xxx'
var DB_TYPE = 'mysql'
function runSql(query, options) {
var doc = SpreadsheetApp.getActiveSpreadsheet();
//var sheet = doc.getActiveSheet();
var sheet = doc.getSheets()[0];
var sheetName = sheet.getName();
//var cell = doc.getActiveSheet().getActiveCell();
var cell = sheet.getRange('a1');
var activeCellRow = cell.getRow();
var activeCellCol = cell.getColumn();
try {
var fullConnectionString = 'jdbc:' + DB_TYPE + '://' + HOST + ':' + PORT
var conn = Jdbc.getConnection(fullConnectionString, USERNAME, PASSWORD);
console.log('query :', query)
var stmt = conn.createStatement();
stmt.execute('USE ' + DATABASE);
var start = new Date();
var stmt = conn.createStatement();
stmt.setMaxRows(MAXROWS);
var rs = stmt.executeQuery(query);
} catch (e) {
console.log(e, e.lineNumber);
Browser.msgBox(e);
return false
}
var results = [];
cols = rs.getMetaData();
console.log("cols", cols)
var colNames = [];
var colTypes = {};
for (i = 1; i <= cols.getColumnCount(); i++) {
var colName = cols.getColumnLabel(i)
colTypes[colName] = { type: cols.getColumnTypeName(i), loc: i }
colNames.push(colName);
}
var rowCount = 1;
results.push(colNames);
while (rs.next()) {
curRow = rs.getMetaData();
rowData = [];
for (i = 1; i <= curRow.getColumnCount(); i++) {
rowData.push(rs.getString(i));
}
results.push(rowData);
rowCount++;
}
rs.close();
stmt.close();
conn.close();
console.log('results', results)
var colCount = results[0].length
var rowCount = results.length
var comment = "Updated on: " + (new Date()) + "\n" + "Query:\n" + query
if (options.omitColumnNames) {
results = results.slice(1)
rowCount -= 1
}
if (options.clearColumns && sheet.getLastRow() > 0) {
var startCellRange = sheet.getRange(startCell)
sheet.getRange(startCellRange.getRow(), startCellRange.getColumn(), sheet.getLastRow(), colCount).clearContent();
}
if (options.clearSheet) {
var startCellRange = sheet.getRange(startCell)
sheet.clear({ contentsOnly: true });
}
//sheet.getRange(activeCellRow, activeCellCol, rowCount, colCount).clearContent();
sheet.getRange(activeCellRow, activeCellCol, rowCount, colCount).setValues(results);
var cell = sheet.getRange(activeCellRow, activeCellCol)
cell.clearNote()
cell.setNote(comment);
sheet.setActiveRange(sheet.getRange(activeCellRow + rowCount + 1, activeCellCol))
console.log('query success!, rows = ', rowCount - 1)
}
function runSqlFromSheet() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sql = doc.getRange('query!A1').getDisplayValue();
var options = {}
Logger.log('sql;', sql)
runSql(sql, options)
}

Copying or updating the row based on the occurrence of a row cell value

I'm trying to add a given row or update an existing row to a Google Sheet based on a specific value in the row data. My row data is represented as an array object, like this: [id, number, date, type, url, count].
What I expect is that, if there exists a row with a matching number, I increment the count by 1 in the same range in the Google Sheet, else I add a new row with my row data.
Here's what I've tried so far, but it works only for count=2 and not beyond that.
function copyRowBasedOnNumber(sheetId, sheetName, rowData) {
var sheet = SpreadsheetApp.openById(sheetId);
var sheetname = sheet.getSheetByName(sheetName);
var count = 0;
var matchingRow = sheetname.getLastRow();
var values = sheetname.getDataRange().getValues();
for (var row in values) {
for (var col in values[row]) {
if (values[row][col] == rowData[1]) { // rowData[1] corresponds to the number
matchingRow = row;
count++;
break;
}
}
}
if(count == 0) {
var lastRowNum = sheetname.getLastRow();
sheet.insertRowAfter(lastRowNum);
rowData[5] = 1;
sheetname.getRange(lastRowNum + 1, 1, 1, rowData.length).setValues([rowData]);
} else {
sheetname.getRange(parseInt(matchingRow) + 1, 6).setValue(count + 1);
}
return count + 1;
}
I've figured it out. In case this helps someone in future, here's the code. Here, count is the value I want to check before I add a new entry or update an existing entry.
function copyRowToSheetWithoutDuplicate(sheetId, tabName, rowData) {
var sheet = SpreadsheetApp.openById(sheetId);
var sheetname = sheet.getSheetByName(tabName);
var count = 0;
var existingCount = 0;
var existingEntryRow = 0;
var allValues = sheetname.getDataRange().getValues();
var numColumns = sheetname.getLastColumn();
var numRows = sheetname.getLastRow();
for(var i=0;i<numRows;i++) {
var dateFromRowData = rowData[3].substring(0,10);
var todayDate = Utilities.formatDate(new Date(), "GMT+05:30", "''yyyy-MM-dd");
if(allValues[i][1]==rowData[1] && dateFromRowData!=todayDate) {
count++;
existingCount = allValues[i][6];
existingEntryRow = i + 1;
break;
}
}
if(count == 0) {
// insert a row and make an entry
sheetname.insertRowAfter(numRows);
rowData.push(1); // count
sheetname.getRange(numRows + 1, 1, 1, rowData.length).setValues([rowData]);
return 1;
} else {
// update the existing count by incrementing it by 1
existingCount++;
rowData.push(existingCount); // count
sheetname.getRange(existingEntryRow, 1, 1, rowData.length).setValues([rowData]);
return existingCount;
}
}