7

我正在尝试为 Google 电子表格编写一个函数,用于定位组的第一列和最后一列。然后它会隐藏该组,或者如果它已经隐藏则显示它。

但是,我还没有找到一种方法来确定一列是否隐藏。我在 Google 的课程表页面https://developers.google.com/apps-script/reference/spreadsheet/sheet上找不到任何东西,而且我还没有找到与 Excel 的 .hidden 等效的东西

getColumnWidth(column) 返回未隐藏的列宽,即使它被隐藏。

这是我的代码:

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;
  }
}

谢谢您的帮助!

4

5 回答 5

9

新的(截至 2018 年)API 是:isColumnHiddenByUser(columnPosition)

返回给定列是否被用户隐藏。

var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];

// Columns start at 1
Logger.log(sheet.isColumnHiddenByUser(1));
于 2019-01-31T20:46:59.190 回答
5

不幸的是,没有 Google Apps 脚本方法可以返回列或行是否隐藏。您可能想为它打开的问题加注星标,作为一种方式。接收有关该问题的更新,以及 b. “签署请愿书”,可以这么说。

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

于 2013-05-29T22:21:39.763 回答
3

一种解决方法。创建 2 行。第一个必须始终有一个值,而第二个必须有一组公式。这 2 行如下所示:

  |           A             |           B             |            C            |
---------------------------------------------------------------------------------
1 |                       1 |                       1 |                       1 |
2 | =NOT(SUBTOTAL(103, A1)) | =NOT(SUBTOTAL(103, B1)) | =NOT(SUBTOTAL(103, C1)) |

SUBTOTAL使用指定的聚合函数返回小计。第一个参数 103 定义了用于聚合的函数类型。第二个参数是应用函数的范围。

  • 3 表示COUNTA并计算范围内的值的数量
  • +100 表示忽略该范围内的隐藏单元格。

单元格范围为 1的结果SUBTOTAL将在隐藏单元格时为 0,在显示单元格时为 1。NOT反转它。

现在您可以使用脚本读取第二行以了解是否隐藏了列。

这是转置的问题和答案:https ://stackoverflow.com/a/27846202/1385429

于 2015-01-08T17:35:53.733 回答
2

抱歉,我也找不到方法,偶然发现了这个堆栈溢出。但我不妨在某个地方分享这个脚本。

我使用第一列作为 -- 或 || 的占位符 值来判断它是隐藏还是显示。(不是最好的,但它似乎是我能找到的全部)

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;
    }
  }

};

有关任何更新,请参见此处:https ://gist.github.com/LiamKarlMitchell/81cef19a530261c4af93

于 2015-08-22T23:30:18.073 回答
1

截至 2018 年,Google 尚未向 Sheets API 添加行/列可见性方法. 现在,在 2018 年末,他们为此创建了一个 API。

这很可悲,但我找到了另一种方法:

当一行是最后一个可见时,您不能隐藏它(与列相同)。Google 电子表格会引发错误并向您显示一条消息。因此,当脚本函数隐藏除我们要检查的那一行之外的每一行时,如果它失败,我们的行就被隐藏了。如果运行成功,则意味着我们的行是可见的。

请注意,这种变通方法过于骇人听闻,无法在性能敏感的脚本中使用。

使用示例:

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')))

代码

/**
 * 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:代码遵循 JS 标准样式。

JavaScript 样式指南

于 2018-02-02T23:11:16.073 回答