VBA - Insert data in different cells without interruption - excel

I have a worksheet, in this I would like to fill different cells by an input.
Currently it works by clicking in the cell. However, you have to click on each cell individually.
Now I want that when I confirm the input in the first cell, the input for the second value appears directly and so I can fill up to 5 values in a row without clicking each time.
So i click a button it should open a input dialog, there i insert my input, then it appears in the first cell, without closing it changes to second input dailog, where i insert my input again ....
Here my code of the currect solution.
I hope u understand and can help me with this function
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim varEintrag
If Target.Cells(1).Address(0, 0) = "D12" Then
varEintrag = Application.InputBox("Bitte Wert eintragen", "Dateneingabe")
If varEintrag <> "Falsch" And varEintrag <> "False" Then
If IsNumeric(varEintrag) Then
Target = CDbl(varEintrag)
Else
Target = varEintrag
End If
End If
End If
End Sub```

Trigger Multiple Cells Entry
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo ClearError
Const iAddress As String = "D12"
Const mrgAddress As String = "D12,E12,D13,D15,E15"
Dim iCell As Range
Set iCell = Intersect(Range(iAddress), Target)
If iCell Is Nothing Then Exit Sub
Dim mrg As Range: Set mrg = Range(mrgAddress)
Application.EnableEvents = False
Dim varEintrag As Variant
For Each iCell In mrg.Cells
varEintrag = Application.InputBox( _
Prompt:="Bitte Wert in Zelle '" & iCell.Address(0, 0) _
& "' eintragen:", _
Title:="Dateneingabe", _
Default:=iCell.Value)
If varEintrag <> "Falsch" And varEintrag <> "False" Then
If IsNumeric(varEintrag) Then
iCell.Value = CDbl(varEintrag)
Else
iCell.Value = varEintrag
End If
Else
Exit For ' Cancel
End If
Next iCell
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

Please, try this modified event. It consecutively asks about the 5 necessary inputs and then place them in the necessary range:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim varEintrag, arrE(4), i As Long, k As Long
If Target.Rows.count > 1 Or Target.Columns.count > 1 Then Exit Sub
If Target.cells(1).Address(0, 0) = "D12" Then
Dim rngRet As Range: Set rngRet = Range("D12, E12, D13, D15, E15")
For i = 0 To UBound(arrE)
varEintrag = Application.InputBox("Bitte Wert eintragen " & i + 1, "Dateneingabe")
If varEintrag <> "Falsch" And varEintrag <> "False" Then
If IsNumeric(varEintrag) Then
arrE(k) = CDbl(varEintrag): k = k + 1
Else
arrE(i) = varEintrag: k = k + 1
End If
End If
Next i
Dim cel As Range: k = 0
For Each cel In rngRet.cells
cel.Value = arrE(k): k = k + 1
Next
End If
End Sub
Edited:
This is a version iterating between each discontinuous range cells and ask for input in each such a cell address:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Rows.count > 1 Or Target.Columns.count > 1 Then Exit Sub
If Target.cells(1).Address(0, 0) = "D12" Then
Dim rngRet As Range: Set rngRet = Range("D12, E12, D13, D15, E15")
Dim varEintrag, cel As Range
For Each cel In rngRet.cells
varEintrag = Application.InputBox("Bitte Wert eintragen in " & cel.Address, "Dateneingabe")
If varEintrag <> "Falsch" And varEintrag <> "False" Then
If IsNumeric(varEintrag) Then
cel.Value = CDbl(varEintrag)
Else
cel.Value = varEintrag
End If
End If
Next cel
End If
End Sub

Related

How to populate a cell in a different sheet based on the value in another sheet and vice versa

I am trying to use VBA so that I can input a value in cell B7 in sheet2 and then it would automatically populate in C7 in sheet3 and also work vice versa. I tried the code below and couldn't get it to work, any suggestions? Also would the code be the same for a string of a number?
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo eh
If Not Intersect(Target, ThisWorkbook.Sheets("sheet 2").Range("B7")) Is Nothing Then
Application.EnableEvents = False
ThisWorkbook.Sheets("sheet 3").Range("C" & Target.Row - 0).Value = Target.Value
eh:
Application.EnableEvents = True
If Err <> 0 Then MsgBox Err & " " & Err.Description, , "Error in Worksheet_Change event, sheet 2"
End If
End Sub
A Workbook SheetChange: Same Value in Cells of Worksheets
Note that the code needs to be copied to the ThisWorkbook module.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim wsNames As Variant: wsNames = VBA.Array("sheet 2", "sheet 3")
Dim CellAddresses As Variant: CellAddresses = VBA.Array("B7", "C7")
Dim iCell As Range
Dim n As Long
For n = 0 To UBound(wsNames)
If StrComp(Sh.Name, wsNames(n), vbTextCompare) = 0 Then
Set iCell = Intersect(Sh.Range(CellAddresses(n)), Target)
If Not iCell Is Nothing Then
Application.EnableEvents = False
Me.Worksheets(wsNames(1 - n Mod 2)) _
.Range(CellAddresses(1 - n Mod 2)).Value = iCell.Value
Application.EnableEvents = True
End If
Exit For
End If
Next n
End Sub

Log changes in Excel spreadsheet using VBA

I have the following problem. I need to log changes in a spreadsheet. My range goes from A1:M300000.
So far I have managed to log the address of the changed cell, the user, the old value, and the new value.
Now I would like to insert the following functions and need help. It's the first time I come into contact with VBA:
I also want my log file to show the value of a cell in another column. So I know which object it is. Example change cell B26 and now also A26 should be displayed in the log file.
Furthermore, I also want to log when new cells are inserted or existing records are deleted.
Here is my VBA code:
Option Explicit
Dim mvntWert As Variant
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wks As Worksheet
Dim lngLast As Long
Set wks = Worksheets("Protokoll")
lngLast = wks.Range("A65536").End(xlUp).Row + 1
If Target.Count > 1 Then Exit Sub
If Intersect(Range("A1:M65536"), Target) Is Nothing Then Exit Sub
With wks
.Range("A" & lngLast).Value = Target.Address(0, 0)
.Range("B" & lngLast).Value = mvntWert
.Range("C" & lngLast).Value = Target.Value
.Range("D" & lngLast).Value = VBA.Environ("Username")
.Range("E" & lngLast).Value = Now
End With
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Intersect(Range("A1:M65536"), Target) Is Nothing Then Exit Sub
mvntWert = Target.Value
End Sub
I hope someone can help me. Thank you very much in advance.
greeting
ironman
Please, try the next code, I prepared yesterday for somebody else asking for a similar issue. It needs only one event and should do what you require here:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RangeValues As Variant, r As Long, boolOne As Boolean, TgValue 'the array to keep Target values (before UnDo)
Dim sh As Worksheet: Set sh = Worksheets("Protokoll")
Dim UN As String: UN = Application.userName
'sh.Unprotect "" 'it should be good to protect the sheet
If sh.Range("A1") = "" Then sh.Range("A1").Resize(1, 6) = _
Array("Time", "User Name", "Changed cell", "From", "To", "Sheet Name")
Application.ScreenUpdating = False 'to optimize the code (make it faster)
Application.Calculation = xlCalculationManual
If Target.cells.count > 1 Then
TgValue = extractData(Target)
Else
TgValue = Array(Array(Target.value, Target.Address(0, 0))) 'put the target range in an array (or as a string for a single cell)
boolOne = True
End If
Application.EnableEvents = False 'avoiding to trigger the change event after UnDo
Application.Undo
RangeValues = extractData(Target) 'define the RangeValue
putDataBack TgValue, ActiveSheet 'put back the changed data
If boolOne Then Target.Offset(1).Select
Application.EnableEvents = True
Dim columnHeader As String, rowHeader As String
For r = 0 To UBound(RangeValues)
If RangeValues(r)(0) <> TgValue(r)(0) Then
sh.cells(rows.count, 1).End(xlUp).Offset(1, 0).Resize(1, 6).value = _
Array(Now, UN, RangeValues(r)(1), RangeValues(r)(0), TgValue(r)(0), Target.Parent.Name)
End If
Next r
'sh.Protect ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub putDataBack(arr, sh As Worksheet)
Dim i As Long, arrInt, El
For Each El In arr
sh.Range(El(1)).value = El(0)
Next
End Sub
Function extractData(rng As Range) As Variant
Dim a As Range, arr, count As Long, i As Long
ReDim arr(rng.cells.count - 1)
For Each a In rng.Areas 'creating a jagged array containing the values and the cells address
For i = 1 To a.cells.count
arr(count) = Array(a.cells(i).value, a.cells(i).Address(0, 0)): count = count + 1
Next
Next
extractData = arr
End Function

Use VBA to select Excel cell values conditionally based on cell format (cell background color)

i want to print value where background yellow is same as cell and background white is [0,0]
for this condition i want to get
[1,9],[0,0],[1,7],[1,6],[0,0],[1,4],[0,0],[1,2],[0,0]
I've written some code
Dim isect As Range
Set isect = Intersect(Target, Me.Range("$B$80:$J$80"))
If Not isect Is Nothing Then
Dim s As String
If Target.Interior.Color = vbYellow Then
s = Target.Value
Else
s = "[0,0]"
End If
Range("D96").Value = s
but it get only one value, what I should do for continuing.
Any help will be appreciated.
Dim isect As Range
Dim aCell As Range
Dim Output As String
Set isect = Intersect(target, Me.Range("$B$80:$J$80"))
If Not isect Is Nothing Then
For Each aCell In isect
If aCell.Interior.Color = vbYellow Then
Output = Output & "," & aCell.Value
Else
Output = Output & "," & "[0,0]"
End If
Next aCell
Range("D96") = Mid(Output, 2)
End If
Is this what you want?
Dependent on Cell Property (Fill Color)
Standard Module Code (e.g. Module1)
Option Explicit
Function getString(SourceRange As Range, _
Optional ByVal FillColor As Long = 0, _
Optional ByVal CriteriaNotMetValue As Variant = Empty, _
Optional ByVal Delimiter As String = ", ") _
As String
If SourceRange Is Nothing Then Exit Function
' Write values of range to array.
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
' Modify values in array.
Dim i As Long, j As Long, Result As String
For i = 1 To UBound(Data)
For j = 1 To UBound(Data, 2)
If SourceRange.Cells(i, j).Interior.Color <> FillColor Then
Data(i, j) = CriteriaNotMetValue
End If
Result = Result & Delimiter & Data(i, j)
Next j
Next i
' Remove redundant Delimiter.
getString = Right(Result, Len(Result) - Len(Delimiter))
End Function
Sheet Code (e.g. Sheet1)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const rngAddress As String = "B80:J80"
Const cellAddress As String = "D96"
Const CriteriaNotMetValue As Variant = "[0,0]"
Const FillColor As Long = vbYellow
Const Delimiter As String = ","
If Intersect(Me.Range(rngAddress), Target) Is Nothing Then Exit Sub
On Error GoTo clearError
Application.EnableEvents = False
Dim Result As String
Result = getString(Me.Range(rngAddress), FillColor, CriteriaNotMetValue, Delimiter)
Me.Range(cellAddress).Value = Result
CleanExit:
Application.EnableEvents = True
Exit Sub
clearError:
Debug.Print "Run-time error '" & Err.Number & "': " & Err.Description
On Error GoTo 0
GoTo CleanExit
End Sub

Update excel cell with date if a cell in a range is update

I need to update a cell with the date and time stamp (NOW()) if any cell is updated within any cell before it within that same row.
So update cell "CU" with date and time when any cell from "A-CR" is updated.
I have done some searching but I can only seem to find bits that work if only updating a single cell, I'm looking for if anything changes within that range.
I currently have some Vba which does something similar which will update the adjacent cell with time and date which is required but I also need an overall one for the whole process.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP")) Is Nothing Then
On Error GoTo safe_exit
With Application
.EnableEvents = False
.ScreenUpdating = False
Dim trgt As Range, ws1 As Worksheet
'Set ws1 = ThisWorkbook.Worksheets("Info")
For Each trgt In Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP"))
If trgt <> vbNullString Then
If UCase(trgt.Value) = "Y" Or UCase(trgt.Value) = "N" Then
Cells(trgt.Row, trgt.Column + 1) = Now()
Cells(trgt.Row, trgt.Column + 2) = Environ("username")
'Select Case trgt.Column
' Case 2 'column B
' Cells(trgt.Row, trgt.Column + 1) = Environ("username")
' Case 4 'column D
' 'do something else
' End Select
Else
trgt = ""
Cells(trgt.Row, trgt.Column + 1) = ""
Cells(trgt.Row, trgt.Column + 2) = ""
End If
End If
Next trgt
'Set ws1 = Nothing
End With
End If
safe_exit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
This works for me:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Intersect(Target, Me.Range("A" & Target.Row & ":CR" & Target.Row)) Is Nothing Then GoTo SafeExit
Me.Cells(Target.Row, "CU") = Now()
SafeExit:
Application.EnableEvents = True
End Sub
The below code takes care of:
Clearing the time if the row is blank.
Updating the time only if the values really change from the previous value.
Dim oldValue As String
'Change the range below where your data will be
Const RangeString = "A:CR"
'Below variable decides the column in which date will be displayed
'Change the below value to 1 for column A, 2 for B, ... 99 for CU
Const ColumnIndex = 99
Private Sub Worksheet_Change(ByVal Target As Range)
Dim WorkRng As Range
Dim HorizontalRng As Range
Dim Rng As Range
Dim HorRng As Range
Dim RowHasVal As Boolean
Set WorkRng = Intersect(ActiveSheet.Range(RangeString), Target)
If Not WorkRng Is Nothing Then
If WorkRng.Cells.Count = 1 And WorkRng.Cells(1, 1).Value = oldValue Then
Exit Sub
End If
Application.EnableEvents = False
For Each Rng In WorkRng
Set HorizontalRng = Intersect(ActiveSheet.Range(RangeString), Rows(Rng.Row))
RowHasVal = False
For Each HorRng In HorizontalRng
If Not VBA.IsEmpty(HorRng.Value) Then
RowHasVal = True
Exit For
End If
Next
If Not RowHasVal Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).ClearContents
ElseIf Not VBA.IsEmpty(Rng.Value) Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).Value = Now
ActiveSheet.Cells(Rng.Row, ColumnIndex).NumberFormat = "dd-mm-yyyy, hh:mm:ss"
End If
Next
Application.EnableEvents = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, ActiveSheet.Range(RangeString)) Is Nothing Then
If Target.Cells.Count = 1 Then
oldValue = Target.Value
Else
oldValue = ""
End If
End If
End Sub

Create comments to a range of cells ftom the values of another range of cells

I want to create comments to a range of cells. The comments should contain the values of another range of cells.
Here is what I have so far:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim sResult As String
If Union(Target, Range("A18")).Address = Target.Address Then
Application.EnableEvents = False
Application.ScreenUpdating = False
sResult = "Maximal " & Target.Value
With Range("I6")
.ClearComments
.AddComment
.Comment.Text Text:=sResult
End With
Application.EnableEvents = True
Application.ScreenUpdating = True
End If
End Sub
This works for one cell. I need this for a range of cells. For example, let's say I need the values of cells A1:F20 in comments of cells A21:F40. I do not want to copy the same Sub as many times.
It should do you the job if you replace
With Range("I6")
.ClearComments
.AddComment
.Comment.Text Text:=sResult
End With
with
For Each cell In Range("A1", "F20").Cells
Dim V As Range
Set V = cell.Offset(20, 0)
With cell
.ClearComments
If Not IsEmpty(V) Then
.AddComment V.Value
End If
End With
Next
This will basically ignore all empty cells.
Output:
My code:
Sub TEST()
For Each cell In Range("A1", "F20").Cells
Dim V As Range
Set V = cell.Offset(20, 0)
With cell
.ClearComments
If Not IsEmpty(V) Then
.AddComment V.Value
End If
End With
Next
End Sub
I made some adaptions to your advices, thanks a lot, this solved my problem:
Private Sub Worksheet_Change(ByVal target As Range)
Dim src As Range: Set src = Worksheets("maxleft").Range("C2:K11")
Dim tar As Range: Set tar = Range("I6:Q15")
For i = 0 To tar.Rows.Count - 1
For j = 0 To tar.Columns.Count - 1
Dim sResult As String
sResult = "Maximal " & Worksheets("maxleft").Cells(src.Row + i, src.Column + j)
With Cells(tar.Row + i, tar.Column + j)
.ClearComments
.AddComment
.Comment.Text Text:=sResult
End With
Next j
Next i
End Sub
From your question I understand that you want to select a range of cells (e.g. "A1:A5"), then select another range of cells (e.g. "B6:B10") and the respective values of the first selected Range should be placed as comments in the secon selected Range. Is this correct?
The following code checks if 2 ranges with an equal length are selected and copies the values of the first selected range as comments to the second selected range:
Private Sub Worksheet_SelectionChange(ByVal target As Range)
If InStr(target.Address, ",") Then
Dim selected_range() As String
selected_range = Split(target.Address, ",")
If Range(selected_range(0)).Rows.Count = Range(selected_range(1)).Rows.Count Then
Dim src As Range: Set src = Range(selected_range(0))
Dim tar As Range: Set tar = Range(selected_range(1))
For i = 0 To src.Rows.Count - 1
Dim sResult As String
sResult = "Maximal " & Cells(src.Row + i, src.Column)
With Cells(tar.Row + i, tar.Column)
.ClearComments
.AddComment
.Comment.Text Text:=sResult
End With
Next i
End If
End If
End Sub

Resources