Quantcast
Channel: Peltier Tech
Viewing all 158 articles
Browse latest View live

The Advanced Chart Utility Is Here

$
0
0

Happy Birthday to Me!

As promised last week, the Advanced Edition of the Peltier Tech Chart Utility is here.

What’s In It?

The new software has all of the goodies of the current product, and nearly doubles it with lots of new custom charts and a handful of new features.

Here are how the products line up.

Comparison of custom charts offered by the Standard and Advanced Editions of the Peltier Tech Chart Utility

You’ll notice all of the new charts, including several more variations on waterfall charts. I guess you can never have too many variations on that theme, because folks are always asking for this or that “minor” adjustment. (“You can do it, you’re smart.”) The split bar is like having a separate waterfall for each bar of the waterfall

There are a couple variations on the histogram. The bars are the same, but the horizontal axis is built in two different ways, both of them better than plain old column charts in Excel, and better than the histogram in the Excel Analysis Toolpak.

Comparison of custom charts offered by the Standard and Advanced Editions of the Peltier Tech Chart Utility

While mulling over a thread in the Mr Excel forum not long ago, I came up with the routine that nicely exports a range to an image file. This is a nice companion to the Export Chart feature that’s been a staple of the Standard Edition. The Export Chart to Word and PowerPoint are goodies that I would toss into projects for clients, because they are cool and they didn’t know they wanted them.

Switch X and Y is a feature I built for my own use back in the day, when my company was still using Excel 97 and the rest of the world was using 2003. Very handy.

After I played with Jon Acampora’s tool to Move and Align Chart Titles, Labels, Legends with the Arrow Keys, I dusted off and finished my own arrow key positioning device and added a resizing function. It’s pretty cool, but there’s still some funny business when you make the first adjustment to the size of the plot area, at least in Excel 2013.

You should also notice that against all odds, the green column has every single one of the items in the yellow column. My previous product release was the Mac version of the Standard Edition of the Utility, and I was very pleased that I was able to get everything into the Mac version. Of course, the devil now owns 3/8 of my soul. Or Steve Jobs. Or do I repeat myself?

What’s coming?

First, I’m going to have to write some articles about using the Utility. I figure each topic will yield a blog post and a section of the online documentation.

Next, or in parallel, I’m going to put together a Mac version. I still have 5/8 of a soul for collateral.

Finally I’ll keep working on more custom charts, and this Advanced Edition will be the repository for them. On my slate are run charts, grouped box plots, tornado (sensitivity) diagrams, simple panel charts, and finally, a revival of the trellis charts based on my old Panel Chart Utility.

Among the charting features I have in mind are a zooming function, where you draw a box around points on the chart, and the axes will adjust to blow up those points. This box-drawing tool could be repurposed to allow selection of a subset of data, placing it into a new series for its own analysis. Also I was working on a point dragger, where you would click and drag on a plotted point, and the cell data would change to reflect the new position of the point. That was a popular feature in Excel 2003 and earlier, and Excel 2007 killed it along with all of those kittens.

How Can You Get The Utility

Go to the Peltier Tech Chart Utility page to license the utility. There are a few special deals.

From now through next Wednesday (June 18), you can buy the Advanced Utility for the price of the Standard Edition, by entering a coupon code found on the Utility page.

If you have already licensed the Standard Edition, email Peltier Tech to get a code to let you upgrade to the Standard Edition at no charge.

If you have a valid license for any of the older one-chart utilities, email Peltier Tech to get a different coupon code that will get you the Standard or Advanced Edition at a 50% discount.

As always, there are discounts for quantities greater than one license.

The post The Advanced Chart Utility Is Here appeared first on Peltier Tech Blog.


Save and Retrieve Information With Text Files

$
0
0

Introduction

There are many techniques one can use to write information from a running Microsoft Office program. You can save data in a workbook, but this is unwieldy for saving small items, such as program settings. You can use ini files or the registry, but both can get complicated. Using the registry is more invasive than you may want to be, and it’s very hard to transfer registry settings among computers. One of the easiest methods to save and retrieve data is by using simple IO commands with text files. Such files are small, they are processed rapidly, they can be read with a simple text editor, and they can be easily copied from computer to computer.

Visual Basic I/O

Visual Basic contains some commands which are useful for fast and simple text file input and output. Since the Visual Basic for Applications (VBA) used to program Microsoft Office is based on VB, Excel and the other Office applications can use these commands to read and write text files. I frequently use this technique to save application settings or to store debugging information.

The VBA help files contain detailed information about the various IO commands. Rather than beat the topic to death, I’ll present a couple simple examples that write and read text from a text file, then I’ll show some practical examples. The reader is directed to the help files for further details.

The subroutine TextIODemoWrite, shown below, opens a specified text file, puts a simple text string into the file, then closes the file. Files are opened using integers starting with 1; the FreeFile function assigns the next available integer to the file, to prevent accidentally assigning the same integer to two files. When you Open the file, a buffer is allocated to it, and the access mode (e.g., Output) is assigned. If the file does not already exist, it is automatically created. Subsequent commands (Write and Close) refer to the file using its integer. Text can be written using Write or Print; refer to the help files for specifics. Closing a file deallocates the buffer and disassociates the file from the file number.

Sub TextIODemoWrite()
  Dim sFile As String
  Dim sText As String
  Dim iFileNum As Integer

  sFile = "C:\test\textio.txt"
  sText = "Testing 1 2 3."

  iFileNum = FreeFile
  Open sFile For Output As iFileNum
  Write #iFileNum, sText
  Close #iFileNum
End Sub

The subroutine TextIODemoRead below shows the reverse operation, opening a text file, retrieving some text, closing the text file, then displaying the text in a message box.

Sub TextIODemoRead()
  Dim sFile As String
  Dim sText As String
  Dim iFileNum As Integer

  sFile = "C:\test\textio.txt"

  iFileNum = FreeFile
  Open sFile For Input As iFileNum
  Input #iFileNum, sText
  Close #iFileNum
  MsgBox sText
End Sub

Save and Retrieve Settings

The VBA procedures above can be expanded to allow us to save settings for later retrieval. The simplistic approach used in function SaveSetting reads variable names and values from a file, and writes them to a temporary file. If the named variable already exists, its new value is written to the temporary file in place of the existing value. When all variables have been read and written, the original file is replaced by the new file.

SaveSetting uses some additional functions, IsFullName, FullNameToPath, FullNameToFileName, and FileExists, which are shown at the end of this article.

Function SaveSetting(sFileName As String, sName As String, _
      Optional sValue As String) As Boolean
  
  Dim iFileNumA As Long
  Dim iFileNumB As Long
  Dim sFile As String
  Dim sXFile As String
  Dim sVarName As String
  Dim sVarValue As String
  Dim lErrLast As Long
  
  ' assume false unless variable is successfully saved
  SaveSetting = False
  
  ' add this workbook's path if not specified
  If Not IsFullName(sFileName) Then
    sFile = ThisWorkbook.Path & "\" & sFileName
    sXFile = ThisWorkbook.Path & "\X" & sFileName
  Else
    sXFile = FullNameToPath(sFileName) & "\X" & FullNameToFileName(sFileName)
  End If
  
  ' open text file to read settings
  If FileExists(sFile) Then
    'replace existing settings file
    iFileNumA = FreeFile
    Open sFile For Input As iFileNumA
    iFileNumB = FreeFile
    Open sXFile For Output As iFileNumB
      Do While Not EOF(iFileNumA)
        Input #iFileNumA, sVarName, sVarValue
        If sVarName <> sName Then
          Write #iFileNumB, sVarName, sVarValue
        End If
      Loop
      Write #iFileNumB, sName, sValue
      SaveSetting = True
    Close #iFileNumA
    Close #iFileNumB
    FileCopy sXFile, sFile
    Kill sXFile
  Else
    ' make new file
    iFileNumB = FreeFile
    Open sFile For Output As iFileNumB
      Write #iFileNumB, sName, sValue
      SaveSetting = True
    Close #iFileNumB
  End If
  
End Function

The function is called using this syntax (bTest is declared as a Boolean). The filename (with or without path), the variable name, and the value are all passed to the function as strings. If a path is not included as part of the file name, then the workbook’s own path is used. The value of the function is true unless an error is encountered.

bTest = SaveSetting("C:\test\settings.txt", "test variable", "test value")

Subroutine GetSetting enumerates the variables in the file until the named variable is found, then it extracts the value of this variable.

Function GetSetting(sFile As String, sName As String, _
      Optional sValue As String) As Boolean
  
  Dim iFileNum As Long
  Dim sVarName As String
  Dim sVarValue As String
  Dim lErrLast As Long
  
  ' assume false unless variable is found
  GetSetting = False
  
  ' add this workbook's path if not specified
  If Not IsFullName(sFile) Then
    sFile = ThisWorkbook.Path & "\" & sFile
  End If
  
  ' open text file to read settings
  If FileExists(sFile) Then
    iFileNum = FreeFile
    Open sFile For Input As iFileNum
      Do While Not EOF(iFileNum)
        Input #iFileNum, sVarName, sVarValue
        If sVarName = sName Then
          sValue = sVarValue
          GetSetting = True
          Exit Do
        End If
      Loop
    Close #iFileNum
  End If
  
End Function

The function is called using this syntax. The filename (with or without path) and the variable name are passed to the function as strings. The value of the function is true unless an error is encountered (i.e., the file or the variable is not found), and the value of the variable is passed back by the function.

If GetSetting("C:\test\settings.txt", "test variable", sValue) Then
  MsgBox sValue
End If

Save Debugging Information

During development or debugging of a program, it’s useful to save information during its execution. Subroutine DebugLog saves information in a text file with a name like debuglog051225.txt in the parent workbook’s directory. It saves the date and time along with the debug message, so the timing of the messages can be followed. You can log any string value, including markers indicating how far program execution has progressed, what the value of a key variable is, what an error may have occurred, etc.

Public Sub DebugLog(sLogEntry As String)
  ' write debug information to a log file

  Dim iFile As Integer
  Dim sDirectory As String
  
  sDirectory = ThisWorkbook.Path & "\debuglog" & Format$(Now, "YYMMDD") & ".txt"

  iFile = FreeFile

  Open sFileName For Append As iFile
  Print #iFile, Now; " "; sLogEntry
  Close iFile

End Sub

The following are a few examples of how to use DebugLog.

DebugLog "Starting Execution"

DebugLog "Variable MyVar = " & MyVar

DebugLog "Error " & Err.Number & ": " & Err.Description

The following is an excerpt from an actual debuglog file, debuglog051223.txt created by one of my old projects.

12/23/2005 8:00:33 AM  Excel Version 9.0, Build 8924
12/23/2005 8:00:33 AM  Program Starting
12/23/2005 8:00:33 AM  - File Name: ABC Engineering 2005-12-23-0.doc
12/23/2005 8:00:33 AM  - Order Number: ABC Engineering 2005-12-23-0
12/23/2005 8:00:38 AM  - saved as C:\Orders\ABC Engineering 2005-12-23-0.doc
12/23/2005 8:00:38 AM  - file exists: True
12/23/2005 8:00:38 AM  - no backup directory specified
12/23/2005 8:01:25 AM  - Checking Row 17: 3chars
12/23/2005 8:01:26 AM  - Checking Row 16: 3chars
12/23/2005 8:01:26 AM  - Checking Row 15: 3chars
12/23/2005 8:01:26 AM  - Checking Row 14: 3chars
12/23/2005 8:01:26 AM  - Checking Row 13: 3chars
12/23/2005 8:01:27 AM  - Checking Row 12: 3chars
12/23/2005 8:01:27 AM  - Checking Row 11: 3chars
12/23/2005 8:01:27 AM  - Checking Row 10: 3chars
12/23/2005 8:01:27 AM  - Checking Row 9: 15chars
12/23/2005 8:01:30 AM  - removing extra empty paragraphs
12/23/2005 8:01:56 AM  Program Finished

Supplementary Functions

