excel vba search multiple criteria - vba

when I run this VBA macro I get the same result despite putting in different nurse id thanks, this code came from a video that I watch and has been modified to work with multiple criteria
Sub finddata()
Dim nursenumber As String
Dim finalrow As Integer
Dim i As Integer
Dim course As Integer
Dim nurserow As Integer
nursenumber = InputBox("please enter nurse number")
nurserow = InputBox("please enter nurse row")
finalrow = Sheets("S1").Range("A10000").End(xlUp).Row
course = ADORIE
'fire update
For i = 2 To finalrow
Worksheets("S1").Activate
If Cells(i, 1) = nursenumber & Cells(i, 7) = "FIRE" Then
Cells(i, 9).Copy
Worksheets("database").Activate
Cells(nurserow, 2).PasteSpecial
End If
'cpr
If Cells(i, 1) = nursenumber & Cells(i, 7) = "CPRNURL4" Or _
Cells(i, 7) = "BUCPRBYS" Or Cells(i, 7) = "BUCPREMS" Or _
Cells(i, 7) = "CPRACLSR" Or Cells(i, 7) = "CPRADULT" Or _
Cells(i, 7) = "CPRALIED" Or Cells(i, 7) = "CPRBASIC" Or _
Cells(i, 7) = "CPRBYST" Or Cells(i, 7) = "CPRCO567" Or _
Cells(i, 7) = "CPRMANHA" Or Cells(i, 7) = "CPRMCORP" Or _
Cells(i, 7) = "CPRNURL4" Then
Cells(i, 9).Copy
Worksheets("database").Activate
Cells(nurserow, 3).PasteSpecial
Next i
End Sub

Following my comments above, also, your code is screaming for a Select Case instead of your multiple Or.
Code
Sub finddata()
Dim nursenumber As String
Dim finalrow As Integer
Dim i As Integer
Dim course As Integer
Dim nurserow As Integer
nursenumber = InputBox("please enter nurse number")
nurserow = InputBox("please enter nurse row")
finalrow = Sheets("S1").Range("A10000").End(xlUp).Row
course = ADORIE
With Worksheets("S1")
For i = 2 To finalrow
If .Cells(i, 1) = nursenumber Then
Select Case .Cells(i, 7).Value
Case "FIRE"
.Cells(i, 9).Copy Destination:=Worksheets("database").Cells(nurserow, 2)
Case "CPRNURL4", "BUCPRBYS", "CPRACLSR", "CPRADULT", "CPRALIED", "CPRBASIC", "CPRBYST", "CPRCO567", "CPRMANHA", "CPRMCORP", "CPRNURL4"
.Cells(i, 9).Copy Destination:=Worksheets("database").Cells(nurserow, 3)
End Select
End If
Next i
End With
End Sub

Related

VBA EXCEL Compare Columns and bring over the value

Image1
Hi, Referring to the image, I am trying to compare column G and Column K, if the value is the same then copy the value in column J to column F. However, my code doesn't copy the value from Column J to F.
Sub createarray1()
Dim i As Integer
Dim j As Integer
Dim masterarray As Range
Set masterarray = Range("D3:G12")
Dim sourcearray As Range
Set sourcearray = Range("H3:K26")
For i = 1 To 10
For j = 1 To 25
If masterarray(i, 4).Value = sourcearray(j, 4).Value Then
masterarray(i, 3) = sourcearray(j, 3).Value
Else
masterarray(i, 3).Value = ""
End If
Next
Next
End Sub
Function concatenate()
Dim nlastrow As Long
For i = 2 To Cells(Rows.Count, "D").End(xlUp).Row
Cells(i, "G").Value = Cells(i, "D").Value & "_" & Cells(i, "E").Value
Next i
Dim nnlastrow As Long
For i = 2 To Cells(Rows.Count, "H").End(xlUp).Row
Cells(i, "K").Value = Cells(i, "H").Value & "_" & Cells(i, "I").Value
Next i
End Function
Use variant arrays, that way you limit the number of calls to the sheet to only 3.
When your positive is found you need to exit the inner loop.
Sub createarray1()
Dim i As Long
Dim j As Long
Dim masterarray As Variant
Dim sourcearray As Variant
With ThisWorkbook.Worksheets("Sheet1") ' change to your sheet
masterarray = .Range("D3:G12")
sourcearray = .Range("H3:K26")
For i = LBound(masterarray, 1) To UBound(masterarray, 1)
masterarray(i, 3) = ""
For j = LBound(sourcearray, 1) To UBound(sourcearray, 1)
If masterarray(i, 4) = sourcearray(j, 4) Then
masterarray(i, 3) = sourcearray(j, 3)
Exit For
End If
Next j
Next i
.Range("D3:G12") = masterarray
End With
End Sub
But this can all be done with the following formula:
=INDEX(J:J,MATCH(G3,K:K,0))
Put it in F3 and copy/drag down.

