Currently working on an excel sheet to rank projects, we would like it to automatically increase the numbers if we insert a new line and input an existing number rank. If we put in a line and type in 9 for its rank we want the pre existing 9 to move to 10 and the old 10 to move to 11 etc. I have kind of worked it out, however my code automatically numbers the first row as 1 and so forth. This is what I have so far.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim I As Integer
I = 1
Application.EnableEvents = False
For I = 1 To 20
Range("A" & I).Value = I
Next
Range("A21").Value = ""
Application.EnableEvents = True
End Sub
You could loop through every cell in column A and, if its value is greater than (or equal to) the one just changed, increment it by one:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim I As Long
Dim v As Long
Dim r As Range
Set r = Application.Intersect(Range("A:A"), Target)
If r Is Nothing Then
Exit Sub
End If
If r.Count > 1 Then
Exit Sub
End If
If IsEmpty(r.Value) Then
Exit Sub
End If
I = 1
v = r.Value
If Application.CountIf(Range("A:A"), v) > 1 Then ' Only change things if this
' value exists elsewhere
Application.EnableEvents = False
For I = 1 To Cells(Rows.Count, "A").End(xlUp).Row
If Cells(I, "A").Address <> r.Address Then
If IsNumeric(Cells(I, "A").Value) Then ' skip cells that aren't numeric
If Cells(I, "A").Value >= v Then
Cells(I, "A").Value = Cells(I, "A").Value + 1
End If
End If
End If
Next
Application.EnableEvents = True
End If
End Sub
Related
I have an admin sheet that has a column containing a list of True and False. I am building a userform UI so users can click next (for now - building previous button after making next work), the userform will show the next False item in admin sheet and its corresponding data in Sheet1 will be displayed in Textbox1.
Reason for this is the row id in admin sheet correlates with Sheet1. So if data in Sheet1 row(31) has something wrong, column(13) in Admin sheet row(31) will be False.
Code:
Dim n As Long
Private Sub CommandButton1_Click()
Dim LR As Long
LR = Sheets("Sheet1").Cells(Rows.count, "B").End(xlUp).row
n = 7
With Worksheets("Admin")
For i = n To LR
If .Cells(i, 13).Value = "False" Then
With Worksheets("Sheet1")
Me.TextBox1 = .Cells(i, 2).Value
Exit For
End With
End If
Next i
End With
n = i + 1
End Sub
This successfully goes to the next False item and displays it correctly in Textbox1. However, it does not iterate to the next one..
Whatever logic we use to set up Next, I am going to assume Previous will be the same?
Thanks guys.
You can do something like this:
Sub cmdNext_Click()
FindRow True
End Sub
Sub cmdPrev_Click()
FindRow False
End Sub
Private Sub FindRow(bForward As Boolean)
Const RW_START As Long = 7
Dim LR As Long, t As Long, dir As Long, i As Long
LR = Sheets("Sheet1").Cells(Rows.Count, "B").End(xlUp).Row
'going forwards, or back?
If bForward Then
n = IIf(n = 0, RW_START, n + 1) '<< Start at top
t = LR '<< towards here
dir = 1 '<< increasing
Else
n = IIf(n = 0, LR, n - 1) '<< Start at bottom
t = RW_START '<< towards here
dir = -1 '<< decreasing
End If
For i = n To t Step dir
If Worksheets("Admin").Cells(i, 13).Value = "False" Then
Me.TextBox1 = Worksheets("Sheet1").Cells(i, 2).Value
n = i
Exit For
End If
Next i
End Sub
I have a spreadsheet where i implement a score board.
The behavior i need is when the cell that has the score value rises the cell near it, on column b, changes it's color to green, when the the cell score value goes down the cell near it changes it's color to red.
The cell range where the score is changing is e5:e67
In short:
When the user inputs a number in column f, the score raises in column e, and in column b (on same row) the color must change to green or red
I made this VBA code, but without luck.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("e5:e67")) Is Nothing Then
If Target.Column = 5 Then
thisRow = Target.Row
Dim OldValue As Variant
Application.EnableEvents = False
Application.Undo
OldValue = Target.Value
Application.Undo
Application.EnableEvents = True
If OldValue < Target.Value Then
Range("b" & thisRow).Interior.ColorIndex = 4
ElseIf OldValue > Target.Value Then
Range("b" & thisRow).Interior.ColorIndex = 3
End If
End If
End If
End Sub
Here is a screen capture of my ranking sheet:
Try by intercepting the Worksheet_Calculate event. You need to save the old value in a static local array, that I call oldVal.
Private Sub Worksheet_Calculate()
Static oldVal
If IsEmpty(oldVal) Then
oldVal = Application.Transpose(Range("e5:e67").Value2)
ReDim Preserve oldVal(5 To 67)
Exit Sub
End If
Dim i As Long
For i = LBound(oldVal) To UBound(oldVal)
If oldVal(i) > Cells(i, "E").Value2 Then Cells(i, "B").Interior.ColorIndex = 3
If oldVal(i) < Cells(i, "E").Value2 Then Cells(i, "B").Interior.ColorIndex = 4
oldVal(i) = Cells(i, "E").Value2
Next
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
If Not Intersect(Target, Range("e6:e67")) Is Nothing Then
If Target.Offset(-1) < Target Then
i = 4
Else
i = 3
End If
Range("b" & Target.Row).Interior.ColorIndex = i
End If
End Sub
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
I have created an excel VBA script to move rows to different sheets based on the status of the item in that row. However, when I run the code it does not always move all the items at once if there is more than one status update. I would like to make it so that if multiple rows have status updates, when I run the script they all move at once. I'm assuming it has something to do with the "if statements" but I am drawing a blank on any other ways to do it. Any help is greatly appreciated. Thanks!
Below is my code:
Sub MoveRows()
Dim xRg As Range
Dim xCell As Range
Dim A As Long
Dim B As Long
Dim C As Long
Dim D As Long
A = Worksheets("Tracking").UsedRange.Rows.Count
B = Worksheets("In Progress").UsedRange.Rows.Count
C = Worksheets("Completed").UsedRange.Rows.Count
D = Worksheets("Removed").UsedRange.Rows.Count
If B = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("In Progress").UsedRange) = 0 Then B = 0
ElseIf C = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Completed").UsedRange) = 0 Then C = 0
ElseIf D = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Removed").UsedRange) = 0 Then D = 0
End If
Set xRg = Worksheets("Tracking").Range("S1:S" & A)
On Error Resume Next
Application.ScreenUpdating = False
For Each xCell In xRg
If CStr(xCell.Value) = "In Progress" Then
xCell.EntireRow.Copy Destination:=Worksheets("In Progress").Range("A" & B + 1)
xCell.EntireRow.Delete
B = B + 1
ElseIf CStr(xCell.Value) = "Completed" Then
xCell.EntireRow.Copy Destination:=Worksheets("Completed").Range("A" & C + 1)
xCell.EntireRow.Delete
C = C + 1
ElseIf CStr(xCell.Value) = "Remove" Then
xCell.EntireRow.Copy Destination:=Worksheets("Removed").Range("A" & D + 1)
xCell.EntireRow.Delete
D = D + 1
End If
Next
Application.ScreenUpdating = True
End Sub
edited to add selected rows deletion
just be sure to have a header row in your "Tracking" worksheet and then AutoFilter() will make your life as easy as the following code:
Option Explicit
Sub MoveRows()
Application.ScreenUpdating = False
With Worksheets("Tracking")
With .Range("S1", .Cells(.Rows.count, "S").End(xlUp))
FilterAndCopy .Cells, "In Progress"
FilterAndCopy .Cells, "Completed"
FilterAndCopy .Cells, "Remove"
End With
End With
Application.ScreenUpdating = True
End Sub
Sub FilterAndCopy(rng As Range, filterStrng As String)
With rng '<--| reference passed 'rng' range
.AutoFilter Field:=1, Criteria1:=filterStrng '<--| filter its 1st column with passed 'filterStrng'
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then '<--| if any cell filtered other than header
With .Resize(.Rows.count).Offset(1).SpecialCells(xlCellTypeVisible).EntireRow
.Copy Destination:=Worksheets(filterStrng).Cells(Rows.count, "A").End(xlUp).Offset(1) '<--|copy filtered cells (skipping headers row) to passed 'filterStrng' named worksheet 1st column from its column A first empty row after last not empty one
.Delete
End With
End If
.Parent.AutoFilterMode = False
End With
End Sub
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