How to sorting sheet by cell's background color - 有代码,但是看不懂报错

How to sort sheet by cell's background color - have the code, but don't understand the error

我正在努力完成这个项目,但最后一部分现在让我耽搁了 2 天。我有一个 Google Sheet,非常简单,我只需要它按单元格的背景颜色自动排序。我有 7 种颜色需要按此顺序排列,并且我尝试使用 Sort Range Plus 扩展,它确实有效,但我不知道如何在编辑 sheet 时使用预先确定的参数调用它。然后我找到了一个 Apps 脚本,它应该完全满足我的需要,我想我首先启用了 Sheets API,就像论坛上说的那样,我必须在我相信有两个地方,但是当我 运行 以下代码时,我仍然在第 25/26 行出现错误:

Error: Exception: Object is not of type RgbColor.
(anonymous) @ SortByColor.gs:26
(SortByColor) @ SortByColor.gs:25

我不确定如何解决这个问题,因为它 运行s 并获取颜色然后出错。我以前没有用过javascript,所以我希望更熟悉的人可以帮助我。也许问题是我错误地启用了它还是什么?如果其他人对相同的代码没有问题,我想我可能做错了。这也是我第一次使用 Google Apps 脚本。

这是我一直在尝试的代码。请原谅注释掉的部分 - 我正在使用我在 2 个不同线程中找到的代码。

function SortByColor() {
    const sheetName = "Patient Progress"; // Please set the sheet name.
    //const a1Notation = "A1:A1099"; // Please set the sort range as a1Notation.

    // 1. Retrieve the background colors from the cells.
    const ss = SpreadsheetApp.getActiveSpreadsheet();
    const sheet = ss.getSheetByName(sheetName);
    //const range = sheet.getRange(a1Notation);
    var range = sheet.getRange(2, 1, ss.getLastRow(), ss.getLastColumn());
    const backgrounds = range.getBackgroundObjects();

    // 2. Create the request body for using the batchUpdate method of Sheets API.
    /** 
    const startRow = range.getRow() - 1;
    const startColumn = range.getColumn() - 1;
    const srange = {
    sheetId: sheet.getSheetId(),
    startRowIndex: startRow,
    endRowIndex: startRow + range.getNumRows(),
    startColumnIndex: startColumn,
    endColumnIndex: startColumn + range.getNumColumns(),
    };**/

    const sortColorOrder = ['#ea9999', '#f9cb9c', '#fff2cc', 'd9ead3', '#cfe2f3', '#d9d2e9', 
    '#fffff' ]; // This means that "red", "orange", "yellow", "green", "blue", "purple", 
    "white" in order.
    const backgroundColorObj = backgrounds.reduce((o, [a]) => {
      const rgb = a.asRgbColor()
      return Object.assign(o, { [rgb.asHexString()]: { red: rgb.getRed() / 255, green: 
        rgb.getGreen() / 255, blue: rgb.getBlue() / 255 } })
      }, {});
    const backgroundColors = sortColorOrder.map(e => backgroundColorObj[e]);

    const requests = [
      {
    sortRange: {
      range: srange,
      sortSpecs: [{ dimensionIndex: 0, sortOrder: "ASCENDING" }],
      },
    },
    {
    sortRange: {
      range: srange,
       //sortSpecs: [{backgroundColor: '#d9d2e9'}, {backgroundColor: '#d9ead3'}, 
      {backgroundColor: '#fff2cc'}]
      sortSpecs: backgroundColors.map((rgb) => ({ backgroundColor: rgb })),
    },
    },
    ];

    // 3. Request to Sheets API using the request body.
    Sheets.Spreadsheets.batchUpdate({ requests: requests }, ss.getId());
}

从你的展示脚本来看,我觉得你可能用到了我的答案 and ,下面的修改怎么样?

修改点:

  • 在您的脚本中,srange 未声明。
  • "white" in order.{backgroundColor: '#fff2cc'}] 行用作脚本行而不是注释。
  • 您设置了 '#fffff' 的十六进制颜色。在这种情况下,我认为它是 '#ffffff'。如果使用'#fffff',则白色背景不排序。请注意这一点。 关于var range = sheet.getRange(2, 1, ss.getLastRow(), ss.getLastColumn());,Rubén的评论已经提到了。

将这些点反映到示例脚本中,就变成了下面的样子。

