365 对行的列垂直堆叠

问题描述 投票:0回答:1

链接到带有虚假数据的示例表: 因此,这里有一个有效的公式,但迭代模式对于手动输入来说太长了。我尝试使用 chatGPT 来简单地迭代该模式,但它基本上崩溃了。它要么不起作用,弄乱了模式,要么上一次它重置了对话并且不记得任何内容。哎呀。

=FILTER(VSTACK(E6:F,G6:H,I6:J,K6:L), (VSTACK(E6:E,G6:G,I6:I,K6:K) <> "") + (VSTACK(F6:F,H6:H,J6:J,L6:L) <> "") )

为了涵盖所有 365 天,我需要它迭代到 ABH 列。

我尝试过应用程序脚本(尽管我宁愿它是一个公式)。它一直工作到第 370 列,然后由于某种原因跳回到 A 列,我无法理解这个奇怪的问题。代码如下:

function stackColumns() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var lastColumn = 736; // Adjust to your actual last column
  var lastRow = 100; // Adjust to your actual last row
  
  // Define constants for batch processing
  var startColumn = 5; // Starting column index (E = column 5)
  var batchSize = 100; // Number of columns to process in each batch

  var stackedData = [];

  // Loop through batches of columns
  for (var start = startColumn; start <= lastColumn; start += batchSize) {
    var end = start + batchSize - 1;
    if (end > lastColumn) {
      end = lastColumn;
    }

    // Get data range for the current batch of columns
    var dataRange = sheet.getRange(6, start, lastRow - 5 + 1, end - start + 1);
    var values = dataRange.getValues();
    var numRows = values.length;
    var numCols = values[0].length;

    // Process each column pair in the current batch
    for (var i = 0; i < numCols - 1; i += 2) { // Increment by 2 for column pairs
      var currentStartColumn = start + i;
      var currentEndColumn = start + i + 1;

      // Process each row in the current column pair
      for (var row = 0; row < numRows; row++) {
        var startValue = (currentStartColumn <= numCols) ? values[row][currentStartColumn - start] : "";
        var endValue = (currentEndColumn <= numCols) ? values[row][currentEndColumn - start] : "";

        // Skip processing if both values are empty
        if (startValue === "" && endValue === "") {
          continue;
        }

        // Push the data pair to stackedData
        var rowData = [
          startValue,
          endValue
        ];
        stackedData.push(rowData);
      }
    }
  }

  // Clear existing content and paste the stacked data starting from a specific cell
  var outputRange = sheet.getRange(7, 739, stackedData.length, 2); // Adjust the number of columns (2 for each pair)
  outputRange.clearContent();
  outputRange.setValues(stackedData);
}

我在这里完全不知所措。这应该不难,但它打败了我。

google-sheets google-apps-script
1个回答
0
投票

您需要一个脚本(尽管最好是公式)来创建名册数据的堆叠列。您有一个脚本,但效果并不令您满意。

此答案基于问题中包含的脚本。但与其尝试解决该脚本的问题,答案是完全重写。答案由两个函数组成:

  • buildRosterStack
    - 使用户能够声明要处理的数。
    • 包括测试
      daysToProcess
      不大于日历数据
  • stackRosters
    - 基于主要脚本。

处理时间小于2秒。


/*
//  
//  NOTES
//  Each day consists of 2 columns
//  Blank rows are not reported
//  Number of days to process is a variable, set in subroutine
//  Sub-routine also tests that the days to process is not more than the Calendar
//
*/

function buildRosterStack(){

  // enter the number of days to process
  var daysToProcess = 335 // 30 Nov 2024 (extent of available data)

  // test the number of days
  var maxYearDays = 366 // days in 2024
  if (daysToProcess>maxYearDays){
    // request exceeds calendar data, stop processing
    console.log("days to Process is greater than Calendar days. Processing stopped")
  }

  stackRosters(daysToProcess)
}



function stackRosters(daysToProcess) {

  var days2Process = daysToProcess //Number of days to process

  var ss = SpreadsheetApp.getActiveSpreadsheet()
  var sheetName = "Master Calendar OLD"
  var sheet = ss.getSheetByName(sheetName)

  // get the dimensions  
  var lastRow = sheet.getLastRow()
  // Logger.log("DEBUG: the last row = "+lastRow)
  
  // Define constants for batch processing
  var startRow = 6
  var startColumn = 5; // Starting column index (E = column 5)
  var stackedData = [] // declare a temporary array
  // Logger.log("DEBUG: the start row = "+startRow+", start column = "+startColumn+", number of days to process = "+days2Process)

  // get the data
  var range = sheet.getRange(startRow,startColumn,lastRow-startRow+1,days2Process*2)
  // Logger.log("DEBUG: the data range = "+range.getA1Notation())
  var values = range.getValues()

  var rowsOfData = values.length
  // Logger.log("DEBUG: rows of data = "+rowsOfData)

    

  // loop through the data
  for (var j=0;j<(days2Process*2);j += 2){ // days
    for (var i=0;i<rowsOfData;i++){ // rows
    
      var dayData1 = values[i][j]
      var dayData2 = values[i][j+1]
      // Logger.log("DEBUG: i="+i+", j="+j+", data1 = "+dayData1+", length:"+dayData1.length+", data 2 = "+dayData2+", length:"+dayData2.length)
      
      // test for BOTH cells as blank
      // if yes, move to next row
      // if no, push BOTH cells onto temporary array
      if (dayData1.length ==0 && dayData2.length==0)
      {
        continue
      }
      else{
        stackedData.push([dayData1,dayData2])
      }
      
    }
  }

  // set output sheet and range and then set the Values
  var targetSheet = ss.getSheetByName("output")
  targetSheet.getRange(1,1,stackedData.length,2).setValues(stackedData)
  console.log("Done")

}

样本输出

snapshot

© www.soinside.com 2019 - 2024. All rights reserved.