Can't retrieve a value from my dictionary using its key using vba

I am completely stumped on this problem here. I created a macro that will read values from the current spreadsheet, place those values into a dictionary using row numbers as keys, create a new spreadsheet, grab the values from those dictionaries, and add them to the new spreadsheet. There are three dictionaries that are filled. I have no problem getting the values from two of the dictionaries and I even have no problems getting the first couple of values from the problematic dictionaries. But when I try to retrieve the last two values in the last For Next loop, the values are read as "" instead of an actual value. The image below is a message that I built from looping the problematic dictionary.
I had the debug loop that produced this message within the last For Next loop. As you can see each key has a value, but when I use dataN.Exist(key) for just the last two values I get "" as the value. I don't understand. The exact same code works to pull the first couple of values but not the last couple. I have even moved those values to different rows but still got the same "". Here is the entire code here below:
Sub Transfer2NewWorkbook()
Dim currentsheet As String
Dim newsheet As String
Dim analysisDate As String
Dim initial As String
Dim aInitial() As String
Dim analystInit As String
Dim aBatch() As String
Dim batch As String
Dim batchNo As String
Dim key As Variant
Dim ikey As Variant
Dim SrowN As String
Dim rowN As Integer
Dim rowD As String
Dim wb As Object
Dim dataRangeN As Range, dataRangeB As Range, dataRangeI As Range
Dim dataN As Object
Set dataN = CreateObject("Scripting.Dictionary")
Dim dataB As Object
Set dataB = CreateObject("Scripting.Dictionary")
Dim dataI As Object
Set dataI = CreateObject("Scripting.Dictionary")
Dim teststring As String
' Grab and Create filenames
currentsheet = ActiveWorkbook.Name
newsheet = currentsheet & "-" & "uploadable"
' Grab data from original spreadsheet
analysisDate = ActiveWorkbook.Sheets(1).Cells(1, 9).Value
initial = ActiveWorkbook.Sheets(1).Cells(1, 2).Value
aInitial = Split(initial, "/")
analystInit = aInitial(1)
batch = ActiveWorkbook.Sheets(1).Cells(1, 4).Value
aBatch = Split(batch, ":")
batchNo = aBatch(1)
Set dataRangeN = Range("A:A")
Set dataRangeB = Range("B:B")
Set dataRangeI = Range("I:I")
For i = 4 To dataRangeB.Rows.Count
If Not IsEmpty(dataRangeB(i, 1)) Then
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "End") = 0 Then
Exit For
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "Blank") = 0 Then
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "Unseeded") = 0 Or StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "Seeded") = 0 Then
If Not IsEmpty(dataRangeI(i, 1)) Then
dataN.Add i, ActiveWorkbook.Sheets(1).Cells(i, 1).Value
dataB.Add i, ActiveWorkbook.Sheets(1).Cells(i, 2).Value
dataI.Add i, ActiveWorkbook.Sheets(1).Cells(i, 9).Value
End If
End If
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "Check") = 0 Then
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "Std") = 0 Then
If Not IsEmpty(dataRangeI(i, 1)) Then
dataN.Add i, ActiveWorkbook.Sheets(1).Cells(i, 1).Value
dataB.Add i, ActiveWorkbook.Sheets(1).Cells(i, 2).Value
dataI.Add i, ActiveWorkbook.Sheets(1).Cells(i, 9).Value
End If
End If
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "DUP") = 0 Then
rowD = dataB.Keys()(dataB.Count - 1)
If StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "CBOD") = 0 Then
dataN.Add rowD, "DUP-CBOD"
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "BOD") = 0 Then
dataN.Add rowD, "DUP-BOD"
End If
Else
dataB.Add i, ActiveWorkbook.Sheets(1).Cells(i, 2).Value
dataI.Add i, ActiveWorkbook.Sheets(1).Cells(i, 9).Value
End If
Else
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "DUP") = 0 Then
rowD = dataB.Keys()(dataB.Count - 1)
If StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "CBOD") = 0 Then
dataN.Add rowD, "DUP-CBOD"
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "BOD") = 0 Then
dataN.Add rowD, "DUP-BOD"
End If
End If
End If
Next i
' Open new spreadsheet
Set wb = Workbooks.Add("C:\Users\dalythe\documents\uploadtemp.xlsx")
ActiveWorkbook.Sheets(1).Cells(2, 2).Value = analysisDate
ActiveWorkbook.Sheets(1).Cells(2, 4).Value = analystInit
ActiveWorkbook.Sheets(1).Cells(3, 5).Value = batchNo
rowN = 4
For Each key In dataB.Keys
If dataI.Exists(key) Then
SrowN = CStr(rowN)
If dataN.Exists(key) Then
ActiveWorkbook.Sheets(1).Cells(SrowN, 1).Value = dataN(key)
End If
ActiveWorkbook.Sheets(1).Cells(SrowN, 2).Value = dataB(key)
ActiveWorkbook.Sheets(1).Cells(SrowN, 3).Value = dataI(key)
rowN = CInt(SrowN)
rowN = rowN + 1
End If
Next
ActiveWorkbook.SaveAs (newsheet & ".xlsx")
End Sub

