Loop to update column is not working correctly - excel

I have a worksheet with data in Column A and Column B, I want to update Column C based on a condition that If
cellB is found in cellA, then cellB is written in Column C on the row of the match from column A.
With the help of the community, I have managed to come up with something but
can someone please tell me why the below loop only works for a few number of rows?
Also, sometimes Column B can be blank, is this a problem? If so, can i skip it if blank?
This works (perhaps its because all the cells have data in them):
Option Explicit
Sub Button2_Click()
Dim cellB As Range
Dim cellA As Range
For Each cellB In Range("b2:b5")
For Each cellA In Range("a2:a5")
If InStr(cellA, cellB) > 0 Then
Range("c" & cellA.Row) = cellB
End If
Next cellA
Next cellB
End Sub
This attempts to update Column C but the cellB values are never updated in the Column C (perhaps its because Column B contain nulls?):
Option Explicit
Sub Button2_Click()
Dim cellB As Range
Dim cellA As Range
For Each cellB In Range("b2:b500")
For Each cellA In Range("a2:a500")
If InStr(cellA, cellB) > 0 Then
Range("c" & cellA.Row) = cellB
End If
Next cellA
Next cellB
End Sub
Snapshot of the worksheet:

Try this way, plase. It will process all existing range, based on the A:A column filled range. It uses an array to collect the processing result and it should be fast enough:
Dim cellB As Range, cellA As Range, sh As Worksheet, lastRow As Long
Dim arrfin As Variant
Set sh = ActiveSheet 'use here your necessary sheet
lastRow = sh.Range("A" & Rows.count).End(xlUp).row
ReDim arrfin(1 To lastRow, 1 To 1)
sh.Range("C:C").Clear
For Each cellA In Range("a2:a" & lastRow)
For Each cellB In Range("b2:b" & lastRow)
If cellA.value <> "" And cellB.value <> "" Then
If InStr(cellA.value, cellB.value) > 0 Then
arrfin(cellA.row, 1) = cellB.value
End If
End If
Next cellB
Next cellA
sh.Range("C1").Resize(UBound(arrfin, 1), UBound(arrfin, 2)).value = arrfin

