I am trying to produce a "reverse pivot" function. I have searched long and hard for such a function, but cannot find one that is already out there.
I have a summary table with anywhere up to 20 columns and hundreds of rows, however I would like to convert it into a flat list so I can import to a database (or even use the flat data to create more pivot tables from!)
So, I have data in this format:
| Customer 1 | Customer 2 | Customer 3
----------+------------+------------+-----------
Product 1 | 1 | 2 | 3
Product 2 | 4 | 5 | 6
Product 3 | 7 | 8 | 9
And need to convert it to this format:
Customer | Product | Qty
-----------+-----------+----
Customer 1 | Product 1 | 1
Customer 1 | Product 2 | 4
Customer 1 | Product 3 | 7
Customer 2 | Product 1 | 2
Customer 2 | Product 2 | 5
Customer 2 | Product 3 | 8
Customer 3 | Product 1 | 3
Customer 3 | Product 2 | 6
Customer 3 | Product 3 | 9
I have created a function that will read the range from sheet1
and append the re-formatted rows at the bottom of the same sheet, however I am trying to get it working so I can have the function on sheet2
that will read the whole range from sheet1
.
No matter what I try, I can't seem to get it to work, and was wondering if anybody could give me any pointers?
Here is what I have so far:
function readRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
heads = values[0]
for (var i = 1; i <= numRows - 1; i++) {
for (var j = 1; j <= values[0].length - 1; j++) {
var row = [values[i][0], values[0][j], values[i][j]];
sheet.appendRow(row)
}
}
};
Here is a demo file that uses a method using built-in custom functions and array formulas:
A1:
=COUNTA(data!A:A)
Calculate the number of rows.A2:
=COUNTA(data!1:1)
Calculate the number of columns.A3:
=CELL("address",data!A1)
Intermediate step.A4:
=LEFT(A3,FIND("!",A3)-1)
Calculates the name of the sheet with the source data.A1: Row headers
A2:
B1: Column headers
B2:
C1: Values
C2:
Description of the main constructs
ROW(INDIRECT("A1:A"&Aux!A1*Aux!A2)
returns an array of consecutive numbers that has the same height as the required final result.{(ROW(INDIRECT("A1:A"&Aux!A1+1))),INDIRECT(Aux!A4&"!R1C1:R"&Aux!A1+1&"C"&Aux!A2+1,false)}
returns a array with the first column including the row index, and the next columns are the source data.That is basically array manipulation... below is a code that does what you want and writes back the result below existing data.
You can of course adapt it to write on a new sheet if you prefer.
to automatically write the result in a new sheet replace last line of code with these :
Please try this code:
https://github.com/Max-Makhrov/GoogleSheets/blob/master/UnpivotTable.js
It gives more power on what you are pivoting
Input sample:
If your data has a single unique key column, this spreadsheet may have what you need.
Your unpivot sheet will contain:
=OFFSET(data!$A$1,INT((ROW()-2)/5)+1,0)
=OFFSET(data!$A$1,0,IF(MOD(ROW()-1,5)=0,5,MOD(ROW()-1,5)))
=INDEX(data!$A$1:$F$100,MATCH(A2,data!$A$1:$A$100,FALSE),MATCH(B2,data!$A$1:$F$1,FALSE))
where
5
is the number of columns to unpivot.I did not make the spreadsheet. I happened across it in the same search that led me to this question.
I wrote a simple general custom function, which is 100% reusable you can unpivot / reverse pivot a table of any size.
In your case you could use it like this:
=unpivot(A1:D4,1,1,"customer","sales")
So you can use it just like any built-in array function in spreadsheet.
Please see here 2 examples: https://docs.google.com/spreadsheets/d/12TBoX2UI_Yu2MA2ZN3p9f-cZsySE4et1slwpgjZbSzw/edit#gid=422214765
The following is the source: