【问题标题】:Unpivot in Google Sheets - multipe header columns and rows在 Google 表格中取消透视 - 多个标题列和行
【发布时间】:2016-07-06 20:24:39
【问题描述】:

我有一个包含大约 20 列和多达 100 行的汇总表,但是我想将其转换为平面列表,以便可以导入数据库。

This solution 在我的情况下无法正常工作,而且我对 JS 的了解远远低于正确调整它的能力。

Example sheet 中有三个标签:

  1. 源数据 - 我目前拥有的虚拟数据
  2. 期望的结果 - 我想将源数据转换成什么
  3. 我得到的结果 - 使用上述 the solution 时得到的结果

工作表是共享的,因此您可以尝试测试脚本(菜单 > 脚本 > 运行)。它会自动创建一个新标签。

【问题讨论】:

  • 嗨鲁本。你是对的,我的询问不够清楚。我已经更新了它。希望现在好多了

标签: javascript google-apps-script google-sheets pivot-table unpivot


【解决方案1】:

这是我在一些 JS 学习和谷歌搜索后想出的。如果有人可以建议如何使它更短/更清洁/更简单 - 我全神贯注。可能远非完美,但它正是我所需要的。

function transpose(){
  var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SOURCE DATA');
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var numColumns = source.getLastColumn();
  var numRows = source.getLastRow();
  Logger.log('numColumns = ' +numColumns);
  Logger.log('numRows = ' +numRows);


  //GET NUMBER OF HEADERS (PRODUCTS)

  var products = []; // get product models in the first row
  for (var b = 2; b <= numColumns; b++){
    if (source.getRange(1, b).getValue() != "") {
      products.push([source.getRange(1, b).getValue()]); //store
    }
  }


  // PRODUCTS and SITES INTO COLUMNS

  var output = [];

  var sites = []; // get sites list
  for (var a = 3; a <= numRows; a++){
    if (source.getRange(a, 1).getValue() != "") {
      sites.push([source.getRange(a, 1).getValue()]); //store
    }
  }

  for(var p in products){
    for(var s in sites){
      var row = [];
      row.push(sites[s]);
      row.push(products[p]);
      output.push(row);//collect data in separate rows in output array
    }
   }

  var date = Utilities.formatDate(new Date(), SpreadsheetApp.getActive().getSpreadsheetTimeZone(), "M/d/yyyy");
  Logger.log('Date = ' +date)
  ss.insertSheet(date,0).getRange(1,1,output.length,output[0].length).setValues(output);

    var newSheet = ss.getSheetByName(date);


  // COPY REGIONS

  var numProducts = products.length; // number of models
  Logger.log('numProducts = ' +numProducts);

  var i = 1;
  var j = 3 // first column number to copy
  do {
    var colC = newSheet.getRange("C1:C").getValues();
    var copyToCell = colC.filter(String).length+1;
    Logger.log('copyTo R = ' +copyToCell);

    source.getRange(3,2,numRows-2,1).copyTo(newSheet.getRange(copyToCell,3), {contentsOnly:true});
    i++;

    source.getRange(3,j,numRows-2,2).copyTo(newSheet.getRange(copyToCell,4), {contentsOnly:true});
    j+=2;  
  }
  while (i <= numProducts);
  while (j < numColumns);


  // SORT BY SITE AND PRODUCT

  newSheet.getDataRange().sort([1, 2]);
}

【讨论】:

    【解决方案2】:

    我编写了这个简单的通用自定义函数,用于在 Google 电子表格中进行反透视/反向透视。 注意:这是一个自定义函数,与任何其他内置电子表格函数一样,因此您不必运行它,您可以像 unique() 或任何其他数组函数一样使用它。

    在您的情况下,它就像使用以下代码一样简单:=unpivot(A1:H6,2,2,"product","MIN","MAX")

    您可以在此处找到示例:https://docs.google.com/spreadsheets/d/12TBoX2UI_Yu2MA2ZN3p9f-cZsySE4et1slwpgjZbSzw/edit#gid=422214765

    这是代码:

    /**
     * Unpivot a pivot table of any size.
     *
     * @param {A1:D30} data The pivot table.
     * @param {1} fixColumns Number of columns, after which pivoted values begin. Default 1.
     * @param {1} fixRows Number of rows (1 or 2), after which pivoted values begin. Default 1.
     * @param {"city"} titlePivot The title of horizontal pivot values. Default "column".
     * @param {"distance"[,...]} titleValue The title of pivot table values. Default "value".
     * @return The unpivoted table
     * @customfunction
     */
    function unpivot(data,fixColumns,fixRows,titlePivot,titleValue) {  
      var fixColumns = fixColumns || 1; // how many columns are fixed
      var fixRows = fixRows || 1; // how many rows are fixed
      var titlePivot = titlePivot || 'column';
      var titleValue = titleValue || 'value';
      var ret=[],i,j,row,uniqueCols=1;
    
      // we handle only 2 dimension arrays
      if (!Array.isArray(data) || data.length < fixRows || !Array.isArray(data[0]) || data[0].length < fixColumns)
        throw new Error('no data');
      // we handle max 2 fixed rows
      if (fixRows > 2)
        throw new Error('max 2 fixed rows are allowed');
    
      // fill empty cells in the first row with value set last in previous columns (for 2 fixed rows)
      var tmp = '';
      for (j=0;j<data[0].length;j++)
        if (data[0][j] != '') 
          tmp = data[0][j];
        else
          data[0][j] = tmp;
    
      // for 2 fixed rows calculate unique column number
      if (fixRows == 2)
      {
        uniqueCols = 0;
        tmp = {};
        for (j=fixColumns;j<data[1].length;j++)
          if (typeof tmp[ data[1][j] ] == 'undefined')
          {
            tmp[ data[1][j] ] = 1;
            uniqueCols++;
          }
      }
    
      // return first row: fix column titles + pivoted values column title + values column title(s)
      row = [];
        for (j=0;j<fixColumns;j++) row.push(fixRows == 2 ? data[0][j]||data[1][j] : data[0][j]); // for 2 fixed rows we try to find the title in row 1 and row 2
        for (j=3;j<arguments.length;j++) row.push(arguments[j]);
      ret.push(row);
    
      // processing rows (skipping the fixed columns, then dedicating a new row for each pivoted value)
      for (i=fixRows;i<data.length && data[i].length > 0 && data[i][0];i++)
      {
        row = [];
        for (j=0;j<fixColumns && j<data[i].length;j++)
          row.push(data[i][j]);
        for (j=fixColumns;j<data[i].length;j+=uniqueCols)
          ret.push( 
            row.concat([data[0][j]]) // the first row title value
            .concat(data[i].slice(j,j+uniqueCols)) // pivoted values
          );
      }
    
      return ret;
    }
    

    【讨论】:

      【解决方案3】:

      我认为您可以使用CONCAT 从位置和区域获取唯一的行键,并使用来自my answer here 的方法,不需要额外的脚本。

      如果您对键连接做了一些花哨的事情(例如CONCAT(A3, "~", A4)),您甚至可以在反透视表中提取您的原始位置和区域(例如REGEXEXTRACT(A1, "(\w+)~")REGEXEXTRACT(A1, "~(\w+)"))。

      【讨论】:

        【解决方案4】:

        在尚未记录的谷歌表格中使用展平功能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-05
          • 1970-01-01
          相关资源
          最近更新 更多