Trying to getlastrow - google-apps-script

Hello I am trying to have a continual list that copies values from one sheet to another in google sheets. My problem is that it is overwriting on the second sheet. I can't figure out how to find the last row before it inserts values. Here is my code.
function SubmitData() {
var s = SpreadsheetApp.getActiveSpreadsheet();
var sht = s.getSheetByName('Validation')
var drng = sht.getDataRange();
var rng = sht.getRange(6,2, drng.getLastRow(),drng.getLastColumn());
var rngA = rng.getValues();//Array of input values
var rngB = [];//Array where values that past the condition will go
var b = 0;//Output iterator
for(var i = 0; i < rngA.length; i++)
{
rngB[b]=[];//Initial new array
rngB[b].push(rngA[i][0],rngA[i][2]);
b++;
}
var shtout = s.getSheetByName('Track Data');
var outrng = shtout.getRange(2,1, rngB.length,2);//Make the output range the same size as the output array
outrng.setValues(rngB);

I don't see any condition in your code, you're just remapping
function SubmitData() {
const s = SpreadsheetApp.getActive();
const sht = s.getSheetByName('Validation');
const shtout = s.getSheetByName('Track Data');
const rng = sht.getRange(6, 2, sht.getLastRow() - 5, sht.getLastColumn() - 1);
const vs = rng.getValues();
let vO = vs.map(r => [r[0], r[2]]);
shtout.getRange(shtout.getLastRow() + 1, 1, vO.length, vO[0].length).setValues(vO);
}

Here is a modified script, easier to read. If you have the "sheet" in a variable you can call the getLastRow() method. Then plus 1.
You also can push an array inside an array.
Be aware that bad written functions can plus the lastrow. The "" will be see ad NOT empty. For instance:
//BAD:
=IF(A10 = "","","This is not empty")
//GOOD:
=IF(A10 = "",,"This is not empty")
The script:
function SubmitData() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const inputSheet = ss.getSheetByName('Validation')
const inputValues = inputSheet.getRange(6,2, inputSheet.getLastRow(),inputSheet.getLastColumn()).getValues()
const output = [];
inputValues.forEach(row => {
output.push([row[0].row[2]])
})
const outputSheet = ss.getSheetByName('Track Data');
outputSheet.getRange(outputSheet.getLastRow() + 1,1,output.length,output[0].length).setValues(output)
}

Related

data transfert based on cell value on google sheet

I'm not good with coding and i tried to mix some codes that i found and made what i needed, but now i face a difficult problem for me, so I'm trying when to press the button that i created to run the script to send the data that have for example an 'X' in the last column. i successfully made the sending from one sheet to another but it send all the data for now i want to be sent only the chosen ones with an 'X'.
any help I'll be grateful.
this is my code
thank you
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Sheet1");
var url = "https://docs.google.com/spreadsheets/d/15nIAXcP0a14OvvBr5lww4tO23stQD4PEu0QDAcgaFyE/edit#gid=0";
var ss2 = SpreadsheetApp.openByUrl(url);
var pasteSheet = ss2.getSheetByName("Sheet2");
// get source range
var max = copySheet.getMaxRows().toString();
var range = copySheet.getRange(2,1,max,4);
var dataValues = range.getValues();
for(var i = 1; i < dataValues.length; i++)
{
if(dataValues[i][5] === 'X')
{
copySheet.appendRow([dataValues[i][0],
dataValues[i][1],
dataValues[i][2],
dataValues[i][3],
dataValues[i][4]]);
}
}
for(var i = 1; i < dataValues.length; i++)
{
if(dataValues[i][5] === 'X')
{
var clearRow = i+1;
dataSheet.getRange('A' + clearRow + ':F' + clearRow).clear();
}
}
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,max,1);
// clear source values
Browser.msgBox('Commande Confirmer');
}
This is all that your function does
dataSheet is undefined so I assume it was csh
function lfunko() {
const ss = SpreadsheetApp.getActive();
const csh = ss.getSheetByName("Sheet1");
const ss2 = SpreadsheetApp.openByUrl("ssurl");
const psh = ss2.getSheetByName("Sheet2");
var vs = csh.getRange(2, 1, csh.getLastRow() - 1, csh.getLastColumn()).getValues();
vs.forEach((r,i) => {
if (vs[i][5] === 'X') {
csh.appendRow([vs[i][0], vs[i][1], vs[i][2], vs[i][3], vs[i][4]]);
csh.getRange(i + 1, 1, 1, 6).clear();
}
});
}