我无法知道您实际电子表格中单元格的背景颜色。所以在这个修改中,我假设你在“A”列使用 ['#ea9999', '#f9cb9c', '#fff2cc', 'd9ead3', '#cfe2f3', '#d9d2e9', '#ffffff'] 的背景颜色。请注意这一点。

修改后的脚本:

请再次确认 Sheets API 是否已经启用。

function myFunction() {
  const sheetName = "Patient Progress"; // Please set the sheet name.

  // 1. Retrieve the background colors from the cells.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName(sheetName);
  const range = sheet.getRange(2, 1, ss.getLastRow() - 1, ss.getLastColumn());
  const backgrounds = range.getBackgroundObjects();

  // 2. Create the request body for using the batchUpdate method of Sheets API.
  const sortColorOrder = ['#ea9999', '#f9cb9c', '#fff2cc', 'd9ead3', '#cfe2f3', '#d9d2e9', '#ffffff']; // This means that "red", "orange", "yellow", "green", "blue", "purple", "white" in order.
  const backgroundColorObj = backgrounds.reduce((o, [a]) => {
    const rgb = a.asRgbColor();
    const hex = rgb.asHexString();
    return Object.assign(o, { [hex == "#ffffffff" ? "#ffffff" : hex]: { red: rgb.getRed() / 255, green: rgb.getGreen() / 255, blue: rgb.getBlue() / 255 } });
  }, {});
  const backgroundColors = sortColorOrder.map(e => backgroundColorObj[e] || "").filter(String);
  if (backgroundColors.length == 0) return;

  const startRow = range.getRow() - 1;
  const startColumn = range.getColumn() - 1;
  const srange = {
    sheetId: sheet.getSheetId(),
    startRowIndex: startRow,
    endRowIndex: startRow + range.getNumRows(),
    startColumnIndex: startColumn,
    endColumnIndex: startColumn + range.getNumColumns()
  };
  const requests = [
    { sortRange: { range: srange, sortSpecs: [{ dimensionIndex: 0, sortOrder: "ASCENDING" }] } },
    { sortRange: { range: srange, sortSpecs: backgroundColors.map(rgb => ({ backgroundColor: rgb })) } }
  ];

  // 3. Request to Sheets API using the request body.
  Sheets.Spreadsheets.batchUpdate({ requests: requests }, ss.getId());
}

注:

  • 遗憾的是,我不知道您的实际电子表格中的背景颜色。因此,在您的实际电子表格中,当使用 ['#ea9999', '#f9cb9c', '#fff2cc', 'd9ead3', '#cfe2f3', '#d9d2e9', '#ffffff'] 颜色以外的背景颜色时,这些颜色将被忽略。请注意这一点。

  • 作为重点,在使用getBackgroundObjects()时,我确认了白底的十六进制值为#ffffffff。我不确定这是错误还是当前规范。所以在这种情况下,#ffffffff被修改为#ffffff.

参考文献:

  • 相关线程。
    • Sort values by color in Google Sheets by using google APP Script

函数随机为行分配颜色,并根据每行的颜色对数据集进行排序。

代码:

function colorSort0() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("Sheet0");
  let vs = sh.getRange(2, 1, sh.getLastRow() - 1, 20).getValues();
  let bs = sh.getRange(2, 1, sh.getLastRow() - 1, 20).getBackgrounds();
  const colors = {};
  const idx = {};
  sh.getRange("X1:X8").getBackgrounds().flat().forEach((b, i) => { colors[i] = b; idx[b] = i; });
  bs.forEach((r, i) => {
    let color = colors[Math.floor(Math.random() * Object.keys(colors).length)];//assigned colors randomyly
    sh.getRange(i + 2, 1, 1, 20).setBackground(color);
    SpreadsheetApp.flush();//Display all assigned colors in the spreadsheet
  });
  vs = sh.getRange(2, 1, sh.getLastRow() - 1, 20).getValues();
  bs = sh.getRange(2, 1, sh.getLastRow() - 1, 20).getBackgrounds();//pickup assigned colors
  let A = vs.map((r, i) => {
    return { values: r, color: bs[i] };
  });
  A.sort((a, b) => {
    return idx[a.color[0]] - idx[b.color[0]];//sort by assigned color
  });
  A.forEach((e, i) => {
    sh.getRange(i + 2, 1, 1, A[i].values.length).setValues([A[i].values]);
    sh.getRange(i + 2, 1, 1, A[i].color.length).setBackgrounds([A[i].color]);
  })
}

运行之前的原始电子表格:

颜色分配后:

颜色排序后: