Convert Excel Tables To Lists
In a dark past I was an Excel instructor (among other things). I have trained countless people in the art of Excel number wizardry. I have then become a certified Excel VBA specialist, and I must say, in my years being a professional programmer, this is the skill that has set me apart from all other programmers around me. Sure, people can do Regular Expressions… So can I. Sure, people can do Object Orientation. So can I. But what programmer fancies dumb jumbling of data, and programming a language that has the word ‘basic’ in it? Right. Most programmers I knew were Linux bashers (pun intended) that had no idea something good was hidden up the sleeve of Microsoft. But ok, sometimes I was able to show them some awesome things, and they would instantly recognize that their world view (Excelll is for end-users) was a grave mistake.
What fun it was to teach people Excel, and more so, VBA! To me, it’s the tool of all tools, and it can greatly help anyone who ever works with data (ehm, anyone). So in this first part of a long long series (I hope) I will show you, the humble ignorant user how to convert an Excel table to a list.
Why? Many times I have gone to companies and helped them with some particular problem. Usually it started out with an analyst/marketer/ceo showing me a bunch of data. The data was always presented as a table, with column headings and row headings, with the data in the middle. That seems like a nice way to present data, yes, it is in fact. The first thing I would do is then convert this table to an ugly list.
So why would you convert it to a list?
Because Excel is in love with lists. Excel craves lists, it’s like Access’ little brother, but it can speak five languages and juggle 4 balls. It’s no database tool (maximum of 65535 rows, 1M in Excel 2007)… but it can transform any list into a deep, deep analysis.
The way this analysis is done later on is with Pivot Tables. I wrote those capitals on purpose. Pivot Tables are so powerful that you can basically give it any data list and it can tell you what’s missing, what’s wrong, what’s unique, what’s the total, what’s the average, you name it. But more on that later on.
Let’s convert!
Warning: code ahead…
A table consists of three parts:
- The row headings (left)
- The column headings (top)
- The data (center)
We will loop through the data cell by cell, and create a row in a new list for each. That’s the basic idea (pun intended).
Before we start, we check some preconditions. We have to make sure that we are inside a set of data, formed into a table. All we do is just check if we have at least two rows and two columns (not the ultimate, but it works).
Sub TableToList() If ActiveCell.CurrentRegion.Rows.Count < 2 Then Exit Sub End If If ActiveCell.CurrentRegion.Columns.Count < 2 Then Exit Sub End If
Then we will need some variables to refer to the various sections of the table
Dim table As Range Dim rngColHead As Range Dim rngRowHead As Range Dim rngData As Range Dim rngCurrCell As Range
Next. we will need some variables for the data itself
Dim rowVal As Variant Dim colVal As Variant Dim val As Variant
Now, we will start pointing our variables to the data, row headings and column headings, like so
Set table = ActiveCell.CurrentRegion Set rngColHead = table.Rows(1) Set rngRowHead = table.Columns(1) Set rngData = table.Offset(1, 1) Set rngData = rngData.Resize(rngData.Rows.Count - 1, rngData.Columns.Count - 1)
Note that “currentregion” is a handy tool that expands any cell into a surrounding of non-empty cells. So this way your selected cell could be anywhere inside the table when you run the macro. The data part is a bit harder, line 4 and 5 together shift and resize the original table to form the right bottom part, where all the data resides.
Dim shList As Worksheet Set shList = ThisWorkbook.Worksheets.Add
Next, we create a new sheet in the workbook, to hold the list.
ActiveCell.Value = "Row#" ActiveCell.Offset(0, 1).Value = "RowValue" ActiveCell.Offset(0, 2).Value = "ColValue" ActiveCell.Offset(0, 3).Value = "Data" ActiveCell.Offset(1, 0).Select
In this sheet, we create a first row, “manually”, where we name the column headings for our list. These column headings are very important for sorting, analysis, pivot tables, export and such. The last statement instantly moves the current cell selection one row down. Notice we’re inserting a special column for Row Number. This is not always necessary, but it doesn’t hurt, and it helps you to always be able to restore the original order of the list.
Now it’s time for the actual grunt work, looping through the table
Dim n As Long For Each rngCurrCell In rngData colVal = rngColHead.Cells(rngCurrCell.Column - table.Column + 1) rowVal = rngRowHead.Cells(rngCurrCell.Row - table.Row + 1)
The “for each rngCurrCell in” is a real beauty in VBA. It just runs through any selection, without worries of overflows, row and column numbers, or calculations. In the loop, we set the value of the current column and row. Note that the rngCurrCell.column and rngCurrCell.row are not relative, it’s the actual number of the column/row. So if the tables starts at C3, the first cel is having column=3 and row=3.
n = n + 1 ActiveCell.Value = n
Here, we upped counter ‘n’ and put it in the list.
ActiveCell.Offset(0, 1).Value = rowVal ActiveCell.Offset(0, 2).Value = colVal ActiveCell.Offset(0, 3).Value = rngCurrCell.Value ActiveCell.Offset(1, 0).Select
We do the same trick again to put a new row in the data list on our new sheet. As you can see this part of code is repeated from the part where we created the header. A small improvement would be to create a function named ‘newRow(n, rv, cv, dv)’ to insert a new row with these values.
Next End Sub
Well, that’s it!
When you are done with your code, run it and look at the list. You can try sorting, filtering, analyzing, totalling, and… pivot tables. A pivot table is a dynamically updating table which automatically totals values from a list, and presents them in… a table. Here’s how to re-create the original table from the list:”
- Choose Data > Pivot Table
- Choose Finish
- Drag ColumnValues to the ‘column fields’
- Drag RowValues to the ‘row fields’
- Drag Data into ‘Drop data items here’
Voila, the list is back. That is, if it was a list of numbers. Pivot Tables are for numeric operations, if you had text in there, it won’t show anything (anything good).
The file(s)
Download the file here:
Table2List.xla
Note: to install an XLA you need to go to Tools > AddIns and select the file
10 comments so far
Leave a reply


