Loop through excel rows and call VBA functions - vba

I need to be able to loop through my rows (specifically, column B), and use the number in a certain cell in order to do specific functions using other cells in that row. For example, Rule #1 indicates that I need to find last modified date of the path in the cell next to the Rule #, but the task is different for each Rule.
I'm new to VBA and I've just been struggling with setting up a loop and passing variables to different subs, and would hugely appreciate any help. To be clear, I'm looking for syntax help with the loop and passing variables
Thank you!
Reference Images: The spreadsheet
The attempt at sketching out the code
Private Sub CommandButton1_Click()
Dim x As Integer
NumRows = Range("B2", Range("B2").End(xlDown)).Rows.Count
Range("B2").Select
For x = 1 To NumRows
If Range(RowCount, 1).Value = 1 Then
RuleOne (RowCount)
End If
Next
'Dim RowCount As Integer
'RowCount = 1
'Worksheets("Sheet2").Cells(1, 2) = Worksheets("Sheet1").UsedRange.Row.Count
'While RowCount < Worksheets("Sheet1").Rows
'If Worksheets("Sheet1").Cells(RowCount, 1).Value = 1 Then
'RuleOne (RowCount)
'End If
'Wend
End Sub
Sub RuleOne(i As Integer)
'use filedatetime and path from i cell
'Worksheets("Sheet2").Cells(1, 1) = FileDateTime(C, i)
Worksheets("Sheet2").Cells(1, 1) = "hello"
End Sub
Sub RuleTwo(i As Integer)
Worksheets("Sheet2").Cells(1, 1) = "hello"
End Sub

Try to change the Range(RowCount, 1).Value = 1 to Cells(x, 2).Value = 1.

The variable RowCount has not been initialised/set.
I assume this is what this variable is meant to be the number in column B
RowCount = Cells(x, "B").Value
I also noticed that the variable NumRows seemed to be one less than it should be (so if the last row was 1 it would skip it). So I used this instead:
NumRows = Cells(Rows.Count, "B").End(xlUp).Row
So try this code:
Sub CommandButton1_Click()
Dim x As Integer
NumRows = Cells(Rows.Count, "B").End(xlUp).Row
For x = 1 To NumRows
RowCount = Range("B" & x).Value
If RowCount = 1 Then
RuleOne (x)
End If
Next
'Dim RowCount As Integer
'RowCount = 1
'Worksheets("Sheet2").Cells(1, 2) = Worksheets("Sheet1").UsedRange.Row.Count
'While RowCount < Worksheets("Sheet1").Rows
'If Worksheets("Sheet1").Cells(RowCount, 1).Value = 1 Then
'RuleOne (RowCount)
'End If
'Wend
End Sub
Sub RuleOne(i As Integer)
'use filedatetime and path from i cell
'Worksheets("Sheet2").Cells(1, 1) = FileDateTime(C, i)
Worksheets("Sheet2").Cells(1, i) = "hello"
End Sub
Sub RuleTwo(i As Integer)
Worksheets("Sheet2").Cells(1, 1) = "hello"
End Sub

Related

Userform lockups using loops not working

I am trying to set up my user form to do a loop or look up to reference my table which is on a sheet and is a large data base.
I want my user form to look up what I type and then auto fill in the other textboxes so that I can limit the number of duplicates and make it more stream lined.
My code is as shown below is embedded into Textbox1 and is set up to run the code after change. It is still not working and I have worked for many days and weeks trying to figure this out.
Option Explicit
Dim id As String, i As String, j As Integer, flag As Boolean
Sub GetDataA()
If Not IsNumeric(UserForm1.TextBox1.Value) Then
flag = False
i = 0
id = UserForm1.TextBox1.Value
Do While Cells(i + 1, 1).Value <> ""
If Cells(i + 1, 1).Value = id Then
flag = True
For j = 2 To 7
UserForm1.Controls("TextBox" & j).Value = Cells(i + 1, j).Value
Next j
End If
i = i + 1
Loop
If flag = False Then
For j = 5 To 10
UserForm1.Controls("TextBox" & j).Value = ""
Next j
End If
Else
End If
End Sub
you may want to adopt this refactoring of your code
Option Explicit
Sub GetDataA()
Dim j As Integer
Dim f As Range
With UserForm1 '<--| reference your userform
If Not IsNumeric(.TextBox1.Value) Then Exit Sub '<--| exit sub if its TextBox1 value is not a "numeric" one
Set f = Range("A1", Cells(Rows.Count, 1).End(xlUp)).Find(what:=.TextBox1.Value, LookIn:=xlValues, lookat:=xlWhole) '<--| try and find its TextBox1 value along column "A" cells from row 1 down to last not empty one
If f Is Nothing Then '<--| if not found
For j = 5 To 10
.Controls("TextBox" & j).Value = ""
Next j
Else '<--| if found
For j = 2 To 7
.Controls("TextBox" & j).Value = f.Offset(, j - 1).Value
Next j
End If
End With
End Sub
note: if this sub is actually inside UserForm1 code pane than you can change With UserForm1 to With Me

