Custom function will not update automatically (settings are set to auto calculations!) - vba

I have a custom function that detects if a cell is bold
Function isBold(cellBold)
If cellBold.Font.Bold = True Then
isBold = 1
ElseIf cellBold.Font.Bold = False Then
isBold = 0
Else
isBold = 0
End If
End Function
Puts 1 in a cell if the reference cell is bold and 0 if it is not bold
This works well and all the first time around but if I make the reference cell bold the number stays at 0. Automatic calculations are on, the only way for the function to calculate again is to retype the function

Adding Application.Volatile to the top of your function will make it auto update when the workbook change event is fired.
Function isBold(cellBold)
Application.Volatile
If cellBold.Font.Bold = True Then
isBold = 1
ElseIf cellBold.Font.Bold = False Then
isBold = 0
Else
isBold = 0
End If
End Function
This will not help you if you just bold a result but you can add an event to the sheet you're working on
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Calculate
End Sub
If both of these things are in place, your formula will update every time you select a different cell which may work well enough for you. However, I suggest using this method with caution because if you have a very large number of formulas this could slow things down.
-Edit- This should fix the copy paste issue.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim col As Range
For Each col In ActiveSheet.UsedRange.Columns
col.Calculate
Next
End Sub

OK, So I'll be the first to admit this is not an ideal solution, and is pretty hackish. But i think it will fix your solution.
After adding the volatile line to your code as so:
Function isBold(cellBold)
Application.Volatile True
If cellBold.Font.Bold = True Then
isBold = 1
ElseIf cellBold.Font.Bold = False Then
isBold = 0
Else
isBold = 0
End If
End Function
First Change your Workbook_Open to this:
Private Sub Workbook_Open()
Sheets("Sheet1").rngLastCell = Range("A1").Address
Sheets("Sheet1").fntLastCell = Range("A1").Font.Bold
End Sub
Then on the worksheet you are working with (In my example Sheet1) Add this to the Worksheet function:
Option Explicit
Public fntLastCell As Boolean
Public rngLastCell As String
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Sheets("Sheet1").Range(rngLastCell).Font.Bold <> fntLastCell Then
Calculate
End If
Sheets("Sheet1").rngLastCell = Target.Address
Sheets("Sheet1").fntLastCell = Target.Font.Bold
End Sub
Now to have it work you must Save then close, Then re open your worksheet.
This works by setting 2 global variables each time you select a new cell.
a Boolean variable that states weather the Last Cell selected WAS PREVIOUSLY Bold or not. And a String Variable that references that same Cell. So, you can now check the Bold state of the cell you exited (when it was entered) against the Current Bold State of the cell you just existed and if there was a change it will calculate the workbook. Otherwise nothing will happen.
Hope this works and helps,
Cheers

Related

Trigger macro with change in different worksheet

Apologies any incorrect terms, this is the first time I am trying to code a macro. I currently have the following code running:
Private Sub Worksheet_Deactivate()
'Alpha Show / Hide
If Sheets("Project_selection").Range("D4") = Range("C2") Then
Sheet3.EnableCalculation = True
ElseIf Sheets("Project_selection").Range("D4") = "All" Then
Sheet3.EnableCalculation = True
Else
Sheet3.EnableCalculation = False
End If
End Sub
which has been cobbled together from other codes and google. It works, but only when I move out of the sheet, which I think is being driven by the first line.
I would actually like it to activate when the Cell D4 in the 'Project_selection' sheet (a separate sheet to the one the code is on) gets changed - does anyone know how I would do that? I have seen references to worksheet_change, but I do not understand how one defines the target/range to get the appropriate reference.
Hope that makes sense and thanks in advance!
If you were to place the following code under the sheet (Project_selection), it would fire that event every time a change has happened in Cell D4:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet: Set ws = Sheets("Project_selection")
If Target.Address = "$D$4" Then
If ws.Range("D4") = ws.Range("C2") Then
Sheet3.EnableCalculation = True
ElseIf ws.Range("D4") = "All" Then
Sheet3.EnableCalculation = True
Else
Sheet3.EnableCalculation = False
End If
End If
End Sub

Why wont the code below execute when a cell is double clicked on?