Function IsFullName(sFile As String) As Boolean
  ' if sFile includes path, it contains path separator "\"
  IsFullName = InStr(sFile, "\") > 0
End Function

Function FullNameToPath(sFullName As String) As String
  ''' does not include trailing backslash
  Dim k As Integer
  For k = Len(sFullName) To 1 Step -1
    If Mid(sFullName, k, 1) = "\" Then Exit For
  Next k
  If k < 1 Then
    FullNameToPath = ""
  Else
    FullNameToPath = Mid(sFullName, 1, k - 1)
  End If
End Function

Function FullNameToFileName(sFullName As String) As String
  Dim k As Integer
  Dim sTest As String
  If InStr(1, sFullName, "[") > 0 Then
    k = InStr(1, sFullName, "[")
    sTest = Mid(sFullName, k + 1, InStr(1, sFullName, "]") - k - 1)
  Else
    For k = Len(sFullName) To 1 Step -1
      If Mid(sFullName, k, 1) = "\" Then Exit For
    Next k
    sTest = Mid(sFullName, k + 1, Len(sFullName) - k)
  End If
  FullNameToFileName = sTest
End Function

Function FileExists(ByVal FileSpec As String) As Boolean
   ' by Karl Peterson MS MVP VB
   Dim Attr As Long
   ' Guard against bad FileSpec by ignoring errors
   ' retrieving its attributes.
   On Error Resume Next
   Attr = GetAttr(FileSpec)
   If Err.Number = 0 Then
      ' No error, so something was found.
      ' If Directory attribute set, then not a file.
      FileExists = Not ((Attr And vbDirectory) = vbDirectory)
   End If
End Function

Final Words

This article was originally posted on an old site which no longer exists. I was able to retrieve my work from this defunct site, so I am reposting it here as is. There are newer techniques for working with text files in Windows, but sometimes the old ways are as simple and effective as the new.

The post Save and Retrieve Information With Text Files appeared first on Peltier Tech Blog.

Pivot Table Resources

$
0
0

Pivot Table Tutorials

There are numerous articles and tutorials about Pivot Tables on the Peltier Tech blog. This is a nearly complete list of Pivot Table posts.

Explore Your Data With Pivot Tables

Pivot tables are one of Excel’s most outstanding features. They allow fast dynamic and interactive analysis of data from the workbook or from any number of external sources. This tutorial shows the power of pivot tables for fast and detailed analysis.

Preliminary Data Exploration with Excel Pivot Tables

In this tutorial we first normalize the data, then generate easy Marginal Means Plots and Interaction Plots to quickly explore the data.

Making Regular Charts from Pivot Tables

Pivot charts are powerful: they are dynamic, interactive, and can be pivoted. However, sometimes you need something that a regular old chart can do, that pivot charts cannot. This tutorial shows how to create a regular chart from a pivot table.

Create and Update a Chart Using Only Part of a Pivot Table’s Data

This tutorial shows how to use a little VBA to create and maintain a chart that uses only part of a pivot table’s data.

Update Regular Chart when Pivot Table Updates

When a  pivot table is pivoted or updated, it may have different numbers of rows and columns, and a regular chart must be updated manually to keep up. Or you could use a little VBA to keep the chart in line with the pivot table.

Using Pivot Table Data for a Chart with a Dual Category Axis

You can easily lay out a pivot table so that two nested fields can be used to populate the labels in a dual category axis.

Grouping by Date in a Pivot Table

If you collect daily data, the day-to-day variation may overwhelm longer-term trends. You can group dates in your pivot table by larger units (weeks, months, years) and perform broader analysis.

Clean Up Date Items in An Excel Pivot Table

Grouping a pivot table by dates can make the table and related chart easier to read. This article shows how to remove extraneous date entries.

Referencing Pivot Table Ranges in VBA

You can create great analyses by merging the power of pivot tables with the flexibility of VBA. This tutorial removes much of the confusion about how to refer to parts of the pivot table in code.

Copy a Pivot Table and Pivot Chart and Link to New Data

If you copy a chart to a new worksheet, it still reflects data from the old worksheet. You can try to fix all the links, but even this tedium will not help with a pivot table. But the approach described here will do the trick.

Pivot Table Conditional Formatting with VBA

Use VBA to format cells within a pivot table according to various conditions.

Dynamic Chart using Pivot Table and VBA

This article shows how VBA can update a regular chart when its pivot table data changes.

Dynamic Chart using Pivot Table and Range Names

This article shows how dynamic range names without VBA can update a regular chart when its pivot table data changes, as long as the number of charted series is unchanged.

Pivot Chart Formatting Changes When Filtered

When you apply a filter or slicer to a PivotChart the custom formatting can change with each change in the filter. Here’s what you can do about it.

Pivot Table Books

Here are a few books about pivot tables, available from Amazon and elsewhere. I’ve selected these books because I know the authors and I’ve used the books, so I can vouch for their quality. Disclosure: if you purchase one of these books using my link, I’ll get a teeny commission.

Beginning PivotTables in Excel 2007: From Novice to Professional

Microsoft Excel Most Valuable Professional Debra Dalgleish explains what PivotTables are, how you can benefit from using them, how to create them and modify them, and how to use their enhanced features. Using a Pivot Table in Microsoft Excel 2007 is a quick and exciting way to slice and dice a large amount of data. Debra carefully explains the benefits of using Pivot Tables for fast data analysis, provides a step-by-step approach to those new to Pivot Tables, and offers tips and tricks that cannot be found elsewhere.

Excel Pivot Tables Recipe Book: A Problem-Solution Approach

Debra Dalgleish, Microsoft Excel Most Valuable Professional since 2001, and an expert and trainer in Microsoft Excel, brings together a one-stop resource for anyone curious about representing, analyzing, and using their data with PivotTables and PivotCharts. Debra presents tips and techniques in this collection of recipes that can’t be found in Excel’s Help section, while carefully explaining the most confusing features of PivotTables to help you realize their powerful potential.

Excel 2013 Pivot Table Data Crunching (MrExcel Library)

This book will help you leverage all the amazing flexibility and analytical power of Pivot Tables. You will learn how to generate complex pivot reports complete with drill-down capabilities and accompanying charts. Then you’ll discover how to build a comprehensive, dynamic pivot table reporting system for any business task or function. Microsoft Excel Most Valuable Professionals Bill Jelen and Mike Alexander include step-by-step instructions, real-world case studies, plus complete and easy recipes for solving your most common business analysis problems.

The post Pivot Table Resources appeared first on Peltier Tech Blog.

Peltier Tech Chart Utilities for Mac Excel – Advanced Edition

$
0
0

It’s nearly finished!

In only a month, I’ve converted the Advanced Edition of the Peltier Tech Chart Utility so that it works on a Mac as well as in Windows. I’m pleased that every feature from the Windows version has made it into the Mac version, though some options are not available. This is due mostly to the inconsistencies between Office on the Mac and Office in Windows, such as the unavailability of modeless forms and the reduced selection of Paste Special options in MacOffice. A small number of differences relate to incompatibilities between the two platforms themselves, such as the strange special keys and special key behavior on the Mac (somehow the Mac’s Cmd-Ctrl-Opt-Shift keys provide less functionality than Windows’ Ctrl-Alt-Shift). And the lack of a customizable ribbon in Mac Office means the user experience is less fulfilling than in Windows.

 The Charts

The Advanced Edition for the Mac has all the custom charts as the Standard Version for the Mac and for Windows: Waterfall, Box Plot, Marimekko, Cluster-Stack, etc., and all the new charts introduced last month in the Advanced Edition for Windows: More Waterfalls, Diverging Stacked Bar, Paretos and Histograms, and more.

In addition to the charts shown here, any new custom charts developed by Peltier Tech will become part of the Advanced Edition. If you hear from the Peltier Tech twitter feed or the Peltier Tech Blog that a new chart has been added (or a bug has been fixed), email for a new download link so you can keep your license up-to-date.

Custom Chart Comparison of All Versions and Editions of the Peltier Tech Chart Utility

The Features

In addition to the helpful features of the Standard Edition, such as Edit Series Formulas, Copy and Paste Series Formats, Label Last Point, and Export Chart as Image File, the Advanced Edition adds such items as Export Range as Image File, Export Charts to PowerPoint and Word, Switch X and Y, and a simpler Error Bar Manager.

In addition to the features shown below, any new functionality developed by Peltier Tech will be added tothe Advanced Edition. If you hear via the Peltier Tech twitter feed or the Peltier Tech Blog that a new feature has been added (or a bug has been fixed), email for a new download link so you can keep your utility current.

Feature Comparison of All Versions and Editions of the Peltier Tech Chart Utility

The Details

The Advanced Edition for the Mac runs on the latest updates of Excel 2011 for the Mac, and whatever relevant versions of the Mac OS that supports Excel 2011. Mavericks, Mountain Lion, Cougar, even Water Buffalo, for all I know, which I find more confusing than Microsoft’s imaginative names, like Windows 7, 8, 3.14, etc. Joking aside, if you keep your Mac software up-to-date, you should have no problems.

Detail Comparison of All Versions and Editions of the Peltier Tech Chart Utility

The Deals

The Advanced Edition of the Peltier Tech Chart Utilities for the Macintosh will be available on Tuesday, July 8, 2104.

The Advanced Edition retails for $99, just slightly more than the $79 for the Standard Edition. But there are some great introductory deals:

  • If you purchase a license for the Advanced Edition between July 8 and July 15, you get it for the same $79 price as the Standard Edition.
  • If you already have a license for the Standard Edition, send me an email and I will send you a coupon code for a free upgrade to the Advanced Edition.
    • In the future, you can upgrade from the Standard to Advanced Edition for only the $20 difference in price.
  • If you have licensed one of the earlier Waterfall or Cluster-Stack Utilities for the Mac, email me and I’ll send a coupon for half off the $79 introductory price.
    • In the future, if you have licensed any of the older utilities, email me for a half-price coupon.
  • When Microsoft releases the long-awaited Excel 2014 for Mac, the Peltier Tech Utility for Mac will be updated, and current licensees will be able to upgrade for no charge.
  • When Microsoft releases Excel 16 for Windows (probably a/k/a Excel 2016 or 2017), the Peltier Tech Chart Utility will be upgraded, and current licensees will as always be able to license the upgrade for half price.

Mark your calendars so you don’t miss the special offers.

The post Peltier Tech Chart Utilities for Mac Excel – Advanced Edition appeared first on Peltier Tech Blog.

Peltier Tech Advanced Chart Utilities for Mac

$
0
0

The Peltier Tech Advanced Chart Utilities for Mac is here.

Over the past month a month, I’ve converted the Advanced Edition of the Peltier Tech Chart Utility so that it works on a Mac as well as in Windows. I’m pleased that every feature from the Windows version has made it into the Mac version, though some options are not available. This is due mostly to the inconsistencies between Office on the Mac and Office in Windows, such as the unavailability of modeless forms and the reduced selection of Paste Special options in MacOffice. A few differences relate to incompatibilities between the two platforms themselves, such as the strange special keys and special key behavior on the Mac (somehow the Mac’s Cmd-Ctrl-Opt-Shift keys provide less functionality than Windows’ Ctrl-Alt-Shift). The lack of a customizable ribbon in Mac Office means the user experience is less fulfilling than in Windows.

 The Charts

The Advanced Edition for the Mac has all the custom charts as the Standard Version for the Mac and for Windows: Waterfall, Box Plot, Marimekko, Cluster-Stack, etc., and all the new charts introduced last month in the Advanced Edition for Windows: More Waterfalls, Diverging Stacked Bar, Paretos and Histograms, and more.

In addition to the charts shown here, any new custom charts developed by Peltier Tech will become part of the Advanced Edition. If you hear from the Peltier Tech twitter feed, the Peltier Tech Facebook page, or the Peltier Tech Blog that a new chart has been added (or a bug has been fixed), email for a new download link so you can keep your license up-to-date.

Custom Chart Comparison of All Versions and Editions of the Peltier Tech Chart Utility

The Features

In addition to the helpful features of the Standard Edition, such as Edit Series Formulas, Copy and Paste Series Formats, Label Last Point, and Export Chart as Image File, the Advanced Edition adds such items as Export Range as Image File, Export Charts to PowerPoint and Word, Switch X and Y, and a simpler Error Bar Manager.

In addition to the features shown below, any new functionality developed by Peltier Tech will be added to the Advanced Edition. If you hear via the Peltier Tech twitter feed or the Peltier Tech Blog that a new feature has been added (or a bug has been fixed), email for a new download link so you can keep your utility current.

Feature Comparison of All Versions and Editions of the Peltier Tech Chart Utility

The Details

The Advanced Edition for the Mac runs on the latest updates of Excel 2011 for the Mac, and the relevant versions of the Mac OS that supports Excel 2011.

Detail Comparison of All Versions and Editions of the Peltier Tech Chart Utility

The Deals

The Advanced Edition retails for $99, just slightly more than the $79 for the Standard Edition. But there are some great introductory deals:

  • If you purchase a license for the Advanced Edition between July 8 and July 15, you get it for the same $79 price as the Standard Edition.
  • If you already have a license for the Standard Edition, send me an email and I will send you a coupon code for a free upgrade to the Advanced Edition.
    • In the future, you can upgrade from the Standard to Advanced Edition for only the $20 difference in price.
  • If you have licensed one of the earlier Waterfall or Cluster-Stack Utilities for the Mac, email me and I’ll send a coupon for half off the $79 introductory price.
    • In the future, if you have licensed any of the older utilities, email me for a half-price coupon.
  • When Microsoft releases the long-awaited Excel 2014 for Mac, the Peltier Tech Utility for Mac will be updated, and current licensees will be able to upgrade for no charge.
  • When Microsoft releases Excel 16 for Windows (probably a/k/a Excel 2016 or 2017), the Peltier Tech Chart Utility will be upgraded, and current licensees will as always be able to license the upgrade for half price.

Visit the Peltier Tech Chart Utilities page to take advantage of these special offers.

The post Peltier Tech Advanced Chart Utilities for Mac appeared first on Peltier Tech Blog.

Swimmer Plots in Excel

$
0
0

A reader of the Peltier Tech Blog asked me about Swimmer Plots. The first chart below is taken from “Swimmer Plot: Tell a Graphical Story of Your Time to Response Data Using PROC SGPLOT (pdf)“, by Stacey Phillips, via Swimmer Plot by Sanjay Matange on the Graphically Speaking SAS blog.

The swimmer chart below is an attempt to show the responses of several patients to drug treatments. Each horizontal stripe represent a patient’s history, color coded by the stage of the patient’s disease at the onset of treatment at month zero. Different events are plotted within each patient’s stripe. The term “Swimmer Plot” comes from the resemblance to lanes in a swimming pool, where swimmers (events) must stay in their own lanes.

Swimmer Plot

The paper cited above gives a detailed protocol and related code for constructing this chart in a statistical graphics package that I’ve never used. The Peltier Tech blog reader wondered if there was a way to build this chart in Excel without having to draw shapes on the chart and locating them inexactly with the mouse.

I’m never one to pass up a reasonable challenge in Excel charting, so I decided to give it a try. This is the kind of chart that can probably be adapted to a variety of uses, and it’s a great way to help people learn how to think outside their usual approaches, to push Excel beyond its supposed limits.

The Approach

One’s first thought might be to build a horizontal bar chart, then use XY scatter data series for the various symbols on the bars. The arrows would have to be shapes drawn on the chart. This mixture of bar and XY chart types causes problems when trying to synchronize axes and aligning markers with bars.

On second thought, though, this chart can be built using XY chart series exclusively. The thick horizontal bands can be made from thick-lined error bars. The arrows at the end of certain bands can also be made using error bars. The only shape needed is for the arrow in the legend.

This entire protocol is one of my longest ever, but it will be worth the ride.

Swimmer Plot Data

All of the data in the chart conforms to two axes. The horizontal (X) axis shows months, either the total duration of the patient’s history or the treatment events. The vertical (Y) axis is simply the index of the subjects (patients): subject 1 is the bottom band in the chart and its associated symbols, subject 2 is the second band and symbols, on up to subject 10 at the top of the chart. In this example, the X axis data has been color coded blue and the Y axis data orange.

This first set of data shows the endpoints of the patient histories. Patients 10 and 3 have month data (18.2 and 9.5 months) in the Stage 1 column, patients 9, 5, and 1 in the Stage 2 column, etc. I optically extracted this data from the chart above before I realized it was included in the pdf article. I’ll take responsibility for any transcription errors.

Swimmer Plot Main Data

Each set of markers in the chart need X (month) and Y (subject) data. The ranges below show data for the four sets of markers and the set of arrows that will be added to the chart.

Swimmer Plot Supplemental Data

Building the Chart: The Swimmer Lanes

The first block of data is used to create the bands in the swimmer chart. Excel’s usual arrangement is to have X values in the first column of the data range and one or more columns of Y values to the right. Our data has Y values in the last column, and several columns of X values to the left. So putting this data into the chart will take a few steps.

Select the Disease Stage 1 column of data, and hold down the Ctrl key to select the unlabeled column of subject indices, then insert an XY Scatter chart. Most of the Disease Stage 1 column is blank, so only two points appear.

Swimmer Plot Construction

I’ve already stretched the chart above to its final size, and I’ve scaled the axes using their ultimate scale parameters. The X axis extends to -1 to allow room for the Durable Responder indicators.

The chart below has had the tick marks and labels removed from the vertical (Y) axis. Note that I’m leaving out chart and axis titles and other annotations to avoid distractions.

Swimmer Plot Construction

Now the next three Disease Stage series must be added. You can do this in at least two ways. My favorite is to select and copy the data, using the Ctrl key if needed to select discontiguous regions, then select the chart and use Paste Special from the Home tab. Use the settings on the screen shot below: add data as new series, values in columns, series names in first row, categories in first column.

Paste Special Dialog

Alternatively, right click on the chart and choose Edit Data from the popup menu or click on Edit Data on the Chart Tools > Design tab to open the Select Data Source dialog. Click the Add button, then populate the Edit Series dialog with the ranges containing the data for the new series.

Select Data Dialog

Repeat until all of the Disease Stages are potted on the chart.

Swimmer Plot Construction

I’ve formatted the markers with the desired formatting for the swimmer plot lanes. Basically I picked four colors that were a bit darker than in the original chart from the cited paper, and lightened them by applying 30% transparency.

Shameless Plug

Previously I noted that the Disease Stage data for this chart was listed with several columns of X data and one column of (shared) Y data. This differs from Excel’s assumption that the data consists of one column of (shared) X data and several columns of Y data. Because of this data arrangement, the chart has to be created tediously, one series at a time.

Such tedium isn’t necessary, however. Using my Peltier Tech Chart Utility, I was able to use the Quick XY Charts feature to create the chart with all of these series in one shot.

Peltier Tech Chart Utility - Quick XY Charts

I selected the data, clicked on the Quick Charts button on the Peltier Tech ribbon, selected Series in Columns and the X-X-Y data layout (highlighted above). The result was this XY Scatter chart, which requires much less manipulation to generate our Swimmer Plot.

Quick XY Swimmer Chart

The series need to be formatted: square markers with the colors and transparency described above and no lines. Also the legend should be moved to the right of the chart.

Back to the Lanes

We’ll use thick error bars as the swimmer lanes. Select one series and add error bars using the “+” icon in Excel 2013…

Add Error Bars in Excel 2013

… or using the Chart Tools > Layout tab in Excel 2007 and 2010.

Add Error Bars in Excel 2007-2010

Excel adds horizontal and vertical error bars to an XY series.

Swimmer Plot Construction

Select the vertical error bars, and click the Delete key. Then select the horizontal error bars and press Ctrl+1 (numeral one) to open the format dialog or task pane. This is the Excel 2013 task pane, but the Excel 2007-2010 format dialog is essentially the same.

Format Error Bars

Select the options shown above: Minus direction only, No End Caps, and Percentage using 100%. The chart below shows Minus 100% error bars with End Caps not removed.

Swimmer Plot Construction

Format the error bar lines with the colors used for the markers, and select a thickness for the bars which will be suitable for the chart.

Format Error Bar Lines

Hey look, bars without a bar chart.

Swimmer Plot Construction

Add and format error bars for the rest of the Disease Stage series.

Swimmer Plot Construction

We need to remove the markers from the chart without removing them from the legend. We have to trick Excel into thinking each series in the legend is formatted with markers while each point is formatted without.Click once to select a series, then again to select a marker, then click Ctrl+1 to open the formatting dialog or task pane for the single point, and choose the No Marker option. The marker from the top Stage 1 point has been removed in this chart:

Swimmer Plot Construction

Repeat; all Stage 1 markers are hidden below:

Swimmer Plot Construction

And repeat for all of the markers:

Swimmer Plot Construction

Add the Treatment Events

Several sets of XY markers are now added. You can copy the data,select the chart, and use Paste Special as described above, or you can use the Select Data Source dialog.

Here is the chart with Complete Response Start markers added to the lanes, with the markers formatted as red triangles like those in the example chart.

Swimmer Plot Construction

Now Partial Response Start points have been added.

Swimmer Plot Construction

Finally, Response Episode End has been added.

Swimmer Plot Construction

Add the Continuation Arrows

The continued Response data is displayed not as markers but as arrows, indicating that the activity extends further to the right than the lanes. This is easy to do with an XY series that shows no markers but instead has error bars with arrowheads on the ends of the bars.

First, add the data as a new series with no markers and a heavy black line. The heavy dark line will somewhat resemble the arrows in the legend.

Swimmer Plot Construction

Add error bars (use the same method as for the error bar lanes above).

Swimmer Plot Construction

Select and delete the vertical error bars as before, then format the horizontal error bars as follows: Plus direction only, No End Caps, and a Fixed Value of 1 (e.g., one month along the X axis).

Format Error Bars

Then format the error bar lines as medium thickness black lines with the appropriate arrowhead type and size. The “begin” arrow points toward the markers, the “end” arrow points away.

Format Error Bar Arrows

The result is a set of arrows extending beyond some of the swimming lanes.

Swimmer Plot Construction

Now we need to remove the black lines from the chart without removing them from the legend. In the same way we hid the unwanted markers from the chart but kept them in the legend to denote the lanes, we can select the entire series with one click, then select one individual line segment, then press Ctrl+1 and format this segment as No Line.

Here the first segment has been hidden.

Swimmer Plot Construction

Now the second segment is hidden.

Swimmer Plot Construction

A few clicks later, all traces of the line are gone.

Swimmer Plot Construction

Add Durable Responder Indicators

Finally, the Durable Responder data is added to the chart. The -0.25 X values place the markers just left of the vertical axis and the start of the lanes.

Swimmer Plot Construction

Final Adjustments

A couple small adjustments improve the look of the chart. First, the vertical axis scale of 0 to 11 leaves rather wide margins above and below the data. If the axis scale min and max are changed to 0.25 and 10.75, this margin is slightly reduced.

The -1 horizontal axis minimum is strange, but changing the horizontal axis number format to 0;;0 hides the negative value.

Swimmer Plot Construction

Finally, if the thick black line is not acceptable as a legend marker for the Continued Response arrows, you can use an arrow for the legend entry.

First, use a white line instead of the black line for the series lines, then hide each segment of this line as you hid the black line segments; this places a white line in the legend. If you had formatted the series as No Line, the line in the legend would not be there, and the markers would be squeezed right up against the legend labels, which does not leave room for a centered arrow.

Then insert an arrow from the Insert Shapes gallery on the ribbon. Format it as a heavy line with the matching arrow appearance. Drag it into the desired position in front of the Continued Response label.

Swimmer Plot Construction

Wrap Up

Charts like this swimmer plot, the related Gantt chart, and other charts were difficult to make in Excel 2003 and earlier versions of Excel. You needed to combine stacked bar chart and XY scatter chart data in the same chart. This required special effort to ;ine up the XY markers with the bars, and keep them aligned.

Excel 2007 introduced much more flexibility in formatting of lines, so you can make thick bars with any line segments, such as series connecting lines and error bars. Swimmer plots and Gantt charts are much easier to make and maintain, because markers and bars are easy to keep in place using a single set of axes.

The post Swimmer Plots in Excel appeared first on Peltier Tech Blog.

Using Pivot Tables in Microsoft Excel

$
0
0

This introduction has been contributed by Debra Dalgleish, Excel MVP.
Contextures, Copyright © 2014. All rights reserved.
Debra Dalgleish, Excel MVP since 2001, is the author of three books on pivot tables, published by Apress. She shares Excel tips, tutorials, and videos on her websites, www.contextures.com and www.pivot-table.com.

What is a Pivot Table?

A pivot table creates an interactive summary from many records.

For example, you may have hundreds of invoice entries in a list on your worksheet.

A pivot table can quickly total the invoices by customer, product or date.

Pivot Table Data

Before you create a Pivot Table or Pivot Chart, organize your data in a table that Excel can understand.

  1. Use Headings: As in this example, the first row must have headings. Use a different heading for each column.
  2. Keep It Together: Keep all the data together — don’t include any completely blank rows or columns in the table.
  3. Isolate It: Leave at least one blank row and one blank column between the data table and any other information on the worksheet.
  4. Create a Named Table: To make it easy to maintain your pivot table, and ensure that new data is included when you update, format the source data as a Named Table.

Create a Pivot Table

Many web sites give instructions for creating a pivot table. (See Pivot Table and Pivot Chart Links).

Create a blank pivot table by clicking a command on the Ribbon.

Click another command and Excel will even recommend a few layouts, based on your data.

Excel shows a preview of a few recommended pivot tables.

After the pivot table is built, Excel displays a task pane summarizing the data in the pivot table.

You can easily rearrange the information in the pivot table by checking the boxes and dragging the buttons to a new position.

Pivot Table Links

The following links on the Contextures web site help with some of the common issues and questions about pivot tables:

These are the most popular pivot table articles on the Contextures web site:

More Pivot Table Resources

The post Using Pivot Tables in Microsoft Excel appeared first on Peltier Tech Blog.

Pivot Tables in Microsoft Excel: Links

$
0
0

This introduction has been contributed by Debra Dalgleish, Excel MVP. 
Contextures, Copyright © 2014. All rights reserved.
Debra Dalgleish, Excel MVP since 2001, is the author of three books on pivot tables, published by Apress. She shares Excel tips, tutorials, and videos on her websites, www.contextures.com and www.pivot-table.com.

Web Sites

Peltier Tech Blog – Pivot Table Resources – a listing of posts on this blog, covering many aspects of pivot tables in Microsoft Excel, including:

Debra Dalgleish’s Excel Tutorials and Videos - which includes these pages of Pivot Table-related topics:

Microsoft – Overview of PivotTable and PivotChart reports
Good introduction to Pivot Tables.

Microsoft – 25 Easy PivotTable Reports
Sample file to download, and on-line instructions

Microsoft – Create a Pivot Table to Analyze Worksheet Data
Basic steps, and links to other articles

Chandoo – Excel Pivot Table Tutorial
Chandoo gives a good overview of pivot tables, with helpful tips and links.

Microsoft Support Articles

Calculated field returns incorrect grand total in Excel (211470)
In a PivotTable, Microsoft Excel may calculate an incorrect grand total for a calculated field.

Pivot Table Uses COUNT Instead of SUM with Blank Cells (110599)
Microsoft Excel automatically uses the SUM function for numeric data and the COUNT function for non-numeric data

How to create a dynamic defined range in an Excel worksheet (830287)
Create a named range that extends to include new information

GETPIVOTDATA formula is automatically created (287736)
When you try to create a simple cell link formula that refers to a cell in the data area of a PivotTable in Microsoft Excel, a GETPIVOTDATA formula is automatically created instead.

You cannot create a PivotTable in Excel 2013 when field names in a source range contain similar characters (2756731)
The data model cannot differentiate between the similar characters.

Pivot Table Books

Here are a few books about pivot tables, available from Amazon and elsewhere. I’ve selected these books because I know the authors and I’ve used the books, so I can vouch for their quality. Disclosure: if you purchase one of these books using my link, I’ll get a teeny commission.

Beginning PivotTables in Excel 2007: From Novice to Professional

Microsoft Excel Most Valuable Professional Debra Dalgleish explains what PivotTables are, how you can benefit from using them, how to create them and modify them, and how to use their enhanced features. Using a Pivot Table in Microsoft Excel 2007 is a quick and exciting way to slice and dice a large amount of data. Debra carefully explains the benefits of using Pivot Tables for fast data analysis, provides a step-by-step approach to those new to Pivot Tables, and offers tips and tricks that cannot be found elsewhere.

Excel Pivot Tables Recipe Book: A Problem-Solution Approach

Debra Dalgleish, Microsoft Excel Most Valuable Professional since 2001, and an expert and trainer in Microsoft Excel, brings together a one-stop resource for anyone curious about representing, analyzing, and using their data with PivotTables and PivotCharts. Debra presents tips and techniques in this collection of recipes that can’t be found in Excel’s Help section, while carefully explaining the most confusing features of PivotTables to help you realize their powerful potential.

Excel 2013 Pivot Table Data Crunching (MrExcel Library)

This book will help you leverage all the amazing flexibility and analytical power of Pivot Tables. You will learn how to generate complex pivot reports complete with drill-down capabilities and accompanying charts. Then you’ll discover how to build a comprehensive, dynamic pivot table reporting system for any business task or function. Microsoft Excel Most Valuable Professionals Bill Jelen and Mike Alexander include step-by-step instructions, real-world case studies, plus complete and easy recipes for solving your most common business analysis problems.

The post Pivot Tables in Microsoft Excel: Links appeared first on Peltier Tech Blog.


Error Bar Ideosyncrasy

$
0
0

After using Excel 2007 for a while, getting used to the idea that everything had changed and we weren’t going back to 2003 ever again, I started fooling around with charts and chart elements. I began to find lots of little changes, most of them actually good ones, even if they were implemented in a funny way (at least until service packs and Excel 2010 cleaned up things).

Anyone who used my first charting utility knows things ain’t always done right the first time, and mine were tiny bits of software. I can’t imagine Microsoft’s task trying to coordinate thousands of developers and a bazillian lines of code.

One of the neat changes I discovered was that error bars were now treated as AutoShape lines, just like any lines in any shapes in Office. This means you had a lot of formatting options available to you, including nice embellishments like arrowheads on the ends of the error bar line segments. Then I forgot about it until a colleague brought it up recently.

To show this nice formatting, let’s look at a simple line chart with simple error bars. For clarity, and to avoid spoiling the story before I’m ready to tell it, I’ll start with positive error bars only.

Simple Line Chart with Simple Error Bars

Select the error bars and click Ctrl+1 (numeral one) to open the Format Error Bars task pane. In the main tab (below the bar chart icon, shown below left) change End Style from Cap to No Cap. Then on the formatting tab (below the paint can icon) check out the Begin and End Arrow Types.

This is the Format Error Bars task pane in Excel 2013; the Format Error Bars dialog in Excel 2007 and 2010 is substantially the same.

Format Error Bar Dialog

The error bar begins at the point, right? And ends at the, uh, end of the error bar, right? At least that’s what seems to make sense. So let’s pick a nice big round ball for the Begin Arrow Type.

Balls at Beginning of Error Bars

And let’s pick a nice big old arrow for the End Arrow Type. I’ve chosen the largest size for both ends of the error bar.

Arrowheads at End of Error Bars

And here’s our line chart with error bars, where the markers of the line chart could be replaced by the balls at the beginning of the error bars, and the arrows point away from the line.

Simple Line Chart with Fancy Ball and Arrowhead Error Bars

This is a very nice embellishment. I’ve used it in several projects already, and shown it to many people.

Anyway, back to the beginning of the story: the message from my colleague was that Excel 2010 and 2013 seem to define the beginnings and ends of the error bars differently.

Well, for positive error bars, Excel 2007, 2010, and 2013 all look the same.

Simple Line Chart with Simple Error Bars

But if we look at negative error bars, only Excel 2013 shows them beginning at the points and ending at the ends of the error bars, pointing downward. Excel 2007 and 2010 show the balls at the ends of the error bars and the arrowheads at the points, pointing upward. That’s bizarre.

Simple Line Chart with Simple Error Bars

Even more bizarre, if the error bars go both ways, only Excel 2013 has symmetric arrows. Excel 2010 shows both sets of arrows pointing upward, the negative ones toward the points, the positive ones away from the points. And Excel 2007 only has one set of arrows, beginning at the end of the negative error bars, ending at the ends of the positive error bars. Though if you had to, you could just pretend the end was the beginning and vice versa. Whatevs.

Simple Line Chart with Simple Error Bars

Excel 2007’s charting infrastructure was finished quickly at the end of the development cycle, so a few glitches weren’t ironed out of the final product. Excel 2010 fixed a lot of inconsistencies in Excel 2007’s charts, but these error bars show that not everything was totally fixed. In Excel 2007 or 2010 you could fake it with a second, hidden plotted series, and format two sets of error bars so they looked right. Excel 2013 has gotten the error bars working nicely, though.

The post Error Bar Ideosyncrasy appeared first on Peltier Tech Blog.

Chart Events in Microsoft Excel

$
0
0

Chart Events

When you use a computer, you continuously interact with objects and programs, through events. An event is anything that happens, such as moving the mouse, clicking on objects, changing data, or activating windows. Programs can raise events of their own as well. A program can respond to events using event procedures. For example, if you click a scroll button, Excel responds by scrolling the window down.

As a programmer, you can write event procedures that will respond to (or trap) events by users. These event procedures can trap events in the worksheet, in the workbook, at the application level, or in a chart. In this article, I introduce you to chart event procedures in Microsoft Excel, which you can use for charts on a chart sheet and embedded charts.

Why Use Chart Events?

Chart events can make it much easier for people to use your programs, and add interactivity to your charts. Perhaps you need users to select a point in a series. If you create an event procedure that detects a click on the chart, users won’t have to type in a series name and a point number.

After the click the program can perform one or more useful tasks:

  • Display a customized chart tip;
  • Extract information from the chart and place it in a worksheet;
  • Activate another chart or worksheet;
  • Identify points to be included in a subsequent analysis.

Although Excel can accept data in a variety of formats and arrangements, you can do certain things with the data to ensure your charts are easy to build and maintain. “Good data” has these characteristics:

  1. Data for each series is arranged in Columns (preferable to Rows)
  2. First column is used for Categories (X axis labels)
  3. First row is used for Series Names
  4. Top left cell is blank
  5. Data below series names is numeric (right-adjusted with no alignment specified)
  6. There are no blank rows or blank columns within the data range
  7. There is a buffer row or column between the table and any other non-blank cells.

Well-Formed Chart Data

In this case, I use sample data similar to the above above to demonstrate chart event procedures.

Chart Sheet Events

The first set of examples is for charts that reside on their own sheets, not embedded in worksheets. These examples are contained in the downloadable workbook ChartSheetEvents.xlsm.

Create A Chart Sheet

Select the entire range you want included in your chart, or select a single cell within this range. If you followed guidelines 6 and 7 about Good Data, Excel selects the range of continuous data that includes the selected cell.

Select the data range, or a single cell within the data range. Press the F11 function key, to quickly create a chart sheet from the data range range, using the default chart type.

Chart Sheet

The Chart Code Module

Right-click the chart sheet tab, and select View Code from the pop-up menu. This opens the Visual Basic Editor (VBE).

Chart Sheet Tab Context Menu

Within the VBE, a code module appears with the caption ChartSheetEvents.xlsm – Chart1 (code):

Chart Code Module

This is a special kind of code module, which is associated with the chart. Code contained in this module runs when events occur on the chart.

The code module should contain only the line

Option Explicit

This line means any variable used in the module must be explicitly declared prior to use. This approach is slightly more work, but it assures that no errant variable will be accidentally defined by a typographical error.

If the module does not include the Option Explicit line, type it in, then go to the VBE’s Tools menu, select Options…, and on the Editor tab, check the Require Variable Declarations box. Every module you create after setting this option will automatically contain the Option Explicit line.

While you’re in the dialog, you may as well uncheck Auto Syntax Check, which pops up a dialog whenever you enter code with a syntax error. Since the code with an error is also colored red, there’s no need for an annoying dialog which you have to cancel to continue.

Chart Code Module with Event Procedure Stub

Chart Event Procedure

At the top of the code module, you see two dropdowns. One contains the items (General) and Chart, the other contains (Declarations). While you can type your entire event procedure from scratch, it’s easier to use these dropdowns when creating procedures.

Select Chart from the left hand dropdown. The following stub of an event procedure appears in the code module:

Chart Code Module with Event Procedure Stub

Private Sub Chart_Activate()
 
End Sub

This procedure runs whenever the chart is activated. Between these lines, type whatever code you want to be executed when the chart is activated. For example:

Private Sub Chart_Activate()
    MsgBox "Welcome to my Chart!"
End Sub

Now when you activate the chart, the following message box appears:

Welcome Message Box

This example is demonstrated using the chart named Welcome in the companion workbook. This is just an example. Remove the message box code before it makes you insane.

More Chart Events

Chart_Activate is good for illustration of chart events, but other events can be much more useful. The chart events available to you are listed below. These can be accessed from the right hand dropdown in the chart code module when Chart is selected in the left hand dropdown.

  • Activate
  • BeforeDoubleClick
  • BeforeRightClick
  • Calculate
  • Deactivate
  • DragOver
  • DragPlot
  • MouseDown
  • MouseMove
  • MouseUp
  • Resize
  • Select
  • SeriesChange

Next you can use an event to tell which chart element has been selected. Choose Chart from the left hand dropdown of the code module, then choose Select from the right hand dropdown, to produce the following procedure stub:

Chart Code Module with Event Procedure Stub

Private Sub Chart_Select(ByVal ElementID As Long, _
        ByVal Arg1 As Long, ByVal Arg2 As Long)
 
End Sub

Note that I’ve inserted the line continuation character (an underscore) in the first line to wrap the line at a convenient place.

The Chart_Select event fires whenever a chart element has been selected. Three arguments are passed to the procedure: ElementID, which identifies the selected chart element, and Arg1 and Arg2, which provide additional information. For example, if ElementID identifies that a series has been selected, Arg1 identifies which series has been selected, and Arg2 identifies the point within the series which has been selected, or Arg1 = -1 to indicate that the entire series is selected. If Arg1 or Arg2 are not relevant to the selected ElementID, they are assigned the value zero.

When you select Chart from the left hand dropdown, the Chart_Activate procedure shell is created in the code module (Activate is the default event for a chart). You can ignore it, delete it, or use it for another purpose.

This table lists the ElementID values, and the meanings of their associated Arg1 and Arg2 parameters.

Chart Element List

No need to memorize the details, since the VBE Object Browser (VBE View menu > Object Browser) knows everything.

Object Browser showing Chart Element List

Now you can add a line to the procedure to identify which chart element has been selected, and show the values of its associated arguments:

Private Sub Chart_Select(ByVal ElementID As Long, _
        ByVal Arg1 As Long, ByVal Arg2 As Long)
 
    MsgBox "Element: " & ElementID & vbCrLf & "  Arg 1: " & Arg1 _
        & vbCrLf & "  Arg 2: " & Arg2
 
End Sub

To test your event procedure, select the chart’s title. Click OK in the message box, and then test your event procedure with other elements, such as a series, and a point in a series.

The following three message boxes appear when selecting the Chart Title (ElementID = 4), Series 1 (ElementID = 3, Arg1 = 1, and Arg2 = -1), and Series 1 Point 4 (ElementID = 3, Arg1 = 1, Arg2 = 4). To select an individual point, you must single click twice: once to select the entire series, then again to select the point.

Object Browser showing Chart Element List

This example is demonstrated using the chart named Select in the companion workbook.

These message boxes aren’t very informative – text descriptions would be more useful. Replace the Chart_Select event code with the following more extensive procedure. It converts the values to text, and creates a more informative message:

Private Sub Chart_Select(ByVal ElementID As Long, _
        ByVal Arg1 As Long, ByVal Arg2 As Long)
 
    Dim sElement As String
    Dim sArg As String
 
    Select Case ElementID
        Case xlChartArea
            sElement = "Chart Area"
        Case xlChartTitle
            sElement = "Chart Title"
        Case xlPlotArea
            sElement = "Plot Area"
        Case xlLegend
            sElement = "Legend"
        Case xlFloor
            sElement = "Floor"
        Case xlWalls
            sElement = "Walls"
        Case xlCorners
            sElement = "Corners"
        Case xlDataTable
            sElement = "Data Table"
        Case xlSeries
            sElement = "Series " & Arg1
            If Arg2 > 0 Then sArg = "Point " & Arg2
        Case xlDataLabel
            sElement = "Data Label"
            sArg = "Series " & Arg1
            If Arg2 > 0 Then sArg = sArg & ", Point " & Arg2
        Case xlTrendline
            sElement = "Trendline"
            sArg = "Series " & Arg1 & ", Trendline " & Arg2
        Case xlErrorBars
            sElement = "Error Bars"
            sArg = "Series " & Arg1
        Case xlXErrorBars
            sElement = "X Error Bars"
            sArg = "Series " & Arg1
        Case xlYErrorBars
            sElement = "Y Error Bars"
            sArg = "Series " & Arg1
        Case xlLegendEntry
            sElement = "Legend Entry"
            sArg = "Series " & Arg1
        Case xlLegendKey
            sElement = "Legend Key"
            sArg = "Series " & Arg1
        Case xlAxis
            sElement = IIf(Arg1 = 1, "Primary ", "Secondary ")
            sElement = sElement & IIf(Arg2 = 1, "Category ", "Value ")
            sElement = sElement & "Axis"
        Case xlMajorGridlines
            sElement = IIf(Arg1 = 1, "Primary ", "Secondary ")
            sElement = sElement & IIf(Arg2 = 1, "Category ", "Value ")
            sElement = sElement & "Major Gridlines"
        Case xlMinorGridlines
            sElement = IIf(Arg1 = 1, "Primary ", "Secondary ")
            sElement = sElement & IIf(Arg2 = 1, "Category ", "Value ")
            sElement = sElement & "Minor Gridlines"
        Case xlAxisTitle
            sElement = IIf(Arg1 = 1, "Primary ", "Secondary ")
            sElement = sElement & IIf(Arg2 = 1, "Category ", "Value ")
            sElement = sElement & "Axis Title"
        Case xlDisplayUnitLabel
            sElement = IIf(Arg1 = 1, "Primary ", "Secondary ")
            sElement = sElement & IIf(Arg2 = 1, "Category ", "Value ")
            sElement = sElement & "Axis Display Unit Label"
        Case xlUpBars
            sElement = "Up Bars"
            sArg = "Group Index " & Arg1
        Case xlDownBars
            sElement = "Down Bars"
            sArg = "Group Index " & Arg1
        Case xlSeriesLines
            sElement = "Series Lines"
            sArg = "Group Index " & Arg1
        Case xlHiLoLines
            sElement = "High-Low Lines"
            sArg = "Group Index " & Arg1
        Case xlDropLines
            sElement = "Drop Lines"
            sArg = "Group Index " & Arg1
        Case xlRadarAxisLabels
            sElement = "Radar Axis Labels"
            sArg = "Group Index " & Arg1
        Case xlShape
            sElement = "Shape"
            sArg = "Shape Number " & Arg1
        Case xlNothing
            sElement = "Nothing"
    End Select
 
    MsgBox sElement & IIf(Len(sArg) > 0, vbCrLf & sArg, "")
End Sub

Test your new code, by selecting elements in the chart. Here are the revised message boxes, made more informative by analyzing the ElementID and other arguments:

Object Browser showing Chart Element List

This example is demonstrated using the chart named Nicely Select in the companion workbook.

This is a more useful procedure, because it tells us in human words what has been selected. On the other hand, it is less useful than it could be, because it pops up a message box every time a new chart element is selected, forcing the user to clear the message box before proceeding.

Identify the Point Clicked By the User

Another useful event procedure tells you which point was clicked on, and display its values. Chart_Select is not the best event to trap to detect clicking on a point, because two Chart_Select events must occur when a point is selected: the series is selected by the first click, and the point by the second. The MouseUp event is a better event to trap.

To create a new event procedure, choose Chart in the left dropdown and MouseUp in the right, to create this shell:

Private Sub Chart_MouseUp(ByVal Button As Long, ByVal Shift As Long, _
        ByVal x As Long, ByVal y As Long)
 
End Sub

Four arguments are passed to this procedure.

Button tells which mouse button was released: xlNoButton, xlPrimaryButton (usually the left button), xlSecondaryButton (right button), or xlMiddleButton.

Shift tells which keys are depressed when the mouse button was released. The value of Shift can be one or a sum of several of the following values:

Shift Key Codes

For example, if Shift = 2, the CTRL key was depressed when the mouse button was clicked; if Shift = 5, both the SHIFT and ALT keys were depressed.

The coordinates of the cursor, x and y, are in chart object client coordinate units. It’s not necessary to be concerned about these, since you just pass them along to other functions to get more useful information.

Test the following event procedure, which uses Chart_MouseUp to determine where the mouse click occurred. The procedure:

  • traps the release of the button,
  • determines where on the chart the click occurred (x, y),
  • passes these coordinates to the GetChartElement function to determine what chart element is located at these coordinates,
  • determines whether a data point (or data label) is located at the mouse click,
  • extracts the X and Y values for the data point, if the click occurred at a data point or data label,
  • displays this information in a message box.
Private Sub Chart_MouseUp(ByVal Button As Long, ByVal Shift As Long, _
        ByVal x As Long, ByVal y As Long)
 
    Dim ElementID As Long, Arg1 As Long, Arg2 As Long
    Dim myX As Variant, myY As Double
 
    With ActiveChart
        ' Pass x & y, return ElementID and Args
        .GetChartElement x, y, ElementID, Arg1, Arg2
 
        ' Did we click over a point or data label?
        If ElementID = xlSeries Or ElementID = xlDataLabel Then
            If Arg2 > 0 Then
                ' Extract x value from array of x values
                myX = WorksheetFunction.Index _
                    (.SeriesCollection(Arg1).XValues, Arg2)
                ' Extract y value from array of y values
                myY = WorksheetFunction.Index _
                    (.SeriesCollection(Arg1).Values, Arg2)
 
                ' Display message box with point information
                MsgBox "Series " & Arg1 & vbCrLf _
                    & """" & .SeriesCollection(Arg1).Name & """" & vbCrLf _
                    & "Point " & Arg2 & vbCrLf _
                    & "X = " & myX & vbCrLf _
                    & "Y = " & myY
            End If
        End If
    End With
End Sub

Here is an informative dialog that results from clicking on the 4th point of the first series. Compare to the third dialog from the last example above.

Mouse Up Dialog

This example is demonstrated using the chart named Identify Point in the companion workbook.

You could do many things with the data from this procedure.

  • A message box requires a user response to continue; you could replace the dialog by drawing a textbox with the same information, as a smarter chart tip. Use the MouseMove event instead, to mimic Excel’s normal chart tip behavior.
  • You could place this data into a worksheet range. After clicking on several points, you would have a small table of values from the selected points. These could be used for subsequent analysis.
  • You could identify the clicked point, then jump to another appropriate chart. This approach has the effect of drilling down deeper into the data. See the short example below.

Drill Down to a Related Chart

Suppose the values for the categories A through E in the chart reflected sums of other values. You could have several other chart sheets, Chart A through Chart E, that show detail for the selected categories. An event procedure such as the following produces this kind of drill down effect (to test the procedure, create chart sheets named Chart A, Chart B, etc.):

Private Sub Chart_MouseUp(ByVal Button As Long, ByVal Shift As Long, _
        ByVal x As Long, ByVal y As Long)
 
    Dim ElementID As Long, Arg1 As Long, Arg2 As Long
    Dim myX As Variant
 
    With ActiveChart
        ' Pass x & y, return ElementID and Args
        .GetChartElement x, y, ElementID, Arg1, Arg2
 
        ' Did we click over a point or data label?
        If ElementID = xlSeries Or ElementID = xlDataLabel Then
            If Arg2 > 0 Then
                ' Extract x value from array of x values
                myX = WorksheetFunction.Index _
                    (.SeriesCollection(Arg1).XValues, Arg2)
 
                ' Don't crash if chart doesn't exist
                On Error Resume Next
                ' Activate the appropriate chart
                ThisWorkbook.Charts("Chart " & myX).Select
                On Error GoTo 0
            End If
        End If
    End With
End Sub

To return to the starting chart on another mouse click, you can add the following Chart_MouseUp event procedure to the code modules of the detail charts. For example, add the following procedure to the code module for the Chart A sheet. When you select an element in Chart A, you’ll return to the main chart:

Private Sub Chart_MouseUp(ByVal Button As Long, ByVal Shift As Long, ByVal x As Long, ByVal y As Long)

    ' Don't crash if chart doesn't exist
    On Error Resume Next
    ' Return to calling chart
    ThisWorkbook.Charts("Chart Drilldown").Select
    On Error GoTo 0

End Sub

This example is demonstrated using the charts named DrillDown and Chart A through Chart E in the companion workbook.

The VBE Project Explorer

You may have noticed the Project Explorer window of the Visual Basic Editor. By default it is docked in the upper left of the VB window. If the Project Explorer window is not open, from within the VBE, choose VBE View menu > Project Explorer or press Ctrl+R. Here is the Project Explorer window in its floating (undocked) state.

VBE Project Explorer Pane

Every VBA Project that you have open in Excel is listed in the Project Explorer, including open workbooks and installed add-ins. If the project is unprotected, its constituent objects are listed in a tree view structure underneath it. If the folder icon in the toolbar is selected, the objects are grouped. If the folder icon is not selected, the objects are listed in alphabetical order without grouping.

You can see three of the four groups of objects in the screenshot above. All chart sheets and worksheets are listed under the Microsoft Excel Objects group, with the ThisWorkbook object that represents the workbook itself. Regular code modules are listed under the Modules group, where we see the module named MChartEvents in the workbook ChartClassEvents.xlsm. The Class Modules group contains class modules, such as CAppEvent and CChartEvent, which will be constructed later in this article. If a project has any user forms, these will be listed under the Forms group.

Under Microsoft Excel Objects, the sheets and workbook are listed in alphabetical order by their “Code Name”. The Code Name is the name of the object in the VB Editor; we see code names Chart1 through Chart5, Chart5a through Chart5e, Sheet1, and ThisWorkbook are shown above. The Excel name of an object is shown in parentheses after its Code Name. You can change the Code Name by changing the (Name) property in the VBE’s Properties window; if you change the Name property, the name displayed on the sheet tab in Excel will be changed.

To access a sheet’s code module, double click it in the Project Explorer window, or right-click a sheet tab in Excel and choose View Code. To access the workbook’s code module, double-click on the ThisWorkbook object in the Project Explorer window.

New Forms, Modules, and Class Modules are added to a project using the VBE’s Insert menu. A new chart sheet or worksheet object is added whenever a sheet is created within Excel. A new project is added to the Project Explorer’s list when a workbook is created or opened, or an add-in is installed, within Excel.

Embedded Chart Events

The approach I have described so far is effective, but only for a single chart sheet. To apply to multiple chart sheets, the event code has to be copied to each chart sheet’s code module. It does not work at all for embedded charts.

A more flexible and powerful technique is to use a class module to trap chart events. A class module can be used for any chart, whether it’s an embedded chart or chart sheet. And it eliminates the need to place the code in a chart sheet’s code module. Any events in the code module of a chart are available in a chart event class module. A chart event class module is demonstrated in the downloadable workbook ChartClassEvents.xlsm.

To create a new class module, click Alt+F11 to switch to the VB Editor. Make sure the ChartClassEvents.xlsm workbook is selected in the Project Explorer window.

Within the VBE, choose Insert menu > Class Module. A new code module opens, with the caption ChartClassEvents.xlsm – Class1 (Code). If the Properties window is not open, choose View menu > Properties, or press the F4 function key. In the Properties window, change the class name to CChartEvent, following the convention that the name of a class module begins with capital C.

The class module should begin with this line:

Option Explicit

If not, follow the instructions in The Chart Code Module subsection in the Chart Sheet Events section of this article, above.

Next, add this line in the Declarations section of the class module, to declare a Chart type object with event trapping enabled.

Public WithEvents EventChart As Chart

After adding this line, the class module contains the EventChart item in the left hand dropdown, in addition to (General) and Class. When the EventChart item is selected, all of the chart events described in the first half of this article appear in the right hand dropdown.

To create the equivalent chart event procedure as you created in the “More Chart Events” subsection above, select EventChart from the left dropdown and Select from the right dropdown, to produce this procedure shell:

Private Sub EventChart_Select(ByVal ElementID As Long, _
        ByVal Arg1 As Long, ByVal Arg2 As Long)
 
End Sub

The shell of the EventChart_Activate procedure is produced when the EventChart item is selected in the left dropdown. This can be deleted or ignored. Add the Msgbox command within this procedure to identify the element and arguments for the selected chart element. The entire class module code should look like this:

Option Explicit
 
' Declare object of type "Chart" with events
Public WithEvents EventChart As Chart
 
Private Sub EventChart_Select(ByVal ElementID As Long, _
        ByVal Arg1 As Long, ByVal Arg2 As Long)
 
    MsgBox "Element: " & ElementID & vbCrLf & "  Arg 1: " & Arg1 _
        & vbCrLf & "  Arg 2: " & Arg2
 
End Sub

The code is almost ready to trap chart events, but first you need to enable events for the chart.

Enabling Events for the Chart

Make sure the ChartClassEvents.xls workbook is selected in the Project Explorer window. From the VBE Insert menu, select Module. A new code module opens, with the caption ChartClassEvents.xls – Module1 (Code). In the Properties window, change the module name to MChartEvents, following the convention that the name of a regular module begins with capital M.

The module should begin with this line:

Option Explicit

If not, follow the instructions in “The Chart Code Module” section. Now you must declare an instance of the chart events class, by adding this line in the Declarations section of the class module, immediately below the Option Explicit line.

Dim clsChartEvent As New CChartEvent

Next, you create two procedures, Set_This_Chart and Reset_Chart, To activate a chart for events, you assign the active chart to the EventChart property of the instance of the class:

Set clsChartEvent.EventChart = ActiveChart

To deactivate the chart for events, you assign the EventChart property of the instance of the class to Nothing:

Set clsChartEvent.EventChart = Nothing

These two lines are wrapped in the Set_This_Chart and Reset_Chart procedures, with a check within the Set_This_Chart procedure to prevent errors if no chart is selected. The entire module looks like this:

Option Explicit
 
Dim clsChartEvent As New CChartEvent
 
Sub Set_This_Chart()
    ' Skip if no chart is selected to prevent an error
    If Not ActiveChart Is Nothing Then
        ' Enable events for the active chart
        ' Works for chart sheets and embedded charts
        Set clsChartEvent.EventChart = ActiveChart
    End If
End Sub
 
Sub Reset_Chart()
    ' Disable events for chart previously enabled as active chart
    Set clsChartEvent.EventChart = Nothing
End Sub

To test the procedures, select any chart, embedded or chart sheet, and run Set_This_Chart. Now select any chart element, and a message box pops up to tell you the ElementID, Arg1, and Arg2.

Enabling Events for Chart(s)

This approach is fine for a single embedded chart, but it can be broadened to include all charts embedded in the active sheet. Instead of a variable clsChartEvent, you declare an array clsChartEvents() to contain all of the enabled charts, and wrap them within loops so all embedded charts on the active sheet are included.

Adjust the MChartEvents module to look like this:

Option Explicit
 
Dim clsChartEvents() As New CChartEvent
 
Sub Set_All_Charts()
    ' Enable events for all charts embedded on a sheet
    ' Works for embedded charts on a worksheet or chart sheet
    If ActiveSheet.ChartObjects.Count > 0 Then
        ReDim clsChartEvents(1 To ActiveSheet.ChartObjects.Count)
        Dim chtObj As ChartObject
        Dim chtnum As Integer
 
        chtnum = 1
        For Each chtObj In ActiveSheet.ChartObjects
            ' Debug.Print chtObj.Name, chtObj.Parent.Name
            Set clsChartEvents(chtnum).EventChart = chtObj.Chart
            chtnum = chtnum + 1
        Next ' chtObj
    End If
End Sub
 
Sub Reset_All_Charts()
    ' Disable events for all charts previously enabled together
    Dim chtnum As Integer
    On Error Resume Next
    Set clsChartEvent.EventChart = Nothing
    For chtnum = 1 To UBound(clsChartEvents)
        Set clsChartEvents(chtnum).EventChart = Nothing
    Next ' chtnum
End Sub

Activate a sheet with embedded charts and run Set_All_Charts. All embedded charts will now respond to chart events as the single embedded chart did in the previous section. This approach works for any embedded charts on a worksheet or a chart sheet (yes, you can embed chart objects on a chart sheet).

The previous code won’t activate the parent chart sheet, however. You reinstate the clsChartEvent declaration, to be used with the chart sheet, and adjust the Set_All_Charts procedure to activate a chart sheet and then activate the embedded charts.

Modify the module to look like this:

Option Explicit
 
Dim clsChartEvent As New CChartEvent
Dim clsChartEvents() As New CChartEvent
 
Sub Set_All_Charts()
    ' Enable events for active sheet if sheet is a chart sheet
    If TypeName(ActiveSheet) = "Chart" Then
        Set clsChartEvent.EventChart = ActiveSheet
    End If
 
    ' Enable events for all charts embedded on a sheet
    ' Works for embedded charts on a worksheet or chart sheet
    If ActiveSheet.ChartObjects.Count > 0 Then
        ReDim clsChartEvents(1 To ActiveSheet.ChartObjects.Count)
        Dim chtObj As ChartObject
        Dim chtnum As Integer
 
        chtnum = 1
        For Each chtObj In ActiveSheet.ChartObjects
            ' Debug.Print chtObj.Name, chtObj.Parent.Name
            Set clsChartEvents(chtnum).EventChart = chtObj.Chart
            chtnum = chtnum + 1
        Next ' chtObj
    End If
End Sub
 
Sub Reset_All_Charts()
    ' Disable events for all charts previously enabled together
    Dim chtnum As Integer
    On Error Resume Next
    Set clsChartEvent.EventChart = Nothing
    For chtnum = 1 To UBound(clsChartEvents)
        Set clsChartEvents(chtnum).EventChart = Nothing
    Next ' chtnum
End Sub

Using Event Procedures to Enable Chart Events

Event procedures in Microsoft Excel have different levels of influence. In the earlier example, the event procedures in the code module behind a chart sheet only detect events within the chart sheet. Similarly, event procedures on a worksheet’s code module only detect events in that worksheet. Event procedures on a workbook’s code module trap events that occur in all sheets within the workbook. Finally, application-level event procedures watch over all sheets and workbooks in Excel. There is no application code module, however, so you need to create a special class module to handle application events.

Using these events is a more convenient way to activate chart events than running the Set_All_Charts and Reset_All_Charts procedures used above. The following code examples demonstrate how you can use events to set different levels of activation for chart events:

  1. all charts in one worksheet
  2. all charts in one chart sheet
  3. all charts on all sheets in one workbook
  4. all charts on all sheets in all workbooks

You can decide which level of activation you need, based on the purpose of your chart event code. If you are only concerned with a single chart in one worksheet, you can stop with the first example. If you have built an extensive add-in that processes events for any charts, you need a full-blown application events class module. The companion workbook ChartClassEvents.xlsm follows level 4.

1. Worksheet Events to Enable All Charts In One Worksheet

You must trap the Activate and Deactivate events for the desired worksheet, and use these events to run the Set_All_Charts and Reset_All_Charts procedures. Right-click the sheet tab, and choose View Code from the pop up menu to open the VBE. You see a new code module with the caption ChartClassEvents.xls – Sheet1 (Code), assuming this is Sheet1. Choose Worksheet on the left hand dropdown and Activate from the right hand dropdown. Now type the line Set_All_Charts inside the Worksheet_Activate procedure stub. Then choose Deactivate from the right hand dropdown, and type the line Reset_All_Charts inside the Worksheet_Deactivate procedure stub. You see the following in the code module:

Option Explicit
 
Private Sub Worksheet_Activate()
    Set_All_Charts
End Sub
 
Private Sub Worksheet_Deactivate()
    Reset_All_Charts
End Sub

This code turns on chart events for all charts embedded in the worksheet when it is activated, then turns off chart events when the worksheet is deactivated. If your program executes additional code in the Worksheet_Activate and _Deactivate events, include the lines above with the other code, in the order that works best for your application.

2. Chart Sheet Events to Enable All Charts In One Chart Sheet

You need to trap the Activate and Deactivate events for the desired chart sheet, and use these events to run the Set_All_Charts and Reset_All_Charts procedures. To open the VBE, right-click the sheet tab, and choose View Code from the pop up menu. It opens the code module with the caption ChartClassEvents.xls – Chart1 (Code), assuming this is Chart1. Choose Chart on the left dropdown and Activate from the right dropdown, and type the line Set_All_Charts inside the Chart_Activate procedure shell. Then choose Deactivate from the right dropdown, and type the line Reset_All_Charts inside the Chart_Deactivate procedure shell. You see the following in the code module:

Option Explicit
 
Private Sub Chart_Activate()
    Set_All_Charts
End Sub
 
Private Sub Chart_Deactivate()
    Reset_All_Charts
End Sub

This code turns on chart events for the chart sheet itself and for all charts embedded in the chart sheet when the sheet is activated, then turns off chart events when the sheet is deactivated. If your program executes additional code in the Chart_Activate and _Deactivate events, include the lines above with the other code, in the order that works best for your application.

3. Workbook Events to Enable All Charts On All Sheets In One Workbook

Remove the Worksheet_Activate, Worksheet_Deactivate, Chart_Activate, and Chart_Deactivate code that enables chart events for specific worksheets or chart sheets. These procedures are rendered redundant by the following Workbook_SheetActivate and _SheetDeactivate event procedures.

You must trap the Activate and Deactivate events for all sheets (worksheets and chart sheets) in the desired workbook, and use these events to run the Set_All_Charts and Reset_All_Charts procedures. Right-click the small Excel icon to the left of the File menu, and choose View Code from the pop up menu to open the VBE. It opens the code module with the caption ChartEvents.xls – ThisWorkbook (Code). Choose Workbook on the left dropdown, SheetActivate from the right dropdown, and type the line Set_All_Charts inside the Workbook_SheetActivate procedure stub. Then choose SheetDeactivate from the right dropdown, and type the line Reset_All_Charts inside the Workbook_SheetDeactivate procedure stub. You now see the following in the code module:

Option Explicit
 
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    Set_All_Charts
End Sub
 
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    Reset_All_Charts
End Sub

This code turns on chart events for all charts embedded in the newly activated sheet, and for the sheet itself if it’s a chart sheet, then turns off chart events when the sheet is deactivated. If your program executes additional code in the Workbook_SheetActivate and _SheetDeactivate events, include the lines above with the other code, in the order that works best for your application.

4. Application Events to Enable All Charts on All Sheets In All Workbooks

You must trap the Activate and Deactivate events for all sheets (worksheets and chart sheets) in any workbook, and the Activate and Deactivate events for all workbooks, and use these events to run the Set_All_Charts and Reset_All_Charts procedures. This process is a little more involved than using sheet or workbook events because you must create a class module to detect application events.

To create the Application Event Class Module, switch to the VB Editor to create a new class module. Make sure the ChartClassEvents.xls workbook is selected in the Project Explorer window. In the VBE, choose Insert menu > Class Module. A new code module opens with the caption ChartClassEvents.xls – Class1 (Code). If the Properties window is not open, choose View menu > Properties or press the F4 function key. In the Properties window, change the class name to CAppEvent (following the convention that the name of a class module begins with a capital C). Now declare an Application type object with event trapping enabled, by adding this line in the Declarations section of the class module.

Public WithEvents EventApp As Excel.Application

After adding this line, the class module contains the EventApp item in the left dropdown, in addition to (General) and Class. Select EventApp from the left dropdown, and select in turn SheetActivate, SheetDeactivate, WorkbookActivate, and WorkbookDeactivate from the right dropdown. Insert the line Set_All_Charts in the Activate event procedures, and Reset_All_Charts in the Deactivate event procedures. The CAppEvent class module should now contain this code:

Option Explicit
 
Public WithEvents EventApp As Excel.Application
 
Private Sub EventApp_SheetActivate(ByVal Sh As Object)
    Set_All_Charts
End Sub
 
Private Sub EventApp_SheetDeactivate(ByVal Sh As Object)
    Reset_All_Charts
End Sub
 
Private Sub EventApp_WorkbookActivate(ByVal Wb As Workbook)
    Set_All_Charts
End Sub
 
Private Sub EventApp_WorkbookDeactivate(ByVal Wb As Workbook)
    Reset_All_Charts
End Sub

You must create an instance of the application class before it will respond to events. To activate the application event class, in the MChartEvents module, add a declaration line:

Dim clsAppEvent As New CAppEvent

Insert the following procedures into the MChartEvents module. The first tells the class that it is responding to events in the current application, and enables events in the active sheet’s charts. The second tells the class that it is responding to events in Nothing (no events!), and disables events in the active sheet’s charts.

Sub InitializeAppEvents()
  Set clsAppEvent.EventApp = Application
  Set_All_Charts
End Sub
 
Sub TerminateAppEvents()
  Set clsAppEvent.EventApp = Nothing
  Reset_All_Charts
End Sub

The last step in activating application-level events is to run the InitializeAppEvents procedure. You could use a command bar button or menu command for this, but those approaches both require the user to remember to go click something. Since you now are an expert on events, you can use workbook events to activate the application events.

The application events and chart events class modules likely reside within an add-in or workbook you’ve built to trap events from the entire application. Open the ThisWorkbook code module for your workbook. If your program is a regular workbook, use the dropdowns at the top of the code module to insert Workbook_Open and Workbook_BeforeClose procedures, and enter InitializeAppEvents and TerminateAppEvents where appropriate, as shown below:

Private Sub Workbook_Open()
    InitializeAppEvents
End Sub
 
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    TerminateAppEvents
End Sub

If your program is an add-in, use the dropdowns at the top of the code module to insert Workbook_AddinInstall and Workbook_AddinUninstall procedures, and enter InitializeAppEvents and TerminateAppEvents where appropriate, as shown below:

Private Sub Workbook_AddinInstall()
    InitializeAppEvents
End Sub
 
Private Sub Workbook_AddinUninstall()
    TerminateAppEvents
End Sub

When the workbook is opened or the add-in installed, the application event class is instantiated, so it can begin watching for chart events. When the workbook is closed or the add-in uninstalled, the application event class in terminated, and chart events are no longer trapped.

In a perfect world, this would be sufficient to keep the application event procedures working. In our programming environment, however, many things can break the application event hooks. If your program encounters a run time error, for example, you may find yourself without application events, and therefore, without chart events. You should insert the InitializeAppEvents line into other procedures where appropriate. For example, you could place it at the top or bottom of every procedure run from your program’s command bar and menu buttons.

The Final Event

In this article, you found out how useful chart events can be. They can extend the user interface of the programs you write, making it easy for users to identify points for your program to work on. With a little ingenuity, you can create powerful applications. For example, recently, I made a utility that draws a trend line for only part of a plotted series using the first and last points indicated by two mouse clicks. I made another utility that lets the user zoom in and out on the basis of mouse actions. Once you’ve experimented with chart events, you’ll think of many ways to enhance your projects.

Chart Event Articles on the Peltier Tech Blog

There are several examples that make use of chart events on this blog, including:

Chart Event to Highlight a Series

Chart Event Class Module to Highlight a Series

Highlight a Series with a Click or a Mouse Over

Accordion Chart for Jorge

The post Chart Events in Microsoft Excel appeared first on Peltier Tech Blog.

Polar Plot in Excel

$
0
0

Polar Plots

Microsoft Excel offers a number of circular charts, but none of them is usually a particularly good choice for displaying data. You can search this blog for “pie chart” and see numerous examples of badly applied pie charts. If you hunt for “radar chart” or “spider chart” you’ll see a class of charts that’s even more deceptive. A major part of the deficiency of radar plots is that they pretend to show a physical, geographical relationship which isn’t present at all.

Excel Polar Plot

Polar Plots, on the other hand, can be used to map information that has a true geographical component. Ironically, this includes actual radar feedback. The data for a polar plot is given in polar coordinates, which is given as R-theta, where R is the distance from the origin (center of the plot) and theta is the angle from a reference angle, such as north or conversely the positive horizontal axis of overlaid cartesian coordinates.

A Polar Plot is not a native Excel chart type, but it can be built using a relatively simple combination of Donut and XY Scatter chart types. We need to build the grid using a donut chart, then overlay the physical data using applicable XY Scatter chart types.

Preparing the Data

We’ll use a donut chart for the circular grid. The data we need is simple, as shown below. I have 9 columns for the 9 concentric donuts (the smallest donut hole is 10% of the diameter, so this hole plus 9 rings of 10% make 100%). Each ring has 12 segments, so each comprises 30° of the 360° circle of the chart.

Excel Polar Plot Grid Data

Our data is provided in polar coordinates in columns A and B below, where R is the distance from the origin to the data point, and theta is the angle from our reference angle (due north) to the point. These are converted to X and Y in columns C and D. The formula in C2and D2 are:

C2:  =A2*SIN(B2/180*PI())
D2:  =A2*COS(B2/180*PI())

These are filled down to C14 and D14.

Excel Polar Plot Values Data

Making the Chart

To create the grid, select the blue shaded cells in the top table, and insert a donut chart (below left). The default diameter of the donut hole is 75% of the diameter of the whole chart, so all of the rings are scrunched together. Select any of the donuts and press Ctrl+1 (numeral one) to open the Format Series dialog or task pane, and set Donut Hole Size to 10%, the smallest possible value (below right). While you’re at it, shrink the ridiculously large chart title, if you need it at all.

Excel Polar Plot Steps 1 and 2

Format each donut series so it has no fill and uses a thin (0.75 point) light gray (25% gray) border (below left). Our grid is ready for real data.

Select the orange shaded range of XY values in the second table above, and copy. Select the chart, and click the Paste Special button on the Paste dropdown on the Home tab of the ribbon to add the data (below right). The data is added as another concentric donut on the outside of the chart.

Excel Polar Plot Steps 3 and 4

Use the following settings in the Paste Special dialog: Add cells as New Series, Values in Columns, Series Names in First Row, and Categories in First Column.

Paste Special Chart Dialog
Select the added ring of data, and choose Change Series Chart Type from the pop-up menu. Choose one of the XY types. Here I’ve selected the line and markers option (below left); if you were plotting the advance of alien spacecraft you’d probably want the markers only option.

Excel has plotted the XY data on secondary axes: the axis labels of both are plainly visible in the left chart below. Format each secondary axis scale in turn so the minimum and maximum are equal but with opposite signs; in this case min is -10 and max is +10. Format the axis so there are no tick marks and no tick labels, and use the same line style as the donut grid borders, 0.75 points thick and 25% gray (below right).

Excel Polar Plot Steps 5 and 6

Remove the major vertical and horizontal gridlines (below left). Remove the unwanted legend entries; click once to select the legend, then once more to select the unwanted entry, then click Delete (below right). If there is only one series of XY points, you can probably dispense with the legend.

Excel Polar Plot Steps 7 and 8

Expand the size of the plot area (below left), and format the series lines and markers if desired (bottom right).

Excel Polar Plot Steps 9 and 10

This may be complete enough for you, but as always, there are embellishments available to the clever chartmonger.

Modified Grid

You can change the grid if you like. If I use the following expanded data, the inner few donuts have only 4 arcs, each covering 90° of the ring. The next few have 12 arcs, as above, each covering 30°. The last few have 24 arcs, covering 15° each.

Excel Polar Plot Extended Grid Data

The resulting grid is shown without data below left, and with data below right.

Excel Polar Plot Fancy Grid

You can show the central circle (donut hole) without the crosshairs if you format the secondary axes to use no line color instead of 25% gray.

Excel Polar Plot Fancy Grid Without Crosshairs

Compass Point Labels

Suppose this is an actual geographic representation and you want to label the points of the compass. Set up data as shown below left. Copy the green range, select the chart, and use Paste Special as above. This series is plotted using the same chart type as the previous paste series was converted to, XY scatter with lines and markers.

Excel Polar Plot with Labels Data and Step 1

Add labels to the new series; the default Y values are used in the labels (below left). Remove the title and legend, or shrink the plot area to make room for the labels.

Change the label positions to Above (for the north label), Right (east), Below (south), and Left (west).

Excel Polar Plot Steps 2 and 3

Change the labels as appropriate (below left). You can use one of these approaches:

  • Select each label (click to select the series of labels, then click again to select the individual label), double click to edit the label’s text, and type the label you want.
  • Select each label (click to select the series of labels, then click again to select the individual label), type an equals sign in the formula bar, and click on the cell containing the label you want. The formula bar will show the link, e.g., =WorksheetName!$F$2.
  • Download and install Rob Bovey’s free Chart Labeler from http://appspro.com. This allows you to assign labels from a worksheet range to the points in a chart.
  • If you’re using Excel 2013, you can format the labels to use Values from Cells, and select the range of cells containing your labels.

Finally, format the last data series so it uses no lines and no markers (below right).

Excel Polar Plot Steps 4 and 5

The post Polar Plot in Excel appeared first on Peltier Tech Blog.

Chart Partial Range Between Variable Endpoints

$
0
0

Plotting Part of a Data Range

Excel is pretty handy for collecting, analyzing, and charting lots of data. If you want to plot a subset of your data, you can manually adjust the data range used by the chart. But there are easier ways to select partial data ranges, and to make this selection less tedious than manually adjusting the chart’s data.

Plotting the Entire Range

In the workbook named “MSFT Price.xlsx” (click to download) and its worksheet named “MSFT 5-week” I have a range and chart showing five weeks of Microsoft adjusted closing price data.

Chart Entire Range

The series formula of the chart is:

=SERIES('MSFT 5-week'!$B$1,'MSFT 5-week'!$A$2:$A$26,'MSFT 5-week'!$B$2:$B$26,1)

Recall that the series formula includes the chart data as follows:

=SERIES(Series Name, X Values, Y Values, Plot Order)

and that the series can be edited right in the Formula Bar, just like any other Excel formula.

A commonly asked question is, How can we plot part of this data, based on some kind of lookup? We’ll use a technique known variously as “Names” (the official moniker), “Defined Names”, “Defined Ranges”, and “Named Ranges”. I’ll show three approaches, which increase in complexity but also in ease of use.

Defined Names – By Index

This exercise is in a worksheet named “MSFT By Index”. The data is the same and the chart is nominally the same as above. We’ll use cells E2:E3 to contain the index of the first and last rows of the data range we want to plot. We will count rows in the data range and enter values into these cells.

Dynamic Names by Count

To define names, go to the Formulas tab of the ribbon, click on the Define Name button, and select Define Name… from the dropdown menu.

Define Names

The New Name dialog appears. You can name the name, define its scope to the entire workbook or to one of its worksheets, add a comment, and write a formula which the name refers to.

Define Name Dialog

For the dates in our chart, we will define the following name:

Name: MSFT_Date_Index
Refers To:
=OFFSET('MSFT By Index'!$A$1,'MSFT By Index'!$E$2,0):
     OFFSET('MSFT By Index'!$A$1,'MSFT By Index'!$E$3,0)

OFFSET takes three arguments: a reference range, the number of rows down from this reference (up for a negative number of rows), and the number of columns to the right of the reference (to the left for a negative number of columns). OFFSET may take two more arguments: the number of rows high and the number of columns wide the resulting range is; if height and width are not entered, the resulting range is the same size as the reference range.

This OFFSET:

=OFFSET('MSFT By Index'!$A$1,'MSFT By Index'!$E$2,0)

indicates the cell $E$2 rows down and zero columns right from $A$1, while this OFFSET:

=OFFSET('MSFT By Index'!$A$1,'MSFT By Index'!$E$3,0)

indicates the cell $E$2 rows down and zero columns right from $A$1. Combining the two OFFSETs, separated by a colon, indicates the range bracketed by the two cells.

For the values, we will use this simple OFFSET that returns the prices in the column immediately to the right of the dates defined by MSFT_Date_Index:

Name: MSFT_Close_Index
Refers To:
=OFFSET(MSFT_Date_Index,0,1)

To make the chart dynamic, replace the cell addresses of the X and Y values in the original series formula:

=SERIES('MSFT By Index'!$B$1,'MSFT By Index'!$A$2:$A$26,'MSFT By Index'!$B$2:$B$26,1)

with the names we’ve defined. Here is the series formula as edited in the formula bar:

=SERIES('MSFT By Index'!$B$1,'MSFT By Index'!MSFT_Date_Index,
            'MSFT By Index'!MSFT_Close_Index,1)

Since the names were scoped to the workbook, the worksheet name in the series formula is replaced by the workbook name:

=SERIES('MSFT By Index'!$B$1,'MSFT Price.xlsx'!MSFT_Date_Index,
            'MSFT Price.xlsx'!MSFT_Close_Index,1)

Here is the chart for an arbitrary pair of first and last index values:

Dynamic Names by Count

Adjust the first and last indices in E2:E3, and the chart updates to reflect the new range.

Dynamic Names by Count

This is a bit tedious in practice, since you need to count rows and enter your findings in the index cells. It is not hard to make the process easier.

Defined Names – By Match

This exercise is in a worksheet named “MSFT By Match”. The data and the chart are the same as above. We’ll use cells F2:F3 to contain the first and last dates of the data range we want to plot. Formulas in E2:E3 will determine the index of these dates within the date range, so we can use the same formulas as above for our names. We will enter dates into cells F2:F3 and let Excel calculate the index values in E2:E3, which is a little nicer than counting rows and typing a number.

Dynamic Names by Match
These formulas in E2:E3 determine the where the dates in F2:F3 fall in the overall list of dates:

Cell E2:  =MATCH(F2,$A$2:$A$26,-1)
Cell E3:  =MATCH(F3,$A$2:$A$26,-1)

The last argument (-1) in the functions is needed because the dates in column A are listed in descending order. Omit this argument, or use +1, for data sorted in ascending order. Use zero if the data are unsorted labels.

The name that includes the dates for our chart is:

Name: MSFT_Date_Match
Refers To:
=OFFSET('MSFT By Match'!$A$1,'MSFT By Match'!$E$2,0):
     OFFSET('MSFT By Match'!$A$1,'MSFT By Match'!$E$3,0)

This is the same, except for the sheet name, as in the previous exercise. The corresponding name for the prices should also look familiar:

Name: MSFT_Close_Match
Refers To:
=OFFSET(MSFT_Date_Match,0,1)

The series formula for the dynamic chart looks like this as edited:

=SERIES('MSFT By Match'!$B$1,'MSFT By Match'!MSFT_Date_Match,
            'MSFT By Match'!MSFT_Close_Match,1)

and like this when Excel replaces the sheet name with the workbook name for the workbook-scoped names:

=SERIES('MSFT By Match'!$B$1,'MSFT Price.xlsx'!MSFT_Date_Match,
            'MSFT Price.xlsx'!MSFT_Close_Match,1)

Here is how the chart looks for an arbitrary pair of dates:

Dynamic Names by Match

Adjust the first and last dates in F2:F3, and the chart updates to reflect the new range.

Dynamic Names by Match

It’s much easier to enter dates than to count rows, especially if the overall data range extended beyond the number of rows visible in one screen.

Defined Names – By Combo Box

This exercise is in a worksheet named “MSFT By Combo”. The data and the chart are the same as above. We’ll use combo box controls that let us select the first and last dates of the data range we want to plot. The combo boxes link to cells E2:E3, so we can again use the same formulas as above for our names. Now we’ll use the best method in this article: we’ll select the dates we want using the combo boxes.

Dynamic Names by Match

To add a combo box control, go to the Developer tab, click Insert, then click the Combo Box from the set of Forms Controls. The cursor turns into a shape crosshair; use this to draw the combo box.

Dynamic Names by Combo

If the Developer tab is not visible, you have to change your settings. In Excel 2010 and 2013, click the green File tab, select Options, select Customize Ribbon, and in the long list of tabs on the right, check the box in front of Developer. In Excel 2007, click the big round Office button in the top left of the Excel window, click Excel Options at the bottom of the dialog, then check Show Developer Tab in the Ribbon.

Right click on the combo box, and choose Format Control from the pop-up. Select the input range (the range of dates that you want to appear in the dropdown) and the cell link (where the index of the selected date will appear).

Dynamic Names by Combo
With both combo boxes formatted, defining the names proceeds as above, with essentially the same formulas. The dates:

Name: MSFT_Date_Combo

Refers To:
=OFFSET('MSFT By Combo'!$A$1,'MSFT By Combo'!$E$2,0):
     OFFSET('MSFT By Combo'!$A$1,'MSFT By Combo'!$E$3,0)

The price values:

Name: MSFT_Close_Combo
Refers To:
=OFFSET(MSFT_Date_Combo,0,1)

Here is the series formula as edited to reflect the names:

=SERIES('MSFT By Combo'!$B$1,'MSFT By Combo'!MSFT_Date_Combo,
            'MSFT By Combo'!MSFT_Close_Combo,1)

and adjusted by Excel to show the workbook name for the workbook-scoped names:

=SERIES('MSFT By Combo'!$B$1,'MSFT Price.xlsx'!MSFT_Date_Combo,
            'MSFT Price.xlsx'!MSFT_Close_Combo,1)

Dynamic Names by Combo

Adjust the first and last dates selected in the combo boxes, and the chart updates to reflect the new range.

Dynamic Names by Combo

The post Chart Partial Range Between Variable Endpoints appeared first on Peltier Tech Blog.

Secondary Axis as Percentage of Target

$
0
0

I haven’t posted in quite a while. I have a few long tutorials that I’m working on, but there hasn’t been enough uninterrupted time to get them done.

I’ve also been working on a new edition of my Chart Utility which will run in PowerPoint. This will allow those users who spend most of their time in PowerPoint to run the utility from there, switching to Excel for long enough to select their data, then build their chart as a native PowerPoint chart. I mean, it’s still really an Excel chart, but it will behave as if it were created in PowerPoint (which it was), and the data will sit in its data sheet in PowerPoint. Tentative plans call for the new utility to be released a month and a half ago. I’ll probably release it in stages, starting in a couple weeks.

In the meantime, a customer asked me to help with a certain topic, and I thought it made a great tutorial, so here it is.

Secondary Axis as Percentage of Target

A customer had a stacked chart showing contributions to a fundraising effort by source (below) and wanted to show percentage toward the target. He had sketched something with labels and tickmarks and arrows everywhere, but I thought that was a bit too intrusive and cluttered. Instead I decided to use a secondary axis scale showing the percentage.

Stacked Columns Showing Fundraising Totals

I’ve written before about how Secondary Axes in Charts can be more confusing than enlightening, adding to the cognitive load required to understand a chart. But I’ve also written about Secondary Axes that Work – Proportional Scales, and I’ve showed how to Add Percentages on the Secondary Axis. This is really another illustration of that last tutorial.

The only way to get a secondary axis is to have a series that is plotted on the secondary axis. I modified his data range by adding a series named “Blank” with a value of zero. The chart below is selected, and you can see from the highlighted ranges in the worksheet that it includes all series including the new Blank one. To the right I’ve done some calculations that we’ll be using momentarily. Essentially, given a target of 300 and a primary Y axis maximum of 160, I know that the corresponding secondary Y axis maximum should be 53.333%.
Stacked Columns Showing Fundraising Totals
The charts below show the steps in constructing the improved chart. Left, I moved the Blank series to the secondary axis. Excel added a secondary vertical axis with a scale ranging from zero to one. Center, I deleted the gridlines, and made all three visible axis lines the same medium-light gray color, and gave the vertical axes major tick marks outside of the axis. Right, I rescaled the axes. I hard-coded the min and max of the primary axis to 0 and 160, just so they didn’t change without me knowing it. I set the min and max of the secondary axis to 0 and 53.333%, and changed the number format to Percentage with No Digits.
Stacked Columns Showing Fundraising Totals
Finally I made the chart a little bit taller to allow for a descriptive title. Probably some indication of currency in the primary axis tick labels would also be useful. I also hid the row with the blank data and the columns with my secondary axis calculations, in case the entire sheet would be made public.
Stacked Columns Showing Fundraising Totals

The post Secondary Axis as Percentage of Target appeared first on Peltier Tech Blog.

Floating Bars in Excel Charts

$
0
0

Floating bars can be used to plot many types of data sets. (“Bars” in this usage means “bars”, as Excel calls horizontally oriented bars, as well as “columns”, as Excel calls vertically oriented bars.) In a waterfall chart, floating bars (usually vertical) show how contributing factors affect a cumulative total. In a Gantt chart, horizontal floating bars along a horizontal date scale help program managers plan task start and end dates and durations, and track progress towards completion of these tasks. Floating bars can be useful to show running highs and lows in a data set, such as daily high and low temperatures, stock prices, diastolic and systolic blood pressure readings, etc.

There are numerous ways to create floating bars in an Excel chart. There are so many ways that I should write more than one post, but I’m going to cram them all into this one. I’ve divided the techniques into the following:

  • Stacked Column and Bar Charts
  • Line Chart Tricks
  • Error Bars
  • XY Chart Line Segments

Stacked Column and Bar Charts

Stacked column and bar charts are probably the most obvious way to create floating bar charts. This approach is pretty flexible, and allows individual floating bars to be formatted differently, but will require some calculations to get the bars to appear as desired.

Stacked Column Charts (Vertical Bars)

This tutorial will show simple floating columns, stacked floating columns, floating columns that span the horizontal axis, and overlapping floating columns, all using stacked column charts.

Floating Columns

In the data set below, there are several high and low values for the categories in a column chart. The clustered column chart shows the values we want to highlight: we want a floating column to connect each low value to its corresponding high value.

We achieve this by inserting a column in the worksheet which has a simple formula to calculate the difference between high and low (“Delta” in the table below). Adjusting the data range and changing from clustered to stacked columns shows all we need. The floating column is resting on top of the Low value column.

A little formatting gives us all we need. The Low series is formatted to be invisible: no border and no fill. The vertical axis has been rescaled to zoom in on the data and remove some of the white space below the floating bars.

You can change the relative width of the columns and gaps between by selecting them and changing the Gap Width property; a Gap Width of 100 means that the gap will be 100% as wide as a bar. I like to use gap widths of 50% to 100%, and I used 75% in most of the charts here.

With this technique, each column can be selected (it may take two single clicks) and formatted independently of the rest, for purposes of highlighting one or more specific values.

The gold and purple colors above may show extreme highlighting, and were selected to clearly show the different colors. In general, subtle highlighting, like the slightly darker shade of point C or the outlined column of point F are usually sufficient.

Stacked Floating Columns

The stacked column chart allows multiple items to be stacked, since each floating column rests on the lower columns. This table and chart show low, medium, and high values.

Insert two columns for the two sets of calculations of floating column heights, and plot these with the minimum value.

As before, format the lowest column to be invisible, and adjust the axis scale, if desired.

As before, individual columns can be formatted independently of the others.

Floating Columns Crossing the Horizontal Axis

If you want to show floating columns that span negative and positive values, you will encounter problems, as shown by this sample data. It all looks fine when we examine the unstacked columns that show the minimum and maximum values.

However, when we plot the minimum values and stack the differences on top, we see that the stacking doesn’t work the way we would have liked. Excel plots columns with negative values below the X axis and columns with positive values above the X axis. Even though the Delta begins below the X axis, the Delta column has a positive value, and is plotted starting at zero or at the top of the minimum, if that value is positive.

Our simple formulas are not adequate, and we need a different approach. We’ll add three columns to the data sheet: one for the blank columns on which the floating columns will rest, one for whatever part of the floating column is positive (above the X axis), and one for whatever part of the floating column is negative. Using pseudo-references, the formulas we need are:

Blank:  =IF(High<0,High,IF(Low>0,Low,0))
  Pos:  =IF(High>0,High-MAX(Low,0),0)
  Neg:  =IF(Low<0,Low-MIN(High,0),0)

When we plot these values, we get the floating columns spanning the ranges we expect. Note that the floating columns may consist of two pieces, one (orange) below and one (blue) above the X axis, if necessary separated from the axis by the blank series (shown gray in the chart below).

As always, format the blank series to be blank (no border and no fill), and format the floaters as desired.

As before, individual floating columns can be formatted independently; the positive and negative portions can be formatted the same or differently.

Overlapping Floating Columns

You may want to show two sets of floating columns. For example, you may want to compare high and low temperatures for a set of dates with the average historical high and low temperatures for those dates. The way to handle this is to have one set of data on the primary axis, and the other set on the secondary axis.

The table and chart below show two sets of high and low values. The blue will eventually be shown on the primary axis and the orange on the secondary.

Insert two columns in the sheet, to capture the differences between high and low in the two sets of data. Here are the low and delta of each set in a stacked column chart.

Here is the same stacked column chart, with the orange series moved to the secondary axis. Each axis has its own Gap Width setting. Here I’ve used 50 for the primary axis (blue columns in back), and 150% for the secondary axis (orange columns in front).

More formatting: Hide the low columns (no border or fill) and adjust the Y axis. Also, delete the secondary vertical axis and if present the secondary horizontal axis. The chart will keep the series for each axis separate (so they have separate gap widths and so they don’t go stacking on each other), but will plot them on the primary axis scales.

Individual columns can always be formatted separately.

Stacked Bar Charts (Horizontal Bars)

The techniques described above for Vertical Column Charts work the same for Horizontal Bar Charts. This tutorial will show simple floating bars, stacked floating bars, floating barsthat span the vertical axis, and overlapping floating bars, all using stacked bar charts.

Floating Bars

In the data set below, there are several high and low values for the categories in a bar chart. The clustered bar chart shows the values we want to highlight: we want a floating bar to connect each low value to its corresponding high value.

To get the vertical axis labels in your chart to be in the same top-to-bottom order as in the worksheet, follow the approach described in Why Are My Excel Bar Chart Categories Backwards? and in Excel Plotted My Bar Chart Upside-Down.

Note also that in an Excel Bar Chart the vertical axis is the X axis (for the independent variable), and the horizontal axis is the Y axis (for the dependent variable). This confuses a lot of people, so I usually stick to “horizontal” and “vertical” instead of “X” and “Y”.

We achieve this by inserting a column in the worksheet which has a simple formula to calculate the difference between high and low (“Delta” in the table below). Adjusting the data range and changing from clustered to stacked bars shows all we need. The floating bar is resting to the right of the Low value bar.

A little formatting gives us all we need. The Low series is formatted to be invisible: no border and no fill. The horizontal axis has been rescaled to zoom in on the data and remove some of the white space to the left of the floating bars.

You can change the relative width of the bars and gaps between by selecting them and changing the Gap Width property; a Gap Width of 100 means that the gap will be 100% as wide as a bar. I like to use gap widths of 50% to 100%, and I used 75% in most of the charts here.

With this technique, each bar can be selected (it may take two single clicks) and formatted independently of the rest, for purposes of highlighting one or more specific values.

Stacked Floating Bars

The stacked bar chart allows multiple items to be stacked, since each floating bar rests on the lower bars. This table and chart show low, medium, and high values.

Insert two columns for the two sets of calculations of floating bar lengths, and plot these with the minimum value.

As before, format the lowest bar to be invisible, and adjust the axis scale, if desired.

As before, individual bars can be formatted independently of the others.

Floating Bars Crossing the Vertical Axis

If you want to show floating bars that span negative and positive values, you will encounter problems, as shown by this sample data. It all looks fine when we examine the unstacked bars that show the minimum and maximum values.

However, when we plot the minimum values and stack the differences on top, we see that the stacking doesn’t work the way we would have liked. Excel plots bars with negative values to the left of the X axis and bars with positive values to the right of the X axis. Even though the Delta begins to the left of the X axis, the Delta bar has a positive value, and is plotted starting at zero or at the right end of the minimum, if that value is positive.

Our simple formulas are not adequate, and we need a different approach. We’ll add three columns to the data sheet: one for the blank bars on which the floating bars will rest, one for whatever part of the floating bar is positive (above the X axis), and one for whatever part of the floating bar is negative. Using pseudo-references, the formulas we need are:

Blank:  =IF(High<0,High,IF(Low>0,Low,0))
  Pos:  =IF(High>0,High-MAX(Low,0),0)
  Neg:  =IF(Low<0,Low-MIN(High,0),0)

When we plot these values, we get the floating bars spanning the ranges we expect. Note that the floating bars may consist of two pieces, one (orange) to the left of and one (blue) to the right of the X axis, if necessary separated from the axis by the blank series (shown gray in the chart below).

As always, format the blank series to be blank (no border and no fill), and format the floaters as desired.

As before, individual floating bars can be formatted independently; the positive and negative portions can be formatted the same or differently.

Overlapping Floating Bars

You may want to show two sets of floating bars. For example, you may want to compare high and low temperatures for a set of dates with the average historical high and low temperatures for those dates. The way to handle this is to have one set of data on the primary axis, and the other set on the secondary axis.

The table and chart below show two sets of high and low values. The blue will eventually be shown on the primary axis and the orange on the secondary.

Insert two columns in the sheet, to capture the differences between high and low in the two sets of data. Here are the low and delta of each set in a stacked bar chart.

Here is the same stacked bar chart, with the orange series moved to the secondary axis. Each axis has its own Gap Width setting. Here I’ve used 50 for the primary axis (blue bars in back), and 150% for the secondary axis (orange bars in front).

If you used the Upside-Down-Bar-Chart trick to plot the primary vertical axis labels in the same order that they appear in the worksheet, you’ll have to display the secondary vertical axis and apply the same trick to it.

More formatting: Hide the low bars (no border or fill) and adjust the Y axis. Also, delete the secondary horizontal axis and if present the secondary vertical axis. The chart will keep the series for each axis separate (so they have separate gap widths and so they don’t go stacking on each other), but will plot their values using the primary axis scales.

Individual bars can always be formatted separately.

Line Chart Tricks

Excel’s line charts have a few built-in features that can be used to generate floating columns. These include Up-Down Bars and High-Low Lines, which can be combined to create Open-High-Low-Close (OHLC) Stock Charts, and also Drop Lines. Being tied into line charts, these features can only be used to generate vertical floating bars.

Up-Down Bars

Up-Down Bars connect the values of a chart’s first line chart series and last line chart series with floating bars. There are actually two sets of bars: Up Bars, which connect a lower first value to a higher last value (the value goes Up), and Down Bars, which connect a higher first value to a lower last value (the value goes Down).

Floating Columns

For simple floating bars, you need to plot two data series in a line chart.

In Excel 2013, click the Plus icon next to the chart, and check the Up-Down Bars box; alternatively, on the Chart Tools > Design ribbon tab, click the Add Chart Element dropdown, and select Up-Down Bars. In Excel 2007 or 2010, on the Chart Tools > Layout ribbon tab, use the Up/Down Bars dropdown.

The chart below specifically has Down Bars, since all of the values in the last series are lower than all those of the first series.

Unlike the Stacked Column Chart technique, we need to carry out no calculations to determine how tall the floating bars have to be, and we don’t need a hidden set of bars on which to balance the floating bars.

Now apply a little formatting. Format the lines to have no markers and no lines, and give the up-down bars a suitable fill color.

You can change the relative width of the up-down bars and gaps between by selecting them and changing the Gap Width property of one of the line chart series; a Gap Width of 100 means that the gap will be 100% as wide as a bar. I like to use gap widths of 50% to 100%, and I used 75% in most of the charts here.

Mixed Formats: Up vs. Down

You can’t format individual up-down bars with their own colors, but since there are Up Bars and Down Bars, you can at least format some with one color and the rest with another color.

In the data below I’ve switched the First and Last values for points C and D. The line series cross, so the Last series is greater than the First for these points.

When Up-Down Bars are added, the black Down Bars for most of the points are replaced by Up Bars for points C and D.

In this way we can assign different formats to highlight selected points.

Up-Down Bars: First to Last

As mentioned before, Up-Down Bars connect the first line chart series to the last, ignoring values in between. In this data set, the earlier First and Last series have had intermediate series Second and Third inserted between them.

When Up-Down Bars are inserted, they connect First and Last, ignoring any values of Second and Third that may extend beyond First and Last.

Floating Columns Crossing the Horizontal Axis

When dealing with the Stacked Column Chart technique, if you recall, we couldn’t simply use a floating column to span values below and above the horizontal axis. Let’s try this with Up-Down Bars.

The lines show where we want the bars to appear, and when we add the Up-Down Bars…

… they go where we want. Again, no calculations required.

Overlapping Floating Columns

We can use Up-Down Bars to generate overlapping sets of floating bars, using primary and secondary axis groups. Here are two pairs of values plotted in a line chart. The Blue series are plotted on the primary axis, and the Orange series on the secondary. The secondary vertical axis has been deleted so that all values are plotted along the primary axis.

One of the primary series is selected, and Up-Down Bars are added.

One of the secondary series is selected, and again Up-Down Bars are selected.

The Up-Down Bars are formatted with different colors, and the line chart series are formatted to use different gap widths as well as no lines and no markers.

As before, individual bars can be formatted as Up Bars among a field of Down Bars. In the table below, first and last values have been switched for points C and D for both primary and secondary series. The line chart series cross…

… and the bars have been formatted differently to highlight points C and D.

High-Low Lines

High Low Lines connect the highest and lowest values of a chart’s line chart series using vertical lines. The order of series makes no difference to these lines.

Floating Columns

For simple floating bars, you need to plot two data series in a line chart.

In Excel 2013, on the Chart Tools > Design ribbon tab, click the Add Chart Element dropdown, click Lines, and select High-Low Lines. In Excel 2007 or 2010, on the Chart Tools > Layout ribbon tab, use the Lines dropdown, and select High-Low Lines.

Format the plotted line series with no lines and no markers to hide them, and you’re left with boring black vertical lines.

In classic versions of Excel (2003 and earlier) you had limited ability to format such lines, but Excel 2007 introduced the ability to make the lines pretty much as wide as desired. The high-low lines in the chart below are 13.5 points thick, and look a lot like the floating columns produced by the other techniques above.

These lines can be assigned colors and thicknesses, but are not actually rectangular shapes, so they don’t have both border and fill colors.

High-Low Lines: Highest to Lowest

High-Low Lines work by connecting the lowest and highest values at each category. It doesn’t matter where in the sequence the high or low value occurs. In the data below, the highest (blue) and lowest (red) values are highlighted: they are distributed among the columns of data.

When High-Low Lines are added, they connect high and low, regardless of which series includes the extremes.

Note that no values are located above or below the formatted High-Low Lines.

Floating Columns Crossing the Horizontal Axis

The Stacked Column Chart technique required tricky formulas to allow a floating column to span values below and above the horizontal axis, while the Up-Down Bar approach did not. Let’s try this with High-Low Lines.

The lines show where we want the bars to appear, and when we add the High-Low Lines…

… and format them…

… they go where we want. As with Up-Down Bars, it works easily, no calculations required.

Overlapping Floating Columns

We can use High-Low Lines to generate overlapping sets of floating bars, using primary and secondary axis groups. Here are two pairs of values plotted in a line chart. The Blue series are plotted on the primary axis, and the Orange series on the secondary. The secondary vertical axis has been deleted so that all values are plotted along the primary axis.

A primary axis series is selected, and High-Low Lines are added.

A secondary axis series is selected, and again High-Low Lines are selected.

The High-Low Lines are formatted with different colors and line widths (13.5 and 8 pts), and the line chart series are formatted to use no lines and no markers.

Stock Charts

Up-Down Bars and High-Low Lines were probably introduced into Excel to enable Open-High-Low-Close type Candlestick stock charts. Open and Close are the First and Last series from the Up-Down Bars examples above, and High and Low are, well, High and Low from the High-Low Lines examples. When applied together with the data columns in the appropriate order, simple line charts can be formatted into OHLC charts.

Line Chart Plus

Here is a table with two weeks of stock data and the corresponding line chart.

Add High-Low Lines…

… add Up-Down Bars…

… and do a little formatting to create a candlestick chart. Use no markers or lines for the plotted series, and use your favorite colors and gap width for the Up-Down Bars. I always forget whether black or white bars signify up or down, and green and red make a bad combination for color vision deficient viewers, so I usually use blue for up and red or orange for down.

In “Classic” versions of Excel (97 through 2003), the line chart with High-Low Lines and Up-Down Bars was smart enough to recognize itself as a stock chart type, but since Excel 2007, such a chart only considers itself a line chart.

In Excel 2007 and later you cannot combine a stock chart with any other chart type, so you can’t add another series to show how, say, some market index varies in comparison. But you can make your stock chart using a line chart like I did here, then add whatever index lines you want.

Built-In OHLC

Using the same data set, you can directly insert an OHLC stock chart.

A little formatting, and it’s identical the the line chart stock chart above.

The only difference is that the “official” stock chart can’t be combined with any other data.

Drop Lines

Drop Lines are lines that drop from data points to the horizontal (category) axis in line charts and area charts. Each line or area series in a chart can have Drop Lines, and every point in a series with Drop Lines has a Drop Line. Drop Lines cannot produce floating bars, since they by definition start at the axis, but they are related to these other techniques, and it’s useful to know about them, even if you use them only infrequently.

Column Chart

Here is the simple data and line chart we’ll use for our Drop Lines example.

In Excel 2013, on the Chart Tools > Design ribbon tab, click the Add Chart Element dropdown, click Lines, and select Drop Lines. In Excel 2007 or 2010, on the Chart Tools > Layout ribbon tab, use the Lines dropdown, and select Drop Lines. The lines are thin vertical black lines.

Like any lines in Excel 2007 and later, we have great flexibility in how we want to format Drop Lines. Here I’ve hidden the line series (no markers and no lines) and I’ve given the Drop Lines a width of 13.5 points and a blue/cyan line color, to produce what appears to be a standard column chart.

Error Bars

Line Charts with Error Bars

Line charts can have vertical Error Bars, oriented upwards or downwards of the data points, or both. This technique will work with column and area charts as well, but it’s easier to illustrate with line charts.

Floating Bars

We can use Error Bars with custom lengths as floating bars. Here we have high and low values, shown together in a line chart. There is another worksheet column with formulas that compute the differences (Delta).

We only need one of the line chart series for our Error Bars. We can plot the High values, and use Minus Error Bars for our floating bars (left), or we can plot the Low values, and use Plus Error Bars for our floating bars (right).

To assign custom values for error bars, first add Error Bars (in Excel 2013, use the Plus icon floating beside the chart; in Excel 2007 or 2010, use the Error Bars control on the Chart Tools > Layout tab). Then under Error Bar Values in the formatting dialog or task pane, select Custom and click Select Values. In the dialog, click in the Plus or Minus box, and select the range of cells with the Error Bar values. If you are only using one of the boxes, you have to explicitly type a zero in the other box, or Excel will not recognize your selection. Stupid Excel.

Hide the line chart series (format with no lines or markers), and format the Error Bar lines to use No End Caps, and appropriate width (here I’ve used 13.5 points) and line color.

Stacked Floating Bars

Here are High, Mid, and Low values along with the computed differences between adjacent points (Upper and Lower). We want stacked floating bars showing the distance between Low and Mid and between Mid and High.

“Aha!” you say, “I’m way ahead of you this time.” Plot the Mid series with Plus and Minus Error Bars (below left), then format the Error Bars as above (below right). But wait, the Plus and Minus Error Bars cannot be independently formatted?

Too bad, but it’s not a big deal. We just need two series, one for each independently formatted set of Error Bars. Here, I’ll plot the High and Low series.

I’ll add Minus Error Bars to the High series, then Plus error bars to the Low series.

Then I’ll hide both series and format the Error Bars.

Floating Columns Crossing the Horizontal Axis

When using Stacked Column Charts to generate floating bars, if you recall, we couldn’t simply use a floating column to span values below and above the horizontal axis. But Up-Down Bars and High-Low Lines didn’t care if they crossed the axis. Let’s try this with Error Bars, using the same High and Low values as before.

So we try the High series with Minus Error Bars, and the Low series with Plus Error Bars. Both allow the Error Bars to cross the category axis.

Format away.

Error Bars as Drop Lines

Error Bars can also be used to create Drop Lines. Here’s a simple line chart using the Drop Lines data from above.

Instead of adding Drop Lines, we can add Error Bars, choose the Minus direction, and a Percentage Value of 100.

No lines and markers for the data series, no end caps but thick lines and a nice line color for the Error Bars.

XY Scatter Charts with Error Bars

As with the line charts in the preceding section, XY scatter charts can support vertical Error Bars. They can also support horizontal Error Bars. Every trick that works with line chart vertical Error Bars will also work with XY scatter chart vertical and horizontal Error Bars.

Vertical Floating Bars

Okay, we already know it’s going to work, but let’s run through the exercise for completeness. Here is the same High and Low data as before, with numeric rather than alphabetic X values.

Plot the High series with Minus Error Bars or the Low series with Plus Error Bars…

… a little formatting, and it’s the same as with the line chart Error Bars.

Horizontal Floating Bars

Plot the same data, but exchange X and Y in the chart.

Plot the High series with Minus horizontal Error Bars or the Low series with Plus horizontal Error Bars.

The same as before, but horizontal.

Vertical Drop Lines

We can use vertical error bars on an XY scatter chart to create drop lines. Same data as before, but in a scatter plot.

Add Minus Error Bars, using the Percentage Value option, and 100%.

Hide the plotted series and format the Error Bars.

This is the answer to two common Excel-related forum questions:

  • How do I get Drop Lines on my scatter plot?
  • How can I get a column chart on a value X axis?

Horizontal Drop Lines

Taking the previous data, but switching X and Y…

Add horizontal Minus Error Bars, using the Percentage Value option, and 100%, then hide the plotted series and format the Error Bars.

XY Chart Line Segments

A very powerful technique for creating floating bars is using XY chart series line segments. You can make vertical and horizontal floating bars, but you are not constrained to these simple orientations. You can position endpoints of your bars pretty much anywhere in you chart, so the possibilities are limitless. In addition, line segments can be independently formatted, even within the same series of points.

I will use simple examples to illustrate the technique, then set you free.

Floating Columns and Bars

Here are plots showing the same High and Low values for vertical and horizontal floating bars.

XY chart segments connect points in the same series, not in different series as in several of the techniques covered so far. So we need to arrange the data to plot points in one series, not two.

We could use that data, but then we’d have to format the in-between (slanted) segments to use no line color. Pretty tedious after the second or third line segment. But if we insert a blank row between each pair of values, Excel will not plot a line segment across the gap, so formatting will be easy.

As with the previous techniques using thick formatted lines, we’ll start with out XY scatter chart, and thicken up the lines. The vertical lines are 13.5 points, the horizontal lines, 10.5 points. But we’ve hidden the markers; why are there circles at the endpoints?

It turns out that Excel’s richly formattable lines have three different “Cap Type” styles. I’ve illustrated them here with small red markers to illustrate their appearance. The Round Cap style has a circular end shape extending beyond the endpoint of the line segment, where the marker is at the center of the circle. The Square Cap style has a square end end shape extending beyond the endpoint of the line segment, with the markers at the center of the square. And the Flat Cap stops exactly at the end of the segment, with the line squared off right at the marker.

We didn’t have to worry about this with the Error Bars, Drop Lines, and High-Low Lines, because their default “Cap Type” is Flat Cap.

The default “Cap Type” for chart series line segments is Round Cap, which makes for nice-looking polygonal plotted lines. But for floating bars, we most likely will want to use the Flat Cap style.

Here are floating bars using vertical and horizontal XY segments and the Flat Cap style.

We can select individual line segments (click once to select the entire series, and again to select the particular line segment), and format them independently of the others.

Stacked Floating Columns and Bars

Here is our stacked floating bar data, plotted as separate series for vertical and horizontal floating bars.

Here is the same data rearranged to facilitate XY series line segments for vertical and horizontal floating bars, including the blank rows between pairs of points.

Hide the markers and fatten up the lines, and we’ve got stacked floating bars.

As before, individual bars (line segments) can be formatted independently of the rest.

Summary

Here is a summary of the Floating Bar techniques discussed in this article.

Most techniques provide vertical bars, a couple horizontal bars, and XY Scatter Line Segments alone produce bars at any orientation.

A few techniques provide actual rectangular bars, which have a border and fill, while many approximate the appearance of a rectangle with thick line segments.

Some techniques allow individual bars in a set to be formatted independently, and some allow easy creation of stacked bars through the use of multiple series.

Stacke column and bar charts do not permit floating bars to cross the category axis, at least not without using tricky formulas to split bars into positive and negative components. The other techniques allow floating bars above, below, or across the axis.

The post Floating Bars in Excel Charts appeared first on Peltier Tech Blog.

Select Data to Display in an Excel Chart With Option Buttons

$
0
0

The Problem

A member of the MrExcel forum wanted to know about using form controls to select columns from a data table to populate a graph. Essentially he wanted his users to be able to choose between two charts, one comparing their scores to district and regional scores, the other comparing their scores to the top 20%. This is a retelling of my suggested approach to his question.

Here is some dummy data I used for his problem, and a chart showing all of the data.

Data and Preliminary Line Chart

My suggested approach will add some columns (F:I) to the existing data range with formulas that show or don’t show data based on which of two option buttons is selected, and my chart will use all of this data. When the formulas don’t show the values, they will not appear in the chart.

The Data

The extended data range is shown below. At first the formula in cell F2 (and copied into the entire range F2:I13) is simply

=B2

To give the user a choice, add two option buttons and label them Chart A and Chart B. Right click on one of them (doesn’t matter which) and select Format Control, and on the Control tab, click in the Cell Link box, and select cell K1. This cell shows which of the buttons is selected, 1 or 2.

Extended Data and Option Buttons

You don’t need to show all of this to the user. You could put the chart and option buttons on the active sheet, and all of the data (and the option button linked cell) can go onto another sheet, and you can hide this other sheet if you want. Or you can place the original data on the same sheet as the chart and option buttons, and the formulas onto another sheet, a hidden sheet if desired. You could replace the two option buttons with one listbox that shows both options; the linked cell works the same way.

The Chart

Set up the chart first, before adjusting the formulas to show the result of the option button selection.

Select A1:A13, then hold Ctrl while selecting F1:I13, and insert a line chart.

Preliminary Line Chart

Delete the legend, because it will always show all series, even if some don’t appear because of the formulas. Instead, label the last point in each series with the series name, and use label text that matches each series color. This is more user-friendly than using a legend, anyway. (I also shortened the axis tick labels so they could all be displayed horizontally.)

Cleaned Up Line Chart

The Formulas

Now adjust the formulas. Keep the formulas in column F the way they are, since this series appears whichever option is selected. The formula in G2 (copied into G2:H13) is

=IF($K$1=1,C2,NA())

This means if the first option button is selected, show the corresponding value, otherwise show #N/A. #N/A isn’t plotted in a line or scatter plot.

Similarly the formula in I2 (and filled into I2:I13) is

=IF($K$1=2,E2,NA())

That is, if the second option button is selected, show the value, otherwise show #N/A.

The Finished Product

Here is the data and chart if the Chart A option button is selected:

Data and Chart 'A'

Here is the data and chart if the Chart B option button is selected:

Data and Chart 'B'

You can download a sample workbook by clicking on this link: MrExcelOptionButtonChart.xlsx.

The post Select Data to Display in an Excel Chart With Option Buttons appeared first on Peltier Tech Blog.


Removing Recent Colors from Microsoft Excel

$
0
0

Recent Colors

When you customize a color and apply it to an object in Microsoft Office, the color is stored as part of the Office file, and presented in a “Recent Colors” category on the various colors dropdowns. Up to ten of these custom colors are displayed, with the most recent at the left of the list and the oldest moving further to the right until a new color pushes it off the list.

The screenshot below shows three custom colors applied to cells B4:B6 of a worksheet, and where they appear in the color dropdown. The pink color was the latest applied, so it is furthest left. It is highlighted with a thin red outline because it is also the fill color of the active cell.

The numerical and alphanumeric codes in columns C and D are the decimal and hexadecimal representations of these colors. They were generated using the following VBA procedure:

Sub OutputColorInfo()
  Dim c As Range
  
  For Each c In Selection.Cells
    c.Offset(, 1).Value = c.Interior.Color
    c.Offset(, 2).Value = WorksheetFunction.Dec2Hex(c.Interior.Color)
  Next
End Sub

Colors are the combination of the three color channels (red, green, and blue), and each channel can have a value between 0 and 255 (or between 0 and FF in hexadecimal notation). The yellow color above has a blue channel value of 66, and red and green channel values of FF, so the code for this yellow is 66FFFF. Note that VBA presents the channels in BGR order, but it’s still called “RGB”.

A customer asked how to get rid of some but not all recent colors used in Excel. This is not too hard to do, but you should remember that any time you format an object with a new custom color, this new color becomes a new Recent Color.

Where are Recent Colors Stored?

Recent Colors appear in the color dropdowns only when the file they were defined for is the active file in its Office application (in this case, the active workbook in Excel). This means they must be stored somewhere within the document.

The first step in modifying the Recent Colors is to close the Office file. Below we see the workbook “recent colors.xlsm” in a Windows Explorer window.

Office files are really zip files which contain xml and other files within a well-defined directory structure. You can access this structure by simply adding the file extension “.zip” to the file name, and dismissing the warning about changing file extensions.

Double click the zip file to see the top-level structure of the file.

Double click on the “xl” directory within the file.

Finally, copy the “styles.xml” file, navigate out of the zip file to the directory the Office file was saved in, and paste the xml file here.

Open “styles.xml” in your favorite text editor. I use Notepad++, which can apply syntax-based color coding to files it recognizes. This is the entire content of my particular styles.xml file. Note the <mruColors> tag near the end of the file. This contains three <color rgb="blahblah"> tags that contain the definitions of our MRU (Most Recently Used) colors.

Changing Recent Colors

Microsoft Office doesn’t bother making the XML easy to see by using line feeds and spaces, but you can go ahead and apply your own, as I’ve done below.

Note that the RGB values in the <color> tags begin with an extra FF (for the transparency channel), and list the red, green, and blue pairs in the RGB order, not the BGR order produced by our VBA routine above. No big deal, Office uses the XML RGB for its user interface and VBA uses BGR, and they don’t talk to each other, so they don’t confuse each other, they only confuse us.

Delete the <color> tag(s) you don’t want (you could also change the color or add new ones if you can determine the desired RGB values). Save the xml file, and copy it back into the “xl” folder in the zip file. Delete the “.zip” extension you added to the Office file earlier, so it is left with its original Office extension (“.xlsm” for our workbook), and reopen the file.

The screenshot below shows the three colored cells, but only the two non-pink Recent Colors in the dropdown. We have successfully removed the recent color from the workbook’s remembered list, but we haven’t removed the color from any objects we formatted with it.

Note that reapplying the pinkish custom color to any object in the workbook will reestablish it as one of our Recent Colors.

Thanks to PowerPoint MVP Steve Rindsberg for showing me the <mruColors> tag I was too busy to notice the first time I looked. Check out Steve’s PowerPoint FAQ Pages and his PPTools – PowerTools for PowerPoint.

The post Removing Recent Colors from Microsoft Excel appeared first on Peltier Tech Blog.

Stick a Shape to a Point in an Excel Chart

$
0
0

This article was inspired by the Mr Excel forum. A member asked Charts: Any way to make a shape stick to a point in a scatterplot, not an absolute location on the chart?

The answer, of course, is Yes, but you have to know the trick, which I’m about to share. Not for the first time.

The Problem – Shapes Won’t Stick to Points in the Chart

Suppose I have some simple X-Y data:

With this data I make a simple X-Y chart:

Now I draw a couple shapes on the chart to highlight two points with larger values than the others.

So far, so good. But when I add some more data…

… the chart’s axes rescale. The points move to stay at the same numerical position along the axis, but the shapes stay where they were originally placed.

So now I have to drag those shapes around whenever the chart axis scales change.

The Solution – Making Shapes Stick to Points

There is actually a pretty simple way to make the shapes stick to the points. The trick is to add a second series to the chart, with data duplicating only the points you want to draw attention to, and use the desired shape as the markers for this series.

Here is the data, with a third column containing the Y values I want to highlight. Also visible is the shape I’ll use.

Here is the original X-Y chart, with blue circles as markers.

Here is the same chart with the second series added, as orange squares that indicate which points will be highlighted.

The trick is simple. Copy the shape, select the series that I want to use the shape as its markers, and paste using a simple Ctrl+V.

Now when I add data, including another highlighted Y value in column C…

… the chart’s axis rescales, but the highlighted points keep their highlighting shape, and the added Y value is highlighted as well.

Enhancements to the Technique

You could use formulas in column C to place values where highlighting is desired, and #N/A errors where it isn’t desired. Below the formula in cell C2 might be

=IF(B2>4,B2,NA())

or better, the threshold for highlighting might be placed into another cell, say E2, to make it easier to modify the highlighting:

=IF(B2>$E$2,B2,NA())

These formulas are then copied down column C as far as needed.

You don’t even need to draw a special shape if all you want to do is circle selected points. Instead of copying the shape and pasting it onto a series, simply format the series to use large circles as markers. Below the circular markers are size 17, with 2.25 point borders and no fill.

Peltier Tech Update

It’s been a busy few months for me, and I haven’t blogged very much lately. I spent a week in Amsterdam at the Excel Summit, where I met a lot of smart Excel users and Excel MVPs for the first time, and caught up with some old friends. I also did some on-site Excel VBA training for a couple companies, and this has reminded me that I want to do more activities like that.

I’ve also spent some time planning and working on new Peltier Tech products and services. Excel 2016 for both Windows and Macintosh will be released by Microsoft in the next several months, and I will release a major upgrade to the Peltier Tech Chart Utility.

Since traveling to training sites is a pain for me and for trainees, I’ve begun work on some live hour-long video training topics. Topics will include “Tricks to Make Excel Charting Less Painful” (based on a session at the Amsterdam Excel conference), “Getting Started with Excel VBA” (based on my recent training workshops), and advanced topics in charting, programming, and programming charts.

The post Stick a Shape to a Point in an Excel Chart appeared first on Peltier Tech Blog.

VBA: A Simple Tool to Open a CSV File and Create Chart with Data Specified by User

$
0
0

In a recent Mr Excel post, a member asked how to convert a CSV File to Excel File with Dynamic Graphing Capability. This is a great topic for a tutorial, but too long for a forum answer.

Problem Statement

The simple statement was this:

  • Convert a CSV file to an Excel workbook
  • Create a chart based on
    • User-specified chart type
    • User-specified columns for X and Y

I expanded on this a little bit:

  • Open a user-selected CSV file
  • Save as an Excel workbook
  • Display dialog for user to select
    • Chart type
    • Columns containing X and Y values for chart
  • Create the desired chart

This is a pretty easy project, which would generally take me half a day or less, depending on other distractions.

Approach

Essentially, I started with this simple VBA procedure, and a similarly simple UserForm (dialog).

Sub OpenCSVFileAndPlotData()
' 1. Get CSV file name
' 2. Open CSV file
' 3. Save as workbook
' 4. Parse file
' 5. Show dialog (select chart type, X values, Y values)
' 6. Draw chart
' 7. Save file
End Sub

My first time through development, I did the least I had to do to make it work. The second time through, I added a bunch of nice embellishments that should make things easier for users to just pick it up and run with it.

For both levels, the following sections have pieces of code describing what is happening, the complete code, and an example workbook.

Building a Simple Solution

Code Workbook

I’m using a macro-enabled Excel workbook named My_CSV_Data_Processor.xlsm. It has a single worksheet names Parameters.

Saved Information: Named Range Containing Chart Types

The worksheet contains a list of chart types that our program will create. These are the simplest and most useful charts built into Excel. The list has two columns, the first being the integer values of Excel’s chart type constants (e.g., xlArea = 1, xlXYScatter = -4169), the second being the chart type names that will appear in the dialog.

The range A2:B12 has been named ChartTypes, so it will be easy for the code to put these values into the dialog.

Starting the Program: Form Control Button

To add a button, the Developer tab must be visible on the ribbon. If you don’t see it, right-click on a blank place in the ribbon, choose Customize the Ribbon. In the list on the right (Main Tabs), click the box in front of Developer.

On the Developer tab, in the Controls group, click the Insert dropdown, then under Form Controls, click on the first icon, Button. Draw a button on the worksheet.

A dialog will pop up asking which VBA procedure to assign to the button; you can revisit this dialog by right-clicking on the button. Select OpenCSVFileAndPlotData and press OK. Then type a caption on the button and resize it as needed.

Code Module

We need to put the code into a regular code module. In the VB Editor, find the workbook’s project in the Project Explorer pane, right click anywhere on it, and choose Insert > Module. When a new code module opens up in the editor, rename it to something useful like MChartFromCSVFile using the Properties pane. The exact name you use isn’t critical, but it should be somewhat descriptive.

On the View menu, click Project Explorer (Ctrl+R) or Properties (F4) if these panes are not visible.

Getting Ready

The first line of the module should be

Option Explicit

If this statement doesn’t appear, type it in, then go to Tools menu > Options, and check the Require Variable Declaration box. While you’re in the Options dialog, uncheck Auto Syntax Check.

After a blank line or two, type Sub and the name of the procedure. The VB Editor automatically skips another line and types End Sub for you:

Sub OpenCSVFileAndPlotData()

End Sub

The main program will be typed between Sub and End Sub. All the variables will be declared at the top using Dim statements. Variables don’t need to be declared at the top of a routine, but VBA offers no just-in-time benefit to declaring them right where you start using them, and I like having them in one place so I can find their declarations easily. In the sections below I will insert a simple Dim statement for the variables used.

1. Get CSV File Name

We can use Excel’s GetOpenFileName to allow the user to select a CSV file from his computer.

  Dim sCSVFullName As String
  sCSVFullName = Application.GetOpenFilename("CSV Files (*.csv), *.csv", , _
      "Select a CSV file", , False)

We’ve specified the CSV file filter, indicated a title for the Open File dialog, and said False to selecting multiple files.

2. Open CSV file

This part is easy, we just need to open the file named in the previous step. Then we’ll set a workbook object variable to this file, so it’s easy to reference later in the code.

  Dim wb As Workbook
  Workbooks.Open sCSVFullName
  Set wb = ActiveWorkbook

3. Save as workbook

We need to remove the file extension from the CSV file name (which includes the file path), which we do by retaining only text up to the last period in the file name. Then we add the Excel workbook file extension, and save the file, specifying the default workbook format.

  Dim sWbkFullName As String, sFileRoot As String
  sFileRoot = Left$(sCSVFullName, InStrRev(sCSVFullName, ".") - 1)
  sWbkFullName = sFileRoot & ".xlsx"
  wb.SaveAs sWbkFullName, xlWorkbookDefault

4. Parse file

Now the file is open, so we’ll extract some information to place in the dialog. We’ll use a two-column display, where the first column has the column number, and the second a simple comma-delimited list of the first few values in that column.

  Dim ws As Worksheet, rng As Range, vRng As Variant
  Dim iRows As Long, iCols As Long, iRow As Long, iCol As Long
  Dim sTemp As String
  Dim vChartData As Variant

  Set ws = wb.Worksheets(1)
  Set rng = ws.UsedRange
  vRng = rng.Value2
  iRows = rng.Rows.Count
  iCols = rng.Columns.Count
  
  '' info to display: column number, first few rows of column
  ReDim vChartData(1 To iCols, 1 To 2)
  For iCol = 1 To iCols
    vChartData(iCol, 1) = iCol ' column number
    sTemp = ""
    For iRow = 1 To 4 ' first 4 values
      sTemp = sTemp & vRng(iRow, iCol) & ", "
    Next
    sTemp = Left$(sTemp, Len(sTemp) - 2) ' remove last comma
    vChartData(iCol, 2) = sTemp
  Next

5. Show dialog

We need to instantiate the UserForm (i.e., load it into memory), pass in the array of column numbers and initial column values, and display the form. At this point, code stops and waits for the user to make his selections and dismiss the form.

When the form is dismissed, we need to get the user’s selections: chart type, whether the CSV file has header labels in the first row, and the columns to be used for X and Y values in the chart. Then we remove the UserForm from memory.

  Dim bFirstRowHeaders As Boolean
  Dim myChartType As XlChartType
  Dim vX As Variant, vY As Variant
  Dim frmChartFromCSVFile As FChartFromCSVFile

  Set frmChartFromCSVFile = New FChartFromCSVFile
  With frmChartFromCSVFile
    '' pass in information we know
    .ChartData = vChartData
    
    .Show
    
    '' get information selected by user
    myChartType = .ChartType
    bFirstRowHeaders = .FirstRowHeaders
    vX = .Xcolumns
    vY = .YColumns
  End With
  Unload frmChartFromCSVFile

6. Draw chart

We need to figure out how to separate the data into separate series, then we need to get the data into the chart.

In XY charts, we let the user create one or more series, where (a) all series share the same set of X values (or no X values if the user didn’t specify them, and Excel will use 1, 2, 3, etc. as X values) and each series has a unique set of Y values, (b) all series share the same set of Y values and each has a unique set of X values, or (c) each series has its own unique sets of X and Y values.

For other chart types, the only relevant combination of X and Y is (a), since Excel uses the same X values for all series regardless of how we specify them. We will deal with this in the Advanced version of this program.

Excel 2013 introduced AddChart2 as an improvement over Excel 2007’s AddChart method. AddChart is hidden in Excel 2013, but AddChart2 will crash Excel 2007 and 2010, so we will use AddChart. In the Advanced program, we will enhance the code to use Excel 2013’s improved default styles while still using the error-free AddChart method.

After adding the chart, we add one series at a time, adding its Y values, X values, and name separately.

  Dim iX As Long, iY As Long, iSrs As Long
  Dim nX As Long, nY As Long, nSrs As Long
  Dim rCht As Range, cht As Chart, srs As Series

  '' define some series parameters
  If IsEmpty(vX) Then
    nX = 0
  Else
    nX = UBound(vX, 1) + 1 - LBound(vX, 1)
  End If
  nY = UBound(vY, 1) + 1 - LBound(vY, 1)
  nSrs = nY
  If nX > nY Then nSrs = nX
  If bFirstRowHeaders Then
    Set rCht = rng.Offset(1).Resize(iRows - 1)
  Else
    Set rCht = rng
  End If
  
  '' select blank cell before inserting chart
  rng.Offset(iRows + 1, iCols + 1).Resize(1, 1).Select
  
  Set cht = ws.Shapes.AddChart.Chart '' Excel 2007+
  
  '' chart type
  With cht
    If myChartType <> 0 Then
      .ChartType = myChartType
    End If
    
    '' add series
    For iSrs = 1 To nSrs
      Set srs = .SeriesCollection.NewSeries
      With srs
        ' X values
        If nX = 0 Then
          ' no X values specified
        ElseIf nX = 1 Then
          ' all series share X values
          .XValues = rCht.Columns(CLng(vX(0, 0)))
        Else
          ' each series has unique X values
          .XValues = rCht.Columns(CLng(vX(iSrs - 1, 0)))
        End If
        ' Y values
        If nY = 1 Then
          ' all series share Y values
          .Values = rCht.Columns(CLng(vY(0, 0)))
        Else
          ' each series has unique Y values
          .Values = rCht.Columns(CLng(vY(iSrs - 1, 0)))
        End If
        ' series name
        If bFirstRowHeaders Then
          If nSrs = nY Then
            .Name = "=" & rng.Cells(1, CLng(vY(iSrs - 1, 0))). _
                Address(True, True, xlA1, True)
          ElseIf nSrs = nX Then
            .Name = "=" & rng.Cells(1, CLng(vX(iSrs - 1, 0))). _
                Address(True, True, xlA1, True)
          End If
        End If
      End With
    Next
  End With

7. Save file

Simple: save changes.

  wb.Save

UserForm

Right click on the workbook’s project in the Project Explorer pane, click Insert > UserForm. When the UserForm appears, give it the name FChartFromCSVFile in the properties pane. This name is descriptive, and is how your code references the UserForm.

UserForm Controls

The Userform contains the following important controls, with the important properties shown below:

btnOK – OK button
Default: True

lstChartType – Listbox with two columns, one hidden.
ColumnCount: 2
ColumnWidths: 0 pt;112 pt
Width: 120
Height: 150

lstChartData – Listbox with two columns, extended multiselect
ColumnCount: 2
ColumnWidths: 42 pt;145 pt
Width: 195
Height: 150
MultiSelect: 2 - fmMultiSelectExtended

lstX, lstY – simple listboxes

lblbtnX, lblbtnY, lblbtnReset – “Label Buttons” or Labels with raised appearance (like regular buttons)
SpecialEffect: 1 - fmSpecialEffectRaised

chkFirstRowHeaders – Checkbox

Plus a few labels that help the user understand the dialog.

UserForm Code

Right click on the UserForm in the Project Explorer, and click on View Code. The Dialog’s code module will appear. Much of this code responds to events on the UserForm, events like clicking buttons. This code also includes properties, which allow the calling procedure to pass information into the UserForm and get information back from it.

As with the regular code module, the UserForm module should begin with

Option Explicit

If a control on the UserForm is to have code associated with it, double-click on the control and the VB Editor will insert a short stub of code into the module. For example, if you double-click on the OK button (named btnOK), the Editor will insert this:

Private Sub btnOK_Click()

End Sub

To make the code useful, we only need to insert our statements within this stub.

When the user clicks the OK button, we want the form to be hidden but remain in memory:

Private Sub btnOK_Click()
  Me.Hide
End Sub

When the UserForm is first loaded, we want the information from the named range ChartTypes to appear in the listbox lstChartTypes. The UserForm_Initialize code runs when the UserForm is loaded, and the code shown here does the magic:

Private Sub UserForm_Initialize()
  Dim vChartTypes As Variant
  
  vChartTypes = ThisWorkbook.Names("ChartTypes").RefersToRange.Value2
  Me.lstChartTypes.List = vChartTypes
End Sub

The button-formatted labels need some simple code attached, so that clicking them will populate the X and Y column lists. Click the lblbtnX label button to populate the lstX listbox:

Private Sub lblbtnX_Click()
  Dim iLst As Long
  
  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Me.lstX.AddItem iLst
    End If
  Next
End Sub

Click the lblbtnY label button to populate the lstY listbox:

Private Sub lblbtnY_Click()
  Dim iLst As Long

  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Me.lstY.AddItem iLst
    End If
  Next
End Sub

Click the lblbtnReset lable button to clear the X and Y listboxes and start over:

Private Sub lblbtnReset_Click()
  Me.lstX.Clear
  Me.lstY.Clear
End Sub

We need the ChartData property to pass the information to display in the lstChartData listbox of the UserForm:

Public Property Let ChartData(vData As Variant)
  Me.lstChartData.List = vData
End Property

We also needproperties to let us extract information from the UserForm: whether the first row of the CSV file has header labels, the selected chart type, and the X and Y columns to be plotted:

Property Get FirstRowHeaders() As Boolean
  FirstRowHeaders = Me.chkFirstRowHeaders.Value
End Property

Public Property Get ChartType() As XlChartType
  With Me.lstChartTypes
    If .ListIndex > -1 Then
      ChartType = CLng(.List(.ListIndex, 0))
    End If
  End With
End Property

Public Property Get Xcolumns() As Variant
  Xcolumns = Me.lstX.List
End Property

Public Property Get YColumns() As Variant
  YColumns = Me.lstY.List
End Property

The Simple Tool

Code Module MChartFromCSVFile

Here is the complete listing of MChartFromCSVFile:

Option Explicit

Sub OpenCSVFileAndPlotData()
  Dim sCSVFullName As String, sWbkFullName As String, sFileRoot As String
  Dim wb As Workbook, ws As Worksheet, rng As Range, vRng As Variant
  Dim rCht As Range, cht As Chart, srs As Series
  Dim iRows As Long, iCols As Long, iRow As Long, iCol As Long
  Dim sTemp As String
  Dim vChartData As Variant
  Dim bFirstRowHeaders As Boolean
  Dim myChartType As XlChartType
  Dim vX As Variant, vY As Variant
  Dim iX As Long, iY As Long, iSrs As Long
  Dim nX As Long, nY As Long, nSrs As Long
  Dim frmChartFromCSVFile As FChartFromCSVFile
  
  ' 1. Get CSV file name
  sCSVFullName = Application.GetOpenFilename("CSV Files (*.csv), *.csv", , "Select a CSV file", , False)

  ' 2. Open CSV file
  Workbooks.Open sCSVFullName
  Set wb = ActiveWorkbook
  
  ' 3. Save as workbook
  sFileRoot = Left$(sCSVFullName, InStrRev(sCSVFullName, ".") - 1)
  sWbkFullName = sFileRoot & ".xlsx"
  wb.SaveAs sWbkFullName, xlWorkbookDefault
  
  ' 4. Parse file
  Set ws = wb.Worksheets(1)
  Set rng = ws.UsedRange
  vRng = rng.Value2
  iRows = rng.Rows.Count
  iCols = rng.Columns.Count
  
  '' info to display: column number, first few rows of column
  ReDim vChartData(1 To iCols, 1 To 2)
  For iCol = 1 To iCols
    vChartData(iCol, 1) = iCol
    sTemp = ""
    For iRow = 1 To 4
      If iRow > iRows Then Exit For
      sTemp = sTemp & vRng(iRow, iCol) & ", "
    Next
    sTemp = Left$(sTemp, Len(sTemp) - 2)
    vChartData(iCol, 2) = sTemp
  Next
  
  ' 5. Show dialog (get chart type, X values, Y values)
  Set frmChartFromCSVFile = New FChartFromCSVFile
  With frmChartFromCSVFile
    '' pass in information we know
    .ChartData = vChartData
    
    .Show
    
    myChartType = .ChartType
    bFirstRowHeaders = .FirstRowHeaders
    vX = .Xcolumns
    vY = .YColumns
  End With
  Unload frmChartFromCSVFile
  
  ' 6. Draw chart
  '' define some series parameters
  If IsEmpty(vX) Then
    nX = 0
  Else
    nX = UBound(vX, 1) + 1 - LBound(vX, 1)
  End If
  nY = UBound(vY, 1) + 1 - LBound(vY, 1)
  nSrs = nY
  If nX > nY Then nSrs = nX
  If bFirstRowHeaders Then
    Set rCht = rng.Offset(1).Resize(iRows - 1)
  Else
    Set rCht = rng
  End If
  
  '' select blank cell before inserting chart
  rng.Offset(iRows + 1, iCols + 1).Resize(1, 1).Select
  
  Set cht = ws.Shapes.AddChart.Chart '' Excel 2007+
  ''Set cht = ws.Shapes.AddChart2.Chart '' Excel 2013 only
  
  '' chart type
  With cht
    .ChartType = myChartType
    
    '' add series
    For iSrs = 1 To nSrs
      Set srs = .SeriesCollection.NewSeries
      With srs
        ' X values
        If nX = 0 Then
          ' no X values specified
        ElseIf nX = 1 Then
          ' all series share X values
          .XValues = rCht.Columns(CLng(vX(0, 0)))
        Else
          ' each series has unique X values
          .XValues = rCht.Columns(CLng(vX(iSrs - 1, 0)))
        End If
        ' Y values
        If nY = 1 Then
          ' all series share Y values
          .Values = rCht.Columns(CLng(vY(0, 0)))
        Else
          ' each series has unique Y values
          .Values = rCht.Columns(CLng(vY(iSrs - 1, 0)))
        End If
        ' series name
        If bFirstRowHeaders Then
          If nSrs = nY Then
            .Name = "=" & rng.Cells(1, CLng(vY(iSrs - 1, 0))).Address(True, True, xlA1, True)
          ElseIf nSrs = nX Then
            .Name = "=" & rng.Cells(1, CLng(vX(iSrs - 1, 0))).Address(True, True, xlA1, True)
          End If
        End If
      End With
    Next
  End With
  
  ' 7. Save file
  wb.Save
  
ExitProcedure:
  
End Sub

UserForm Module FChartFromCSVFile

Here is the complete listing of FChartFromCSVFile:

Option Explicit

Private Sub btnOK_Click()
  Me.Hide
End Sub

Private Sub lblbtnReset_Click()
  Me.lstX.Clear
  Me.lstY.Clear
End Sub

Private Sub lblbtnX_Click()
  Dim iLst As Long
  
  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Me.lstX.AddItem iLst
    End If
  Next
End Sub

Private Sub lblbtnY_Click()
  Dim iLst As Long

  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Me.lstY.AddItem iLst
    End If
  Next
End Sub

Public Property Let ChartData(vData As Variant)
  Me.lstChartData.List = vData
End Property

Property Get FirstRowHeaders() As Boolean
  FirstRowHeaders = Me.chkFirstRowHeaders.Value
End Property

Public Property Get ChartType() As XlChartType
  With Me.lstChartTypes
    If .ListIndex > -1 Then
      ChartType = CLng(.List(.ListIndex, 0))
    End If
  End With
End Property

Public Property Get Xcolumns() As Variant
  Xcolumns = Me.lstX.List
End Property

Public Property Get YColumns() As Variant
  YColumns = Me.lstY.List
End Property

Private Sub UserForm_Initialize()
  Dim vChartTypes As Variant
  
  vChartTypes = ThisWorkbook.Names("ChartTypes").RefersToRange.Value2
  Me.lstChartTypes.List = vChartTypes
End Sub

Workbook with Working Code

You can download the simple workbook My_CSV_Data_Processor.xlsm to see all of this code in one place, and to see how it works.

Advanced Version

The next blog post has a number of enhancements that make things easier for the user and prevent various warning messages. Stay tuned…

 

The post VBA: A Simple Tool to Open a CSV File and Create Chart with Data Specified by User appeared first on Peltier Tech Blog.

VBA: An Advanced Add-in to Open a CSV File and Create Chart with Data Specified by User

$
0
0

Introduction

This article builds upon a previous post, VBA: A Simple Tool to Open a CSV File and Create Chart with Data Specified by User, which showed how to build the barest possible VBA procedure for opening a CSV file and making a chart from its data. This article will show how to make the VBA procedure more robust, easier to use, and resistant to errors. It is assumed that you’ve already built the simple VBA tool from the earlier article.

Advanced Solution

Rather than the simple workbook we created in the previous solution, the advanced solution will use an add-in. This integrates the add-in’s functionality more smoothly into Excel, making the solution a more professional option.

Add-ins are like regular Excel workbooks, complete with worksheets and other Excel objects, but they have a different file extension, .xlam, and they are not visible in the Excel interface. They can be opened like regular workbooks when their functionality is needed, or they can be installed so that they are always available.

Code Workbook (Add-In)

Saved Information: Named Range Containing Chart Types and Styles

The worksheet contains a list of chart types that our program will create. These are the simplest and most useful charts built into Excel. The list has three columns, the first being the integer values of Excel’s chart type constants (e.g., xlArea = 1, xlXYScatter = -4169), the second the default chart styles in Excel 2013 (ignored in earlier versions), and the third the chart type names that will appear in the dialog. To modify the eerlier worksheet, simply insert a column between the Value and Type values, and insert the Style values.

The range A2:C12 has been named “ChartTypes”, so it will be easy for the code to put these values into the dialog. We can save information like this even in the invisible worksheets of an invisible add-in.

Create an Add-In

Now that we’ve updated the chart type data, we can save our workbook as an add-in.

With the workbook active, go to File tab > Save As, browse to a folder, change the Save As Type to Excel Add-In (*.xlam), and note that the dialog changes to the default user add-in library (C:\Users\[username]\AppData\Roaming\Microsoft\AddIns). This is a convenient place to store add-ins, because they are easier to find when you want to install them. However, if you have an orderly file system hierarchy, you may want to store the add-in with related files. If so, navigate to the desired folder. Then click Save.

The worksheets of an add-in are not visible in the Excel interface. However, you can temporarily change an add-in back to a regular workbook. In the VB Editor’s Project Explorer, select the ThisWorkbook object of the add-in’s VB project, choose the IsAddIn property in the Property Window, and change it to False. The add-in workbook is now visible like any other workbook. Make any adjustments, then change the IsAddIn property back to True.

Starting the Program: The Excel Ribbon

Since the sheet is not visible, there is no button to start the code. We’ll use a button on the ribbon instead.

Many web pages and blog posts have been written about writing XML code for custom ribbon controls. As far as I know, only two books have been dedicated to the ribbon.

One is RibbonX: Customizing the Office 2007 Ribbon (affiliate link), written by two Excel MVPs and one Access MVPs. This is a very comprehensive volume that covers more than you could possibly want to know about customizing your ribbon. On a dollars-per-page basis, it also has to be about the cheapest Excel reference I’ve ever purchased.

The other book about the Office ribbon is RibbonX For Dummies, and I must admit I know very little about it.

To make it easy to add custom ribbon elements to your workbook or add-in, you should download the Custom UI Editor from the Open XML Developer web site. Open the add-in or workbook in the Custom UI Editor, insert an Office 2007 Custom UI Part from the Insert menu, and paste the code below into the Custom UI Part.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon>
    <tabs>
      <tab idMso="TabData">
        <group id="gpCSV" label="Process CSV">
          <button id="btnProcessCSV" label="Process CSV File" screentip="Import CSV 
              file, save as Excel workbook, insert chart using dialog-selected type 
              and data" size="large" onAction="RX_OpenCSVFileAndPlotData" 
              imageMso="GroupChartLocation" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

This code adds a custom group, “Process CSV”, to the Data tab of Excel’s ribbon, and adds a custom button, “Process CSV File”, to this group. The button calls a procedure named RX_OpenCSVFileAndPlotData.

The Custom UI Editor can be used to generate the callback for this procedure:

'Callback for btnProcessCSV onAction
Sub RX_OpenCSVFileAndPlotData(control As IRibbonControl)
End Sub

This callback is pasted into a regular code module, and the procedure that we’ve been working on, OpenCSVFileAndPlotData, is called from within the callback. You could simply have called OpenCSVFileAndPlotData from the XML code, but you would have had to add the control As IRibbonControl argument to the procedure definition. This makes it harder to simply call the code from the VB Editor’s Immediate Window.

Here is the finished callback, ready to go:

'Callback for btnProcessCSV onAction
Sub RX_OpenCSVFileAndPlotData(control As IRibbonControl)
  OpenCSVFileAndPlotData
End Sub

The button looks like this, at the right end of the Data tab of the ribbon:

Code Module

Here are the adjustments to the MChartFromCSVFile code module.

1. Get CSV File Name

There are several things we can do to make sure the program is nice to the users.

First of all, we need to exit gracefully if the user cancels the GetOpenFileName dialog. Canceling the dialog returns False, so we need to prevent the error that will occur when the program tries to open a file named “False”.

We should check whether the file is already open in Excel, and offer to work on the open file.

We should check whether the file is even a CSV file. If it is not a CSV file, it will not open in Excel with the expected column structure. It is possible to make the program smart enough to open any text, and split the data into columns using any delimiter (commas, tabs, pipe characters), but that is for another exercise.

If the user decides to abort at any point, the execution proceeds to a label named ExitProcedure at the end of the main procedure.

  Do
    sCSVFullName = Application.GetOpenFilename("CSV Files (*.csv), *.csv", , _
        "Select a CSV file", , False)
    
    '' check whether user cancels
    If sCSVFullName = "False" Then GoTo ExitProcedure
    
    '' check that file isn't already open
    bOpenFile = False
    For Each wbTest In Workbooks
      If wbTest.FullName = sCSVFullName Then
        bOpenFile = True
        Exit For
      End If
    Next
    If bOpenFile Then
      iMsgBoxResult = MsgBox("Data file is already open. Continue with open file?", _
          vbYesNo + vbQuestion, "File Already Open")
      If iMsgBoxResult = vbYes Then
        Set wb = wbTest
        Exit Do
      End If
    End If
    
    '' ensure that it's a CSV file
    If LCase$(Right$(sCSVFullName, 4)) <> ".csv" Then
      iMsgBoxResult = MsgBox("That doesn't appear to be a CSV file. Continue anyway?", _
          vbYesNo + vbQuestion, "Not a CSV File")
      If iMsgBoxResult = vbYes Then Exit Do
    Else
      Exit Do
    End If
  Loop

2. Open CSV file

The only thing to add here is a check whether our workbook wb has already been defined (that is, the CSV file was already open when the user started the program).

  If wb Is Nothing Then
    Workbooks.Open sCSVFullName
    Set wb = ActiveWorkbook
  End If

3. Save as workbook

There are many little changes we can do to make a user’s life easier. We want to save the workbook with the same name as the original CSV file, but we don’t want to bother the user with any duplicate file names. If we encounter a duplicate, we’ll append “_1″ to the file name; if that’s also a duplicate, we’ll append “_2″, and so on.

We need to check for duplicate file names among files already open in Excel, because two open workbooks cannot share the same file name. Then we need to check for duplicate file names in the directory we will save the workbook in.

  sFileRoot = Left$(sCSVFullName, InStrRev(sCSVFullName, ".") - 1)
  sWbkFullName = sFileRoot & ".xlsx"
  iFile = 0
  Do
    '' check for duplicate file (already open)
    bOpenFile = False
    For Each wbTest In Workbooks
      If wbTest.FullName = sWbkFullName Then
        bOpenFile = True
        Exit For
      End If
    Next
    
    '' check for duplicate file (in folder)
    If Not bOpenFile Then
      If Len(Dir(sWbkFullName)) = 0 Then Exit Do
    End If
    
    '' increment file name
    iFile = iFile + 1
    sWbkFullName = sFileRoot & "_" & CStr(iFile) & ".xlsx"
  Loop
  
  wb.SaveAs sWbkFullName, xlWorkbookDefault

All of this checking may seem excessively compulsive, but being a good programmer means preventing user frustration. Remember, the user may know where you live.

4. Parse file

We can improve the dialog display slightly, by not trying to show the first four rows of data if there are less than three rows in the CSV file.

While we’re making life easier for the user, let’s check the first row for text values, so we can precheck the dialog box if it looks like the file starts with column headers.

  Set ws = wb.Worksheets(1)
  Set rng = ws.UsedRange
  vRng = rng.Value2
  iRows = rng.Rows.Count
  iCols = rng.Columns.Count
  
  '' info to display: column number, first few rows of column
  ReDim vChartData(1 To iCols, 1 To 2)
  For iCol = 1 To iCols
    vChartData(iCol, 1) = iCol
    sTemp = ""
    For iRow = 1 To 4
      If iRow > iRows Then Exit For
      sTemp = sTemp & vRng(iRow, iCol) & ", "
    Next
    sTemp = Left$(sTemp, Len(sTemp) - 2)
    vChartData(iCol, 2) = sTemp
  Next

  '' first row header labels if all cells in first row are text
  For iCol = 1 To iCols
    bFirstRowHeaders = Not IsNumeric(vRng(1, iCol))
    If Not bFirstRowHeaders Then Exit For
  Next

5. Show dialog

When we load the dialog (UserForm), we pass in the array that shows the first few rows of data using the ChartData property, and also pass in our best guess about whether the first row of the has header labels in the FirstRowHeaders property.

After the user dismisses the dialog, we check whether the user canceled using the Cancel property. If the user did not cancel, we get chart type, first row headers, and X and Y columns using the appropriate properties.

Now we’re done with the UserForm, so we can unload it. If the user has canceled, we jump to the ExitProcedure label at the end of our program.

  Set frmChartFromCSVFile = New FChartFromCSVFile
  With frmChartFromCSVFile
    '' pass in information we know
    .ChartData = vChartData
    .FirstRowHeaders = bFirstRowHeaders
    
    .Show
    
    '' check whether user canceled
    bCancel = .Cancel
    If Not bCancel Then
      '' get information selected by user
      myChartType = .ChartType
      bFirstRowHeaders = .FirstRowHeaders
      vX = .Xcolumns
      vY = .YColumns
    End If
  End With
  Unload frmChartFromCSVFile

  If bCancel Then GoTo ExitProcedure

6. Draw chart

We define the chart series data as in the earlier program. We select a blank cell so the chart we insert has no data plotted in it.

We insert the chart using the Excel 2007 syntax, so the code runs as expected in Excel 2007 and 2010. After we assign the selected chart type in Excel 2013, we apply the default Excel 2013 chart style for that chart type, to obtain the nicer Excel 2013 styles.

One by one we add each series, and if there are more than one series, we add a legend to our chart.

  '' define some series parameters
  If IsEmpty(vX) Then
    nX = 0
  Else
    nX = UBound(vX, 1) + 1 - LBound(vX, 1)
  End If
  nY = UBound(vY, 1) + 1 - LBound(vY, 1)
  nSrs = nY
  If nX > nY Then nSrs = nX
  If bFirstRowHeaders Then
    Set rCht = rng.Offset(1).Resize(iRows - 1)
  Else
    Set rCht = rng
  End If
  
  '' select blank cell before inserting chart
  rng.Offset(iRows + 1, iCols + 1).Resize(1, 1).Select
  
  Set cht = ws.Shapes.AddChart.Chart '' Excel 2007+
  
  '' chart type and style
  With cht
    If myChartType <> 0 Then
      .ChartType = myChartType
      If Val(Application.Version) >= 15 Then
        '' Excel 2013 ChartStyles
        If iChartStyle > 0 Then
          .ChartStyle = iChartStyle
        End If
      End If
    End If
    
    '' add series
    For iSrs = 1 To nSrs
      Set srs = .SeriesCollection.NewSeries
      With srs
        ' X values
        If nX = 0 Then
          ' no X values specified
        ElseIf nX = 1 Then
          ' all series share X values
          .XValues = rCht.Columns(CLng(vX(0, 0)))
        Else
          ' each series has unique X values
          .XValues = rCht.Columns(CLng(vX(iSrs - 1, 0)))
        End If
        ' Y values
        If nY = 1 Then
          ' all series share Y values
          .Values = rCht.Columns(CLng(vY(0, 0)))
        Else
          ' each series has unique Y values
          .Values = rCht.Columns(CLng(vY(iSrs - 1, 0)))
        End If
        ' series name
        If bFirstRowHeaders Then
          If nSrs = nY Then
            .Name = "=" & rng.Cells(1, CLng(vY(iSrs - 1, 0))). _
                Address(True, True, xlA1, True)
          ElseIf nSrs = nX Then
            .Name = "=" & rng.Cells(1, CLng(vX(iSrs - 1, 0))). _
                Address(True, True, xlA1, True)
          End If
        End If
      End With
    Next
    
    If iSrs > 1 Then
      .HasLegend = True
    End If
  End With

7. Save file

Let’s select cell A1 before saving, just to satisfy our obsession with an orderly worksheet.

  ws.Range("A1").Select
  wb.Save

UserForm

The UserForm looks much like the earlier version, with the addition of a Default “label button” (a label with a raised appearance that functions as a button). This uses the first column of the CSV file as the chart’s X values, and each subsequent column as Y values for another series in the chart.

There also is a Cancel button if the user decides to bail out.

The lstChartType listbox now has three columns, two hidden columns for the chart type codes and the newly added chart style codes, and a visible column for the chart type names. This simply requires changing the ColumnWidths property to 0 pt;0 pt;112 pt. There is a new ChartStyles property used to get the appropriate Excel 2013 chart style codes for the selected chart type.

There are many changes to the code that make things run more smoothly.

Clicking the OK button will invoke some validation of selected columns, to ensure that the selected data is appropriate for the selected chart type. Data entry controls will be shaded light red if the data is not correctly validated and a message to the user will explain the problem.

Clicking the Cancel button sets a variable so that our code knows when the user canceled the process. In addition, code is added so that clicking the red X in the top right corner of the dialog doesn’t lead to error messages.

The X label button will do a little thinking before adding selected columns to the X listbox: if the chart type is a scatter chart, all selected columns will be added as X value columns, but if not, the list of X value columns will be cleared and only the first selected column will be added.

New variables in the UserForm module:

Dim mbCancel As Boolean
Const miBAD_COLOR As Long = &HC0C0FF
Const miGOOD_COLOR As Long = &H80000005

Validation added to the OK button:

Private Sub btnOK_Click()
  Dim bValid As Boolean
  Dim sInvalid As String
  
  bValid = True
  mbCancel = False
  
  'validate
  Me.lstX.BackColor = miGOOD_COLOR
  Me.lstY.BackColor = miGOOD_COLOR
  If Me.lstY.ListCount < 1 Then
    bValid = False
    sInvalid = "There must be at least one Y range in any chart."
    Me.lstY.BackColor = miBAD_COLOR
  End If
  Select Case Me.ChartType
    Case -4169, 75, 74
      If Me.lstX.ListCount = Me.lstY.ListCount Then
      ElseIf Me.lstX.ListCount <= 1 And Me.lstY.ListCount > 0 Then
      ElseIf Me.lstY.ListCount = 1 And Me.lstX.ListCount > 0 Then
      Else
        bValid = False
        Me.lstX.BackColor = miBAD_COLOR
        Me.lstY.BackColor = miBAD_COLOR
        sInvalid = sInvalid & "For a " & Me.lstChartTypes.List _
            (Me.lstChartTypes.ListIndex, 1) & " chart, there must be" & vbNewLine
        sInvalid = sInvalid & "- equal numbers of X and Y ranges," & vbNewLine
        sInvalid = sInvalid & "- at most 1 X range and multiple Y ranges, or" _
            & vbNewLine
        sInvalid = sInvalid & "- multiple X ranges and one Y range." & vbNewLine
      End If
    Case Else
      If Me.lstX.ListCount > 1 Then
        bValid = False
        sInvalid = sInvalid & "There can be at most one X range for a " & _
            Me.lstChartTypes.List(Me.lstChartTypes.ListIndex, 1) & " chart." & vbNewLine
        Me.lstX.BackColor = miBAD_COLOR
      End If
  End Select
  
  If bValid Then
    Me.Hide
  Else
    'Me.Repaint
    MsgBox sInvalid, vbExclamation, "Invalid Data Selections"
  End If
End Sub

The Cancel button code:

Private Sub btnCancel_Click()
  mbCancel = True
  Me.Hide
End Sub

This code ensures that clicking the red X closes the form as if the user had clicked the Cancel button:

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
  If CloseMode = 0 Then
    Cancel = True
    btnCancel_Click
  End If
End Sub

Here’s the code for the Default label button:

Private Sub lblbtnDefault_Click()
  Dim iLst As Long
  
  Me.lstX.Clear
  Me.lstY.Clear

  Me.lstX.AddItem 1
  For iLst = 2 To Me.lstChartData.ListCount
    Me.lstY.AddItem iLst
  Next
End Sub

Here is the updated X label button code:

Private Sub lblbtnX_Click()
  Dim iLst As Long
  Dim myChartType As XlChartType
  
  myChartType = Me.ChartType
  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Select Case myChartType
        Case -4169, 75, 74 ' scatter
        Case Else ' not scatter
          Me.lstX.Clear
      End Select
      Me.lstX.AddItem iLst
      Select Case myChartType
        Case -4169, 75, 74 ' scatter
        Case Else ' not scatter
          Exit For
      End Select
    End If
  Next
End Sub

ChartStyle property

Public Property Get ChartStyle() As Long
  With Me.lstChartTypes
    If .ListIndex > -1 Then
      ChartStyle = CLng(.List(.ListIndex, 1))
    End If
  End With
End Property

Code Module MChartFromCSVFile

Here is the complete listing of MChartFromCSVFile:

Option Explicit

'Callback for btnProcessCSV onAction
Sub RX_OpenCSVFileAndPlotData(control As IRibbonControl)
  OpenCSVFileAndPlotData
End Sub

Sub OpenCSVFileAndPlotData()
  Dim sCSVFullName As String, sWbkFullName As String, sWbkFileName As String, _
      sFileRoot As String
  Dim iFile As Long
  Dim bOpenFile As Boolean
  Dim wb As Workbook, wbTest As Workbook, ws As Worksheet, rng As Range, vRng As Variant
  Dim rCht As Range, cht As Chart, srs As Series
  Dim iRows As Long, iCols As Long, iRow As Long, iCol As Long
  Dim sTemp As String
  Dim vChartData As Variant
  Dim bFirstRowHeaders As Boolean
  Dim myChartType As XlChartType, iChartStyle As Long
  Dim vX As Variant, vY As Variant
  Dim iX As Long, iY As Long, iSrs As Long
  Dim nX As Long, nY As Long, nSrs As Long
  Dim bCancel As Boolean
  Dim iMsgBoxResult As VbMsgBoxResult
  Dim frmChartFromCSVFile As FChartFromCSVFile
  
  ' 1. Get CSV file name
  Do
    sCSVFullName = Application.GetOpenFilename("CSV Files (*.csv), *.csv", , _
        "Select a CSV file", , False)
    
    '' check whether user cancels
    If sCSVFullName = "False" Then GoTo ExitProcedure
    
    '' check that file isn't already open
    bOpenFile = False
    For Each wbTest In Workbooks
      If wbTest.FullName = sCSVFullName Then
        bOpenFile = True
        Exit For
      End If
    Next
    If bOpenFile Then
      iMsgBoxResult = MsgBox("Data file is already open. Continue with open file?", _
          vbYesNo + vbQuestion, "File Already Open")
      If iMsgBoxResult = vbYes Then
        Set wb = wbTest
        Exit Do
      End If
    End If
    
    '' ensure that it's a CSV file
    If LCase$(Right$(sCSVFullName, 4)) <> ".csv" Then
      iMsgBoxResult = MsgBox("That doesn't appear to be a CSV file. Continue anyway?", _
          vbYesNo + vbQuestion, "Not a CSV File")
      If iMsgBoxResult = vbYes Then Exit Do
    Else
      Exit Do
    End If
  Loop
  
  ' 2. Open CSV file
  If wb Is Nothing Then
    Workbooks.Open sCSVFullName
    Set wb = ActiveWorkbook
  End If
  
  ' 3. Save as workbook
  sFileRoot = Left$(sCSVFullName, InStrRev(sCSVFullName, ".") - 1)
  sWbkFullName = sFileRoot & ".xlsx"
  iFile = 0
  Do
    '' check for duplicate file (already open)
    bOpenFile = False
    For Each wbTest In Workbooks
      If wbTest.FullName = sWbkFullName Then
        bOpenFile = True
        Exit For
      End If
    Next
    
    '' check for duplicate file (in folder)
    If Not bOpenFile Then
      If Len(Dir(sWbkFullName)) = 0 Then Exit Do
    End If
    
    '' increment file name
    iFile = iFile + 1
    sWbkFullName = sFileRoot & "_" & CStr(iFile) & ".xlsx"
  Loop
  
  wb.SaveAs sWbkFullName, xlWorkbookDefault
  
  ' 4. Parse file
  Set ws = wb.Worksheets(1)
  Set rng = ws.UsedRange
  vRng = rng.Value2
  iRows = rng.Rows.Count
  iCols = rng.Columns.Count
  
  '' info to display: column number, first few rows of column
  ReDim vChartData(1 To iCols, 1 To 2)
  For iCol = 1 To iCols
    vChartData(iCol, 1) = iCol
    sTemp = ""
    For iRow = 1 To 4
      If iRow > iRows Then Exit For
      sTemp = sTemp & vRng(iRow, iCol) & ", "
    Next
    sTemp = Left$(sTemp, Len(sTemp) - 2)
    vChartData(iCol, 2) = sTemp
  Next
  
  '' first row header labels if all cells in first row are text
  For iCol = 1 To iCols
    bFirstRowHeaders = Not IsNumeric(vRng(1, iCol))
    If Not bFirstRowHeaders Then Exit For
  Next
  
  ' 5. Show dialog (get chart type, X values, Y values)
  Set frmChartFromCSVFile = New FChartFromCSVFile
  With frmChartFromCSVFile
    '' pass in information we know
    .ChartData = vChartData
    .FirstRowHeaders = bFirstRowHeaders
    
    .Show
    
    '' check whether user canceled
    bCancel = .Cancel
    If Not bCancel Then
      '' get information selected by user
      myChartType = .ChartType
      iChartStyle = .ChartStyle
      bFirstRowHeaders = .FirstRowHeaders
      vX = .Xcolumns
      vY = .YColumns
    End If
  End With
  Unload frmChartFromCSVFile
  
  If bCancel Then GoTo ExitProcedure
  
  ' 6. Draw chart
  '' define some series parameters
  If IsEmpty(vX) Then
    nX = 0
  Else
    nX = UBound(vX, 1) + 1 - LBound(vX, 1)
  End If
  nY = UBound(vY, 1) + 1 - LBound(vY, 1)
  nSrs = nY
  If nX > nY Then nSrs = nX
  If bFirstRowHeaders Then
    Set rCht = rng.Offset(1).Resize(iRows - 1)
  Else
    Set rCht = rng
  End If
  
  '' select blank cell before inserting chart
  rng.Offset(iRows + 1, iCols + 1).Resize(1, 1).Select
  
  Set cht = ws.Shapes.AddChart.Chart '' Excel 2007+
  ''Set cht = ws.Shapes.AddChart2.Chart '' Excel 2013 only
  
  '' chart type and style
  With cht
    If myChartType <> 0 Then
      .ChartType = myChartType
      If Val(Application.Version) >= 15 Then
        '' Excel 2013 ChartStyles
        If iChartStyle > 0 Then
          .ChartStyle = iChartStyle
        End If
      End If
    End If
    
    '' add series
    For iSrs = 1 To nSrs
      Set srs = .SeriesCollection.NewSeries
      With srs
        ' X values
        If nX = 0 Then
          ' no X values specified
        ElseIf nX = 1 Then
          ' all series share X values
          .XValues = rCht.Columns(CLng(vX(0, 0)))
        Else
          ' each series has unique X values
          .XValues = rCht.Columns(CLng(vX(iSrs - 1, 0)))
        End If
        ' Y values
        If nY = 1 Then
          ' all series share Y values
          .Values = rCht.Columns(CLng(vY(0, 0)))
        Else
          ' each series has unique Y values
          .Values = rCht.Columns(CLng(vY(iSrs - 1, 0)))
        End If
        ' series name
        If bFirstRowHeaders Then
          If nSrs = nY Then
            .Name = "=" & rng.Cells(1, CLng(vY(iSrs - 1, 0))). _
                Address(True, True, xlA1, True)
          ElseIf nSrs = nX Then
            .Name = "=" & rng.Cells(1, CLng(vX(iSrs - 1, 0))). _
                Address(True, True, xlA1, True)
          End If
        End If
      End With
    Next
    
    If iSrs > 1 Then
      .HasLegend = True
    End If
  End With
  
  ' 7. Save file
  ws.Range("A1").Select
  wb.Save
  
ExitProcedure:
  
End Sub

blah

UserForm Module FChartFromCSVFile

Here is the complete listing of FChartFromCSVFile:

Option Explicit

Dim mbCancel As Boolean
Const miBAD_COLOR As Long = &HC0C0FF
Const miGOOD_COLOR As Long = &H80000005

Private Sub btnCancel_Click()
  mbCancel = True
  Me.Hide
End Sub

Private Sub btnOK_Click()
  Dim bValid As Boolean
  Dim sInvalid As String
  
  bValid = True
  mbCancel = False
  
  'validate
  Me.lstX.BackColor = miGOOD_COLOR
  Me.lstY.BackColor = miGOOD_COLOR
  If Me.lstY.ListCount < 1 Then
    bValid = False
    sInvalid = "There must be at least one Y range in any chart."
    Me.lstY.BackColor = miBAD_COLOR
  End If
  Select Case Me.ChartType
    Case -4169, 75, 74
      If Me.lstX.ListCount = Me.lstY.ListCount Then
      ElseIf Me.lstX.ListCount <= 1 And Me.lstY.ListCount > 0 Then
      ElseIf Me.lstY.ListCount = 1 And Me.lstX.ListCount > 0 Then
      Else
        bValid = False
        Me.lstX.BackColor = miBAD_COLOR
        Me.lstY.BackColor = miBAD_COLOR
        sInvalid = sInvalid & "For a " & Me.lstChartTypes.List _
            (Me.lstChartTypes.ListIndex, 1) & " chart, there must be" & vbNewLine
        sInvalid = sInvalid & "- equal numbers of X and Y ranges," & vbNewLine
        sInvalid = sInvalid & "- at most 1 X range and multiple Y ranges, or" _
            & vbNewLine
        sInvalid = sInvalid & "- multiple X ranges and one Y range." & vbNewLine
      End If
    Case Else
      If Me.lstX.ListCount > 1 Then
        bValid = False
        sInvalid = sInvalid & "There can be at most one X range for a " & _
            Me.lstChartTypes.List(Me.lstChartTypes.ListIndex, 1) & " chart." & vbNewLine
        Me.lstX.BackColor = miBAD_COLOR
      End If
  End Select
  
  If bValid Then
    Me.Hide
  Else
    'Me.Repaint
    MsgBox sInvalid, vbExclamation, "Invalid Data Selections"
  End If
End Sub

Private Sub lblbtnDefault_Click()
  Dim iLst As Long
  
  Me.lstX.Clear
  Me.lstY.Clear

  Me.lstX.AddItem 1
  For iLst = 2 To Me.lstChartData.ListCount
    Me.lstY.AddItem iLst
  Next
End Sub

Private Sub lblbtnReset_Click()
  Me.lstX.Clear
  Me.lstY.Clear
End Sub

Private Sub lblbtnX_Click()
  Dim iLst As Long
  Dim myChartType As XlChartType
  
  myChartType = Me.ChartType
  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Select Case myChartType
        Case -4169, 75, 74
        Case Else
          Me.lstX.Clear
      End Select
      Me.lstX.AddItem iLst
      Select Case myChartType
        Case -4169, 75, 74
        Case Else
          Exit For
      End Select
    End If
  Next
End Sub

Private Sub lblbtnY_Click()
  Dim iLst As Long

  For iLst = 1 To Me.lstChartData.ListCount
    If Me.lstChartData.Selected(iLst - 1) Then
      Me.lstY.AddItem iLst
    End If
  Next
End Sub

Public Property Let ChartData(vData As Variant)
  Me.lstChartData.List = vData
End Property

Property Let FirstRowHeaders(bFirstRowHeaders As Boolean)
  Me.chkFirstRowHeaders.Value = bFirstRowHeaders
End Property

Property Get FirstRowHeaders() As Boolean
  FirstRowHeaders = Me.chkFirstRowHeaders.Value
End Property

Public Property Get ChartType() As XlChartType
  With Me.lstChartTypes
    If .ListIndex > -1 Then
      ChartType = CLng(.List(.ListIndex, 0))
    End If
  End With
End Property

Public Property Get ChartStyle() As Long
  With Me.lstChartTypes
    If .ListIndex > -1 Then
      ChartStyle = CLng(.List(.ListIndex, 1))
    End If
  End With
End Property

Public Property Get Xcolumns() As Variant
  Xcolumns = Me.lstX.List
End Property

Public Property Get YColumns() As Variant
  YColumns = Me.lstY.List
End Property

Public Property Get Cancel() As Boolean
  Cancel = mbCancel
End Property

Private Sub UserForm_Initialize()
  Dim vChartTypes As Variant
  
  vChartTypes = ThisWorkbook.Names("ChartTypes").RefersToRange.Value2
  Me.lstChartTypes.List = vChartTypes
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
  If CloseMode = 0 Then
    Cancel = True
    btnCancel_Click
  End If
End Sub

Add-In with Working Code

You can download the advanced add-in My_CSV_Data_Processor.xlam to see all of this code in one place, and to see how it works.

Using the Add-In

You could open the add-in like a regular workbook, by double-clicking on it in Windows Explorer, dragging it onto the Excel window from Windows, or by using Excel’s File Open dialog. Alternatively you could install it as an add-in, so it is always available:

  • In Excel, click on the File tab or in Excel 2007 the big round Office button in the top left corner
  • Select Options (or Excel Options) from the list
  • Click Add-Ins in the dialog
  • Click the Go button
  • Click Browse and navigate to the folder containing .xlam add-in file
  • Select the .xlam file and click OK a couple times to return to Excel

However the add-in is used, a new button is added to the end of the Data tab on the ribbon. Click the button to launch the code.

The post VBA: An Advanced Add-in to Open a CSV File and Create Chart with Data Specified by User appeared first on Peltier Tech Blog.

Apply Custom Data Labels to Charted Points

$
0
0

Often you want to add custom data labels to your chart. The chart below uses labels from a column of data next to the plotted values.

Simple Chart with Custom Data Labels

When you first add data labels to a chart, Excel decides what to use for labels—usually the Y values for the plotted points, and in what position to place the points—above or right of markers, centered in bars or columns. Of course you can change these settings, but it isn’t obvious how to use custom text for your labels.

This chart is the starting point for our exercise. It plots simple data from columns B and C, and it displays only the default data labels, showing the Y values of each point.

Simple Chart with Default Data Labels

There are a number of ways to apply custom data labels to your chart:

  • Manually Type Desired Text for Each Label
  • Manually Link Each Label to Cell with Desired Text
  • Use the Chart Labeler Program
  • Use Values from Cells (Excel 2013 and later)
  • Write Your Own VBA Routines

Manually Type Desired Text for Each Label

The least sophisticated way to get your desired text into each label is to manually type it in.

Click once on a label to select the series of labels.

Simple Chart with Data Labels Selected

Click again on a label to select just that specific label.

Simple Chart with Specific Data Label Selected

Double click on the label to highlight the text of the label, or just click once to insert the cursor into the existing text.

Simple Chart with Data Label Text Selected

Type the text you want to display in the label, and press the Enter key.

Simple Chart with Data Label Text Being Typed

Repeat for all of your custom data labels. This could get tedious, and you run the risk of typing the wrong text for the wrong label (I initially typed “alpha” for the label above, and had to redo my screenshot).

One thing that makes this approach unsophisticated is that the typed labels are not dynamic. If th text in one of the cells changes, the corresponding label will not update.

Manually Link Each Label to Cell with Desired Text

Select an individual label (two single clicks as shown above, so the label is selected but the cursor is not in the label text), type an equals sign in the formula bar, click on the cell containing the label you want, and press Enter. The formula bar shows the link (=Sheet1!$D$3).

Simple Chart with Data Label Link Being Entered

Repeat for each of the labels. This could get tedious, but at least the labels are dynamic. If the text in one of the cells changes, the corresponding label updates to show the new text.

Use the Chart Labeler Program

Brilliant Excel jockey and former MVP Rob Bovey has written a Chart Labeler add-in, which allows you to assign labels from a worksheet range to the points in a chart. It is free for anyone to use and can be downloaded from http://appspro.com. Rob colls it the XY Chart Labeler, but it actually works with any chart type that supports data labels.

When installed, the add-in adds a custom ribbon tab with a handful of useful commands. The tab is added at the end of the ribbon, but being pressed for space I moved it digitally to the beginning.

XY Chart Labeler Ribbon Tab

With a chart selected, click the Add Labels ribbon button (if a chart is not selected, a dialog pops up with a list of charts on the active worksheet). A dialog pops up so you can choose which series to label, select a worksheet range with the custom data labels, and pick a position for the labels.

XY Chart Labeler Dialog

If you select a single label, you can see that the label contains a link to the corresponding worksheet cell. This is like the previous method, but less tedious and much faster.

XY Chart Labeler Dialog

Use Values from Cells (Excel 2013 and later)

After years and years of listening to its users begging, Microsoft finally added an improved labeling option to Excel 2013.

First, add labels to your series, then press Ctrl+1 (numeral one) to open the Format Data Labels task pane. I’ve shown the task pane below floating next to the chart, but it’s usually docked off to the right edge of the Excel window.

Format Data Labels Task Pane

Click on the new checkbox for Values From Cells, and a small dialog pops up that allows you to select a range containing your custom data labels.

Format Data Labels Task Pane

Select your data label range.

Format Data Labels Task Pane

Then uncheck the Y Value option. I also uncheck the Show Leader Lines option, which is another enhancement added in Excel 2013. Leader lines are hardly ever useful for the charts I make, but many users are happy with them.

Format Data Labels Task Pane

While these data labels are not explicitly linked to worksheet cells as in the previous approaches, they still reflect any changes to the cells that contain the labels.

Write Your Own VBA Routines

I’ve put together a couple little routines that help with data point labeling. These are quick and dirty, because sometimes that’s all that you need. Also, writing your own code allows you to streamline your workflow according to your specific requirements.

Add Data Labels from Range Selected by User

This routine first makes sure a chart is selected, then it determines which series is to be labeled. It asks the user to select a range using an InputBox, and if the user doesn’t cancel it adds a label to the series point by point, linking the label to the appropriate cell.

Sub AddLabelsFromUserSelectedRange()
  Dim srs As Series, rng As Range, lbl As DataLabel
  Dim iLbl As Long, nLbls As Long

  If Not ActiveChart Is Nothing Then
    If ActiveChart.SeriesCollection.Count = 1 Then
      ' use only series in chart
      Set srs = ActiveChart.SeriesCollection(1)
    Else
      ' use series associated with selected object
      Select Case TypeName(Selection)
        Case "Series"
          Set srs = Selection
        Case "Point"
          Set srs = Selection.Parent
        Case "DataLabels"
          Set srs = Selection.Parent
        Case "DataLabel"
          Set srs = Selection.Parent.Parent
      End Select
    End If

    If Not srs Is Nothing Then
      ' ask user for range, avoid error if canceled
      On Error Resume Next
      Set rng = Application.InputBox( _
          "Select range containing data labels", _
          "Select Range with Labels", , , , , , 8)
      On Error GoTo 0

      If Not rng Is Nothing Then
        ' point by point, assign cell's address to label
        nLbls = srs.Points.Count
        If rng.Cells.Count < nLbls Then nLbls = rng.Cells.Count
        For iLbl = 1 To nLbls
          srs.Points(iLbl).HasDataLabel = True
          Set lbl = srs.Points(iLbl).DataLabel
          With lbl
            .Text = "=" & rng.Cells(iLbl).Address(External:=True)
            .Position = xlLabelPositionRight
          End With
        Next
      End If
    End If
  End If
End Sub

Add Data Labels from Row or Column Next to Y Values

This routine first makes sure a chart is selected, then it determines which series is to be labeled. It doesn’t bother the user, instead the routine parses the series formula to find the range containing the Y values, and if this is a valid range, it finds the next column or row, depending on the orientation of the Y values range. The code then adds a label to the series point by point, linking the label to the appropriate cell.

Sub AddLabelsFromRangeNextToYValues()
  Dim srs As Series, rng As Range, lbl As DataLabel
  Dim iLbl As Long, nLbls As Long
  Dim sFmla As String, sTemp As String, vFmla As Variant

  If Not ActiveChart Is Nothing Then
    If ActiveChart.SeriesCollection.Count = 1 Then
      ' use only series in chart
      Set srs = ActiveChart.SeriesCollection(1)
    Else
      ' use series associated with selected object
      Select Case TypeName(Selection)
        Case "Series"
          Set srs = Selection
        Case "Point"
          Set srs = Selection.Parent
        Case "DataLabels"
          Set srs = Selection.Parent
        Case "DataLabel"
          Set srs = Selection.Parent.Parent
      End Select
    End If

    If Not srs Is Nothing Then
      ' parse series formula to get range containing Y values
      sFmla = srs.Formula
      sTemp = Mid$(Left$(sFmla, Len(sFmla) - 1), InStr(sFmla, "(") + 1)
      vFmla = Split(sTemp, ",")
      sTemp = vFmla(LBound(vFmla) + 2)
      On Error Resume Next
      Set rng = Range(sTemp)

      If Not rng Is Nothing Then
        ' use next column or row as appropriate
        If rng.Columns.Count = 1 Then
          Set rng = rng.Offset(, 1)
        Else
          Set rng = rng.Offset(1)
        End If

        ' point by point, assign cell's address to label
        nLbls = srs.Points.Count
        If rng.Cells.Count < nLbls Then nLbls = rng.Cells.Count
        For iLbl = 1 To nLbls
          srs.Points(iLbl).HasDataLabel = True
          Set lbl = srs.Points(iLbl).DataLabel
          With lbl
            .Text = "=" & rng.Cells(iLbl).Address(External:=True)
            .Position = xlLabelPositionRight
          End With
        Next
      End If
    End If
  End If
End Sub

 

The post Apply Custom Data Labels to Charted Points appeared first on Peltier Tech Blog.

Viewing all 158 articles
Browse latest View live