'If ... Then' statement with loop

I've what seems like a pretty simple application with looping and 'If..Then' statements but need some help on structuring it.
In very a basic example, I have a list numbers in column A and the values PM or AM listed in column B. I want to write a loop that will search every value in column B until the end of the data set, and add 12 to each value in column A each time column B has a value of PM. In a nutshell, it would look like this:
If column B = PM
then add 12 to its corresponding cell in column A
else move down to the next row and do the same thing until you reach an empty cell
There are many ways, here is a typical one:
Sub dural()
Dim i As Long
i = 1
Do While Cells(i, "B").Value <> ""
If Cells(i, "B").Value = "PM" Then
Cells(i, "A").Value = Cells(i, "A").Value + 12
End If
i = i + 1
Loop
End Sub
you can set it with For next loop and 2 variables. one for last row and the 2nd for the row count:
Sub Macro1()
Dim LastRow As String
Dim i As Integer
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRow
If Cells(i, 2).Value = "PM" Then Cells(i, 1).vlaue = Cells(i, 1).vlaue + 10
Next i
End
'
End Sub
This is another way to do this.
Option Explicit
Sub Add()
Dim rData As Range
Dim r As Range
Set rData = Cells(1, 1).CurrentRegion.Columns("B").Cells
For Each r In rData
If UCase$(r.Value) = "PM" Then
r.Offset(, -1).Value = r.Offset(, -1).Value + 12
End If
Next r
End Sub

Issue with Do...Until Function VBA

I have an issue with my VBA code. I try to go through a whole table that has a lot of data. I go through a first column with a first condition required. Once this condition is complete, I go through the column next to the first one but starting at the same position I stopped the previous one. Once the second condition is complete, I try to do a copy paste. But for some reasons I got the error "Subscript out of Range" Could you please help me?
Here is the code:
Sub Match()
Dim i As Integer
i = 0
Dim j As Integer
Do
i = i + 1
Loop Until Sheets("Sheet1").Range("A1").Offset(i, 0).Text = Sheets("Sheet2").Range("I5").Text
j = i
Do
j = j + 1
Loop Until Sheets("Sheet1").Range("B1").Offset(j, 0).Value = Sheets("Sheet2").Range("I11").Value
Sheets("Sheet1").Range("C1").Offset(j, 0).Copy
Sheets("Sheet2").Range("N11").Paste
End Sub
Thanks guys
This should do the same thing without any loops:
Sub Match()
Dim lastA As Long, lastB As Long
Dim i As Long, j As Long
With Sheets("Sheet1")
last a = .Cells(.Rows.count, 1).End(xlUp).Row
last b = .Cells(.Rows.count, 2).End(xlUp).Row
End With
i = WorksheetFunction.Match(Sheets("Sheet2").Range("I5").Text, Sheets("Sheet1").Range("A:A"), 0)
j = WorksheetFunction.Match(Sheets("Sheet2").Range("I11").value, Sheets("Sheet1").Range("B" & i & ":B" & lastB), 0)
Sheets("Sheet2").Range("N11").value = Sheets("Sheet1").Cells(j, 3).value
End Sub
I didn't get the same error as you but I changed the last line and it seems to work.
Sub Match()
Dim i As Integer
i = 0
Dim j As Integer
Do
i = i + 1
Loop Until Sheets("Sheet1").Range("A1").Offset(i, 0).Text = Sheets("Sheet2").Range("I5").Text
j = i
Do
j = j + 1
Loop Until Sheets("Sheet1").Range("B1").Offset(j, 0).Value = Sheets("Sheet2").Range("I11").Value
Sheets("Sheet1").Range("C1").Offset(j, 0).Copy Destination:=Sheets("Sheet2").Range("N11")
End Sub
I did notice that your code runs for ever if you do not get a match which is not good. You may want to add a solution to this. It can be as easy as adding
Or i > 10000 on the Loop Until lines.
I modified your code slightly:
Sub Match()
Dim i As Integer
i = 0
Dim j As Integer
Do
i = i + 1
Loop Until Sheets("Sheet1").Range("A1").Offset(i, 0).Text = Sheets("Sheet2").Range("I5").Text
j = i
Do
j = j + 1
Loop Until Sheets("Sheet1").Range("B1").Offset(j, 0).Value = Sheets("Sheet2").Range("I11").Value
Sheets("Sheet1").Range("C1").Offset(j, 0).Copy Sheets("Sheet2").Range("N11")
End Sub
and it worked fine with data like:
In Sheet1.
Note the B match must be below the A match.

