how to select specific cell to next one after the cell filled - excel

I would like to specify my excel to go on my cells. I mean when the first cell should be S5, and when this filled go to C6, then to C11, E11, G11, I11, K11, M11, O11, Q11, S11, then C12 E12........same method till s34 then goto H36.
I am try to use this:
If Not IsEmpty(Range("$C$11:$Q$11").Value) Then ActiveCell.Offset(0, 1).Select
Unfortunately in this case the active cell go one row down and one column right, and use not only in the specified range. I am not good in Excel macro.

Run this code and see what it does.
I'm not sure what exactly you are doing so this just shows the cell address as an illustration.
Sub x()
Dim cl As Range, r As Long
For r = 11 To 12
For Each cl In Range("C" & r & ", E" & r & ",G" & r)
MsgBox cl.Address
Next cl
Next r
End Sub

Take a look at the worksheet_change event. When you edit a cell you can then check which cell you are exiting from and force a move to the desired one.

By and large, the code below does what you describe. Please install it on the code sheet of the worksheet on which you want the action (NOT a standard code module). The correct location is critical for its functioning.
Private Sub Worksheet_Activate()
Cells(5, "S").Select
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Rng As Range
Dim C As Long
Dim R As Long
If Target.Cells.CountLarge > 1 Then Exit Sub
Set Rng = Application.Union(Range("S5"), Range("C6"))
For C = 5 To 19 Step 2
Set Rng = Application.Union(Rng, Range(Cells(11, C), Cells(34, C)))
Next C
If Not Application.Intersect(Target, Rng) Is Nothing Then
Select Case Target.Row
Case 5
Rng.Areas(2).Select
Case 6
With Rng.Areas(1)
If Len(.Value) = 0 Then
GoBack .Row, .Column
Else
Rng.Areas(3).Cells(1).Select
End If
End With
Case Else
C = Rng.Areas.Count
With Rng.Areas(C)
If Target.Address = .Cells(.Cells.Count).Address Then
Cells(36, "H").Select
Else
With Target
R = .Row
C = .Column + 2
End With
If C > .Column Then
R = R + 1
C = Rng.Areas(3).Column
End If
Cells(R, C).Select
End If
End With
End Select
End If
End Sub
Private Sub GoBack(R As Long, _
C As Long)
Dim Cell As Range
Set Cell = Cells(R, C)
MsgBox "Cell " & Cell.Address(0, 0) & " must be filled first.", _
vbExclamation, "Missing data"
Cell.Select
End Sub
I have programmed it so that S5 is selected whenever the sheet is activated. After the user makes a change to it C6 will be selected. If C6 is changed the code checks if S5 was filled and directs the user to go back if it's still blank. This method could be expanded to encompass a complete check if all cells must be filled. As the code is now the selection moves to the next cell when a change is made and to H36 after S34 was filled.

Related

Trace Dependencies for user defined range and list Source Cell/Dependency Cell in separate sheet

I have a range of cells (user defined) that I want vba to tell me which cell(s) these are linked to.
Every source cell can be linked to 1 or multiple cells.
I have the code so far that it
prompts the user for the range
checks that only 1 row is selected.
counts the amount of cells in the range.
creates a separate sheet to list the dependencies.
I am struggling to have the each source cell listed horizontally and 2 rows below the dependency cell(s).
Option Explicit
Sub ListDependents()
Dim rng As Range
Dim r As Range
Dim cell As Range
Dim n As Long, i As Long
Application.ScreenUpdating = False
'Use InputBox to prompt user for range.
'Test for cancel and a single-cell selection.
Set rng = Application.InputBox( _
Title:="Please select a range", _
Prompt:="Select range", _
Type:=8)
On Error GoTo 0
'Test for cancel.
If rng Is Nothing Then Exit Sub
'Test for single-cell selection.
'Remove comment character if single-cell selection is okay.
If rng.Rows.Count > 1 Then
MsgBox "You’ve selected more than 1 row. Please select contiguous cells per row only."
End If
'rng.Select to confirm selection
MsgBox rng.Address
'count cells to be reviewed for dependencies
For Each cell In rng.Areas
n = n + cell.Cells.Count
Next cell
Sheets.Add().Name = "Dependents"
'add first cell of range in B1, second in C1 etc until end of range
'then add first dependent of first range cell in B3, second in C3 etc
If n > "0" Then
i = 1 + i
Sheets("Depentent Test").Cells(2, i) =
End Sub
Source Sheet
Destination Sheet
Try this. I would suggest replacing my variable names with more useful ones. I haven't included a check that a cell has any dependents which is advisable as otherwise it will probably error.
Sub ListDependents()
Dim rng As Range
Dim r As Range
Dim cell As Range
Dim n As Long, i As Long, j As Long
Application.ScreenUpdating = False
'Use InputBox to prompt user for range.
'Test for cancel and a single-cell selection.
Set rng = Application.InputBox( _
Title:="Please select a range", _
Prompt:="Select range", _
Type:=8)
On Error GoTo 0
'Test for cancel.
If rng Is Nothing Then Exit Sub
'Test for single-cell selection.
'Remove comment character if single-cell selection is okay.
If rng.Rows.Count > 1 Then
MsgBox "You’ve selected more than 1 row. Please select contiguous cells per row only."
End If
'rng.Select to confirm selection
MsgBox rng.Address
Sheets.Add().Name = "Dependents"
'add first cell of range in B1, second in C1 etc until end of range
'then add first dependent of first range cell in B3, second in C3 etc
Dim ra As Range, r1 As Range, r2 As Range
j = 2
For Each ra In rng.Areas
For Each r1 In ra
Cells(1, j) = r1.Address
i = 3
For Each r2 In r1.Dependents
Cells(i, j) = r2.Address
i = i + 1
Next r2
j = j + 1
Next r1
Next ra
End Sub
I found a solution to add the headers above each dependency. I moved the rows down by one to have space for a header and then used offset to match the respective header.
j = 2
For Each ra In rng.Areas
For Each r1 In ra
Cells(2, j) = r1.Address
Cells(1, j) = r1.OffSet(-1, 0).Value
i = 4
For Each r2 In r1.Dependents
Cells(i, j) = r2.Address
Cells(i - 1, j) = r2.OffSet(-1, 0).Value
i = i + 2
Next r2
j = j + 1
Next r1
Next ra

