Simplification - changing 2 cells at once - excel

I am trying to figure out how to simplify the code with no luck.
I managed to build a working code, which does the following:
1. If 'ja' is filled into cell 34
- in cell 35 the date appears
- in cell 36 the username appears
2. If the cell is empty, the content is cleared
Do you have any tips / can help me out?
Thank you very much.
This is the code I have so far:
'show date
If Target.Column = 34 Then
Select Case Target
Case "ja", "Ja": Target.Offset(0, 1) = Date
End Select
'show username
If Target.Column = 34 Then
Select Case Target
Case "ja", "Ja": Target.Offset(0, 2) = Application.UserName
End Select
End If
End If
' clear contents
Dim n As Long
If Target.Column = 34 Then
If IsEmpty(Cells(Target.Row, 34)) Then
Range("AI" & Target.Row & ":AJ" & Target.Row).ClearContents
End If
End If
End Sub

I think this would do it:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Column = 34 Then
Select Case Target
Case "ja", "Ja"
Target.Offset(0, 1) = Date 'show date
Target.Offset(0, 2) = Application.UserName 'show username
Case vbNullString 'Clear contents
Range("AI" & Target.Row & ":AJ" & Target.Row).ClearContents
End Select
End If
End Sub

Related

How can I replace single cell references with ranges

I have 5 columns ((a)uptick, (b)downtick, (c)original, (d)current), and (e) Stored Value. All columns need to be a range of rows. When d2 changes I want to compare it to e2 and if d2>e2 then bump the counter in a2 by 1 (uptick), if d2<e2 then bump the counter in b2 (downtick). I have it working with many if and elseif statements but would rather use less code using variables for the range. To detect the changing cell I use "If Not Intersect (Target, Range("d2:d10")) Is Nothing Then...."
I cannot seem to figure out how to replace specific cell references with ranges. Any help would be most appreciated!
Sample Code below not using ranges yet.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("D2:D10")) Is Nothing Then
If Target.Value > Range("E2") Then
Range("A2") = Range("A2") + 1
Pause 2#
Range("E2") = Target.Value
ElseIf Target.Value < Range("E2").Value Then
Range("B2") = Range("B2") + 1
Pause 2#
Range("E2") = Target.Value
End If
End If
End Sub
I assume you want to change the cell value in the same row that the value was entered in column D, i.e. if D4 has been changed, then adjust A4 or B4. To do that, you need the row number of the changed cell. You can extract that with target.row. Throw that into a variable and use the variable instead of the row number in the Range() property.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("D2:D10")) Is Nothing Then
dim myRow as long
myRow = target.row
If Target.Value > Range("E" & myRow) Then
Range("A" & myRow) = Range("A" & myRow) + 1
Pause 2#
Range("E" & myRow) = Target.Value
ElseIf Target.Value < Range("E" & myRow).Value Then
Range("B" & myRow) = Range("B" & myRow) + 1
Pause 2#
Range("E" & myRow) = Target.Value
End If
End If
End Sub
You could use .Offset to get the same result. The following code assumes you're only interested in the range D2:D10 and aren't concerned if the value in column D equals the value in column E.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("D2:D10"), Target) Is Nothing Then
If Target.Rows.Count > 1 Then Exit Sub
If Target > Target.Offset(, 1) Then
Target.Offset(, -3) = Target.Offset(, -3) + 1
Else
If Target < Target.Offset(, 1) Then
Target.Offset(, -2) = Target.Offset(, -2) + 1
End If
End If
End If
End Sub

VBA : combine range with row insert and merging

here you see the lines for merging certain cells when a row is inserted.
Range(Cells(ActiveCell.row, "H"), Cells(ActiveCell.row, "L")).mergeCells = True
Range("H" & ActiveCell.row + 1).Resize(, 5).Merge
i would like to add a range value but i can't find how or where to add it in the existing code.
the range in the excel is "H3752":"L4990", so only in that range the cells are to be merged, and not in the entire worksheet.
kinds regards.
The below code should work:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Cells(Target.Row + Target.Rows.Count, Target.Item(1, 1).Column).ID = Target.Address
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Item(1, 1).ID <> "" Then
'Code for if row is deleted
Else
'Code for if row is inserted
If Target.Row >= 3752 And Target.Row <= 4990 Then
Range(Cells(Target.Row, "H"), Cells(Target.Row, "L")).MergeCells = True
Range("H" & Target.Row + 1).Resize(, 5).Merge
End If
End If
Target.Item(1, 1).ID = ""
Cells(Target.Row + Target.Rows.Count, Target.Item(1, 1).Column).ID = Target.Address
End Sub
To change what rows you are looking at you can change this line: If Target.Row >= 3752 And Target.Row <= 4990 Then If you are trying to change the columns you can change this letters in this section:
Range(Cells(Target.Row, "H"), Cells(Target.Row, "L")).MergeCells = True
Range("H" & Target.Row + 1).Resize(, 5).Merge
works like a charm! but if i secure the excel file i do get an error now : "1004 while executing : error defined by the application or object"

