Excel VBA sreach - excel

I have a piece of code (VBA) that search through a sheet and finds matches then shows up the last matching row in some text boxes.
I put this code in a button,and want to make it to stop each time it finds an occurrence instead of finding the last one and stop.
here's the code:
Private Sub cmdFindNext_Click()
Dim lastrow
Dim myfname As String
lastrow = Sheets("Sheet2").Range("B" & Rows.Count).End(xlUp).Row
myfname = txtUsername.Text
For currentrow = 2 To lastrow
If Cells(currentrow, 3).Text Like "*" & myfname & "*" Then
txtHost.Text = Cells(currentrow, 2).Text
txtUsername.Text = Cells(currentrow, 3).Text
txtPassword.Text = Cells(currentrow, 4).Text
txtUser.Text = Cells(currentrow, 5).Text
txtDepartment.Text = Cells(currentrow, 6).Text
txtPosition.Text = Cells(currentrow, 7).Text
txtFormerusers.Text = Cells(currentrow, 8).Text
txtCompany.Text = Cells(currentrow, 9).Text
End If
Next currentrow
txtUsername.SetFocus
End Sub

I am not sure why you are using If .Cells(currentrow, 3).Text Like "*" & myfname & "*" Then since you are searching for wildcard, it will enter this If condition on every try.
The code below will execute one "find" on every click of the button, when you reach the end, it will restart. (you can remove it by modifying the first If startrow < 2 Or startrow >= lastrow Then)
Option Explicit
Public startrow As Long
Sub cmdFindNext_Click()
Dim lastrow As Long
Dim currentrow As Long
Dim myfname As String
With Sheets("Sheet2")
lastrow = .Cells(.Rows.Count, "B").End(xlUp).Row
' reset the start row if first run, or finished scanning entire range
If startrow < 2 Or startrow >= lastrow Then
startrow = 2
End If
myfname = txtUsername.Text
For currentrow = startrow To lastrow
If .Cells(currentrow, 3).Text Like "*" & myfname & "*" Then
txtHost.Text = .Cells(currentrow, 2).Text
txtUsername.Text = .Cells(currentrow, 3).Text
txtPassword.Text = .Cells(currentrow, 4).Text
txtUser.Text = .Cells(currentrow, 5).Text
txtDepartment.Text = .Cells(currentrow, 6).Text
txtPosition.Text = .Cells(currentrow, 7).Text
txtFormerusers.Text = .Cells(currentrow, 8).Text
txtCompany.Text = .Cells(currentrow, 9).Text
startrow = startrow + 1
Exit Sub
End If
Next currentrow
End With
txtUsername.SetFocus
End Sub

Related

Finding text and then replacing on next line