Worksheet Change event with data validation

My VBA is not running once a cell data is changed.
On my worksheet I have VBA running in Column F and G.
Column G has data validation that I want to trigger based on the numerical value input in column F.
Example:
Column F has a numerical value of 2.5 which results in Column G displaying "Good Standing".
If I change the Column F value to < 2, I want Column G cell to show blank
and vice versa if Column F value is originally < 2, and I increase it to > 2 Column G will display "Good Standing.
Private Sub Worksheet_Change(ByVal Target As Range)
StrtRow = 2
EndRow = Range("F" & Rows.Count).End(xlUp).Row
For i = StrtRow To EndRow
If Range("F" & i).Value >= 2 Then
Range("G" & i).Value = "Good Standing"
End If
Next
End Sub
You're missing an Else clause to clear the contents if < 2. Taking #SJR 's comment into account, try this (not tested)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngWatched As Range: Set rngWatched = Me.Range("F:F")
Dim cl As Range
If Not Intersect(rngWatched, Target) Is Nothing Then
Application.EnableEvents = False
For Each cl In Intersect(rngWatched, Target)
If cl.Value >= 2 Then
cl.Offset(0, 1).Value = "Good Standing"
Else
cl.Offset(0, 1).ClearContents
End If
Next
Application.EnableEvents = True
End If
End Sub

Find previous cell address (to the left) in active row with different value than active cell value