Error 1004 when multiplying cell values based on criteria

I have a macro which looks at a range of cells. Every other cell is either a 1 or a 0 (sign bit). Depending on the sign bit, the next cell (a normal number) is multiplied either by 1 or 0. I keep getting a run time error 1004 Application-defined or object-defined error on the body of the ElseIf of the If statement (indicated below). Not sure what I'm doing wrong. My code is in a "proof-of-concept" stage so it's still pretty hackish.
Dim N As Long
------------------------------------------
Private Sub CommandButton1_Click()
Dim x As Integer
Dim y As Integer
x = 0
y = 1
N = Application.InputBox(Prompt:="Enter value", Type:=1)
If N > Columns.Count Then
N = Columns.Count
Else
For i = 4 To 9999
Cells(1, i).ClearContents
Cells(3, i).ClearContents
Next i
End If
For i = 4 To N + 3
x = x + y
Cells(1, i) = x
Next i
For i = 4 To N + 3
If Cells(2, i) = 1 Then
Cells(2, i).Offset(0, 1).Select = Cells(2, i).Offset(0, 1).Select * -1
ElseIf Cells(2, i) = 0 Then
'This is the line with errors vvvvvvvvvvvvvvvvv
Cells(2, i).Offset(0, 1).Select = Cells(2, i).Offset(0, 1).Select * 1
End If
Next i
End Sub
That's because you're using Select. Obviously, Select and Activate don't give you values. They select or activate the cell, not different from manually clicking on them using the mouse or moving/activating to them using the keyboard or what else. Multiplying them by a value is a major no-no.
The Range property you should be looking for is Value. In any case, I think you're making it difficult because of having two loops. You really should reconsider your design pattern. In any case, here's my approach (mine's vertical, but it seems like yours is horizontal, so be clear exactly what is on your end so this can be adjusted).
Private Sub CommandButton1_Click()
Dim WS As Worksheet
Dim LastRow As Long
Dim Iter As Long
Dim CurrCell As Range
Const Col = 1
With ThisWorkbook
Set WS = .Sheets("Sheet3") 'Change as necessary.
End With
With WS
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
For Iter = 1 To LastRow 'Change as necessary.
Set CurrCell = .Cells(Iter, Col)
Select Case CurrCell.Value
Case 1
CurrCell.Offset(0, 1).Value = (CurrCell.Offset(0, 1).Value * (-1))
Case 0
CurrCell.Offset(0, 1).Value = (CurrCell.Offset(0, 1).Value * 1) 'Is this even necessary? It's an identity.
End Select
Next
End With
End Sub
Screenshot:
Let us know if this helps.

Copy a value down n-times

I have two tables: "VALUES" and "INSERT". In Table "INSERT" the cell "A1" contains a value that needs to be coped down as many times as there are rows > "" in "VALUES"
I have tried the following code but it does not work as I intended but copies the value of "A1" 4 times every other row in "VALUES".
What am I doing wrong? Thank you for your help!
Sub InsertValuePart()
Dim maxRow As Integer
Dim calcVal As String
Dim x As String
Dim i As Long
Sheets("VALUES").Select
maxRow = Cells(Rows.Count, 1).End(xlUp).row
Sheets("INSERT").Select
Cells(1, 1).Activate
x = Cells(1, 1).Value
Cells(2, 1).Select
For i = 1 To maxRow
Cells(i, 1).Value = x
i = i + 1
Next
Application.CutCopyMode = False
Range("A1").Select
End Sub
No need to define i as it is treated in your for command. Also a for command will automatically iterate over each value so using i = i + 1 will give you values of i = 1, 3, 5. If you do not include that then i = 1,2,3,....,maxRow. Also calcVal was not used anywhere so I got rid of it.
Sub InsertValuePart()
Dim maxRow As Integer
Dim x As String
maxRow = Sheets("VALUES").Cells(Rows.Count, 1).End(xlUp).Row
x = Sheets("INSERT").Cells(1, 1).Value
For i = 1 to maxRow
Sheets("INSERT").Cells(i,1).Value = x
Next
Sheets("INSERT").Range("A1").Select
End Sub
Another way to do it is listed below on one line:
Sub InsertValuePart()
Sheets("INSERT").Range("A1", "A" & CStr(Sheets("VALUES").Cells(Rows.Count, 1).End(xlUp).Row)).Value = Sheets("INSERT").Range("A1").Value
End Sub