How to quickly determine if part of a string matches another string? - excel

I have address lists that sometimes have junk at the end of the street suffix that needs to be removed. For example Yada Yada St. apt#12 needs to become Yada Yada St. Now, I have found a list of street suffixes and their variations from here. I need to do this all in excel so I put the 3 column list of suffixes (columns 1-3 being Primary Street Suffix, Commonly Used Street Suffix or Abbreviation, and Postal Service Standard Suffix Abbreviation respectively) into a worksheet labeled SuffixList and I put the address list into sheet 1 which is where the code is.
I created a code to check each address against each suffix variation (column 2 on SuffixList) using a space before and after the suffix I'm checking to make sure I'm not catching any street names, just the street suffixes. I also have the . and , variations being checked in the code as you can see below. The code I'm using now works, it just takes too long and I'm looking for a faster method.
Also, any time I find a match, I am replacing the street suffix used with the officially correct one (column 3 on suffix list).
Current Code:
Sub JunkRemover()
'Link to an official abbreviations list
'https://www.usps.com/send/official-abbreviations.htm
Dim Orig As String
Dim NewAddr As String
Dim x As Integer 'Row Reference
Dim i As Long 'Address List Iterator
Dim y As Integer 'SuffixList Iterator
Dim ChangeCount As Integer
'WARNING!!!!!!!!!!!!
'This code assumes address field is in column A and that the address column has no blanks.
'If that is not the case, replace 1 for the appropriate number for x
'a=1, b=2, c=3, d=4 etc.
x = 1
ChangeCount = 0
i = 2
While Cells(i, x) <> ""
Orig = UCase(Cells(i, x))
y = 2
While Sheets("SuffixList").Cells(y, 2) <> ""
If InStr(1, Orig, " " & UCase(Sheets("SuffixList").Cells(y, 2) & " ")) > 1 Then
NewAddr = Left(Orig, InStr(1, Orig, " " & UCase(Sheets("SuffixList").Cells(y, 3) & " ")) + Len(Sheets("SuffixList").Cells(y, 3)))
Cells(i, x) = NewAddr
ChangeCount = ChangeCount + 1
ElseIf InStr(1, Orig, " " & UCase(Sheets("SuffixList").Cells(y, 2) & ". ")) > 1 Then
NewAddr = Left(Orig, InStr(1, Orig, " " & UCase(Sheets("SuffixList").Cells(y, 3) & ". ")) + Len(Sheets("SuffixList").Cells(y, 3)))
Cells(i, x) = NewAddr
ChangeCount = ChangeCount + 1
ElseIf InStr(1, Orig, " " & UCase(Sheets("SuffixList").Cells(y, 2) & ", ")) > 1 Then
NewAddr = Left(Orig, InStr(1, Orig, " " & UCase(Sheets("SuffixList").Cells(y, 3) & ", ")) + Len(Sheets("SuffixList").Cells(y, 3)))
Cells(i, x) = NewAddr
ChangeCount = ChangeCount + 1
End If
y = y + 1
Wend
i = i + 1
Wend
MsgBox ChangeCount & " Rows Changed", vbOKOnly
End Sub
Further Examples:
OrigAddress NewAddress
4000 NO MAIN ST 1 4000 NO MAIN ST
135 ALDEN ST APT3 135 ALDEN ST
1820 HIGHLAND AVE 1820 HIGHLAND AVE
4901 NO MAIN ST. REAR 4901 NO MAIN ST
1820 HIGHLAND AVE, 1 1820 HIGHLAND AVE
Final Code users Potter's answer:
Sub JunkRemover2()
'Link to an official abbreviations list
'https://www.usps.com/send/official-abbreviations.htm
Dim Orig As String
Dim NewAddr As String
Dim x As Integer 'Row Reference
Dim i As Long 'Address List Iterator
Dim y As Integer 'SuffixList Iterator
Dim ChangeCount As Integer
Dim PauseTime, Start, Finish, TotalTime As Double
Dim slRows As Double
Dim slCols As Integer
Dim slRowsAddr As Double
Dim slColsAddr As Integer
'WARNING!!!!!!!!!!!!
'This code assumes address field is in column A and that the address column has no blanks.
'If that is not the case, replace 1 for the appropriate number for x
'a=1, b=2, c=3, d=4 etc.
x = 1
ChangeCount = 0
With Sheets("SuffixList")
'i am using Column 1 to find out how many rows there are(change it if you want)
slRows = Sheets("SuffixList").Cells(Rows.Count, 1).End(xlUp).Row
slCols = Sheets("SuffixList").Cells(1, Columns.Count).End(xlToLeft).Column
suffixData = Sheets("SuffixList").Range(Sheets("SuffixList").Cells(2, 2), Sheets("SuffixList").Cells(slRows, slCols))
End With
i = 2
While Cells(i, x) <> ""
Orig = UCase(Cells(i, x))
For y = 1 To slRows - 1
If InStr(1, Orig, " " & UCase(suffixData(y, 1) & " ")) > 1 Then
NewAddr = Left(Orig, InStr(1, Orig, " " & UCase(suffixData(y, 2) & " ")) + Len(suffixData(y, 2)))
Cells(i, x) = NewAddr
ChangeCount = ChangeCount + 1
Exit For
ElseIf InStr(1, Orig, " " & UCase(suffixData(y, 1) & ". ")) > 1 Then
NewAddr = Left(Orig, InStr(1, Orig, " " & UCase(suffixData(y, 2) & ". ")) + Len(suffixData(y, 2)))
Cells(i, x) = NewAddr
ChangeCount = ChangeCount + 1
Exit For
ElseIf InStr(1, Orig, " " & UCase(suffixData(y, 1) & ", ")) > 1 Then
NewAddr = Left(Orig, InStr(1, Orig, " " & UCase(suffixData(y, 2) & ", ")) + Len(suffixData(y, 2)))
Cells(i, x) = NewAddr
ChangeCount = ChangeCount + 1
Exit For
End If
Next
i = i + 1
Wend
MsgBox ChangeCount & " Rows Changed", vbOKOnly
End Sub