App Script: How to set the values of each cell using the .getRangeList?

I am using the .SetValues to attempt to fill every cell I selected through this line var targetSheetRange = targetSheet.getRangeList(arr1);
Unfortunately, when I do it, it always returns me the value of the first cell on all the remaining cells in my Target sheet instead of setting the value of each individual cell from the Source Sheet.
Here's my code:
function filtersCopyData() {
var dTable = SpreadsheetApp.getActiveSpreadsheet();
var sSheetDay = dTable.getSheetByName('Day 1'); // Source Sheet
var sheetRange = sSheetDay.getRangeList(['K3','K4','K5','K6','K7']).getRanges().map(range => range.getValues());
var targetSheet = dTable.getSheetByName('All Filters report'); // Target Sheet
var arr1 = ['B4:C4', 'B6:C6', 'B7:C7', 'B9:C9', 'B10:C10'];
var targetSheetRange = targetSheet.getRangeList(arr1);
targetSheetRange.setValue(sheetRange);
}
K3 value is 9, K4 value is 20, K5 value is 10, K6 value is 10, and K7 value is 10.
targetSheetRange.setValue(sheetRange); When this code is run, all the cells in arr1 return the value of 9, instead of copying the value of each cell from the Source Sheet.
I hope this thing that I'm trying to accomplish does make sense on the code, PS. I'm really a beginner. Thank you everyone!
Description
RangeList is an Array not a Range. I'm suprised your script even ran. You have to use Array.forEach to set the values of the non-contiguous ranges.
You are creating a RangeList and then getting the A1Notation of each range. You can simply define an array of the range A1Notations.
Note, some of the names are different than yours for my test sheet.
Script
function test() {
try {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("Data");
var rangeList = ["A1","A3","A5"];
var values = rangeList.map( range => sheet.getRange(range).getValue() );
rangeList = ["C1:D1","C3:D3","C5:D5"];
rangeList.forEach( (range,index) => sheet.getRange(range).setValues([[values[index],values[index]]]));
}
catch(err) {
console.log(err);
}
}
Reference
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getRangeList(String)
https://developers.google.com/apps-script/reference/spreadsheet/range-list#getRanges()
https://www.w3schools.com/jsref/jsref_map.asp
https://www.w3schools.com/jsref/jsref_foreach.asp
Writing to a rangelist with a rangelist of values
function filtersCopyData() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0'); // Source Sheet
const vs = sh.getRangeList(['K3','K4','K5','K6','K7']).getRanges().map(range => range.getValue());
const tsh = ss.getSheetByName('Sheet1');
const arr1 = ['B4:C4', 'B6:C6', 'B7:C7', 'B9:C9', 'B10:C10'];
const rgl = breakUpRangeList(ss,tsh,tsh.getRangeList(arr1));
const l = rgl.getRanges().length;
rgl.getRanges().forEach((r,i) => {
let a1 = r.getA1Notation();
let idx = i % arr1.length;
r.setValue(vs[idx]);
});
}
function breakUpRangeList(ss=SpreadsheetApp.getActive(),sh=ss.getSheetByName("Sheet0"),rgl) {
let b = [];
rgl.getRanges().forEach(rg => {
rg.getValues().forEach((r,i) => {
let row = rg.getRow() + i;
r.forEach((c, j) => {
let col = rg.getColumn() + j;
b.push(sh.getRange(row, col).getA1Notation())
})
})
})
//Logger.log(JSON.stringify(b));
return sh.getRangeList(b);
}

