Preventing duplicates in a column regardless of the case of the entry - excel

I type three entries in specific cells
[A2,B2,C2] and run code to take this data to the first empty row in a table.
The code also prevents duplicates based on the entered value in cell B2. If it already exists in the range (B2:B5000) it prevent duplicates.
The problem is it does not ignore the case.
For example:
I enter value "Acetic Acid"
After awhile I add "acetic Acid" or change any letter case.
The code adds it normally without preventing.
How do I ignore the letter case?
Sub tarheel()
LastRow = Range("A10000").End(xlUp).Row + 1
LR = Range("b10000").End(xlUp).Row + 1
For r = 5 To LR
If Cells(r, 2) = Range("b2") Then MsgBox "This Item Name already exist, No shift will done": Exit Sub
Next
Cells(LastRow, 1).Value = Range("A2").Value
Cells(LastRow, 2).Value = Range("B2").Value
Cells(LastRow, 3).Value = Range("C2").Value
Range("A2:C2").Select
Selection.ClearContents
Range("A2").Select
End Sub

thanks for all your replies and i will try it too and give feedback to you.
i could figure it out by adding this line at the top of my module.
Option Compare Text
and it fixed my problem.
thanks

To change case in VBA, you have LCase and UCase, which will respectively change all of your string into lower case or upper case.
Here is your code with the change and got ride of the useless (and ressource-greedy) select at the end :
Sub tarheel()
LastRow = Range("A10000").End(xlUp).Row + 1
LR = Range("b10000").End(xlUp).Row + 1
IsIn = False
For r = 5 To LR
If LCase(Cells(r, 2)) = LCase(Range("b2")) Then _
MsgBox "This Item Name already exist, No shift will done": Exit Sub
Next
Cells(LastRow, 1).Value = Range("A2").Value
Cells(LastRow, 2).Value = Range("B2").Value
Cells(LastRow, 3).Value = Range("C2").Value
Range("A2:C2").ClearContents
'Range("A2").Select
End Sub

You can replace your loop that compares for existing values with a case insensitive one by forcing both values to either upper or lower case.
For r = 5 To LR
If lcase(Cells(r, 2)) = lcase(Range("b2")) Then
MsgBox "This Item Name already exist, No shift will done"
Exit Sub
end if
Next
It may be more efficient to use a case-insensitive worksheet function to check the whole range at once.
If cbool(application.countif(Range("B5:B" & LR), Cells(r, 2))) Then
MsgBox "This Item Name already exist, No shift will done"
Exit Sub
end if
Another possible:
If not iserror(application.match(Cells(r, 2), Range("B5:B" & LR), 0)) Then
MsgBox "This Item Name already exist, No shift will done"
Exit Sub
end if

Sub tarheel()
LastRow = Range("A10000").End(xlUp).Row + 1
LR = Range("b10000").End(xlUp).Row + 1
IsIn = False
For r = 5 To LR
If LCase(Cells(r, 2)) = LCase(Range("b2")) Then _
MsgBox "This Item Name already exist, No shift will done": Exit Sub
Next
Cells(LastRow, 1).Value = Range("A2").Value
Cells(LastRow, 2).Value = Range("B2").Value
Cells(LastRow, 3).Value = Range("C2").Value
Range("A2:C2").ClearContents
'Range("A2").Select
End Sub

Related

Add 10 entries from userform to sheet

I am looking for a way to shorten my code to input data from a form of 10 entries.
This is my userform with one RMA number (applies to all 10 PN), one customer name, 10 part numbers, and 10 serial numbers that go with each part number.
This is how I want data transferred to the worksheet.
The part number textboxes are named TB#.
The serial number textboxes are named SNTB#.
This is the code I have for the first entry. I was thinking of adding code to say "TB"&"i" and "SNTB"&"i", but I don't know where to place that statement or how to start it.
Private Sub EnterButton_Click()
'this assigns receiving data to first columns of log Sheet
If TB1.Value = "" Then
Else
Worksheets("RM Tracker").Activate
Dim lastrow
lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
lastrow = lastrow + 1
Cells(lastrow, 1) = RMATB.Value
Cells(lastrow, 2) = CustCB.Value
Cells(lastrow, 3) = TB1.Value
Cells(lastrow, 4) = SNTB1.Value
Cells(lastrow, 5) = ReceiveTB.Value
ActiveCell.Offset(1, 0).Select
End If
ActiveWorkbook.Save
Call resetform
End Sub
Sub resetform()
RMATB.Value = ""
CustCB.Value = ""
TB1.Value = ""
SNTB1.Value = ""
ReceiveTB = ""
'sets focus on that first textbox again
RecForm.RMATB.SetFocus
End Sub
You can incorporate a for loop where "i" represents the row you are working with. When you are appending data you need to put that reference within the loop so the new row is recalculated.
Private Sub EnterButton_Click()
'this assigns receiving data to first columns of log Sheet
If TB1.Value = "" Then
Else
Worksheets("RM Tracker").Activate
dim i as long
For i = 1 To 10
Dim lastrow as long ' should put a data type with dim statements
lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
lastrow = lastrow + 1
Cells(lastrow, 1) = Userform1.Controls("RMATB" & i).Value ' change userform name to fit your need
Cells(lastrow, 2) = Userform1.Controls("CustCB" & i).Value
Cells(lastrow, 3) = Userform1.Controls("TB1" & i).Value
Cells(lastrow, 4) = Userform1.Controls("SNTB1" & i).Value
Cells(lastrow, 5) = Userform1.Controls("ReceiveTB" & i).Value
Next i
End If
ActiveWorkbook.Save
Call resetform
End Sub
Sub resetform()
RMATB.Value = ""
CustCB.Value = ""
TB1.Value = ""
SNTB1.Value = ""
ReceiveTB = ""
'sets focus on that first textbox again
RecForm.RMATB.SetFocus

