I have some complicated Excel formatting to do, but I have no idea where to begin.
There are few criteria that need to be met:
When there are cell values in F3 and H3, the time at cell N4 should automatically be the time in N3 plus three hours.
If system time is exceeds the value in N4, and the value in F4 and H4 is still empty, it will trigger a message or format highlighting to inform user that the time is over.
If there is new bath being created in column B, the time in column N will stop adding the time and just left blank for user to key in the new time.
For 1. & 3., you'd simply use an if formula:
=IF(AND(F3<>"",H3<>"",B3=B4),N3+3/24,"")
This is assuming the value in N3 is a time value, otherwise it gets a bit trickier - but hardly impossible.
Your problem statement no. 2 is somewhat trickier, I don't think you can it without VBA, and the code isn't entirely straightforward. However, I'll give it a go. In a similar-ish workbook, I have a line which moves forward to indicate when different tasks needs to be completed. To have the "line" move, I color in a column of cells using conditional formatting, comparing the column of cells to a timestamp I have in Y29. The code I use to update the timestamp is the following, it updates the cells every minute:
In a standard module
Option Explicit
Public setDate As Date
Public Const nameToIgnore = "OAA0006Monitor"
Sub UpdateTime()
If currentUser() = nameToIgnore Then
Else
setDate = Now() + TimeValue("00:01:00")
Application.OnTime setDate, "TimeUp"
End If
End Sub
Sub TimeUp()
If currentUser() = nameToIgnore Then
Else
ThisWorkbook.Worksheets("ArbPlan 2011 (5)").Range("Y29") = Time
UpdateTime
End If
End Sub
Sub KillOnTime()
If currentUser() = nameToIgnore Then
Else
On Error Resume Next
Application.OnTime setDate, "TimeUp", , False
On Error GoTo 0
End If
End Sub
In the ThisWorkbook-module
Option Explicit
Private Sub Workbook_Activate()
UpdateTime
End Sub
Private Sub Workbook_Deactivate()
KillOnTime
End Sub
I don't think this should be very hard to convert to the purpose you want it for, instead of using conditional formatting, you can even have the code do all the formatting for you! :)
Anyway, I hope this gives you a good starting point, feel free to comment if you feel anything is unclear, or if you have trouble understanding any of the logic of the code.
Related
I'd like to modify values on specific cells depending on a specific group if it's expanded or collapsed.
I found a way, but it's a manual way (image1 image2) (the macro needs to be launched on each run).
Is there a way to use a function (i.e. worksheet_change), so that will be on real time ?
P.S. Sorry for my bad English and be kind, I'm kinda new on VBA (first code).
Thank you.
Private Sub groups()
If Worksheets("Feuil1").Columns("F").ShowDetail = True Then
Range("K2:K7").Value = "YES"
Else
Range("K2:K7").Value = "NO"
End If
End Sub
Thank you Luuklag for your solution, but as I said in my comment, in your code I have to update manually the placeholder cell which is not what I'm looking for.
But, I found something where my cells get updated by expanding or collapsing my group. And for this, as you said, I need a placeholder cell that gets updated on each calculation.
I use the formula =NOW on cell A1, because it's always useful to know the time and date.
Here is the (combined) code, for those who are looking a solution :
Private Sub Worksheet_Calculate()
Application.EnableEvents = False
'Where F is the column having the group button
If Columns("F").ShowDetail = True Then
'This is where you choose the cells that are dependent to the group and attribute something
Range("G10:G19").Value = "YES"
Else
'Same here. It could be other cells too
Range("G10:G19").Value = "NO"
End If
Application.EnableEvents = True
End Sub
There is a simple solution to this. Every time you expand or collapse a group you trigger the worksheet_calculate event. This can be used to your advantage.
All you need is a placeholder cell, which you populate with a volatile function (a function that changes its value on each calculation). You can use =randbetween(1,10) or =NOW() for example.
You then have your worksheet change event to look for your placeholder cell, AA1 in this example.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("AA1")) Is Nothing Then
Call groups
End If
End Sub
What if we could fill a date by only referring a number ? This type of feature would improve user-friendliness in some excel scenarios.
For instance : In March sheet, when I type "7" in a given dates column, the cell in which I inserted the value would return "07/03/19" (or 03/07/19).
If possible, this means I need to specify in the VBA code the month and year for this sheet, and change this variable for every single sheet (february etc.). If the sheet names are months names (Eg "March"), there could even be a way to do it with a one solution VBA code. The following formula takes advantages of it, so I guess VBA could do it to.
=MONTH(DATEVALUE(MID(CELL("filename";$A$1);FIND("]";CELL("filename";$A$1))+1;255)&" 1"))
Enter this formula in a sheet named "March" and it will return "3".
I have been looking for a simple way to do this, but there is none to my knowledge (until you bring your light :)). Data validation feature won't help as far as I know. Also, it's important that the cell in which the number is inserted autofill itself (not another cell).
Is this at least possible ? I bet yes. I've been told to look at event function, but I know too little with VBA.
This may need modified to fit your needs, but maybe a solution like this using the Worksheet_Change event.
Worksheet Change portion:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo SafeExit:
Application.EnableEvents = False
If Target.Cells.Count = 1 Then '
If Not Intersect(Target, Me.Columns("A")) Is Nothing Then 'change as needed
Target.Value = DateFromDay(Me.Name, Target.Value)
End If
End If
SafeExit:
Application.EnableEvents = True
End Sub
Main Function
Public Function DateFromDay(monthName As String, dayNum As Integer) As Date
On Error Resume Next
DateFromDay = DateValue(dayNum & " " & monthName & " " & Year(Now()))
End Function
You might consider the Workbook_SheetChange event as well to add this functionality to multiple sheets.
I apologise for how trivial this must be for VBA developers, but I have done some digging and cannot fathom why the following code, when assigned to a cell and executed, results in #VALUE!
Function foo()
Range("A1:B3").Value = 10
End Function
The excel sheet:
I initially tried
ActiveSheet.Range("A1").Value = "abc"
but that didn't work either. What very simple thing am I doing wrong here?
Also, why, when I try to re-execute the function (using F2 and then Enter), does excel resubmit other functions that are in the same worksheet? This is truly maddening. I have hit F2 and Enter, so why would Excel think that I want to resubmit all other functions, and how can this be prevented?
Thanks very much.
Edit: You tried to use UDF for changing some fields and consistent about the use of some kind of event modification instead of firing your code from a button in your comments with #Mathieu Guindon. Since UDF fire the code only when some cells are recalculated, it is assumed that your requirement is to fire the code when some cells in the sheet get changed either manually or through some formula. The solutions offered below run the code when value of cell F1 change. You may please modify it according to your need.
Old Post: It is not a clean way but may be a called dirty workaround idea. Supposing you want to any change in cell F1 value to execute the code, may try
Public F1Val As Variant
Private Sub Worksheet_Activate()
F1Val = Range("F1").Value
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If F1Val <> Range("F1").Value Then
Range("A1:B3").Value = 10
F1Val = Range("F1").Value
End If
End Sub
Caution:Certainly it will backfire if cell F1 is linked with formula with the cells getting changed.
Alternately if only manual change of cell F1 is suffice for code to execute then may simply try
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F1")) Is Nothing Then
Range("A1:B3").Value = 10
End If
End Sub
I am currently working with an excel sheet where I have grouped row 1-17 and have written a cell value in cell B18. I am wondering if there is a way to change the value in B18 when I click on the +/- sign when expanding/collapsing the rows.
For example: I want the cell value in B18 to be "Yes" when I click on the plus sign, and the value to be "No" when I click on the minus sign. Is there any way to do this?
Kinds regards,
Sandra
Hello and welcome to Stack Overflow!
In general, you should always provide some proof (code) of your previous attempts, not only it helps us to understand better what you're trying to achieve, but also because of core principle behind this website is to help people with their code, not to do the coding for them!
Either way, I'll go out of my way and make an exception, given this is your first question and what you're trying to achieve is fairly easy to do.
Though my answers depends on what exactly you're trying to achieve though as it's not clear from your intial question.
If all the rows (1:17) are hidden
Private Sub check_hidden_area()
If Rows("1:17").EntireRow.Hidden = True Then
Range("B18") = True
Else
Range("B18") = False
End If
End Sub
If at least 1 row in (1:17) is hidden:
Private Sub check_hidden_area()
Range("B18") = False
For i = 1 To 17
If Rows(i).EntireRow.Hidden = True Then
Range("B18") = True
Exit For
End If
Next i
End Sub
PS/Note: The procedures listed do work, but as of now they don't auto-trigger (start) unless you launch them manually. Unfortunately it is impossible to trigger the code on the "+/-" buttons.
Closest thing you can get to this being correct is to fire the macro on every worksheet change, this will however clog down the speed of your program and hog your CPU/Memory, especially if working with bigger data ranges
Private Sub Worksheet_Change (ByVal Target as Range)
'...
Call check_hidden_area
End Sub
Alternatively just create a button (or something..) and call the procedure on _Click trigger, eg.
Private Sub CommandButton1_Click
Call check_hidden_area
End Sub
I want to be able to run macros based on the outcome of the cell, for example.
If A1 is 1111100 then run X macro If its 1000000 then run this macro etc. I have had a look at "Case Select" but my lack of knowledge in this matter makes me thing that might not be what I want.
Any ideas? :/
Thank you in advanced.
JB
you can combine the two types, and yes, a Case Select is the easiest to read and maintain.
Here's example code that runs different routines depending on what is in A1:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("A1"), Target) Is Nothing Then
Application.EnableEvents = False
Select Case Target.Value
Case "A"
FunctionWhenA
Case 1
ThasIsAnotherFunction
End Select
Application.EnableEvents = True
End If
End Sub
note that I also disable/enable events so this isn't triggered every time a cell is changed
There are two main types of Excel macros
1- Those that are written to perform actions, change data, etc.
2- And those that are written to perform calculations and return values to certain cells
(used as customized formulas that are not built in to excel)
The first type can only be triggered to start execution by clicking a button on a form, invoking the Macros window within Excel and selecting the name of the macro to be run
The second type can be run as soon as a value of a certain cell changes (that cell must be an input for the said macro function to work with, calculate and return a certain output), and thus the returned value will be stored on another cell.
In the second type, Excel will ignore any code that tries to modify the content of other cells, perform actions on the worksheet, workbook, or any other action that is not limited to the cell contanining the formula for the custom macro.
If you intend to run a macro of the first type, and want it to be executed right after a certain value changes, then that is not possible.
If you want to write a macro of the second type, then that is possible but code will only be limited to a single cell only.
Yes would need to loop through them.
You could replace the "cas" subs in following with your implementation of VBA for that case.
Function Strange(myVal)
Select Case myVal
Case 1
Cas1
Case 2
Cas2
Case 3
Cas3
End Select
End Function
Sub Cas1()
MsgBox ("hi")
End Sub
Sub Cas2()
MsgBox ("ha")
End Sub
Sub Cas3()
MsgBox ("ho")
End Sub
Sub LoopThem()
Do While ActiveCell.Value <> ""
Strange (ActiveCell.Value)
ActiveCell.Offset(1, 0).Activate
Loop
End Sub
So cell A1 to A3 with values 1,2,3 would consecutively pop up msgboxes "hi" "ha" "ho".
Fixed it.
Done this via using Intergers to stop when I have no further cells with data to stop the macro, and detect on many '1's are within the code and copy the data as neededs using "For" commands.