I was previously using a macro which found the first blank line in a workbook and then put tags in the next 9 columns. This was working well for a project however i've now encountered issues in that macro doesn't always find the exact blank row i want (maybe because of formatting i'm not sure)
This was my code for that idea:
Sub SetupTags(pintNumFeatures As Integer, pintNumRecords As Integer, pintSubGroupSize As Integer)
Dim lngRow As Long
Dim lngCol As Long
Dim lngTotal As Long
Dim lngCell As Long
Dim lngDataRow As Long
Dim lngDataCol As Long
Dim lngFirstRow As Long
lngFirstRow = FindFirstBlankRow
lngRow = lngFirstRow
lngCol = 9
lngTotal = pintNumFeatures * pintNumRecords
lngDataCol = 1
lngDataRow = 1
For lngCell = 1 To lngTotal
ActiveWorkbook.Worksheets(1).Cells(lngRow, lngCol).Value = "[act]{rowcol:" & lngDataRow & "," & lngDataCol & "}"
lngCol = lngCol + 1
If lngCol > 13 Then
lngRow = lngRow + 1
lngCol = 9
End If
lngDataRow = lngDataRow + 1
If lngDataRow > pintNumRecords Then
lngDataCol = lngDataCol + 1
lngDataRow = 1
End If
Next lngCell
'now figure out the column specific stuff
Dim intPartRows As Integer
Dim intPartRow As Integer
Dim intFeature As Integer
Dim intRecordNumber As Integer
intPartRows = CInt(pintNumRecords / 5)
lngRow = lngFirstRow
lngCol = 1
intRecordNumber = 1
For intFeature = 1 To pintNumFeatures
For intPartRow = 0 To intPartRows - 1
ActiveWorkbook.Worksheets(1).Cells(lngRow, 1).Value = "[part_" & intFeature & "]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 2).Value = "[dim_" & intFeature & "]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 3).Value = "[date]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 4).Value = "[date]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 5).Formula = "=AVERAGE(I" & lngRow & ":M" & lngRow & ")"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 6).Formula = "=MAX(I" & lngRow & ":M" & lngRow & ") - MIN(I" & lngRow & ":M" & lngRow & ")"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 14).Value = "[tf1]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 15).Value = "[tf2]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 16).Value = "[tf3]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 17).Value = "[tf4]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 18).Value = "[tf5]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 19).Value = "[tf6]{Row:" & intRecordNumber & "}"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 20).Value = "[tf7]{Row:" & intRecordNumber & "}"
lngRow = lngRow + 1
intRecordNumber = intRecordNumber + 5
Next intPartRow
Next intFeature
End Sub
Function FindFirstBlankRow() As Long
Dim lngRow As Long
Dim lngFound As Long
'we need to check for blanks and not shaded to determine the actual last used row since the xlSpecialCells is not always accurate
'change this for each stage maybe 27 is the first empty row of stage 2 onwards we cannot have any empty rows passed this point'
For lngRow = 27 To 1000
If Sheet1.Cells(lngRow, 2).Value = "" Then
lngFound = lngRow
Exit For
End If
Next lngRow
FindFirstBlankRow = lngFound
End Function
Sub ReAddTags() 'pintNumFeatures As Integer, pintNumRecords As Integer, pintSubGroupSize As Integer)
Dim lngRow As Long
Dim lngFirstRow As Long
lngFirstRow = FindFirstBlankRow
lngRow = lngFirstRow
ActiveWorkbook.Worksheets(1).Cells(lngRow, 1).Value = "[All Feature Numbers]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 2).Value = "[ALL EXTRA INFO]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 4).Value = "[ALLLABELS]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 6).Value = "[allnoms]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 7).Value = "[FEATURE_SOURCES]"
ActiveWorkbook.Worksheets(1).Cells(lngRow, 9).Value = "[ACTROWS]"
End Sub
So i need to approach it a different way i have constant across the workbook of the word "Sequence" it always sits 1 line above the where i want to reintroduce these tags so i'm looking for something like this
• Find the next Sequence Text (this is always 1 line above where I want to put the tags back in)
• Then move one line below and add the tags back in
• There would need to be some kind of IF statement saying that if there is text in this line then skip to the next sequence text (this would stop it putting tags back into stages that have already been populated with data)
I can find some other code which does a find and replace but nothing as advanced to skip a line and also populate this IF statement
Sub test()
Dim rngColumn As Range
Dim rngCell As Range
Set rngColumn = Worksheets("Sheet1").Columns("H")
For Each rngCell In rngColumn.Cells
If Trim(rngCell) <> "" Then
If Trim(rngCell) = "815" Then
rngCell.Value = "'0815"
End If
End If
Next rngCell
Set rngColumn = Nothing
Set rngCell = Nothing
End Sub
Any guidance would be greatly appreciated
For moving to the next available row in a column you could use:
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Range("A1").Select

vba program to detect cell value in column and copy corresponding cell value in previous column

