I've just started using Google Apps script to manage some sheets for a project i'm working on, I am new to Javascript so please go easy if there are any howlers in my code!.
We have and app called forms2mobile that captures data and drops it into a Google spreadsheet. It actually drops different data into different sheets depending on which part of the app you use.
I've hacked together a script that pulls all data from one sheet (source), and drops only certain columns into a second sheet (destination). It then deletes all rows from the source, and any blank rows from the destination.
The problem I have is with deleting blank rows from the destination. Typically the destination will have empty rows at the bottom, and the code I have will only delete empty rows within the range that contains data. So i'm always left with empty rows at the bottom.
The destination sheet will then be used as a data source for forms2mobile, which of course isn't happy with empty rows.
I've found the class getMaxRows() but i'm not sure how to implement it. If anyone could make any suggestions that would be great.
Cheers
Paul
function NEW_copyColumnNumbers( ) {
var spreadsheet_source = SpreadsheetApp.openById('1a89ZIUcy-8168D1damCV3Q9Ix0arQn9jGS6pgp');
var spreadsheet_target = SpreadsheetApp.openById('1GQiLt9utSH_6CV__oJwmcLOkI4E9iNIRPWU7Xr');
var range_input = spreadsheet_source.getRange("A2:CC407");
var range_output = spreadsheet_target.getRange("A"+(spreadsheet_target.getLastRow()+1));
var keep_columns = [66,66,10,11,12,13,14,23,26,31,69,71,74,75,80];
copyColumnNumbers(range_input, range_output, keep_columns);
clearEmptyRows();
clearSourceData();
}
function copyColumnNumbers( range_input, range_output, columns_keep_num ) {
// Create an array of arrays containing the values in the input range.
var range_values = range_input.getValues();
// Loop through each inner array.
for ( var i = 0, row_count = range_values.length; i < row_count; i++ ) {
// Loop through the indices to keep and use these indices to
// select values from the inner array.
for ( j = 0, col_keep_count = columns_keep_num.length; j < col_keep_count; j++ ) {
// Capture the value to keep
var keep_val = range_values[i][columns_keep_num[j]];
// Write the value to the output using the offset method of the output range argument.
range_output.offset(i,j).setValue(keep_val);
}
}
}
function clearEmptyRows() {
var ss = SpreadsheetApp.openById('1GQiLt9utSH_6CV__oJwmcLOkI4E9iNIRPWU7Xr');
var s = ss.getActiveSheet();
var values = s.getDataRange().getValues();
nextLine: for( var i = values.length-1; i >=0; i-- ) {
for( var j = 0; j < values[i].length; j++ )
if( values[i][j] != "" )
continue nextLine;
s.deleteRow(i+1);
}
//I iterate it backwards on purpose, so I do not have to calculate the indexes after a removal
}
function clearSourceData() {
var ss = SpreadsheetApp.openById('1a89ZIUcy-8168D1damCV3Q9Ix0arQn9jGS6pgp');
var s = ss.getActiveSheet();
var data = s.getDataRange().getValues();
for(var n =data.length+1 ; n<0 ; n--){
if(data[n][0]!=''){n++;break}
}
s.deleteRows(2, (s.getLastRow()-1));
}
This is how it works :
function removeEmptyRows(){
var sh = SpreadsheetApp.getActiveSheet();
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
Note : you can handle columns the same way if necessary using getMaxColumn(), getLastColumn() and deleteColumns(number, howMany)
EDIT
by the way, here is also another way to delete empty rows in a spreadsheet... if you combine both it will "clean" your sheet entirely !
function deleteEmptyRows(){
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues();
var targetData = new Array();
for(n=0;n<data.length;++n){
if(data[n].join().replace(/,/g,'')!=''){ targetData.push(data[n])};
Logger.log(data[n].join().replace(/,/g,''))
}
sh.getDataRange().clear();
sh.getRange(1,1,targetData.length,targetData[0].length).setValues(targetData);
}
Demo sheet in view only - make a copy to use
Script to removeEmptyRows and removeEmptyColumns in Google Sheets. It puts together everything Serge and apptailor mentioned previously. Here is a sample sheet with the script included File > Make a copy... to edit a copy of the sheet. Also a video that shows you how to use this sheet.
//Remove All Empty Columns in the Entire Workbook
function removeEmptyColumns() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var maxColumns = sheet.getMaxColumns();
var lastColumn = sheet.getLastColumn();
if (maxColumns-lastColumn != 0){
sheet.deleteColumns(lastColumn+1, maxColumns-lastColumn);
}
}
}
//Remove All Empty Rows in the Entire Workbook
function removeEmptyRows() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var maxRows = sheet.getMaxRows();
var lastRow = sheet.getLastRow();
if (maxRows-lastRow != 0){
sheet.deleteRows(lastRow+1, maxRows-lastRow);
}
}
}
Just a quick note, I added this "if" statement to keep Serge insas's code from throwing an error if there is no empty bottom row when you are trying to remove empty rows.
Place this if around the last line function removeEmptyRows() and it
will not throw an error:
if (maxRows-lastRow != 0){
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
Removing all empty lines (bottom-up)
before
after
function isEmptyRow(row){
for (var columnIndex = 0; columnIndex < row.length; columnIndex++){
var cell = row[columnIndex];
if (cell){
return false;
}
}
return true;
}
function removeEmptyLines(sheet){
var lastRowIndex = sheet.getLastRow();
var lastColumnIndex = sheet.getLastColumn();
var maxRowIndex = sheet.getMaxRows();
var range = sheet.getRange(1, 1, lastRowIndex, lastColumnIndex);
var data = range.getValues();
sheet.deleteRows(lastRowIndex+1, maxRowIndex-lastRowIndex);
for (var rowIndex = data.length - 1; rowIndex >= 0; rowIndex--){
var row = data[rowIndex];
if (isEmptyRow(row)){
sheet.deleteRow(rowIndex + 1);
}
}
}
function removeEmptyLinesFromAllSheets(){
SpreadsheetApp.getActive().getSheets().forEach(removeEmptyLines);
}
Removing only empty lines from below and above the data
before
after
function isEmptyRow(row){
for (var columnIndex = 0; columnIndex < row.length; columnIndex++){
var cell = row[columnIndex];
if (cell){
return false;
}
}
return true;
}
function getFirstNonBlankRowIndex(data){
for (var rowIndex = 0; rowIndex < data.length; rowIndex++){
var row = data[rowIndex];
if (!isEmptyRow(row)){
return rowIndex;
}
}
return 0;
}
function removePaddedEmptyLines(sheet){
var lastRowIndex = sheet.getLastRow();
var lastColumnIndex = sheet.getLastColumn();
var maxRowIndex = sheet.getMaxRows();
var range = sheet.getRange(1, 1, lastRowIndex, lastColumnIndex);
var data = range.getValues();
var firstRowIndex = getFirstNonBlankRowIndex(data);
sheet.deleteRows(lastRowIndex+1, maxRowIndex-lastRowIndex);
sheet.deleteRows(1, firstRowIndex);
}
function removePaddedEmptyLinesFromAllSheets(){
SpreadsheetApp.getActive().getSheets().forEach(removePaddedEmptyLines);
}
I have tried this piece of code and it works good, you may take a look and try it:
function DeleteBlankRows(){
var sh = SpreadsheetApp.getActiveSheet();
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
for (var Raw = 1; Raw < sh.getLastRow() ; Raw++)
{
if( sh.getRange('A'+Raw).getValue() == '')
{
sh.deleteRow(Raw) //deleteRows(lastRow+1, maxRows-lastRow);
}
}
This works perfectly for me.
function removeEmptyRows(){
var spreadsheet = SpreadsheetApp.openById("IDOFYOURSPREADSHEETFOUNDINURL");
var sh = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
This version allows you to specify top rows you don't want removed and also to ignore columns after ignoreAfterCol in case you don't want some columns considered when you are looking for blanks:
function removeEmptyLines(sheet,ignoreFirstRows,ignoreAfterCol){
sheet=ss.getSheetByName('Sheet12')
//get data and boundaries
var allData = sheet.getRange(1,1,sheet.getMaxRows(),ignoreAfterCol).getValues();
var sheetLength = allData.length;
while(allData[allData.length-1].toString().replace(/,/g,'')=='') allData.pop();
var lastPopulatedRow = allData.length;
//delete empty rows from end
var rowsToDeleteFromEnd = sheetLength - lastPopulatedRow;
if(rowsToDeleteFromEnd > 0) sheet.deleteRows(lastPopulatedRow+1,rowsToDeleteFromEnd);
//iterate through rows and delete blanks one by one
for(var i=lastPopulatedRow-1; i>ignoreFirstRows; i--){
if(allData[i].toString().replace(/,/g,'')=='') sheet.deleteRow(i+1);
}
}
this will help to delete exactly what you want:
Plus point:
you can check as many columns as you want to identify if a row is empty
this will also delete blank rows that contain formula
improve performance: this script deletes directly the empty rows according to their position without iteration through all the rows.
function deleteBlankRows(start_row=4) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//temporarily insert last column to avoid affecting existing data
sheet.insertColumnsAfter(sheet.getMaxColumns(),1);
var lastRow = findLastRow();
var lastCol = sheet.getMaxColumns()
var temp_col = sheet.getRange(start_row,lastCol,lastRow-start_row,1)
//insert formula to show row position if any row is blank from column A to N (can adjust if needed)
sheet.getRange(start_row,lastCol).setFormula('=if(countif(A'+start_row+':N'+start_row+',"*?")=0,row(),0)').copyTo(temp_col)
//get a reversed list of rows position excluded non-empty rows
var rowsPosition = temp_col.getValues().filter(x => x != 0).reverse()
//delete empty rows from bottom to top
rowsPosition.forEach(function(rowPosition){
if (Number(rowPosition) > start_row) {
sheet.deleteRow(Number(rowPosition))
}
})
//finally, delete the temporary column
sheet.deleteColumn(lastCol)
}
function findLastRow() {
const sh = SpreadsheetApp.getActive().getActiveSheet();
const data = sh.getRange("A:L").getValues();
const mR = sh.getMaxRows();
const indexes = [];
data[0].forEach((_, ci) => {
let col = data.map(d => d[ci]);
let first_index = col.reverse().findIndex(r => r != '');
if (first_index != -1) {
let max_row = mR - first_index;
indexes.push(max_row);
}
});
last_row = indexes.length > 0 ? Math.max(...indexes) : 0;
return last_row;
}
function deleteblankRw(){
var sheet=SpreadsheetApp.getActive().getSheetByName('test')
var e=sheet.getRange('A'+sheet.getMaxRows()).getNextDataCell(SpreadsheetApp.Direction.UP).getRow()
for (k=2;k<=e;k++) {
if(sheet.getRange('A'+k).getValue()=='') {
sheet.deleteRow(k);
k=2;e--
if(k==e){break};
SpreadsheetApp.flush();
}
}
}
Related
Getting an TypeError: Cannot read property '0' of undefined (line 35)
I am trying to find a cell value in google sheets and then return the cell value into another cell.
I dont get why I am getting a TypeError and I have tried all forms of toString methods or what not.
Please help
function hiearchyRoleGenerator() {
Logger.log("Setting spreasheets up")
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var generatorSheet = sheets[0];
var primeSheet = sheets[1];
var ecsSheet = sheets[2];
var cloudSalesSheet = sheets[3];
var salesDevSheet = sheets[4];
Logger.log("Setting cells up")
var businessUnit = generatorSheet.getRange("A2").getValue();
var startPoint = generatorSheet.getRange("B2").getValue();
var endPoint = generatorSheet.getRange("C2").getValue();
var separator = generatorSheet.getRange("D2");
var concat = generatorSheet.getRange("E2");
var target = startPoint.toString();
Logger.log(target)
//Logger.log("Finding Start Point")
//Logger.log(startPointResult)
//Logger.log(String(startPointResult))
if (businessUnit == "Prime") {
var lastRow = primeSheet.getLastRow();
var data = primeSheet.getRange(1,1,lastRow,7).getValues();
var dataResult = []
var i,j;
for (var i = 0; i <= lastRow ;i++) {
//Logger.log(values[i][0])
for (var j = 0; j<7; j++){
//Logger.log(values[i][j])
if(data[i][j] == startPoint){ //[i] row [j] column ERROR IS HERE
dataResult.push(data[[i][j]]);
}
}
}
concat.setValue(dataResult);
}
}
Can you try something like this?
var range = sheet.getRange(1,1,lastRow,7);
var values = range.getValues();
for (var row in values) {
for (var col in values[row]) {
if(values[row][column] == startPoint){ //[i] row [j] column ERROR IS HERE
dataResult.push(values[row][column]);
}
}
Also row and Column are relative to range so may be using var i,j starting with 0 might be an issue. you might have to use 1 instead
I want to remove duplicates across 2 different sheets.
I have my active sheet, and I want to remove duplicates that already exist in my sheet "Blacklist". I want to run this process for both Column A and Column B (or simply for any values across the entire sheets). When a duplicate is found, I want to leave the row in tact but replace the value with '' (e.g. an empty cell).
I have a working version I mangled together, but only for the active sheet.
N.B. it's the findDuplicate function that I use, the removeDuplicate function I left there not to mess anything up :)
// this is a Google Apps Script project
function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{ name: 'Find duplicates...', functionName: 'findDuplicate' },
{ name: 'Remove duplicates...', functionName: 'removeDuplicate' }
];
spreadsheet.addMenu('Duplicates', menuItems);
}
function removeDuplicate() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveRange();
var data = range.getValues();
var rowNum = range.getRow();
var columnNum = range.getColumn();
var columnLength = data[0].length;
var uniqueData = [];
var duplicateData = [];
// iterate through each 'row' of the selected range
// x is
// y is
var x = 0;
var y = data.length;
// when row is
while (x < y) {
var row = data[x];
var duplicate = false;
// iterate through the uniqueData array to see if 'row' already exists
for (var j = 0; j < uniqueData.length; j++) {
if (row.join() == uniqueData[j].join()) {
// if there is a duplicate, delete the 'row' from the sheet and add it to the duplicateData array
duplicate = true;
var duplicateRange = sheet.getRange(
rowNum + x,
columnNum,
1,
columnLength
);
duplicateRange.deleteCells(SpreadsheetApp.Dimension.ROWS);
duplicateData.push(row);
// rows shift up by one when duplicate is deleted
// in effect, it skips a line
// so we need to decrement x to stay in the same line
x--;
y--;
range = sheet.getActiveRange();
data = range.getValues();
// return;
}
}
// if there are no duplicates, add 'row' to the uniqueData array
if (!duplicate) {
uniqueData.push(row);
}
x++;
}
}
function findDuplicate() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveRange();
var data = range.getValues();
var rowNum = range.getRow();
var columnNum = range.getColumn();
var columnLength = data[0].length;
var uniqueData = [];
// iterate through each 'row' of the selected range
for (var i = 0; i < data.length; i++) {
var row = data[i];
var duplicate = false;
// iterate through the uniqueData array to see if 'row' already exists
for (var j = 0; j < uniqueData.length; j++) {
if (row.join() == uniqueData[j].join()) {
// if there is a duplicate, highlight the 'row' from the sheet
duplicate = true;
var duplicateRange = sheet.getRange(
rowNum + i,
columnNum,
1,
columnLength
);
duplicateRange.setValue('');
}
}
// if there are no duplicates, add 'row' to the uniqueData array
if (!duplicate) {
uniqueData.push(row);
}
}
}
Thanks so much for your help! I've been at this for a few hours and figured I should just ask the experts for advice :)
The first lines of both your removeDuplicate and findDuplicate function seems indeed to indicate that you refer to the active spreadsheet / sheet / range
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveRange();
var data = range.getValues();
If you want to be able to use the same function for a given spreadsheet / sheet / range which is not the active one, you will need to use other functions than the getActiveXXX().
For example, to get the sheet named "Blacklist", you should use
sheet = spreadsheet.getSheetByName("Blacklist")
(see also https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getsheetbynamename)
If you want to access a specific range which differs from the active range, you should use the getRange method (see also https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getrangea1notation)
Note that getRange method can be used in different ways, e.g.
getRange("A1:D4"), getRange(1, 1, 3, 3) (the parameters being respectively startRow, startColumn, numRows,numColumns)
Additionally, if you don't want to hardcode the last line of your 2 columns, you will most probably need this function to find the last line in the code :
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getlastrow
(there is also an example there showing how to use getRange() in combination with getLastRow()).
I hope this will help you going further.
Please note that I didn't check the rest of your code and just assumed that your deduplication logic works fine as you mentioned it in your commment.
Good luck !
I have the script mostly working- except the data being pushed actually says "Range" I must be missing something- can you not set values across a range?
function up4Grabs() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var destsheet = SpreadsheetApp.openById("MYID GOES HERE").getSheetByName('Items');
var destLastRow = destsheet.getLastRow();
var destRange = destsheet.getRange(1,9,destLastRow);
var dataLastRow = sheet1.getLastRow();
var dataRange = sheet1.getRange(1,9,dataLastRow);
var data = dataRange.getValues();
for(var i = 0; i < data.length; i++) {
if (data[i] > 0) {
var targetLastRow = destsheet.getLastRow() + 1;
var test = destsheet.getRange(1,9,targetLastRow);
sheet1.getvalues(test).setValues(sheet1.getRange(i+1,1,1,9))
}
}
}
Problem:
setValue() setting "Range" rather than actual values.
Cause:
You're passing a range rather than a value to the setValue() in the first place.
Solution:
function up4Grabs() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var destsheet = SpreadsheetApp.openById("MY ID GOES HERE").getSheetByName('Items');
var destLastRow = destsheet.getLastRow();
var destRange = destsheet.getRange(1,9,destLastRow);
var dataLastRow = sheet1.getLastRow();
var dataRange = sheet1.getRange(1,9,dataLastRow);
var data = dataRange.getValues();
for(var i = 0; i < data.length; i++) {
if (data[i] > 0) {
var targetLastRow = destsheet.getLastRow() + 1;
var values = sheet1.getRange(i+1,1,1,9).getValues();
destsheet.getRange(1,9,values.length,9).setValues(values);
}
}
}
Since you're setting the values of a whole range, you need to use setValues() rather than setValue(), note: plural rather than singular. I've also added getValues() to the range you were already pulling, this returns the array of values within the range that can then be passed to setValues().
I want to add the word "Flag" into column "G" or Array [6] where the corresponding row shows a value greater than 0.5 in column "E" or Array [5]. Note, that Array [6] is empty and only the script can add a value there if condition is met.
Here is my attempt but it does not add the word "Flag" into the cell.
I appreciate any help or pointer. Thanks in advance!
function test() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet1');
var rg=sh.getDataRange()
var vA=rg.getValues();
var g = [];
for(var i=1;i<vA.length;i++) {
g[i] = [vA[i][6]];
if(Number(vA[i][5])>0.5)g[i] = ['Flag']; {
SpreadsheetApp.getActiveSheet().getRange(2,7,g.length,1).setValues(g);
}}}
The error states:Cannot convert Array to Object[].
Here is an amended version of your code that will work if all your data is plain values and not formulas.
Please note this will overwrite any formulas.
function test() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('Sheet1');
var rg = sh.getDataRange();
var vA = rg.getValues();
for (var i = 1; i < vA.length; ++i) {
if (Number(vA[i][5]) > 0.5) {
vA[i][6] = 'Flag';
//change value of array element
}
}
rg.setValues(vA);
//set changed values to source range
}
Edit
This checks column F and makes changes to column G.
It will not overwrite the formulas in column F, but it will overwrite any formulas in column G.
function test() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('Sheet1');
var lastRow = sh.getLastRow();
var checkRg = sh.getRange('F2:F' + lastRow);
var flagRg = sh.getRange('G2:G' + lastRow);
var checkVa = checkRg.getValues();
var flagVa = flagRg.getValues();
for (var i = 0; i < checkVa.length; ++i) {
if (Number(checkVa[i][0]) > 0.5) {
flagVa[i][0] = 'Flag';
//change value of array element
}
}
flagRg.setValues(flagVa);
//set changed values to source range
}
Not sure what is in columns A thru F and beyond G.
for(var i=1;i<vA.length;i++) {
if(Number(vA[i][5])>0.5) vA[i][6] = 'Flag';
}
SpreadsheetApp.getActiveSheet().getDataRange.setValues(vA);
Or if you only want to replace G.
var g = [];
for(var i=1;i<vA.length;i++) {
g[i-1] = [vA[i][6]]; // Notice its an array
if(Number(vA[i][5])>0.5) g[i-1] = ['Flag']; // Notice an array again
}
SpreadsheetApp.getActiveSheet().getRange(2,7,g.length,1).setValues(g);
I need to move data from two sheets to one separate sheet. My code works provided the sheet is laid out as follows:
However, the sheet must be laid out like this:
I need to insert data above the row containing Amount Total but below the first row containing the headers. I feel this may be possible by adding rows above the Amount Total using the script but my current code uses getLastRow() to skip over the existing data in exports sheet. This does not work when Amount Total is placed as shown in the 2nd image. How can I achieve this? My existing code is below:
function exportData() {
var ards = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Newtownards");
var bangor = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Bangor");
var export = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Export");
var lastRow = export.getLastRow();
var nextCell = lastRow + 1;
//get values for export
var ardsRefValues = ards.getRange("B12:G12").getValues();
var ardsAmountValues = ards.getRange("B13:G13").getValues();
var bangorRefValues = bangor.getRange("B12:G12").getValues();
var bangorAmountValues = bangor.getRange("B13:G13").getValues();
for(var i = 0; i<=6; i++){
var a = ardsRefValues.join().split(',').filter(Boolean);
var b = ardsAmountValues.join().split(',').filter(Boolean);
var c = bangorRefValues.join().split(',').filter(Boolean);
var d = bangorAmountValues.join().split(',').filter(Boolean);
}//close for loop
//find length of the arrays
var aLength = a.length - 1;
var cLength = c.length - 1;
//loop through ards data arrays
for(i = 0; i<=aLength; i++){
export.getRange(nextCell, 5).setValue(a[i]);
export.getRange(nextCell, 4).setValue(b[i]);
nextCell++
}//close for loop
//loop through bangor data arrays
for(i = 0; i<=cLength; i++){
export.getRange(nextCell, 5).setValue(c[i]);
export.getRange(nextCell, 4).setValue(d[i]);
nextCell++
}//close for loop
var data = new Array();
var lastRow = export.getLastRow();
var total = 0;
for(var i = 2; i<=lastRow; i++){
var range = export.getRange(i, 4);
data = range.getValue();
total += data;
}
export.getRange(2, 7).setValue(total);
}//close function
Update: Good news is that these sheets will be updated every week. So the amount Total must be added into the row just below the last row of data