I have a large workbook and am trying to increase performance.
Is it possible/viable to store my formulas in some sort of list contained within the code rather than in the cells on the spreadsheet?
Variable SelectedRow = the currently selected row
For example:
ColumnBFormula = A(SelectedRow) + 1
ColumnCFormula = A(SelectedRow) + 2
If the user enters 4 in cell A3, then the macro writes formulas above ONLY in empty cells B3 and C3, then converts to values. The rest of the spreadsheet remains unchanged (should only have values everywhere).
Then the user enters a 6 in cell A4 and the spreadsheet writes the formulas to empty cells B4 and C4, calculates then converts to values.
Thanks
Try:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Lastrow As Long
'Refer to Sheet1
With ThisWorkbook.Worksheets("Sheet1")
'Check if Column A affected
If Not Intersect(Target, Range("A:A")) Is Nothing And IsNumeric(Target) Then
'Disable event to avoid event trigger
Application.EnableEvents = False
Target.Offset(0, 1).Value = Target + 1
Target.Offset(0, 2).Value = Target + 2
'Enable event
Application.EnableEvents = True
End If
End With
End Sub
Instructions:
Enable Events:
Given you know what you want the code to do, you could do this without entering formulas.
In the VBA editor, add this code into the "ThisWorkbook" object ...
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim objCell As Range
Application.EnableEvents = False
For Each objCell In Target.Cells
If objCell.Column = 1 Then
If objCell.Value = "" Then
objCell.Offset(0, 1) = ""
objCell.Offset(0, 2) = ""
Else
objCell.Offset(0, 1) = objCell.Value + 1
objCell.Offset(0, 2) = objCell.Value + 2
End If
End If
Next
Application.EnableEvents = True
End Sub
Hopefully that works for you.
FYI - You'll need to add the relevant error checking for values if not numeric etc, it will need to be improved.
Related
I am creating a spreadsheet that a user will fill in specific cells with data/text.
the whole sheet will be locked to prevent one from changing things.
i want as the first cell B4 to always be unlocked and has data entered in, this then unlocks cell B5 for data entry. this will continue on for many more cells.
here is what i have done so far.....
Private Sub Worksheet_Change(ByVal Target As Range)
If IsNumeric(Range("B4:F4")) = True Then
Range("B5").Locked = False
End If
End Sub
So... I made an attempt to help you.
Private Sub Worksheet_Change(ByVal target As Range)
Const inputrange As String = "B4:F4"
Const lockrange As String = "B5:F5"
Const lockedworksheet As String = "Tabelle2"
Set insect = Application.Intersect(target, Range(lockrange))
If Not (insect Is Nothing) Then Exit Sub
Worksheets(lockedworksheet).Unprotect
Range(inputrange).Locked = False
Range(lockrange).Locked = True
For Each cell In Range(inputrange)
If IsNumeric(cell.Value) And cell.Value <> 0 Then _
Cells(cell.Row + 1, cell.Column).Locked = False Else _
Cells(cell.Row + 1, cell.Column).Value = ""
Next cell
Worksheets(lockedworksheet).Protect
End Sub
If you need an explanation, just ask.
I found the attached when looking for how to due an event change to correct user data based on the values in two columns. I'm not a programmer, so I may have butchered the code as I combined two different solutions together.
Right now, it's working exactly as I want it to. Changing the offset cell value forces Excel to replace the target value with what I've specified. What I'm looking to achieve (and am not sure is possible), is to reverse the code. Basically, I want to change the offset cell, if the values are entered in the opposite order. The code will change the cell value to "Beta" if a user enters "Bravo" in column A, and then "Gamma" in column C.
What I'm trying to achieve is that if the user enters "Bravo" in column A second, that Excel still sees the combination of these cells and still replaces the value with "Beta". I know this is additional code, but I couldn't find anything to support replacing cell when the target cell isn't the value being updated.
Thanks in advance!
Dim oldCellAddress As String
Dim oldCellValue As String
Private Sub Worksheet_Change(ByVal Target As Range)
oldCellValue = "Bravo"
If Target = "Bravo" And Target.Offset(0, -2) = "Gamma" Then
Target.Value = "Beta"
Application.EnableEvents = True
End If
End Sub
This may meet your needs:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim colnum As Long, v As Variant
colnum = Target.Column
v = Target.Value
If colnum = 1 Then
If v = "Bravo" And Target.Offset(0, 2) = "Gamma" Then
Application.EnableEvents = False
Target.Value = "Beta"
Application.EnableEvents = True
End If
Exit Sub
End If
If colnum = 3 And v = "Gamma" And Target.Offset(0, -2) = "Bravo" Then
Application.EnableEvents = False
Target.Offset(0, -2).Value = "Beta"
Application.EnableEvents = True
End If
End Sub
For example if the user puts Bravo in cell A1 and C1 already contained Gamma, the code puts Beta in A1 (the code corrects the A1 entry).If the user puts Gamma in cell C1 and cell A1 already contained Bravo, the code corrects A1.
There are two possible scenarios like below...
Scenario 1:
If ANY CELL on the sheet is changed, the following code will check the content of column A and C in the corresponding row and change the content of the Target Cell.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.CountLarge > 1 Then Exit Sub
Dim r As Long
r = Target.Row
On Error GoTo Skip:
Application.EnableEvents = False
If Cells(r, "A") = "Bravo" And Cells(r, "C") = "Gamma" Then
Target.Value = "Beta"
End If
Skip:
Application.EnableEvents = True
End Sub
Scenario 1:
If a cell in column D is changed, the change event will be triggered and check the content in column A and C in the corresponding row and change the Target Cell in Column D.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.CountLarge > 1 Then Exit Sub
Dim r As Long
On Error GoTo Skip:
'The below line ensures that the sheet change event will be triggered when a cell in colunm D is changed
'Change it as per your requirement.
If Not Intersect(Target, Range("D:D")) Is Nothing Then
Application.EnableEvents = False
r = Target.Row
If Cells(r, "A") = "Bravo" And Cells(r, "C") = "Gamma" Then
Target.Value = "Beta"
End If
End If
Skip:
Application.EnableEvents = True
End Sub
I am looking to parse an entire row in a particular excel sheet for any change in data in that row. If there is any change in data in that row then i want to add the date in which that particular cell of that row. I want to pass the row as an input. I tried the following code but it doesnt work.
Private Function User_func1(ByVal i As Long)
Dim j As Long
For j = 1 To j = 100
If Cells(i, j).Value > 1 Then
Cells(i, 2) = Now()
End If
Next j
End Function
You can use the Worksheet_Change event in the sheet you want to scan.
Option Explicit
Const RowtoTest = 2
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Target.Row = RowtoTest Then
Target.Value = Date
End If
Application.EnableEvents = True
End Sub
Option 2: Get the row to test from a certain cell, lets say Cell "A1" (value is set to 2, means look for changes in cells in row 2).
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
' compare the row number to the number inputted as the row to test in cell A1
If Target.Row = Range("A1").Value Then
Target.Value = Date
End If
Application.EnableEvents = True
End Sub
I am currently trying to add a script into excel. excuse my terminology, I am not that hot with programming!
I do all of my accounting on excel 2003, and I would like to be able to add the value of say cells f6 to f27 to the cells e6 to e27, respectively. The thing is, I want the value of the "f" column to reset every time.
So far I have found this code, which works if I copy and paste it into VBA. but it only allows me to use it on one row:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Target.Address = Range("f7").Address Then
Range("e7") = Range("e7") + Range("f7")
Range("f7").ClearContents
End If
Application.EnableEvents = True
End Sub
would somebody be kind enough to explain how I can edit this to do the same through all of my desired cells? I have tried adding Range("f7",[f8],[f9] etc.. but i am really beyond my knowledge.
First, you need to define the range which is supposed to be "caught"; that is, define the range you want to track for changes. I found an example here. Then, simply add the values to the other cell:
Private Sub Worksheet_Change(ByVal Target as Range)
Dim r as Range ' The range you'll track for changes
Set r = Range("F2:F27")
' If the changed cell is not in the tracked range, then exit the procedure
' (in other words, if the intersection between target and r is empty)
If Intersect(Target, r) Is Nothing Then
Exit Sub
Else
' Now, if the changed cell is in the range, then update the required value:
Cells(Target.Row, 5).Value = Cells(Target.Row, 5).Value + Target.Value
' ----------------^
' Column 5 =
' column "E"
' Clear the changed cell
Target.ClearContents
End if
End Sub
Hope this helps
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ErrHandler
Application.ScreenUpdating = False
Application.EnableEvents = False
If Intersect(Target, Range("B1:B5,F6:F27")) Then 'U can define any other range
Target.Offset(0, -1) = Target.Offset(0, -1).Value + Target.Value ' Target.Offset(0,-1) refer to cell one column before the changed cell column.
'OR: Cells(Target.row, 5) = Cells(Target.row, 5).Value + Target.Value ' Where the 5 refer to column E
Target.ClearContents
End If
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
If the following conditions are met:
For any given row between row 10 and row 100 inclusively:
The cell in column A is not empty
The cell in column B is not empty
The cell in column O is empty
I would like to highlight a specific cell (let's say A1).
Example:
I populate A10 and E10 while leaving O10 empty, then cell A1 gets highlighted. If I then populate cell O10, the highlight in cell A1 disappears.
I can proceed to the next row. Any row at any time should generate these actions.
Thanks!
This will do the highlights based on the conditions you specified. When you run it, it'll stop at the first row you need to input something in column O. If you want it to keep running until row 101 and highlight all the rows, then remove then Exit Do command that's between the 2 End If statements.
Sub Highlight()
Dim TheRow As Integer
TheRow = 9
Application.ScreenUpdating = False 'This hides the visual process and speeds up
'the execution
Do
TheRow = TheRow + 1
If TheRow = 101 Then Exit Do
Cells(TheRow, 1).Select
Selection.Interior.Pattern = 0
Cells(TheRow, 2).Select
Selection.Interior.Pattern = 0
If Not Cells(TheRow, 1).Value = "" And Not Cells(TheRow, 2).Value = "" And Cells(TheRow, 15).Value = "" Then
If Cells(TheRow, 1).Value = "" Then
Cells(TheRow, 1).Select
Selection.Interior.Color = 656
End If
If Cells(TheRow, 2).Value = "" Then
Cells(TheRow, 2).Select
Selection.Interior.Color = 656
End If
Exit Do 'this is the line to remove if you want to highlight all cells
End If
Loop
Application.ScreenUpdating = True
End Sub
And then, create an event handler that triggers when a cell in column 15 changes. Put the following code in the module of the actual worksheet (in the VBA project explorer, double click on the sheet you want have this functionality for; don't put this in a different module!)
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 15 Then
If Target.Row > 9 And Target.Row < 101 Then Call Highlight
End Sub
Let me know if this solution works and remember to click "accept solution" and to vote for it!
Happy coding.
You don't need VBA: just use conditional formatting on cell A10 with the following formula:
=AND(NOT(ISBLANK($A10)),NOT(ISBLANK($B10)),ISBLANK($O10))
OK - I misunderstood what you wanted. Here is a VBA UDF to do the checking.
Enter =Checker($A$10:$B$100,$O$10:$O$100) in cell A1, then use conditional formatting on cell A1 that is triggered when it becomes True.
Public Function Checker(theRangeAB As Range, theRangeO As Variant) As Boolean
Dim varAB As Variant
Dim varO As Variant
Dim j As Long
varAB = theRangeAB.Value2
varO = theRangeO.Value2
Checker = False
For j = 1 To UBound(varAB)
If Not IsEmpty(varAB(j, 1)) And Not IsEmpty(varAB(j, 2)) Then
If IsEmpty(varO(j, 1)) Then
Checker = True
Exit For
End If
End If
Next j
End Function