The code below ran earlier but will not execute when a cell is double clicked.
Private Sub Worksheet_DoubleClick(ByVal Target As range, Cancel As Boolean)
If Target.Font.Bold = False Then
Target.Font.Bold = True
Target.Font.Color = vbRed
Else
Target.Font.Bold = False
Target.Font.Color = 1
End If
End Sub
Not an answer to why it's not working (#Mat's Mug and #Scott Craner beat me to that again), but a shortened version of the code.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
With Target.Font
.Bold = Not .Bold
.Color = Choose(Abs(CLng(.Bold)) + 1, 1, vbRed)
End With
End Sub
Ok, not as easy to follow as the original but here's what it's doing:
Target.Font.Bold is either TRUE or FALSE, so Not .Bold will return the opposite.
Bold = TRUE so Not Bold = FALSE
Abs(CLng(.Bold)) + 1
Again, .Bold is either TRUE or FALSE. Numerically TRUE = -1, FALSE = 0.
CLNG(.Bold) will return -1 or 0.
ABS(CLNG(.Bold)) will return 1 or 0.
Abs(CLng(.Bold)) + 1 will return 1 or 2 - which is used in the CHOOSE command to return vbRed or 1.
DO NOT type any of these signatures manually!
Use the code pane dropdowns instead:
Select Worksheet from the left dropdown, and pick an event to handle in the right dropdown; the VBE will generate a method stub with the proper signature for you.
Typing them out manually off the top of your head can (and does!) result with handlers that end up never being called, or worse, that are called, but are given parameter values in the wrong arguments, e.g. if UserForm_QueryClose is typed up manually with inverted parameters (the handler has 2 Integer parameters, so you need to remember the exact order.. otherwise you assign Cancel and the form understands that you assigned CloseMode)
If you're not seeing Worksheet in the left dropdown, then you're not in a worksheet's code-behind module. Worksheet events can only be handled in a worksheet module.
In a Workbook module (i.e. ThisWorkbook) you can handle the SheetBeforeDoubleClick event to handle a double-click on any worksheet in the workbook:
Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
End Sub

Using VBA to hide rows in Excel if a Value returns 0

I'm trying to create an automated proposal document, and when a certain value returns 0 in my spreadsheet, I want to hide a bunch of extraneous rows/graphics that are in those rows to reduce clutter and make a clean pdf to send out.
Private Sub Worksheet_Change(ByVal Target As Range)
If .Range("F15").Value = "0" Then
Rows("7:25").EntireRow.Hidden = True
ElseIf Range("f15").Value Then
Rows("7:25").EntireRow.Hidden = False
End If
End Sub
Where should I go from here? If f15 returns as a value greater than 0, I wish for the rows to be shown.
try this, holp it works
Private Sub Worksheet_Change(ByVal Target As Range)
If .Range("F15").Value = "0" Then
Rows("7:25").EntireRow.Hidden = True
Else
Rows("7:25").EntireRow.Hidden = False
End If
End Sub

Change worksheet tab color if range of cells contains text

