VBA loop selection.find - excel

I want to loop or find multiple value in another sheets. My code doesn't work even after I do..loop the code.
For i = 1 To lastrowBAU
Worksheets(fname).Range("A1:A" & lastrowsheet).Select
Do Until Cell Is Nothing
Set Cell = Selection.find(What:=ThisWorkbook.Worksheets("BAU").Range("A" & i).Value, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
MatchCase:=False)
If Not Cell Is Nothing Then
Cell.Activate
ActiveCell.Copy
ActiveCell.Insert Shift:=xlShiftDown
ActiveCell.Offset(1, 0).Select
Selection.Replace What:=ThisWorkbook.Worksheets("BAU").Range("A" & i).Value, _
replacement:=ThisWorkbook.Worksheets("BAU").Range("B" & i).Value, _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False
Set Cell = Worksheets(fname).Range("A1:A" & lastrowsheet).FindNext(Cell)
End If
Loop
Next i

You need to set the cell before entering the loop
Set cell = rngSrc.Find(sA, LookIn:=xlFormulas, LookAt:=xlPart, _
After:=rngSrc.Cells(rngSrc.Cells.Count), SearchOrder:=xlByRows, MatchCase:=False)
If Not cell Is Nothing Then
however you also need to avoid an endless loop by checking if the search has returned to the first one found.
Option Explicit
Sub macro1()
Dim ws As Worksheet, wsBAU As Worksheet
Dim cell As Range, rngSrc As Range
Dim fname As String, lastrow As Long, lastrowBAU As Long
Dim i As Long, n As Long, first As String
Dim sA As String, sB As String
fname = "Sheet1"
With ThisWorkbook
Set ws = .Sheets(fname)
Set wsBAU = .Sheets("BAU")
End With
With ws
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngSrc = .Range("A1:A" & lastrow)
End With
With wsBAU
lastrowBAU = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With ws
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngSrc = .Range("A1:A" & lastrow)
End With
' search and replace
Application.ScreenUpdating = False
For i = 1 To lastrowBAU
sA = wsBAU.Cells(i, "A")
sB = wsBAU.Cells(i, "B")
Set cell = rngSrc.Find(sA, LookIn:=xlFormulas, LookAt:=xlPart, _
After:=rngSrc.Cells(rngSrc.Cells.Count), SearchOrder:=xlByRows, MatchCase:=False)
If Not cell Is Nothing Then
first = cell.Address
Do
' insert cell above
cell.Insert xlDown
cell.Offset(-1).Value2 = cell.Value2
cell.Value2 = Replace(cell.Value2, sA, sB)
' expand search range
n = n + 1
Set rngSrc = ws.Range("A1:A" & lastrow + n)
' find next
Set cell = rngSrc.FindNext(cell)
Loop While cell.Address <> first
End If
Next
Application.ScreenUpdating = True
MsgBox n & " replacements", vbInformation
End Sub

Related

How to write data continuously from UserForm to excel sheet vba?