WorksheetChange Event to Concatenate Row and First Letter of First Name + First Letter of Last Name

I think the code should be something like this, but I'm getting an error on this line where I am trying to handle the first and last names. Basically, I want to create a code in Column A, which is the first letter of the person's first name and first letter of the person's last name, concatenated with the row number. The row will be the active row (always Column A) and the first and last names will be stored in Column B.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 1 Then Exit Sub
On Error GoTo ErrHandler
Application.EnableEvents = False
If Target.Column = 1 Then
Target.Offset(0, 0).FormulaR1C1 = "=ROW()"
TV1 = Target.Offset(0, 0).FormulaR1C1
Target.Offset(0, 0).FormulaR1C1 = "=UPPER(LEFT(R[" & "=ROW()" & "]C[1],1)&MID(R[" & "=ROW()" & "]C[1],FIND("" "",R[" & "=ROW()" & "]C[1],1)+1,1))"
TV2 = Target.Offset(0, 0).FormulaR1C1
Target.Offset(0, 0).Value = TV2 & "-" & TV1
End If
End Sub
I don't like to avoid dealing with more than a single cell as the Target. It isn't hard to deal with multiple cells.
After disabling events and performing your processing, you are not turning them back on again. You code will only run once without manually turning events back on.
If you are putting first and last names into column B, shouldn't the processing be subject to column B and not column A?
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns("B")) Is Nothing Then
On Error GoTo ErrHandler
Application.EnableEvents = False
Dim trgt As Range
For Each trgt In Intersect(Target, Target.Parent.UsedRange, Columns("B"))
trgt = StrConv(Trim(trgt.Value2), vbProperCase)
If CBool(InStr(2, trgt.Value2, Chr(32))) Then
trgt.Offset(0, -1) = _
UCase(Left(trgt.Value2, 1)) & _
UCase(Mid(trgt.Value2, InStr(1, trgt.Value2, Chr(32)) + 1, 1)) & _
Format(trgt.Row, "000")
End If
Next trgt
End If
ErrHandler:
Application.EnableEvents = True
End Sub
I've added some trim and proper-case conversion to auto-correct the values being typed into column B.
In the following image, I copied the names from G5:G8 and pasted them into B2:B5.
I would do this differently. Why write formulas when you can do it simply in VBA?
I've made some annotations to your original code also:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 1 Then Exit Sub
Application.EnableEvents = False
' No error handler in your code
'On Error GoTo ErrHandler
' don't need to check if column 1 since we already did that and exited the sub if it was not
' If Target.Column = 1 Then
'Target.Offset(0,0) = Target
'Target.Offset(0, 0).FormulaR1C1 = "=ROW()"
'TV1 = Target.Offset(0, 0).FormulaR1C1
'Target.Offset(0, 0).FormulaR1C1 = "=UPPER(LEFT(R[" & "=ROW()" & "]C[1],1)&MID(R[" & "=ROW()" & "]C[1],FIND("" "",R[" & "=ROW()" & "]C[1],1)+1,1))"
'TV2 = Target.Offset(0, 0).FormulaR1C1
'Target.Offset(0, 0).Value = TV2 & "-" & TV1
'Just do the creation in VB
With Target
.Value = .Row & Left(.Offset(0, 1), 1) & Left(Split(.Offset(0, 1))(1), 1)
End With
'If you have more than two space-separated words in the name, then something like
Dim V As Variant
With Target
V = Split(.Offset(0, 1))
.Value = .Row & Left(V(0), 1) & Left(V(UBound(V)), 1)
End With
'Don't forget to reenable events
Application.EnableEvents = True
End Sub
Also, since the names are in Column B, why are you testing for a change in Column A? There could be reasons, but if there are not, it might be smoother to check for changes in column B.
I figured it out!!
If Target.Column = 1 Then
Target.Offset(0, 0).FormulaR1C1 = "=ROW()"
TV1 = Target.Value
Target.Offset(0, 0).FormulaR1C1 = "=UPPER(LEFT(RC[1],1)&MID(RC[1],FIND("" "",RC[1],1)+1,1))"
TV2 = Target.Value
Target.Value = TV2 & "-" & TV1
End If

