<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Peltier Tech Blog &#187; VBA</title>
	<atom:link href="http://peltiertech.com/WordPress/category/vba/feed/" rel="self" type="application/rss+xml" />
	<link>http://peltiertech.com/WordPress</link>
	<description>Peltier Tech Excel Charts and Programming Blog</description>
	<lastBuildDate>Tue, 07 Feb 2012 14:40:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>New RefEdit Approach &#8211; Volunteers Wanted</title>
		<link>http://peltiertech.com/WordPress/new-refedit-approach-volunteers-wanted/</link>
		<comments>http://peltiertech.com/WordPress/new-refedit-approach-volunteers-wanted/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 19:33:59 +0000</pubDate>
		<dc:creator>Jon Peltier</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[RefEdit]]></category>

		<guid isPermaLink="false">http://peltiertech.com/WordPress/?p=3320</guid>
		<description><![CDATA[I published a tutorial about Using RefEdit Controls in Excel Dialogs, which showed how to use these helpful range-selection controls in Excel UserForms. Then I wrote about an Unspecified but Painfully Frustrating Error that seemed more often than not associated with RefEdit controls. This and other RefEdit problems skyrocketed as users of my commercial utilities upgraded [...]]]></description>
			<content:encoded><![CDATA[<p>I published a tutorial about <a href="http://peltiertech.com/WordPress/using-refedit-controls-in-excel-dialogs/"title="Using RefEdit Controls in Excel Dialogs" >Using RefEdit Controls in Excel Dialogs</a>, which showed how to use these helpful range-selection controls in Excel UserForms. Then I wrote about an <a href="http://peltiertech.com/WordPress/unspecified-painfully-frustrating-error/"title="Unspecified but Painfully Frustrating Error" >Unspecified but Painfully Frustrating Error</a> that seemed more often than not associated with RefEdit controls.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Unspecified Error" src="http://peltiertech.com/images/2009-06/unspecifiederror.png" alt="System Error &amp;H80004005 (-2147467259). Unspecified error" width="375" height="126" /></p>
<p>This and other RefEdit problems skyrocketed as users of my commercial utilities upgraded to Excel 2007 and beyond, to the point where I had to find an <a href="http://peltiertech.com/WordPress/refedit-control-alternative/"title="Alternative to Excel’s Flaky RefEdit Control" >Alternative to Excel’s Flaky RefEdit Control</a>. When I converted RefEdits to this alternative technique, support calls decreased by at least 90%. This was a nice change, but I didn&#8217;t think that the alternative worked as smoothly as a working RefEdit.</p>
<h2>Alternative Approach</h2>
<p>I was mulling over this issue with RefEdits recently, especially the fact that it seemed worse when the dialog was designed using one version of Excel and deployed on another version. Then I realized that if the problem is a mismatch between the RefEdit library on my machine and the library on a user&#8217;s machine, I should let the user&#8217;s machine add the RefEdits to the dialog.</p>
<p><span id="more-3320"></span>This is accomplished with a teeny bit of VBA code:</p>
<pre><code>    Set ctl = Me.Controls.Add("RefEdit.Ctrl", RefName, True)</code></pre>
<p>where <tt>Me</tt> refers back to the form, <tt>RefEdit.Ctrl</tt> is the class name for a RefEdit control, <tt class="tt">ctl</tt> is a variable declared as an <tt class="tt">Object</tt>, <tt class="tt">RefName</tt> is a string variable containing the name of the RefEdit control, and <tt class="tt">True</tt> reflects the visibility of the control.</p>
<p>With this in mind, I designed a dialog with space for two RefEdits; the user will select two ranges, one which will be filled in with red, the other with blue. The dialog has a label for each RefEdit, a button to clear any fill colors in the worksheet, and an OK button to apply the red and blue fills and to dismiss the dialog.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2011-08/FormWithoutRefEdits.png" alt="Dialog Without RefEdit Controls" width="502" height="316" /></p>
<p>On the worksheet is a simple Forms Menu button that runs the following code to load the dialog:</p>
<pre><code>Sub RefEditOnTheFly()
  Load UserForm1
  UserForm1.Show
End Sub</code></pre>
<p>The dialog contains the following code in its module:</p>
<pre><code>Private Sub UserForm_Initialize()
  Dim ctl As Object
  Dim i As Long

  For i = 1 To 2
    <span style="color: #339966;">' add RefEdit control</span>
    Set ctl = Me.Controls.Add("RefEdit.Ctrl", "RefEdit" &amp; i, True)

    <span style="color: #339966;">' position and size RefEdit control</span>
    With Me.Controls("RefEdit" &amp; i)
      .Top = Me.Controls("Label" &amp; i).Top + 12
      .Left = 27
      .Height = 15.75
      .Width = 264
      .TabIndex = Me.Controls("Label" &amp; i).TabIndex + 1
    End With
  Next
End Sub

Private Sub btnClear_Click()
  <span style="color: #339966;">' remove fill color from worksheet</span>
  ActiveSheet.Cells.Interior.ColorIndex = xlNone
End Sub

Private Sub btnOK_Click()
  On Error Resume Next
  <span style="color: #339966;">' apply fill color to selected ranges</span>
  Range(Me.Controls("RefEdit1").Text).Interior.Color = RGB(255, 0, 0)
  Range(Me.Controls("RefEdit2").Text).Interior.Color = RGB(0, 0, 255)
  Unload Me
End Sub</code></pre>
<p><tt class="tt">UserForm_Initialize</tt> runs when the form first loads, and adds the two RefEdit controls. <tt class="tt">btnClear_Click</tt> and <tt class="tt">btnOK_Click</tt> run when the buttons are clicked and remove or apply fill colors.</p>
<p>Here is how the dialog looks when it first loads:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2011-08/FormWithRefEdits.png" alt="Dialog With RefEdit Controls" width="627" height="599" /></p>
<p>When the user clicks in a RefEdit and starts to select a range, the dialog is compressed to the size of the RefEdit, and the selected range is highlighted with the &#8220;marching ants&#8221; border.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2011-08/FormWithRefEditCollapsed.png" alt="Dialog With RefEdit Collapsed For Selection" width="627" height="599" /></p>
<p>Here the dialog has had both RefEdits populated with ranges from the worksheet. The RefEdit containing the blue range has focus (note the cursor at the end of the address) so the ants are marching around this range.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2011-08/FormWithPopulatedRefEdits.png" alt="Dialog With Populated RefEdit Controls" width="627" height="599" /></p>
<p>When the dialog is dismissed with the OK button, the red range is filled in, then the blue range is filled in. The blue fill color fills any red cells from the red range.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2011-08/RangeColoredRedThenBlue.png" alt="Ranges Colored After Dismissing Dialog" width="627" height="599" /></p>
<h2>Try It, You&#8217;ll Like It</h2>
<p>I&#8217;ve put together a small Excel 2003 workbook to test out this RefEdit scheme. It has a simple worksheet, blank except for the &#8220;Go&#8221; button that loads the dialog. The dialog contains the two RefEdits shown above, drawn using VBA when the Go button is clicked.</p>
<p>If you&#8217;re willing to try it out, download the <a href="http://peltiertech.com/images/2011-08/RefEdit-on-the-fly.zip" rel="nofollow" title="RefEdit-on-the-fly.zip" >RefEdit-on-the-fly.zip</a> zip file, unzip the RefEdit-on-the-fly.xls Excel workbook inside it, and open the workbook. Then add a comment below, telling me the version of Excel you&#8217;re using, including Service Pack number, and if you&#8217;re using Excel 2010, whether you&#8217;re using the 32- or 64-bit version. Also mention any language pack, if you are not using English. Then tell me whether the dialog with RefEdits behaves as shown above. If the dialog fails, let me know what error messages you receive (the whole message, not just the number).
<p>Peltier Technical Services, Inc., Copyright © 2011.<br /> <br /><span style="font: 80% Verdana,Tahoma,Arial,sans-serif;">Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" rel="nofollow" rel="license" >Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License</a>.<br /> <br />
<a href="http://peltiertech.com/Utility/" rel="nofollow"  title="PTS Chart Utilities: Waterfall, Cluster-Stack Column, Box and Whisker, Marimekko"><img src="http://peltiertech.com/Utility/pix/pts_banner_map.png" alt="PTS Chart Utilities: Waterfall, Box and Whisker, Cluster-Stack, Panel, Marimekko, Dot, Panel" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://peltiertech.com/WordPress/new-refedit-approach-volunteers-wanted/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Add Series to Existing Chart</title>
		<link>http://peltiertech.com/WordPress/add-series-to-existing-chart/</link>
		<comments>http://peltiertech.com/WordPress/add-series-to-existing-chart/#comments</comments>
		<pubDate>Thu, 14 Oct 2010 12:56:40 +0000</pubDate>
		<dc:creator>Jon Peltier</dc:creator>
				<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://peltiertech.com/WordPress/?p=3239</guid>
		<description><![CDATA[The report you submitted at the end of last year was well received. Your brilliant analysis was backed up by informative charts. Your boss, his boss, and the shareholders were all very impressed. Now you have to update the chart to show year to date information, but you don&#8217;t want to generate all new charts. [...]]]></description>
			<content:encoded><![CDATA[<p>The report you submitted at the end of last year was well received. Your brilliant analysis was backed up by informative charts. Your boss, his boss, and the shareholders were all very impressed.</p>
<p>Now you have to update the chart to show year to date information, but you don&#8217;t want to generate all new charts. You also would rather not go through the hassle of copying data and pasting it into each chart, or worse, navigate the source data dialog umpteen times.</p>
<p>Here&#8217;s your old pal Jon with a time saving VBA routine to update your charts painlessly.</p>
<h2>Last Year&#8217;s Report</h2>
<p>In your acclaimed report, you compared 2008 and 2009 monthly sales. Very nice, the generally increasing trend seen in 2008 continued in 2009. Must be a fine product.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesChart1.png" alt="Chart, Units Sold by Month, 2008-2009" /></p>
<p><span id="more-3239"></span>The data for this chart is in a simple table, shown below with the source data highlighted by selecting the chart.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesData1.png" alt="Data, Units Sold by Month, 2008-2009" /></p>
<h2>The Interim Report</h2>
<p>In the intervening months, sales data for 2010 has been generated, in the next column of the table. Now we have to add this data to the chart.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesData2.png" alt="Data, Units Sold by Month, 2008-2010" /></p>
<p>All that is needed is to select the chart and run the VBA procedure below. The code starts with the series formula of the last series in the chart:</p>
<pre class="vbasmall"><code>=SERIES(Report!$C$1,Report!$A$2:$A$13,Report!$C$2:$C$13,2)</code></pre>
<p>which contains the series source data as follows:</p>
<pre class="vbasmall"><code>=SERIES(Name,X_Values,Y_Values,Plot_Order)</code></pre>
<p>The code extracts the Y_Values argument, then depending on the orientation of this data, determines the next column or row of data to use for the Y values of a new series.</p>
<p>If the name of the existing last series was taken from the worksheet, then the corresponding cell in the next column or row will provide the name for the new series; otherwise, the generic name &#8220;Series N&#8221; will be used. The new series will use the same X values as the existing last series.</p>
<p>The code adds a new series with the old X values, the new Y values and series name, and a plot order one higher than the last:</p>
<pre class="vbasmall"><code>=SERIES(Report!$D$1,Report!$A$2:$A$13,Report!$D$2:$D$13,3)</code></pre>
<p>Here is the resulting chart:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesChart2.png" alt="Chart, Units Sold by Month, 2008-2010" /></p>
<p>Awesome, monthly sales have followed the upward trend. When we select the chart, we can easily see that the source data now includes the range for the new series.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesData3.png" alt="Data, Units Sold by Month, 2008-2010" /></p>
<p>The code is listed below. It&#8217;s not too complicated, and includes a little bit of error handling in case you forgot to select a chart before running it, or in case the series formula of the last series cannot be parsed into something useful.</p>
<p>It&#8217;s common courtesy to give the user a meaningful explanation of why your code crapped out (or why they broke it):</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesHandledError.png" alt="Handled Error Message" /></p>
<p>The alternative is ugly.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-10/AddSeriesRunTimeError.png" alt="Run-Time Error Message" /></p>
<pre class="vbasmall"><code>Sub AddSeriesToEnd()
  <span style="color: #339966;">' Add series to active chart</span>
  <span style="color: #339966;">' Use same X values</span>
  <span style="color: #339966;">' Use Name and Y values one column to right of last existing series</span>
  Dim sFmla As String
  Dim iParen As Long
  Dim sFmlaArgs As String
  Dim vFmlaArgs As Variant
  Dim sMsg As String
  Dim iOffset As Long
  Dim jOffset As Long
  Dim rValues As Range
  Dim rName As Range

  If ActiveChart Is Nothing Then
    sMsg = "Select a chart, and try again."
    GoTo CantHandle
  End If

  With ActiveChart
    sFmla = .SeriesCollection(.SeriesCollection.Count).Formula
    iParen = InStr(sFmla, "(")
    sFmlaArgs = Mid$(sFmla, iParen + 1)
    sFmlaArgs = Left$(sFmlaArgs, Len(sFmlaArgs) - 1)
    vFmlaArgs = Split(sFmlaArgs, ",")

    If UBound(vFmlaArgs) + 1 - LBound(vFmlaArgs) &lt;&gt; 4 Then
      sMsg = "Series Formula too complicated to parse"
      GoTo CantHandle
    End If

    On Error Resume Next
    Set rValues = Range(vFmlaArgs(2))
    Set rName = Range(vFmlaArgs(0))
    On Error GoTo 0

    If rValues Is Nothing Then
      sMsg = "Last series values are not in a range"
      GoTo CantHandle
    End If

    If rValues.Rows.Count &gt; 1 And rValues.Columns.Count = 1 Then
      <span style="color: #339966;">' series in columns, so offset 1 column</span>
      jOffset = 1
    ElseIf rValues.Rows.Count &gt; 1 And rValues.Columns.Count = 1 Then
      <span style="color: #339966;">' series in rows, so offset 1 row</span>
      iOffset = 1
    Else
      <span style="color: #339966;">' one cell or multiple rows and columns</span>
      sMsg = "Series values range cannot be parsed"
      GoTo CantHandle
    End If

    vFmlaArgs(3) = vFmlaArgs(3) + 1
    If Not rName Is Nothing Then
      vFmlaArgs(0) = rName.Offset(iOffset, jOffset).Address(True, True, xlA1, True)
    Else
      vFmlaArgs(0) = "New Series " &amp; vFmlaArgs(3)
    End If
    vFmlaArgs(2) = rValues.Offset(iOffset, jOffset).Address(True, True, xlA1, True)

    sFmlaArgs = Join(vFmlaArgs, ",")
    sFmla = Left$(sFmla, iParen) &amp; sFmlaArgs &amp; ")"
    With .SeriesCollection.NewSeries
      .Formula = sFmla
    End With
  End With

ExitSub:
  Exit Sub

CantHandle:
  <span style="color: #339966;">' display generated error message</span>
  MsgBox sMsg, vbCritical + vbOKOnly
  GoTo ExitSub
End Sub</code></pre>
<p>If you&#8217;re not sure how to make use of this code, please read <a href="http://peltiertech.com/WordPress/how-to-use-someone-elses-macro/"title="How To: Use Someone Else's Macro" >How To Use Someone Else&#8217;s Macro</a>.</p>
<p>Peltier Technical Services, Inc., Copyright © 2011.<br /> <br /><span style="font: 80% Verdana,Tahoma,Arial,sans-serif;">Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" rel="nofollow" rel="license" >Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License</a>.<br /> <br />
<a href="http://peltiertech.com/Utility/" rel="nofollow"  title="PTS Chart Utilities: Waterfall, Cluster-Stack Column, Box and Whisker, Marimekko"><img src="http://peltiertech.com/Utility/pix/pts_banner_map.png" alt="PTS Chart Utilities: Waterfall, Box and Whisker, Cluster-Stack, Panel, Marimekko, Dot, Panel" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://peltiertech.com/WordPress/add-series-to-existing-chart/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Format All Series The Same</title>
		<link>http://peltiertech.com/WordPress/format-all-series-the-same/</link>
		<comments>http://peltiertech.com/WordPress/format-all-series-the-same/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 11:52:59 +0000</pubDate>
		<dc:creator>Jon Peltier</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[Formatting]]></category>

		<guid isPermaLink="false">http://peltiertech.com/WordPress/?p=3228</guid>
		<description><![CDATA[A quick post today to respond to a user of my Quick XY Chart Utility. This noncommercial utility generates XY charts using input data in a variety of layouts, beyond X in first column and Y in subsequent columns. The utility does not apply any particular formatting to the output charts, using the defaults it [...]]]></description>
			<content:encoded><![CDATA[<p>A quick post today to respond to a user of my <a href="http://peltiertech.com/Excel/ChartsHowTo/QuickChartUtility.html" rel="nofollow" title="Quick XY Chart Utility" >Quick XY Chart Utility</a>. This noncommercial utility generates XY charts using input data in a variety of layouts, beyond X in first column and Y in subsequent columns.</p>
<p><a href="http://peltiertech.com/Excel/ChartsHowTo/QuickChartUtility.html" rel="nofollow" title="Quick XY Chart Utility" ><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-09/QuickXYChart.png" alt="Quick XY Chart Utility Dialog" /></a></p>
<p>The utility does not apply any particular formatting to the output charts, using the defaults it finds. One user of the utility had charts with over 100 series, and he wanted them all to be formatted identically.</p>
<p><span id="more-3228"></span><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-09/AllTheSameBefore.png" alt="All XY Series Formatted Differently" /></p>
<p>In Excel 2003 and earlier, this is easy to do manually. Format the first series as desired, select the next series (use the up arrow key), press the F4 key, repeat the up arrow/F4 cycle until all series look the same. However, in Excel 2007, the F4 (Repeat Last Action) functionality has been eviscerated, particularly in charts. This is one of the productivity-sapping changes I have discussed in the past.</p>
<p>I wrote a little VBA procedure to apply the same formatting to all series in the chart. I wrote the routine in Excel 2003, but it will work fine in Excel 2007. It does not make use of the more extensive formatting capabilities introduced in Excel 2007, and that is just as well, since they do nothing to enhance the effectiveness of a chart.</p>
<pre class="vbasmall"><code>Sub FormatAllSeriesTheSame()
  Dim srs As Series

  For Each srs In ActiveChart.SeriesCollection
    srs.MarkerStyle = xlMarkerStyleNone
    With srs.Border
        .ColorIndex = 5 ' blue lines
        .Weight = xlThin
        .LineStyle = xlContinuous
    End With
  Next
End Sub</code></pre>
<p>Select the chart and run the code.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-09/AllTheSameAfter.png" alt="All XY Series Formatted The Same" /></p>
<p>We can improve on this routine, making it a better experience for the user. First, the following routine can check that there is an active chart. If not, the code exits gracefully with a reminder that the user should select a chart first. Second, to avoid the screen flashing and to speed up the reformatting, the routine deactivates <tt class="tt">ScreenUpdating</tt> while it is reformatting the chart.</p>
<pre class="vbasmall"><code>Sub FormatAllSeriesTheSame()
  Dim srs As Series

  If ActiveChart Is Nothing Then
    MsgBox "Select a chart and try again.", _
        vbExclamation + vbOKOnly, "No Active Chart"
  Else
    Application.ScreenUpdating = False
    For Each srs In ActiveChart.SeriesCollection
      srs.MarkerStyle = xlMarkerStyleNone
      With srs.Border
        .ColorIndex = 5  ' blue
        .Weight = xlThin
        .LineStyle = xlContinuous
      End With
    Next
    Application.ScreenUpdating = True
  End If
End Sub
</code></pre>
<p>If you aren&#8217;t sure how to use this code, please read my tutorial about <a href="http://peltiertech.com/WordPress/how-to-use-someone-elses-macro/"title="How To: Use Someone Else's Macro" >How To Use Someone Else&#8217;s Macro</a>.</p>
<p>Peltier Technical Services, Inc., Copyright © 2011.<br /> <br /><span style="font: 80% Verdana,Tahoma,Arial,sans-serif;">Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" rel="nofollow" rel="license" >Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License</a>.<br /> <br />
<a href="http://peltiertech.com/Utility/" rel="nofollow"  title="PTS Chart Utilities: Waterfall, Cluster-Stack Column, Box and Whisker, Marimekko"><img src="http://peltiertech.com/Utility/pix/pts_banner_map.png" alt="PTS Chart Utilities: Waterfall, Box and Whisker, Cluster-Stack, Panel, Marimekko, Dot, Panel" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://peltiertech.com/WordPress/format-all-series-the-same/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Alternative to Excel&#8217;s Flaky RefEdit Control</title>
		<link>http://peltiertech.com/WordPress/refedit-control-alternative/</link>
		<comments>http://peltiertech.com/WordPress/refedit-control-alternative/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 06:00:33 +0000</pubDate>
		<dc:creator>Jon Peltier</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[RefEdit]]></category>

		<guid isPermaLink="false">http://peltiertech.com/WordPress/?p=3195</guid>
		<description><![CDATA[I recently wrote about Using RefEdit Controls in Excel Dialogs. I use(d) them a lot, and they are a handy way on a dialog to get a range that the user wants a procedure to use. These controls are prone to incompatibility issues between versions of Excel, particularly between Classic Excel (up to 2003) and [...]]]></description>
			<content:encoded><![CDATA[<p>I recently wrote about <a href="http://peltiertech.com/WordPress/using-refedit-controls-in-excel-dialogs/"title="Using RefEdit Controls in Excel Dialogs" >Using RefEdit Controls in Excel Dialogs</a>. I use(d) them a lot, and they are a handy way on a dialog to get a range that the user wants a procedure to use.</p>
<p>These controls are prone to incompatibility issues between versions of Excel, particularly between Classic Excel (up to 2003) and new Excel (2007 and later), and whenever there&#8217;s a new security update from Office update, these problems seem to arise again. I’ve written about this and related problems in <a href="http://peltiertech.com/WordPress/unspecified-painfully-frustrating-error/"title="Unspecified but Painfully Frustrating Error" >Unspecified but Painfully Frustrating Error</a>. This error has led to an inordinate amount of customer support to update customer installations and correct the errors.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Unspecified Error" src="http://peltiertech.com/images/2009-06/unspecifiederror.png" alt="System Error &amp;H80004005 (-2147467259). Unspecified error" /></p>
<p><span id="more-3195"></span>To improve the user experience of my customers, and to cut down on customer support incidents, I’ve replaced the RefEdit controls in all of my commercial utilities with an alternative method, as I&#8217;ve discussed in <a href="http://peltiertech.com/WordPress/excel-chart-utility-upgrades/"title="Charting Utility Upgrades » Peltier Tech Blog" >Charting Utility Upgrades</a>. This article describes the replacement for the RefEdit functionality.</p>
<h2>RefEdit</h2>
<p>A typical dialog using a RefEdit looks like this:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Dialog with RefEdit" src="http://peltiertech.com/images/2010-04/RefEditDialog.png" alt="Dialog with RefEdit" /></p>
<p>Clicking in the RefEdit highlights the indicated range. The user can edit the text within the RefEdit, and the highlighted range updates.</p>
<p>Clicking in the RefEdit&#8217;s drop box, or selecting a range in the sheet contracts the dialog so that only the refEdit is visible, and the indicated range updates as the user changes the selection.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Dialog with RefEdit, Contracted" src="http://peltiertech.com/images/2010-04/RefEditInputBox.png" alt="Dialog with RefEdit, Contracted" /></p>
<h2>TextBox and Inputbox</h2>
<p>The new approach uses a TextBox in the dialog instead of the RefEdit, which at first doesn&#8217;t look like it&#8217;s going to work:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Dialog with TextBox" src="http://peltiertech.com/images/2010-04/TextBoxDialog.png" alt="Dialog with TextBox" /></p>
<p>We can use a couple invisible properties of a TextBox to provide a drop button like that in the RefEdit, so it looks exactly the same in the dialog. I call the properties &#8220;hidden&#8221; because they do not appear in the TextBox property window in the VB Editor, though they appear for example in the ComboBox property window. Fortunately you can type the properties and they work. One hidden property is <tt class="tt">TextBox.DropButtonStyle</tt> which sets the style of the drop button (see below); we use the &#8220;Reduce&#8221; style to match the RefEdit. The other property is <tt class="tt">TextBox.ShowDropButtonWhen</tt> which controls the visibility of the drop button, and we write code that always shows the drop button.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Drop Button Styles" src="http://peltiertech.com/images/2010-04/DropButtonStyles.png" alt="Drop Button Styles" /></p>
<p>The TextBox does not interact directly with a range as does the RefEdit. Instead, when this drop button is clicked, the dialog is temporarily hidden, and an InputBox appears to solicit the user&#8217;s input.</p>
<p>The InputBox control is familiar to Excel VBA programmers who use it to ask the user to enter a number or some text. The syntax of the InputBox is:</p>
<pre class="vbasmall"><code>Application.InputBox(Prompt, Title, Default, Left, Top, HelpFile, HelpContextId, Type)</code></pre>
<p><tt class="tt">Prompt</tt> is the text that instructs the user, <tt class="tt">Title</tt> is the text in the title bar of the dialog, <tt class="tt">Default</tt> is the value in the input box when the InputBox opens. <tt class="tt">Left</tt> and <tt class="tt">Top</tt> define the position of the InputBox (if unspecified it appears in the center of the window). <tt class="tt">HelpFile</tt> and <tt class="tt">HelpContextId</tt> are used with custom help topics. Finally, <tt class="tt">Type</tt> is used to define the expected type of input:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="InputBox input types" src="http://peltiertech.com/images/2010-04/InputBoxType.png" alt="InputBox input types" /></p>
<p>It may be tempting to use type 8 to indicate a range object, but there is an obscure glitch that causes it to fail when the worksheet contains conditional formatting conditions that use formulas in their definitions. Fortunately using Type 0 to specify a formula works just fine.<br class="spacer_" /></p>
<p>The dialog with the drop-button-enabled TextBox looks like this:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Dialog with TextBox and Drop Button" src="http://peltiertech.com/images/2010-04/AltRefEditDialog.png" alt="Dialog with TextBox Drop Button" /></p>
<p>By itself the drop button has no function, but we can write code to respond to the user clicking on it. We have the dialog hide itself and show the following InputBox:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="InputBox for Range Selection" src="http://peltiertech.com/images/2010-04/AltRefEditInputBox.png" alt="InputBox for Range Selection" /></p>
<p>The InputBox is larger than the compact dialog that shows only the active RefEdit, but that&#8217;s a minor cosmetic difference. The largest drawback of this approach is that it doesn&#8217;t show the highlighted range when the user is editing the text in the TextBox. The advantage of course is the avoidance of incompatibilities between RefEdit and the user&#8217;s MS Office environment.</p>
<h2>The Code</h2>
<p>The following procedure, in a regular code module, determines the address of the selected range, loads the dialog, passes the range address to the dialog, and waits for the user to finish. If the user does not cancel the dialog, then the procedure selects the new range.</p>
<pre class="smallvba"><code>Sub ShowDialog()
  Dim frmAlternativeRefEdit As FAlternativeRefEdit
  Dim rRange As Range
  Dim sRange As String
  Dim bCanceled As Boolean

  If ActiveSheet Is Nothing Then Exit Sub

  If TypeName(Selection) = "Range" Then
    Set rRange = Selection.Areas(1)
    sRange = Selection.Parent.Name
    If InStr(rRange.Address(, , , True), "'") &gt; 0 Then
      sRange = "'" &amp; sRange &amp; "'"
    End If
    sRange = sRange &amp; "!"
    sRange = sRange &amp; rRange.Address
  End If

  Set frmAlternativeRefEdit = New FAlternativeRefEdit
  With frmAlternativeRefEdit

    .Address = sRange
    .Show

    <span style="color: #008000;">' wait for user input
</span>
    bCanceled = .Cancel
    If Not bCanceled Then
      sRange = .Address
    End If
  End With

  Unload frmAlternativeRefEdit
  Set frmAlternativeRefEdit = Nothing

  If bCanceled Then GoTo ExitSub

  If IsRange(sRange) Then
    Application.Goto Range(sRange)
  End If

ExitSub:

End Sub</code></pre>
<p>The UserForm (dialog) is named FAlternativeRefEdit. The following code all goes into the code module behind the UserForm.</p>
<p>At the top of the code module we need:</p>
<pre class="smallvba"><code>Option Explicit
Private mbCancel As Boolean</code></pre>
<p>When the dialog is initialized, the drop button style and visibility are set:</p>
<pre class="smallvba"><code>Private Sub UserForm_Initialize()
  Me.txtRefChtData.DropButtonStyle = fmDropButtonStyleReduce
  Me.txtRefChtData.ShowDropButtonWhen = fmShowDropButtonWhenAlways
End Sub</code></pre>
<p>We include this snippet to make sure closing the dialog using the big red X is the same as pressing the Cancel button:</p>
<pre class="smallvba"><code>Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
  If CloseMode = vbFormControlMenu Then
    Cancel = True
    btnCancel_Click
  End If
End Sub</code></pre>
<p>The Cancel and OK buttons run the following code:</p>
<pre class="smallvba"><code>Private Sub btnCancel_Click()
  mbCancel = True
  Me.Hide
End Sub

Private Sub btnOK_Click()
  mbCancel = False
  Me.Hide
End Sub</code></pre>
<p>The dialog gets the address from the calling procedure and passes back the new address using these properties:</p>
<pre class="smallvba"><code>Public Property Let Address(sAddress As String)
  CheckAddress sAddress
End Property

Public Property Get Address() As String
  Dim sAddress As String

  sAddress = Me.txtRefChtData.Text
  If IsRange(sAddress) Then
    Address = sAddress
  Else
    sAddress = Application.ConvertFormula(sAddress, xlR1C1, xlA1)
    If IsRange(sAddress) Then
      Address = sAddress
    End If
  End If

End Property

Public Property Get Cancel() As Boolean
  Cancel = mbCancel
End Property</code></pre>
<p>When the user clicks the DropButton on the TextBox, this code runs:</p>
<pre class="smallvba"><code>Private Sub txtRefChtData_DropButtonClick()
  Dim var As Variant
  Dim rng As Range
  Dim sFullAddress As String
  Dim sAddress As String

  Me.Hide

  On Error Resume Next
  var = Application.InputBox("Select the range containing your data", _
      "Select Chart Data", Me.txtRefChtData.Text, Me.Left + 2, _
       Me.Top - 86, , , 0)
  On Error GoTo 0

  If TypeName(var) = "String" Then
    CheckAddress CStr(var)
  End If

  Me.Show
End Sub</code></pre>
<p><tt class="tt">Me.Left + 2</tt> and <tt class="tt">Me.Top - 86</tt> are empirically derived positioning values that align the InputBox to the dialog that called it. They were not rigorously determined and may not work the same for all settings in all versions of Windows.</p>
<p>Finally, this procedure parses the address in the InputBox, making sure the format (<tt class="tt">xlA1</tt> or <tt class="tt">xlR1C1</tt>) is appropriate, and also ensuring that the user can select a range on a different worksheet. I&#8217;ve incorporated the suggestion made by Julien in the comments, who found that my original <tt class="tt">CheckAddress</tt> routine gave the wrong address if an entire column or row was selected.</p>
<pre class="smallvba"><code>Private Sub CheckAddress(sAddress As String)
  Dim rng As Range
  Dim sFullAddress As String

  If Left$(sAddress, 1) = "=" Then sAddress = Mid$(sAddress, 2, 256)
  If Left$(sAddress, 1) = Chr(34) Then sAddress = Mid$(sAddress, 2, 255)
  If Right$(sAddress, 1) = Chr(34) Then sAddress = Left$(sAddress, Len(sAddress) - 1)

  On Error Resume Next
  sAddress = Application.ConvertFormula(sAddress, xlR1C1, xlA1)

  If IsRange(sAddress) Then
    Set rng = Range(sAddress)
  End If

  If Not rng Is Nothing Then
    sFullAddress = rng.Address(, , Application.ReferenceStyle, True)
    If Left$(sFullAddress, 1) = "'" Then
      sAddress = "'"
    Else
      sAddress = ""
    End If
    sAddress = sAddress &amp; Mid$(sFullAddress, InStr(sFullAddress, "]") + 1)

    rng.Parent.Activate

    Me.txtRefChtData.Text = sAddress
  End If

End Sub</code></pre>
<h2>Sample Workbook</h2>
<p><a href="http://peltiertech.com/images/2010-04/RefEdit_Alternative.zip" rel="nofollow" title="RefEdit Alternative Workbook" >RefEdit_Alternative.zip</a> is a zipped workbook that contains the dialog and code featured in this post. Click on the button on the first worksheet to see it in action.</p>
<h2>Summary</h2>
<p>Using a TextBox and InputBox is an effective replacement for Excel&#8217;s RefEdit control.It may not be quite as elegant as the RefEdit, when the RefEdit is working. However, the TextBox/InputBox combination does not suffer from incompatibilities between different systems and Excel versions. Since I have converted my professional utilities to this alternative system, my customer support incidents have been reduced by 90%.</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 5854px; width: 1px; height: 1px; overflow: hidden;">On Error Resume Next</div>
<p>Peltier Technical Services, Inc., Copyright © 2011.<br /> <br /><span style="font: 80% Verdana,Tahoma,Arial,sans-serif;">Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" rel="nofollow" rel="license" >Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License</a>.<br /> <br />
<a href="http://peltiertech.com/Utility/" rel="nofollow"  title="PTS Chart Utilities: Waterfall, Cluster-Stack Column, Box and Whisker, Marimekko"><img src="http://peltiertech.com/Utility/pix/pts_banner_map.png" alt="PTS Chart Utilities: Waterfall, Box and Whisker, Cluster-Stack, Panel, Marimekko, Dot, Panel" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://peltiertech.com/WordPress/refedit-control-alternative/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Build an Excel Add-In 6 – Interface for 2003</title>
		<link>http://peltiertech.com/WordPress/build-an-excel-add-in-6-%e2%80%93-interface-for-2003/</link>
		<comments>http://peltiertech.com/WordPress/build-an-excel-add-in-6-%e2%80%93-interface-for-2003/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 07:00:01 +0000</pubDate>
		<dc:creator>Jon Peltier</dc:creator>
				<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://peltiertech.com/WordPress/?p=3175</guid>
		<description><![CDATA[This is the sixth of nine installments in the Build an Excel Add-In series. In previous installments, we wrote some code to perform a useful task, enhanced its functionality to make it more broadly applicable, modularized the code and included an auxiliary modular procedure, built a dialog to ask the user for preferences, and brought [...]]]></description>
			<content:encoded><![CDATA[<p>This is the sixth of nine installments in the <strong>Build an Excel Add-In</strong> series. In previous installments, we wrote some code to perform a useful task, enhanced its functionality to make it more broadly applicable, modularized the code and included an auxiliary modular procedure, built a dialog to ask the user for preferences, and brought all the code together. What remains is to construct the user interface elements for Classic Excel (2003 and earlier) and for new Excel (2007 and later), tie up a few loose ends, and create a setup file for easy deployment. A linked outline can be found at the end of this article.</p>
<h2>Microsoft Office User Interfaces</h2>
<p>Microsoft introduced a flexible and powerful user interface system in Office 97, and this interface has remained in use through Office 2003 (and a subset remains in use in later versions). The user interface consists of various command bars, which include menu bars and toolbars. Command bars can contain menus as well as buttons. Menus can contain submenus and buttons. Submenus can contain, well, you get the idea. This system of menus, toolbars, and buttons is easily customized through the user interface and via VBA.</p>
<p>Here is what our add-in&#8217;s menu customizations look like. This article shows how to create these customizations.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-03/PTPlot_2003Menu.png" alt="Excel macros dialog" /></p>
<p><span id="more-3175"></span>The Microsoft Office development team at Microsoft noticed some things about the command-bar-style interface, and about how users interacted with it. The interface was becoming complicated, with three or more levels of menus and submenus existing in some places. Each application ended up with its Tools menu, a kitchen junk drawer of commands that didn&#8217;t logically fit into the other menus. Users didn&#8217;t know what all the features were, or couldn&#8217;t find them, if they were buried more than a level deep, so they kept suggesting new features which already existed. Many users also didn&#8217;t know how to clean up their interfaces, so there were too many rows of docked toolbars and too many floating toolbars obstructing the workspace.</p>
<p>In response to the complicated nature of the command-bar-based interface and to the inability of some users to learn to use it as intended, the Microsoft Office team gutted the interface, replacing most toolbar implementations in favor of a new Ribbon in Office 2007. The ribbon is controlled using XML instead of VBA. Instead of toolbars which are visible all or most of the time, the ribbon has a set of different tabs. These tabs contain fewer buttons, and the buttons used more tend to be larger. The tabs become visible when the Office program thinks you might want to use them, and invisible when you actually do want to use them. No parts of the new interface can be undocked, so users who didn&#8217;t know how to click the close box of a floating toolbar now have clean interfaces, while users who like dispatching toolbars and palettes to areas on the screen where they are needed have to resort to extra mouse travel distances and excess mouse clicks. The ribbon-based interface is easy to customize using the RibbonX XML dialect and related VBA callbacks, but it is practically inaccessable through the user interface. Unless, of course, you count the QAT (Quick Access Toolbar), which is like a Classic toolbar on strong sedatives. Fortunately the ability of a user to customize their own interface was resuscitated for use in Office 2010.</p>
<p>This article will show how to construct a simple set of Classic Excel menu and toolbar  customizations using VBA. The next article in the sequence will show simple XML code and VBA callbacks for use in New Excel.</p>
<h2>Classic Excel User Interface Code</h2>
<p>The object model for the Office command bar system is straightforward. The CommandBars collection contains menu bars, standard toolbars, and popup menus (context or right-click menus). There is a lot of documentation of this system on the internet. This article shows a set of simple, hard-coded routines, all that is necessary for this simple add-in. There are a number of examples of more elaborate and flexible routines that use tables in Excel workbooks to define all of the interface elements to be created. John Walkenbach describes <a href="http://spreadsheetpage.com/index.php/tip/creating_custom_menus/" rel="nofollow" title="Spreadsheet Page Excel Tips: Creating Custom Menus" >Creating Custom Menus</a> using his <strong>MenuMakr</strong> system. I started with his system, but like any good engineer, I tweaked it beyond all recognition to create the system I use in my own add-ins and in projects for my clients.</p>
<p>Here is the simple code in its entirety, copied out of its code module. Explanations for selected sections of the code follow the complete listing.</p>
<pre class="vbasmall"><code><span style="color: #339966;">''========================================================================
'' Peltier Technical Services, Inc., Copyright © 2010. All rights reserved.
''========================================================================
</span>Option Explicit

Const sMenuName As String = "&amp;PTS Charts"
Const sToolbars As String = "Worksheet Menu Bar|Chart Menu Bar|PTS Charts"
Const sButton As String = "PT_Plotter"
Const sOnAction As String = "PT_Plotter_Dialog"

Sub Create_PTPlotter_Menu()
  Dim ctlpop As CommandBarPopup
  Dim ctlbtn As CommandBarButton
  Dim iMenu As Long
  Dim vMenu As Variant

  Delete_PTPlotter_Menu

  vMenu = Split(sToolbars, "|")

  For iMenu = LBound(vMenu) To UBound(vMenu)
    On Error Resume Next
    If Application.CommandBars(vMenu(iMenu)) Is Nothing Then
      With Application.CommandBars.Add(vMenu(iMenu), msoBarFloating)
        .Left = Application.Left + Application.Width / 4
        .Top = Application.Top + 144
        .Visible = True
      End With
    End If
    On Error GoTo 0

    With Application.CommandBars(vMenu(iMenu))
      On Error Resume Next
      If .Type = msoBarTypeMenuBar Then
        Set ctlpop = .Controls(sMenuName)
        On Error GoTo 0
        If ctlpop Is Nothing Then
          Set ctlpop = .Controls.Add(10, 1, , , True)
          With ctlpop
            .Caption = sMenuName
            .Visible = True
          End With
        End If
        Set ctlbtn = ctlpop.Controls.Add(1, 1, , , True)
      Else
        Set ctlbtn = .Controls.Add(1, 1, , , True)
        .Visible = True
      End If

      With ctlbtn
        .Caption = sButton
        .OnAction = "'" &amp; ThisWorkbook.Name &amp; "'!" &amp; sOnAction
        .TooltipText = "Create chart from arbitrary data range"
        .FaceId = 422
        .Visible = True
      End With
      Set ctlpop = Nothing
    End With
  Next
End Sub

Sub Delete_PTPlotter_Menu()
  Dim ctlpop As CommandBarPopup
  Dim ctlbtn As CommandBarControl
  Dim iMenu As Long
  Dim vMenu As Variant

  On Error Resume Next
  vMenu = Split(sToolbars, "|")

  For iMenu = LBound(vMenu) To UBound(vMenu)
    With Application.CommandBars(vMenu(iMenu))
      If .Type = msoBarTypeMenuBar Then
        Set ctlpop = .Controls(sMenuName)
        Do
          Set ctlbtn = ctlpop.Controls(sButton)
          If ctlbtn Is Nothing Then Exit Do
          ctlbtn.Delete
          Set ctlbtn = Nothing
        Loop

        If ctlpop.Controls.Count = 0 Then
          ctlpop.Delete
        End If
      Else
        Do
          Set ctlbtn = .Controls(sButton)
          If ctlbtn Is Nothing Then Exit Do
          ctlbtn.Delete
          Set ctlbtn = Nothing
        Loop

        If .Controls.Count = 0 Then
          .Delete
        End If

      End If
    End With
  Next
</code></pre>
<h1><code>End Sub</code></h1>
<h2>Explanations</h2>
<p>The module starts by defining a few constants. The menu name <tt class="tt">sMenuName</tt>, &#8220;&amp;PTS Charts&#8221; has an ampersand that tells Excel to use the next character (P) as an accelerator key, that is, to activate the menu when Alt plus the next character is pressed (Alt+P). This character will appear underlined in the menu name: <span style="text-decoration: underline;">&#8220;P</span>TS Charts&#8221;.</p>
<p><tt class="tt">sToolBars</tt> is a pipe-delimited string of command bars which will be customized. The remaining constants list the button caption and the name of the procedure to be run when the button is clicked.</p>
<p><tt class="tt">Create_PTPlotter_Menu</tt> is the routine that adds our buttons to the Classic Excel interface. The first command in this routine is <tt class="tt">Delete_PTPlotter_Menu</tt>, which removes any existing buttons from this add-in which have somehow been orphaned due to a disorderly shutdown.</p>
<p>The pipe-delimited string is converted into an array of command bar names. The program loops through this array, looking for command bars with each name. If such a command bar is not found, then a new standard command bar is created using that name, other wise the program continues with the found command bar.</p>
<p>If the command bar is a menu bar, the program looks for a menu with the indicated name. If such a menu is not found on the command bar, a new menu is created, otherwise the existing menu is used. Then the button is placed on the menu. If the command bar is a regular toolbar, the button is placed directly on the toolbar.</p>
<p>The caption of the button is assigned, as is the name of the procedure to run when the button is clicked. The procedure name is prepended with the workbook name in single quotes, so Excel will not confuse our procedure with a procedure with the same name in another workbook.</p>
<p>The button is assigned its tooltip text, which appears when the cursor passes over the button.</p>
<p>Built-in button image number 422 is used for the button&#8217;s icon. <a href="http://peltiertech.com/Excel/Zips/ShowFace.zip" rel="nofollow" title="Display FaceIDs" >Display FaceIDs</a> is a simple utility that helps you browse Excel&#8217;s button images. Not described here is the means to assign a custom button image.</p>
<p>Finally the button is made visible, so users can find it.</p>
<p><tt class="tt">Delete_PTPlotter_Menu</tt> goes through the command bars listed in the pipe-delimited string, looking for buttons with the name used by our add-in. This is done inside Do loops, in case multiple crashes left behind multiple identical buttons. If the last button of a menu or toolbar is deleted, the empty menu or toolbar is also deleted.</p>
<h2>Our Menu and Toolbar</h2>
<p>The menu and toolbar customizations produced by the code above are displayed below.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-03/PTPlot_2003Menu.png" alt="Excel macros dialog" /></p>
<p>The menu is on the Worksheet Menu Bar; the menu on the Chart menu Bar is the same. The PTS Charts menu and the PTS Charts toolbar already existed, with a variety of my utilities displayed, and the PT_Plotter button is added at the end of the list.</p>
<h2>Contents: How to Build an Excel Add-In</h2>
<ul style="margin-left: 24pt;">
<li><a href="http://peltiertech.com/WordPress/build-an-excel-add-in-1-basic-routine/"title="Build an Excel Add-In 1 – Basic Routine" >Build an Excel Add-In 1 – Basic Routine</a></li>
<li><a href="http://peltiertech.com/WordPress/build-an-excel-add-in-2-enhanced-functionality/"title="Build an Excel Add-In 2 – Enhanced Functionality" >Build an Excel Add-In 2 – Enhanced Functionality</a></li>
<li><a href="http://peltiertech.com/WordPress/build-an-excel-add-in-3-auxiliary-modular-functions/"title="Build an Excel Add-In 3 - Auxiliary Modular Functions" >Build an Excel Add-In 3 – Auxiliary Modular Functions</a></li>
<li><a href="http://peltiertech.com/WordPress/build-an-excel-add-in-4-create-the-dialog/"title="Build an Excel Add-In 4 – Create the Dialog" >Build an Excel Add-In 4 – Create the Dialog</a></li>
<li><a href="http://peltiertech.com/WordPress/build-an-excel-add-in-5-tie-it-all-together/"title="Build an Excel Add-In 5 – Tie the Code Together" >Build an Excel Add-In 5 – Tie the Code Together</a></li>
<li><strong>Build an Excel Add-In 6 – Interface for 2003</strong></li>
<li>Build an Excel Add-In 7 – Interface for 2007</li>
<li>Build an Excel Add-In 8 – Last Steps</li>
<li>Build an Excel Add-In 9 – Deployment</li>
</ul>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 2363px; width: 1px; height: 1px; overflow: hidden;">
<pre class="vbasmall"><code>Create_LblLastPt_Menu</code></pre>
</div>
<p>Peltier Technical Services, Inc., Copyright © 2011.<br /> <br /><span style="font: 80% Verdana,Tahoma,Arial,sans-serif;">Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" rel="nofollow" rel="license" >Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License</a>.<br /> <br />
<a href="http://peltiertech.com/Utility/" rel="nofollow"  title="PTS Chart Utilities: Waterfall, Cluster-Stack Column, Box and Whisker, Marimekko"><img src="http://peltiertech.com/Utility/pix/pts_banner_map.png" alt="PTS Chart Utilities: Waterfall, Box and Whisker, Cluster-Stack, Panel, Marimekko, Dot, Panel" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://peltiertech.com/WordPress/build-an-excel-add-in-6-%e2%80%93-interface-for-2003/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Recorded Macro Error with Bubble and Stock Charts</title>
		<link>http://peltiertech.com/WordPress/recorded-macro-error-with-bubble-and-stock-charts/</link>
		<comments>http://peltiertech.com/WordPress/recorded-macro-error-with-bubble-and-stock-charts/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 06:00:34 +0000</pubDate>
		<dc:creator>Jon Peltier</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[VBA Errors]]></category>

		<guid isPermaLink="false">http://peltiertech.com/WordPress/?p=3018</guid>
		<description><![CDATA[You have a chart that you make every week or every month, and you&#8217;re tired of making it from scratch every time. So you record a macro to automate the process. When you run the macro to make your chart the next time, you get no chart. Instead you get an ugly error message. That&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>You have a chart that you make every week or every month, and you&#8217;re tired of making it from scratch every time. So you record a macro to automate the process.</p>
<p>When you run the macro to make your chart the next time, you get no chart. Instead you get an ugly error message.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://peltiertech.com/images/2010-01/VBA_Error.png" alt="Chart Type VBA Error" /></p>
<p><span id="more-3018"></span>That&#8217;s frustrating. All you did was record and rerun a macro. You didn&#8217;t even change the code, so at least this once, you <em>couldn&#8217;t</em> have messed it up. And still it crashed.</p>
<p>Let&#8217;s examine the macro recorder code.</p>
<pre class="vbasmall"><code>Sub RecordedMacro_MakeBubbleChart()
<span style="color: #339966;">'
' RecordedMacro_MakeBubbleChart Macro
' Macro recorded 1/26/2010 by Jon Peltier
'

'
</span>    Charts.Add
    <span style="color: #0000ff;">ActiveChart.ChartType = xlBubble</span>
    <span style="color: #ff6600;">ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("A1:C7"), _
        PlotBy:=xlColumns</span>
    ActiveChart.Location Where:=xlLocationAsObject, Name:="Sheet1"
End Sub
</code></pre>
<p>The macro recorder follow the order of the Excel 2003 chart wizard, putting the chart type before the chart source data. The steps given by the recorder work fine for most chart types, but a few chart types cannot be correctly assigned until the chart has been populated with sufficient data. In particular, code which creates <strong>stock charts</strong> and <strong>bubble charts</strong> will fail if you set the chart type before the chart is populated with data.</p>
<p>To make the code run properly without crashing, all you need to do is switch the <tt class="tt" style="color: #ff6600;">SetSourceData</tt> and <tt class="tt" style="color: #0000ff;">ChartType</tt> commands. The following code works fine.</p>
<pre class="vbasmall"><code>Sub RecordedMacro_MakeBubbleChart()
<span style="color: #339966;">'
' RecordedMacro_MakeBubbleChart Macro
' Macro recorded 1/26/2010 by Jon Peltier
'

'
</span>    Charts.Add
    <span style="color: #ff6600;">ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("A1:C7"), _
        PlotBy:=xlColumns</span>
    <span style="color: #0000ff;">ActiveChart.ChartType = xlBubble</span>
    ActiveChart.Location Where:=xlLocationAsObject, Name:="Sheet1"
End Sub
</code></pre>
<p>This code isn&#8217;t particularly efficient, but at least it works. You can improve it following the suggestions in <a href="http://peltiertech.com/WordPress/how-to-fix-a-recorded-macro/"title="How To: Fix a Recorded Macro" >How To Fix a Recorded Macro</a>.</p>
<p>This error has existed in Excel from the first modern version (Excel 97) through Excel 2003. Microsoft must have received inquiries about the problem, and they addressed it with a KB article, <a href="http://support.microsoft.com/kb/139662" rel="nofollow" title="How to Use a Visual Basic Macro to Create a Bubble Chart" >How to Use a Visual Basic Macro to Create a Bubble Chart</a>., which propagated through versions 5/95, 97, 2000, 2002, and 2003. The author of the article didn&#8217;t think to rearrange the two VBA commands, so he wrote a long procedure that made an XY chart, and for markers, the chart used custom AutoShape circles sized according to the bubble values. It&#8217;s a nice procedure and a nice technique to know, but also a long voyage to go such a short distance.</p>
<p>When Microsoft rebuilt the charting infrastructure for Excel 2007, they changed some of the code produced by the macro recorder. Here is the Excel 2007 bubble chart macro:</p>
<pre class="vbasmall"><code>Sub RecordedMacro_MakeBubbleChart()
<span style="color: #339966;">'
' RecordedMacro_MakeBubbleChart Macro
' Macro recorded 1/26/2010 by Jon Peltier
'

'</span>
  ActiveSheet.Shapes.AddChart.Select
  ActiveChart.SetSourceData Source:=Range("'Sheet1'!$A$1:$C$5")
  ActiveChart.ChartType = xlBubble
End Sub
</code></pre>
<p>Excel 2007&#8242;s macro recorder has been criticized because it didn&#8217;t capture any actions that affected the new shapes which comprise the chart. But in the simple macro above, we see that some improvements were made to Excel 2007&#8242;s macro recorder:</p>
<ul style="margin-left: 24px;">
<li>In earlier versions of Excel, a separate chart sheet is made, then later inserted in the worksheet. In 2007, a chart is directly added to the worksheet&#8217;s Shapes collection. That&#8217;s more efficient.</li>
<li>More important, the chart type is not set until after the chart is populated with data. The error in recorded macros no longer occurs.</li>
</ul>
<p>Peltier Technical Services, Inc., Copyright © 2011.<br /> <br /><span style="font: 80% Verdana,Tahoma,Arial,sans-serif;">Licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" rel="nofollow" rel="license" >Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License</a>.<br /> <br />
<a href="http://peltiertech.com/Utility/" rel="nofollow"  title="PTS Chart Utilities: Waterfall, Cluster-Stack Column, Box and Whisker, Marimekko"><img src="http://peltiertech.com/Utility/pix/pts_banner_map.png" alt="PTS Chart Utilities: Waterfall, Box and Whisker, Cluster-Stack, Panel, Marimekko, Dot, Panel" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://peltiertech.com/WordPress/recorded-macro-error-with-bubble-and-stock-charts/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

