Splitters!

A recent post on the Tek-Tips VBA forum reminded me that VBA has a split function, which will split a string into sub-strings at any specified character (such as a space).  D’oh I thought, why did I waste my time writing my own split function when it is there in VBA already?  Then I remembered that if the string has multiple consecutive split characters (such as two or more consecutive spaces) the VBA split function will treat each of these as a separate sub-string, which is not normally what we want.

Writing a split function from scratch is one way around this problem, but the Microsoft on line documentation for VB gives an alternative.  The suggested code here uses the VB split function, then copies each non-blank member of the resulting array to a new array.  This works well if you want to split entire lines of text, but if you want to split only some of the text, and return the remainder as a single string, then this approach will not work.  To avoid this problem I wrote the code shown below, which removes all duplicate instances of the separator string, then uses the VBA split function on the resulting string.

Function SplitText2(Texta As Variant, Optional NumCols As Long = -1, Optional Separator As Variant = " ") As Variant
Dim NumLines As Long, i As Long, j As Long, Linea As Variant, Numwords As Long
Dim MaxWords As Long, SplitString As String, SplitString2 As String, LenString As Long, SplitCount As Long, NextChar As String
Dim AddChar As String, MaxCols As String</code>

If LCase(Separator) = "tab" Then Separator = Chr(9)
If Val(Separator) &gt; 0 Then Separator = Chr(CLng(Separator))

Texta = GetArray(Texta)
NumLines = UBound(Texta) - LBound(Texta) + 1
If NumCols = -1 Then MaxCols = 10 Else MaxCols = NumCols
ReDim Preserve Texta(1 To NumLines, 1 To MaxCols)

For i = 1 To NumLines
' Remove 2nd and subsequent consecutive separator characters
SplitString2 = ""
SplitString = Texta(i, 1)
LenString = Len(SplitString)
SplitCount = 0
For j = 1 To LenString
NextChar = Mid(SplitString, j, 1)
If NextChar = Separator Then
If SplitCount = 0 Then
SplitCount = 1
AddChar = NextChar
Else
AddChar = ""
End If
Else
AddChar = NextChar
SplitCount = 0
End If
SplitString2 = SplitString2 &amp; AddChar
Next j

'Split text
Linea = Split(SplitString2, Separator, NumCols)

' Add Linea to Texta
Numwords = UBound(Linea) - LBound(Linea) + 1
If Numwords &gt; MaxWords Then
MaxWords = Numwords
ReDim Preserve Texta(1 To NumLines, 1 To Numwords)
End If

For j = 0 To Numwords - 1
Texta(i, j + 1) = Linea(j)
Next j
Next i

SplitText2 = Texta
End Function
Function SplitText2(Texta As Variant, Optional NumCols As Long = -1, Optional Separator As Variant = " ") As Variant
Dim NumLines As Long, i As Long, j As Long, Linea As Variant, Numwords As Long
Dim MaxWords As Long, SplitString As String, SplitString2 As String, LenString As Long, SplitCount As Long, NextChar As String
Dim AddChar As String, MaxCols As String

If LCase(Separator) = "tab" Then Separator = Chr(9)
If Val(Separator) &gt; 0 Then Separator = Chr(CLng(Separator))

Texta = GetArray(Texta)
NumLines = UBound(Texta) - LBound(Texta) + 1
If NumCols = -1 Then MaxCols = 10 Else MaxCols = NumCols
ReDim Preserve Texta(1 To NumLines, 1 To MaxCols)

For i = 1 To NumLines
' Remove 2nd and subsequent consecutive separator characters
SplitString2 = ""
SplitString = Texta(i, 1)
LenString = Len(SplitString)
SplitCount = 0
For j = 1 To LenString
NextChar = Mid(SplitString, j, 1)
If NextChar = Separator Then
If SplitCount = 0 Then
SplitCount = 1
AddChar = NextChar
Else
AddChar = ""
End If
Else
AddChar = NextChar
SplitCount = 0
End If
SplitString2 = SplitString2 &amp; AddChar
Next j

