macro only runs manually - excel

My knowledge with VBA is fairly basic so this may seem like a silly question.
I have written a code so that cell A1 in sheet1 will read "XX" if cell B1 in sheet2 has a value in it. The code works but only if I select it and run it manually from VBA. if cell B1 in sheet2 has a value in it, cell A1 in sheet1 is not updating automatically. Here is the code
Sub IsNumeric()
If Sheets ("Sheet2").Range("B2) > 0 Then
Sheets("Sheet1").Range("A1").Value = "XX"
End If
End Sub
Cell B2 in sheet2 is a formula which will only generate a number if another cell is selected. i am not sure if this is relevant but as i mentioned the code is working just fine, just not automatically.
Thanks!

You need to change your code a touch. Have a proper UDF defined and called from Sheet1 A1, with a reference passed to Sheet2 A1, for example
The function
Function IsNumeric2(rngCheck As Excel.Range)
If rngCheck.Value > 0 Then
IsNumeric2 = "XX"
Else
IsNumeric2 = ""
End If
End Function
The call, in cell A1, =IsNumeric2(Sheet2!A1)

If you want macro's to work automatically, based on an event in the workbook, you can add a workbook event macro in ThisWorkbook. In this case you can use the Workbook_SheetChange event for instance, which runs everytime you make a change on a sheet: https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.sheetchange
Private Sub Workbook_SheetChange(ByVal Sh As Object,ByVal Source As Range)
Application.EnableEvents = False 'Switch off events because otherwise it gets triggered again for the changes made in this macro
'First make sure that it only triggers when you change B2 of sheet 2
If Source.Address = "$B$2" and Source.Parent.Name = "Sheet2" then
If Source.Value > 0 Then
ThisWorkbook.sheets("Sheet1").Range("A1").Value = "XX"
End If
end if
Application.EnableEvents = True 'Turn the events back on again.
End Sub

Related

Excel VBA - Copy a formula result to a cell in another sheet + add succesive formula results in consecutive rows each time the formula is recalculated

I am running a partially randomize set of data and trying to find the best solutions depending on certain parameter changes. I need to "record" certain solutions and then compare different results for different parameters each time the randomized variables are recalculated.
I would like to do the to following:
On Sheet1, cell S255, is the result of a formula =SUM(M252:S252)
I need to automatically add that result (Sheet1 S255), to Sheet5, column A, starting at A1.
Then, each time the formula is recalculated and the result changes, I need the new result to be added to the consecutive row to the previous result (so the second result would go to A2, third one to A3, and so on).
Looking for similar cases I have come to be able to do 1. and 2. using this event:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet: Set ws = Sheets("Sheet5") 'declare and set the worksheet the data is to be copied into, amend the sheet name as required
If Target.Address = "$S$255" Then 'if anything changes in C6 or C9 in this sheet
ws.Range("A1").Value = Target.Parent.Range("S255") 'copy the value from cell C10 in this sheet to Sheet2 in cell E5
End If
End Sub
Doing 3. is proving more challenging. What event would be suitable to do so?
Thanks in advance for your time and understanding!
Thats how you are able to solve it with the Worksheet_Calculate event like BigBen suggested. Under "Random numbers" are just a few numbers with the RANDBETWEEN-Function for showing puposes. Just change the code for your case. Everytime you press "Delete" for exaple the new sum will be set under the Results column.
Private Sub Worksheet_Calculate()
Dim lastRow As Long
'EnableEvents must be switched off so that the macro does not
'call itself in an endless loop by cell change
Application.EnableEvents = False
lastRow = WorksheetFunction.CountA(Range("C:C")) + 1
Range("C" & lastRow).Value = Range("A9").Value
Application.EnableEvents = True
End Sub
'example saving sum ONLY IF SUM CHANGES
Private Sub Worksheet_Calculate()
Dim offsetLastSum As Long, curSum As Double
offsetLastSum = Range("NEXT_SUM_OFFSET").Value2
curSum = Range("THE_SUM").Value2
With Range("SUM_HISTORY_HEAD")
If .Offset(offsetLastSum - 1).Value2 <> curSum Then
Application.EnableEvents = False
.Offset(offsetLastSum).Value2 = curSum
Application.EnableEvents = True
End If
End With
End Sub

Stopping a macro if there's no value entered

I want my macro to stop if there's no value entered in any of the four cells I need. But i want it to run if there's at leats one value in those four cells.
This is what i have so far:
If Range("e12,h12,k12,d12").Value = "" Then
MsgBox ("Por favor introducir dimensiones")
Range("e12").Select
Exit Sub
End If
If you introduce a value in cell e12, it will run. But if you introduce a value in any other cell, the msgbox will pop out and the macro will stop.
Could you help me find the problem?
Thank you!
Please install the event procedure below in the code sheet of the worksheet on which you want the action.
Private Sub Worksheet_Change(ByVal Target As Range)
Const Triggers As String = "E12,H12,K12,D12"
Dim Rng As Range
Dim Cell As Range
' skip if more than one cell was changed (like paste)
If Target.Cells.CountLarge = 1 Then
Set Rng = Range(Triggers)
For Each Cell In Rng
If Cell.Value = "" Then
Cell.Select
Exit For
End If
Next Cell
End If
End Sub
Now, if the user enters something in E12 the macro will select H12. If the user enters something in D12 next the macro will take him back to K12. That's all very nice.
But if the user changes something in A3 (anywhere, in fact) he will be taken to the first empty cell of the trigger range. Therefore the system must be tweaked to accommodate your workflow. Perhaps the code should be made to run only when D12 is entered, or when the user clicks on the cell he shouldn't click on before completing the trigger range.
In short, the scope of the procedure may have to be trimmed to suit your workflow. This can be done by either including specific cells in the trigger range, or by excluding other cells.
you coudl use WorksheetFunction.CountA() function to count the number of not empty cells:
If WorksheetFunction.CountA(Range("e12,h12,k12,d12")) <> 4 Then
MsgBox ("Por favor introducir dimensiones")
Range("e12").Select
Exit Sub
End If

Automatic Sheet Calculation (Checkbox linked to cell)

I'm working on a table where I've inserted some Checkboxes (Form Control) which are linked to cells that return True or False when either Checkbox is ticked.
I wrote a code that should change the cell's color according to the returned value.
The code works fine but only when I double click the cell and validate by pressing Enter, or when I run the Sub by hitting F5 or a clicking a button.
(I used a similar code that updates everything automatically in another project but it doesn't seem to work here)
How can I make the Sub run automatically (or the sheet update) once a checkbox is ticked?
Here is the code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("A2:Q21"), Range(Target.Address)) Is Nothing Then
Dim cell As Range
For Each cell In ActiveWorkbook.Sheets("Sheet1").Range("A2:Q21")
If cell.Value = "True" Then
cell.Interior.Color = vbGreen
ElseIf cell.Value = "False" Then
cell.Interior.Color = vbRed
End If
Next
End Sub
I know I could use conditional formatting but this sheet will expand rapidly and I don't see myself copy-pasting hundreds of checkboxes
As the sheet will expand I think it'll be better to include a "lastRow" statement since I will be adding new rows at the bottom using a UserForm
Thanks!
You should extract the part doing the coloring to a new function and call that from both the original and from the checkbox's event handler.
' In Sheet1 Module
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("A2:Q21"), Range(Target.Address)) Is Nothing Then
ColorCells
End If
End Sub
' In Module1 Module
Sub CheckBox1_Click()
ColorCells
End Sub
Public Sub ColorCells()
Dim cell As Range
For Each cell In ActiveWorkbook.Sheets("Sheet1").Range("A2:Q21")
If cell.Value = "True" Then
cell.Interior.Color = vbGreen
ElseIf cell.Value = "False" Then
cell.Interior.Color = vbRed
End If
Next
End Sub
Update
If there are too many checkboxes than you may use the Worksheet's Calculation event handler assuming that the checkboxes have Linked Cells and some other Cell refers to their value.
' In Sheet1 Module
Private Sub Worksheet_Calculate()
ColorCells
End Sub
Note, if the checkbox does not have a Linked Cell, it won't work. If the checkbox has a Linked Cell but it is not referred to by any other cell, it won't work. This is because in these cases no recalculation will be initiated.
You can test this: Assign A1 to a Checkbox (on a new sheet), and try if the macro runs (should not), then write in A2 =2*--A1, and check again, now it should work.
If you want to minimize the footprint of this requirement, find an unused cell on the sheet and enter the following formula: =INDEX(1:1048576,1,1). This refers to all cells but it does not require a lengthy calculation. Of course, if you want to place it into A1, you should change the ,1,1 part to something else to avoid circular references.
Instead of firing your colouring sub at Worksheet_Change, put it under Worksheet_Calculate. Then insert the formula =A1:Q21(or whatever you need to cover your range) somewhere in your sheet. It will resolve to #value but that isn't important. This formula will force your sheet to automatically recalculate when anything within its range is changed, including the cells linked to your checkboxes. And then upon recalculate it will fire the sub that colours your cells correctly.

