I am trying to create 'buttons' at the top of a spreadsheet, so when clicked the reader can jump around the spreadsheet. Ive created an editorial calendar and would like to be able to jump to different months on the sheet. Is this possible?
You can't add buttons but you can add a custom menu using Google Apps Script:
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#addMenu(String,Object)
You can write a jump script using this Google Apps Script function: https://developers.google.com/apps-script/reference/spreadsheet/sheet#setActiveSelection(Range)
Here is a full working example:
function jumpToJanuary() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// Now fixed cell - here you can search for specified cell value
var range = sheet.getRange("B4");
sheet.setActiveSelection(range);
};
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Jump to January",
functionName : "jumpToJanuary"
}];
sheet.addMenu("Jump Example Menu", entries);
};
Related
My work has a Google Form where different information is inputted. All this information is then automatically put into a Google Sheet. We will call it "All data sheet".
"All data sheet" has multiple sheets in it, one with all of the data and then one for each type of data which needs to be given to different people. One of those is called 'Caretaker'.
I then have a second Google Sheet (example called 'Sorting') that pulls everything from the 'Caretaker' sheet onto 'Import_range'.
This allows the caretaker to see everything that needs fixing with the oldest thing at the top and the newest at the bottom.
The caretaker would like the newest at the top.
I can easily make another sheet (see 'Sorted') that uses the sort function to put the newest at the top.
However, he would also like another column where he can either check a box to show it's done or write an x.
When new data appears, the checked box does not move down.
Is there any way to sort the data but also have an input column which stays with the sorted data?
Link to example.
You have to use Google Apps Script.
Try this:
To start, go to Tools and click Script editor.
Delete the code in Code.gs
Paste the code provided below and save
Refresh your Spreadsheet and Custom Menu will pop up in the Menu
Go To Custom Menu and Click Update Sorted Sheet
First execution will require user's authorization. Once you authorized the script, make sure to rerun the Custom Menu.
The code below will create a Custom Menu in your Spreadsheet. Clicking the custom menu will execute a function that will update the Sorted Sheet and retain its checkbox values.
I also added comments to explain the function of each line in the code.
Code:
function updateSorted() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Import_range");
var sortedSh = ss.getSheetByName("Sorted");
/* Use this if the Import_range is from different spreadsheet
var iSS = SpreadsheetApp.openById("Insert Sheet ID here");
var sh = iSS.getSheetByName("Insert Sheet name here");
and comment the var sh = ss.getSheetByName("Import_range"); above*/
/*
Check if the Sorted Sheet has data.
If true, compare Sorted Sheet and Import_range data
else, copy Import_range data to Sorted Sheet.
*/
if(sortedSh.getLastRow() > 1){
var sData = sortedSh.getRange(2, 1, sortedSh.getLastRow()-1, 5).getValues(); //remove unnecessary data
var sDataFiltered = sData.filter(e => e[4]); //get Date column of Sorted sheet
var sDates = sortedSh.getRange(2, 5, sortedSh.getLastRow()-1, 1).getValues().flat();
var sDatesFiltered = sDates.filter((a) => a); //remove unnecessary data
var importDates = sh.getRange(2, 4, sh.getLastRow()-1, 1).getValues().flat(); //get Date column of Import_range
//convert dates to String format
var arr1 = sDatesFiltered.map( dateString => String(dateString))
var arr2 = importDates.map( dateString => String(dateString))
var difference = arr2.filter(x => !arr1.includes(x)); //get the difference between arr1 and arr2
difference.forEach(dates => {
var index = arr2.indexOf(dates); //get new entry position in Import_range
var newEntry = sh.getRange(index+2, 1, 1, 4).getValues().flat(); //get row data of new entry from Import_range
newEntry.unshift(false); //append false in the beggining of the array
sDataFiltered.push(newEntry); //append new entry to sDataFiltered array
})
var range = sortedSh.getRange(2, 1, sDataFiltered.length, 5);
range.setValues(sDataFiltered); //set the values of Sorted sheet using the sDataFiltered array as data
sortedSh.getRange(2, 1, sDataFiltered.length, 1).insertCheckboxes(); //get the checkbox range and insert checkbox
range.sort({column: 5, ascending: false}); //sort the data by Date column
}else{
var range = sh.getRange(2, 1, sh.getLastRow()-1, 4);
var data = range.getValues();
data.forEach(row => {
row.unshift(false)
})
var sortedRange = sortedSh.getRange(2, 1, data.length, 5);
sortedRange.setValues(data);
sortedSh.getRange(2, 1, data.length, 1).insertCheckboxes();
sortedRange.sort({column: 5, ascending: false});
}
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Custom Menu')
.addItem('Update Sorted Sheet', 'updateSorted')
.addToUi();
}
Examples:
Populating Empty Sorted Sheet:
Updating Import_range sheet, clicking checkboxes and updating Sorted Sheet:
Implementing Time Driven Triggers:
Open your Apps Script project.
At the left, click Triggers alarm.
At the bottom right, click Add Trigger.
Select and configure the type of trigger you want to create.
Click Save.
For time driven, your trigger setup should somehow look like this:
The example trigger above will update the sheet every minute. The down side of using time driven trigger is the quota limit. Gmail accounts are limited to 90 minutes of total runtime. Exceeding quotas will result to errors. See Quotas for Google Services.
Using Buttons: Alternative to Custom Menu
To create a user friendly button in your Sheet
Go to Insert -> Drawing
Draw the desired button shape and style.
Click Save and Close
Move the button to your desired position
Right click, click the 3 vertical dots and select Assign script
Type updateSorted and click OK
Click the button to run
Note: If you decided to use buttons and want to remove the Custom Menu in your sheet, just remove the onOpen function in your Apps Script.
References:
Google Apps Script on Sheets
Custom Menu
Simple Triggers
Class Sheet
Class Range
Class Spreadsheet
Installable Trigger
I want to import data from google spreadsheet to another sheet along with the color which is present in original sheet.
The suggested solution is below:
function onOpen() {
var destination = SpreadsheetApp.getActive(),
sheetName = 'Sheet1';
var previousCopy = destination.getSheetByName(sheetName);
if (previousCopy) previousCopy.setName('Dirty');
}
function getSheetCopy() {
var destination = SpreadsheetApp.getActive();
var dirty = destination.getSheetByName('Dirty');
Logger.log(dirty);
if (!dirty) return;
destination.deleteSheet(dirty);
// Replace sourceId by required identifier,
// and replace sheetName value as required
var sourceId = '1el850cyzxy4PrL2uDhN7Dr9vWNX3cGA5-ks1amAX-Ak',
sheetName = 'Sheet1';
var source = SpreadsheetApp.openById(sourceId);
source.getSheetByName(sheetName).copyTo(destination).setName(sheetName);
}
The idea is to make a full copy (mirror) of the source sheet every time we open a target (destination) spreadsheet. onOpen trigger only marks the previous copy as "Dirty". It has limited AuthMode and can not do updates itself.
First time you should make empty "Sheet1" to get ready for automated updates...
Time triggered getSheetCopy does the main work and removes "Dirty" mark once. Trigger period is 1 minute (minimal). So when open a spreadsheet, you can see if the mirrored sheet is "Dirty" (not updated) or already actual.
I am trying to create a simple Google Script inside of Google Sheets where, once the user runs the function from a custom menu (I have already created that), the user is prompted with a question. I want to place that text answer they provided into a specific cell. Thank you for any help you can provide.
Try this function and modify where necessary.
function setAnswer() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('sheetNameHere');
var cell = sheet.getRange('B2');
var answer = Browser.inputBox('Your question here');
cell.setValue(answer);
}
If you want to specify the cell each time, you can use an inputBox for that, too.
function setAnswer() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
//line above changed to reflect dynamic use of function
var rangeA1 = Browser.inputBox('Please type the cell reference you wish to save your answer in:');
var cell = sheet.getRange(rangeA1);
var answer = Browser.inputBox('Your question here');
cell.setValue(answer);
}
The first column of my spreadsheet has dropdown lists in each cell with the options "yes" and "no".
If "yes" is selected, I want to enable the cell in the same row, next column with another dropdown list with options "red" and "blue". If "no" is selected, then the next cell should remain disabled.
So far I have tried the data validation menu with custom formula is set to =if(B2="Yes", "red", "blue") in cell B3, but it doesn't work.
How can I do this?
You can do this with onEdit and script like this:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var s=ss.getActiveSheet()
var col=e.range.getColumn()
var ro=e.range.getRow()
var nota=e.range.getA1Notation()
if(col==1){
var val=e.range.getValue()
if(val=="No"){
s.getRange(ro,2,1,1).setDataValidation(null)
}
else{
s.getRange(ro,2,1,1).clearContent()
var cell = s.getRange(ro,2,1,1);
var rule =
SpreadsheetApp.newDataValidation().requireValueInList(['Red', 'Blue']).build();
cell.setDataValidation(rule);
}}}
Here is a share example. Copy and try it.
https://docs.google.com/spreadsheets/d/1wHA1Rz9U9dr4n8DntLvZWPe4izck7xgi3ygUpx-uNmo/edit?usp=sharing
I have two sheets. One is source and other destination.
I have used following script from another discussion:
Paste Special Values (google-apps-script)
With minor amendments, the script is shown below:
function moveValuesOnly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange('sourceSheet!A2:M38');
source.copyTo(ss.getRange('destinationSheet!B2'), {contentsOnly: true});
}
It works fine and taking values from the source file and paste it in destination.
I need that the function could be repeated automatically for every new entry in the source
After the first transfer to destination, I refresh the cells at source and enter new data.
I want that it should also move to new cell in destination instead of overwriting the previous entries. Every next entry should be stored in new column(or row) in the destination.
I'm not sure what your data looks like, whether you're wanting to clear out the source sheet each time or whether the data is coming from a form. In any case this function will determine where your last row of data is on the destination sheet and pop the source data (which is always A2:M38?) straight below there.
function moveValuesOnly() {
var ss = SpreadsheetApp.getActive().getSheetByName('Source sheet name');
var ds = SpreadsheetApp.getActive().getSheetByName('destination sheet name');
var source = ss.getRange('sourceSheet!A2:M38');
var dslen = ds.getDataRange().getLastRow();
var i = dslen + 1
source.copyTo(ds.getRange("B" + i), {contentsOnly: true});
}