<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>VB</title>
        <link>http://nimblecoder.com/blog/category/3.aspx</link>
        <description>VB</description>
        <language>en-US</language>
        <copyright>Ryan Van Slooten</copyright>
        <generator>Subtext Version 2.1.1.1</generator>
        <item>
            <title>Macro Guidelines for Excel VBA Beginners</title>
            <link>http://nimblecoder.com/blog/archive/2008/05/27/macro-guidelines-for-excel-vba-beginners.aspx</link>
            <description>  &lt;p&gt;     I'm in the process of updating an Excel spreadsheet that is failing when it is running     inside of Internet Explorer. The issue is related to the ActiveSheet and other global     properties having a value of Nothing when the code is assuming they have valid references.     As I am going through this spreadsheet, I am noting a wide variety of programming     deficiencies and inefficiencies. Here is a list of some of the issues encountered:&lt;/p&gt;   &lt;blockquote&gt;     If you run spreadsheets under Internet Explorer, use     &lt;span style="font-weight:bold;"&gt;Application.ThisWorkbook&lt;/span&gt; and to ensure the browser     evaluates the reference correctly.&lt;/blockquote&gt;   &lt;blockquote&gt;     NOTE: This is not an exhaustive list, nor do I claim that the "Better" examples     are the best code example, but rather they are (hopefully) significant improvements     over the "Bad" examples. In many cases, I have kept the design of the bad example     so that you can see the differences however you should strive to completely refactor     the code if possible.&lt;/blockquote&gt;   &lt;ol&gt;     &lt;li&gt;       &lt;h3&gt;         Do not abuse the "With" statement in VBA.&lt;/h3&gt;       Some people like "With" and some people don't and I don't particularly care for       it. In particular, do not use nested "With" statements.       &lt;h4&gt;         Example of Bad Code&lt;/h4&gt;       &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
With ActiveSheet
  With TestForm
    ' ...
  End With ' TestForm
End With ' ActiveSheet
' ... BAD EXAMPLE: DO NOT USE ...

&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using the "Goto" statement in VBA.&lt;/h3&gt;
      "Goto" is almost always a bad idea and a sign of spaghetti code. There are very few cases were it is appropriate to use it -- very few cases!
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
For i = iHere To lRealLastRow Step 2
  BuildStr = "A" &amp;amp; i + 1
  Range(BuildStr).Select
  If Range(BuildStr).Value = "---" Then GoTo DoneWithNames
  SelectItemDlg.Items_List.AddItem Range(BuildStr).Text
Next

DoneWithNames:
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code (I still would have designed it differently)&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
Dim MyCell As Range
For i = iHere To lRealLastRow Step 2
  Set MyCell = Cells(i + 1, 1)
  If MyCell.Value = "---" Then
    Exit For
  End If
  SelectItemDlg.Items_List.AddItem MyCell.Text
Next
' ...
&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using the name of a Form inside the Form code&lt;/h3&gt;
      The current form is implied in the code. It is not necessary to use the form name to reference controls on the form. If you want to differeniate form controls, you can use the 'Me' keyword such as: Me.Hide
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
' This example is doubly bad because it uses the form name (ChartConfig)
' both explicitly and in a With statement
If ChartConfig.Variable1.Text = ChartConfig.Variable2.Text Then
    MsgBox "Variable1 cannot be same as Variable2. Please choose another variable type.", vbOKCancel

    'Turn off the Change effect on Variable2.
    changeCasevar = False
    With ChartConfig
        .Variable2.Text = ""
        .Variable2Desc.Text = ""
        .Variable2Uom.Text = ""
    End With
    'Turn back on the Change effect on Variable2.
    changeCasevar = True
    Exit Sub
    '
End If

' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code (I still would have designed it differently)&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
If Variable1.Text = Variable2.Text Then
    MsgBox "Variable1 cannot be same as Variable2. Please choose another variable type.", vbOKCancel

    'Turn off the Change effect on Variable2.
    changeCasevar = False

    Variable2.Text = ""
    Variable2Desc.Text = ""
    Variable2Uom.Text = ""

    'Turn back on the Change effect on Variable2.
    changeCasevar = True
    Exit Sub
