How to overwrite cell function with Paste value only using Google Script - google-apps-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());
}
}
}

Related

Converting Formula Result in cell into Notes

So I understand this is very similar to:
Set Notes from Column A based on contents of Column B
function addNote() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var values_range = sheet.getRange("R5:R6");
var notes_range = sheet.getRange("AS5:AS6");
var notes = notes_range.getValues();
values_range.setNotes(notes)
}
However it's returning blank for me. It seems to be because the cells are the results of a SUM.
Is there a way to get the result?
Copy display values in column B as notes in column A
function addNote() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0")
const vs = sh.getRange(2,2,sh.getLastRow() - 1).getDisplayValues();
vs.forEach((r,i)=>{
sh.getRange(i + 2,1).setNote(r[0])
});
}

Google sheets script to export rows to different worksheet

Here is a script I'm using that works, but is trying to import too much data. I apologize for my ignorance when it comes to this.
function copyPaste() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getSheetByName("Print Results");
var rangeSource = source.getDataRange();
var data = rangeSource.getValues();
var lr = rangeSource.getLastRow();
var lc = rangeSource.getLastColumn();
Logger.log(data);
var sss = SpreadsheetApp.openById("XXXXXX");
var target = sss.getSheetByName("Sheet2")
target.getRange(target.getLastRow()+1,1,lr,lc).setValues(data);
}
What I need this to do is only select A8:M, and only copy over the rows that have a USER ID in column J. The USER ID is always a number, so a simple rule of ">0" should work for that. USER ID is imported from a different tab using a vlookup formula so the cell is not "empty".
Only copy rows where Column J is not null
function copyPaste() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Print Results");
const rg = sh.getDataRange();
const vs = rg.getValues().filter(r => r[9] != '');
Logger.log(vs);
const sss = SpreadsheetApp.openById("XXXXXX");
const target = sss.getSheetByName("Sheet2")
target.getRange(target.getLastRow()+1,1,vs.length,vs[0].length).setValues(vs);
}
.filter() method

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.

Trying to getlastrow

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)
}

Functions all executing at the same time

I am trying to copy data from one sheet, paste it into another and then delete the row that have a "flag" attached to them (Column D). When I execute this code, it just deletes the flag and not the whole row. What is going on here? The functions seem to execute in the wrong order.
Tried using Utilities.sleep(), as well as
separating both into different functions
using a for loop writing out all the columns I want deleted
applying flush to the functions before executing the next
//copies the code
function myFunction() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange("K:N")
var values = range.getValues()
var target = ss.getSheetByName("worklist")
target.getRange("A:D").setValues(values)
SpreadsheetApp.flush()
Utilities.sleep(5 * 1000)
}
//deletes the rows with flags in them
function myFunction2() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange("K:N")
var values = range.getValues()
var target = ss.getSheetByName("worklist")
Utilities.sleep(6 * 1000)
var oldnews = target.getRange("D:D")
for (i = oldnews.length; i > 0; i--){
if (oldnews[i] !== undefined) {
target.getRange(i,1)
target.getRange(i,2)
target.getRange(i,3)
target.getRange(i,4)
}
}
SpreadsheetApp.flush()
}
It's not really clear what your asking. So I just guessed at some of this.
function myFunction() {
var ss = SpreadsheetApp.openById("id");
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange(1,11,sheet.getLastRow(),4);
var values = range.getValues()
var target = ss.getSheetByName("worklist")
target.getRange(1,1,values.length,values[0].length).setValues(values);
SpreadsheetApp.flush();
var d=0;
for(var i=0;i<values.length;i++) {
if(values[i][3]) {
target.deleteRow(i+1-d++);
}
}
}
Try the below code:
function myFunction() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url);
var sheet = ss.getSheetByName('Bad Emails Input');
var range = sheet.getRange("K:N");
var values = range.getValues();
var target = ss.getSheetByName("worklist");
target.getRange("A:D").setValues(values);
SpreadsheetApp.flush();
//If you have a header row change the below to A2:D and count to 2
var data=ss.getSheetByName("worklist").getRange("A:D").getValues(),count=1;
for (i in data) {
var rowdata=data[i];
if (!rowdata[0] || rowdata[0]==''){break;}
if (rowdata[3] == 'flag') {//change the flag to however it is in column D
ss.getSheetByName("worklist").deleteRow(count);
count++;
}
}
}