im trying to make a vba code that will detect when Active balancing is on ( A value in cell ) and then copy the previous tension value, and simillarly do the same at the end of Active balancing to copy the next tension value. (see picture for more explanation).
im planing to show those values in another sheet
thanks to the help of Mr.PeterT i modified his code to do it but i couldn't succeed. thanks for you help and mentoring guys!
image of values i want to extract
Option Explicit
Sub find_balanced_cells_and_tensions()
FindWith "A"
End Sub
Sub FindWith(checkValue As Variant)
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Sheets.Add
destinationSheet.Name = "Equilibrage.actif.info"
Dim destRow As Long
destRow = 1
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Sheets("Equilibrage.passif")
Dim lastRow As Long
Dim lastColumn As Long
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, 1).End(xlUp).Row
lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column
Dim i As Long
Dim j As Long
For j = 1 To lastColumn
For i = 2 To lastRow
If sourceSheet.Cells(i, j).Value = checkValue _
& sourceSheet.Cells(i + 1, j).Value = checkValue Then
sourceSheet.Cells(i - 1, j - 1).Copy _
Destination:=destinationSheet.Range("A" & destRow)
destRow = destRow + 1
ElseIf sourceSheet.Cells(i, j).Value = checkValue _
& sourceSheet.Cells(i + 1, j).Value <> checkValue Then
sourceSheet.Cells(i + 1, j - 1).Copy _
Destination:=destinationSheet.Range("B" & destRow)
destRow = destRow + 1
Exit For 'immediately skip to the next row
End If
Next i
Next j
End Sub
Untested but should be close.
I will test if you can share a sample dataset.
Sub find_balanced_cells_and_tensions()
FindWith "A"
End Sub
Sub FindWith(checkValue As Variant)
Dim sourceSheet As Worksheet
Dim destinationSheet As Worksheet
Dim destRow As Long, lastRow As Long, lastColumn As Long, valCount As Long
Dim i As Long, j As Long, preVal, postval, cellLabel, dt, tm
Set sourceSheet = ThisWorkbook.Sheets("Equilibrage.passif")
Set destinationSheet = ThisWorkbook.Sheets.Add()
destinationSheet.Name = "Equilibrage.actif.info"
destRow = 1
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, 1).End(xlUp).Row
lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column
For j = 4 To lastColumn Step 2 'only process relevant columns
i = 3
Do 'from 3 to lastrow-1 to allow for -1 at top and +1 at bottom
If sourceSheet.Cells(i, j).Value = checkValue Then
dt = sourceSheet.Cells(i - 1, 1).Value 'collect start info
tm = sourceSheet.Cells(i - 1, 2).Value
cellLabel = sourceSheet.Cells(1, j).Value
preVal = sourceSheet.Cells(i - 1, j - 1).Value
valCount = 1 'how many values in this run?
Do While sourceSheet.Cells(i, j).Offset(valCount).Value = checkValue
valCount = valCount + 1
Loop
postval = sourceSheet.Cells(i + valCount, j - 1).Value
destinationSheet.Cells(destRow, 1).Resize(1, 5).Value = _
Array(dt, tm, cellLabel, preVal, postval)
destRow = destRow + 1
i = i + valCount
End If
i = i + 1
Loop While i < lastRow
Next j
End Sub
So after countless hit and miss and the help of Tim Williams and Funthomas, i arrived to this code that does the job plus some things.
the worksheet to get the values from is this one :
Value source
And the result of the code is like this :
Results
the final code is like this :
Option Explicit
Sub find_balanced_cells_and_tensions_A()
FindWith "A" ' we can replace A by any value we want to look for here
End Sub
Sub FindWith(checkValue As Variant)
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Sheets.Add
destinationSheet.Name = "Equilibrage.actif.info"
'___ variables to track cells where will put our extacted values _______
Dim destRow As Long
destRow = 1
Dim destRow2 As Long
destRow2 = 1
'______ source sheet where we take our values from ___________
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Sheets("Equilibrage.passif")
'_____ defining the end of columns and rows to end scaning for values _____________
Dim lastRow As Long
Dim lastColumn As Long
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, 1).End(xlUp).Row
lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column
Dim i As Long
Dim j As Long
For j = 1 To lastColumn
For i = 2 To lastRow
'_____this part is to detect the start of balancing and taking the tension value of the previous row______________________
If sourceSheet.Cells(i, j).Value = checkValue _
And sourceSheet.Cells(i - 1, j).Value = 0 Then
sourceSheet.Cells(i - 1, j - 1).Copy _
Destination:=destinationSheet.Range("E" & destRow)
Range("A" & destRow).Value = sourceSheet.Cells(1, j)
Range("B" & destRow).Value = "was actively balanced at"
Range("C" & destRow).Value = sourceSheet.Cells(i, 2)
Range("D" & destRow).Value = "from"
Range("F" & destRow).Value = "to"
destRow = destRow + 1
'______ this condition is for when the balancing starts at the first row of the table so we take the present tension instead of the previous ___________
ElseIf sourceSheet.Cells(i, j).Value = checkValue _
And sourceSheet.Cells(i - 1, j).Value <> checkValue _
And sourceSheet.Cells(i - 1, j).Value <> 0 Then
sourceSheet.Cells(i, j - 1).Copy _
Destination:=destinationSheet.Range("E" & destRow)
Range("A" & destRow).Value = sourceSheet.Cells(1, j)
Range("B" & destRow).Value = "was actively balanced at"
Range("C" & destRow).Value = sourceSheet.Cells(i, 2)
Range("D" & destRow).Value = "from"
Range("F" & destRow).Value = "to"
destRow = destRow + 1
End If
'_____to find the next tension value after the end of balancing _____________
If sourceSheet.Cells(i, j).Value = checkValue _
And sourceSheet.Cells(i + 1, j).Value <> checkValue _
And IsEmpty(sourceSheet.Cells(i + 1, j).Value) = False Then
sourceSheet.Cells(i + 1, j - 1).Copy _
Destination:=destinationSheet.Range("G" & destRow2)
Range("H" & destRow2).Value = "at"
Range("I" & destRow2).Value = sourceSheet.Cells(i + 1, 2)
destRow2 = destRow2 + 1
'_____in case the balancing ends at the last row we take the present tension as the next one doesnt exist _____________
ElseIf sourceSheet.Cells(i, j).Value = checkValue _
And IsEmpty(sourceSheet.Cells(i + 1, j).Value) = True Then
sourceSheet.Cells(i, j - 1).Copy _
Destination:=destinationSheet.Range("G" & destRow2)
Range("H" & destRow2).Value = "at"
Range("I" & destRow2).Value = sourceSheet.Cells(i, 2)
destRow2 = destRow2 + 1
End If
Next i
Next j
'_____ Cells modification and formating _________________
Range("C:C").NumberFormat = "hh:mm:ss"
Range("I:I").NumberFormat = "hh:mm:ss"
Range("E:E").Style = "Normal"
Range("G:G").Style = "Normal"
Range("A:K").Font.Size = 14
Range("E:E").Font.Bold = True
Range("G:G").Font.Bold = True
Worksheets("Equilibrage.actif.info").Columns.AutoFit
End Sub