I have tried code that I've found here on stackoverflow, and elsewhere but they aren't working as I think they can. I'll list them below. I'm almost certain this is an easy question.
What I'm trying to do: If in any of the cells in the range A2:A100 there is any text or number whatsoever, then make the worksheet tab red. And I will need to do this on over 20 tabs. This must execute upon opening the workbook, and thus not require manually changing a cell or recalculating.
The problems I've had with other code: As far as I can tell they require editing a cell, and then quickly hitting enter again. I tried SHIFT + F9 to recalculate, but this had no effect, as I think this is only for formulas. Code 1 seems to work albeit with having to manually re-enter text, but no matter what color value, I always get a black tab color.
Code I've tried:
Code 1:
Private Sub Worksheet_Change(ByVal Target As Range)
MyVal = Range("A2:A27").Text
With ActiveSheet.Tab
Select Case MyVal
Case ""
.Color = xlColorIndexNone
Case Else
.ColorIndex = 6
End Select
End With
End Sub
Code 2: This is from a stackoverflow question, although I modified the code slightly to fit my needs. Specifically, if in the set range there are no values to leave the tab color alone, and otherwise to change it to color value 6. But I'm sure I've done something wrong, I'm unfamiliar with VBA coding.
Private Sub Worksheet_Calculate()
If Range("A2:A100").Text = "" Then
ActiveWorkbook.ActiveSheet.Tab.Color = xlColorIndexNone
Else
ActiveWorkbook.ActiveSheet.Tab.Color = 6
End If
End Sub
Thanks for your help!
I posted this on superuser first, but perhaps stackoverflow is more appropriate since it is explicitly programming-related.
Only two things will be able to switch the condition in this statement:
If Range("A2:A100").Text = "" Then
You've already identified both of them, changing the contents of the one of the cells in that range on a worksheet, or a formula in one of those cells recalculating to or from a value of "". As far as event triggers go, if the formula result changes, both the WorkSheet_Calculate and Worksheet_Change events will fire. Of the two, Worksheet_Change is the one to respond to, because WorkSheet_Calculate will only fire if any of the cells in A2:A100 contain a formula. Not if they only contain values - your "Code 2" isn't wrong, the event was just never firing.
The simple solution is to set your tab colors when you open the workbook. That way it doesn't matter if you have to activate a cell in that range and change it - that's only way the value you're testing against is going to change.
I'd do something like this (code in ThisWorkbook):
Option Explicit
Private Sub Workbook_Open()
Dim sheet As Worksheet
For Each sheet In Me.Worksheets
SetTabColor sheet
Next sheet
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Not Intersect(Target, Sh.Range("A2:A100")) Is Nothing Then
SetTabColor Sh
End If
End Sub
Private Sub SetTabColor(sheet As Worksheet)
If sheet.Range("A2:A100").Text = vbNullString Then
sheet.Tab.Color = xlColorIndexNone
Else
sheet.Tab.Color = 6
End If
End Sub
EDIT: To test for the presence of specific text, you can do the same thing but need to have the test check every cell in the range you're monitoring.
Private Sub SetTabColor(sheet As Worksheet)
Dim test As Range
For Each test In sheet.Range("A2:A100")
sheet.Tab.Color = xlColorIndexNone
If test.Text = "whatever" Then
sheet.Tab.Color = vbRed
Exit For
End If
Next test
End Sub
Maybe test the len of the trimmed joined string of cells:
Private Sub Worksheet_Calculate()
If Len(Trim(Join(Application.Transpose(Range("A2:A100"))))) = 0 Then
ActiveWorkbook.ActiveSheet.Tab.Color = xlColorIndexNone
Else
ActiveWorkbook.ActiveSheet.Tab.Color = 6
End If
End Sub
This code will fire off every time the sheet calculates though as it is event code, I am not sure if that is what you want? If not then post back and we can drop it into a normal sub for you and make it poll all the sheets to test.
Worksheet_Change function will get called everytime there's change in the target range. You just need to place the code under Worksheet. If you have placed the code in the module or Thisworkbook then it wont work.
Paste the below in Sheet1 of your workbook and check if it works. Of Course you will need to do modification to the below code as I have not written complete code.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim WatchRange As Range
Dim IntersectRange As Range
Set WatchRange = Range("A1:A20")
Set IntersectRange = Intersect(Target, WatchRange)
If IntersectRange Is Nothing Then
''Here undo tab color
Else
ActiveSheet.Tab.ColorIndex = 6
End If
End Sub

Excel VBA: function to turn activecell to bold

I have the following function inside my module.
Function Colorize(myValue)
ActiveCell.Select
Selection.Font.Bold = True
Colorize = myValue
End Function
The cell that will use this function should be turning bold - however, I get no error messages back and sad but true, its not turning bold. What am I missing?
Thanks
A UDF will only return a value it won't allow you to change the properties of a cell/sheet/workbook. Move your code to a Worksheet_Change event or similar to change properties.
Eg
Private Sub worksheet_change(ByVal target As Range)
target.Font.Bold = True
End Sub
I use
chartRange = xlWorkSheet.Rows[1];
chartRange.Font.Bold = true;
to turn the first-row-cells-font into bold. And it works, and I am using also Excel 2007.
You can call in VBA directly
ActiveCell.Font.Bold = True
With this code I create a timestamp in the active cell, with bold font and yellow background
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ActiveCell.Value = Now()
ActiveCell.Font.Bold = True
ActiveCell.Interior.ColorIndex = 6
End Sub