Excel Time Format

Having trouble with time formatting.
I have set the cell to custom format 00:00.
Currently in column A a date is inputted, this can be as 0300 which converts to 03:00 which is perfect or you can just enter 03:00.
I now have a problem if a user enters 03;00 as i need this to display 03:00
how can i ensure that all times are in the hh:mm format and not in hh;mm etc.
This needs to auto change on input for anything in column A, except what is the header (A1:A5) although this should not be affected.
Thanks
On your sheets change event you would place the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.CountLarge = 1 And Target.Column = 1 And Target.Row > 5 Then
Target.Value2 = Replace(Target.Value2, ";", ":")
End If
End Sub
Explaining the code... it first checks to make sure that the change isn't on multiple cells (ie paste) and that the change is on column A below Row 5. If it does pass the conditional it simply replaces ; for :.
This does what i require.
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
Dim xStr As String
Dim xVal As String
Set rng1 = Range("A:A")
Set rng2 = Range("C:C")
Set rng3 = Range("I:I")
On Error GoTo EndMacro
If Application.Intersect(Target, Union(rng1, rng2, rng3)) Is Nothing Then Exit Sub
If Target.Count > 1 Then Exit Sub
If Target.Value = "" Then Exit Sub
If Target.Row < 5 Then Exit Sub
Application.EnableEvents = False
With Target
If Not .HasFormula Then
Target.Value = Replace(Target.Value, ";", ":")
Target.Value = Left(Target.Value, 5)
xVal = .Value
Select Case Len(xVal)
Case 1 ' e.g., 1 = 00:01 AM
xStr = "00:0" & xVal
Case 2 ' e.g., 12 = 00:12 AM
xStr = "00:" & xVal
Case 3 ' e.g., 735 = 07:35 AM
xStr = "0" & Left(xVal, 1) & ":" & Right(xVal, 2)
Case 4 ' e.g., 1234 = 12:34
xStr = Left(xVal, 2) & ":" & Right(xVal, 2)
Case 5 ' e.g., 12:45 = 12:45
xStr = Left(xVal, 2) & Mid(xVal, 2, 1) & Right(xVal, 2)
Case Else
Err.Raise 0
End Select
.Value = Format(TimeValue(xStr), "hh:mm")
End If
End With
Application.EnableEvents = True
Exit Sub
EndMacro:
Application.EnableEvents = True
End Sub
Thanks

VBA code to display message box if value in another cell contains specific text

I am new to VBA...looking for code that will only allow me to enter a value in a column if the value in one or more of the three cells immediately to the left "contains" the word "Other". I've successfully written the code so that if the value in one or more of the cells is "Other" I am restricted from entering a value, but have not been successful in using ISERROR and FIND so that the code looks for text that includes "other". Here is what I have right now...
If Target.Column = 15 And Target <> "" Then
If Cells(Target.Row, Target.Column - 1).Value <> "Other" _
Or Cells(Target.Row, Target.Column - 2).Value <> "Other" _
Or Cells(Target.Row, Target.Column - 3).Value <> "Other" _
Then
Target.Value = ""
MsgBox "First Select 'Other' value in one or more of the 'Excluded Employee' Columns to the left"
Exit Sub
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub
Any suggestions would be most appreciated!
If Target.Column = 15 And Target <> "" Then
If InStr(1, Cells(Target.Row, Target.Column - 1).Value, "Other") = 0 _
And InStr(1, Cells(Target.Row, Target.Column - 2).Value, "Other") = 0 _
And InStr(1, Cells(Target.Row, Target.Column - 3).Value, "Other") = 0 _
Then
Target.Value = ""
MsgBox "First Select 'Other' value in one or more of the 'Excluded Employee' Columns to the left"
Exit Sub
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub
You can use COUNTIF with a wildcard to look for at least once cell containing other, i.e.:
If target.Column = 15 And target.Value <> "" Then
If Application.WorksheetFunction.CountIf(target.Offset(0, -3).Resize(1, 3), "*other*") = 0 Then
target.Value = ""
MsgBox "First Select 'Other' value in one or more of the 'Excluded Employee' Columns to the left"
Exit Sub
End If
End If

Resources