Placing a timestamp on a cell accross multiple sheets on edit - javascript

I tried many different variations of this script and can't figure out why it's not working.
I want to update the same cell "J3" with a timestamp across multiple tabs onedit. I have another function on the spreadsheet already using onEdit(e), so i set a new function with an onEdit trigger.
I retrieve the names of the tabs I want to update and store them in an array.
function Overview_timestamp(e) //function to use in the onEdit trigger
{
var activeSheet = e.source.getActiveSheet();
var range = e.range;
var cellToStamp = "J3" ;
var name_range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Structure').getRange(2, 5, 14, 1).getValues(); //sheets i want to update
var flattened_name_range = [] ; //converting into 1D array
for (var i = 0; i < name_range.length; i++) {
flattened_name_range.push(name_range[i][0]);
}
if(flattened_name_range.indexOf(activeSheet())!==-1 ) {
activeSheet.getRange(cellToStamp).setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm:ss");}
}

Try this:
function Overview_timestamp(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'Sheet name') {//just to limit action to one sheet but it would be nice to have additional control like clicking a checkbox or selecting a value on a validated cell.
const shts = e.source.getSheetByName('Structure').getRange(2, 5, 14).getValues().flat();
shts.forEach(n => {
e.source.getSheetByName(n).getRange('J3').setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm:ss")
});
}
}
I did it this way on my sheet using a checkbox at A1 on Sheet1
function onEdit(e) {
//e.source.toast('entry');
const sh = e.range.getSheet();
if (sh.getName() == 'Sheet1' && e.range.columnStart==1 && e.range.rowStart==1 && e.value=='TRUE') {
//e.source.toast('cond');
const shts = e.source.getSheetByName('Sheet2').getRange(2, 5, 14).getValues().flat().filter(e=>e);
shts.forEach(n => {
e.source.getSheetByName(n).getRange('J3').setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm:ss")
});
e.range.setValue('FALSE');
}
}

Related

Method search on google sheet data from one column using google script?

I had tried to search data like below flow picture and script to search data from google sheet using google app script but the script using is not working properly but can someone tell me how to setup search function to find data like flow on image? thanx
[Flow searching data][1]
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "Search", functionName: "searchRecord"} ];
ss.addMenu("Commands", menuEntries);
}
function searchRecord()
{
var ss = SpreadsheetApp.getActiveSpreadsheet()
var wsSearchingData = ss.getSheetByName("Searching Data")
var wsDatabase = ss.getSheetByName("Database")
var searchString = wsSearchingData.getRange("E4").getValue();
var column =1; //column Index
var columnValues = wsDatabase.getRange(2, column, wsDatabase.getLastRow()).getValues(); //1st is header row
var searchResult = columnValues.findIndex(searchString); //Row Index - 2
var searchValue = wsDatabase.getRange("B2:B2041").getValues()
var matchingDatabase = searchValue.map(searchColumn => {
var matchColumn = columnValues.find(r => r[0] == searchColumn[0])
return matchColumn = matchColumn ? [matchColumn[2]] : null
})
console.log(matchingDatabase)
if(searchResult != -1)
{
//searchResult + 2 is row index.
SpreadsheetApp.getActiveSpreadsheet().setActiveRange(sheet.getRange(searchResult + 1, 1))
}
Array.prototype.findIndex = function(search){
if(search == "") return false;
for (var i=0; i<this.length; i++)
if (this[i] == search) return i;
wsSearchingData.getRange("B11").setValue(search[0]);
wsSearchingData.getRange("C11").setValue(search[1]);
wsSearchingData.getRange("D11").setValue(search[2]);
wsSearchingData.getRange("E11").setValue(search[3]);
wsSearchingData.getRange("F11").setValue(search[4]);
return;
}
}
[1]: https://i.stack.imgur.com/HF9K8.png
var searchResult = columnValues.findIndex(searchString); //Row Index - 2
replace the above code with:
var searchResult = columnValues.filter(r=>r[1]==searchString)
You can then put searchResult directly as output in the sheet. Make sure that [1] in the above contains the column index of Name in the columnValues Array.

Apps Script: how to copy hyperlink from a cell to another sheet