'For Next' vs 'For Each Next' feat. 'Range' vs 'Cells'
All five examples do the same thing.
They are best copied into a standard module (e.g. Module1) and are then easily run from VBE or called via a Button click event e.g.
Option Explicit
Sub Button2_Click()
updateForEachNextCellsVersion
End Sub
There are two For loops: the For Next loop and the For Each Next loop.
The first two examples use the For Each Next loop, while the remaining two use the For Next loop.
The 1st and 3rd example use Cells, while the 2nd and 4th use Range.
Why would you use Cells when Range is so much easier? You should know both. The biggest downside of Range is that you cannot loop through a row incrementing the columns. For this task only Cells can be used.
The usage of Cells with column numbers is shown in the 5th example.
The Code
Option Explicit
Sub updateForEachNextCellsVersion()
' Calculate the row of the last non-blank cell in column A.
Dim LastRow As Long: LastRow = Cells(Rows.Count, "A").End(xlUp).Row
' Declare the cell ranges for column A and B.
Dim celA As Range, celB As Range
' Loop through rows of column A.
For Each celA In Range(Cells(2, "A"), Cells(LastRow, "A")).Cells
' Loop through rows of column B.
For Each celB In Range(Cells(2, "B"), Cells(LastRow, "B")).Cells
' Check if the current cell in column B is not blank.
If Not IsEmpty(celB) Then
' Check if the values of the current cells in columns A and B
' are equal.
If celA.Value = celB.Value Then
' Write value of current cell in column B to
' column C, to the row of current cell in column A.
Cells(celA.Row, "C").Value = celB.Value
End If
End If
Next celB
Next celA
End Sub
Sub updateForEachNextRangeVersion()
' Calculate the row of the last non-blank cell in column A.
Dim LastRow As Long: LastRow = Range("A" & Rows.Count).End(xlUp).Row
' Declare the cell ranges for column A and B.
Dim celA As Range, celB As Range
' Loop through rows of column A.
For Each celA In Range("A2:A" & LastRow).Cells
' or: For Each celA In Range("A2", "A" & LastRow).Cells
' Loop through rows of column B.
For Each celB In Range("B2:B" & LastRow).Cells
' or: For Each celB In Range("B2", "B" & LastRow).Cells
' Check if the current cell in column B is not blank.
If Not IsEmpty(celB) Then
' Check if the values of the current cells in columns A and B
' are equal.
If celA.Value = celB.Value Then
' Write value of current cell in column B to
' column C, to the row of current cell in column A.
Range("C" & celA.Row).Value = celB.Value
End If
End If
Next celB
Next celA
End Sub
Sub updateForNextCellsVersion()
' Calculate the row of the last non-blank cell in column A.
Dim LastRow As Long: LastRow = Cells(Rows.Count, "A").End(xlUp).Row
' Declare the counters for the loops (i for column A, j for column B).
Dim i As Long, j As Long
' Loop through rows of column A.
For i = 2 To LastRow
' Loop through rows of column B.
For j = 2 To LastRow
' Check if the current cell in column B is not blank.
If Not IsEmpty(Cells(j, "B")) Then
' Check if the values of the current cells in columns A and B
' are equal.
If Cells(i, "A").Value = Cells(j, "B").Value Then
' Write value of current cell in column B to
' column C, to the row of current cell in column A.
Cells(i, "C").Value = Cells(j, "B").Value
End If
End If
Next j
Next i
End Sub
Sub updateForNextRangeVersion()
' Calculate the row of the last non-blank cell in column A.
Dim LastRow As Long: LastRow = Range("A" & Rows.Count).End(xlUp).Row
' Declare the counters for the loops (i for column A, j for column B).
Dim i As Long, j As Long
' Loop through rows of column A.
For i = 2 To LastRow
' Loop through rows of column B.
For j = 2 To LastRow
' Check if the current cell in column B is not blank.
If Not IsEmpty(Range("B" & j)) Then
' Check if the values of the current cells in columns A and B
' are equal.
If Range("A" & i).Value = Range("B" & j).Value Then
' Write value of current cell in column B to
' column C, to the row of current cell in column A.
Range("C" & i).Value = Range("B" & j).Value
End If
End If
Next j
Next i
End Sub
Sub updateForNextCellsColumnNumbersVersion()
' Calculate the row of the last non-blank cell in column A.
Dim LastRow As Long: LastRow = Cells(Rows.Count, 1).End(xlUp).Row
' Declare the counters for the loops (i for column A, j for column B).
Dim i As Long, j As Long
' Loop through rows of column A.
For i = 2 To LastRow
' Loop through rows of column B.
For j = 2 To LastRow
' Check if the current cell in column B is not blank.
If Not IsEmpty(Cells(j, 2)) Then
' Check if the values of the current cells in columns A and B
' are equal.
If Cells(i, 1).Value = Cells(j, 2).Value Then
' Write value of current cell in column B to
' column C, to the row of current cell in column A.
Cells(i, 3).Value = Cells(j, 2).Value
End If
End If
Next j
Next i
End Sub

Related

if then till last row