Creating a button that adds a value to a cell if pressed

I've created a button, then assigned a macro to it which is in module1. when I select a cell within a range, then press the button, I want that cell to be given a value. if a cell within the range is not selected then pressing the button should pop up with a message box. I am just starting to write the code and already getting an issue.
If Intersect(Target, Range("D12:AS23")) Is Nothing Then
MsgBox "Please select a date.", , "Error"
Exit Sub
Else
Edit: I've got past this issue now using active cell instead of the target. but now I'm struggling again at the next bit. its saying application/object-defined error and highlighting this line. full code below
Cells(LastRow, 2).Value = Application.SumIf(Sheets("Settings").range("ListEmployeeNames"), Cells(3, 2).Value, Sheets("Settings").range("ListEmployeeID"))
Sub AddNote()
Dim SelectedDate As Date
SelectedDate = Cells(ActiveCell.Row, 2) - 1 + ActiveCell.Value
If intersect(ActiveCell, range("D12:AS23")) Is Nothing Then
MsgBox "Please select a date.", , "Error"
Exit Sub
Else
With Sheets("Notes")
xtt = Application.InputBox("Insert your Comment here", "Comment")
If xtt = vbNullString Or xtt = False Then
End If
Dim LastRow As Integer
LastRow = 2 + .listobjects("TblNotes").range.rows.Count
Cells(LastRow, 2).Value = Application.SumIf(Sheets("Settings").range("ListEmployeeNames"), Cells(3, 2).Value, Sheets("Settings").range("ListEmployeeID"))
Cells(LastRow, 4).Value = SelectedDate
Cells(LastRow, 5).Value = xht
End With
End If
End Sub
Got it working 90% on my own, thanks to #LeeLiFong for tipping me off about "target" being an issue and also #BraX for point int he right direction about including arguements to qualify things. I cant accept my answer for another 48 hours.
Dim SelectedDate As Date
SelectedDate = Cells(ActiveCell.Row, 2) - 1 + ActiveCell.Value
If intersect(ActiveCell, range("D12:AS23")) Is Nothing Then
MsgBox "Please select a date.", , "Error"
Exit Sub
Else
Call SmoothCodeStart
With Sheets("Notes")
xt4 = Application.InputBox("Insert your Comment here", "Comment")
If xt4 = vbNullString Or xt4 = False Then
End If
Dim LastRow As Integer
LastRow = 2 + .listobjects("TblNotes").range.rows.Count
.Cells(LastRow, 2).Value = Application.SumIf(Sheets("Settings").range("ListEmployeeNames"), Cells(3, 2).Value, Sheets("Settings").range("ListEmployeeID"))
.Cells(LastRow, 4).Value = SelectedDate
.Cells(LastRow, 6).Value = xt4
End With
Call SmoothCodeEnd
End If

VBA copy certain columns from one sheet to another when condition is met

New member here trying to fathom what might be wrong with the following code...
I am trying to copy rows from "A5" to the last row and columns A:L except columns "C & D" when C = "Y" but not getting anything when execute Macro and debug now giving much away (although I am new to this :-)). Any ideas or help would be appreciated.
Private Sub UpdateImportFile_Click()
Dim count As Long
count = WorksheetFunction.CountA(Range("A5", Range("A5").End(xlDown)))
For i = 5 To count
If Worksheets("Case Entry").Cells(i, 3).Value = "Y" Then
Worksheets("Case Entry").Rows(i).Columns(1, 2).Copy
Worksheets("Import File").Activate
Worksheets("Import File").Cells("A2").Select
ActiveSheet.PasteSpecial xlPasteValues
End If
Next
Application.CutCopyMode = False
ThisWorkbook.Worksheets("Case Entry").Cells(1, 1).Select
End Sub
Try this:
Private Sub UpdateImportFile_Click()
Dim count As Long
count = WorksheetFunction.CountA(Range("A5", Range("A5").End(xlDown)))
With Worksheets("Case Entry")
For i = 5 To count + 4
If .Cells(i, 3).Value = "Y" Then
Worksheets("Import File").Cells(i, 1).Resize(1, 2).Value = .Cells(i, 1).Resize(1, 2).Value
End If
Next
End With
End Sub

How to assign variable to value from loop VBA

