<?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>Blog of Travis Hydzik &#187; Visual Basic</title>
	<atom:link href="http://thydzik.com/category/visual-basic/feed/" rel="self" type="application/rss+xml" />
	<link>http://thydzik.com</link>
	<description>random snippets and information</description>
	<lastBuildDate>Fri, 27 Jan 2012 13:54:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>VBA/VB6 functions to return folder or file type and date modified.</title>
		<link>http://thydzik.com/vbavb6-functions-to-return-folder-or-file-type-and-date-modified/</link>
		<comments>http://thydzik.com/vbavb6-functions-to-return-folder-or-file-type-and-date-modified/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 08:03:44 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[folder]]></category>
		<category><![CDATA[modified]]></category>
		<category><![CDATA[type]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=642</guid>
		<description><![CDATA[Here are two quick functions; The first getType takes in a path of a folder or file and returns the type. The second function getDate takes in a folder or path and returns the date modified. getDate references getType.<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/vbavb6-functions-to-return-folder-or-file-type-and-date-modified/' addthis:title='VBA/VB6 functions to return folder or file type and date modified. ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Here are two quick functions;</p>
<p>The first <em>getType </em>takes in a path of a folder or file and returns the type.</p>
<pre class="brush: vb; title: ; notranslate">
Function getType(ByRef path As String) As String
    On Error Resume Next
    Dim res As Long
    res = GetAttr(path)
    If Err.Number = 0 Then
        If res And vbDirectory Then
            getType = &quot;folder&quot;
        Else
            getType = &quot;file&quot;
        End If
    Else
        getType = &quot;error&quot;
    End If
End Function
</pre>
<p>The second function <em>getDate </em>takes in a folder or path and returns the date modified. <em>getDate </em>references <em>getType</em>.</p>
<pre class="brush: vb; title: ; notranslate">
Function getDate(ByRef path As String) As Double
    Select Case getType(path)
        Case &quot;file&quot;
            getDate = CreateObject(&quot;scripting.filesystemobject&quot;).getfile(path).datelastmodified
        Case &quot;folder&quot;
            getDate = CreateObject(&quot;scripting.filesystemobject&quot;).getfolder(path).datelastmodified
    End Select
End Function
</pre>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/vbavb6-functions-to-return-folder-or-file-type-and-date-modified/' addthis:title='VBA/VB6 functions to return folder or file type and date modified. ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/vbavb6-functions-to-return-folder-or-file-type-and-date-modified/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VB6/VBA functions to convert binary string to Base64 string</title>
		<link>http://thydzik.com/vb6vba-functions-to-convert-binary-string-to-base64-string/</link>
		<comments>http://thydzik.com/vb6vba-functions-to-convert-binary-string-to-base64-string/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 05:46:19 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[Base64]]></category>
		<category><![CDATA[binary]]></category>
		<category><![CDATA[byte array]]></category>
		<category><![CDATA[function]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=637</guid>
		<description><![CDATA[Here are some functions to convert a binary string, to a byte array, to a Base64 string and then back to a byte array and binary string. Run tester to see it in action, enjoy. Thanks to Tim Hastings for the Base64 functions.<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/vb6vba-functions-to-convert-binary-string-to-base64-string/' addthis:title='VB6/VBA functions to convert binary string to Base64 string ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Here are some functions to convert a binary string, to a byte array, to a <a href="http://en.wikipedia.org/wiki/Base64" title="Wikipedia Base64" target="_blank">Base64</a> string and then back to a byte array and binary string. Run <em>tester</em> to see it in action, enjoy.</p>
<pre class="brush: vb; title: ; notranslate">
Private Function encodeBase64(ByRef arrData() As Byte) As String
    Dim objXML As MSXML2.DOMDocument
    Dim objNode As MSXML2.IXMLDOMElement

    Set objXML = New MSXML2.DOMDocument

    Set objNode = objXML.createElement(&amp;quot;b64&amp;quot;)
    objNode.DataType = &amp;quot;bin.base64&amp;quot;
    objNode.nodeTypedValue = arrData
    encodeBase64 = objNode.Text

    Set objNode = Nothing
    Set objXML = Nothing
End Function

Private Function decodeBase64(ByVal strData As String) As Byte()
    Dim objXML As MSXML2.DOMDocument
    Dim objNode As MSXML2.IXMLDOMElement

    Set objXML = New MSXML2.DOMDocument
    Set objNode = objXML.createElement(&amp;quot;b64&amp;quot;)
    objNode.DataType = &amp;quot;bin.base64&amp;quot;
    objNode.Text = strData
    decodeBase64 = objNode.nodeTypedValue

    Set objNode = Nothing
    Set objXML = Nothing
End Function

Function bin2Byte(ByVal s As String) As Byte()
    Dim bitsIn As Long
    bitsIn = 8

    Dim i As Long
    'pad with zeros
    If Len(s) Mod bitsIn &amp;lt;&amp;gt; 0 Then
        For i = 1 To bitsIn - Len(s) Mod bitsIn
            s = &amp;quot;0&amp;quot; &amp;amp; s
        Next i
    End If

    i = Len(s)
    Dim bytes() As Byte
    Dim byteCount As Long
    byteCount = -1
    Dim sByte As String
    Do While LenB(s) &amp;gt; 0
        byteCount = byteCount + 1
        ReDim Preserve bytes(byteCount)

        sByte = Mid$(s, Len(s) - bitsIn + 1)
        'sByte = Mid$(s, 1, bitsIn)
        For i = 0 To 7 Step 1
            bytes(byteCount) = bytes(byteCount) + CLng(Mid$(sByte, 8 - i, 1)) * 2 ^ i
        Next i
        s = Mid$(s, 1, Len(s) - bitsIn)
        's = Mid$(s, bitsIn + 1)
    Loop
    bin2Byte = bytes
End Function

Function byte2Bin(ByRef bytes() As Byte) As String
    Dim i As Long, j As Long
    Dim bin As String
    For i = 0 To UBound(bytes)
        bin = Space$(8)

        For j = 0 To 7
            If bytes(i) And 2 ^ j Then
                Mid(bin, 8 - j, 1) = &amp;quot;1&amp;quot;
            Else
                'Mid(bin, 8 - j, 1) = &amp;quot;0&amp;quot;
            End If
        Next j

        byte2Bin = bin &amp;amp; byte2Bin
    Next i
    byte2Bin = LTrim$(byte2Bin)
    byte2Bin = Replace(byte2Bin, &amp;quot; &amp;quot;, &amp;quot;0&amp;quot;, 1, -1, vbBinaryCompare)
End Function

Sub tester()
    'note we can't add any 0 padding to the test binary string
    Dim bin As String
    bin = &amp;quot;111101000001100010101&amp;quot;
    Dim binOut As String
    binOut = byte2Bin(decodeBase64(encodeBase64(bin2Byte(bin))))

    MsgBox binOut = bin
End Sub
</pre>
<p>Thanks to <a href="http://www.nonhostile.com/howto-encode-decode-base64-vb6.asp" title="Free, Easy and Quick Base64 Encoding and Decoding in Visual Basic">Tim Hastings</a> for the Base64 functions.</p>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/vb6vba-functions-to-convert-binary-string-to-base64-string/' addthis:title='VB6/VBA functions to convert binary string to Base64 string ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/vb6vba-functions-to-convert-binary-string-to-base64-string/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Photoshop VBScript to automatically resize images</title>
		<link>http://thydzik.com/photoshop-vbscript-to-automatically-resize-images/</link>
		<comments>http://thydzik.com/photoshop-vbscript-to-automatically-resize-images/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 18:28:43 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[automatic]]></category>
		<category><![CDATA[Photoshop]]></category>
		<category><![CDATA[resize]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[VBS]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=625</guid>
		<description><![CDATA[Decided to learn Photoshop VBScripting, don&#8217;t know why I didn&#8217;t do this sooner, I now have scripts to automatically generate my blog thumbnails (as below), and add little Google Maps markers on them (see here). A few constants to change in the script (edit with Notepad); RESIZEWIDTH &#8211; thumbnail width RESIZEHEIGHT &#8211; thumbnail height IGNOREVERTICAL [...]<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/photoshop-vbscript-to-automatically-resize-images/' addthis:title='Photoshop VBScript to automatically resize images ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Decided to learn Photoshop VBScripting, don&#8217;t know why I didn&#8217;t do this sooner, I now have scripts to automatically generate my blog thumbnails (as below), and add little Google Maps markers on them (see <a href="http://sonyaandtravis.com/egypt-egyptian-museum-and-islamic-cairo/">here</a>).</p>
<p>A few constants to change in the script (edit with Notepad);</p>
<ul>
<li>RESIZEWIDTH &#8211; thumbnail width</li>
<li>RESIZEHEIGHT &#8211; thumbnail height</li>
<li>IGNOREVERTICAL &#8211; should vertical (portrait0 images be ignored (I like to do these manually as I crop them to landscape)</li>
<li>SUFFIX &#8211; thumbnail suffix</li>
</ul>
<p>To run it, simply place the script in your image folder (make sure to take a backup) and execute the file.<br />
<a href="http://thydzik.com/downloads/auto-resize-images-v0.1.vbs">auto-resize-images-v0.1.vbs</a></p>
<pre class="brush: vb; title: ; notranslate">
Public Const RESIZEWIDTH = 150
Public Const RESIZEHEIGHT = 113

Public Const IGNOREVERTICAL = True
Public Const SUFFIX = &quot;-th&quot;

Dim spath
spath = Mid(WScript.ScriptFullName, 1, InStrRev(WScript.ScriptFullName, &quot;\&quot;, -1, vbBinaryCompare))

Dim fso
Set fso = CreateObject(&quot;Scripting.FileSystemObject&quot;)

Dim foldero
Set foldero = fso.GetFolder(spath)

Dim fileo
Dim sfile

For Each fileo In foldero.Files
    'only modify jpg files
    sfile = fileo.Name
    If InStrRev(sfile, &quot;.jpg&quot;, -1, vbTextCompare) = Len(sfile) - 3 Then
        resize spath &amp; sfile
    End If
Next

MsgBox &quot;Complete.&quot;

Sub resize(sfilename)

    Set WshShell = WScript.CreateObject(&quot;WScript.Shell&quot;)
    Set colProcessList = GetObject(&quot;Winmgmts:&quot;).ExecQuery(&quot;Select * from Win32_Process&quot;)

    Dim found
    found = False

    For Each objProcess In colProcessList
        If StrComp(objProcess.Name, &quot;photoshop.exe&quot;, vbTextCompare) = 0 Then
            found = True
            Exit For
        End If
    Next

    Dim appRef
    If found Then
        Set appRef = GetObject(, &quot;Photoshop.Application&quot;)
    Else
        Set appRef = CreateObject(&quot;Photoshop.Application&quot;)
    End If

    Do While appRef.documents.Count
       appRef.activeDocument.Close 2 'dont' save
    Loop

    Dim originalRulerUnits
    originalRulerUnits = appRef.Preferences.RulerUnits
    appRef.Preferences.RulerUnits = 1 'pixels

    Dim docRef
    Set docRef = appRef.Open(sfilename)

    Dim modified
    modified = False

    If docRef.Width &gt;= docRef.Height Then 'horizontal photo
            If docRef.Width &lt;&gt; RESIZEWIDTH Then 'proceed if not already resized
                docRef.ResizeImage RESIZEWIDTH 'preserves aspect ratio
                modified = True
            End If
    Else 'verticle photo
        If Not IGNOREVERTICAL Then 'proceed
            If docRef.Height &lt;&gt; RESIZEHEIGHT Then 'proceed if not already resized
                docRef.ResizeImage , RESIZEHEIGHT 'preserves aspect ratio
                modified = True
            End If
        End If
    End If

    If modified Then 'only save if the image was modified
        Dim jpgSaveOptions
        Set jpgSaveOptions = CreateObject(&quot;Photoshop.JPEGSaveOptions&quot;)
        jpgSaveOptions.Quality = 8

        'calculate the new file name
        Dim newfilename
        newfilename = Mid(sfilename, 1, Len(sfilename) - 4) &amp; SUFFIX &amp; &quot;.jpg&quot;

        docRef.SaveAs newfilename, jpgSaveOptions, True, 2 'for psLowercase
    End If

    docRef.Close 2 'dont' save

    appRef.Preferences.RulerUnits = originalRulerUnits

End Sub
</pre>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/photoshop-vbscript-to-automatically-resize-images/' addthis:title='Photoshop VBScript to automatically resize images ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/photoshop-vbscript-to-automatically-resize-images/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Ping function VBScript</title>
		<link>http://thydzik.com/simple-ping-function-vbscript/</link>
		<comments>http://thydzik.com/simple-ping-function-vbscript/#comments</comments>
		<pubDate>Sun, 14 Nov 2010 17:04:06 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[cmd]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[ping]]></category>
		<category><![CDATA[timeout]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=567</guid>
		<description><![CDATA[I was after a ping function that met the following constraints; Didn&#8217;t use GetObject. Didn&#8217;t display any command (cmd) prompt. Didn&#8217;t use a temporary files. Here is what I found; I was looking at a way to timeout the ping function after 1 second using Threading but this didn&#8217;t quite make it so simple. Whilst [...]<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/simple-ping-function-vbscript/' addthis:title='Simple Ping function VBScript ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>I was after a ping function that met the following constraints;</p>
<ul>
<li>Didn&#8217;t use GetObject.</li>
<li>Didn&#8217;t display any command (cmd) prompt.</li>
<li>Didn&#8217;t use a temporary files.</li>
</ul>
<p>Here is what I found;</p>
<p>
<pre class="brush: vb; title: ; notranslate">&lt;br /&gt;
Function ping(node)&lt;br /&gt;
    Set WshShell = CreateObject(&amp;quot;WScript.Shell&amp;quot;)&lt;br /&gt;
    ping = Not CBool(WshShell.Run(&amp;quot;ping -n 1 &amp;quot; &amp;amp; node, 0, True))&lt;br /&gt;
End Function&lt;br /&gt;
</pre>
</p>
<p>I was looking at a way to timeout the ping function after 1 second using Threading but this didn&#8217;t quite make it so simple. Whilst ping offers a timeout value if you ping an incorrect hostname it will hang for a little while.</p>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/simple-ping-function-vbscript/' addthis:title='Simple Ping function VBScript ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/simple-ping-function-vbscript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Decimal to Binary functions in Visual Basic</title>
		<link>http://thydzik.com/decimal-to-binary-functions-in-visual-basic/</link>
		<comments>http://thydzik.com/decimal-to-binary-functions-in-visual-basic/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 11:16:00 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[16 bit]]></category>
		<category><![CDATA[binary]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[decimal]]></category>
		<category><![CDATA[signed integer]]></category>
		<category><![CDATA[string]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=563</guid>
		<description><![CDATA[Here are functions to perform decimal to/from binary conversion. CBin &#8211; converts a decimal integer to binary string. CDeci &#8211; converts a binary string to decimal integer. CBinS16 &#8211; converts a decimal signed integer to 16 bit binary string. CdecS16 &#8211; converts a 16 bit binary string to decimal signed integer.<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/decimal-to-binary-functions-in-visual-basic/' addthis:title='Decimal to Binary functions in Visual Basic ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Here are functions to perform decimal to/from binary conversion.</p>
<ul>
<li>CBin &#8211; converts a decimal integer to binary string.</li>
<li>CDeci &#8211; converts a binary string to decimal integer.</li>
<li>CBinS16 &#8211; converts a decimal signed integer to 16 bit binary string.</li>
<li>CdecS16 &#8211; converts a 16 bit binary string to decimal signed integer.</li>
</ul>
<pre class="brush: vb; title: ; notranslate">
'converts an integer to binary string
Function CBin(ByVal n As Double) As String
    On Error Resume Next 'caters for 0 values
    Dim i As Double
    i = 2 ^ Int(Log(n) / Log(2))
    Do While i &gt;= 1
        CBin = CBin &amp; Fix(n / i)
        n = n - i * Fix(n / i)
        i = i / 2
    Loop
End Function

'converts a binary string to integer
Function CDeci(ByRef s As String) As Double
    Dim i As Long
    CDeci = 0
    For i = 0 To Len(s) - 1
        CDeci = CDeci + (Mid$(s, Len(s) - i, 1) * 2 ^ i)
    Next i
End Function

'converts an integer to 16 bit signed binary string
Function CBinS16(ByVal n As Double) As String
    Dim i As Double

    CBinS16 = vbNullString
    If n &lt; -2 ^ 15 Then
        CBinS16 = &quot;0&quot;
        n = n + 2 ^ 16
        i = 2 ^ 14
    ElseIf n &lt; 0 Then
        CBinS16 = &quot;1&quot;
        n = n + 2 ^ 15
        i = 2 ^ 14
    Else 'not negative
        i = 2 ^ 15
    End If

    Do While i &gt;= 1
        CBinS16 = CBinS16 &amp; Fix(n / i)
        n = n - i * Fix(n / i)
        i = i / 2
    Loop
End Function

'converts 16 bit signed binary string to integer
Function CDecS16(ByRef s As String) As Double
    Dim i As Long
    CDecS16 = 0
    For i = 0 To Len(s) - 1
        CDecS16 = CDecS16 + (Mid$(s, Len(s) - i, 1) * 2 ^ i)
    Next i
    If CDecS16 &gt;= 2 ^ 15 Then 'negative number
        CDecS16 = CDecS16 - 2 ^ 16
    End If
End Function
</pre>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/decimal-to-binary-functions-in-visual-basic/' addthis:title='Decimal to Binary functions in Visual Basic ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/decimal-to-binary-functions-in-visual-basic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server Quickest way to Insert Multiple Rows with VB</title>
		<link>http://thydzik.com/sql-server-quickest-way-to-insert-multiple-rows-with-vb/</link>
		<comments>http://thydzik.com/sql-server-quickest-way-to-insert-multiple-rows-with-vb/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 08:37:08 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[INSERT]]></category>
		<category><![CDATA[optimise]]></category>
		<category><![CDATA[quickest]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[TickCount]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=555</guid>
		<description><![CDATA[Having to parse huge amounts of data from xml files to an SQL Server database, I needed to greatly optimise my code. Here are some tests to insert 10000 rows into table TABLETESTER. First, using the standard INSERT INTO without specifying column names. TickCount of 70547. Specifying the column names is actually marginally faster. TickCount [...]<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/sql-server-quickest-way-to-insert-multiple-rows-with-vb/' addthis:title='SQL Server Quickest way to Insert Multiple Rows with VB ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Having to parse huge amounts of data from xml files to an SQL Server database, I needed to greatly optimise my code. Here are some tests to insert 10000 rows into table TABLETESTER.</p>
<p>First, using the standard INSERT INTO without specifying column names. TickCount of <strong>70547</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 10000
	Connection.Execute &amp;quot;INSERT INTO TABLETESTER VALUES (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
Next i
</pre>
<p>Specifying the column names is actually marginally faster. TickCount of <strong>66782</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000
    Connection.Execute &amp;quot;INSERT INTO TABLETESTER (NUMBERVAL, STRINGVAL) VALUES (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
Next i
</pre>
<p>Removing the optional INTO is a little faster still. TickCount <strong>64843</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000
	Connection.Execute &amp;quot;INSERT TABLETESTER (NUMBERVAL, STRINGVAL) VALUES (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
Next i
</pre>
<p>Now lets try some of the methods to combine multiple inserts.</p>
<p>Bunching multiple statements in a single Execute increases the speed by 2. TickCount <strong>35391</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 100
	s = vbNullString
	For j = 1 To 100
		s = s &amp;amp; &amp;quot;INSERT TABLETESTER (NUMBERVAL, STRINGVAL) VALUES (1, 'abcdefghijklmnopqrstuvwxyz');&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>Using UNION ALL increases it by a whopping 10 fold. TickCount <strong>2781</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 100
	s = &amp;quot;INSERT INTO TABLETESTER (NUMBERVAL, STRINGVAL) SELECT  1, 'abcdefghijklmnopqrstuvwxyz'&amp;quot;
	For j = 2 To 100
		s = s &amp;amp; &amp;quot; UNION ALL SELECT  1, 'abcdefghijklmnopqrstuvwxyz'&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>Increasing the inner loop count. TickCount <strong>3125</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 1000
	s = &amp;quot;INSERT INTO TABLETESTER (NUMBERVAL, STRINGVAL) SELECT  1, 'abcdefghijklmnopqrstuvwxyz'&amp;quot;
	For j = 2 To 1000
		s = s &amp;amp; &amp;quot; UNION ALL SELECT  1, 'abcdefghijklmnopqrstuvwxyz'&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>Decreasing the inner loop count. TickCount <strong>8235</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 10
	s = &amp;quot;INSERT INTO TABLETESTER (NUMBERVAL, STRINGVAL) SELECT  1, 'abcdefghijklmnopqrstuvwxyz'&amp;quot;
	For j = 2 To 10
		s = s &amp;amp; &amp;quot; UNION ALL SELECT  1, 'abcdefghijklmnopqrstuvwxyz'&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>SQL Server 2008 has a new method of combining multiple inserts. TickCount <strong>3282</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 100
	s = &amp;quot;INSERT TABLETESTER (NUMBERVAL, STRINGVAL) VALUES (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
	For j = 2 To 100
		s = s &amp;amp; &amp;quot;, (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>Increasing the inner loop count, note 1000 is the maximum allowed. TickCount <strong>2859</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 1000
	s = &amp;quot;INSERT TABLETESTER (NUMBERVAL, STRINGVAL) VALUES (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
	For j = 2 To 1000
		s = s &amp;amp; &amp;quot;, (1, 'abcdefghijklmnopqrstuvwxyz')&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>Finally, not a SQL syntax change, but compacting the strings. TickCount <strong>2453</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
For i = 1 To 100000 / 1000
	s = &amp;quot;INSERT TABLETESTER (NUMBERVAL,STRINGVAL) VALUES (1,'abcdefghijklmnopqrstuvwxyz')&amp;quot;
	For j = 2 To 1000
		s = s &amp;amp; &amp;quot;,(1,'abcdefghijklmnopqrstuvwxyz')&amp;quot;
	Next j
	Connection.Execute = s
Next i
</pre>
<p>So from our original method at 66782 to our optimised method at 2453, we get a <strong>97%</strong> speed saving!</p>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/sql-server-quickest-way-to-insert-multiple-rows-with-vb/' addthis:title='SQL Server Quickest way to Insert Multiple Rows with VB ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/sql-server-quickest-way-to-insert-multiple-rows-with-vb/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Visual Basic 6 &#8211; quickest way to find first/last character in string</title>
		<link>http://thydzik.com/visual-basic-6-quickest-way-to-find-firstlast-character-in-string/</link>
		<comments>http://thydzik.com/visual-basic-6-quickest-way-to-find-firstlast-character-in-string/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 09:32:20 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[compare]]></category>
		<category><![CDATA[faster]]></category>
		<category><![CDATA[InStrRev]]></category>
		<category><![CDATA[optimise]]></category>
		<category><![CDATA[Right]]></category>
		<category><![CDATA[StrComp]]></category>
		<category><![CDATA[strings]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=550</guid>
		<description><![CDATA[When you are parsing large amounts of data, the way you code string matching can make a huge difference. In one case I needed to find if a string was contained within quotes, here are the test results from quickest to slowest. The test situation was to find if the last character in the string [...]<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/visual-basic-6-quickest-way-to-find-firstlast-character-in-string/' addthis:title='Visual Basic 6 &#8211; quickest way to find first/last character in string ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>When you are parsing large amounts of data, the way you code string matching can make a huge difference. In one case I needed to find if a string was contained within quotes, here are the test results from quickest to slowest.</p>
<p>The test situation was to find if the last character in the string &#8216;abcdefghijklmnopqrstuvwxyz&#8217; is &#8216;z&#8217; and iterated 100000000 times.</p>
<p>First, the most intuitive which most would use.  TickCount of <strong>49546</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
Right(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;, 1) = &amp;amp;quot;z&amp;amp;quot;
</pre>
<p>Function Right takes in a Variant by default, by succeeding it with a dollar sign it accepts Strings by default. TickCount of <strong>22828</strong>, a significant saving.</p>
<pre class="brush: vb; title: ; notranslate">
Right$(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;, 1) = &amp;amp;quot;z&amp;amp;quot;
</pre>
<p>Using the equals sign would be seem the norm, but what if the String Compare function was used. TickCount of <strong>18047</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
StrComp(Right$(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;, 1), &amp;amp;quot;z&amp;amp;quot;, vbBinaryCompare) = 0
</pre>
<p>What if Mid was used to extract the last character instead of Right. TickCount of <strong>28391</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
StrComp(Mid$(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;, Len(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;), 1), &amp;amp;quot;z&amp;amp;quot;) = 0
</pre>
<p>Now what if we use the In String function. String length binary is faster than standard String length. TickCount of <strong>14516</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
InStrRev(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;, &amp;amp;quot;z&amp;amp;quot;, -1, vbBinaryCompare) = LenB(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;) / 2
</pre>
<p>Finally, with out String length binary. TickCount of <strong>11312</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
InStrRev(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;, &amp;amp;quot;z&amp;amp;quot;, -1, vbBinaryCompare) = Len(&amp;amp;quot;abcdefghijklmnopqrstuvwxyz&amp;amp;quot;)
</pre>
<p><strong>So using In String Reverse is 77% faster.</strong></p>
<p>UPDATE next day: Three that I totally forgot about</p>
<p>In String starting at last character, TickCount <strong>11266</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
InStr(Len(&amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;), &amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;, &amp;quot;z&amp;quot;, vbBinaryCompare) = Len(&amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;)
</pre>
<p>And In String Binary which is naturally fast. TickCount <strong>6672</strong>.</p>
<pre class="brush: vb; title: ; notranslate">
InStrB(LenB(&amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;) - 1, &amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;, &amp;quot;z&amp;quot;, vbBinaryCompare) = LenB(&amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;) - 1
</pre>
<p><strong>So using In String Binary is 70% faster.</strong></p>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/visual-basic-6-quickest-way-to-find-firstlast-character-in-string/' addthis:title='Visual Basic 6 &#8211; quickest way to find first/last character in string ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/visual-basic-6-quickest-way-to-find-firstlast-character-in-string/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Base64/sexatrigesimal encoding/decoding in VBA/VB6/Visual Basic</title>
		<link>http://thydzik.com/base64sexatrigesimal-encodingdecoding-in-vbavb6visual-basic/</link>
		<comments>http://thydzik.com/base64sexatrigesimal-encodingdecoding-in-vbavb6visual-basic/#comments</comments>
		<pubDate>Sun, 10 Oct 2010 10:23:33 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[Base36]]></category>
		<category><![CDATA[decoding]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[sexatrigesimal]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=546</guid>
		<description><![CDATA[Here is an implementation of Base 36 enconding/decoding functions is VB6.<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/base64sexatrigesimal-encodingdecoding-in-vbavb6visual-basic/' addthis:title='Base64/sexatrigesimal encoding/decoding in VBA/VB6/Visual Basic ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Here is an implementation of <a href="http://en.wikipedia.org/wiki/Base_36">Base 36</a> enconding/decoding functions is VB6.</p>
<pre class="brush: vb; title: ; notranslate">
'Convert positive integer to a base36 string.
Function base36encode(ByRef number As Long) As String

    Dim alphabet As String
    alphabet = &amp;quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;quot;
    If number = 0 Then
        base36encode = &amp;quot;0&amp;quot;
        Exit Function
    End If
    base36encode = vbNullString
    Do While number &amp;lt;&amp;gt; 0
        base36encode = Mid(alphabet, number Mod 36 + 1, 1) &amp;amp; base36encode
        number = number \ 36
    Loop

End Function

'Convert base36 string to positive integer.
Function base36decode(ByRef base36 As String) As Long

    Dim alphabet As String
    alphabet = &amp;quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;quot;

    base36decode = InStr(1, alphabet, Right(base36, 1), vbTextCompare) - 1 'get the last character
    For i = Len(base36) - 1 To 1 Step -1
        base36decode = base36decode + 36 ^ (Len(base36) - i) * (InStr(1, alphabet, Mid(base36, i, 1), vbTextCompare) - 1)
    Next i

End Function
</pre>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/base64sexatrigesimal-encodingdecoding-in-vbavb6visual-basic/' addthis:title='Base64/sexatrigesimal encoding/decoding in VBA/VB6/Visual Basic ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/base64sexatrigesimal-encodingdecoding-in-vbavb6visual-basic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>eventquery.vbs &#8211; ERROR: Unable to execute the query for the&#8230;</title>
		<link>http://thydzik.com/eventquery-vbs-error-unable-to-execute-the-query-for-the/</link>
		<comments>http://thydzik.com/eventquery-vbs-error-unable-to-execute-the-query-for-the/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 05:41:47 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[event viewer]]></category>
		<category><![CDATA[eventquery]]></category>
		<category><![CDATA[VBS]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=540</guid>
		<description><![CDATA[If you received this error when trying to execute eventquery.vbs the cause is an overflow of events past 32,767 (the maximum capacity of a VB6 Integer). There is a very simple fix for this which is to change the data type from an Integer to a Long (which has a maximum capacity of 2,147,483,647). In [...]<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/eventquery-vbs-error-unable-to-execute-the-query-for-the/' addthis:title='eventquery.vbs &#8211; ERROR: Unable to execute the query for the&#8230; ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>If you received this error when trying to execute eventquery.vbs the cause is an overflow of events past 32,767 (the maximum capacity of a VB6 Integer). There is a very simple fix for this which is to change the data type from an Integer to a Long (which has a maximum capacity of 2,147,483,647).</p>
<p>In eventquery.vbs, scroll down to line 1700 and 1703 and change both CInt to CLng.<br />
Before;</p>
<pre class="brush: vb; first-line: 1700; highlight: [1700,1703]; title: ; notranslate">
        If CInt(objLogs.Item(arrKeyName(intLoopCount))) &gt; 0 Then
            strFilterLog = arrKeyName(intLoopCount)
            intRecordRangeFrom = 0
            intRecordRangeTo = CInt(objLogs.Item(arrKeyName(intLoopCount)))
</pre>
<p>After;</p>
<pre class="brush: vb; first-line: 1700; highlight: [1700,1703]; title: ; notranslate">
        If CLng(objLogs.Item(arrKeyName(intLoopCount))) &gt; 0 Then
            strFilterLog = arrKeyName(intLoopCount)
            intRecordRangeFrom = 0
            intRecordRangeTo = CLng(objLogs.Item(arrKeyName(intLoopCount)))
</pre>
<p>Or download the already updated <a href="http://thydzik.com/downloads/eventquerynew.vbs">eventquery.vbs</a>.</p>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/eventquery-vbs-error-unable-to-execute-the-query-for-the/' addthis:title='eventquery.vbs &#8211; ERROR: Unable to execute the query for the&#8230; ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/eventquery-vbs-error-unable-to-execute-the-query-for-the/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Longest Common Subsequence implemented in VBA (Visual Basic for Applications)</title>
		<link>http://thydzik.com/longest-common-subsequence-implemented-in-vba-visual-basic-for-applications/</link>
		<comments>http://thydzik.com/longest-common-subsequence-implemented-in-vba-visual-basic-for-applications/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 18:22:16 +0000</pubDate>
		<dc:creator>thydzik</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[backTrace]]></category>
		<category><![CDATA[LCS]]></category>
		<category><![CDATA[Longest Common Subsequence]]></category>
		<category><![CDATA[TraceBack]]></category>
		<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://thydzik.com/?p=461</guid>
		<description><![CDATA[From Wikipedia, The longest common subsequence (LCS) problem is to find the longest subsequence common to all sequences in a set of sequences (often just two). The following is a VBA implementation of this problem. The following functions are included; String functions; longestCommonSubsequence - calculate an LCS array. backTraceUp and backTraceLeft - trace back either [...]<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/longest-common-subsequence-implemented-in-vba-visual-basic-for-applications/' addthis:title='Longest Common Subsequence implemented in VBA (Visual Basic for Applications) ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>From <a href="http://en.wikipedia.org/wiki/Longest_common_subsequence_problem">Wikipedia</a>, <em>The longest common subsequence (LCS) problem is to find the longest subsequence common to all sequences in a set of sequences (often just two).</em></p>
<p>The following is a VBA implementation of this problem. The following functions are included;</p>
<p>String functions;</p>
<ul>
<li><strong>longestCommonSubsequence </strong>- calculate an LCS array.</li>
<li><strong>backTraceUp </strong>and <strong>backTraceLeft </strong>- trace back either defaulting up or left respectively, and find the LCS.</li>
<li><strong>getDiff </strong>- returns the difference of the two strings. The succeeding character of =, &#8211; or + indicated if the character was equal, removed or added, respectively.</li>
<li><strong>passGetDiffOutput </strong>- passes the output of getDiff so that =, &#8211; or + are now values in a 2 x n array, with indix 0 being equal, indix 1 being removed and indix 2 being added.</li>
</ul>
<p>Array functions;</p>
<ul>
<li><strong>longestCommonSubsequenceArr </strong>- calculate an LCS array.</li>
<li><strong>backTraceUpArr </strong>- trace back defaulting up and find the LCS.</li>
<li><strong>getDiffArr </strong>- returns the difference of the two arrays as a 2 x n array, with indix 0 being equal, indix 1 being removed and  indix 2 being added.</li>
</ul>
<p>Common functions;</p>
<ul>
<li><strong>max </strong>- standard maximum function.</li>
<li><strong>stringToArray </strong>- convert a string to an array for array functions.</li>
</ul>
<p>Examples;</p>
<ul>
<li><strong>exampleString</strong></li>
<li><strong>exampleArr</strong></li>
</ul>
<p><a href="http://thydzik.com/downloads/longest-common-subsequence.bas">Download the Basic (bas) File</a></p>
<p>Unfortunately, the limitations of VBA makes a dog&#8217;s dinner out of what would be some very concise code or, perhaps that’s just my implementation…</p>
<pre class="brush: vb; title: ; notranslate">
Option Explicit

Public Function longestCommonSubsequence(ByRef string1 As String, ByRef string2 As String) As Long()
    If string1 = vbNullString Or string2 = vbNullString Then
        Exit Function
    End If

    Dim num() As Long

    'define the array, note rows of zeros get added to front automatically
    ReDim num(Len(string1), Len(string2))

    Dim i As Long, j As Long

    For i = 1 To Len(string1)
        For j = 1 To Len(string2)
            If Mid$(string1, i, 1) = Mid$(string2, j, 1) Then
                num(i, j) = num(i - 1, j - 1) + 1
            Else
                num(i, j) = max(num(i - 1, j), num(i, j - 1))
            End If
        Next j
    Next i

    longestCommonSubsequence = num
End Function

Sub exampleString()

    Dim arr() As Long

    Dim string1 As String
    Dim string2 As String

    string1 = &amp;quot;this is a find the haystack string&amp;quot;
    string2 = &amp;quot;this is a replace the needle string&amp;quot;

    arr = longestCommonSubsequence(string1, string2)

    Dim s As String, t As String
    s = backTraceUp(arr, string1, string2, Len(string1), Len(string2))
    t = backTraceLeft(arr, string1, string2, Len(string1), Len(string2))
    Dim a As String, b As String
    a = getDiff(arr, string1, string2, Len(string1), Len(string2))

    Dim brr() As Long

    brr = passGetDiffOutput(a)
End Sub

Public Function max(ByRef a As Long, ByRef b As Long) As Long
    If a &amp;gt;= b Then
        max = a
    Else
        max = b
    End If
End Function

'back traces c, defaulting in the up direction
Public Function backTraceUp(ByRef c() As Long, ByRef string1 As String, ByRef string2 As String, ByRef i As Long, ByRef j As Long) As String
    If i &amp;lt; 1 Or j &amp;lt; 1 Then
        backTraceUp = vbNullString
    ElseIf Mid$(string1, i, 1) = Mid$(string2, j, 1) Then
        'equal characters, save it and then go up and left
        backTraceUp = backTraceUp(c, string1, string2, i - 1, j - 1) &amp;amp; Mid$(string1, i, 1)
    Else
        'go in the direction of the highest number, defaulting to up
        If (c(i, j - 1) &amp;gt; c(i - 1, j)) Then
            backTraceUp = backTraceUp(c, string1, string2, i, j - 1)
        Else
            backTraceUp = backTraceUp(c, string1, string2, i - 1, j)
        End If
    End If
End Function

'back traces c, defaulting in the left direction
Public Function backTraceLeft(ByRef c() As Long, ByRef string1 As String, ByRef string2 As String, ByRef i As Long, ByRef j As Long) As String
    If i &amp;lt; 1 Or j &amp;lt; 1 Then
        backTraceLeft = vbNullString
    ElseIf Mid$(string1, i, 1) = Mid$(string2, j, 1) Then
        'equal characters, save it and then go up and left
        backTraceLeft = backTraceLeft(c, string1, string2, i - 1, j - 1) &amp;amp; Mid$(string1, i, 1)
    Else
        'go in the direction of the highest number, defaulting to left
        If (c(i, j - 1) &amp;gt;= c(i - 1, j)) Then
            backTraceLeft = backTraceLeft(c, string1, string2, i, j - 1)
        Else
            backTraceLeft = backTraceLeft(c, string1, string2, i - 1, j)
        End If
    End If
End Function

'the following function returns a string with indication to what was deleted or added
'proceding character can be;
' = no change
' - deletion
' + addition
Public Function getDiff(ByRef c() As Long, ByRef stringOld As String, ByRef stringNew As String, ByRef i As Long, ByRef j As Long) As String
    If i &amp;gt; 0 Then
        If j &amp;gt; 0 Then 'both are greater than zero
            'can only do the following comparison when i and j are greater than zero
            If Mid$(stringOld, i, 1) = Mid$(stringNew, j, 1) Then
                getDiff = getDiff(c, stringOld, stringNew, i - 1, j - 1) &amp;amp; Mid$(stringOld, i, 1) &amp;amp; &amp;quot;=&amp;quot;
            Else
                If i = 0 Then
                    getDiff = getDiff(c, stringOld, stringNew, i, j - 1) &amp;amp; Mid$(stringNew, j, 1) &amp;amp; &amp;quot;+&amp;quot;
                ElseIf c(i, j - 1) &amp;gt;= c(i - 1, j) Then
                    getDiff = getDiff(c, stringOld, stringNew, i, j - 1) &amp;amp; Mid$(stringNew, j, 1) &amp;amp; &amp;quot;+&amp;quot;
                ElseIf j = 0 Then
                    getDiff = getDiff(c, stringOld, stringNew, i - 1, j) &amp;amp; Mid$(stringOld, i, 1) &amp;amp; &amp;quot;-&amp;quot;
                ElseIf c(i, j - 1) &amp;lt; c(i - 1, j) Then
                    getDiff = getDiff(c, stringOld, stringNew, i - 1, j) &amp;amp; Mid$(stringOld, i, 1) &amp;amp; &amp;quot;-&amp;quot;
                Else
                    getDiff = vbNullString
                End If
            End If
        Else 'i is is greater than zero
                If j = 0 Then
                    getDiff = getDiff(c, stringOld, stringNew, i - 1, j) &amp;amp; Mid$(stringOld, i, 1) &amp;amp; &amp;quot;-&amp;quot;
                ElseIf c(i, j - 1) &amp;lt; c(i - 1, j) Then
                    getDiff = getDiff(c, stringOld, stringNew, i - 1, j) &amp;amp; Mid$(stringOld, i, 1) &amp;amp; &amp;quot;-&amp;quot;
                Else
                    getDiff = vbNullString
                End If
        End If
    Else
        If j &amp;gt; 0 Then 'j is  greater than zero
                If i = 0 Then
                    getDiff = getDiff(c, stringOld, stringNew, i, j - 1) &amp;amp; Mid$(stringNew, j, 1) &amp;amp; &amp;quot;+&amp;quot;
                ElseIf c(i, j - 1) &amp;gt;= c(i - 1, j) Then
                    getDiff = getDiff(c, stringOld, stringNew, i, j - 1) &amp;amp; Mid$(stringNew, j, 1) &amp;amp; &amp;quot;+&amp;quot;
                Else
                    getDiff = vbNullString
                End If
        Else 'none are greater than zero
                getDiff = vbNullString
        End If
    End If
End Function

'this function returns the location of the string difference
Public Function passGetDiffOutput(ByRef outputStr As String) As Long()
    Dim i As Long
    i = 1

    Dim typeChr As String

    Dim oldi As Long
    Dim newi As Long
    oldi = 0
    newi = 0

    Dim toFrom() As Long
    Dim toFromCount As Long
    toFromCount = -1

    Dim typeChrPrev As String
    typeChrPrev = vbNullString

    Do While i &amp;lt; Len(outputStr)
        typeChr = Mid$(outputStr, i + 1, 1)
        Select Case typeChr
            Case &amp;quot;=&amp;quot;
                If typeChr &amp;lt;&amp;gt; typeChrPrev Then

                    'check if it is comming from a deletion
                    If typeChrPrev = &amp;quot;-&amp;quot; Then
                        toFrom(2, toFromCount) = oldi
                    End If

                    'check if it is comming from a addition
                    If typeChrPrev = &amp;quot;+&amp;quot; Then
                        toFrom(2, toFromCount) = newi
                    End If
                End If

                oldi = oldi + 1 'update old index
                newi = newi + 1 'update new index
            Case &amp;quot;-&amp;quot;
                'check if it is comming from a addition
                If typeChrPrev = &amp;quot;+&amp;quot; Then
                    toFrom(2, toFromCount) = newi
                End If

                oldi = oldi + 1 'update old index
                If typeChr &amp;lt;&amp;gt; typeChrPrev Then
                    toFromCount = toFromCount + 1
                    ReDim Preserve toFrom(2, toFromCount)
                    'let old be -1
                    toFrom(0, toFromCount) = -1
                    toFrom(1, toFromCount) = oldi
                End If
            Case &amp;quot;+&amp;quot;
                'check if it is comming from a deletion
                If typeChrPrev = &amp;quot;-&amp;quot; Then
                    toFrom(2, toFromCount) = oldi
                End If

                newi = newi + 1 'update new index
                If typeChr &amp;lt;&amp;gt; typeChrPrev Then
                    toFromCount = toFromCount + 1
                    ReDim Preserve toFrom(2, toFromCount)
                    'let new be 1
                    toFrom(0, toFromCount) = 1
                    toFrom(1, toFromCount) = newi
                End If
        End Select

        i = i + 2
        typeChrPrev = typeChr
    Loop

    'check if it ended on a deletion or adition
    If typeChrPrev = &amp;quot;-&amp;quot; Then
        toFrom(2, toFromCount) = oldi
    End If

    If typeChrPrev = &amp;quot;+&amp;quot; Then
        toFrom(2, toFromCount) = newi
    End If

    passGetDiffOutput = toFrom
End Function

'note, arrays must be single dimension
Public Function longestCommonSubsequenceArr(ByRef array1() As String, ByRef array2() As String) As Long()
    On Error Resume Next
    If UBound(array1, 2) &amp;gt; 0 Or UBound(array2, 2) &amp;gt; 0 Then 'multidimensional arrays
        If Error = vbNullString Then
            Exit Function
        End If
    End If

    If UBound(array1) &amp;lt; 0 Or UBound(array2) &amp;lt; 0 Then 'check if arrays are bounded
        If Error &amp;lt;&amp;gt; vbNullString Then
            Exit Function
        End If
    End If

    Dim num() As Long

    'define the array, note rows of zeros get added to front automatically
    ReDim num(UBound(array1) + 1, UBound(array2) + 1)

    Dim i As Long, j As Long

    'note, arrays must always start at indice zero.
    For i = 0 To UBound(array1)
        For j = 0 To UBound(array2)
            If array1(i) = array2(j) Then
                num(i + 1, j + 1) = num(i, j) + 1
            Else
                num(i + 1, j + 1) = max(num(i, j + 1), num(i + 1, j))
            End If
        Next j
    Next i

    longestCommonSubsequenceArr = num
End Function

Public Function stringToArray(ByRef str As String) As String()
    Dim i As Long
    Dim arr() As String
    ReDim arr(Len(str) - 1)
    For i = 1 To Len(str)
        arr(i - 1) = Mid$(str, i, 1)
    Next i
    stringToArray = arr
End Function

Sub exampleArr()

    Dim string1 As String
    Dim string2 As String

    string1 = &amp;quot;this is a find the haystack string&amp;quot;
    string2 = &amp;quot;this is a replace the needle string&amp;quot;

    Dim a1() As String
    Dim a2() As String

    a1 = stringToArray(string1)
    a2 = stringToArray(string2)

    Dim c() As Long

    c = longestCommonSubsequenceArr(a1, a2)

    Dim str() As String

    str = backTraceUpArr(c, a1, a2, UBound(a1), UBound(a2))

    Dim dif() As String
    dif = getDiffArr(c, a1, a2, UBound(a1), UBound(a2))

End Sub

'back traces c, defaulting in the up direction
Public Function backTraceUpArr(ByRef c() As Long, ByRef array1() As String, ByRef array2() As String, ByRef i As Long, ByRef j As Long) As String()
    Dim arr() As String
    If i &amp;lt; 0 Or j &amp;lt; 0 Then
        backTraceUpArr = arr
    ElseIf array1(i) = array2(j) Then
        'equal characters, save it and then go up and left
        arr = backTraceUpArr(c, array1, array2, i - 1, j - 1)
        'check the bounding of arr
        Dim bound As Long
        On Error Resume Next
        bound = UBound(arr)
        If Error &amp;lt;&amp;gt; vbNullString Then
            ReDim arr(0)
            arr(0) = array1(i)
        Else 'no error
            ReDim Preserve arr(bound + 1)
            arr(bound + 1) = array1(i)
        End If
        backTraceUpArr = arr
    Else
        'go in the direction of the highest number, defaulting to up
        If (c(i + 1, j) &amp;gt; c(i, j + 1)) Then
            backTraceUpArr = backTraceUpArr(c, array1, array2, i, j - 1)
        Else
            backTraceUpArr = backTraceUpArr(c, array1, array2, i - 1, j)
        End If
    End If
End Function

'returns a 2xn array, where
'indice 0 are equal
'indice 1 are deletions
'indice 2 are additions
Public Function getDiffArr(ByRef c() As Long, ByRef arrayOld() As String, ByRef arrayNew() As String, ByRef i As Long, ByRef j As Long) As String()
    Dim arr() As String
    Dim bound As Long
    On Error Resume Next
    If i &amp;gt;= 0 Then
        If j &amp;gt;= 0 Then 'both are greater or equal to zero
            'can only do the following comparison when i and j are greater or equal than zero
            If arrayOld(i) = arrayNew(j) Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i - 1, j - 1)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(0, 0) = arrayOld(i)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(0, bound + 1) = arrayOld(i)
                    End If
                    getDiffArr = arr
            Else
                If i = 0 Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i, j - 1)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(2, 0) = arrayNew(j)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(2, bound + 1) = arrayNew(j)
                    End If
                    getDiffArr = arr
                ElseIf c(i + 1, j - 1 + 1) &amp;gt;= c(i - 1 + 1, j + 1) Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i, j - 1)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(2, 0) = arrayNew(j)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(2, bound + 1) = arrayNew(j)
                    End If
                    getDiffArr = arr
                ElseIf j = 0 Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i - 1, j)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(1, 0) = arrayOld(i)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(1, bound + 1) = arrayOld(i)
                    End If
                    getDiffArr = arr
                ElseIf c(i + 1, j - 1 + 1) &amp;lt; c(i - 1 + 1, j + 1) Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i - 1, j)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(1, 0) = arrayOld(i)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(1, bound + 1) = arrayOld(i)
                    End If
                    getDiffArr = arr
                Else
                    getDiffArr = arr
                End If
            End If
        Else 'i is is greater or equal to zero
                If j = 0 Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i - 1, j)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(1, 0) = arrayOld(i)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(1, bound + 1) = arrayOld(i)
                    End If
                    getDiffArr = arr
                ElseIf c(i + 1, j - 1 + 1) &amp;lt; c(i - 1 + 1, j + 1) Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i - 1, j)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(1, 0) = arrayOld(i)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(1, bound + 1) = arrayOld(i)
                    End If
                    getDiffArr = arr
                Else
                    getDiffArr = arr
                End If
        End If
    Else
        If j &amp;gt;= 0 Then 'j is  greater than zero
                If i = 0 Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i - 1, j)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(2, 0) = arrayNew(j)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(2, bound + 1) = arrayNew(j)
                    End If
                    getDiffArr = arr
                ElseIf c(i + 1, j - 1 + 1) &amp;gt;= c(i - 1 + 1, j + 1) Then
                    arr = getDiffArr(c, arrayOld, arrayNew, i, j - 1)
                    bound = UBound(arr, 2) 'check the bounding of arr
                    If Error &amp;lt;&amp;gt; vbNullString Then
                        Err.Clear
                        ReDim arr(2, 0)
                        arr(2, 0) = arrayNew(j)
                    Else 'no error
                        ReDim Preserve arr(2, bound + 1)
                        arr(2, bound + 1) = arrayNew(j)
                    End If
                    getDiffArr = arr
                Else
                    getDiffArr = arr
                End If
        Else 'none are greater than zero
                getDiffArr = arr
        End If
    End If
End Function
</pre>
<div class="addthis_toolbox addthis_default_style addthis_" addthis:url='http://thydzik.com/longest-common-subsequence-implemented-in-vba-visual-basic-for-applications/' addthis:title='Longest Common Subsequence implemented in VBA (Visual Basic for Applications) ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://thydzik.com/longest-common-subsequence-implemented-in-vba-visual-basic-for-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced
Object Caching 1436/1524 objects using disk: basic
Content Delivery Network via t01.thydzik.com

Served from: thydzik.com @ 2012-02-10 20:38:02 -->