I need to copy this data from one sheet to another but with all the links active, because with this formula, copy just like a text.
I really don't know what do and what do I have to change to copy every data from the original sheet.
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var values = [
[formS.getRange("D1").getValue(), formS.getRange("D2").getValue(), formS.getRange("D3").getValue(), formS.getRange("D4").getValue(), formS.getRange("D5").getValue(), formS.getRange("D6").getValue(), formS.getRange("D7").getValue(), formS.getRange("D8").getValue(), formS.getRange("D9").getValue(), formS.getRange("D10").getValue(), formS.getRange("D11").getValue(), formS.getRange("D12").getValue(), formS.getRange("D13").getValue(), formS.getRange("D14").getValue(), formS.getRange("D15").getValue(), formS.getRange("D16").getValue(), formS.getRange("D17").getValue(), formS.getRange("D18").getValue(), formS.getRange("D19").getValue(), formS.getRange("D20").getValue(), formS.getRange("D21").getValue(), formS.getRange("D22").getValue(), formS.getRange("D23").getValue(), formS.getRange("D24").getValue(), formS.getRange("D25").getValue(), formS.getRange("D26").getValue(), formS.getRange("D27").getValue(), formS.getRange("D28").getValue(), formS.getRange("D29").getValue(), formS.getRange("D30").getValue(), formS.getRange("D31").getValue(), formS.getRange("D32").getValue(), formS.getRange("D33").getValue(), formS.getRange("D34").getValue(), formS.getRange("D35").getValue(), formS.getRange("D36").getValue(), formS.getRange("D37").getValue(), formS.getRange("D38").getValue(), formS.getRange("D39").getValue(), formS.getRange("D40").getValue(), formS.getRange("D41").getValue(), formS.getRange("D42").getValue(), formS.getRange("D43").getValue(), formS.getRange("D44").getValue(), formS.getRange("D45").getValue(), formS.getRange("D46").getValue(), formS.getRange("D47").getValue(), formS.getRange("D48").getValue(), formS.getRange("D49").getValue(), formS.getRange("D50").getValue(), formS.getRange("D51").getValue(), formS.getRange("D52").getValue()]
];
dataS.getRange(dataS.getLastRow() + 1, 1, 1, 52).setValues(values);
ClearCell();
RE-EDIT:
Complete project with Submit, Search and Update buttons!
function ClearCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var RangeToClear = [ "D1:D52"];
for (var i=0; i<RangeToClear.length; i++) {
formS.getRange(RangeToClear[i]).clearContent();
}
}
//-------------------------------------------------------------------------------
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var lastRow = dataS.getLastRow() + 1
formS.getRange("D1:D52").copyTo(dataS.getRange(lastRow, 1, 1, 52), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
dataS.getRange(lastRow,1).clearDataValidations()
ClearCell();
}
//----------------------------------------------------------------------------
function Search() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var str = formS.getRange("D1").getValue();
var dataS = ss.getSheetByName("ToCompleteProyect")
var values= dataS.getDataRange();
Logger.log(values.getLastRow())
for (var i = 0; i < values.getLastRow(); i++) {
var row = dataS.getRange(i+1,1).getValue();
if (row == str) {
dataS.getRange(i+1,2,1,51).copyTo(formS.getRange("D2:D52"),SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
}
}
}
//------------------------------------------------------------------------------
function Update(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var str = formS.getRange("D1").getValue();
var dataS = ss.getSheetByName("ToCompleteProyect")
var values= dataS.getDataRange();
Logger.log(values.getLastRow())
for (var i = 0; i < values.getLastRow(); i++) {
var row = dataS.getRange(i+1,1).getValue();
if (row == str) {
formS.getRange("D2:D52").copyTo(dataS.getRange(i+1, 2, 1, 51), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
ClearCell();
}
}
}
EDIT:
One simple way to do it is just to copy-paste but not only the values but the cells transposed as one would do with the Copy and Paste Special. It's indeed a much simpler code and it seems to me that does the trick, you just need this line:
formS.getRange("D1:D52").copyTo(dataS.getRange(lastRow, 1, 1, 52), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true) ---> this last TRUE value is the one which transposes the data
And the full function:
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var lastRow = dataS.getLastRow() + 1
formS.getRange("D1:D52").copyTo(dataS.getRange(lastRow, 1, 1, 52), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
ClearCell();
}
Was it useful??
OLD: If the links is always in the same column/s of the last row, you can then pass them through this second function. I took myself the liberty also of suggesting a way of simplifying grabbing the values of the form ;)
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var values = formS.getRange("D1:D52").getValues() //Here I took the entire range
values = [values.map(function(n){return n[0]})] // and turn that column into a row
var lastRow = dataS.getLastRow() + 1
dataS.getRange(lastRow, 1, 1, 52).setValues(values);
linkCellContents(dataS.getRange(lastRow, 10, 1, 1)) // assuming you need to make a link the value in column number 10 (J)... repeat this line with each column you need to convert
ClearCell();
}
function linkCellContents(range) {
var value = range.getValue()
var richValue = SpreadsheetApp.newRichTextValue()
.setText(value)
.setLinkUrl(value)
.build();
range.setRichTextValue(richValue);
}

BUTTON to move data from multiple google sheets into one master

My boss told to move same set of data from 40 multiple google sheets into one master sheets which are filled by 40 people separately currently am working on it with an ADD on function
is there any way to put a submit button on each sheets so that when user fill the data and click on submit button the data go direct to the master sheets ?
I have the script which is working fine with sheets but the only cons of that is the script only combine the tabs into same spreadsheet
here is code :
const masterSheet = "ASM-A30";
const masterSheetFormulaCell = "A2";
const ignoreSheets = ["Verified NDRx","Business Tracker","NDRX","PMT_EBx","PMT_EBx.","NDRx PMT Business Tracker.","Analysis"];
const dataRange = "A2:AA";
const checkRange = "A2:A" ;
//end set variables
const ss = SpreadsheetApp.getActiveSpreadsheet() ;
ignoreSheets.push(masterSheet) ;
const allsheets = ss.getSheets() ;
const filteredListofSheets = allsheets.filter(s => ignoreSheets.indexOf(s.getSheetName()) == -1);
let formulaArray = filteredListofSheets.map(s => `FILTER({'${s.getSheetName()}'!${dataRange},"${s.getSheetName()} - Row "&ROW('${s.getSheetName()}'!${dataRange})}, '${s.getSheetName()}'!${checkRange}<>"")`);
let formulaText = "={" + formulaArray.join(";")+ "}"
//console.1og( formulaText) ;
ss. getSheetByName(masterSheet).getRange(masterSheetFormulaCell) .setFormula(formulaText) ;
}
Try this
const ignoreSheets = ["Verified NDRx","Business Tracker","NDRX","PMT_EBx","PMT_EBx.","NDRx PMT Business Tracker.","Analysis"];
const masterSheet = "ASM-A30";
function compile() {
let result = []
SpreadsheetApp.getActiveSpreadsheet().getSheets().filter(s => ignoreSheets.indexOf(s.getSheetName()) == -1).forEach((s,i) => {
let [headers, ...data] = s.getDataRange().getValues()
if (i == 0) { result.push(headers.flat()) }
data.forEach(r => result.push(r))
})
if(result.length) {
var master = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(masterSheet)
master.clearContents()
master.getRange(1, 1, result.length, result[0].length).setValues(result)
SpreadsheetApp.getActiveSpreadsheet().toast('Updated!');
}
}
to add rows, change
if (i == 0) { }
and try
var master = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(masterSheet)
// master.clearContents()
master.getRange(+master.getLastRow()+1, 1, result.length, result[0].length).setValues(result)
SpreadsheetApp.getActiveSpreadsheet().toast('Updated!');

Firing a bigQuery query on editing a particular column in google sheets

/* I am new to app scripting and I have a very specific question. I have a sheet with column A. Whenever this sheet is changed to add/edit the column A, i need to trigger bigQuery query and update results in another column B. I used onedit() function but it does not run the bigQuery query. I also tried using an installable trigger but still no luck. Any advice on how to handle such scenario.
Issue 1: Only top edited row is added to array " dat"
2: The function runBigQuery is not triggered. */
Script:
function onMyEdit(e){
// Trying to find if the edited sheet is 'A' and column is 25. If so, I //want to get edited value(s) in the column 25 and add to an array
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = e.range;
var colZ=range.getColumn()+1;
var dat=[]
if (sheet.getName() == 'A' && range.getColumn() == 25 )
{
for(var i=0;i<range.getNumRows();i++)
{
var offset=range.getRow() + i;
var g=sheet.getRange('Y' + offset).getValue();
var val=sheet.getRange('Z' + offset).getValue();
if (val== "Not found")
{
dat.push(g)
}
}
}
dat = dat.filter(function(n){ return n != "" });
for (var i = 0; i < dat.length; i++)
{
dat[i] = '"' + dat[i] + '"';
}
var unique = [...new Set(dat)]
//Initiate Query by calling function runBigQuery
var values= runBigQuery(unique)
// Append the results to another sheet.
appendData(sheetName,values)
}
Thanks,

Sheet Coming in as undefined