I need help arranging different values using vba code

So I have an excel sheet that has information that a user can put to look at different times. The problem I have is that I want the user to pick on cell c7 if they want to use the server or grid, depending on their answer they will get different responses on the cell (c9). In the code, I am having a problem that it doesn't know if the user picks grid or server. So I would like to add that to my code. Here is my code.
Sub findData()
Dim workflow As String
Dim server As String
Dim finalrow As Integer
Dim i As Integer
workflow = Sheets("Sheet1").Range("c5").Value
server = Sheets("sheet1").Range("c9").Value
Grid = Sheets("sheet1").Range("c9").Value
finalrow = Sheets("Sheet3").Range("c100").End(xlUp).Row
For i = 5 To finalrow
If Cells(i, 3) = workflow Then
If Cells(i, 4) = server Then
If Cells(i, 5) = Grid Then
Range(Cells(i, 2), Cells(i, 12)).Copy
Range("j42").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
End If
End If
End If
Next i
End Sub
Why not this approach instead?
Sub findData()
Dim workflow As String
Dim finalrow As Integer
Dim i As Integer
workflow = Sheets("Sheet1").Range("c5").Value
finalrow = Sheets("Sheet3").Range("c100").End(xlUp).Row
For i = 5 To finalrow
If Cells(i, 3) = workflow Then ' 1. If Cells(i, 3) = workflow
If Cells(i, 4) = "Server" Then ' 2. If Cells(i, 4) = "Server"
Range(Cells(i, 2), Cells(i, 12)).Copy
Range("j42").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
ElseIf Cells(i, 4) = "Grid" Then ' 2. If Cells(i, 4) = "Server"
Else ' 2. If Cells(i, 4) = "Server"
'not handled
End If ' 2. If Cells(i, 4) = "Server"
End If ' 1. If Cells(i, 3) = workflow
Next i
End Sub

Excel VBA, Loop Recording Answer