I want that if cell in column e is not blank but cell in column i is blank then write unregister in column i or else write what ever written in column i.
Please help - I have used below code:
Sub Simple_If()
Dim lastrow As Long
lastrow = Cells(Rows.Count, "F").End(xlUp).Row
If Range("e2:e" & lastrow).Value <> "" And Range("i2:i" & lastrow).Value = "" Then
Range("i2:i" & lastrow).Value = "unregister"
End If
End Sub
The reason your code was not working is because you can't get .value of a .range (Range("e2:e" & lastrow).Value <> ""). Instead, use a for loop to iterate through each cells value individually.
I have commented each line of the code below to help you understand what is happening.
To make this work, change SO.xlsm to the name of your workbook and 63649177 to the name of your worksheet.
Sub Simple_If()
Dim WB As Workbook ' workbook - full name of the file containing data.
Dim WS As Worksheet ' worksheet - worksheet within workbook containing data.
Dim lRow As Long ' last row - find last row containing data
Dim i As Long ' iteration - used for loop
Set WB = Workbooks("SO.xlsm") ' set the name of the workbook here
Set WS = WB.Worksheets("63649177") ' set the name of the worksheet here
lRow = WS.Cells(WS.Rows.count, "E").End(xlUp).Row ' find the last row of E in the WS object, not user defined.
Set Rng = WS.Range("E2:E" & lRow) ' set the initial range
For i = 2 To lRow ' from line 2 to the last row, repeat this loop
If WS.Range("E" & i).Value <> "" And WS.Range("I" & i).Value = "" Then ' if E contains data and I does not then
WS.Range("I" & i).Value = "unregister" ' fill cell with "unregister"
End If ' end if
Next ' cycle through next iteration of loop
End Sub
Output
Loop Through Rows
You were trying to check the values of two ranges "E2:E & LastRow" and "I2:I & LastRow" in one go, but you cannot do that. You have to loop through the rows of the ranges and check each cell i.e. "E2", "E3", "E4" ... "E" & LastRow and "I2", "I3", "I4" ... "I" & LastRow. For this task a For Next loop can used.
The 1st code is showing how it is done using Range.
The 2nd code is showing how it is done using column strings (letters) with Cells.
The 3rd code is showing how it is done using column numbers with Cells.
The 4th code is showing how you can define the column ranges (rng1, rng2) and use Cells with one parameter.
The 5th code is showing how you can define constants to store the so called 'magic' characters and later quickly access (change) them. It is also modified to be able to change the resulting column (tgtCol).
Range might seem easier, but you have to learn Cells, too, e.g. because you cannot loop through columns using Range, you have to use column numbers with Cells.
Study the first three codes closely, and you will learn the differences soon enough.
The Code
Option Explicit
Sub fillSimpleRangeVersion()
' Calculate the last non-blank cell in column "F".
Dim LastRow As Long
LastRow = Range("F" & Rows.Count).End(xlUp).Row
Dim i As Long
' Loop through the rows from 2 to LastRow.
For i = 2 To LastRow ' i will change: "2, 3, 4 ... LastRow"
' Check that current cell in column "E" is not blank and
' that current cell in column "I" is blank:
' If not E2 blank and I2 blank then,
' If not E3 blank and I3 blank then ...
' If not E & LastRow blank and I & LastRow blank then.
If Not IsEmpty(Range("E" & i)) And IsEmpty(Range("I" & i)) Then
' If true, write "unregister" to current cell in column "I".
Range("I" & i).Value = "unregister"
' The Else statement is not needed, because you only write when
' the condition is true.
Else
' If not true, do nothing.
End If
Next i
End Sub
Sub fillSimpleCellsStringsVersion() ' Column Strings E, F, I
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
Dim i As Long
For i = 2 To LastRow
If Not IsEmpty(Cells(i, "E")) And IsEmpty(Cells(i, "I")) Then
Cells(i, "I").Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsNumbersVersion() ' Column Numbers 5, 6, 9
Dim LastRow As Long
LastRow = Cells(Rows.Count, 6).End(xlUp).Row
Dim i As Long
For i = 2 To LastRow
If Not IsEmpty(Cells(i, 5)) And IsEmpty(Cells(i, 9)) Then
Cells(i, 9).Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsVersionWithRanges()
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
Dim rng1 As Range
Set rng1 = Range("E2:E" & LastRow)
Dim rng2 As Range
Set rng2 = Range("I2:I" & LastRow)
Dim i As Long
For i = 1 To rng1.Rows.Count
If rng1.Cells(i).Value <> "" And rng2.Cells(i).Value = "" Then
rng2.Cells(i).Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsExpanded()
Const FirstRow As Long = 2 ' First Row
Const LastRowCol As Variant = "F" ' The column to Calculate Last Row
Const Col1 As Variant = "E" ' Column 1
Const Col2 As Variant = "I" ' Column 2
Const tgtCol As Variant = "I" ' Target Column, the Column to Write to
' You want to write to the same column "CritCol2 = tgtCol", but if you
' want to write to another column, you can easily change "tgtCol".
Const Criteria As String = "unregister" ' Write Criteria
Dim LastRow As Long
LastRow = Cells(Rows.Count, LastRowCol).End(xlUp).Row
Dim i As Long
For i = FirstRow To LastRow
If Not IsEmpty(Cells(i, Col1)) And IsEmpty(Cells(i, Col2)) Then
Cells(i, tgtCol).Value = Criteria
Else
' The following line is only needed if "CritCol2" is different
' than "tgtCol".
Cells(i, tgtCol).Value = Cells(i, Col2).Value
End If
Next i
End Sub