End If

&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Use Error Handling and Resume to restore Application.ScreenUpdating&lt;/h3&gt;
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
' There are quite a few global variables and a pass-by-reference
' boolean that should just be the function return value.
Application.ScreenUpdating = False

iOption = "Single"
x = ChartPicker.Input_Val_Text
Call CheckUserRangeInputsAndOutputs(iOption, OkToChart)
iOption = ""

If OkToChart = True Then
    With ChartConfig
        CreateChartingArrays
    End With
End If

Application.ScreenUpdating = True
' ... BAD EXAMPLE: DO NOT USE ...
  &lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code (I still would have designed it differently)&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
  On Error GoTo ErrorHandler

  Application.ScreenUpdating = False

  If CheckUserRangeInputsAndOutputs("Single") Then
    ChartConfig.CreateChartingArrays
  End If

Exit_Handler:
  Application.ScreenUpdating = True
  Exit Sub

ErrorHandler:
  MsgBox "Error " &amp;amp; Err.Number &amp;amp; ": " &amp;amp; Err.Description
  Resume Exit_Handler

  &lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Use If, Else If, and Else correctly.&lt;/h3&gt;
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
If TextBoxMinimum.Text = "" Then
  MsgBox "Must enter Minimum Value before proceeding", vbOK
  Result = False
  Exit Function
End If

If TextBoxMaximum.Text = "" Then
  MsgBox "Must enter Maximum Value before proceeding", vbOK
  Result = False
  Exit Function
End If
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
' For a explicit method, you can directly refer to the controls
Result = False
If Not IsNumeric(TextBoxMinimum.Text) Then
  MsgBox "Must enter Minimum Value before proceeding", vbOK
  TextBoxMinimum.SetFocus
ElseIf Not IsNumeric(TextBoxMaximum.Text) Then
  MsgBox "Must enter Maximum Value before proceeding", vbOK
  TextBoxMaximum.SetFocus
Else
  Result = True
End If

' If you can use a generic method, you can iterate through all of the controls
' There are obviously better ways of doing this, especially with .NET
Dim ValidateControl
Dim ControlList = Array(TextBox1, TextBox2, TextBox3)
For Each ValidateControl In ControlList
  If Input_Val_Text = Null Or Input_Val_Text = "" Then
    MsgBox "Must enter Value in " &amp;amp; ValidateControl.Name &amp;amp; " before proceeding", vbOK
    Result = False
    Exit Function
  End If