I am trying to add new data to excel sheet via UserForm but it's doesn't write continuously. just replace value of range E2 and its rows.
Note:If data already exist then update its relevant columns or write
new data to next empty row.
my code is below.
Option Explicit
Private Sub cmdAdd_Click()
Dim FindValue As String, Rng As Range
Dim iRow As Long, ws2 As Worksheet
Set ws2 = Worksheets("ITEM NAMES")
iRow = ws2.Cells(Rows.Count, 2).End(xlUp).Row + 1
FindValue = TextItemName
If Trim(FindValue) <> "" Then
With ws2.Range("E:E")
Set Rng = .Find(What:=FindValue, _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not Rng Is Nothing Then
Rng.Offset(0, 1) = TextHSNCode.Value
Else
ws2.Cells(iRow, 5).Value = TextItemName.Value
ws2.Cells(iRow, 6).Value = TextHSNCode.Value
End If
End With
End If
End Sub

Trying to find value in range and get its row. Variable not set error?

The code below is supposed to take the value for net in each month, copies it, search for net name in range1(another worksheet) and pastes value in the cell corresponding to that row and column "AA".
This part of code is having issue:
Set Netrng = Range("AA" & Range1.Find(What:=Net, After:=ActiveCell, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Rows.row)
The error is -
object variable or with block variable not set.
what am I doing wrong?
Sub test()
Dim Range2 As Range
Dim lRow As Long
Dim Count As Long
Dim Net As String
Dim Line As Range
Dim Netrng As Range
Dim First As Range
Dim Range1 As Range
Dim wb As Worksheet
Set First = ActiveCell
Set wb = ActiveSheet
Set Range1 = wb.Range(First, First.End(xlDown))
ActiveWindow.ActivatePrevious
ActiveSheet.PivotTables("PivotTable1").PivotFields("Client Code").CurrentPage _
= "BUN"
ActiveSheet.Range("B5").Activate
lRow = Cells(Rows.Count, 1).End(xlUp).row - 6
Set Range2 = Range(ActiveCell.Offset(2, -1), ActiveCell.Offset(lRow, -1))
Set Months = Range(ActiveCell.Offset(0, 0), ActiveCell.Offset(0, 2))
Count = 1
While Count <= Range2.Count
Set Line = Range2.Rows(Count)
Net = Line.Value
Line.Offset(0, 1).Copy
ActiveWindow.ActivatePrevious
Set Netrng = Range("AA" & Range1.Find(What:=Net, After:=ActiveCell, LookIn:=xlValues, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).row)
Netrng.Offset(0, 4).PasteSpecial Paste:=xlPasteValues
Netrng.Value = 0
ActiveWindow.ActivatePrevious
Line.Offset(0, 2).Copy
ActiveWindow.ActivatePrevious
Netrng.Offset(0, 8).PasteSpecial Paste:=xlPasteValues
ActiveWindow.ActivatePrevious
Count = Count + 1
Wend
End Sub
As is, the code is assuming that the Find is successful, which may not always be the case.
To test:
Dim foundRng as Range
Set foundRng = Range1.Find(What:=Net, After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not FoundRng is Nothing Then
Set Netrng = Range("AA" & foundRng.Row)
...
End If
Other recommendations:
Avoid using Select and Activate. (and ActiveCell, ActiveWindow, anything Active).
Fully qualify which Workbook and Worksheet each Range is on (helpful reading in the answer on avoiding Select).
While...Wend is old-fashioned. Use a For Each loop.

How to accelerate an Excel VB Macro

I am trying to accelerate my Excel VB Macro.
I have tried the 5 alternatives below.
But I wonder if I could shorten the execution further.
I found 2 alternatives in User Blogs which I could not get to work.
One alternative is also found in a User Blog but do not understand.
Sub AccelerateMacro()
'
' v1 052817 by eb+mb
' Macro to copy as fast as possible sheet from one workbook into another workbooks
' Declarations for variables are not shown to make code example more legible
' Macro is stored in and run from "DestinationWorkBook.xlsm"
StartTime = Timer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Alternative = "First"
If Alternative = "First" Then
Workbooks.Open Filename:="SourceWorkBook.xls"
Cells.Select
Selection.Copy
Windows("DestinationWorkBook.xlsm").Activate
Sheets("DestinationSheet").Select
Range("A1").Select
ActiveSheet.Paste
Windows("SourceWorkBook.xls").Activate
ActiveWorkbook.Close
End If
If Alternative = "Second" Then
Workbooks.Open Filename:="SourceWorkBook.xls", ReadOnly:=True
Cells.Select
Selection.Copy
Windows("DestinationWorkBook.xlsm").Activate
Sheets("DestinationSheet").Select
Range("A1").Select
ActiveSheet.Paste
Workbooks("SourceWorkBook.xls").Close SaveChanges:=False
End If
If Alternative = "Third" Then
' I could not get this alternative to work
Workbooks.Open("SourceWorkBook.xls").Worksheets("SourceSheet").Copy
Workbooks.Open("DestinationWorkBook.xlsm").Worksheets("DestinationSheet").Range("A1").PasteSpecial
End If
If Alternative = "Fourth" Then
' I could not get this alternative to work
Workbooks.Open("DestinationWorkBook.xlsm").Worksheets("DestinationSheet").Range("A1") = Workbooks.Open("SourceWorkBook.xls").Worksheets("SourceSheet")
End If
If Alternative = "Fifth" Then
' I don't understand the code in this alternative
Dim wbIn As Workbook
Dim wbOut As Workbook
Dim rSource As Range
Dim rDest As Range
Set wbOut = Application.Workbooks.Open("DestinationWorkBook.xlsm")
Set wbIn = Application.Workbooks.Open("SourceWorkBook.xls")
With wbIn.Sheets("SourceSheet").UsedRange
wbOut.Sheets("DestinationSheet").Range("A1").Resize(.Rows.Count, .Columns.Count) = .Value
End With
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
End Sub
Instead of using UsedRange, find the actual Last Row and Last Column and use that range. UsedRange may not be the range that you think it is :). You may want to see THIS for an explanation.
See this example (UNTESTED)
Sub Sample()
Dim wbIn As Workbook, wbOut As Workbook
Dim rSource As Range
Dim lRow As Long, LCol As Long
Dim LastCol As String
Set wbOut = Workbooks.Open("DestinationWorkBook.xlsm")
Set wbIn = Workbooks.Open("SourceWorkBook.xls")
With wbIn.Sheets("SourceSheet")
'~~> Find Last Row
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find Last Column
LCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'~~> Column Number to Column Name
LastCol = Split(Cells(, LCol).Address, "$")(1)
'~~> This is the range you want
Set rSource = .Range("A1:" & LastCol & lRow)
'~~> Get the values across
wbOut.Sheets("DestinationSheet").Range("A1:" & LastCol & lRow).Value = _
rSource.Value
End With
End Sub

Moving Data with vba

I received data in column F,G,H, and I. I need to get that all into column E and take out the duplicates and the blank cells. The code i have so far works but it puts them all in the same row and doesn't keep them on their appropriate lines. I need them to stay on the same line they are currently in but to just transcribe over into the other column. This is what I have so far:
Sub Sample()
Dim ws As Worksheet
Dim LastRow As Long, lastCol As Long, i As Long
Dim Rng As Range, aCell As Range, delRange As Range '<~~ Added This
Dim MyCol As New Collection
~~> Change this to the relevant sheet name
Set ws = Sheets("Sheet1")
With ws
'~~> Get all the blank cells
Set delRange = .Cells.SpecialCells(xlCellTypeBlanks) '<~~ Added This
'~~> Delete the blank cells
If Not delRange Is Nothing Then delRange.Delete '<~~ Added This
LastRow = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
lastCol = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, MatchCase:=False).Column
Set Rng = .Range("A1:" & Split(.Cells(, lastCol).Address, "$")(1) & LastRow)
'Debug.Print Rng.Address
For Each aCell In Rng
If Not Len(Trim(aCell.Value)) = 0 Then
On Error Resume Next
MyCol.Add aCell.Value, """" & aCell.Value & """"
On Error GoTo 0
End If
Next
.Cells.ClearContents
For i = 1 To MyCol.Count
.Range("A" & i).Value = MyCol.Item(i)
Next i
'~~> OPTIONAL (In Case you want to sort the data)
.Columns(1).Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
End With
End Sub
Try this.
Sub CopyThingy()
Dim wb As Workbook
Dim ws As Worksheet
Dim lCount As Long
Dim lCountMax As Long
Dim lECol As Long
Dim lsourceCol As Long
lECol = 5 '* E column
Set wb = ThisWorkbook
Set ws = wb.Sheets(1) '*Your Sheet
lCountMax = ws.Cells(ws.Rows.Count, "F").End(xlUp).Row
lsourceCol = 6
lCount = lCountMax
Do While lCount > 1
If ws.Cells(lCount, lsourceCol) <> "" Then
ws.Cells(lCount, lECol).Value = ws.Cells(lCount, lsourceCol).Value
End If
lCount = lCount - 1
Loop
lCountMax = ws.Cells(ws.Rows.Count, "G").End(xlUp).Row
lsourceCol = 7
lCount = lCountMax
Do While lCount > 1
If ws.Cells(lCount, lsourceCol) <> "" Then
ws.Cells(lCount, lECol).Value = ws.Cells(lCount, lsourceCol).Value
End If
lCount = lCount - 1
Loop
lCountMax = ws.Cells(ws.Rows.Count, "H").End(xlUp).Row
lsourceCol = 8
lCount = lCountMax
Do While lCount > 1
If ws.Cells(lCount, lsourceCol) <> "" Then
ws.Cells(lCount, lECol).Value = ws.Cells(lCount, lsourceCol).Value
End If
lCount = lCount - 1
Loop
End Sub

How can a macro search for another cell which have the same value, and then change the value's?

I want the macro to look for same value as in B2. And then copy the value from range D2:G2 to the found range. In this example D9:G9.
Thank you in advance :D.
I tried:
Sub Button1_Click()
Dim myRng1, myRng2 As Range, cell As Range
Set myRng1 = Range("A4:A1000")
Set myRng2 = Range("D2:G2")
myRng2.Select
Selection.Copy
For Each cell In myRng1
If Range("A2") = Range("A" & cell.Row) Then Range("D" & cell.Row).Select
ActiveSheet.Paste
Next cell
End Sub
Sub Find()
Dim Findcode As String
Dim Rng As Range
Range("A2:F2").Select
Selection.Copy
Findcode = Sheets("Sheet1").Range("a2").Value
If Trim(Findcode) <> "" Then
With Sheets("Sheet1").Range("A4:A60000")
Set Rng = .Find(What:=Findcode, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
ActiveSheet.Paste
Else
MsgBox "Nothing found"
End If
End With
End If
End Sub

Resources