I have excel sheet, where I have bunch of data and some excel filter and sort buttons. Is there possibility to detect when sort function was executed and run code after?
I tried worksheet_calculate, but there is issue, that this event is firing not only on sort. Or is here possibility to determine that sort was performed in worksheet_calculate event?
Control the sort rather than have Excel try to detect the sort.Instead of allowing the user to manually perform sorts from the Ribbon, provide a button and have the button macro perform the sort and any associated actions afterwards.
A sort action changes the selection of its filter range. You can capture the sort event quite simply by utilizing the Worksheet_SelectionChange event. You must apply the Application.Intersect method the same way you would for a standard Worksheet_Change event.
The range you are testing against the selection target must be the filter range EXCLUDING the header row.
When you sort one of the columns within the filter range via the header controls, the Target.Value will capture an array including the header row values.
You need two lines of code at this point to help detect the sort action. Please see basic skeleton below:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim filterRangeNoHeaders As Range
Set filterRangeNoHeaders = Range("A2:A11")
If VarType(Target.Value) <> 8204 Then Exit Sub
If Target(1, 1) <> "FirstHeaderTitle" Then Exit Sub
If Not Application.Intersect(filterRangeNoHeaders, Target) _
Is Nothing Then
'Code to execute after sort is detected
End If
End Sub
Related
I have a database which auto refreshes and updates the table from an external source every 15 minutes. I tried the following code which updates the PivotTable every time the source data is edit/added/deleted:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Worksheets("PIVOT TABLE WORKSHEET").PivotTables("PIVOT TABLE NAME").RefreshTable
End Sub
When i manually edit the source data, the PivotTables refresh accordingly. However, when the source data is updated automatically the PivotTables remain unchanged. Is there a way to make the Pivot tables refresh together with the database without the need of a user input?
You'll have better results if you use the Worksheet_Change event instead of the Worksheet_SelectionChange event, so that the procedure runs when data changes, not when you select a cell with the mouse or keyboard.
Worksheet_Change vs. Worksheet_SelectionChange events
Worksheet_SelectionChange fires when the selection changes on a worksheet.
For example, when the user clicks on a cell, or pushes an arrow key.
Worksheet_Change fires when cells on the worksheet are changed, either by the user or by an external link.
Note: Worksheet_Change does **not** occur when cells change during a re-calculation; use theCalculate` event to trap a sheet re-calculation.)
Depending on how the data is laid out in your worksheet(s), you may want to limit the execution of this procedure by checking which cell(s) were changed, which is easiest overall by comparing the event procedure's Target parameter to a specific cell or cell-range, using the Intersect function.
Caution: Beware of infinity!
When using code that changes cells within the area being "watched" by the Worksheet_Change event procedure, you risk entering into an infinite loop, since the change fires the event again, which changes cells again, etc.
(Click image to enlarge.)
There are several ways this could be avoided. This most common is to temporarily disable events with the Application.EnableEvents property while the Change event does what it needs to do. (Don't forget to re-enable events at the end of the procedure... see example below.)
Example:
Here's an untested example using all these points:
Private Sub Worksheet_Change(ByVal Target As Range)
Const cellsToWatch = "A1:D4"
With Worksheets("PIVOT TABLE WORKSHEET")
'exit the procedure if at least part of the changed cells were not within `A1:D4`
If Application.Intersect(.Range(cellsToWatch), Target) Is Nothing Then
'the change wasn't within `cellsToWatch`
Exit Sub
End If
Application.EnableEvents = False 'disable execution of this or other events
'----------Run your code here:--------------
.Calculate
.PivotTables("PIVOT TABLE NAME").RefreshTable
'-------------------------------------------
Application.EnableEvents = True 're-enable events
End With
End Sub
More Information:
MSDN : Worksheet_Change event (Excel)
MSDN : Worksheet_SelectionChange event (Excel)
MSDN : Application.Intersect method (Excel/VBA)
Office Support : Intercept function (Excel/Worksheet)
Stack Overflow : Stop Excel from firing Worksheet_Change before _BeforeSave?
MSDN : Application.EnableEvents property (Excel)
I have a worksheet where in the first three columns (A,B,C) I store data. These values are used in a macro.
I would like to know how it is possible to make this macro run automatically after data is pasted onto these columns. I am almost sure that I will use the Worksheet-Change module, but as for the code I am clueless.
Thanks in advance.
A simple implementation:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1:C" & ThisWorkbook.Worksheets(1).UsedRange.Rows.Count)) Is Nothing Then
'Call your Macro to do stuff
End If
End Sub
Intersect checks if Target is in the range you want to monitor. So if something changes in columns past C, Intersect will return Nothing and your macro won't be called. Just keep in mind that the Worksheet_Change event fires on any change, even double clicking into the cells. If all you are doing in this Worksheet is copy&pasting data and then running your Macro, this should be fine, but if you are manipulating your data further, you might have to look at more sophisticated solutions. Examples include mirroring your Worksheet and comparing it pre/post Worksheet Changed Event. You can read more on this here: Detect whether cell value was actually changed by editing
I've got a code written that categorizes employees along with their qualifications. In order to weed out employees with unwanted qualifications I have applied a filter to each column that titles the category of their qualification.
I've written my VBA code in order that repetitious names and qualifications are made invisible for ease of location. However, I am unable to get the code to run automatically.
Currently the only way I can get the code to run is by setting it to
Private Sub Worksheet_Change(ByVal Target As Range) and then changing the value of an arbitrary cell.
i found what I believe to be the correct solution at:
http://www.ozgrid.com/forum/showthread.php?t=72860
But I cannot make sense of it.
Is there a way to run this code without having to select and deselect a cell after the filter has run?
The key points from my article Trapping a change to a filtered list with VBA
There is more detail and a sample file with the article, the key points are summarised below
A "dummy" WorkSheet is added with a single SUBTOTAL formula in A1 pointing back to the range being filtered on the main sheet.
A Worksheet_Calculate() Event is added to the "dummy" WorkSheet, this Event fires when the SUBTOTAL formula updates when the filter is changed.
The next two setps are needed if it is desired to run the Workbook Calculation as Manual
Add a Workbook_Open Event to set the EnableCalculation property of all sheets other than "Dummy" to False.
Run the Workbook in Calculation mode
The ozgrid code you mentioned tells you that you can put your code in a worksheet_calculate event (in the worksheet module), as long as you have something that will recalculate when you change your autofilter. This something can be a subtotal formula that you can hide in your worksheet, e.g. =subtotal(3,A:A)
Still need to investigate but looks like Chart Calculate event is triggered when Calculation = xlCalculationManual. At least works on my Excel 2007. So the steps are:
create a chart (saying "Chart 1" on Sheet1) which actually uses data from any of your table column
check that it updates its picture when you change the filter
create a new class e.g. clsChartEvents:
Public WithEvents Chart As Chart
Private Sub Chart_Calculate()
Stop
End sub
add this code to some module or class:
Private chartEvents as new ChartEvents 'create a module-scope variable
sub SubscribeToChartEvents
set chartEvents.Chart = Sheet1.ChartObjects("Chart 1").Chart
end sub
execute SubscribeToChartEvents
change a filter and you should appear in Sub Chart_Calculate()
In excel workbook project, how could we detect if the filters on some worksheet are updated?
Make sure that you have a formula (e.g. COUNT) that includes an entire column of the data. In the case of a Table, turn on the Total row.
When the filter is changed, the Excel calculation event will fire because of the formula and you can pick this up by inserting the following code into the sheet.
Private Sub Worksheet_Calculate()
MsgBox "Calculation"
End Sub
Your sheet will need to be designed to only have data, otherwise code will be needed to determine if the calculation event on the sheet did not originate due to a change in filter.
You will need to add code to pick up the filter values. Focus on the Filter class members like Citeria1, Criteria2, Operator, On, etc.
My case was an Excel database. I created a label indicating "number of filtered items" or "number of meeting instances", so that when you filter using dropdown filters this label will update. I didn't find any "filter change" event. I tried the method described above like the following:
Select a cell in your sheet that you are not willing to use
Set the formula of the cell to "=count(B:B)" or "=counta(C:C)" or any formula that depends on the entire column. Make sure that the cell is not in the same column
Set the format type of this auxiliary cell to "custom" and set the format to ";;;" so the cell contents will be invisible
In VBA, use the "worksheet calculate" event to execute your code
Private Sub Worksheet_Calculate()
' The commands and actions you want to execute when filter changes
End Sub
Now, you are done
How can I capture the event in Excel when a user clicks on a cell. I want to be able to use this event to trigger some code to count how many times the user clicks on several different cells in a column.
Check out the Worksheet_SelectionChange event. In that event you could use Intersect() with named ranges to figure out if a specific range were clicked.
Here's some code that might help you get started.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
If Not Intersect(Target, Range("SomeNamedRange")) Is Nothing Then
'Your counting code
End If
End Sub
Use the Worksheet.SelectionChange event to trap this.
Worksheet SelectionChange event would do it. Note that this fires every time user clicks a new cell.