Combine duplicate rows in a loop vba

I want to combine duplicate rows with the same A and C columns values and sum their cells values for the column B (by adding the value of the textbox2 from the duplicate to the original). My problem is about the condition of the "If" in the Loop. It doesn't consider those conditions when I have duplicates and just add a new row. Is there a better way to do this?
Private Sub CommandButton1_Enter()
ActiveSheet.Name = "Sheet1"
Dim lastrow As Long
With Sheets("Sheet2")
lastrow = .Cells(Rows.Count, "H").End(xlUp).Row
For x = lastrow To 3 Step -1
For y = 3 To lastrow
If .Cells(x, 1).Value = .Cells(y, 1).Value And .Cells(x, 3).Value = .Cells(y, 3).Value And x > y Then
.Cells(y, 8).Value = .Cells(y, 8).Value + TextBox2.Text
.Cells(y, 2).Value = .Cells(y, 2).Value + TextBox2.Text
.Rows(lastrow).EntireRow.Delete
Else
.Cells(lastrow + 1, 8).Value = TextBox2.Text
.Cells(lastrow + 1, 2).Value = TextBox2.Text
.Cells(lastrow + 1, 1).Value = TextBox1.Text
.Cells(lastrow + 1, 3).Value = TextBox3.Text
Exit For
End If
Next y
Next x
End With
End Sub
Here's a picture of the data
There's no blank cell in the column H (I changed the color of the font to make it invisible).
Create a primary key by joining the 2 columns with tilde ~ and use a Dictionary Object to locate duplicates.
Option Explicit
Private Sub CommandButton1_Click()
Dim wb As Workbook, ws As Worksheet
Dim iLastRow As Long, iRow As Long, iTarget As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet2")
iLastRow = ws.Cells(Rows.Count, "H").End(xlUp).Row
Dim dict As Object, sKey As String
Set dict = CreateObject("Scripting.Dictionary")
' build dictionary and
' consolidate any existing duplicates, scan up
For iRow = iLastRow To 3 Step -1
' create composite primary key
sKey = LCase(ws.Cells(iRow, 1).Value) & "~" & Format(ws.Cells(iRow, 3).Value, "yyyy-mm-dd")
If dict.exists(sKey) Then
iTarget = dict(sKey)
' summate and delete
ws.Cells(iTarget, 2) = ws.Cells(iTarget, 2) + ws.Cells(iRow, 2)
ws.Cells(iTarget, 8) = ws.Cells(iTarget, 8) + ws.Cells(iRow, 8)
ws.Rows(iRow).EntireRow.Delete
Else
dict(sKey) = iRow
End If
Next
' add new record from form using dictionary to locate any existing
iLastRow = ws.Cells(Rows.Count, "H").End(xlUp).Row
sKey = LCase(TextBox1.Text) & "~" & Format(DateValue(TextBox3.Text), "yyyy-mm-dd")
If dict.exists(sKey) Then
iTarget = dict(sKey)
ws.Cells(iTarget, 2) = ws.Cells(iTarget, 2) + TextBox2.Text
ws.Cells(iTarget, 8) = ws.Cells(iTarget, 8) + TextBox2.Text
Else
iTarget = iLastRow + 1
ws.Cells(iTarget, 1) = TextBox1.Text
ws.Cells(iTarget, 2) = TextBox2.Text
ws.Cells(iTarget, 3) = TextBox3.Text
ws.Cells(iTarget, 8) = TextBox2.Text
End If
End Sub

