可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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!
回答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
回答2:
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
回答3:
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
回答4:
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.
回答5:
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));