my newbie question:
I would need to define variable from values gathered by loop.
I have column of datas, and I need to filter those data and copy to another new sheet named with variable.
Problem is, I cannot get variable from loop.
Is it possible?
Example: variable is "hu"
i = 2
Do Until IsEmpty(Cells(i, 9))
**hu** = Cells(i, 9).Value
i = i + 1
Loop
ActiveWorkbook.Worksheets.Add
ActiveSheet.Name = **hu**
Worksheets("Sheet1").Range("A1:I1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$I$1").AutoFilter Field:=9, Criteria1:=**hu**
With ActiveSheet.AutoFilter.Range
On Error Resume Next
Set rng2 = .Offset(1, 0).Resize(.Rows.Count - 1, 1) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
End With
If rng2 Is Nothing Then
MsgBox "No data to copy"
Else
Set rng = ActiveSheet.AutoFilter.Range
rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy _
Destination:=Worksheets("Comparison2").Range("A2")
End If
ActiveSheet.ShowAllData
Thanks!
You need to include a subroutine call within your loop to use the variable.
Something like this ..
Option Explicit
Sub do_it()
Dim hu As String
Dim i As Integer
i = 2
Cells(i, 9).Select
Do Until IsEmpty(Cells(i, 9))
hu = Cells(i, 9).Value
get_worksheet (hu)
i = i + 1
Loop
End Sub
Sub get_worksheet(name)
ActiveWorkbook.Worksheets.Add
..etc
end sub
With data like:
In column I, this is a way to get the last item before the empty:
Sub marine()
i = 2
Do Until Cells(i, 9).Value = ""
hu = Cells(i, 9).Value
i = i + 1
Loop
MsgBox hu
End Sub
Ok I googled and found out the problem, error message was due to "This error happens also when a Sub is called the same as variable (i.e. in one Sub you have for loop with iterator "a", whilst another Sub is called "a")."
I changed the name of variable and code works.
Thanks to everyone

Which is faster and more efficient - For loop, MATCH, FIND, etc?

What I am doing is search some strings one by one in the entire range - like search for "blah1", if found then exit, else search "blah2" in the entire range in the same manner. "blah's" are searched in one column.
Right now i am just running a For loop code as shown below which so far works ok in my tests...but was wondering if MATCH, FIND or other methods may be faster...any opinion?
Sub test()
Dim LR As Long
LR = Sheet1.Cells(Rows.Count, "A").End(xlUp).Row
If Cells(1, "B") = "" Then
For i = 1 To LR
If Cells(i, "A") = "blah1" Then
Cells(1, "B") = Cells(i, "A").Row
Cells(1, "C") = Cells(i, "A")
Exit For
End If
Next i
End If
If Cells(1, "B") = "" Then
For i = 1 To LR
If Cells(i, "A") = "blah2" Then
Cells(1, "B") = Cells(i, "A").Row
Cells(1, "C") = Cells(i, "A")
Exit For
End If
Next i
End If
End Sub
Try this one. Since your code is repeated (for "blah1" and "blah2") I used additional function:
Sub test()
If Sheet1.Cells(1, "B") = "" Then
If findString("blah1") Then Exit Sub
If findString("blah2") Then Exit Sub
End If
End Sub
'Function findString returns TRUE if something found and FALSE otherwise
Function findString(searchString As String) As Boolean
Dim rng As Range, res
With Sheet1
Set rng = .Range("A1:A" & .Cells(.Rows.Count, "A").End(xlUp).Row)
res = Application.Match(searchString, rng, 0)
'Application.Match returns error if nothing found
findString = Not IsError(res)
If findString Then
.Cells(1, "B").Value = rng.Cells(res, 1).Row
.Cells(1, "C").Value = searchString
End If
End With
End Function
I'm reasonably new to Excel Vba, but my limited understanding is that reading from cells is relatively slow. If I were doing this I would read all the values into an array, and carry out the same for loop as you have used, but on the array, rather than cell values.
To confirm, you could use VBAs Timer function to check speed.
Let me know if you'd like more detailed explanations of how to do this.
Here's how you can turn a range into an array (and vice versa). Step through this code with the Locals window turned on and watch what happens. You are particularly interested in the astrArray variable.
Sub ChangeArray()
'
Dim astrArray As Variant
'
' Dim astrArray
' that is, with no type specified
' is exactly equivalent
'
Dim lngIndex As Long
Dim strMessage As String
'
Range("A1").Value = "This"
Range("A2").Value = "is"
Range("A3").Value = "only"
Range("A4").Value = "a"
Range("A5").Value = "test"
astrArray = Range("A1:A5")
For lngIndex = 1 To 5
strMessage = strMessage & astrArray(lngIndex, 1) & " "
Select Case lngIndex
Case 1
astrArray(lngIndex, 1) = "No,"
Case 2
astrArray(lngIndex, 1) = "it's"
Case 3
astrArray(lngIndex, 1) = "actually"
Case 4
astrArray(lngIndex, 1) = "real"
Case 5
astrArray(lngIndex, 1) = "life"
End Select
Next lngIndex
MsgBox strMessage
Range("A1:A5") = astrArray
End Sub
A key requirement: to do this, the variable must be DIMmed Variant!
Another thing to pay attention to: the variable is two-dimensional, even though the range selected is one-dimensional.

Resources