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.
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 am working on a spreadsheet to copy a users data from the previous day, then delete any numerical values but keep cells with "NA". What I want is for users to not be able to change/delete the cells that still have "NA" in them. I found some code that used OFFSET to move down one cell if a certain cell was selected (based on the row and column) but I haven't been able to figure out how to use the OFFSET to move down one cell if the current cell contains "NA". (https://www.extendoffice.com/documents/excel/3820-excel-lock-cell-without-protecting-sheet.html) This worksheet is already locked with a Quality-set password, so I can't do anything to unlock the spreadsheet, then select the "NA" cells to be locked, then relock the spreadsheet, thus looking for a creative way to keep the cells from being selected or changed. Also, the code would need to run all the time, not just when a macro was selected to run. Any ideas?
If it's possible for the user to open the book without macros enabled, then I'm not sure what you're asking is possible.
If you can assume macros are enabled though, you could use events to either prevent the user selecting the cell (similar to the OFFSET you mention) or you could track changes manually onto a hidden tab in order to note changes and deal with them as you see fit. There are many ways you can achieve the latter, just search "VBA tracking changes to a sheet" etc.
This is how you'd use the OFFSET method:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells(1, 1).Text = "NA" Then
Beep
Cells(Target.Row, Target.Column).Offset(0, 1).Select
End If
End Sub
Keep in mind though, this is a very simplistic method. It won't prevent users selecting multiple cells (a range) and deleting the contents. Nor will it prevent values being pasted to range that includes the 'NA'.
UPDATE:
The following is an improved version that will at least prevent users from selecting multiple cells (for pasting into or deleting) if one of the cells contains "NA".
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim testarea As Range
Set testarea = Intersect(UsedRange, Target.Cells)
If Not (testarea Is Nothing) Then
Application.EnableEvents = False
For Each cell_to_check In Intersect(UsedRange, Target.Cells)
If cell_to_check.Text = "NA" Then
Beep
Cells(cell_to_check.Row, cell_to_check.Column).Offset(0, 1).Select
Do Until Selection.Text <> "NA"
Selection.Offset(0, 1).Select
Loop
Exit For
End If
Next
Application.EnableEvents = True
End If
End Sub
This is still slightly flawed however, as it is still possible to drag-fill cells from other areas over a cell containing "NA".
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 have some data validation drop down lists in excel, I can tab through all the lists but I have to press alt + down arrow to show the list, Is their a way it can be automatically shown as soon as I focus on the tab.
So on focus of the drop down list, I would like the list to appear So that I can select it with the arrow down key and hit enter to select it.
Any other helpful tips for drop down lists and VBA would be great!
edit: still using VBA send keys.
On the sheet where the data validation cell resides (assumed it is cells A1:C1 on Sheet1), put in the following code in the Microsoft Excel Sheet1 Module (the module that holds the VBA code that is related to the first sheet)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo Err1:
If Target = Range("A1") Then
Application.SendKeys ("%{UP}")
End If
If Target = Range("B1") Then
Application.SendKeys ("%{UP}")
End If
If Target = Range("C1") Then
Application.SendKeys ("%{UP}")
End If
Err1:
'do nothing
End Sub
I found this helpful but would like to pass on a couple of observations.
Using
If Target.Cells.Count = 1 Then
If Target.Validation.InCellDropdown = True Then
in the event will apply this to all validation drop lists on the sheet rather than listing the individual cells. You need the first if to avoid an error caused by selecting multiple cells.
Beware of send keys being called twice in a row. It turns your num lock off and I had to add an API call to turn it back on again.
I hope this helps others