I cannot find the way to properly simplify the nested loops to build an array of values and data validations and then set them all in the sheet in a single call to the server.
Is it even possible ??
function onEdit(){
testValidation()
}
function testValidation() {
var sheet = SpreadsheetApp.getActiveSheet();
var source = SpreadsheetApp.getActive().getRange('A3:J4').getValues()
var destination = SpreadsheetApp.getActive().getRange('M3:V4');
destination.clearDataValidations();
var validationRule = SpreadsheetApp.newDataValidation().requireCheckbox().build(); // checkbox
for(var r = 0; r <= source.length - 1; r++) {
for(var c = 0; c <= source[0].length - 1; c++) {
if(source[r][c] ==="" ){
sheet.getRange(r + 3,c + 14).clearDataValidations().setValue(null)
}else{
sheet.getRange(r + 3,c + 14).setDataValidation(validationRule).setValue("true")
}
}
}
}
Link to shared spreadsheet :
https://docs.google.com/spreadsheets/d/1fyFPIssp3zUjRmWxU9LqHvpowH8SHdMQYizNOZ3xKsA/edit?usp=sharing
In your situation, how about the following modified script?
Modified script 1:
function testValidation() {
var check = SpreadsheetApp.newDataValidation().requireCheckbox().build();
var sheet = SpreadsheetApp.getActiveSheet();
var source = sheet.getRange('A3:J4').getValues();
var values = source.map(r => r.map(c => c != "" ? check : null));
sheet.getRange('M3:V4').clearContent().setDataValidations(values).check();
}
In this modification, the checkboxes and the clear are set by setDataValidations.
I thought that this method might be low process cost.
Modified script 2:
function testValidation() {
// Ref: https://stackoverflow.com/a/21231012/7108653
const columnToLetter = column => {
let temp,
letter = "";
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
};
var sheet = SpreadsheetApp.getActiveSheet();
var source = sheet.getRange('A3:J4').getValues();
var rangeList = source.flatMap((r, i) => r.flatMap((c, j) => c != "" ? `${columnToLetter(j + 14)}${i + 3}` : []));
sheet.getRange('M3:V4').clearDataValidations().setValue(null);
if (rangeList.length == 0) return;
sheet.getRangeList(rangeList).insertCheckboxes().check();
}
I thought that the cells of M3:V4 can be cleared using sheet.getRange('M3:V4').clearDataValidations().setValue(null).
In this modification, the checkboxes are put using insertCheckboxes() method of Class RangeList.
References:
insertCheckboxes()
setDataValidations()
Related
I am trying to search column E for a cell starting with "X". I then want to move that entire row up to the top.
This is what I've created so far, using IndexOf:
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var Today = spreadsheet.getSheetByName("Today");
var TodayList = Today.getRange('E:E').getValues();
var i = TodayList.indexOf("X", 0);
Today.moveRows(Today.getRow(i), 1);
In your situation, how about the following modification?
In the case of Array.prototype.indexOf(), the values cannot be directly checked from the 2-dimensional array. But, in your situation, I thought that the 1st character can be directly checked using the index as follows.
Modified script:
function myFunction() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var Today = spreadsheet.getSheetByName("Today");
var TodayList = Today.getRange('E1:E' + Today.getLastRow()).getValues();
TodayList.forEach(([e], i) => {
if (e[0] == "X") {
var row = i + 1;
Today.moveRows(Today.getRange(`${row}:${row}`), 1);
}
});
}
When this script is run, the values are retrieved from column "E". And, each cell value is checked from the retrieved values. When the 1st character of the cell value is "X", the row is moved to the 1st row.
In this modification, the lower rows are moved to the upper row. If you want to do this with the reverse, please modify it as follows.
From
TodayList.forEach(([e], i) => {
if (e[0] == "X") {
var row = i + 1;
Today.moveRows(Today.getRange(`${row}:${row}`), 1);
}
});
To
var len = TodayList.length;
var offset = 0;
TodayList.reverse().forEach(([e], i) => {
if (e[0] == "X") {
var row = len - i + offset;
Today.moveRows(Today.getRange(`${row}:${row}`), 1);
offset++;
}
});
References:
forEach()
moveRows(rowSpec, destinationIndex)
Find X rows and move to top
function funko() {
const ss = SpreadsheetApp.getActive();
const tsh = ss.getSheetByName("Today");
const tvs = tsh.getRange(1, 1, tsh.getLastRow(), tsh.getLastColumn()).getValues();
let a = [];
let d = 0;
tvs.forEach((r, i) => {
if (r[4] == "X") {
a.push(r)
tsh.deleteRow(i + 1 - d++);
}
});
tsh.insertRowsBefore(1,a.length)
a.reverse();
tsh.getRange(1,1,a.length,a[0].length).setValues(a);
}
function getNamedRange( e ) {
const sheet = SpreadsheetApp.getActiveSheet();
const activeRange = e.range;
const namedRange = sheet.getNamedRange( activeRange.getA1Notation() );
//alert named range
SpreadsheetApp.getUi().alert( namedRange );
return namedRange;
}
I have tried multiple ways of doing this to no avail.
Main goal: get the name of the named range where the edited cell is found
So if A1:C5 was a named range of "firstRange"
and I edited cell A2, the onEdit(e) would run getNamedRange(e) and alert "firstRange"
I have tried getName() and all sorts of combos using the reference section
Google Reference Link
First, when I saw this question and Programmatically test if a Google Sheet cell is in a named range, also I thought that this might be the same situation. But, I noticed that in my answer, the intersection ranges between the specific range and the specific named range are retrieved. I thought that the basic method is the same. So in order to use my answer for this question, it is required to modify a little. So in this answer, I would like to propose the sample script for achieving the goal by modifying it.
Sample script 1:
When this sample script is modified for your script, it becomes as follows.
function getNamedRange(e) {
var inputRange = e.range;
var columnToLetter = function (column) { // <--- https://stackoverflow.com/a/21231012/7108653
var temp, letter = '';
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
};
var res = [];
var result = [];
var sheet = SpreadsheetApp.getActiveSheet();
var namedRanges = sheet.getNamedRanges();
for (var i = 0; i < namedRanges.length; i++) {
var nr = namedRanges[i];
// Retrieve a1Notations from "inputRange".
var iStartRow = inputRange.getRow();
var iEndRow = iStartRow + inputRange.getNumRows() - 1;
var iStartColumn = inputRange.getColumn();
var iEndColumn = iStartColumn + inputRange.getNumColumns() - 1;
var irA1Notations = [];
for (var j = iStartRow; j <= iEndRow; j++) {
var temp = [];
for (var k = iStartColumn; k <= iEndColumn; k++) {
temp.push(columnToLetter(k) + j);
}
Array.prototype.push.apply(irA1Notations, temp);
}
// Retrieve a1Notations from "myNamedRange".
var namedRange = nr.getRange();
var nStartRow = namedRange.getRow();
var nEndRow = nStartRow + namedRange.getNumRows() - 1;
var nStartColumn = namedRange.getColumn();
var nEndColumn = nStartColumn + namedRange.getNumColumns() - 1;
var nrA1Notations = {};
for (var j = nStartRow; j <= nEndRow; j++) {
for (var k = nStartColumn; k <= nEndColumn; k++) {
nrA1Notations[columnToLetter(k) + j] = null;
}
}
// Retrieve intersection ranges.
result = irA1Notations.filter(function (e) { return nrA1Notations.hasOwnProperty(e) });
if (result.length > 0) {
res.push(nr.getName())
}
}
if (res.length == 0) return;
SpreadsheetApp.getUi().alert(res.join(","));
}
Sample script 2:
In this case, I thought that the following simple script might be able to be used.
function getNamedRange(e) {
const range = e.range;
const sheet = SpreadsheetApp.getActiveSheet();
const r = sheet.getNamedRanges().filter(r => {
const temp = r.getRange();
const startRow = temp.getRow();
const endRow = startRow + temp.getNumRows();
const startCol = temp.getColumn();
const endCol = startCol + temp.getNumColumns();
return (range.rowStart >= startRow && range.rowStart <= endRow && range.columnStart >= startCol && range.columnStart <= endCol) ? true : false;
});
if (r.length == 0) return;
SpreadsheetApp.getUi().alert(r.map(f => f.getName()).join(","));
}
Note:
When you edit a cell, when the edited cell is included in the named range, a dialog is opened. And, you can see the name of the named range.
From this question, it seems that you are using getNamedRange as the installable OnEdit trigger. In the above scripts, you can also use the simple trigger. So you can also modify the function name from getNamedRange to onEdit.
In your script, return namedRange; is used. But when getNamedRange is run using the installable OnEdit trigger, I thought that return namedRange; is not used.
Reference:
Related thread.
Programmatically test if a Google Sheet cell is in a named range
function test() {
var ss1 = SpreadsheetApp.getActiveSpreadsheet();
var ss = ss1.getActiveSheet();
var only = ['AutoGR', 'Sheet2', 'Sheet3', 'Sheet4'];
if (only.indexOf(ss.getName()) == -1) return;
var numRows = SpreadsheetApp.getActiveSheet().getLastRow();
var range;
for (var i = 1; i <= numRows; i++) {
range = ss.getRange('B' + i);
if (range.getValues() == "Crate") {
range.offset(0, 4).setValue(3000);
}
}
for (var i = 1; i <= numRows; i++) {
range = ss.getRange('B' + i);
if (range.getValues() == "Pallet") {
range.offset(0, 4).setValue(4200);
}
}
}
What I am trying to achieve is if values in column B = ‘Crate’ then in the same row under column named Qty put value automatically as 3000, if values in column B = ‘Pallet’ then Qty column automatically gets updated as 4200 but when B=‘close operation’ I have to add qty manually.
Setting Column F in multiple sheets using getValues() and setValues()
function test() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const incl = ['AutoGR', 'Sheet2', 'Sheet3', 'Sheet4'];
const shts = ss.getSheets().filter(sh => ~incl.indexOf(sh.getName()));
shts.forEach(sh => {
let bs = sh.getRange(1,2,sh.getLastRow()).getValues();
let fs = sh.getRange(1,6,sh.getLastRow()).getValues();
bs.forEach((r,i) => {
if(r[0] == "Crate") {
fs[i][0] = 3000;
} else if(r[0] == "Pallet") {
fs[i][0] = 4200;
}
})
sh.getRange(1,6,fs.length,1).setValues(fs);
})
}
If this causes problems in other cells in F then you may be forced to write to F one cell at a time but you'll still get better performance on the read side.
Click here for Sample Sheet
I need a solution that matches a cell value (Sheet1! Q5) to a range in another tab/sheet (NegotiationData! A1:O1) and paste the relevant data fetched from the first sheet under the designated columns of the second sheet under the matched value.
For example, if Sheet1!Q5 matches with the name in NegotiationData! A1 then do the following
Fetch Sheet1! R6 and paste in NegotiationData!A3:A
Fetch Sheet1! Q6 and paste in NegotiationData!B3:B
Fetch Sheet1! Q7 and paste in NegotiationData!C3:C
Also, each time the script runs it should not overwrite data but find the next empty row and paste the values.
I have an incomplete script that I'm trying to achieve the above from my research from various posts but since I'm just a week old to coding I'm not able to go any further than where I have got with the below script.
I'm not finding how to match the value and fetch the relevant data and paste them below the matched value.
Please help!
The Incomplete / Incorrect Script (File Name: NegotiationSubmit)
function submitNegotiation() {
var sh, id, v, estNum, negotiation, negoNotes, i;
sh = SpreadsheetApp.getActive();
id = sh.getSheetByName('Sheet1').getRange('Q5').getValue();
v = sh.getRange('R6').getValue();
estNum = Number(sh.getRange('Q6').getValue().split(" ")[1]);
negoNotes = sh.getRange('Q7').getValue();
negotiation =sh.getSheetByName('NegotiationData').getRange('A1:O');
if(v && estNum) {
negotiation.setValues(negotiation.getValues()
.map(function (r, i) {
if (r[0] == id) {
r[1] = v;
r[2] = estNum;
r[3] = negoNotes;
}
return r;
})
)
}
}
How about this modification?
Modification points :
Retrieve values of "Q5:R7" at once, and the values are converted to the import values.
Use the destructuring assignment for retrieving each value.
Import the converted values using the number of column retrieved by ids[0][i] == id.
Modified script :
function submitNegotiation() {
var id, estNum, v, negoNotes;
var sh = SpreadsheetApp.getActive();
var values = sh.getSheetByName('Sheet1').getRange("Q5:R7").getValues();
[id] = values[0];
[estNum, v] = values[1];
[negoNotes] = values[2];
// estNum = Number(estNum.split(" ")[1]); // If you want to use "estNum = Number(sh.getRange('Q6').getValue().split(" ")[1]);", please use this line.
var sh2 = sh.getSheetByName('NegotiationData');
var ids = sh2.getRange("A1:O1").getValues();
for (var i=0; i<ids[0].length; i++) {
if (ids[0][i] == id) {
sh2.getRange(sh2.getLastRow() + 1, i + 1, 1, 3).setValues([[v, estNum, negoNotes]]);
}
}
}
Note :
I was confused to the following points.
In your script, estNum is Number(sh.getRange('Q6').getValue().split(" ")[1]);. But in your sample spreadsheet, Estimate 1 of cell "Q6" is used.
I commented this in modified script.
In your sample spreadsheet, "Story ID" is 1. But in your script, it's US-001 of cell "R6".
In this modified script, US-001 of cell "R6" was used.
If I misunderstand your question, I'm sorry.
Edit :
function submitNegotiation() {
var id, estNum, v, negoNotes;
var sh = SpreadsheetApp.getActive();
var values = sh.getSheetByName('Sheet1').getRange("Q5:R7").getValues();
[id] = values[0];
[estNum, v] = values[1];
[negoNotes] = values[2];
estNum = Number(estNum.split(" ")[1]); // If you want to use "estNum = Number(sh.getRange('Q6').getValue().split(" ")[1]);", please use this line.
var sh2 = sh.getSheetByName('NegotiationData');
var ids = sh2.getRange("A1:O1").getValues();
for (var i=0; i<ids[0].length; i++) {
if (ids[0][i] == id) {
var temp = sh2.getRange(1, i + 1, sh2.getLastRow(), 3).getValues();
for (var j=temp.length-1; j>=0; j--) {
if (temp[j].join("") != "") {
sh2.getRange(j + 2, i + 1, 1, 3).setValues([[v, estNum, negoNotes]]);
break;
}
}
}
}
}
I realize that this does not resemble your code. Sorry about that. I'm learning too. But I'm putting it up anyway to provide an alternative method that includes finding the last row of the appropriate column...
function submitNegotiation() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Sheet1');
var negotiationData = ss.getSheetByName('NegotiationData');
// Sheet1 variables
var user = sheet1.getRange('Q5').getValue();
var storyId = Number(sheet1.getRange('R6').getValue().split("-")[1]);
var estimateNum = sheet1.getRange('Q6').getValue();
var note = sheet1.getRange('Q7').getValue();
var pointers = [storyId, estimateNum, note];
// NegotiationData variables
var range = negotiationData.getDataRange().getValues();
var columns = negotiationData.getLastColumn();
var users = negotiationData.getRange(1, 1, 1, columns).getValues();
for(var i = 0; i < columns; i++) {
// match user with users to get column number
if(users[0][i] == user) {
var col = negotiationData.getRange(1, i + 1).getColumn();
// count rows in col
var rowCount = 1;
for(var i = 1; i < range.length; i++) {
if (range[i][col - 1] != "") {
rowCount++;
}
}
// assign pointers
var newRow = rowCount + 1;
for(var j = 0; j < pointers.length; j++) {
negotiationData.getRange(newRow, col, 1, 1).setValue(pointers[j]);
col++;
}
}
}
}
I'm trying to write a function for Google Spreadsheet that locates the first and last column of a group. It then hides the group, or shows it if it's already hidden.
However, I haven't been able to find a way to determine whether a column is hidden or not. I haven't been able to find anything anything on Google's Class Sheet page https://developers.google.com/apps-script/reference/spreadsheet/sheet, and I haven't found an equivalent to Excel's .hidden
getColumnWidth(column) returns the unhidden column width even when it's hidden.
Here's my code:
function hideShowColumns(startCol, endCol) {
//endCol is one column past the last data set that should be hidden
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Transposed Data");
//import the data from the Column Headers
var colHeaderData = sheet.getRange(1, 1, 2, sheet.getMaxColumns()).getValues();
var startColNum = 0;
var endColNum = 0;
// This section searches for the column names in the header rows and returns their column number
for (var i =0; i < 2; ++i) {
for (var j = 0; j < colHeaderData[0].length; ++j) {
if (colHeaderData[i][j] == startCol)
startColNum = j;
if (colHeaderData[i][j] == endCol)
endColNum = j;
}
}
//This is the wrong command getColumnWidth doesn't change if column is hidden
if (sheet.getColumnWidth(startColNum + 1) != 0) {
sheet.hideColumns(startColNum + 2, endColNum - startColNum - 1);
Logger.log(sheet.getColumnWidth(startColNum + 2));
return;
}
//This is the wrong command getColumnWidth doesn't change if column is hidden
if (sheet.getColumnWidth(startColNum + 1) == 0) {
for (var j = startColNum + 1; j < endColNum - 1; ++j) {
sheet.unhideColumn(j);
Logger.log(sheet.getColumnWidth(startColNum + 2));
}
return;
}
}
Thanks for the help!
The new (as of 2018) api for this is: isColumnHiddenByUser(columnPosition)
Returns whether the given column is hidden by the user.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// Columns start at 1
Logger.log(sheet.isColumnHiddenByUser(1));
Unfortunately there is no Google Apps Script method that will return whether a column or row is hidden or not. You might like to star the issue opened for it, as a way of a. receiving updates about the issue, and b. "signing the petition", so to speak.
https://code.google.com/p/google-apps-script-issues/issues/detail?id=195&q=hidden%20column&colspec=Stars%20Opened%20ID%20Type%20Status%20Summary%20Component%20Owner
A workaround. Create 2 rows. The first must always have a value and the second has a set of formulas. These 2 rows look like this:
| A | B | C |
---------------------------------------------------------------------------------
1 | 1 | 1 | 1 |
2 | =NOT(SUBTOTAL(103, A1)) | =NOT(SUBTOTAL(103, B1)) | =NOT(SUBTOTAL(103, C1)) |
SUBTOTAL returns a subtotal using a specified aggregation function. The first argument 103 defines the type of function used for aggregation. The second argument is the range to apply the function to.
3 means COUNTA and counts the number of values in the range
+100 means ignore hidden cells in the range.
The result of SUBTOTAL with a range of 1 cell will be 0 when the cell is hidden and 1 when the cell is shown. NOT inverts it.
Now your can read the second row with your script to know if a column is hidden.
Here's the transposed question and answer: https://stackoverflow.com/a/27846202/1385429
Sorry, I also could not find a way and stumbled upon this stack overflow.
But I might as well share this script somewhere.
I use the first column as a place holder for a -- or || value to tell if its hidden or shown. (Not the best but its all I could seem to find)
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name: "Toggle Rows",
functionName: "toggleRows"
},{
name: "Hide Rows",
functionName: "hideRows"
},{
name: "Show Rows",
functionName: "showRows"
}];
sheet.addMenu("Script", entries);
};
function toggleRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var maxRows = sheet.getMaxRows();
var r = sheet.getRange(1, 1, maxRows+1);
var values = r.getValues();
var hideRanges = [];
var showRanges = [];
var toggleValue = null;
var startRow = null;
var tmp;
var len = values.length;
var i;
for (i = 0; i < len; i++) {
tmp = values[i][0];
if (startRow === null && (tmp === '--' || tmp === '||')) {
startRow = i + 1;
toggleValue = tmp;
} else if (startRow !== null && tmp !== toggleValue) {
if (toggleValue === '--') {
hideRanges.push([startRow, (i + 1) - startRow]);
} else {
showRanges.push([startRow, (i + 1) - startRow])
}
if (tmp === '--' || tmp === '||') {
startRow = i + 1;
toggleValue = tmp;
} else {
startRow = null;
}
}
}
var customRange = null;
var range = null;
i = hideRanges.length;
while (i--) {
customRange = hideRanges[i];
range = sheet.getRange(customRange[0], 1, customRange[1]);
range.setValue('||');
sheet.hideRows(customRange[0], customRange[1]);
}
i = showRanges.length;
while (i--) {
customRange = showRanges[i];
range = sheet.getRange(customRange[0], 1, customRange[1]);
range.setValue('--');
sheet.showRows(customRange[0], customRange[1]);
}
};
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var maxRows = sheet.getMaxRows();
var r = sheet.getRange(1, 1, maxRows+1);
var values = r.getValues();
var startRow = null;
var tmp;
var len = values.length;
var i;
for (i = 0; i < len; i++) {
tmp = values[i][0];
if (startRow === null && (tmp === '--' || tmp === '||')) {
startRow = i + 1;
} else if (startRow !== null && (tmp !== '--' && tmp !== '||')) {
var numRows = (i + 1) - startRow;
sheet.getRange(startRow, 1, numRows).setValue('||');
sheet.hideRows(startRow, numRows);
startRow = null;
}
}
};
function showRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var maxRows = sheet.getMaxRows();
var r = sheet.getRange(1, 1, maxRows+1);
var values = r.getValues();
var startRow = null;
var tmp;
var len = values.length;
var i;
for (i = 0; i < len; i++) {
tmp = values[i][0];
if (startRow === null && (tmp === '--' || tmp === '||')) {
startRow = i + 1;
} else if (startRow !== null && (tmp !== '--' && tmp !== '||')) {
var numRows = (i + 1) - startRow;
sheet.getRange(startRow, 1, numRows).setValue('--');
sheet.showRows(startRow, numRows);
startRow = null;
}
}
};
See here for any updates: https://gist.github.com/LiamKarlMitchell/81cef19a530261c4af93
As of 2018, Google hasn't added row/col visibility methods to the Sheets API yet. Now, late 2018, they created an API for this.
That's sad but I found another way:
When a row is the last one visible, you cannot hide it (same with columns). Google Spreadsheet throws an error and shows you a message. So, when a script function hides every row except the one we want to check, if it fails, our row was hidden. If the run is successful, it means that our row was visible.
Please be advised that this work-around is too hackerish to be used in a performance sensitive script.
Usage examples:
var sheet = SpreadsheetApp.getActive().getActiveSheet()
// Is the tenth row hidden?
isRowHidden(sheet.getRange('B10'))
// Is column B hidden?
isColumnHidden(sheet.getRange('B10'))
// Is cell B10 visible? (not in a hidden row and/or column)
!(isCellHidden(sheet.getRange('B10')))
Code
/**
* Takes the first row of a range and checks whether is hidden or not.
* Second parameter is an optional sheet. Defaults to the active sheet.
* #param {range} row
* #param {sheet} [sheet]
* #returns {boolean} True if row is hidden, false if it is visible.
*/
function isRowHidden (row, optionalSheet) {
var ss = SpreadsheetApp.getActive()
var sheet = optionalSheet || ss.getActiveSheet()
SpreadsheetApp.setActiveSheet(sheet)
var dup = ss.duplicateActiveSheet()
SpreadsheetApp.setActiveSheet(sheet)
var isHidden = false
var rowIndex = row.getRow()
var numRows = dup.getMaxRows()
if (numRows === 1) {
ss.deleteSheet(dup)
return false
}
try {
if (rowIndex === numRows ) {
dup.hideRows(1, numRows - 1)
} else if (rowIndex === 1) {
dup.hideRows(rowIndex + 1, numRows - 1)
} else {
dup.hideRows(1, rowIndex - 1)
dup.hideRows(rowIndex + 1, numRows - rowIndex)
}
isHidden = false
} catch (e) {
isHidden = true
} finally {
ss.deleteSheet(dup)
}
return isHidden
}
/**
* Takes the first column of a range and checks whether is hidden or not.
* Second parameter is an optional sheet. Defaults to the active sheet.
* #param {range} column
* #param {sheet} [sheet]
* #returns {boolean} True if column is hidden, false if it is visible.
*/
function isColumnHidden (col, optionalSheet) {
var ss = SpreadsheetApp.getActive()
var sheet = optionalSheet || ss.getActiveSheet()
SpreadsheetApp.setActiveSheet(sheet)
var dup = ss.duplicateActiveSheet()
SpreadsheetApp.setActiveSheet(sheet)
var isHidden = false
var colIndex = col.getColumn()
var numCols = dup.getMaxColumns()
if (numCols === 1) {
ss.deleteSheet(dup)
return false
}
try {
if (colIndex === numCols ) {
dup.hideColumns(1, numCols - 1)
} else if (colIndex === 1) {
dup.hideColumns(colIndex + 1, numCols - 1)
} else {
dup.hideColumns(1, colIndex - 1)
dup.hideColumns(colIndex + 1, numCols - colIndex)
}
isHidden = false
} catch (e) {
isHidden = true
} finally {
ss.deleteSheet(dup)
}
return isHidden
}
/**
* Takes the first cell of a range and checks whether is hidden or not.
* Second parameter is an optional sheet. Defaults to the active sheet.
* #param {range} cell
* #param {sheet} [sheet]
* #returns {boolean} True if cell is hidden, false if it is visible.
*/
function isCellHidden (cell, optionalSheet) {
var isHidden = isColumnHidden(cell, optionalSheet) || isRowHidden(cell, optionalSheet)
return isHidden
}
PS: Code follows JS Standard Style.