You're right; it is slow because every time you compare stuff you access the Excel application, which is considerably slower than just accessing, say, a variable.
I would suggest you copy the relevant fields you want to arrays like so:
dim suffixData as variant
'Now you need to save all that sheets' content into an array
'1stly you need the sheet's dimentions
dim slRows as double
dim slCols as integer
'I am using Column 1 to find out how many rows there are(change it if you want)
with Sheets("SuffixList")
slRows = .Cells(rows.count, 1).end(xlUp).row
slCols = .Cells(1, columns.count).end(xlToLeft).column
suffixData = .Range(.cells(1,1), .cells(slRows, slCols))
end with
From here onwards you should use suffixData(row, column) to access that sheet as if it was the actual sheet. On a thousand+ iterations on it you will see a definite improvements.
You can do the same trick with the other sheets and calculate everything without even looking up Excel while you do your costly loops.
The reverse is also advisable. You don't want to write to a cell each time you have its value.
It's much better to write it to a 2D array as if it was the spreadsheet and then copy the entire array to the sheet.

Related

VBA Code: How to parse out each First, Middle, and Last names from an input function and then using that to count the characters

I am very confused on where I am at right now. But I need to parse/separate out the first, middle, and last name of a input function. Then display the number of characters that is in that entire name minus the spaces as well as display the number of characters in users first and last names minus the spaces.
ex: Matt Lose Wright has 15 Characters
Matt Wright has 10 Characters
I am trying
My Code:
Sub ParseName()
Dim name As String
name = InputBox("Enter First Name, Middle Name, and Last Name")
Dim First As Double
Dim Middle As Double
Dim Last As Double
First = InStr(1, name, "First", vbTextCompare)
Middle = InStr(2, name, "Middle", vbTextCompare)
Last = InStr(3, name, "Last", vbTextCompare)
Dim Count As Integer
Dim Cell As Object
Dim n As Integer
Count = 0
name = InputBox("Enter First Name, Middle Name, and Last Name")
If name = "" Then
For Each Cell In Selection
n = InStr(1, Cell.Value, name)
While n <> 0
Count = Count + 1
n = InStr(n + 1, Cell.Value, name)
Wend
Next Cell
MsgBox Count & " Occurrences of " & name
End If
End Sub
To summarise - I have shown you three techniques.
A = "Matt Lose Wright"
B = Split(A, " ")
MsgBox Len(Replace(A, " ", ""))
For Each name in B
MsgBox Name & " " & Len(Name)
Next
MsgBox B(0) & " " & B(UBound(B)) & " " & Len(B(0)) & " " & Len(B(UBound(B)))
Output
14
Matt 4
Lose 4
Wright 6
Matt Wright 4 6
See Split, your friend when parsing - https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/split-function
A = "Matt Lose Win Wright"
B = Split(A, " ")
MsgBox Len(Replace(A, " ", ""))
For Each name in B
MsgBox Name & " " & Len(Name)
Next
MsgBox B(0) & " " & B(UBound(B)) & " " & Len(B(0)) & " " & Len(B(UBound(B)))
Output
17
Matt 4
Lose 4
Win 3
Wright 6
Matt Wright 4 6