The file you linked to is no longer available. Thank you for the interesting article though.
Thanks for the tip. I fixed the link, it should work again.
I downloaded and installed the add-in but not sure how its supposed to work–didn’t see where it added itself to any menu options or a toolbar. I know I must be missing the obvious…Help? Or do I just need to the code?
Great tip!
Many thanks for the tip. The table to list converter was exactly what I was looking for. But like George, I didn’t manage to get it to work. Can you provide more info on how to start addin? Thank you!
You can activate it like this:
- Tools > Customize
- Macros > Custom menu item -> drag to toolbar
- right click item
- assign macro
- type Table2List.xla!TableToList
Now put your active cell on the table, and click the button!
Hi Michiel! This bit of code is great and does exactly what I was looking for… almost! How could it be adapted to take into account the fact that some of the source data is already in list format ?
For example let’s say there are 3 columns of row headings (Region, Country, Customer) and then 4 columns of sales figures (Q1, Q2, Q3, Q4). And I want to turn this into a list with 4 columns of row headings (Region, Country, Customer, Quarter) and 1 column of values ?
Hope you can help me, I’ve been stuck all morning trying to figure out a way to do this with VBA! Cheers
Laurent, this is solvable. Just make a column in your data that combines the data of the three Region, Country and Customer. Like this: =A2&”-”&B2&”-”&C2. So you will have columns ‘combined’, q1,q2,q3,q4. Then run the macro.
Invoice Statement for FEB-09 ( Hyderabad – BANA )
Dollars in Whole Amounts
SERVICES RENDERED 120%
Sl No. Inv. No. Inv. Date Process DB ID Class Code LOB Co. No. CC GL Acct. 2 Dot 3 Dot 4 Dot Desc Head Count FTE Month Start Month Close Net Rate / FTE Gross Rate / FTE FEB 09 Inv. Amt. (USD) FEB 09 LOB Rebate FEB 2009 Net Invoice Value (USD) Desc Remarks
– – 0 0 0 0 Cards – Ops Rita Nag Chowdhury
Total 0 0 0 0 0
Re-imbursables
Sl No. Inv. No. Inv. Date Process DB ID Class Code LOB Co. No. CC GL Acct. 2 Dot 3 Dot 4 Dot Desc Head Count FTE Month Start Month Close Net Rate / FTE Gross Rate / FTE FEB 09 Inv. Amt. (USD) FEB 09 LOB Rebate FEB 2009 Net Invoice Value (USD) Desc Remarks
Total – – –
Seat-Utilization
Sl No. Inv. No. Inv. Date Process DB ID Class Code LOB Co. No. CC GL Acct. 2 Dot 3 Dot 4 Dot Desc Head Count FTE Month Start Month Close Net Rate / FTE Gross Rate / FTE FEB 09 Inv. Amt. (USD) FEB 09 LOB Rebate FEB 2009 Net Invoice Value (USD) Desc Remarks
Total 0 0 0
Hi,
Thanks for this. It really helped.
Can I adapt this code to work with Pivot tables that has multiple row or columns headings? At present it seems to work only when there is one row & one column heading
Please email me about this
Manindra
I was really wondering to know “how to convert excel tables to data lists”. This tip really helped me. Many thanks Michel. Really Useful.