将包含特定文本的行移动到数组中的最后一行

Moving a row that contains certain text up to the last row in an array

提问人:workflowz 提问时间:11/17/2023 最后编辑:Tanaikeworkflowz 更新时间:11/18/2023 访问量:47

问:

我在这里搜索并尝试修改一些脚本,但没有任何运气。

在我的工作表中,有一个查询引入生产数据。在该数据下方,我有一个浮动的 Grand Totals 行,该行将上述数据的 SKU 计数、总数量和成本相加。我们通常在确认所有生产线项目后,将此行向上拖动到最后一行的下方。

我想在 A 列中搜索包含文本“总计”的行,并将该行及其公式和格式移动到生产数据的最后一行下方。这应该从A6-A499行开始对活动工作表完成。我不想从命名的工作表中获取范围,因为工作表名称是动态的,其中有生产计划的周数。

多年来一直在使用 SO,但这是我的第一篇文章。如果这是重复,请原谅我。我搜索了很多线程,但无法完成此脚本。

这是我一起破解的脚本 - 我觉得 if 语句缺少一些东西..但它可能不止于此。

如果下面的方向和脚本还不够,我可以用谨慎的数据制作一个共享表,但我希望我已经很好地解释了我的需求。

我添加了一个 UI 菜单项来运行它,认为在运行它时我需要在“活动工作表”上,以便也避免需要定义某个工作表名称。我可以看到它在工作簿中的所有工作表上也很有用,在编辑或其他东西时触发。任何建议将不胜感激!

function onOpen() {
  SpreadsheetApp.getUi().createMenu("⚙️ Admin Settings")
    .addItem("Move GT", "MoveGT")
    .addToUi();
}

function MoveGT() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getActiveSheet();
  var r = s.getRange("A6:A499");

  if(r.getColumn() == 1 && r.getValue() == "Grand Total") {
    var row = r.getRow();
    var numColumns = s.getLastColumn();
    var targetSheet = ss.getActiveSheet();
    var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
    s.getRange(row, 1, 1, numColumns).moveTo(target);
    s.deleteRow(row);
  }
}
javascript google-apps-script google-sheets

评论

0赞 Chiến Lê 11/17/2023
only 返回区域中第一列的位置,仅返回区域中左上角单元格的值。对于您的情况,我认为您应该使用遍历范围的第一列来获取数据范围以找到“总计”行,或者只是r.getColumn()r.getValue()r = s.getDataRange()r.getLastRow()

答:

0赞 Tanaike 11/17/2023 #1

我相信你的目标如下。

  • 您想从“A”列中搜索“总计”值。
  • 您希望将搜索到的行移动到同一工作表的最后一行,同时保留单元格格式和公式。
  • 您希望将搜索的行移动到 A6:L499 范围内的最后一行非空白行。

在您的显示脚本中,当单元格“A6”的值为“总计”时,我认为您的脚本有效。但是,我担心当“总计”放在除“A6”之外的单元格中时,您的脚本无法使用。我猜这可能是您当前的问题。如果我的理解是正确的,那么下面的修改怎么样?

修改后的脚本:

function MoveGT() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getActiveSheet();
  var r = s.getRange("A6:A499");

  // I modified the below script.
  var lastCol = s.getLastColumn();
  var ranges = r.createTextFinder("Grand Total").matchEntireCell(true).findAll().map(e => e.offset(0, 0, 1, lastCol));
  if (ranges.length == 0) return;
  var lastRow = r.getDisplayValues().findIndex(([a]) => a == "") + r.getRow();
  ranges.forEach((e, i) => e.moveTo(s.getRange(lastRow + i, 1)));
  ranges.reverse().forEach(e => s.deleteRow(e.getRow()));
}
  • 运行此脚本时,将从“A”列中搜索值“总计”。并且,搜索到的行将移动到同一工作表的最后一行。

  • 我认为在这种情况下,可以使用以下修改后的脚本。

    function MoveGT() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var s = ss.getActiveSheet();
      var r = s.getRange("A6:A499");
    
      // I modified the below script.
      var offset = r.getRow();
      var values = r.getDisplayValues();
      var rows = values.reduce((ar, [a], i) => {
        if (a == "Grand Total") {
          ar.push(i + offset);
        }
        return ar;
      }, []);
      var len = rows.length;
      if (len == 0) return;
      var lastRow = values.findIndex(([a]) => a == "") + offset;
      var lastCol = s.getLastColumn();
      rows.forEach((e, i) => s.getRange(e, 1, 1, lastCol).moveTo(s.getRange(lastRow + i, 1)));
      rows.reverse().forEach(e => s.deleteRow(e));
    }
    

引用:

评论

0赞 workflowz 11/18/2023
非常接近!脚本将其推送到工作表的最后一行。抱歉,我忘了提到我在移动行时要求,它必须搜索 A6:L499 范围内的最后一行非空白行。这是窗口数据在该范围内没有任何公式。列 M-Q 的公式级联到工作表的最后一行,这可能是脚本选择最后一行的原因。在 A500:L600 中,我在另一个脚本中使用了一个隐藏查询。虽然我想移动整个“总计”行,但我需要确定最后一行,其中包含 A6:L499 中的数据并将其移动到该行下方。
0赞 workflowz 11/18/2023
做到了。非常感谢Tanaike的帮助!这将极大地帮助我们的新流程。
0赞 Tanaike 11/18/2023
@workflowz 感谢您再次回复和测试。我很高兴您的问题得到了解决。也谢谢你。