Delete last 3 characters if they are equal to something

(without affecting the char level formatting in the cell)
I've already posted a similar question, but I unfortunately I realized I couldn't use any of the solutions because all of them removed all the formatting in the cells :(
I have a code that replaces various text strings. It looks like this (+ some more IFs):
Sub Fix()
Dim X As Long, Cell As Range
For Each Cell In Selection
For X = Len(Cell.Text) To 1 Step -1
If Cell.Characters(X, 3).Text = ", ," Then Cell.Characters(X, 3).Text = ","
If Cell.Characters(X, 3).Text = ", (" Then Cell.Characters(X, 3).Text = " ("
If Cell.Characters(X, 3).Text = ", [" Then Cell.Characters(X, 3).Text = " ["
If Cell.Characters(X, 3).Text = ", -" Then Cell.Characters(X, 3).Text = " -"
If Cell.Characters(1, 3).Text = "abc" Then Cell.Characters(1, 3).Text = ""
Next
Next
End Sub
The last line of my code deletes abc if this is contained at the beginning of the selected cell(s).
I am looking to find out how to delete abc when this is contained at the end of the selected cell(s).
But it's really important for me to preserve all the original formatting in the cells (text size, colors, bold/italic/underline letters etc).
Please bear in mind that I am a complete beginner and I don't know anything about programming. I've copied the code above from the internet and just changed the values.
Thank you in advance for your help.
Replace Characters (Preserve Formatting)
Option Explicit
Sub FixIt()
Const NoC As Long = 3
Const Special As String = "abc"
Dim Source As Variant: Source = Array(", ,", ", (", ", [", ", -")
Dim Target As Variant: Target = Array(",", " (", " [", " -")
Dim Cell As Range
Dim UB As Long: UB = UBound(Source)
Dim i As Long, x As Long
Dim Current As String
For Each Cell In Selection
Current = Cell.Characters(Len(Cell.Text) - NoC + 1, NoC).Text
If Current = Special Then _
Cell.Characters(Len(Cell.Text) - NoC + 1, NoC).Delete
For x = Len(Cell.Text) - NoC + 1 To 1 Step -1
GoSub replaceCurrent
Next
Next
Exit Sub
replaceCurrent:
Current = Cell.Characters(x, NoC).Text
For i = 0 To UB
If Current = Source(i) Then Current = Target(i): Exit For
Next
If i <= UB Then Cell.Characters(x, NoC).Text = Current
Return
End Sub
If you want to remove the last three characters of a cell if they are abc, then:
Before:
the code:
Sub EasyAsABC()
Dim s As String, L As Long
With ActiveCell
s = .Text
L = Len(s)
If Right(s, 3) = "abc" Then
.Characters(L, 1).Text = ""
.Characters(L - 1, 1).Text = ""
.Characters(L - 2, 1).Text = ""
End If
End With
End Sub
and after:
Something like this would probably work:
Sub FixData()
Dim X As Long, Y As Long, Cell As Range, FindChars As Variant, ReplaceChars As Variant, StartRemove As Variant, EndRemove As Variant
FindChars = Array(", ,", ", (", ", [", ", -") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
ReplaceChars = Array(",", " (", " [", " -") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
StartRemove = Array("something1", "somthingelse1") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
EndRemove = Array("something2", "somthingelse2") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
For Each Cell In Selection
For Y = LBound(FindChars) To UBound(FindChars)
If InStr(1, Cell.Text, FindChars(Y)) > 0 Then Cell.Characters(InStr(1, Cell.Text, FindChars(Y)), Len(FindChars(Y))).Delete
Next
For Y = LBound(StartRemove) To UBound(StartRemove)
If Left(Cell.Text, Len(StartRemove(Y))) = StartRemove Then Cell.Characters(1, Len(StartRemove(Y))).Delete
Next
For Y = LBound(EndRemove) To UBound(EndRemove)
If Right(Cell.Text, Len(EndRemove(Y))) = EndRemove Then Cell.Characters(Len(Cell) - Len(EndRemove(Y)) + 1, Len(EndRemove(Y))).Delete
Next
Next
End Sub
Edit based on conversations since and updates to reflect these conversations.
This code has 4 arrays, it rips through the find and replace arrays first to find and replace any instance. Then it goes through the start array to find only things at the start then lastly it loops the end array to find anything at the end of the string.
Using cell.characters().delete will remove those chars without altering the individual character formatting around it.
Since all your strings are length of 3, you simply need to adjust your loop:
For X = Len(Cell.Text) - 2 To 1 Step -1
Just add a line like:
If Cell.Characters(X, 3).Text = "abc" Then Cell.Characters(X, 3).Text = ""
That would make your last line loking for abc redundant and can be removed. However, it seems you could also use some other construct alltogether if you like too, possibly:
Sub Fixt()
Dim X As Long, Cell As Range
Dim arr1 As Variant: arr1 = Array("abc", ", ,", ", (", ", [", ", -")
Dim arr2 As Variant: arr2 = Array("", ",", " (", ", [", " -")
For Each Cell In Selection
For X = Len(Cell.Text) - 2 To 1 Step -1
Match = Application.Match(Cell.Characters(X, 3).Text, arr1, 0)
If IsNumeric(Match) Then Cell.Characters(X, 3).Text = arr2(Match - 1)
Next
Next
End Sub
Try,
Sub test()
Dim rngDB As Range, rng As Range
Dim i As Integer, x As Integer
Dim vWhat As Variant, vReplace As Variant
Dim s As String
Set rngDB = Selection
vWhat = Array("abc", ", ,", ", (", ", [", ", -")
vReplace = Array("", ",", " (", " [", " -")
For Each rng In rngDB
x = Len(rng) - 2
s = rng
If x > 0 Then
For i = 0 To UBound(vWhat)
If Mid(s, x, 3) = vWhat(i) Then
rng.Characters(x, 3).Text = vReplace(i)
End If
Next i
End If
Next rng
End Sub

Universal VBA Word Count for Excel

I was trying to create a universal, error resistant VBA code that would count words in selected ranges as MS Word does. This below is the best I could do and I was hoping that somebody would have a look and let me know if I missed something or suggest any improvements. The code is quite fast and works with single cell, non-adjacent cells and whole columns, I need it to be as universal as possible. I'll be looking forward to feedback.
Option Explicit
Sub word_count()
Dim r() As Variant 'array
Dim c As Long 'total counter
Dim i As Long
Dim l As Long 'string lenght
Dim c_ch As Long 'character counter
Dim c_s As String 'string variable
Dim cell As range
Dim rng As range
If Selection Is Nothing Then
MsgBox "Sorry, you need to select a cell/range first", vbCritical
Exit Sub
ElseIf InStr(1, Selection.Address, ":", vbTextCompare) = 0 And InStr(1, Selection.Address, ",", vbTextCompare) = 0 Then 'for when only one cell is selected
word_count_f Selection.Value, c
MsgBox "Your selected cell '" & Replace(Selection.Address, "$", "") & "' in '" & Selection.Parent.Name & "' has " & c & " words."
Exit Sub
ElseIf InStr(1, Selection.Address, ",", vbTextCompare) > 0 Then 'when user selects more than one cell by clicking one by one -> address looks like ('A1,A2,A3') etc
Application.ScreenUpdating = False
Dim help() As Variant
ReDim help(1 To Selection.Cells.Count)
i = 1
For Each cell In Selection 'loading straigh to array wouldn't work, so I create a helper array
help(i) = cell.Value
i = i + 1
Next cell
r = help
Else 'load selection to array to improve speed
Application.ScreenUpdating = False
r = Selection.Value
End If
Dim item As Variant
For Each item In r
word_count_f item, c
Next item
MsgBox "Your selected range '" & Replace(Selection.Address, "$", "") & "' in '" & Selection.Parent.Name & "' has " & c & " words."
End Sub
Private Function word_count_f(ByVal item As Variant, ByRef c As Long)
Dim l As Long 'lenght variable
Dim c_s As String 'whole string variable
Dim c_ch As Long 'characted count variable
l = Len(item)
If l = 0 Then Exit Function
c_s = item
c_s = Trim(c_s)
Do While InStr(1, c_s, " ", vbTextCompare) > 0 'remove double spaces to improve accuracy
c_s = Replace(c_s, " ", " ")
Loop
If InStr(1, c_s, " ", vbTextCompare) = 0 And l > 0 Then 'if there was just one word in the cell
c = c + 1
ElseIf InStr(1, c_s, " ", vbTextCompare) > 0 Then 'else loop through string to count words
For c_ch = 1 To l 'loop through charactes of the string
If (Mid(c_s, c_ch, 1)) = " " Then
c = c + 1 'for each word
End If
Next c_ch
c = c + 1 'add one for the first word in cell
Else 'hopefully useless msgbox, but I wanted to be sure to inform the user correctly
MsgBox "Sorry, there was an error while processing one of the cells, the result might not be accurate", vbCritical
End If
End Function
You can achieve this in a similar way but with less code if you are interested to see?:
Sub word_count()
start_time = Timer
Dim r As Variant 'temp split array
Dim arr As Variant 'array
Dim c As Long 'total counter
If Selection Is Nothing Then
MsgBox "Sorry, you need to select a cell/range first", vbCritical
Exit Sub
Else
c = 0
For Each partial_selection In Split(Selection.Address, ",")
If Range(partial_selection).Cells.Count > 1 Then
arr = Range(partial_selection).Value
Else
Set arr = Range(partial_selection)
'single cell selected don't convert to array
End If
For Each temp_cell In arr
If Len(Trim(temp_cell)) > 0 Then
r = Split(temp_cell, " ")
For Each temp_word In r
If Len(Trim(temp_word)) > 0 Then
c = c + 1
'If the word is just a blank space don't count
End If
Next
'c = c + (UBound(r) - LBound(r) + 1)
'trimmed = Trim(temp_cell)
'c = c + 1 + (Len(trimmed) - Len(Replace(trimmed, " ", "")))
Else 'Blank cell
'Do nothing
End If
Next
Next
End If
Dim item As Variant
time_taken = Round(Timer - start_time, 3)
MsgBox "Your selected range '" & Replace(Selection.Address, "$", "") _
& "' in '" & Selection.Parent.Name & "' has " & c & " words." _
& vbNewLine & "Time Taken: " & time_taken & " secs"
Debug.Print c & " in "; time_taken; " secs"
End Sub
You could try this sort of approach? There may be the need to check for the next character to the space being another space, which would need some additions made. To detect word one as being the same as word one in the count. Also, transferring the range to an array would make it a touch faster.
Function Word_Count(rng As Excel.Range) As Long
Dim c As Excel.Range
Dim s As String
Dim l As Long
For Each c In rng.Cells
s = Trim(c.Value)
If s <> "" Then
If InStr(1, s, " ") > 0 Then
' Find number of spaces. You can use the ubound of split maybe here instead
l = l + (Len(s) - Len(Replace(s, " ", "")))
Else
End If
' Will always be 1 word
l = l + 1
End If
Next c
Word_Count = l
Set c = Nothing
End Function

VBA Do loop until 0 or ""

Below code is counting a final amount of students in a school and average amount of students in a class.
It's running the code until the user types "0".
How can I ensure that the "0 class" won't be counted as an additional class? Currently I am achieving it by subtracting -1 from B, but it's not an elegant solution - calculation is correct, but the class is still listed in final MsgBox.
Btw, if I wanted to end the loop when user is leaving the cell empty, what should I do? Simple Loop Until Zak = "" doesn't work.
Many thanks,
Sub D1()
Dim Zak As Byte
Dim B As Byte, C As Byte
Dim kzak As String
Dim ktrid
Dim trid As Byte
Dim k, l As Integer
B = 0
kzak = ""
Do
Zak = InputBox("Amount of students")
B = B + 1
kzak = kzak & Str(B) & (" class") & (" ") & _
("Students ") & Str(Zak) & Chr(10)
k = k + Zak
Loop Until Zak = 0
C = (B - 1)
l = k / C
MsgBox kzak & Chr(10) & ("At school is ") & Str(k) & (" students") & _
(", on avarage ") & Str(l) & (" in a class")
End Sub
This is a late post, but here is code to accomplish all the requirements you stated with just a few tweaks to your existing code:
Public Sub D2()
Dim Zak As String
Dim B As Integer
Dim kzak As String
Dim k As Integer
Dim l As Integer
B = 0
kzak = ""
Do
Zak = InputBox("Amount of students")
If Val(Zak) > 0 Then
B = B + 1
kzak = kzak & Str(B) & (" class") & (" ") & ("Students ") & Zak & Chr(10)
k = k + Val(Zak)
End If
Loop Until Zak = ""
If B > 0 Then
l = k / B
MsgBox kzak & Chr(10) & ("At school is ") & Str(k) & (" students") & (", on avarage ") & Str(l) & (" in a class")
End If
End Sub
Notice some of the changes I made.
First, I declared the variables more appropriately. Also, with your code k would have been a variant.
Second, I was able to remove the B - 1 hack while also assuring `B' had a value to avoid a divide by zero error.
Third, this code handles Cancel from the InputBox.
A common approach to this is to ask first, and then test with a Do While instead of a Loop Until, and then ask again. Something like this:
Zak = InputBox("Amount of students")
Do While Zak <> 0
...
...
Zak = InputBox("Amount of students")
Loop

Crazy issue with string formatting

I am running into an issue that is driving me crazy. I have two FOR loops in my macro that each have a counter to keep track of how many times a certain process was performed. The counters work great and at the end of the loop contain the correct numbers. The next thing I have to do is to format the counts into a five digit number with leading zeros. I have tried this using two different approaches (see below).
cCount = String(5 - Len(cTemp), "0") & cTemp
mCount = String(5 - Len(mTemp), "0") & mTemp
or
cCount = Format(cTemp, "00000")
mCount = Format(mTemp, "00000")
The problem is with the second counter. As I step through it, the first format formula works, but the second line does not, regardless of which version above that I use. Now here is the thing, if, while I am still in the macro, I go and change the name of mCount to anything else, for example mCnt, and then move the macro step back up to reprocess that line, it will correctly format the variable. But it isn't the name, because if I then run the macro again using mCnt, it will do the same thing. I can change it back to mCount and it will work.
All variables are dimmed as Integers. An example of what I am looking for would be if mTemp is 15, then mCount would be 00015. However, mCount is just coming back as 15. cCount is working fine.
The fact that everything is correct and that I can make it work if I pause the macro, change the variable name, and reprocess the line, has got me completely at a loss as to what the issue is.
Sub MakePay()
Dim strFileToOpen As String
Dim payDate, payTab, payCheckTemp, payCheck, payAccTemp As String
Dim payAcc, payAmount, payTotalC, payTotalM As String
Dim savePath As String
Dim payFileNameCLP, payFileNameMF As String
Dim payString1, payString2, payString3, payString4, payString5, payString6 As String
Dim payString7, payString8, payString9 As String
Dim rCnt, i, j, cTemp, cCount, mTemp, mCount As Integer
Dim payTotalMTemp, payAmountTemp, payTotalCTemp As Double
' Set date
payDate = Format(Now(), "yyyymmddhhmmss")
' Ask for check number and format to field length
payCheckTemp = InputBox("Please enter the check number.")
payCheck = payCheckTemp & String(15 - Len(payCheckTemp), " ")
' Create file names and open text files for writing
payFileNameCLP = "CLP_" & payDate & "_01.txt"
payFileNameMF = "MDF_" & payDate & "_01.txt"
savePath = Environ("USERPROFILE") & "\Desktop\"
Open savePath & payFileNameCLP For Output As #1
Open savePath & payFileNameMF For Output As #2
' Build header rows and print them
payString1 = "100"
payString2 = "200 C"
Print #1, payString1
Print #1, payString2
Print #2, payString1
Print #2, payString2
' reset counters for number of claims and total dollar amounts in files
cTemp = 0
mTemp = 0
payTotalCTemp = 0
payTotalMTemp = 0
For i = 1 To Sheets.Count
' Process the Clearpoint tab
If Left(Sheets(i).Name, 3) = "CLE" Then
Sheets(i).Activate
rCnt = Cells(Rows.Count, 1).End(xlUp).Row
For j = 3 To (rCnt - 1)
' Read accession # and format it for field length
payAccTemp = Cells(j, 3).Value
payAcc = payAccTemp & String(17 - Len(payAccTemp), " ")
' Read payment amount, if $0, skip
payAmountTemp = Format(Cells(j, 5).Value2, "#,###.00")
If payAmountTemp = "" Then
GoTo SkipCDL
End If
' Add payment to total Clearpoint payments
payTotalCTemp = payTotalCTemp + payAmountTemp
' Format payment by deleting decimal and then format to field length
payAmount = Format(payAmountTemp * 100, "0000000;-000000")
' Build payment strings and print them
payString3 = "400" & String(10, " ") & payAcc & payCheck
payString4 = "450" & String(10, " ") & payAcc & String(150, " ") & payAmount
payString5 = "500" & String(10, " ") & payAcc & String(73, " ") & payAmount
Print #1, payString3
Print #1, payString4
Print #1, payString5
' Increase Clearpoint patient count
cTemp = cTemp + 1
SkipCDL:
Next j
' Process Medfusion tab
ElseIf Left(Sheets(i).Name, 3) = "MED" Then
Sheets(i).Activate
rCnt = Cells(Rows.Count, 1).End(xlUp).Row
For j = 3 To (rCnt - 1)
' Read accession # and format it for field length
payAccTemp = Cells(j, 3).Value
payAcc = payAccTemp & String(17 - Len(payAccTemp), " ")
' Read payment amount, if $0, skip
payAmountTemp = Format(Cells(j, 5).Value2, "#,###.00")
If payAmountTemp = "" Then
GoTo SkipMDF
End If
' Add payment to total Medfusion payments
payTotalMTemp = payTotalMTemp + payAmountTemp
' Format payment by deleting decimal and then format to field length
payAmount = Format(payAmountTemp * 100, "0000000;-000000")
' Build payment strings and print them
payString3 = "400" & String(10, " ") & payAcc & payCheck
payString4 = "450" & String(10, " ") & payAcc & String(150, " ") & payAmount
payString5 = "500" & String(10, " ") & payAcc & String(73, " ") & payAmount
Print #2, payString3
Print #2, payString4
Print #2, payString5
' Increase Medfusion count
mTemp = mTemp + 1
SkipMDF:
Next j
End If
Next i
' Format patient counter and total payment to field length
cCount = Format(cTemp, "00000")
mCount = Format(mTemp, "00000")
payTotalC = Format(payTotalCTemp * 100, "000000000;-00000000")
payTotalM = Format(payTotalMTemp * 100, "000000000;-00000000")
' Build footer strings and print them
payString6 = "800" & String(26, " ") & "9999" & cCount & String(131, " ") & payTotalC
payString7 = "800" & String(26, " ") & "9999" & mCount & String(131, " ") & payTotalM
payString8 = "900" & String(57, " ") & "099990" & cCount & String(154, " ") & String(2, "0") & payTotalC
payString9 = "900" & String(57, " ") & "099990" & mCount & String(154, " ") & String(2, "0") & payTotalM
Print #1, payString6
Print #2, payString7
Print #1, payString8
Print #2, payString9
' Close all files
Application.DisplayAlerts = False
Close #1
Close #2
Application.DisplayAlerts = True
End Sub
The issue is with how the variables are declared.
In VBA/classic vb, all declarations should be on their own line OR have the correct data type specified, otherwise you risk accidentally creating a Variant data type, which can masquerade as any other data type, which the VB engine has rules for determining the type.
See https://msdn.microsoft.com/en-us/library/56ht941f(v=vs.90).aspx
Also, whenever coding in VBA make sure Option Explicit is declared at the top of any new code module. It will save you loads of pain in the future.
Also, you are trying to push String formatting into an Integer, which cannot happen.
So...
Option Explicit
.....
'Dim i, j as Integer 'BAD i is a variant, j is an integer
Dim i As Integer
Dim j As Integer 'GOOD both are Integers
'OR
Dim x As Integer, y as Integer 'I believe this will work too
dim displayI as String
i = 23
displayI = Format(i, "00000")
In your code why not just format inline?
payString6 = "800" & String(26, " ") & "9999" & Format(cCount,"00000") & String(131, " ") & payTotalC

Resources