Пропускать пустые значения при конвертации в гугл листы - PullRequest
0 голосов
/ 02 марта 2020

Я использую этот превосходный скрипт для преобразования широкой таблицы в длинную таблицу в листах Google { ссылка }.

Код:

/**
 * 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; i++)
  {
    // skip totally empty or only whitespace containing rows
    if (data[i].join('').replace(/\s+/g,'').length == 0 ) continue;

    // unpivot the row
    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;
}

Однако у меня много строк и столбцов, и в моей результирующей таблице слишком много строк для вывода. В моих данных много пробелов. Я хотел бы пропустить запись строк с пустыми значениями, как показано ниже:

Широкий формат:

Region Activity1  Activity2  Activity3
A      1                     2
B                 1 
C      1

Требуемый длинный формат:

Region ActivityName Frequency   
A      Activity1    1   
A      Activity3    2   
B      Activity2    1   
C      Activity1    1   

Я сейчас использую код, который находится в связанном ответе. Я получаю сообщение об ошибке: «Ошибка слишком велика». Мои результаты определенно не были бы слишком большими, если бы я мог пропустить пустые значения.

1 Ответ

1 голос
/ 04 марта 2020

Казалось, проще заново создать сценарий, чем отладить ваш. В этом сценарии предполагается, что данные начинаются в ячейке A1.

Ключевые элементы

  • Создайте два временных массива: один для хранения значений строк, а другой для прогрессивной компиляции массивов строк.
  • L oop через строки и столбцы
  • Добавлять значение, установленное в массив, каждый раз, когда значение столбца не пустое
  • , когда закончите, обновите новый массив значения
  • Не забудьте удалить «старые» столбцы данных, которые находятся за пределами столбцов «новых» данных

function so6049421501() {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheetname = "Sheet1";
  var sheet = ss.getSheetByName(sheetname);

  // get data
  var range = sheet.getDataRange();
  // Logger.log("DEBUG: source range = "+range.getA1Notation())
  var data = range.getValues();

  // get number ofrows in the source data
  var fixRows = range.getNumRows()-1;
  var fixColumns = range.getNumColumns()-1;
  // Logger.log("DEBUG: rows = "+fixRows+", columns = +fixColumns");

  // create a new array to hold values
  var newarray = [];
  // set the number of columns in the new array
  var numCols = 3;
  // add header row
  newarray.push(["Region","ActivityName","Frequency"]);

  for (var r = 0;r<fixRows;r++){

    for (var c=0;c<fixColumns;c++){
      // create a new array to hold the values for this row
      var rowarray = [];

      // if column isn't blank
      if (data[+r+1][+c+1] !==""){

        // column isn't blank
        // push the region
        // Logger.log("DEBUG: region = "+data[r+1][0]);
        rowarray.push(data[r+1][0])

        // push the activity
        // Logger.log("DEBUG: activity = "+data[0][+c+1]);
        rowarray.push(data[0][+c+1])

        // push the frequency
        DEBUG: Logger.log("Frequency = "+data[+r+1][+c+1])
        rowarray.push(data[+r+1][+c+1]);

        //Logger.log(rowarray)
        newarray.push(rowarray);
      }  
    } 
  }
  // Logger.log(newarray);
  //Logger.log("DEBUG: new array len = "+newarray.length);
  // Logger.log("DEBUG: target range = "+sheet.getRange(1, 1, newarray.length, numCols).getA1Notation());


  // Update the new array
  sheet.getRange(1, 1, newarray.length, numCols).setValues(newarray);
  // delete the data in the unused columns
  sheet.getRange(1,4,+fixRows+1,+fixColumns+1-numCols).clear()


  return;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...