TypeError: lastrow.setValues is not a function

I'm trying to copy past a particular range to another spreadsheet serving as a database. The goal is to copy past values that are in the range(a43:n54), to the last row of the database page, then to clear the range (d11:n22) of the source sheet.
I've already used part of code I saw on another thread (the get/set values part). But here when I run the function, it says that line 35 "lastrow.setValues(values) is not a function". I know it means my function is not valid and most likely it will do the same with all the setValues section...
function myfunction()
{
// spreadsheet identification
const sourcesheet = SpreadsheetApp.getActiveSpreadsheet();
const destination = SpreadsheetApp.openByUrl("page_url")
// identification of the ranges to copy and to delete
const ws = sourcesheet.getSheetByName ("Récap");
const source_range_to_delete = ws.getRange("d11:n22");
const source_range_to_copy = ws.getRange("a43:n54");
// get last row of target spread sheet
const destpage = destination.getSheetByName("Feuille 1");
var destrange =destpage.getRange("A1:n").getValues();
var lrIndex;
for( var i = destrange.length-1;i>=0;i--){
lrIndex = i;
if(!destrange[i].every(function(c){ return c == "";})) {
break;
}
}
var lastrow =lrIndex +1;
//get values
var values = source_range_to_copy.getValues()
var bGcolors = source_range_to_copy.getBackgrounds();
var colors = source_range_to_copy.getFontColors();
var fontSizes = source_range_to_copy.getFontSizes();
// set values
lastrow.setValues(values);
lastrow.setBackgrounds(bGcolors);
lastrow.setFontColors(colors);
lastrow.setFontSizes(fontSizes);
source_range_to_delete.clearContent({contentsOnly:true});
}
function myfunction() {
// spreadsheet identification
const sourcesheet = SpreadsheetApp.getActiveSpreadsheet();
const destination = SpreadsheetApp.openByUrl("page_url");
// identification of the ranges to copy and to delete
const ws = sourcesheet.getSheetByName("Récap");
const source_range_to_delete = ws.getRange("d11:n22");
const source_range_to_copy = ws.getRange("a43:n54");
// get last row of target spread sheet
const destpage = sourcesheet.getSheetByName("Feuille 1");
var data = sourcesheet.getRange("a1:n").getValues();
for (var lastrow = data.length-1; lastrow >= 0; lastrow--) {
if (data[lastrow].some(c => c != "")) break;
}
//get values
var values = source_range_to_copy.getValues();
var bGcolors = source_range_to_copy.getBackgrounds();
var colors = source_range_to_copy.getFontColors();
var fontSizes = source_range_to_copy.getFontSizes();
// set range right after the last row on destination sheet
var destrange = destpage.getRange(lastrow + 2,1,values.length,values[0].length);
// set values of destination range
destrange.setValues(values);
destrange.setBackgrounds(bGcolors);
destrange.setFontColors(colors);
destrange.setFontSizes(fontSizes);
source_range_to_delete.clearContent();
}
setValues() is a method of class Range. lastrow is an integer.

In Google Sheets set dynamic dropdown with Apps Script