I,ve tried to find a VBA solution for finding the previous cell (located on the same row) with different value than the selected cell has. So if the selected cell is for example [N6] (as in my picture) then my search range should be ("A6:N6") from which I need to find the last cell with a different cell value (which would be cell [L6] in my picture because it's the previous cell with a different value than cell [N6]. The search should start from the end (N6,M6,L6...) backwards until the first match is found (first different cell value). When the first match is found then select it. I have hundreds of columns, so my picture is just to show the principle. I execute my vba code with Private Sub Worksheet_SelectionChange(ByVal Target As Range) so when the user selects a cell with the mouse. I get the desired cell with {=ADDRESS(6;MATCH(2;1/(A6:O6<>"D")))} but I would need a VBA solution for my problem. My current VBA solution takes me to cell [I6] instead of [L6] and I can't figure out how to edit my code to find the correct cell ([L6] in my example picture).
Dim rngSel As String, rngStart As String
Dim rngActiveStart As Range
rngSel = ActiveCell.Address(0, 0)
rngStart = Cells(ActiveCell.Row, 1).Address(0, 0)
Set rngActiveStart = Range(rngStart & ":" & rngSel)
Dim c
For Each c In rngActiveStart.Cells
If c <> Target.Value And c.Offset(0, 1) = Target.Value Then
c.Select
MsgBox "Previous different cell: " & c.Address(0, 0)
Exit For
End If
Next
Using selection_Change
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim r As Long, col As Long, x
Dim v As String
r = Target.Row
v = Target.Value
Application.EnableEvents = False
For x = Target.Column To 1 Step -1
With Me
If .Cells(r, x) <> v Then
.Cells(r, x).Select
Exit For
End If
End With
Next x
Application.EnableEvents = True
End Sub
You need a For i = max To min Step -1 loop to loop backwards/left:
Public Sub MoveLeftUntilChange()
Dim SelRange As Range 'remember the selected range 'N6
Set SelRange = Selection
Dim iCol As Long
For iCol = SelRange.Column To 1 Step -1 'move columns leftwards
With SelRange.Parent.Cells(SelRange.Row, iCol) 'this is the current row/column to test againts the remembered range N6
If .Value <> SelRange.Value Then 'if change found select and exit
.Select
Exit For
End If
End With
Next iCol
End Sub

Using VBA in Excel to share cell vales between sheets to populate data in cells

Updated Question
I have a VBA script attached to sheet 1 that uses the B5:B50 cell values to populate the adjacent column with pre-defined text. If I want to use this script in another sheet, but still use the B5:B50 cell values of the previous sheet. How to I do that?
For Example:
In sheet 1, If I enter the value of 2 in the cell B5, it will populate D5 and E5 with the text value attached to CONST TXT. I want to do the same thing in sheet 2, but instead of the user entering the value again into B5 of sheet 2, it just gets the value of B5 from the previous sheet and then populate D5 and E5.
Sheet 2 B values will need to update as soon as the B values are updated in Sheet 1.
Private Sub Worksheet_Change(ByVal Target As Range)
Const NUM_COLS As Long = 5
Const TXT = "• Course Name:" & vbNewLine & _
"• No. Of Slides Affected:" & vbNewLine & _
"• No. of Activities Affected:"
Dim rng As Range, i As Long, v
If Target.CountLarge <> 1 Then Exit Sub
If Not Intersect(Target, Me.Range("B5:B50")) Is Nothing Then
Set rng = Target.Offset(0, 2).Resize(1, NUM_COLS) 'range to check
v = Target.Value
If IsNumeric(v) And v >= 1 And v <= NUM_COLS Then
For i = 1 To rng.Cells.Count
With rng.Cells(i)
If i <= v Then
'Populate if not already populated
If .Value = "" Then .Value = TXT
Else
'Clear any existing value
.Value = ""
End If
End With
Next i
Else
rng.Value = "" 'clear any existing content
End If
End If
End Sub
As I understand you, you want something like an equivalent of offset which returns a range on a different sheet. There are a couple of options.
You can use Range.AddressLocal, which returns the address of Range without any worksheet or workbook qualifiers, and then apply this to the other worksheet:
'returns a cell 1 to the right of rng, but on Sheet2
Worksheets("Sheet2").Range(rng.Offset(0, 1).AddressLocal)
Or you can get the Row and Column properties of your range and use them in Cells in the other worksheet:
'returns a cell 1 to the right of rng, but on Sheet2
Worksheets("Sheet2").Cells(rng.Row, rng.Column + 1)
To use it in your code, I think it's just a case of replacing
If .Value = "" Then .Value = TXT
with
If Worksheets("Sheet2").Range(.Offset(0, 1).AddressLocal).Value = "" Then Worksheets("Sheet2").Range(.Offset(0, 1).AddressLocal).Value = TXT
and replacing
.Value = ""
with
Worksheets("Sheet2").Range(.Offset(0, 1).AddressLocal).Value = ""
(or the same using the Cells construction).
The below will copy the Target.Value into the same cell in Sheet2
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
If Not Intersect(Target, Me.Range("B5:B50")) Is Nothing And Target.Count = 1 Then
With Target
ws2.Cells(.Row, .Column).Value = .Value
End With
End If
End Sub

Setting Excel cell value based on another cell value using VBA

I have the following spreadsheet. When ever there is an x in cell B I need to populate the d and e cells in the same row using an equation I have.
if there is no x in the b cell I need to manually enter values into cells d & e.
How do I make my code non-row specific?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim val As String
val = Range("B3").Value
If val = "x" Then
Range("E3").Value = Range("d2").Value * Range("G2").Value
Range("D3").Value = Range("D2").Value
End If
End Sub
I'm not sure if I understand correctly, but if you have a parameter: row = 3 you can use Range("E" & row) instead of Range("E3").
Put a loop around that where you vary 'row' for the rows you want to modify.
Hope that helps!
You've created a sub procedure around the Worksheet_SelectionChange event. In fact, you require Worksheet_Change and you need to,
disable event handling so you can write new values/formulas to the worksheet without running the Worksheet_Change on top of itself.
loop through each matching cell in Target to compensate for circumstances when Target can be more than a single cell,
add error control.
Rewrite:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B:B")) Is Nothing Then
On Error GoTo safe_exit
Application.EnableEvents = False
Dim t As Range
For Each t In Intersect(Target, Range("B:B"))
If LCase(t.Value) = "x" Then
'I've made these formulas relative to each target
'you may want to make some absolute references
t.Offset(0, 3) = t.Offset(-1, 2) * t.Offset(-1, 5)
t.Offset(0, 2) = t.Offset(-1, 2)
Else
t.Offset(0, 2).resize(1, 2) = vbnullstring
End If
Next t
End If
safe_exit:
Application.EnableEvents = True
End Sub
Please try below code.
It loop through all non empty rows in column B and check if there is value: x
If so it populate your formulas.
Sub new_sub()
' get last_row of data
last_row = ActiveSheet.UsedRange.Rows.Count
' loop through all rows with data and check if in column B any cell contains value: x
For i = 1 To last_row
' if there is any cell with value: x
' then add below formulas
If Cells(i, 2).Value = "x" Then
' for column E: take value from row above for col D and G and multiple
Range("E" & i).Value = Range("d" & i - 1).Value * Range("G" & i - 1).Value
' for column D: take value from row above
Range("D" & i).Value = Range("D" & i - 1).Value
End If
Next i
End Sub

Resources