Excel VBA, If cell is not numeric and empty in a column, selected cell copy and paste to another column

A B C
a rm rm
b
c
d 4000
e 5000
f r1 r1
g c1 c1
h 103
i 1.8
For example, in B Column, if cell value are not number, copy the value to C Column
how to make that code?
please, inquiry for that!
The formula to do it would be: =IF(ISNUMBER(CELL), " ", CELL)
For your case put this snippet right in C2 and copy it down: =IF(ISNUMBER(B2), " ", B2)
At first you need to find the last non blank row number of column A.
Then run a loop and check if the value of column A is numeric or not.
Public Sub M()
Dim sh As Worksheet
Set sh = Worksheets("Worksheet name here")
Dim lastrow As Long, i As Long
lastrow = sh.Cells(1048576, 2).End(xlUp).Row
For i = 1 To lastrow
If IsNumeric(.Cells(i, 2).Value) = False Then
.Cells(i, 3).Value = .Cells(i, 2).Value
End If
Next i
End Sub
You could try:
Formula:
=IF(AND($B1<>"",ISNUMBER($B1)=FALSE),$B1,"")
VBA:
Sub test()
Dim LastRow As Long, i As Long
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRow
If .Range("B" & i).Value <> "" And Not IsNumeric(.Range("B" & i).Value) Then
.Range("C" & i).Value = .Range("B" & i).Value
End If
Next i
End With
End Sub

How do I round columns based on heading type

I have a table consisting of strings and numbers. Row one contains the heading and row two contains the unit type (percent and dollars). I would like to round the numbers in the column based on the heading in row two.
At the moment I am selecting the columns individually. Is there a way to round the column based on the heading in row two?
Sub Round()
Dim Lastrow As Long
Lastrow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row 'Determine
last row
For Each cell In ActiveSheet.Range("R3:R" & Lastrow)
cell.Value = WorksheetFunction.Round(cell.Value, 2) 'Round dollars to 2 places
Next cell
For Each cell In ActiveSheet.Range("AB3:AB" & Lastrow)
cell.Value = WorksheetFunction.Round(cell.Value, 2)
Next cell
For Each cell In ActiveSheet.Range("Q3:Q" & Lastrow)
cell.Value = WorksheetFunction.Round(cell.Value, 1) 'Round percentages to 1 places
Next cell
....
End Sub
You were close enough, just needed a bit from both of those tries together. Please see if the below helps, I've added an alternative using arrays as well (if you have lots of data, it will be much faster):
Sub RoundRanges()
Dim ws As Worksheet: Set ws = ActiveSheet 'better use something like: ActiveWorkbook.Sheets("Sheet name here")
Dim lRow As Long: lRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row 'get last row
Dim lCol As Long: lCol = ws.Cells(2, ws.Columns.Count).End(xlToLeft).Column 'get last column
Dim R As Long, C As Long
For C = 1 To lCol 'iterate through each column
Select Case ws.Cells(2, C) 'get the text of the cell 2...
Case "Percent"
For R = 3 To lRow 'iterate through each row
ws.Cells(R, C) = WorksheetFunction.Round(ws.Cells(R, C).Value, 1) 'apply the desired calculation
Next R
Case "Dollars"
For R = 3 To lRow 'iterate through each row
ws.Cells(R, C) = WorksheetFunction.Round(ws.Cells(R, C).Value, 2) 'apply the desired calculation
Next R
End Select
Next C
'ALTERNATIVE:
'Dim arrData As Variant: arrData = ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol))
'For R = LBound(arrData) + 2 To UBound(arrData) 'skip first 2 rows
' For C = LBound(arrData, 2) To UBound(arrData, 2)
' If arrData(2, C) = "Percent" Then
' arrData(R, C) = Round(arrData(R, C), 1)
' ElseIf arrData(2, C) = "Dollars" Then
' arrData(R, C) = Round(arrData(R, C), 2)
' End If
' Next C
'Next R
'ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol)) = arrData
End Sub

