Escolar Documentos
Profissional Documentos
Cultura Documentos
Automation
Published by Tim Wilson on June 8, 2013All posts from Tim Wilson
The single post on this blog that has, for several years now, consistently driven the most
traffic to this site, is this onethat I wrote almost three years ago. Apparently, through
sheer volume of content on the page and some dumb luck with the post title, I
consistently do well for searches for Excel dynamic named ranges (long live the long
tail of SEO!).
The kicker is that I wrote that post before Id discovered the awesomeness of Excel
tables, and before Excel 2010 had really gone mainstream. Ive been meaning to redo
the original post with an example that uses tables, because it simplifies things a bit.
This is that post 100% plagiarized from the original when it makes sense to do so.
The content was created in Excel 2010 for Windows. However, it should work fine on
Excel 2007 for Windows, too. Macs are a bit of a crap shoot, unfortunately (but you can
always run Parallels, so I hear, and use Excel for Windows!).
This post describes (and includes a downloadable file of the example) a technique that
Ive used extensively to make short work of updating recurring reports. Here are the
criteria I was working against when I initially implemented this approach:
Reporting of the most recent value (think sparklines, where you want to show the
last x data values in a small chart, and then report the last value explicitly as a
number)
No macros I dont have anything against macros, but they introduce privacy
concerns, version compatibility, odd little warnings, and, in this case, arent needed
The example shown here is pretty basic, but the approach scales really well.
Sound like fun?
Now, turn that range of data into a table by selecting the area from A2 to D19 and
choosing Insert Table. Then, click over to the Table Tools / Design group and
change the table name from Table1 to Main_Data (this isnt required, but I always
like to give my tables somewhat descriptive names). The sheet should now look like
this:
Because this is now a table, as you add data in additional rows, as long as they are on
the rows immediately below the table, the table will automatically expand (and that new
data will be included in references to Main_Data, which is critical to this whole
exercise).
While were on this tab, we should go ahead and defined some named cells and some
named ranges. Well name the cells in the first row of each metric column (the row
labeled Current> as the current value for that metric (the cells dont have to be
named cells, but it makes for easier, safer updating of the dashboard as the complexity
grows). Name each cell by clicking on the cell, then clicking in the cell address at the
top left and typing in the cell name. Its important to have consistent naming
conventions, so well go with <metric>_Current for this (it works out to have the metric
identified first, with the qualifier/type after just trust me!). The screen capture below
shows this being done for the cell where the current value for Orders will go, but this
needs to be done for Revenue and Web Traffic as well (I just remove the space for
Web Traffic WebTraffic_Current).
And, of course, well actually need data this would come later, but Ive gone ahead
and dropped some fictitious stuff in there:
When you click OK, you will have a dropdown in cell C1 that contains all of the available
months. This is a critical cell its what well use to select the date we want to key off of
for reporting, and its what well use to look up the data. So, we need to make it a
named cell ReportPeriod:
Now, lets do a similar operation for the report range this tells the spreadsheet how
many months to include in each chart. Click in cell C3, select Data Data Validation,
choose List, and then enter the different values you want as options (Ive used 3, 6, 9,
and 12 here, but any list of integers will work):
Does this seem like a lot of work? It can be a bit of a hassle on the initial setup, but it
will pay huge dividends as the report gets updated each day, week, or month. Trust me!
Before we leave this tab, go ahead and select a value in each dropdown this will
make it easier to check the formulas in the next step.
COLUMN() this is 2, the column that the current metric is listed in (this function
resolves to 3 for Orders and to 4 for Web Traffic (Note: If you have additional
columns in your data sheet, you may have to make this COLUMN()-<some fixed
value>. If, for instance, you have a blank column A before the table starts to provide
some space, you would use COLUMN()-1. This applies to other uses of COLUMN()
throughout this post.)
So, the formula simply takes the currently selected month, finds the row with that value
in the data array, and then moves over to the column that matches the current column
of the formula:
Well do this by defining a named range called Revenue_Range (note how this has a
similar naming convention toRevenue_Current, the name we gave the cell with the
single value this comes in handy for keeping track of things when setting up the
dashboard). We cant use VLOOKUP, because that function doesnt really work with
arrays and ranges of data. Instead, well use a combination of the MATCH function
(which is sort of like VLOOKUP on steroids) and the INDEX function (which is a handy
way to grab a range of cells). Pull your hat down and fasten your seatbelt, as this one
gets a little scary. Ultimately, the formula looks like this:
=INDEX(Main_Data,MATCH(ReportPeriod,Main_Data[Report Period])-ReportRange+1,
COLUMN(Revenue_Current)):INDEX(Main_Data,
MATCH(ReportPeriod,Main_Data[Report Period]), COLUMN(Revenue_Current))
Its really not that bad when you break it down. I promise!
Working from the outside in, youve got a couple of INDEX() functions. Think of those as
being INDEX(First Cell) and INDEX(Last Cell).
row_num this is the row number within the array that we want to use; well come
back to that in just a minute
Now, back to how we determine the row_num value. We do this using the MATCH
function, which we need to use on a 1-dimensional array rather than a 2-dimensional
array (Main_Data is a multi-column table, which makes it a 2-dimensional array). All we
want this function to return is the number of the row in the Main_Data table for the
currently selected report period, which, as it turns out, is the same row as the currently
selected report period in the first column (Report Period). The formula is pretty simple:
MATCH(ReportPeriod,Main_Data[Report Period])
The formula looks in the first column of the Main_Data table for the ReportPeriod value
and finds itin the seventh row of the table. So, row_num is set to 7.
INDEX(First Cell) is almost identical to INDEX(Last Cell), except the row_num value
needs to be set to 2 instead of 7 that will make the full range match
the ReportRange value of 6. So, row_num is calculated as:
MATCH(ReportPeriod,Main_Data[Report Period])-ReportRange+1
(The +1 is needed because we want the total number of cells included in the range to
be ReportRange inclusive.)
Now, thats not all that scary, is it? We just need to drop the full formula into a named
range called Revenue_Range by selecting Formulas Name Manager New,
naming the range Revenue_Range, and inserting the formula:
=INDEX(Main_Data,MATCH(ReportPeriod,Main_Data[Report Period])-ReportRange+1,
COLUMN(Revenue_Current)):INDEX(Main_Data,
MATCH(ReportPeriod,Main_Data[Report Period]), COLUMN(Revenue_Current))
Orders_Range: =INDEX(Main_Data,MATCH(ReportPeriod,Main_Data[Report
Period])-ReportRange+1, COLUMN(Orders_Current)):INDEX(Main_Data,
MATCH(ReportPeriod,Main_Data[Report Period]), COLUMN(Orders_Current))
WebTraffic_Range: =INDEX(Main_Data,MATCH(ReportPeriod,Main_Data[Report
Period])-ReportRange+1, COLUMN(WebTraffic_Current)):INDEX(Main_Data,
MATCH(ReportPeriod,Main_Data[Report Period]), COLUMN(WebTraffic_Current))
Tip: After creating one of these named ranges, while still in the Name Manager, you can
select the range and click into the formula box, and the current range of cells defined by
the formula will show up with a blinking dotted line around them.
Youre getting sooooooo close, so hang in there! In order for the chart labels to show up
correctly, we need to makeone more named range. Well call it Date_Range and define
it with the following formula (this is just like the earlier_Range formulas, but we know we
want to pull the dates from the first column, so, rather than using the COLUMN()
formula, we simply use a constant, 1:
=INDEX(Main_Data,MATCH(ReportPeriod,Main_Data[Report Period])ReportRange+1,1):INDEX(Main_Data, MATCH(ReportPeriod,Main_Data[Report
Period]),1)
If you want, you can fiddle around with the different settings on the Dashboard tab and
watch how both the Current values and (if you get into Name Manager)
the _Range areas change.
ORyou can move on to the final step, where it all comes together!
Right-click on the chart and select Select Data. Click to Add a new series and enter
Revenue (without the quotes Excel will add those for you) as the series name and
the following formula for the series values:
=DynamicChartsWithTables_Example.xlsx!Revenue_Range
(Change the name of the workbook if thats not what your workbook is named)
Tighten it up with some level of formatting (if you just cant stand to wait, you can go
ahead and start flipping the dropdowns to different settings), drop =ReportPeriod into
cell E6 and =Revenue_Current into cell E7, and you will wind up with something that
looks like this:
Okay, so that still looks pretty horridbut this isnt a post about data visualization, and
Im trying to make the example as illustrative as possible. In practice, we use this
technique to populate a slew of sparklines (no x-axis labels) and a couple of bar charts,
as well as some additional calculated values for each metric.
To add charts for orders and web traffic is a little easier than creating the initial chart.
Just copy the Revenue chart a couple of times (if you hold down <Ctrl>-<Shift> and
then click and drag the chart it will make a copy and keep that copy aligned with the
original chart).
Then, simply click on the data line in the chart and look up at the formula box. You will
see a formula that looks something like this:
=SERIES(Revenue,DynamicChartsWithTables_Example.xlsx!Date_Range,
DynamicCharts_ExampleWithTables.xlsx!Revenue_Range,1)
Change the bolded text, Revenue, to be Orders and the chart will update.
Repeat for a Web Traffic chart, and youll wind up with something like this:
So, is it worth it? Not if youre going to produce one report a couple of times and move
on. But, if youre in a situation where you have a lot of recurring, standardized reports
(not as mindless report monkeys these should be well-structured, well-validated,
actionable performance measurement tools), then the payoff will hit pretty quickly.
Updating the report is simply a matter of updating the data on the Data tab (some of
which can even be done automatically, depending on the data source and the API
availability), then the Report Period dropdown on the Dashboard tab can be changed
to the new report period, and the charts get automatically updated! You can then spend
your time analyzing and interpreting the results. Often, this means going back and
digging for more data to supplement the reportbut Im teetering on the verge of much
larger topic, so Ill stop
As an added bonus, you can hide the Data tab and distribute the spreadsheet itself,
enabling your end users to flip back and forth between different date ranges a poor
mans BI tool, if ever there was one (in practice, there will seldom be any real insight
gleaned from this limited number of adjustable dropdowns, and thats not the reason to
set them up in the first place).
I was curious as to what it would take to create this example from scratch and document
it as I went. As its turned out, this is a lonnnnnnngggg post. But, if youve skimmed it,
get the gist, and want to start fiddling around with the example used here, feel free
to download it!
Happy dynamic charting!