'Split text
Linea = Split(SplitString2, Separator, NumCols)

' Add Linea to Texta
Numwords = UBound(Linea) - LBound(Linea) + 1
If Numwords &gt; MaxWords Then
MaxWords = Numwords
ReDim Preserve Texta(1 To NumLines, 1 To Numwords)
End If

For j = 0 To Numwords - 1
Texta(i, j + 1) = Linea(j)
Next j
Next i

SplitText2 = Texta
End Function

Note that this function lacks a couple of features found in my earlier Split function, but it does have the virtue of simplicity.

Posted in Excel, UDFs, VBA | Tagged , , | Leave a comment

Frame Analysis with Excel – 5; Large frames in Excel 2003

Continuing from: Frame Analysis with Excel – 4, 2D frame analysis

Download Frame2.zip – the download file includes complete open source code.

The solution presented in the previous post in this series made use of the Excel built in functions MINVERSE() and MMULT(), which restricted the size of problem that could be handled, especially in versions earlier than 2007.  These functions have now been replaced with a VBA Gaussian Elimination routine, and the matrices are no longer written back to the spreadsheet, so frames with more than 250 degrees of freedom can now be tackled.  There is still plenty of scope for improving the efficiency of the solution routine, but nonetheless the present system is adequate for quite large frames, so for the next few posts I will concentrate on improving the functionality:

  • Provision for moment and translational release of member ends
  • Output of member actions at nodes or intermediate points
  • Addition of graphics
Posted in Excel, Frame Analysis, Newton, VBA | Tagged , , , | 5 Comments

Importing tab delimited files and clearing large ranges

Wray Sisk commented on Importing text files with VBA – 3, asking if it could be modified to read tab delimited files.

It could be, and has been; download here: Text-in2.ZIP

It turned out to be a simple task; just the addition of one line to the splittext() function:

 If LCase(Separator) = “tab” Then Separator = Chr(9)

To allow the use of other non displaying characters, and also so the code for tab (9) could be used instead of “tab” I also added:

If Val(Separator) > 0 Then Separator = Chr(CLng(Separator))

and changed the data type of separator from string to variant.

Whilst changing the spreadsheet I noticed that I had commented in the post about the very slow performance of Excel 2007 in clearing large ranges.  There is a solution to this one, the slow down is associated with the Google Desktop COM add-in,  and if you de-activate this the problem goes away.  More details from Charles Williams here: Google Toolbar Slows Excel

Posted in Excel, UDFs, VBA | Tagged , , , , , | 2 Comments

You can’t count on money

An interesting bug is reported at Daily Dose of Excel:
Code snipit to test

If you use a variable of data type currency as a counter in VBA you get some very strange behaviour.  The function below returns the result of counting between the specified limits:
Function CheckCurrency(startval, endval)
Dim c As Currency

For c = startval To endval
Next c

CheckCurrency = c

End Function

The function should return a value one greater than “endval”, but the screen shot below shows the results of using currency as a counter:

currency

Just to prove it is the currency data type causing the problem, here are the results of the same function, with the counter changed to a long:

currency1

The message is, don’t count on currency.

Posted in Excel, VBA | Leave a comment

Happy Birthday Newton Excel Bach

Newton Excel Bach is one year old today.   To mark the occasion I have downloaded the statistics for number of hits on each post, and pasted them into an Excel worksheet.  The link to each post is preserved in the spreadsheet, so it makes a convenient index to what has been posted over the year, which can be downloaded here.

The top end of the list is shown in the screen shot below:

First Year Statistics

Firts Year Statistics

 

It’s interesting that the posts covering importing of text files are by far the most popular, and a good proportion of the people reading these posts were directed here from a comment on a Daily Dose of Excel post which is about 4 years old.  Clearly many people have an issue with the built in methods of importing text files in Excel.

At the other end of the table, the least popular post was alice through the looking-glass, or how to shake hands with an alien , which I think was a bit of a shame, so you can all click on the link and read it now 🙂

Posted in Bach, Computing - general, Excel, Newton | 3 Comments