I'm trying to set a dynamic dropdown in Google Sheet using Apps Script. I managed to get most parts working except setting the data validation in the cells necessary:
function sheetByName(ssId, sheetName) {
var ss = SpreadsheetApp.openById(ssId);
var sheet = ss.getSheetByName(sheetName);
return sheet;
};
function columnByName(sheet, columnName) {
var data = sheet.getDataRange().getValues();
var column = data[0].indexOf(columnName);
return column;
};
function columnValues(sheet, index) {
var data = sheet.getDataRange().getValues();
var values = [];
for(n=1; n<data.length; ++n) {
values.push(data[n][index]);
}
return values;
}
function columnSetDataValidation(sheet, index, options) {
var data = sheet.getDataRange().getValues();
var rule = SpreadsheetApp.newDataValidation()
.requireValueInList(options)
.setAllowInvalid(true)
.build();
for(n=1; n<data.length; ++n) {
var cell = data[n][index];
};
};
function dropDownBedrijven() {
var sheetCollegas = sheetByName("<<ID HERE>>", "Collegas");
var sheetBedrijven = sheetByName("<<ID HERE>>", "Bedrijven");
var getColumnIndexInBedijven = columnByName(sheetBedrijven, "Bedrijf");
var getColumnIndexInCollegas = columnByName(sheetCollegas, "Bedrijf");
var bedrijven = columnValues(sheetBedrijven, getColumnIndexInBedijven).filter(item => item);
columnSetDataValidation(sheetCollegas, getColumnIndexInCollegas, bedrijven);
};
I can't manage to get the function columnSetDataValidation to set data validation in the required cells.
Do you have any idea how to go about it?
You need to use range.setDataValidation(rule) with a range.
In your function columnSetDataValidation you are correctly building the rule, but are failing to assign the rule to a range. You are looping over the values of the range and then changing the value of var cell until the loop ends. Nowhere did you call range.setDataValidation(rule).
Try the following solution:
function columnSetDataValidation(sheet, index, options) {
var range = sheet.getDataRange();
var rule = SpreadsheetApp.newDataValidation()
.requireValueInList(options)
.setAllowInvalid(true)
.build();
for(n = 1; n < range.getLastRow(); ++n) {
var cell = range.getCell(n,index);
cell.setDataValidation(rule);
};
};
References:
Range.getCell(row, column)
Range.setDataValidation(rule)
Try this:
function columnSetDataValidation() {
const ss=SpreadsheetApp.getActive();
const sheet=ss.getSheetByName('Sheet1');
const range = sheet.getRange(2,4,sheet.getLastRow()-1);//putting validation in column 4
const options=[1,2,3,4,5];
const rule = SpreadsheetApp.newDataValidation()
.requireValueInList(options)
.setAllowInvalid(true)
.build();
range.setDataValidation(rule);
}

How to overwrite cell function with Paste value only using Google Script

I have a database that makes live calculations, but once the new data added to the database has been processed that day, I effectively want to Copy + Paste value only on these cells so that the results of the formulas are fixed and can no longer change.
The current script I am using is:
function myFunction() {
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var r = ss.getRange(1,2,ss.getLastRow());
var vals = r.getValues();
for(var i =0;i<vals.length;i++){
ss.getRange(i+1,2).setValue(ss.getRange(i+1,2).getValue());
}
}
However, in column B beneath the data set, all the cells start with IF(B2092="","",etc). On cells that are empty, I still require the formula to remain in place. I only want to script to be applied to cells that have data within.
Can anyone help with this? Thanks
Try this:
function myFunction() {
var sh = SpreadsheetApp.getActive();
var ss = sh.getActiveSheet();
var rg = ss.getRange(1,2,ss.getLastRow());
var vals = rg.getValues(); // get values
var formulas = rg.getFormulas(); // get formulas
// merge values & formulas
var data = formulas.map((row,row_index) =>
row.map((cel, cel_index) =>
{ return (cel) ? cel : vals[row_index][cel_index] }));
rg.setFormulas(data); // output
}
Corrected version:
function copy_values_and_formulas() {
var sh = SpreadsheetApp.getActive();
var ss = sh.getActiveSheet();
var rg = ss.getRange(1,2,ss.getLastRow());
var vals = rg.getValues(); // get values
var formulas = rg.getFormulas(); // get formulas
// merge values & formulas
var data = vals.map((row, row_index) =>
row.map((cel, cel_index) =>
{ return (cel == 0) ? formulas[row_index][cel_index] : cel }));
rg.setFormulas(data); // output
}
function myFunction() {
var sh = SpreadsheetApp.getActive();
var ss = sh.getActiveSheet();
var rg = ss.getRange(1,2,ss.getLastRow());
var vals = rg.getDisplayValues();
for(var i=0;i<vals.length;i++){
if(vals[i][1] && vals[i][1].length!=0) {
ss.getRange(i+1,2).setValue(ss.getRange(i+1,2).getValue());
}
}
}