I am trying to count visible columns in a spreadsheet with no luck. I've been trying using SUBTOTAL function but it's applied to hidden/visible rows only. I also tried working with CELL("width") function, but it doesn't return 0 when a cell is hidden
Is there any other option to ignore hidden columns in a count formula?
You can definitely create your own custom function using Google Apps Script.
For example, the following function counts the number of visible columns in your active sheet:
function countVisibleColumns() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet()
var n_cols = sheet.getMaxColumns();
var hidden_cols = []
var cnt = 0;
for (var i=1; i<=n_cols ; i++) {
if ( sheet.isColumnHiddenByUser(i) ){
continue;}
else {cnt +=1} }
Logger.log(cnt)
return cnt;
}
You just need to click on Tools => Script editor and then copy the aforementioned code into a blank script. Then you can directly use the function as a formula in the google sheet like =countVisibleColumns().
See screenshot attached for more information.
I made some 'conditional formatting' in Google Sheets for one sheet but I need to apply to others. There are about 45 tables and I really don't want to copy-paste it. Can anyone help me with that?
A quick solution would be to do the following:
Record a macro of how you apply the conditional formatting on the first sheet
Edit the macro so that it loops through each sheet (see code example below)
Be sure to do this on a copy of the original sheet first in case there are any issues
Code:
function autoConditionalFormat() {
// Counts how many sheets there are
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
numSheets = sheets.length;
// Loop to get name of each tab (sheet)
var tabNames = new Array()
for (var i=0; i<numSheets; i++) tabNames.push( [ sheets[i].getName() ] )
// Loops through each sheet
for (var i = 0; i < numSheets; i++) {
// Applies some conditional formatting to each sheet
SpreadsheetApp.setActiveSheet(ss.getSheetByName(tabNames[i]));
// Insert what your macro recorded here:
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A2').activate();
var conditionalFormatRules = spreadsheet.getActiveSheet().getConditionalFormatRules();
conditionalFormatRules.push(SpreadsheetApp
.newConditionalFormatRule()
.setRanges([spreadsheet.getRange('A2')])
.whenCellNotEmpty()
.setBackground('#B7E1CD')
.build());
spreadsheet.getActiveSheet()
.setConditionalFormatRules(conditionalFormatRules);
}
}
}
if I have a workbook with 20 or so sheets, is there a way I can easily save each one as their own workbook? Is this possible with scripts?
This can be done with a script as follows: (a) get the list of sheets; (b) for each, create a new spreadsheet, naming it after the sheet; (c) copy the sheet there; (d) delete the initial "Sheet1" sheet from the new spreadsheet, so that it doesn't get in the way.
function saveEach() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
var newss = SpreadsheetApp.create(sheets[i].getSheetName());
sheets[i].copyTo(newss);
newss.deleteSheet(newss.getSheets()[0]);
}
}
Reference: SpreadsheetApp
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];
}
Please help.
I want more frequent updates so I want to use gscripts.
I need to retrieve the value of this source:
Filename: Peta Finance
Name Sheet: Data
Key: xxx111xxx
Cell: B15
Target is:
Filename: Finance
Name Sheet: Data1
Key: xxx222xxx
Cell: A2
I try this code, except that they are not working:
function importData() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); //source ss
var sheet = ss.getSheetByName("Finance Peta"); //opens the sheet with your source data
var values = sheet.getRange("C1").getValues(); //gets needed values
var ts = SpreadsheetApp.openById("xxx"); //target ss - paste your key
ts.getSheetByName("Finance").getRange("B15").setValues(values);
}
Funnily enough I asked something similar the other day. My code, edited to match yours is as follows:
function importData() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data1 Key");
var update = 'IMPORTRANGE("XXX","Data Key!B15"); //"XXX" is the spreadsheet key of your source [Peta Finance]
sheet.clear(); //Be careful with this. It clears the whole sheet including formatting. This part might need playing around a bit with
sheet.getRange("A2").setValue(update);
Utilities.sleep(245); //This just gives the set number of milliseconds before it carries out it's next process (not necessarily required if this is only action)
};
I then created a menu which allows me to manually refresh the data, or cell in your case. This is as follows in the same script file:
function onOpen(){
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{name: 'Import Data', functionName: 'importData'}
];
spreadsheet.addMenu('Import', menuItems);
}
You can then add timed triggers to set it to update, although importrange should automatically do it.
To do this click on Resources >> Current Project's Triggers >> set one up >>
Make it as follows >> Run: importData Events: Time-driven >> select the time between updates.