Google Sheets Unpivot: 5 Methods to Transform Your Data
While Google Sheets doesn't have a built-in unpivot function like Excel's Power Query, there are several effective methods to transform your wide-format data into long format. This comprehensive guide covers 5 proven techniques, from simple formulas to advanced scripts.
Table of Contents
Understanding Unpivot in Google Sheets Context
Unpivoting transforms data from wide format (multiple columns) to long format (fewer columns, more rows). This is essential for data analysis, visualization, and integration with other tools.
Example Transformation:
Before (Wide Format):
| Product | Q1 | Q2 | Q3 | Q4 |
|---|---|---|---|---|
| Laptop | 100 | 120 | 110 | 130 |
| Phone | 200 | 180 | 220 | 250 |
After (Long Format):
| Product | Quarter | Sales |
|---|---|---|
| Laptop | Q1 | 100 |
| Laptop | Q2 | 120 |
| Laptop | Q3 | 110 |
| Laptop | Q4 | 130 |
| Phone | Q1 | 200 |
| Phone | Q2 | 180 |
Method 1: QUERY Function with UNPIVOT-like Logic
The QUERY function is Google Sheets' most powerful tool for data manipulation. While it doesn't have a direct UNPIVOT clause, we can achieve similar results using UNION operations.
Step-by-Step Implementation:
Step 1: Set Up Your Data
Ensure your data is in a clean format with headers in row 1. For our example, we'll use sales data with quarters as columns.
Step 2: Create the QUERY Formula
=QUERY({
QUERY(A2:E, "SELECT A, 'Q1', B WHERE B IS NOT NULL", 0);
QUERY(A2:E, "SELECT A, 'Q2', C WHERE C IS NOT NULL", 0);
QUERY(A2:E, "SELECT A, 'Q3', D WHERE D IS NOT NULL", 0);
QUERY(A2:E, "SELECT A, 'Q4', E WHERE E IS NOT NULL", 0)
}, "SELECT * WHERE Col1 IS NOT NULL")
Step 3: Add Headers
Manually add headers above your formula result: Product, Quarter, Sales
Step 4: Handle Dynamic Ranges
For dynamic data ranges, use this enhanced formula:
=QUERY({
QUERY(A:E, "SELECT A, 'Q1', B WHERE A IS NOT NULL AND B IS NOT NULL", 0);
QUERY(A:E, "SELECT A, 'Q2', C WHERE A IS NOT NULL AND C IS NOT NULL", 0);
QUERY(A:E, "SELECT A, 'Q3', D WHERE A IS NOT NULL AND D IS NOT NULL", 0);
QUERY(A:E, "SELECT A, 'Q4', E WHERE A IS NOT NULL AND E IS NOT NULL", 0)
}, "SELECT * WHERE Col1 != 'Product'")
✅ Pros:
- No scripting required
- Updates automatically when source data changes
- Handles NULL values gracefully
- Works with large datasets
❌ Cons:
- Complex formula for many columns
- Manual adjustment needed for different data structures
- Limited flexibility for varying column names
Method 2: Google Apps Script Automation
For maximum flexibility and automation, Google Apps Script provides a programmatic solution that can handle any data structure.
Complete Script Solution:
Apps Script Code:
function unpivotData() {
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getDataRange().getValues();
if (data.length < 2) {
throw new Error("Need at least 2 rows of data (header + data)");
}
const headers = data[0];
const keyColumn = headers[0]; // First column is the key
const valueColumns = headers.slice(1); // Rest are value columns
const unpivotedData = [];
unpivotedData.push([keyColumn, "Attribute", "Value"]); // New headers
// Process each data row
for (let i = 1; i < data.length; i++) {
const row = data[i];
const keyValue = row[0];
// Create a row for each value column
for (let j = 1; j < row.length; j++) {
if (row[j] !== "" && row[j] !== null && row[j] !== undefined) {
unpivotedData.push([
keyValue,
headers[j],
row[j]
]);
}
}
}
// Create new sheet with results
const newSheet = SpreadsheetApp.getActiveSpreadsheet()
.insertSheet("Unpivoted_" + new Date().getTime());
if (unpivotedData.length > 0) {
newSheet.getRange(1, 1, unpivotedData.length, 3)
.setValues(unpivotedData);
// Format the header row
newSheet.getRange(1, 1, 1, 3)
.setFontWeight("bold")
.setBackground("#f0f0f0");
}
return `Unpivoted ${data.length - 1} rows into ${unpivotedData.length - 1} rows`;
}
How to Implement:
- Open Google Sheets and go to Extensions → Apps Script
- Replace the default code with the script above
- Save the project (Ctrl+S)
- Return to your sheet and run the function
- Authorize the script when prompted
💡 Advanced Tip:
You can modify the script to handle specific column ranges, custom headers, or data validation. Add error handling for production use.
Method 3: Manual Restructuring with Formulas
For smaller datasets or when you need full control over the process, manual restructuring using basic formulas is often the most transparent approach.
Formula-Based Approach:
Step 1: Create the Structure
Set up your target columns: Key, Attribute, Value
Step 2: Use INDEX and MOD Functions
For the Key column (assuming source data starts at A2):
=INDEX($A$2:$A$10, INT((ROW()-2)/4)+1)
For the Attribute column:
=INDEX($B$1:$E$1, MOD(ROW()-2,4)+1)
For the Value column:
=INDEX(INDIRECT("$B$2:$E$10"), INT((ROW()-2)/4)+1, MOD(ROW()-2,4)+1)
Step 3: Filter Out Empty Values
Wrap your formulas with IF statements to handle empty cells:
=IF(INDEX(INDIRECT("$B$2:$E$10"), INT((ROW()-2)/4)+1, MOD(ROW()-2,4)+1)="", "",
INDEX(INDIRECT("$B$2:$E$10"), INT((ROW()-2)/4)+1, MOD(ROW()-2,4)+1))
Method 4: FLATTEN and TRANSPOSE Combination
This method uses Google Sheets' array functions to create a quick unpivot for simple data structures.
Implementation Steps:
Step 1: Flatten the Values
=FLATTEN(TRANSPOSE(B2:E10))
Step 2: Create Repeated Keys
=FLATTEN(ARRAYFORMULA(REPT(A2:A10&"|", 4)))
Step 3: Create Attribute Labels
=FLATTEN(ARRAYFORMULA(REPT(TRANSPOSE(B1:E1), ROWS(A2:A10))))
Step 4: Combine Results
Use SPLIT to separate the key from the delimiter and combine all arrays:
={SPLIT(FLATTEN(ARRAYFORMULA(REPT(A2:A10&"|", 4))), "|"),
FLATTEN(ARRAYFORMULA(REPT(TRANSPOSE(B1:E1), ROWS(A2:A10)))),
FLATTEN(TRANSPOSE(B2:E10))}
Method 5: Online Tools Integration
Sometimes the fastest solution is to export your data, use a specialized tool, and import the results back.
Workflow with UnpivotTool:
- Export from Google Sheets: File → Download → CSV
- Use UnpivotTool: Visit our online unpivot tool
- Upload and Transform: Select columns and unpivot instantly
- Import Back: File → Import → Upload CSV
Method Comparison Summary:
| Method | Complexity | Flexibility | Performance | Best For |
|---|---|---|---|---|
| QUERY Function | Medium | Medium | High | Fixed column structures |
| Apps Script | High | Very High | High | Complex, recurring tasks |
| Manual Formulas | Medium | Low | Medium | Small datasets, learning |
| FLATTEN/TRANSPOSE | Low | Low | High | Simple, uniform data |
| Online Tools | Very Low | Medium | High | One-time transformations |
Advanced Tips and Troubleshooting
Common Issues and Solutions:
Issue: Formula returns #REF! error
Solution: Check that your range references are correct and don't exceed the actual data range.
Issue: Empty cells create unwanted rows
Solution: Add WHERE clauses in QUERY functions or IF statements in manual formulas to filter out empty values.
Issue: Performance is slow with large datasets
Solution: Use Google Apps Script for datasets over 10,000 rows, or consider using our online tool for faster processing.
Issue: Column headers are not dynamic
Solution: Use INDIRECT functions with cell references instead of hardcoded ranges.
Performance Optimization Tips:
- Limit Ranges: Use specific ranges instead of entire columns (A:A) when possible
- Avoid Volatile Functions: Minimize use of NOW(), RAND(), and similar functions
- Use Array Formulas: ARRAYFORMULA can be more efficient than copying formulas down
- Consider Caching: For static data, copy and paste values to remove formula overhead
Real-World Use Cases
Sales Data Analysis
Transform monthly sales reports from wide format (one column per month) to long format for trend analysis and visualization in Google Data Studio.
Survey Response Processing
Convert survey data where each question is a column into a format suitable for statistical analysis with question-answer pairs.
Financial Reporting
Restructure budget data from departmental columns to a format that allows for easy filtering and pivot table creation.
Inventory Management
Transform product data with multiple attribute columns (size, color, material) into a normalized format for database import.
Frequently Asked Questions
Q: Can Google Sheets handle large unpivot operations?
A: Google Sheets can handle up to 10 million cells total. For datasets over 100,000 rows, consider using Google Apps Script or external tools for better performance.
Q: How do I unpivot data with mixed data types?
A: Google Sheets automatically handles mixed data types. However, ensure your formulas account for different formats using TEXT() or VALUE() functions when necessary.
Q: Can I automate unpivot operations to run on schedule?
A: Yes, use Google Apps Script with time-driven triggers to automatically unpivot data at specified intervals.
Q: What's the difference between unpivot and transpose?
A: Transpose simply flips rows and columns. Unpivot transforms multiple columns into attribute-value pairs, creating a normalized data structure.
Q: How do I preserve data formatting during unpivot?
A: Use Google Apps Script to copy both values and formatting, or manually apply formatting to the unpivoted results using conditional formatting rules.
Conclusion
While Google Sheets doesn't have Excel's built-in unpivot functionality, these five methods provide flexible solutions for any data transformation need. Choose the QUERY method for most scenarios, Apps Script for complex automation, or our online tool for quick one-time transformations.
The key is matching the method to your specific requirements: data size, complexity, automation needs, and technical expertise level.
Need a Quick Solution?
Skip the complex formulas and try our free online unpivot tool. Upload your CSV, select columns, and get results instantly.
Try UnpivotTool Now →