Last active
February 7, 2026 22:19
-
-
Save Medohh2120/f8553c149684e39bb499249e39f01017 to your computer and use it in GitHub Desktop.
Wide" data into a "Long" database format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Name: UNPIVOT_PLUS | |
| Description: Given a Table or a range with headers, Transforms "Wide" data into a "Long" database format. | |
| V3 UPDATE: Now supports multi-row headers and multi-column anchors. | |
| Automatically handles merged cells (Fill-Down or Fill-Right logic). | |
| optionally removing Grid blank entries. | |
| optionally removing Grid errors. | |
| Made By: Medohh2120 | |
| */ | |
| UNPIVOT_PLUS = LAMBDA(Table, [No_of_headers], [No_of_cols], [Col_names], [Value_name], [Remove_blanks], [Remove_errors], | |
| LET( | |
| /* 1. Defaults */ | |
| No_of_headers, IF(ISOMITTED(No_of_headers), 1, No_of_headers), | |
| No_of_cols, IF(ISOMITTED(No_of_cols), 1, No_of_cols), | |
| Col_names, IF(ISOMITTED(Col_names), "", Col_names), | |
| value_name, IF(ISOMITTED(Value_name), "Value", Value_name), | |
| Remove_blanks, IF(ISOMITTED(Remove_blanks), TRUE, Remove_blanks), | |
| Remove_errors, IF(ISOMITTED(Remove_errors), TRUE, Remove_errors), | |
| /* 2. Data Extraction */ | |
| Grid, DROP(Table, No_of_headers, No_of_cols), | |
| Anchors, IF(No_of_cols > 0, DROP(TAKE(Table, , No_of_cols), No_of_headers), ""), | |
| raw_hdrs, TAKE(DROP(Table, , No_of_cols), No_of_headers), | |
| anchor_names, IF(No_of_cols > 0, INDEX(Table, No_of_headers, SEQUENCE(, No_of_cols)), ""), | |
| /* 3. Helper Values */ | |
| r, ROW(Grid), | |
| c, COLUMN(Grid), | |
| f_Grid, TOCOL(Grid), | |
| /* 4. (Only if No_of_cols > 0) This loops through each anchor column, applies the SCAN (fill-down) logic then broadcasts each */ | |
| f_anchors, IF(No_of_cols = 0,"", | |
| DROP( | |
| REDUCE("",SEQUENCE(No_of_cols), | |
| LAMBDA(acc, nxt, LET( | |
| col_data, INDEX(Anchors, , nxt), | |
| filled_col, SCAN("", col_data, LAMBDA(a, b, IF(b = "", a, b))), | |
| HSTACK(acc, TOCOL(IF(c, filled_col)))) | |
| ) | |
| ),,1 | |
| ) | |
| ), | |
| /* 5. This loops through each header, applies the SCAN (fill-right) logic then broadcasts each (Always runs) */ | |
| header_stack, DROP( | |
| REDUCE("",SEQUENCE(No_of_headers), | |
| LAMBDA(acc, nxt, | |
| LET( | |
| user_input, IFERROR(INDEX(Col_names, nxt), ""), | |
| filled_hdrs, SCAN("", INDEX(raw_hdrs, nxt, ), LAMBDA(a, b, IF(b = "", a, b))), | |
| HSTACK(acc, VSTACK(IF(user_input <> "", user_input, "Col" & nxt), TOCOL(IF(r, filled_hdrs)))) | |
| ) | |
| ) | |
| ),,1 | |
| ), | |
| /* 6. Smart Stack */ | |
| header_and_grid, HSTACK(header_stack, VSTACK(value_name, f_Grid)), | |
| stacked, IF(No_of_cols = 0, header_and_grid, HSTACK(VSTACK(anchor_names, f_anchors), header_and_grid)), | |
| /* 7. handle all four states (Blanks, Errors, Both, None) */ | |
| FILTER(stacked, | |
| VSTACK(1, | |
| NOT( | |
| (Remove_blanks * ISBLANK(f_Grid)) | |
| + | |
| (Remove_errors * ISERROR(f_Grid)) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
0 anchor columns case : (in case of 0 header, transpose the whole data and use this case)