I have a spreadsheet with revenue and expense data. Here is a spreadsheet with what it looks like with data redacted: https://docs.google.com/spreadsheets/d/1xYXt_pvhpzCO7D61SoOwcmNNIGaFHkExwLHhl56c-NU/edit?usp=sharing
I want to create a script that validates the data in column C by forcing a user to enter a date. Once a date is entered, I want to return a new row beneath it. The code works in that it validates data and enters a new row, but when I enter a date into C96, the new row pushes the 'Date' cell, currently in C100, down to C101 and says the date is invalid. I set up my code so that it should be rerunning the script and not making C101 data validated. Additionally, I am getting errors with the 'getRange' method. It is saying that 'TypeError: Cannot call method "getRange" of undefined.'
Currently I have triggers for onEdit and onOpen for both dateValidation functions and onEdit triggers for the addRow functions.
For some reason, on my original file, the code still runs despite these errors. I have starred the location of the errors in my code below. I am very new to Google Scripts/ programming in general, so if anyone can help me out it would be greatly appreciated.
Here is my code currently:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("General Ledger");
// Get row of first revenue
var firstRowRevLookup = 'Revenue';
var firstRowRange = sheet.getRange('B1:B');
var firstRowValues = firstRowRange.getValues();
var x = [];
for (var i = 0; i<firstRowValues.length; i++) {
if(firstRowValues[i] == firstRowRevLookup) {
x.push(i+3);
}
}
var firstRowRevenue = Number(x);
Logger.log(firstRowRevenue);
//Get row of last revenue
var lastRowRevLookup = 'End Revenues';
var lastRowRange = sheet.getRange('C1:C');
var lastRowValues = lastRowRange.getValues();
var y = [];
for (var i = 0; i < lastRowValues.length; i++) {
if(lastRowValues[i] == lastRowRevLookup) {
y.push(i);
}
}
var lastRowRevenue = Number(y);
Logger.log(lastRowRevenue)
//Get row of first expense
var firstRowExLookup = 'Expenses';
var z = [];
for(var i = 0; i<firstRowValues.length; i++) {
if(firstRowValues[i] == firstRowExLookup){
z.push(i+3);
}
}
var firstRowExpense = Number(z);
Logger.log(firstRowExpense);
//Get row of last expense
var lastRowExLookup = 'End Expenses';
var q = [];
for(var i = 0; i <lastRowValues.length; i++) {
if( lastRowValues[i] == lastRowExLookup) {
q.push(i);
}
}
var lastRowExpense = Number(q);
Logger.log(lastRowExpense);
dateValidationExpenses(sheet, firstRowExpense, lastRowExpense);
dateValidationRevenue(sheet, firstRowRevenue, lastRowRevenue);
//User must enter date into column C
function dateValidationExpenses(sheet, firstRowExpense, lastRowExpense) {
// Logger.log(sheet);
**var dateRange = sheet.getRange(firstRowExpense, 3, lastRowExpense-firstRowExpense+1);**
//Logger.log(dateRange);
var rule = SpreadsheetApp.newDataValidation()
.requireDate()
.setAllowInvalid(false)
.setHelpText('Please enter date using format "=date(year,month,day)"')
.build();
dateRange.setDataValidation(rule);
dateRange.setFontWeight('normal');
}
//User must enter date into column C
function dateValidationRevenue(sheet,firstRowRevenue,lastRowRevenue) {
**var dateRange = sheet.getRange(firstRowRevenue, 3, lastRowRevenue-firstRowRevenue+1);**
var rule = SpreadsheetApp.newDataValidation()
.requireDate()
.setAllowInvalid(false)
.setHelpText('Please enter a date using format "=date(year,month,day)"')
.build();
dateRange.setDataValidation(rule);
dateRange.setFontWeight('normal');
}
function addRowExpenses () {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('General Ledger');
var testCell = sheet.getRange(lastRowExpense,3).getValue();
//Logger.log(testCell);
if (testCell !== '') {
sheet.insertRows(lastRowExpense+1);
}
}
function addRowRevenue () {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('General Ledger');
var testCell = sheet.getRange(lastRowRevenue,3).getValue();
//Logger.log(testCell);
if (testCell !== '') {
sheet.insertRows(lastRowRevenue+1);
}
}
function editTrigger1() {
var sheet = SpreadsheetApp.getActive()
ScriptApp.newTrigger('addRowExpenses')
.forSpreadsheet(sheet)
.onEdit()
.create();
}
function editTrigger2() {
var sheet = SpreadsheetApp.getActive()
ScriptApp.newTrigger('addRowRevenue')
.forSpreadsheet(sheet)
.onEdit()
.create();
}
The variable sheet is declared outside of a function, which makes it a "global". You don't need to pass sheet
Currently:
dateValidationExpenses(sheet, firstRowExpense, lastRowExpense);
dateValidationRevenue(sheet, firstRowRevenue, lastRowRevenue);
Change to:
dateValidationExpenses(firstRowExpense, lastRowExpense);
dateValidationRevenue(firstRowRevenue, lastRowRevenue);
sheet is available to the dateValidationExpenses function without the need to pass it. That should solve the issue with the error you are getting on this line:
var dateRange = sheet.getRange(firstRowExpense, 3, lastRowExpense-firstRowExpense+1);

Categories