I have received a request to fill in date based on specific status chosen (cell value) in a column representing that status.
For example if I choose a Status "Event_1" in column A from a drop down list, macro should find a column with the same name (Event_1) and fill in date in that column for the Row where the status was changed.
I only got as far as filling adjacent cell with a date when said cell is changed. I know I should probably adjust offset to a column number representing my status, however I'm not sure how to achieve this.
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
Dim ColNum As Integer
With Target
If .Count > 1 Then Exit Sub
If Not Intersect(Range("A:A"), .Cells) Is Nothing Then
Application.EnableEvents = False
If IsEmpty(.Value) Then
.Offset(0, 1).ClearContents
Else
With .Offset(0, 1)
.NumberFormat = "dd mmm yyyy"
.Value = Now
End With
End If
Application.EnableEvents = True
End If
End With
End Sub
What about this?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ColNum As Integer
With Target
If .Count > 1 Then Exit Sub
If Not Intersect(Range("A:A"), .Cells) Is Nothing Then
Application.EnableEvents = False
If IsEmpty(.Value) Then
'.Offset(0, 1).ClearContents
'Why???
Else
ColNum = Application.WorksheetFunction.Match(Target.Value, Range("1:1"), 0)
With .Offset(0, ColNum - 1)
.NumberFormat = "dd mmm yyyy"
.Value = Now
End With
End If
Application.EnableEvents = True
End If
End With
End Sub
The only part I don't get is this one:
If IsEmpty(.Value) Then
.Offset(0, 1).ClearContents
Why? You should specify what you want to do when there is no option selected.
A Worksheet Change: One Timestamp Per Row
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ClearError
Const FirstColCellAddress As String = "B1"
Const FirstRowCellAddress As String = "A2"
Const TimeFormat As String = "dd/mm/yyyy hh:mm:ss"
Dim scrg As Range
With Range(FirstRowCellAddress)
Set scrg = .Resize(.Worksheet.Rows.Count - .Row + 1)
End With
Dim irg As Range: Set irg = Intersect(scrg, Target)
If irg Is Nothing Then Exit Sub
Dim srrg As Range
Dim sCell As Range
With Range(FirstColCellAddress)
Set sCell = .Resize(, .Worksheet.Columns.Count - .Column + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
Set srrg = .Resize(, sCell.Column - .Column + 1)
End With
Dim sIndex As Variant
Dim sString As String
Dim drrg As Range
Dim dCell As Range
Dim rgClear As Range
Dim rgTime As Range
For Each sCell In irg.Cells
Set drrg = srrg.Rows(sCell.Row - srrg.Row + 1)
If rgClear Is Nothing Then
Set rgClear = drrg
Else
Set rgClear = Union(rgClear, drrg)
End If
sString = CStr(sCell.Value)
sIndex = Application.Match(sString, srrg, 0)
If IsNumeric(sIndex) Then
Set dCell = drrg.Cells(sIndex)
If rgTime Is Nothing Then
Set rgTime = dCell
Else
Set rgTime = Union(rgTime, dCell)
End If
End If
Next sCell
Application.EnableEvents = False
If Not rgClear Is Nothing Then rgClear.Clear
If Not rgTime Is Nothing Then
Dim TimeStamp As Date: TimeStamp = Now
With rgTime
.NumberFormat = TimeFormat
.Value = TimeStamp
End With
End If
SafeExit:
If Not Application.EnableEvents Then Application.EnableEvents = True
Exit Sub
ClearError:
Debug.Print "Run-time error '" & Err.Number & "': " & Err.Description
Resume SafeExit
End Sub
Related
I want to have a sheet were after I enter a truck number it automatically places the date and time in a following cell, that works no problem, but when I try to place a protection on the cells after data has been enter so it cannot be modify it gives me errors, what am I doing wrong?
I have selected the complete sheet and unlock the cells, then I have wrote this code on the visual basic for excel
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveSheet.Unprotect Password:="YourPassword"
Target.Locked = True
ActiveSheet.Protect Password:="YourPassword"
Dim x As Integer
Dim y As Integer
For x = 2 To 1000
For y = 2 To 1000
If Cells(x, 3).Value <> "" And Cells(x, 5).Value = "" Then
Cells(x, 5).Value = Date & " " & Time
Cells(x, 5).NumberFormat = "m/d/yyyy h:mm:ss AM/PM"
End If
Next
Range("B:B").EntireColumn.AutoFit
If Cells(y, 6).Value <> "" And Cells(y, 7).Value = "" Then
Cells(y, 7).Value = Date & " " & Time
Cells(y, 7).NumberFormat = "m/d/yyyy h:mm:ss AM/PM"
End If
Next
Range("B:B").EntireColumn.AutoFit
End Sub
[ ]2]2
this is the code and error
after I apply the code for the protection the time and date doesnt stamp anymore
Worksheet Change: Monitoring 2 Non-Adjacent Columns
Adjust the values in the constants section, especially the password ('pw').
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
ScanTrucks Target
End Sub
Private Sub ScanTrucks(ByVal Target As Range)
On Error GoTo ClearError
' Scan In
Const siCol As String = "C"
Const diCol As String = "E"
' Scan Out
Const soCol As String = "F"
Const doCol As String = "G"
' Both
Const fRow As Long = 2
Const afCol As String = "B"
Const pw As String = "123"
Dim ws As Worksheet: Set ws = Target.Worksheet
Dim scrg As Range
Dim srg As Range
Dim sCell As Range
Dim drg As Range
Dim dCell As Range
' Scan In
Set scrg = ws.Columns(siCol)
With scrg
Set srg = Intersect(Target, _
.Resize(.Rows.Count - fRow + 1).Offset(fRow - 1))
End With
If Not srg Is Nothing Then
For Each sCell In srg.Cells
If Len(CStr(sCell.Value)) > 0 Then
Set dCell = sCell.EntireRow.Columns(diCol)
If Len(CStr(dCell.Value)) = 0 Then
Set drg = RefCombinedRange(drg, dCell)
End If
End If
Next sCell
End If
' Scan Out
Set srg = Nothing
With scrg.EntireRow.Columns(soCol)
Set srg = Intersect(Target, _
.Resize(.Rows.Count - fRow + 1).Offset(fRow - 1))
End With
If Not srg Is Nothing Then
For Each sCell In srg.Cells
If Len(CStr(sCell.Value)) > 0 Then
Set dCell = sCell.EntireRow.Columns(doCol)
If Len(CStr(dCell.Value)) = 0 Then
Set drg = RefCombinedRange(drg, dCell)
End If
End If
Next sCell
End If
If drg Is Nothing Then Exit Sub
' Unprotect, format, write and protect.
ws.Unprotect Password:=pw
Application.EnableEvents = False
ws.Columns(afCol).AutoFit
With drg
.NumberFormat = "m/d/yyyy h:mm:ss AM/PM"
.Value = Now
.Locked = True
End With
SafeExit:
If Not Application.EnableEvents Then Application.EnableEvents = True
If Not ws.ProtectionMode Then ws.Protect Password:=pw
Exit Sub
ClearError:
Debug.Print "Run-time error '" & Err.Number & "':" & Err.Description
Resume SafeExit
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to a range combined from two ranges.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefCombinedRange( _
ByVal CombinedRange As Range, _
ByVal AddRange As Range) _
As Range
If CombinedRange Is Nothing Then
Set RefCombinedRange = AddRange
Else
Set RefCombinedRange = Union(CombinedRange, AddRange)
End If
End Function
Am using the following code that works for populating static dates in column C when data is filled in column B.
I would like to also have column E populated with static dates if data is filled in column D. Please advise tq
Private Sub Worksheet_Change(ByVal Target As Range)
'Update 20140722
Dim WorkRng As Range
Dim Rng As Range Dim xOffsetColumn As Integer
Set WorkRng = Intersect(Application.ActiveSheet.Range("B:B"), Target)
xOffsetColumn = 1
If Not WorkRng Is Nothing Then
Application.EnableEvents = False
For Each Rng In WorkRng
If Not VBA.IsEmpty(Rng.Value) Then
Rng.Offset(0, xOffsetColumn).Value = Now
Rng.Offset(0, xOffsetColumn).NumberFormat = "dd-mm-yyyy, hh:mm:ss"
Else
Rng.Offset(0, xOffsetColumn).ClearContents
End If
Next
Application.EnableEvents = True
End If
End Sub
A Worksheet Change: Time Stamp and Clear
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const fRow As Long = 1 ' possibly 2 or more to exclude headers
Const cOffset As Long = 1
' Reference the intersecting range.
Dim irg As Range ' Intersect
With Columns("B")
With .Resize(.Rows.Count - fRow + 1).Offset(fRow - 1)
'Debug.Print Union(.Cells, .EntireRow.Columns("D")).Address
Set irg = Intersect(Union(.Cells, .EntireRow.Columns("D")), Target)
End With
End With
If irg Is Nothing Then Exit Sub
Dim trg As Range ' Time
Dim crg As Range ' Clear
Dim iCell As Range
' Combine cells into the Time and Clear ranges.
For Each iCell In irg.Cells
If Not VBA.IsEmpty(iCell.Value) Then
If trg Is Nothing Then Set trg = iCell _
Else Set trg = Union(trg, iCell)
Else
If crg Is Nothing Then Set crg = iCell _
Else Set crg = Union(crg, iCell)
End If
Next iCell
Application.EnableEvents = False
' Write.
If Not trg Is Nothing Then
With trg.Offset(, cOffset)
.NumberFormat = "dd-mm-yyyy, hh:mm:ss"
.Value = Now
End With
End If
If Not crg Is Nothing Then
crg.Offset(, cOffset).ClearContents
End If
Application.EnableEvents = True
End Sub
I have been using this below code to get the Unique sorted value from Sheet1.Range("C4:C") and to paste into Sheet2.Range("C4"). This is working fine
But now i want use the same code to get the Unique sorted value from Sheet3.Range("C4:C") and to paste into Sheet2.Range("G4").
now the problem is that how to mention the Sheet reference in code that which sheet range unique sorted value will be paste.
Standard Module (e.g. Module1)
Option Explicit
Sub copySortedUniqueColumn( _
SourceRange As Range, _
DestinationCell As Range, _
Optional ByVal doSort As Boolean = True)
Dim Data As Variant
If SourceRange.Rows.Count > 1 Or SourceRange.Columns.Count > 1 Then
Data = SourceRange.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = SourceRange.Value
End If
Dim arl As Object: Set arl = CreateObject("System.Collections.ArrayList")
Dim Key As Variant
Dim i As Long
With CreateObject("Scripting.Dictionary")
.CompareMode = vbTextCompare
For i = 1 To UBound(Data, 1)
Key = Data(i, 1)
If Not IsError(Key) Then
If Len(Key) > 0 Then
If Not .Exists(Key) Then
.Item(Key) = Empty
arl.Add Key
End If
End If
End If
Next i
If .Count = 0 Then Exit Sub
End With
If doSort Then
arl.Sort
End If
ReDim Data(1 To arl.Count, 1 To 1)
i = 0
For Each Key In arl
i = i + 1
Data(i, 1) = Key
Next Key
With DestinationCell
.Resize(.Worksheet.Rows.Count - .Row + 1).ClearContents
.Resize(i).Value = Data
End With
End Sub
Function defineColumnRange( _
FirstCellRange As Range) _
As Range
On Error GoTo clearError
If FirstCellRange Is Nothing Then GoTo ProcExit
With FirstCellRange
Dim cel As Range: Set cel = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If cel Is Nothing Then GoTo ProcExit
Set defineColumnRange = .Resize(cel.Row - .Row + 1)
End With
ProcExit:
Exit Function
clearError:
Resume ProcExit
End Function
Sheet Module (Sheet1)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const srcFirst As String = "C4"
Const dstFirst As String = "C4"
Dim srg As Range: Set srg = defineColumnRange(Range(srcFirst))
If srg Is Nothing Then
With Sheet2.Range(dstFirst)
.Resize(.Worksheet.Rows.Count - .Row + 1).ClearContents
End With
Exit Sub
End If
Dim rg As Range: Set rg = Intersect(srg, Target)
If rg Is Nothing Then Exit Sub
Dim dCel As Range: Set dCel = Sheet2.Range(dstFirst)
On Error GoTo clearError
Application.EnableEvents = False
copySortedUniqueColumn srg, dCel
SafeExit:
Application.EnableEvents = True
Exit Sub
clearError:
Resume SafeExit
End Sub
Simply do the following:
Copy the sheet module code (which you initially put in Sheet1) to the sheet module of Sheet3 and change dstFirst to G4.
(This is a follow-up question on my answer to filter unique values and sort A to Z Excel VBA.)
Sub Macro5()
Dim rng As Range
Set rng = Selection
For Each cell In rng
ActiveCell.Value = ActiveCell.Value + 1
Next
End Sub
Quick fix for your code would be
Sub Macro5()
Dim rng As Range
Set rng = Range("B2:B10")
Dim cell As Range
For Each cell In rng
cell.Value = cell.Value + 1
Next
End Sub
Update: By the comment I guess you would like to use the SelectionChange Event. Put the following code into the code module of the sheet
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo EH
Application.EnableEvents = False
Dim rg As Range
Set rg = Range("B2:B12")
If Not (Intersect(rg, Target) Is Nothing) Then
Dim sngCell As Range
' This will only increase the values of the selected cells within B2:B10
' Not sure if this is wanted. Otherwise just modify according to your needs
For Each sngCell In Intersect(Target, rg)
sngCell.Value = sngCell.Value + 1
Next sngCell
End If
EH:
Application.EnableEvents = True
End Sub
Update 2: If you want to run the code via a button put the following code into a standard module and assign it to a button you create on the sheet
Sub Increase()
On Error GoTo EH
Application.EnableEvents = False
Dim rg As Range
Set rg = Range("B2:B10")
If Not (Intersect(rg, Selection) Is Nothing) Then
Dim sngCell As Range
For Each sngCell In Intersect(Selection, rg)
sngCell.Value = sngCell.Value + 1
Next sngCell
End If
EH:
Application.EnableEvents = True
End Sub
Test if the current cell is within your range!
Sub Macro5()
Dim rng As Range
Dim fixed_rng As Range
Set rng = Selection
Set fixed_rng = Range("B1:B10")
if Application.Union(rng, fixed_rng) = fixed_rng then
For Each cell In rng
ActiveCell.Value = ActiveCell.Value + 1
Next
End If
End Sub
I am doing a macro to check and validate all cells by colorindex. kindly help me if there is wrong in my code. Many Thanks.
Sub Validate()
Dim rng As Range: Set rng = Application.Range("CATALOG!B2:F98")
Dim cel As Range
Dim i As Boolean
i = False
For Each cel In rng
With cel
If .Interior.ColorIndex = 6 Then
If .EntireRow.Hidden = False Then
i = True
End If
End If
End With
Next cel
If i = True Then
MsgBox "yellow"
Else
MsgBox "none"
End If
End Sub
It's pretty unclear what you're asking, but there are two ways:
1) first, when you want to check if every cell in range has .Interior.ColorIndex = 6. Then your code should look like:
Sub Validate()
Dim rng As Range: Set rng = Application.Range("CATALOG!B2:F98")
Dim cel As Range
Dim i As Boolean
i = True
For Each cel In rng.Cells
If Not cel.Interior.ColorIndex = 6 Then
i = False
Exit For 'we found cell with different color, so we can exit loop
End If
Next cel
If i = True Then
MsgBox "yellow"
Else
MsgBox "none"
End If
End Sub
2) you want to check if any cell has .Interior.ColorIndex = 6. Then it should look like:
Sub Validate()
Dim rng As Range: Set rng = Application.Range("CATALOG!B2:F98")
Dim cel As Range
Dim i As Boolean
i = False
For Each cel In rng.Cells
If cel.Interior.ColorIndex = 6 Then
i = True
Exit For 'we found cell with the color, so we can exit loop
End If
Next cel
If i = True Then
MsgBox "yellow"
Else
MsgBox "none"
End If
End Sub
Of what I've gatered you are trying to loop through all non hidden cells and see if they have a yellow background color, and if they are yellow they need to change based on a input.
Sub Validate()
Dim rng As Range: Set rng = Application.Range("CATALOG!B1:F98")
Dim cel As Range
For Each cel In rng
With cel
If .Interior.ColorIndex = 6 Then
If .EntireRow.Hidden = False Then
.Interior.ColorIndex = InputBox("please input new colorIndex", "SetColorIndex")
End If
End If
End With
Next cel
End Sub