Troubles stopping my loop

Do While Cells(i, 1).Value <> ""
....
End If
i = i + 1
Loop
End Sub
Right. It works fine with numbers and stop perfectly. But With Text. It does not stop.
Ideally I want to stop at the last row of my content rather than my last row in Excel. I manage to make it work fine with numbers, but I cannot fix it with Text.
Any help would be great as I am a beginner in VBA.
Sub checkRoutine()
Dim i As Integer
Dim LastRow As Long
i = 1
Do While Cells(i, 1).Value <> ""
If IsNumeric(Cells(i, 1).Value) Then Cells(i, 2).Value = Cells(i, 1).Value & " " & Cells(7, 5).Value
If Not IsNumeric(Cells(i, 1).Value) Then
LastRow = Range("A" & Rows.Count).End(xlUp).row + 1
ActiveSheet.Cells(LastRow, "A").Value = Cells(i, 1).Value & " " & Cells(7, 5).Value
End If
i = i + 1
Loop
End Sub
As suggested by so many people, you need to change to use a For loop:
Sub checkRoutine()
Dim i As Long
Dim LastRow As Long
LastRow = Range("A" & Rows.Count).End(xlUp).row
For i = 1 To LastRow
If IsNumeric(Cells(i, 1).Value) Then
Cells(i, 2).Value = Cells(i, 1).Value & " " & Cells(7, 5).Value
Else
LastRow = Range("A" & Rows.Count).End(xlUp).row + 1
Cells(LastRow, "A").Value = Cells(i, 1).Value & " " & Cells(7, 5).Value
End If
Next
End Sub

Not able to operate on dynamic non empty cells

i have to sort data from sheet1 to sheet2 with reference to non-empty cell in column A. and
i have written code for it as below:
Sub polo()
Dim lastrow As Long
lastrow = Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
j = 2
For i = 1 To lastrow
If Sheets("Sheet1").Cells(i, 1).Value = "" Then
Sheets("Sheet2").Cells(j, 2).Value = Sheets("Sheet1").Cells(i, 1).Offset(, 1).Value
Sheets("Sheet2").Cells(j, 4).Value = Sheets("Sheet1").Cells(i - 1, 2).Value
j = j + 1
End If
Next i
End Sub
But the problem is, i am getting result as in column D of sheet2.
I want result as shown in column E.
Please help.
Try this version:
Sub polo()
Dim lastrow As Long
Dim sTemp as String
lastrow = Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
j = 2
For i = 1 To lastrow
If Sheets("Sheet1").Cells(i, 1).Value = "" Then
Sheets("Sheet2").Cells(j, 2).Value = Sheets("Sheet1").Cells(i, 1).Offset(, 1).Value
Sheets("Sheet2").Cells(j, 4).Value = stemp
j = j + 1
Else
stemp = Sheets("Sheet1").Cells(i, 2).Value
End If
Next i
End Sub

Resources