Next
&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using the ActiveSheet, Range, Cells, and other global variables.&lt;/h3&gt;
      Rather than assuming a position, it is much better to set a variable to the desired
      Workbook, Worksheet, or Range.
      &lt;blockquote&gt;In particular, if there is any chance the spreadsheet might run under a browser,
      use &lt;span style="font-weight:bold;"&gt;Application.ThisWorkbook&lt;/span&gt; to ensure the browser
      evaluates the macro correctly.
      &lt;/blockquote&gt;
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
'NOTE: Arrays start with 1st position as "0", not "1"
'Thus ColLtrs(0) is not used but placed there as a spacer for letter to column alignment:
ColLtrs = Array("", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")

With ActiveSheet
  Range(ColLtrs(iOutCol) &amp;amp; iOutRow).Select
    
  If UnitSystem = "Metric" Then
    iRow = ActiveCell.Row
    For i = iRow To iLastRow - 1
      currCell = ColLtrs(ActiveCell.Column) &amp;amp; i + 1

      If Range(currCell).Value &amp;lt;&amp;gt; "" Then
        'capture the value from original calculatated data
        Range(currCell).Select

        strOrigValueCell = ColLtrs(iResultsCol) &amp;amp; ActiveCell.Row
        Result = ConvertUom(Range(strOrigValueCell))
      End If
    Next i
  End If
End With
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
Dim mySheet As Worksheet
Dim Value As Variant

Set mySheet = ActiveSheet

For i = iRow To iLastRow - 1
  Value = mySheet.Cells(i, iOutCol).Value
  If Value &amp;lt;&amp;gt; "" Then
    Result = ConvertUom(UnitSystem, Value)
  End If
Next i

' To get a column letter/code, do not reinvent the wheel!
' Various functions from:
' http://www.dicks-blog.com/archives/2004/05/21/column-numbers-to-letters/

Function ColLetter(ColNumber As Long) As String
    On Error Resume Next
    ColLetter = Application.Substitute(Application.ConvertFormula("R1C" &amp;amp; ColNumber, xlR1C1, xlA1, 4), "1", "")
End Function

Function ColumnLetter(ByVal c As Long) As String
  Dim p As Long
  While c
    p = 1 + (c - 1) Mod 26
    c = (c - p) \ 26
    ColumnLetter = Chr$(64 + p) &amp;amp; ColumnLetter
  Wend
End Function
&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using .Select and moving selection in macros unless absolutely.&lt;/h3&gt;
      Do not change the current sheet or selection unless that is the intention of the macro.
      In general, don't mess with the user, flip sheets, or other heinous acts and 
      try to leave things the way you found them.
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
For i = 1 To 10
  Range("A" &amp;amp; i).Select
  ActiveCell.Value = "Row " &amp;amp; i
Next i
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;Dim iColumn As Long
Dim mySheet As Worksheet
Dim myRange As Range

iColumn = 1
Set mySheet = ActiveSheet

For iRow = 1 To 10
  Set rng = mySheet.Cells(iRow, iColumn)
  rng.Value = "Row " &amp;amp; iRow
Next iRow
&lt;/pre&gt;
    &lt;/li&gt;
  &lt;/ol&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/68.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2008/05/27/macro-guidelines-for-excel-vba-beginners.aspx</guid>
            <pubDate>Tue, 27 May 2008 23:28:20 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/68.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2008/05/27/macro-guidelines-for-excel-vba-beginners.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/68.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/68.aspx</trackback:ping>
        </item>
        <item>
            <title>Throw Away Knowledge</title>
            <link>http://nimblecoder.com/blog/archive/2007/11/13/throw-away-knowledge.aspx</link>
            <description>&lt;p&gt;I have spent the past hour trying to modify a VBScript / JavaScript utility to print out my password expiration date and it is driving me a little crazy. I cannot understand why something that should be so simple can be so blasted difficult. I have several account at client sites and the password expires periodically. In order to make sure I don't let the account lapse, I wanted to print the password expiration date. I had a version that worked before but the distinguishedName had to be exact. I used the &lt;a href="http://www.joeware.net/freetools/tools/adfind/index.htm" target="_blank"&gt;adfind&lt;/a&gt; utility to figure out my distinguished name and put it in the script. Today I wanted to remove that limitation but it is proving to be a big waste of time. Every attempt to make this work with either VBScript or JavaScript has been thwarted with malice.&lt;/p&gt; &lt;p&gt;Of couse that doesn't stop me from trying -- oh no! Merely a &lt;a href="http://en.wikipedia.org/wiki/Monty_Python_and_the_Holy_Grail" target="_blank"&gt;flesh wound&lt;/a&gt;. As a programmer determined to make things work, it will bug me until it actually does work! There is silliness involved such as this code to convert an Integer64 to a useable native data type in VBScript:&lt;/p&gt;&lt;pre class="csharpcode"&gt;numDays = CCur((maxPwdAge.HighPart * 2 ^ 32) + _
                maxPwdAge.LowPart) / CCur(-864000000000)

whenPasswordExpires = DateAdd(&lt;span class="str"&gt;"d"&lt;/span&gt;, numDays, oUser.PasswordLastChanged)
&lt;/pre&gt;
&lt;p&gt;JavaScript doesn't have the CCur function so I have to use an alternative (and talk about silly -- using a currency data type to do this!). With both VBScript and JavaScript, I am having trouble searching Active Directory with a query or filter. At this point, I may use C# script where I have full .NET power.&lt;/p&gt;
&lt;p&gt;&lt;a title="C by Dissection" href="http://www.flickr.com/photos/14402141@N00/2006820976/"&gt;&lt;img alt="C by Dissection" src="http://static.flickr.com/2099/2006820976_4758b8d2b4_m.jpg" align="left" border="0" /&gt;&lt;/a&gt;This brings me to the point of this entry. Much of the programming technologies in use are destined for a short lifetime. It is an utter waste to invest time, money, and effort to build complex solutions against technologies and frameworks that will be replaced in two years. It is the dilemma that we find ourselves in though, and sometimes there is no or little choice.&lt;/p&gt;
&lt;p&gt;As I write this entry I am looking at the waste land of books including my original C programming textbook from university, a ancient graphics programming book that describes "&lt;a href="http://en.wikipedia.org/wiki/Mode_X" target="_blank"&gt;Mode X&lt;/a&gt;", some COM and ATL books, and tucked away somewhere I have the Petzold Win95 book and Prosise MFC Win95 book. Then I start thinking about &lt;a href="http://en.wikipedia.org/wiki/Lvalue" target="_blank"&gt;l-values and r-values&lt;/a&gt;, some of the ridiculous MFC hacks I've had to make in the past and I'm glad I don't have to deal with that much anymore. Things have improved especially in the area of dynamic or scripting languages where the power of these languages allow the programmer to accomplish a significant amount of work with less effort. One of the benefits is that is almost forces other languages to add features and streamline for greater efficiency. Unfortunately it is a slow process but I do see progress.&lt;/p&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/46.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/11/13/throw-away-knowledge.aspx</guid>
            <pubDate>Tue, 13 Nov 2007 21:59:16 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/46.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/11/13/throw-away-knowledge.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/46.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/46.aspx</trackback:ping>
        </item>
        <item>
            <title>New Printers Breaking (Formerly) Stable Code!</title>
            <link>http://nimblecoder.com/blog/archive/2007/08/07/new-printers-breaking-formerly-stable-code.aspx</link>
            <description>&lt;p&gt;I am almost embarassed to mention it, but in a past life I developed several major corporate applications using VB6. The applications are remarkably stable and have only been recompiled three or four times since their original deployment for various fixes or changes. This particular application has been in use for 10 years (since 1997) and uses Crystal Reports 5.0 for printing. Back in the day, I read Visual Basic Programmer's Journal (VBPJ) quite a bit and saw an article about using the Win32 API for Crystal Reports in VB. Since I was more of a C\C++ programmer thrust into the VB programmer role, I instantly liked this article and used these methods in my application. At the time I was not familiar with &lt;a href="http://vb.mvps.org/hardweb/mckinney.htm"&gt;Hardcode Visual Basic&lt;/a&gt; (or &lt;a href="http://vb.mvps.org/hardcore/"&gt;here&lt;/a&gt;) by &lt;a href="http://www.soundclick.com/brucemckinney"&gt;Bruce McKinney&lt;/a&gt; so this code used a common hack when copying memory into VB:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;' Slightly modified code. Original code from VBPJ.&lt;/span&gt;
&lt;span class="rem"&gt;' ... Removed extra code for sample ...&lt;/span&gt;

&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Declare&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; CopyMemory &lt;span class="kwrd"&gt;Lib&lt;/span&gt; &lt;span class="str"&gt;"kernel32"&lt;/span&gt; &lt;span class="kwrd"&gt;Alias&lt;/span&gt; &lt;span class="str"&gt;"RtlMoveMemory"&lt;/span&gt; _
    (Destination &lt;span class="kwrd"&gt;As&lt;/span&gt; Any, Source &lt;span class="kwrd"&gt;As&lt;/span&gt; Any, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Length &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Long&lt;/span&gt;)

&lt;span class="kwrd"&gt;Private&lt;/span&gt; Type DevModeBuffer &lt;span class="rem"&gt;' Holds DevMode Data.&lt;/span&gt;
    sData &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; * 4096
&lt;span class="kwrd"&gt;End&lt;/span&gt; Type

&lt;span class="kwrd"&gt;Private&lt;/span&gt; m_HoldDevMode   &lt;span class="kwrd"&gt;As&lt;/span&gt; DevMode
&lt;span class="kwrd"&gt;Private&lt;/span&gt; m_DModeBuffer   &lt;span class="kwrd"&gt;As&lt;/span&gt; DevModeBuffer
&lt;span class="kwrd"&gt;Private&lt;/span&gt; m_lDModeSize    &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Long&lt;/span&gt;

&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; SetupPrinter(lFlags &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Long&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;
    &lt;span class="rem"&gt;' ... Printer setup ...&lt;/span&gt;

    &lt;span class="rem"&gt;' Get size of DevMode &amp;amp; DevNames from PrintDlg return&lt;/span&gt;
    m_lDModeSize = GlobalSize(PDlg.hDevMode)

    &lt;span class="rem"&gt;' Fill Buffers with Space to Perpare for copy to.&lt;/span&gt;
    m_DModeBuffer.sData = &lt;span class="kwrd"&gt;String&lt;/span&gt;$(4095, 32)

    &lt;span class="rem"&gt;' Lock memory &amp;amp; copy the standard size DevMode.&lt;/span&gt;
    lDModePointer = GlobalLock(PDlg.hDevMode)  &lt;span class="rem"&gt;' Locks the memory&lt;/span&gt;
    &lt;span class="kwrd"&gt;Call&lt;/span&gt; CopyMemory(m_HoldDevMode, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; lDModePointer, Len(m_HoldDevMode))

    &lt;span class="rem"&gt;' Copy entire DevMode Structure for later use.&lt;/span&gt;
    &lt;span class="kwrd"&gt;Call&lt;/span&gt; CopyMemory(m_DModeBuffer, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; lDModePointer, m_lDModeSize) &lt;span class="rem"&gt;' Copies the memory&lt;/span&gt;

    &lt;span class="rem"&gt;' ... More printer setup ...&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;
&lt;p&gt;The key to this code is the String * 4096 and the String$(4095, 32) which initializes the buffer. Prior to Hardcode VB, it wasn't really possible to have arbitrary sized buffers because VB passed the String parameter (BSTR) differently to API functions. So people used a fixed buffer size (in this case 4096) in a Type (structure) and VB passed the parameter as a pointer-to-memory, not a pointer-to-a-pointer-to-memory.&lt;/p&gt;
&lt;p&gt;After a little bit of debugging, it quickly becomes apparent that this new printer returns a much larger memory block (6952 bytes) and the CopyMemory statement happily copies the entire block regardless of the allocated size. Fortunately, the change was fairly simple.&lt;/p&gt;
&lt;p&gt;With the advent of Hardcore VB and the Win.TLB, it was possible to reference DLL functions in a manner that wasn't previously possible by altering the data type and ByVal/ByRef settings. The Win.TLB has a function CopyMemoryLpToStr() so the code essentially becomes:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;' Remove the * 4096 from DevModeBuffer.sData&lt;/span&gt;

&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; SetupPrinter(lFlags &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Long&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;
    &lt;span class="rem"&gt;' ...&lt;/span&gt;
    &lt;span class="rem"&gt;' Fill Buffers with Space to Perpare for copy to.&lt;/span&gt;
    m_DModeBuffer.sData = &lt;span class="kwrd"&gt;String&lt;/span&gt;$(m_lDModeSize + 1, 32)

    &lt;span class="rem"&gt;' Copy entire DevMode Structure for later use.&lt;/span&gt;
    &lt;span class="kwrd"&gt;Call&lt;/span&gt; CopyMemoryLpToStr(m_DModeBuffer.sData, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; lDModePointer, m_lDModeSize) &lt;span class="rem"&gt;' Copies the memory&lt;/span&gt;
    &lt;span class="rem"&gt;' ...&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;
&lt;p&gt;Well I hope this is the last time I have to touch this application. It has been remarkably stable even though I have moved on to different departments several times and no one is actively maintaining it.&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:2cbc403b-af3d-45c7-a8a4-f6d414aa1f81" style="display:inline; margin:0px; padding:0px 0px 0px 0px;"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/VB6" rel="tag"&gt;VB6&lt;/a&gt;&lt;/div&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/36.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/08/07/new-printers-breaking-formerly-stable-code.aspx</guid>
            <pubDate>Tue, 07 Aug 2007 15:14:40 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/36.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/08/07/new-printers-breaking-formerly-stable-code.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/36.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/36.aspx</trackback:ping>
        </item>
        <item>
            <title>Formatting XML in Excel/VB</title>
            <link>http://nimblecoder.com/blog/archive/2007/05/23/Formatting-XML-in-ExcelVB.aspx</link>
            <description>&lt;p&gt;I was working on a spreadsheet that submitted XML data to a web service and the XML that was being generated by the XmlDocument object was not very tidy. Normally with C# I use Tidy.NET to clean up the HTML or XML, but since this was being used in Excel I didn't want to have any external dependencies. I found the following code online and it seems to work pretty well:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Option&lt;/span&gt; Explicit

&lt;span class="rem"&gt;' http://www.vb-helper.com/howto_formatted_xml_document.html&lt;/span&gt;
&lt;span class="rem"&gt;' Add formatting to the document.&lt;/span&gt;
&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; FormatXmlDocument(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; xml_doc &lt;span class="kwrd"&gt;As&lt;/span&gt; DOMDocument)
    FormatXmlNode xml_doc.documentElement, 0
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

&lt;span class="rem"&gt;' Add formatting to this element. Indent it and add a&lt;/span&gt;
&lt;span class="rem"&gt;' carriage return before its children. Then recursively&lt;/span&gt;
&lt;span class="rem"&gt;' format the children with increased indentation.&lt;/span&gt;
&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; FormatXmlNode(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; node &lt;span class="kwrd"&gt;As&lt;/span&gt; IXMLDOMNode, _
                          &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; indent &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;)
&lt;span class="kwrd"&gt;Dim&lt;/span&gt; child &lt;span class="kwrd"&gt;As&lt;/span&gt; IXMLDOMNode
&lt;span class="kwrd"&gt;Dim&lt;/span&gt; text_only &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;

    &lt;span class="rem"&gt;' Do nothing if this is a text node.&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;TypeOf&lt;/span&gt; node &lt;span class="kwrd"&gt;Is&lt;/span&gt; IXMLDOMText &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="rem"&gt;' See if this node contains only text.&lt;/span&gt;
    text_only = &lt;span class="kwrd"&gt;True&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; node.hasChildNodes &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; child &lt;span class="kwrd"&gt;In&lt;/span&gt; node.childNodes
            &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; (&lt;span class="kwrd"&gt;TypeOf&lt;/span&gt; child &lt;span class="kwrd"&gt;Is&lt;/span&gt; IXMLDOMText) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                text_only = &lt;span class="kwrd"&gt;False&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;For&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt; child
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="rem"&gt;' Process child nodes.&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; node.hasChildNodes &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="rem"&gt;' Add a carriage return before the children.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; text_only &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            node.insertBefore _
                node.ownerDocument.createTextNode(vbCrLf), _
                node.FirstChild
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="rem"&gt;' Format the children.&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; child &lt;span class="kwrd"&gt;In&lt;/span&gt; node.childNodes
            FormatXmlNode child, indent + 2
        &lt;span class="kwrd"&gt;Next&lt;/span&gt; child
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="rem"&gt;' Format this element.&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; indent &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="rem"&gt;' Indent before this element.&lt;/span&gt;
        node.parentNode.insertBefore _
            node.ownerDocument.createTextNode(Space$(indent)), _
            node

        &lt;span class="rem"&gt;' Indent after the last child node.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; text_only &lt;span class="kwrd"&gt;Then&lt;/span&gt; _
            node.appendChild _
                node.ownerDocument.createTextNode(Space$(indent))

        &lt;span class="rem"&gt;' Add a carriage return after this node.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; node.nextSibling &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            node.parentNode.appendChild _
                node.ownerDocument.createTextNode(vbCrLf)
        &lt;span class="kwrd"&gt;Else&lt;/span&gt;
            node.parentNode.insertBefore _
                node.ownerDocument.createTextNode(vbCrLf), _
                node.nextSibling
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/25.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/05/23/Formatting-XML-in-ExcelVB.aspx</guid>
            <pubDate>Wed, 23 May 2007 15:23:57 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/25.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/05/23/Formatting-XML-in-ExcelVB.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/25.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/25.aspx</trackback:ping>
        </item>
        <item>
            <title>Visual Floating Point Debugger Tool</title>
            <link>http://nimblecoder.com/blog/archive/2007/02/07/visual-floating-point-debugger-tool.aspx</link>
            <description>&lt;p&gt;When I was debugging communication protocols a long time ago, I would often have to convert a 32-bit integer into a 32-bit floating point number. This did not mean using &lt;font face="Courier New"&gt;atof&lt;/font&gt;, &lt;font face="Courier New"&gt;fscanf&lt;/font&gt;, &lt;font face="Courier New"&gt;_fcvt&lt;/font&gt; or similar function, but rather interpretting the bits as an &lt;a href="http://en.wikipedia.org/wiki/IEEE_754"&gt;IEEE 754&lt;/a&gt; or &lt;font face="Arial"&gt;IEC 60559:1989 &lt;/font&gt;floating point number. An example would be:&lt;/p&gt;
&lt;p&gt;1.0 == 0x3F800000 (1065353216)&lt;/p&gt;
&lt;p&gt;In the process, I wrote a tool that displays the components of the floating point number and allows you to change the raw hexadecimal bits. Here is a screen shot:&lt;/p&gt;
&lt;p&gt;&lt;img width="296" height="474" align="middle" src="/blog/images/nimblecoder_com/blog/FloatScreenShot01.PNG" alt="screen shot" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;This tool was written with VB6 however I have always wanted to make a C++/WTL version of the tool. Maybe I will get around to it sometime. &lt;/font&gt;&lt;font face="Arial"&gt;&lt;a href="http://www.codeproject.com/dotnet/ExtremeFloatingPoint1.asp"&gt;Here&lt;/a&gt; is a decent article describing the floating point format.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.nimblecoder.com/blog/Images/nimblecoder_com/blog/Float.zip"&gt;Float Tool Source&lt;/a&gt;: 18KB&lt;/p&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/10.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/02/07/visual-floating-point-debugger-tool.aspx</guid>
            <pubDate>Wed, 07 Feb 2007 19:10:43 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/10.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/02/07/visual-floating-point-debugger-tool.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/10.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/10.aspx</trackback:ping>
        </item>
        <item>
            <title>Export Excel Worksheet to ADO Recordset</title>
            <link>http://nimblecoder.com/blog/archive/2007/01/15/2.aspx</link>
            <description>This weekend I was working on a spreadsheet and I needed to save the data as a recordset. Unfortunately there didn't seem to be a way to do it easily without VBA macros. So I wrote this macro to save the current worksheet as an ADODB.Recordset XML file. Remember to add a reference to &lt;span style="font-family: Courier New;"&gt;Microsoft.ActiveX Data Object 2.8 Library&lt;/span&gt; in the Excel Visual Basic Editor.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea name="code" class="vb" cols="60" rows="10"&gt;  
Public Sub CreateAdoRecordsetXml()
    Dim rst As New ADODB.Recordset
    Dim sheet As Worksheet
    Dim col As Long, colcount As Long
    Dim row As Long, rowcount As Long
    Dim Filename As String

    Filename = ActiveWorkbook.Path + "\" + ActiveSheet.Name + ".xml"
    Set sheet = ActiveSheet
    colcount = sheet.UsedRange.Columns.count
    rowcount = sheet.UsedRange.Rows.count

    col = 1
    row = 1
    Do While col &amp;lt;= colcount
        Call rst.Fields.Append(sheet.Cells(row, col).Text, adVarChar, 255, adFldMayBeNull)
        col = col + 1
    Loop
    rst.Open

    row = 2
    Do While row &amp;lt;= rowcount
        col = 1
        Call rst.AddNew
        With rst.Fields
            Do While col &amp;lt;= colcount
                If sheet.Cells(row, col).Text &amp;lt;&amp;gt; "" Then
                    .Item(col - 1).Value = sheet.Cells(row, col).Text
                End If
                col = col + 1
            Loop
        End With
        Call rst.Update
        row = row + 1
    Loop

    Call rst.Save(Filename, adPersistXML)
End Sub
&lt;/textarea&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/2.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/01/15/2.aspx</guid>
            <pubDate>Mon, 15 Jan 2007 18:22:28 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/2.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/01/15/2.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/2.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/2.aspx</trackback:ping>
        </item>
    </channel>
</rss>