0

У меня есть сводная таблица с примерно 20 столбцами и до ста строк, однако я хотел бы преобразовать ее в плоский список, чтобы я мог импортировать в базу данных.Unpivot в Google Таблицах - столбцы и строки заголовков многоуровня

This solution не работает должным образом в моем случае, и мои знания JS далеки от возможности правильно его отрегулировать.

Там уже три вкладки в Example sheet:

  1. Источник данных - фиктивные данные о том, что я в настоящее время
  2. желаемого результата - то, что я хочу, чтобы преобразовать источник данных для
  3. Что я получаю - результат я получаю при использовании the solution, упомянутых выше

Лист является общим, поэтому вы можете попробовать и протестировать скрипт (Меню> Сценарий> Выполнить). Он автоматически создаст новую вкладку.

+0

привет Ruben. Вы правы, мой запрос не был достаточно ясным. Я обновил его. Надеюсь, что сейчас лучше –

ответ

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]); 
} 
0

Я думаю, что вы можете использовать CONCAT, чтобы получить уникальный ключ строки из местоположения и области и использовать метод из my answer here, который не требует дополнительных скриптов.

Если вы делаете что-то фантазию с ключом конкатенацией (например CONCAT(A3, "~", A4)), вы можете даже извлечь исходное расположение и область в UNPIVOT таблицы (например REGEXEXTRACT(A1, "(\w+)~") и REGEXEXTRACT(A1, "~(\w+)")).

1

Я написал эту легкую общую пользовательскую функцию для разворачивания/обратного поворота в Google Spreadsheet. Примечание: это настраиваемая функция, как и любая другая встроенная функция электронных таблиц, поэтому вам не нужно ее запускать, вы можете использовать ее как 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; 
} 
Смежные вопросы