Excel number and box issues - excel

I have an excel file full of adresses which I need to import in our system.
the housenumber column is formatted like this:
Normal house numbers just show the number but house numbers with a certain boxnumber are shown like this: 25 B12
I need to get the boxnumbers (if they exist) in another column
I managed to do this with these functions
Function GetBus(Text As String, ByRef NumberCell As Range) As String
Dim LastWord As String
LastWord = ReturnLastWord(Text)
If Left(LastWord, 1) = "B" Then
GetBus = Right(LastWord, Len(LastWord) - 1)
Else
GetBus = ""
End If
End Function
Function ReturnLastWord(Text As String) As String
Dim LastWord As String
LastWord = StrReverse(Text)
LastWord = Left(LastWord, InStr(1, LastWord, " ", vbTextCompare))
ReturnLastWord = StrReverse(Trim(LastWord))
End Function
So creating the new column with the box values is working. What is not working is deleting the box part in the number column (fe: if number value is 25 B1 the B1 part should be removed)
Any Ideas of how to do this or is this not possible in excel?

This is something which I wrote couple of years ago so I am not sure if there are bugs in it but a quick test seems to portray that it is working correctly. You might have to change it to make it exactly work in your situation.
Code:
Option Explicit
Sub SplitAddress()
Dim MyAr() As String, tempStr As String, strUnique As String
Dim lRow As Long, i As Long, j As Long, lRow2 As Long
Dim cell As Range
strUnique = "SiddR" & Format(Now, "ddmmyyhhmmss")
With ActiveSheet
.Columns("A:A").Replace What:=" ", Replacement:=strUnique, LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Columns("C").NumberFormat = "#"
.Columns("D").NumberFormat = "#"
For i = 2 To lRow
MyAr = Split(.Range("A" & i).Value, strUnique)
tempStr = ""
For j = LBound(MyAr) To (UBound(MyAr) - 1)
If tempStr = "" Then
tempStr = MyAr(j)
Else
tempStr = tempStr & " " & MyAr(j)
End If
Next j
.Range("B" & i).Value = tempStr
.Range("C" & i).Value = MyAr(UBound(MyAr))
Next i
For i = 2 To lRow
If Not IsNumeric(.Range("C" & i).Value) Then
tempStr = ""
For j = 1 To Len(.Range("C" & i).Value)
If IsNumeric(Mid(.Range("C" & i).Value, j, 1)) Then
If tempStr = "" Then
tempStr = Mid(.Range("C" & i).Value, j, 1)
Else
tempStr = tempStr & Mid(.Range("C" & i).Value, j, 1)
End If
Else
Exit For
End If
Next
.Range("D" & i).Value = Mid(.Range("C" & i).Value, j)
.Range("C" & i).Value = tempStr
If Len(Trim(tempStr)) = 0 Then
MyAr = Split(.Range("A" & i).Value, strUnique)
.Range("C" & i).Value = MyAr(UBound(MyAr) - 1)
End If
End If
Next
.Columns("A:A").Replace What:=strUnique, Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
.Columns("D:D").Replace What:="-", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End With
End Sub
Screenshot:
Screenshot:
With your test data
EDIT: Now when I look at this code again, I see that it can be optimized much much further :)

Related

VBA UserForm Issue - Could not set the list property. Invalid property array index

The below code works as long as there are more than one instance of the search criteria. However, if there is only one row that is listed as the what in the find function I receive the error "Could not set the list property. Invalid property array index"
Private Sub UserForm_Initialize()
Dim iRow As Integer, iMax As Integer
iRow = Cells.Find(What:="New Jersey Audit Adjustment", _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Row
iMax = Cells.Find(What:="New Jersey Audit Adjustment", _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, _
MatchCase:=False, SearchFormat:=False).Row
Me.ComboBox1.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
Me.ComboBox2.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
Me.ComboBox3.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
Me.ComboBox4.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
Me.ComboBox5.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
End Sub
The error occurs here Me.ComboBox1.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value if I have one row listed with "New Jersey Audit Adjustment"
When your range contains one cell, the .value will give you a value instead of an array. As the .list expects an array you could fill an array with one element or use addItem (see below)
If Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Cells.Count = 1 Then
Me.ComboBox1.AddItem Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
Else
Me.ComboBox1.List = Worksheets("C-Proposal-19").Range("B" & iRow & ":B" & iMax).Value
End If

Date not change while repalce "." to "/"

I'am trying to replace . to / on selection but after replace some cell not change. I have to change it mannual by click enter. Please suggest it via VBA. for change. I also try to calculate and numberformat but both are not working
Sub Reverse_Cheque()
Dim ChequeDate As String, i As Long
i = 2
'Debug.Print ChequeDate.Address
Range("A1").CurrentRegion.Columns.AutoFit
Range("L:L").Insert
Range("L1").Value = "expire date"
Do Until Range("k" & i).Value = ""
ChequeDate = Range("K" & i).Value
Range("k" & i).Value = Replace(Range("k" & i).Value, ".", "/")
Range("k" & i).NumberFormat = "dd-mm-yyy"
'Range("L" & i).Value = Range("k" & i).Value + 89
i = i + 1
Loop
End Sub
Range("k" & i).Value = Replace(Range("k" & i).Value, ".", "/")
Range("k" & i).NumberFormat = "dd-mm-yyy"
This is not the right way to do it. This will only work if the previous number format is "General". This is an example to replicate the above issue. The below will not work.
[A1].NumberFormat = "#"
[A1].Value = #1/1/2021#
[A1].NumberFormat = "dd/mm/yyyy"
For the above to work, you will have to press F2 and then Enter.
The below will work without F2 and Enter
[A1].NumberFormat = "General"
[A1].Value = #1/1/2021#
[A1].NumberFormat = "dd/mm/yyyy"
And hence it is always advisable to change the number format first before inputing new data.
Also you do not need a loop. You can use .Replace to replace all . in one go. Here is an example. Change it to suit your needs.
With Columns("K")
.NumberFormat = "dd/mm/yyyy"
.Replace What:=".", Replacement:="/", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
End With

Use variables inside a formula

I am attempting to use variables in what should be a simple addition formula. First I search for the column header in row 3 call "Jan Expense Hours" MsgBox ColL comes back with the letter "I" and MsgBox ColL2 comes back with the letter "J", both of which are correct. lRow comes back with row 55 which is also correct. Although when I try to add these variables to Worksheets("Calcs").Range("F4:F" & lRow).Formula = "=SUM('Resource Details'! & [ColL] & 4: & [ColL2] & 4)" I get an Application-defined or object-defined error on this line of code. Does anyone have an Idea what I am doing wrong? Btw, I'm searching for the column header because the columns do shift on various copies.
Full Procedure:
Sub JanTotHrsFind()
Dim lRow As Long
Dim lCol As Long
Dim strSearch As String
Dim aCell As Range
Dim ColL As String
Dim ColL2 As String
Dim ColNo As Long
Sheets("Resource Details").Activate
'find the column
strSearch = "*Jan Expense Hours*"
Set aCell = Sheets("Resource Details").Rows(3).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=True, SearchFormat:=False)
'convert column number to letter
ColNo = aCell.Column
ColL = Split(Cells(, ColNo).Address, "$")(1)
ColL2 = Split(Cells(, (ColNo + 1)).Address, "$")(1) 'adds one more column to right
MsgBox ColL
MsgBox ColL2
lRow = Cells.Find(What:="SUBTOTAL*", _
After:=Range(ColL & "4"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row - 1 'minus 1 row to move above
MsgBox "Last Row: " & lRow
'formula for Jan Expense Hours + Jan Capital Hours
'Worksheets("Calcs").Range("F4:F" & lRow).Formula = "=SUM('Resource Details'!I4:J4)"
'Worksheets("Calcs").Range("F4:F" & lRow).Formula = "=SUM('Resource Details'![" & ColL & "]4:[" & ColL2 & "]4)"
Worksheets("Calcs").Range("F4:F" & lRow).Formula = "=SUM('Resource Details'! & [ColL] & 4: & [ColL2] & 4)"
End Sub
You should not write your variables within brackets.
So:
Worksheets("Calcs").Range("F4:F" & lRow).Formula = "=SUM('Resource Details'!" & [ColL] & "4:" & [ColL2] & "4)"
Can you please try your code as I corrected above and see how it goes.

Sum Specific Rows Of Used Range

I know how to find the last row, and add a SUM() to that, but how do I SUM(G+H) in column O for each row of the used range?
I would use this to get the last row and sum columns, how could this be converted to sum rows?
With ws
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow = 1
End If
.Range("C" & LastRow + 1).FormulaR1C1 = "=SUM(R[-" & LastRow & "]C:R[-1]C)"
.Range("C" & LastRow + 1 & ":M" & LastRow + 1).FillRight
End With
Something like this would get G + H in column O:
Sub testme()
Dim l_counter As Long
For l_counter = 1 To 100
ActiveSheet.Cells(l_counter, 15).FormulaR1C1 = "=RC7+RC8"
Next l_counter
End Sub
Just make sure that you change the 100 to a variable, in your case, LastRow

How to match data between columns to do the comparasion

I do not really know how to explain this in a clear manner. Please see attached image
I have a table with 4 different columns, 2 are identical to each other (NAME and QTY). The goal is to compare the differences between the QTY, however, in order to do it. I must:
1. sort the data
2. match the data item by item
This is not a big deal with small table but with 10 thousand rows, it takes me a few days to do it.
Pleas help me, I appreciate.
My logic is:
1. Sorted the first two columns (NAME and QTY)
2. For each value of second two columns (NAME and QTY), check if it match with first two column. If true, the insert the value.
3. For values are not matched, insert to new rows with offset from the rows that are in first two columns but not in second two columns
Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lastRow As Long, i As Long, newRow As Long
Dim aCell As Range, SrchRange As Range
Set ws = Sheets("Sheet1")
With ws
.Columns("A:B").Copy .Columns("G:G")
.Columns("G:H").Sort Key1:=.Range("G2"), Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
lastRow = .Range("G" & Rows.Count).End(xlUp).Row
newRow = lastRow
Set SrchRange = .Range("G2:G" & lastRow)
lastRow = .Range("C" & Rows.Count).End(xlUp).Row
.Range("I1").Value = "NAME": .Range("J1").Value = "QTY"
For i = 2 To lastRow
If Len(Trim(.Range("C" & i).Value)) <> 0 Then
Set aCell = SrchRange.Find(What:=.Range("C" & i).Value, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
.Range("I" & aCell.Row).Value = .Range("C" & i).Value
.Range("J" & aCell.Row).Value = .Range("D" & i).Value
Else
newRow = newRow + 1
.Range("I" & newRow).Value = .Range("C" & i).Value
.Range("J" & newRow).Value = .Range("D" & i).Value
End If
End If
Next
End With
End Sub
SNAPSHOT
Based on your above requirements, the logic totally changes and hence I am posting it as a different answer.
Also in your "This is Wonderful" snapshot above, there is a slight error. As per logic SAMPLE10 cannot come above SAMPLE11. It has to come after SAMPLE11.
See the below snapshot
And here is the code :)
Option Explicit
Sub sAMPLE()
Dim ws As Worksheet
Dim lastRow As Long, i As Long, newRow As Long, rw As Long
Dim aCell As Range, SrchRange As Range
Set ws = Sheets("Sheet1")
With ws
.Columns("A:B").Copy .Columns("G:G")
.Columns("G:H").Sort key1:=.Range("G2"), Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
.Columns("H:H").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
lastRow = .Range("G" & Rows.Count).End(xlUp).Row
For i = 2 To lastRow
.Range("H" & i).Value = GetLastNumbers(.Range("G" & i).Value)
If .Range("H" & i).Value <> 0 Then
.Range("G" & i).Value = Left(.Range("G" & i).Value, _
Len(.Range("G" & i).Value) - Len(.Range("H" & i).Value))
End If
Next i
.Columns("G:H").Sort key1:=.Range("H2"), Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
For i = 2 To lastRow
If .Range("H" & i).Value <> 0 Then _
.Range("G" & i).Value = .Range("G" & i).Value & .Range("H" & i).Value
Next i
.Columns("H:H").Delete
newRow = lastRow
Set SrchRange = .Range("G2:G" & lastRow)
lastRow = .Range("C" & Rows.Count).End(xlUp).Row
.Range("I1").Value = "NAME": .Range("J1").Value = "QTY"
For i = 2 To lastRow
If Len(Trim(.Range("C" & i).Value)) <> 0 Then
Set aCell = SrchRange.Find(What:=.Range("C" & i).Value, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
.Range("I" & aCell.Row).Value = .Range("C" & i).Value
.Range("J" & aCell.Row).Value = Application.Evaluate("=SUMPRODUCT((C2:C" & lastRow _
& "=" & """" & .Range("C" & i).Value & """" & ")*(D2:D" & lastRow & "))")
Else
newRow = newRow + 1
.Range("I" & newRow).Value = .Range("C" & i).Value
.Range("J" & newRow).Value = .Range("D" & i).Value
End If
End If
Next
lastRow = .Range("G" & Rows.Count).End(xlUp).Row
For i = lastRow To 2 Step -1
If .Range("G" & i).Value = .Range("G" & i - 1).Value Then
.Range("H" & i - 1).Value = .Range("H" & i).Value + .Range("H" & i - 1).Value
If Application.WorksheetFunction.CountA(.Range("I" & i & ":J" & i)) = 0 Then
.Range("G" & i & ":J" & i).Delete Shift:=xlUp
Else
.Range("G" & i & ":H" & i).Delete Shift:=xlUp
End If
End If
Next i
lastRow = .Range("I" & Rows.Count).End(xlUp).Row
newRow = .Range("G" & Rows.Count).End(xlUp).Row
If lastRow <= newRow Then Exit Sub
.Range("I" & newRow & ":J" & lastRow).Sort key1:=.Range("I" & newRow), Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
For i = lastRow To newRow Step -1
If .Range("I" & i).Value = .Range("I" & i - 1).Value Then
.Range("J" & i - 1).Value = .Range("J" & i).Value + .Range("J" & i - 1).Value
.Range("I" & i & ":J" & i).Delete Shift:=xlUp
End If
Next i
End With
End Sub
Function GetLastNumbers(strVal As String) As Long
Dim j As Long, strTemp As String
For j = Len(strVal) To 1 Step -1
If Not IsNumeric(Mid(strVal, j, 1)) Then Exit For
strTemp = Mid(strVal, j, 1) & strTemp
Next j
GetLastNumbers = Val(Trim(strTemp))
End Function

Resources