I am trying to figure out how to add a timestamp on a new row that is created in Google Sheets.
So whenever a new row is created, one of the cells in that row will have a timestamp reflecting when the row was created.
Is this possible?
Thanks!!
Add this function:
function addTimeStamp(e) {
var typeOfChange = e.changeType;
//Logger.log('typeOfChange: ' + typeOfChange);
//Logger.log('typeof typeOfChange: ' + typeof typeOfChange);
if (typeOfChange === "INSERT_ROW") {
var timeStamp = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
var activeRangeIs = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveRange();
//Logger.log(activeRangeIs);
var whatRow = activeRangeIs.getRow();
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(whatRow, 3).setValue(timeStamp);
};
};
Then use an installable trigger. Resources menu, Current Project Triggers.
Related
I have two sheets. On one sheet (Sheet1), I have a column 'A' which has 5 fixed values, and a column 'B' which records the timestamp value in 'A' change. The other sheet (Sheet2) is meant to record all the changes in the first sheet in one day.
I use this simple query in the recording sheet:
=QUERY(Sheet1!A$1:X,"select * where C>="& Sheet2!D1)
with Sheet1!C has timestamps and Sheet2!D1 is the timestamp of 12:00 AM today
The problem is when I change the value of a row in C columns more than one time, instead of creating a new row in Sheet2 it change the value of that row in Sheet2 into new values.
So how do I change my code to get my desire results?
EDIT 2: here is my new code, but it doesn't help.
function importdata(x) {
// var row = x.range.getRow();
// var col = x.range.getColumn();
var addedsheet=SpreadsheetApp.getActive().getSheetByName("Change"); // Sheet where I want to keep the record of the change
var original_sheet = SpreadsheetApp.getActive().getSheetByName("Master"); //sheet where the change is happended
var compared_value = addedsheet.getRange(1,4).getValue(); // Cell D1 of sheet "Change", which has timestamp of today
var insert_area = original_sheet.getRange("A2:X").getValues() // area to get value from "Master" sheet to put into "Change"
var compared_area = original_sheet.getRange("C2:C").getValues(); // area where has timestamp
if (compared_area >= compared_value){
addedsheet.values.append([insert_area])}
} //if timestamp of one row from Master is greater than the value at Change!D1 =>append that row at the end (this is what I'm trying to do)
EDIT 3: I fixed the above code by append[insert_area][0] instead of [insert_area]
But then I have a new problem: there will a chance that a row in sheet 1 will be overwrited in sheet 2. I try something like this, but it returns nothing on the sheet.
function for_each_row(){
var addedsheet=SpreadsheetApp.getActive().getSheetByName("Change"); // Sheet where I want to keep the record of the change
var original_sheet = SpreadsheetApp.getActive().getSheetByName("Master"); //sheet where the change is happended
var compared_value = addedsheet.getRange(1,4).getValue(); // Cell D1 of sheet "Change", which has timestamp of today
var number_of_row_2 = addedsheet.getLastRow;
var number_of_row_1 = original_sheet.getLastRow();
for (var i=2; i<number_of_row_1 +1; i++){
var compared_stamp = original_sheet.getRange("C"+i).getValues();
var insert_values = (original_sheet.getRange(i,1,1,24).getValues())
if (compared_stamp > compared_value){
var insert_values = (original_sheet.getRange(i,1,1,24).getValues());
for (var j = 2; j<number_of_row_2 +1; j++){
var value_from_sheet = addedsheet.getRange(j,1,1,24).getValues();
if (insert_values ===value_from_sheet){
return
}
else(
addedsheet.appendRow(insert_values[0]))
}
}
}
}
My thought is if a row satisfies the 1st condition then the value will be check in sheet 2. If sheet 2 didn't have that row then append that row.
Issue:
If I understand you correctly, you want to do the following:
If sheet Master is edited, iterate through all rows in this sheet (excluding headers), and for each row, check the following:
Column C has a higher value than cell D1 in sheet Change.
This row, with these exact values, does not exist in Change.
If these conditions are meet, append the row to Change.
Solution:
Use filter and some to filter out rows that don't match your two conditions, and use setValues to write the resulting rows to your other sheet.
Code snippet:
function onEdit(e) {
var editedSheet = e ? e.range.getSheet() : SpreadsheetApp.getActiveSheet();
if (editedSheet.getName() === "Master") {
var addedSheet = SpreadsheetApp.getActive().getSheetByName("Change");
var compared_value = addedSheet.getRange(1,4).getValue();
var newData = editedSheet.getRange("A2:X" + editedSheet.getLastRow()).getValues();
var currentData = addedSheet.getRange("A2:X" + addedSheet.getLastRow()).getValues();
var filteredData = newData.filter(row => row[2] >= compared_value)
.filter(row => !currentData.some(currentRow => JSON.stringify(currentRow) === JSON.stringify(row)));
addedSheet.getRange(addedSheet.getLastRow()+1,1,filteredData.length,filteredData[0].length).setValues(filteredData);
}
}
Note:
An easy way to check if two rows have the same values is using JSON.stringify(row).
I'm assuming the timestamps are not Dates. If they are, you should compare them using getTime(). So you should change the corresponding code to newData.filter(row => row[2].getTime() >= compared_value.getTime()).
The following function is designed to get my spreadsheet, add a new tab, insert a new tab with a query that runs, and then save the new tab under a new name.
Everything works except the new tab always is inserted as then next unused tab number and not renamed. Tried a number of variations (setName, etc.) and nothing seems to work.
Help!
function costIncome() {
var spreadsheetId =https://docs.google.com/spreadsheets/d/thisIsTheSheetID/edit';
var targetRange = 'PlaySheet!B:F';
var SELECT = 'select B,E,F,sum(C) ';
var WHERE = ' ';
var GROUPBY = ' group by B,F,E order by D,B';
var HAVING = ' ';
var SQL = SELECT + WHERE + GROUPBY + HAVING;
//var SQL = 'select B,E,F,sum(C) group by B,F,E';
var Query = '=QUERY('+targetRange+',\"'+SQL+'\")';
var currentDoc = SpreadsheetApp.openByUrl(spreadsheetId);
currentDoc.insertSheet('costfunds');
var pushQuery = currentDoc.getRange(1, 1).setFormula(Query);
var pullResult = currentDoc.getDataRange().getValues();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); // Get Active spreadsheet object
var sh = spreadsheet.getActiveSheet(); // Get Active sheet's object
sh.setName("Name changed!")
}
I found an answer elsewhere
SpreadsheetApp.flush();
tempSheet.setName("MYCHANGEDSHEET");
I lost the link for the original post, but thanks to him/her/them.
So many things are poorly functioning/documented in G-Sheets. SMH.
I'm pretty new to excel or google sheets. The work place, that I work at does not have anything stream lined.
I'm trying to create my own work book that I can refresh everyday I log in so that I can have a list of things that I need to work on for that day.
One of the functions that I would like to have is, whenever a new sheet is shared with me on Google Sheets, I want the URL for that sheet to populate in one of the cells in my workbook automatically and arranged based on timestamp.
I was trying to search for this on Google, but I read that: shared with me docs are not stored anywhere specifically.
Any help or pointing me in the right direction is highly appreciated.
It is easy to fetch the files that have been shared with you. For that, you can simply call the Drive API's Files: list method specifying in the q parameter the sharedWithMe attribute.
Afterwards, you can use the SpreadsheetApp class to gather a spreadsheet and insert data into it. In this case, you can simply make several calls of apendRow() to insert the results.
Finally, properties can be used to store the status of the script (last date checked), so that it can know where to resume from. In this case below, we'll be saving the date in the LAST_DATE property.
Code.gs
var SPREADSHEET_ID = 'YOUR_SPREADSHEET_ID';
var SHEET_NAME = 'YOUR_SHEET_NAME';
function myFunction() {
var sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
var lastDate = new Date(PropertiesService.getScriptProperties().getProperty('LAST_DATE'));
var currentDate = new Date();
var files = getFiles(lastDate);
for (var i=0; i<files.length; i++) {
var row = [
new Date(files[i].sharedWithMeDate),
files[i].title,
files[i].alternateLink,
files[i].sharingUser.emailAddress,
files[i].owners.map(getEmail).join(', ')];
sheet.appendRow(row);
}
console.log('lastDate: %s, currentDate: %s, events added: %d', lastDate, currentDate, files.length);
PropertiesService.getScriptProperties().setProperty('LAST_DATE', currentDate.toISOString());
}
function getEmail(user) {
return user.emailAddress;
}
function getFiles(lastSharedDate) {
var query = "sharedWithMe and mimeType = 'application/vnd.google-apps.spreadsheet'";
var res = Drive.Files.list({
q: query,
orderBy: "sharedWithMeDate desc",
fields: "*",
pageSize: 1000
});
// `query` parameter cannot compare sharedWithMeDate, so we do it afterwards
return res.items.filter(function (i) {
return (new Date(i.sharedWithMeDate) > lastSharedDate);
}).reverse();
}
You can set up the script to be ran periodically (i.e once a day, or more in case you'd need it) using Time-driven triggers.
I have a lot of named ranges in my spreadsheet and time to time I need to delete all of them and create new one. In past I did this by deleting worksheet but recently I've discovered that this operation is not deleting named ranges. So Ive tried to use Class NamedRanges and list trough them by name on second row and to remove them one by one but it doesn't work here is what I tried:
function CellNamerRemove()
{
// the purpose of the CellNamerRemove function is to automatically remove all range names the complete vertical CellRanges
// for each column that has a 'header' in the sheet called 'RawData'. The Quality purpose is to force
// Named-Links only to exist in referencing the raw data from the Starccm+ files
// get a reference to the RawData Spreadsheet
var thisSheetString = "RawData";
var maxRows = SpreadsheetApp.getActiveSheet().getMaxRows();
var lastColumn = SpreadsheetApp.getActiveSheet().getLastColumn();
// loop from 1st column ie 1 to lastColumn.
for(thisColumn = 1; thisColumn <= lastColumn;thisColumn++)
{
var thisName = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(thisSheetString).getRange(2, thisColumn, 1, 1).getValue();
var ss = SpreadsheetApp.getActiveSpreadsheet();
// ss.setNamedRange(trim(thisName), thisRange);
ss.getRangeByName(thisName).remove();
}
}
Can you help me with?
actually I prepared and ran this script which helped me remove ALL named ranges.
function removeNamedRanges(){
var namedRanges = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getNamedRanges();
for(i=0;i<namedRanges.length;i++){
namedRanges[i].remove();
}
}
The problem is in this line:
ss.getRangeByName(thisName).remove();
It should be:
ss.removeNamedRange(thisName);
I'm trying to create a dynamic HYPERLINK formula that will automatically create the link based on the sheet name in Column A, but I'm not sure how (or if it's possible) to get the URL of the sheet based on the name.
Here's the setup:
Single Google Spreadsheet with multiple tabs
Tab names: 1500, 1501, 1502, Consolidated
On the Consolidated tab, I have two columns: Column A is the Sheet Name, and Column B is a HYPERLINK formula, that when clicked should open the corresponding sheet.
Is there a way to programmatically get the URL for the sheet based on the sheet name in Column A? Perhaps I could use a script to populate Column C with the URL, then use the following formula: =HYPERLINK(C2,A2)?
Thanks for the help!
Surprised to see this as a top search on Google but with no answer.
Anyway, here's the method I found that works for me: combine Hyperlink with values from a different column using the &, a basic example is shown below:
If you are trying to automatically generate direct URL's to specific sheets based on their name, and do not want to use scripts, you are out of luck. Currently, the only way to link directly to specific sheets is by appending the correct gid number to the spreadsheet URL. A gid must be either copied manually from the active sheet's URL, or automatically extracted with a custom function, created using scripts.
Since you're open to using scripts, it looks like i found a detailed tutorial of how to do this. https://www.benlcollins.com/spreadsheets/index-sheet/
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Index Menu')
.addItem('Create Index', 'createIndex')
.addItem('Update Index', 'updateIndex')
.addToUi();
}
// function to create the index
function createIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
// check if sheet called sheet called already exists
// if no index sheet exists, create one
if (ss.getSheetByName('index') == null) {
var indexSheet = ss.insertSheet('Index',0);
}
// if sheet called index does exist, prompt user for a different name or option to
cancel
else {
var indexNewName = Browser.inputBox('The name Index is already being used,
please choose a different name:', 'Please choose another name',
Browser.Buttons.OK_CANCEL);
if (indexNewName != 'cancel') {
var indexSheet = ss.insertSheet(indexNewName,0);
}
else {
Browser.msgBox('No index sheet created');
}
}
// add sheet title, sheet names and hyperlink formulas
if (indexSheet) {
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
}
// function to update the index, assumes index is the first sheet in the workbook
function updateIndex() {
// Get all the different sheet IDs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var indexSheet = sheets[0];
var namesArray = sheetNamesIds(sheets);
var indexSheetNames = namesArray[0];
var indexSheetIds = namesArray[1];
printIndex(indexSheet,indexSheetNames,indexSheetIds);
}
// function to print out the index
function printIndex(sheet,names,formulas) {
sheet.clearContents();
sheet.getRange(1,1).setValue('Workbook Index').setFontWeight('bold');
sheet.getRange(3,1,names.length,1).setValues(names);
sheet.getRange(3,2,formulas.length,1).setFormulas(formulas);
}
// function to create array of sheet names and sheet ids
function sheetNamesIds(sheets) {
var indexSheetNames = [];
var indexSheetIds = [];
// create array of sheet names and sheet gids
sheets.forEach(function(sheet){
indexSheetNames.push([sheet.getSheetName()]);
indexSheetIds.push(['=hyperlink("#gid='
+ sheet.getSheetId()
+ '","'
+ sheet.getSheetName()
+ '")']);
});
return [indexSheetNames, indexSheetIds];
}