I am trying to write some code to choose start time and end times of a shift using input data for shift duration which is read from a column (reports times if cell is not empty).
I am just debugging at the moment before I try and hard code with variables and ranges however
my
If Cells(i, j).Value <> "" Then
Shiftduration = Cells(i, j).Value * (0.5 / 12)
lines are not working correctly and are returning 0 values when I am testing, as their values are not being recorded. Thus it not taking into account the actual start time of a shift ie (Shift end time - shift duration)
Sub Test2()
Sheets("Test").Select
Dim i As Long, j As Long
Dim Shiftduration As Long
Dim ShiftStart As Long
For i = 31 To 44
For j = 4 To 4
If Cells(i, j).Value <> "" Then
Shiftduration = Cells(i, j).Value * (0.5 / 12)
nextshift = Cells(i + 1, 1).Value
ShiftstartRange = nextshift - Shiftduration
Cells(1, 21) = nextshift
Cells(1, 22) = Shiftduration
Cells(i, 8) = ShiftstartRange
Else
End If
Next j
Next i
End Sub
All of my code
Thanks!
I changed Shiftduration and ShiftStart from Long to Double.
And I specify with which sheet your are working.
Let me know if its works like you want
Sub Test2()
Dim wb As Workbook
Dim ws As Worksheet
Dim i As Long, j As Long
Dim Shiftduration As Double
Dim ShiftStart As Double
Set wb = ThisWorkbook
Set ws = wb.Sheets("Test")
For i = 31 To 44
For j = 4 To 4
If ws.Cells(i, j).Value <> "" Then
Shiftduration = ws.Cells(i, j).Value * (0.5 / 12)
nextshift = ws.Cells(i + 1, 1).Value
ShiftstartRange = nextshift - Shiftduration
ws.Cells(1, 21) = nextshift
ws.Cells(1, 22) = Shiftduration
ws.Cells(i, 8) = ShiftstartRange
Else
End If
Next j
Next i
End Sub

Fast merging duplicates in excel using VBA

I created a macro in Excel to mergue duplicated rows:
The idea is that if 2 rows or more have the same A B C columns, I mergue their D columns removing ABC duplicates.
I need to do this, but checking more colums.
My macro looks like this:
processingRow = 2
Do Until Cells(processingRow, 1).Value = ""
i = processingRow + 1
Do Until Cells(i, 1).Value = ""
If Cells(processingRow, 8) = Cells(i, 8) And _
Cells(processingRow, 12) = Cells(i, 12) And _
Cells(processingRow, 7) = Cells(i, 7) And _
Cells(processingRow, 6) = Cells(i, 6) And _
Cells(processingRow, 5) = Cells(i, 5) And _
Cells(processingRow, 4) = Cells(i, 4) And _
Cells(processingRow, 3) = Cells(i, 3) And _
Cells(processingRow, 2) = Cells(i, 2) And _
Cells(processingRow, 1) = Cells(i, 1) Then
If Cells(i, 14) <> "" Then
Cells(processingRow, 14) = Cells(processingRow, 14) & "," & Cells(i, 14)
End If
Rows(i).Delete
End If
i = i + 1
Loop
processingRow = processingRow + 1
Loop
When running the macro with 500 rows, it takes a while, but its still reasonable. But I need to run this macro in a excel with more than 2500 rows, and it takes so much time that its not practical anymore.
This is my first macro in excel using VBA, so I was wondering if there is a faster way to process rows/cells, since accessing them individually seems extremelly slow.
Any ideas?
EDITED: I missed that you weren't checking every column to determine what was a duplicate. This should be closer now:
Sub Tester()
Dim rngCheck As Range, rw As Range
Dim dict As Object, k As String, rwDup As Range
Dim rngDel As Range, tmp
Set dict = CreateObject("scripting.dictionary")
With ActiveSheet
Set rngCheck = .Range(.Cells(2, 1), _
.Cells(Rows.Count, 1).End(xlUp)).Resize(, 14)
End With
For Each rw In rngCheck.Rows
k = RowKey(rw)
If dict.exists(k) Then
Set rwDup = dict(k)
tmp = rw.Cells(14).Value
If Len(tmp) > 0 Then
rwDup.Cells(14).Value = rwDup.Cells(14).Value & "," & tmp
End If
If rngDel Is Nothing Then
Set rngDel = rw
Else
Set rngDel = Application.Union(rngDel, rw)
End If
Else
dict.Add k, rw
End If
Next rw
If Not rngDel Is Nothing Then rngDel.EntireRow.Delete
End Sub
'create a "key" for the row by joining all columns to be checked
Function RowKey(rw As Range) As String
Dim arr, x As Long, sep As String, rv As String
arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 12)
For x = LBound(arr) To UBound(arr)
rv = rv & sep & rw.Cells(arr(x)).Value
sep = Chr(0)
Next x
RowKey = rv
End Function