how to compare two column and copy the value in VBA

I'm trying to figure out how to write compare code. I have two sheets', sheet1 and sheet2.
in sheet1 have five digits id numbers in column A, in sheet2 have same five digits id number in column C, but in sheet2 the id number is not the same row as column A in sheet1, they are differents row.
I'm trying to figure out how to make comparisons in sheet1 column A to search for a match in ANY row in sheet2 column B then copy the value from the same row in sheet2 Column C to sheet1 column D!
this is my own testing code but is not working.
Sub FindStuff()
Dim lr As Long
Dim i As Integer
lr = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To lr
If UCase(Sheet2.Cells(1, 3).Value) = UCase(Sheet1.Cells(i, 1).Value) Then
Sheet2.Cells(14, 5).Value = Sheet1.Cells(i, 1).Offset(, 5).Value
End If
Next i
End Sub
The code you post has both syntax error and logic error, I'm not sure exactly what you are trying to do. Can you post an workbook example?
I changed your formula with Vlookup in the code, you can test and let me know if this is what you need.
Sub MatchValues()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim lr As Long
Dim r As Long
Application.ScreenUpdating = False
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
lr = ws2.Cells(Rows.Count, 3).End(xlUp).Row
For r = 2 To lr
On Error Resume Next
Cells(r, 4) = WorksheetFunction.VLookup(ws2.Cells(r, 3).Value, _
ws1.Range("A:A"), 1, 0)
Next
Application.ScreenUpdating = True
End Sub

Macro to fill blank cells within a range

Let's say i have the range of cells A1:C3 and i need to fill in any empty cells from the range with the value that is in cells A4:C4, the emplty cells in column A will be filled with the value of A4, those in column B with the value from B4 and so on.
This is dynamic by both Rows and Columns. The assumption is that the last row is the cell that will be used to fill in blanks. If the assumption is true, you can add rows and columns as you please and this code will work without any modification
Determine last row in range (Determined by Column A)
Determine last column (Determined by last row in step 1)
Loop through rows column by column
Fill blanks with the value associated with the last row if blank
Option Explicit
Sub Test()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1") '<== Update Sheet Name
Dim LRow As Long, LCol As Long, r As Long, c As Long
LRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
LCol = ws.Cells(LRow, ws.Columns.Count).End(xlToLeft).Column
Application.ScreenUpdating = False
For c = 1 To LCol
For r = 1 To LRow - 1
If ws.Cells(r, c) = "" Then
ws.Cells(r, c).Value = ws.Cells(LRow, c).Value
End If
Next r
Next c
Application.ScreenUpdating = True
End Sub
Both examples below are from the same macro. Notice that it works as expected for your propsed example (4 Rows x 3 Columns) and for other table sizes like the example on right (8 Rows x 7 Columns)
If all the cells in A1:C3 are empty, then consider:
Sub FillInTheBlanks()
Range("A1:C3").Value = Range("A4:C4").Value
End Sub
If some of the cells in A1:C3 are not empty, then use:
Sub FillInTheBlanks2()
For i = 1 To 3
For j = 1 To 3
If Cells(i, j) = "" Then
Cells(4, j).Copy Cells(i, j)
End If
Next j
Next i
End Sub
You can try this.. just change Worksheets(1) to your desired Worksheet and 4 to desired row
Dim rng As Range
Dim cel As Range
With ThisWorkbook.Worksheets(1)
Set rng = .Range("A1:C3")
For each cel in rng
If Len(Trim(CStr(cel.Value))) = 0 Then cel.Value = .Cells(4, cel.Column).Value
Next
End With

Resources