Run macro at specific time when check box is checked(manual calculation)

I'm trying to run a macro in excel at a specific time if check box is checked.
It is working as it should, only problem is that it works only when
workbook is set to automatic calculations and I need workbook to be set to manual calculations.
Here is a VBA code I'm using in that file:
sheet1:
Private Sub Worksheet_Calculate()
Dim time_dt As Date
time_dt = Cells(1, 7)
If Range("C1").Value = "YES" Then
Application.OnTime TimeValue(time_dt), "FillFirstColumn"
End If
End Sub
and here is a Module 1 code:
Sub FillFirstColumn()
Range("A1:A20").Value = "YES"
End Sub
When I click on check box, cell D1 is changing from FALSE to TRUE. In a cell C1 I have this formula =IF(D1=TRUE,"YES","NO"). And C1 is not recalculating unless a workbook is set to automatic.
Based on advice from a comment below I've added this VBA code to sheet1:
Private Sub CheckBox1_Click()
ThisWorkbook.Worksheets("Sheet1").Cells(1, "C").Calculate
End Sub
but formula in C1 is still not recalculating.
You can Calculate all open workbooks, one workbook with many worksheets, one worksheet, a range of cells in a worksheet or a single cell.
thisworkbook.worksheets("sheet1").cells(2, "B").calculate
The above will recalculate a single cell (Sheet1!B2) in the workbook that the sub procedure was running in.

Why can't I change the active Excel worksheet using VBA

I have a Function that is attempting to change the current active sheet ("Sheet1") to (Sheet2) and then assign a value to a cell in Sheet2.
However the ActiveSheet.name doesn't change and the assignment fails. see the code snippet. The function is called from sheet1.
Dim oldwksheet as String
oldwksheet = ActiveSheet.Name 'value is Sheet1
Sheets("Sheet2").Activate
Sheets("Sheet2").Select
oldwksheet = ActiveSheet.Name 'value still is Sheet1"
Sheets("Sheet2").Range("F2") = Now() 'this fails.
end function
Why? What am I doing wrong.
You need a sub and not a function.
A function can only return a value to the cell in which it resides. It can't select or activate worksheets or deposit values in arbitrary cells.
I couldn't say why, but you could use a Function
assuming your function's named after "MyFunction" then place in relevant worksheet code pane the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count = 1 Then If Left(Target.Formula, 12) = "=MyFunction(" Then Sheets("Sheet2").Range("F2") = Now()
End Sub
this way, whenever you type =MyFunction() in any cell of the relevant worksheet, the current date and time is being placed in cell F2 of Sheet2

Resources