I am new to VBA and am quite stuck at using Application Enable.Events function. I tried using the Application Enable.Events function to understand it better but the code that I have generated is not producing the results that I am expecting. So far my code is as follows -
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Application.EnableEvents = False
ThisWorkbook.Save
Application.EnableEvents = True
End Sub
Because Application.EnableEvents is being set to false, nothing happens if I double click on the cells in Excel. My understanding is that double clicking any cells will not impact any code between line 2 and 4. Please correct me if my understanding is wrong.
However, if I comment out the Application.EnableEvent as follows ...
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'Application.EnableEvents = False
ThisWorkbook.Save
'Application.EnableEvents = True
End Sub
My expectation is that this would allow the workbook to save itself every time a cell is being double clicked on. However, that is not the case. If I type "? Application.EnableEvents" inside the immediate window, it would give me false.
I am suspecting that I am missing a small step to update the vba code. It would be awesome to use simple words for any explanations as I am fairly new to coding and vba.
Thank you everyone!
Related
I have an Excel file that are used by end users, where, in a specific range of cells, if a change is made, a change event macro is triggered.
What I do with this macro is to check if the last action is any type of pasting.
What I need is to, somehow, get in a variable the content the user has copied (clipboard?) and then execute a function or procedure which checks the validy of the data. If it's correct, it will paste the values mantaining the conditional format, and if wrong it will undo the operation and disable the events.
So far, I think I am close to have everything but I am missing the knowledge to get in VBA the clipboard content in a variable.
I would appreciate general feedback as well.
PD: I have stated range(B:B) to keep it simple, in reality I will have a function for each column because the validation changes based (but that's on me,I just need to have 1 correct in order to replicate the logic).
Private Sub Worksheet_Change(ByVal Target As Range)
lastAction = Application.CommandBars("Standard").FindControl(ID:=128).List(1)
If Left(lastAction, 5) = "Paste" Then
If Not Application.Intersect(Target, Range("B:B")) Is Nothing Then
validation (Application.Intersect(Target, Range("B:B")))
End If
Else
End If
End Sub
Function validation(cell) As Boolean
Dim check As Boolean
check = Application.WorksheetFunction.VLookup(cell, MDM.Range("AK2:AK86"), 1, False)
If check = True Then
ActiveSheets.PasteSpecial Paste:=xlPasteAllMergingConditionalFormats
Application.CutCopyMode = False
Else
With Application
.EnableEvents = False
.Undo
End With
Application.EnableEvents = True
End If
End Function
I need to do this validation because if the user paste the value from another excel, it will remove both the conditional formatting and the data validation for that column.
I've used the clsClipboard class described at the following link
http://www.la-solutions.co.uk/content/CONNECT/MVBA/MVBA-Clipboard.htm
Copy the VBA class module code to a file named clsClipboard.cls, then import new Class module into your project.
Usage:
Sub test()
Dim CB As New clsClipboard
Dim myVar As String
CB.SetText "this is a test"
myVar = CB.GetText()
Debug.Print myVar
Set CB = Nothing
End Sub
I've created a drop down menu through data validation for workbook navigation. The following is a snippet of code I have for the drop down box to change worksheets in the workbook:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then _
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets("Imported Data").Visible = False
End Sub
The code is meant to hide all other worksheets that are accessible by the drop down list besides the one selected. I have about 10 tabs and this code has worked perfectly to achieve the basic goal of navigation. However, some pages have formulas and when you update data in the cells meant for calculations the workbook jumps to a random worksheet in the workbook that is not at all referenced in this sub.
Is there some way to have my worksheets not try to do anything with this sub unless the dropdown menu itself is changed?
Bonus (less important) Question: is there a way to make the drop box default to (blank) unless the menu itself is accessed?
Then _
The space followed by an underscore _ means that the current statement isn't finished yet but continues on the next line. Right now the last 3 lines will run whenever there is a change in the worksheet. Put the entire code in If-Endif.
Also avoid unnecessary use of On Error Resume Next. Use proper error handling.
You need to make the sheet visible before you activate it and not vice versa.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets("Imported Data").Visible = False
End If
Letscontinue:
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
is there a way to make the drop box default to (blank) unless the menu itself is accessed?
If you have created it with Data Valdation then insert a blank value in the list.
I am trying to activate a macro by clicking in a cell.
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("B37")) Is Nothing Then
Worksheets("DaysEditor").Activate
Sheets("DaysEditor").Columns("C:LY").Hidden = False
Sheets("DaysEditor").Columns("C:EX").Hidden = True
Sheets("DaysEditor").Range("A1").Select
End If
End If
End Sub
This code works on a cell that doesn't have a formula but will not work on cells with a formula in them.
A few minor tweaks I would change with your code. Firstly, if you are going to make multiple calls to a worksheet, I suggest that you either make a variable of it or use it within a With <obj> statement.
Worksheets() is essentially a function. Every time you use it it has to get the function's "value" - hence not the most efficient way of doing things.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address = "$B$37:$C$37" Then
With Worksheets("DaysEditor")
.Columns("C:LY").Hidden = False
.Columns("C:EX").Hidden = True
.Activate
.Range("A1").Select
End With
End If
End Sub
Generally I advise against using the Activate method. But since you appear to actually want to be on the worksheet when the code runs then it's not a big deal here. Just remember that Activate is not necessary for the remainder of your code to function.
One last tweak is that I moved your Activate method after you hide/unhide the columns. Probably not a big deal either, but no need to watch the screen redraw unnecessarily.
Thanks to #K.Davis he helped me figure out that the problem was the that cell I was attaching this to was a merged cell and that was the problem. I changed the Selection.Count = 1 to Selection.Count = 2 and the code works perfectly!
I am running a macro that opens a file referencing the one I am working in, pastes the relevant items as values into a separate sheet and makes a workbook out of that sheet.
The reason why I am doing this is because there are several thousand countifs, averageifs, and processor-intensive ilk.
The program runs from start to finish, just fine. The issue is that only a few of the items are calculated before the copy/paste operation and so I get a lot of #VALUE errors on the copy of the sheet with the formulas--even though the formulas are calculating correctly on further inspection.
I suspect the correct course of action is to delay the run until the sheet finishes calculating. Any and all help would be appreciated.
EDIT: I've tried all manner of application.calculations and nothing seems to be working. The links and items calculate normally if I open manually and let the processor do its thing. The only items that calculate are the ones that contain "COUNTA" somewhere in it. Is it possible that the application calculation methods don't work with Countifs and the like?
Shouldn't be that hard to do - the Worksheet object has a Calculate property that fires after it calculates. You can add a custom property to the worksheet that exposes a flag that you set after it is done calculating. In the worksheet code that has the time consuming calculation...
Option Explicit
Private can_copy As Boolean
Public Property Get CopyOK()
CopyOK = can_copy
End Property
Private Sub Worksheet_Calculate()
can_copy = True
End Sub
Private Sub Worksheet_Activate()
can_copy = False
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
can_copy = False
End Sub
'For volitile functions.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
can_copy = False
End Sub
...and in the calling code:
Dim book As Workbook
Set book = Application.Workbooks.Open("C:\foobar.xlsm")
Do While Not book.Worksheets("Sheet1").CopyOK
DoEvents
Loop
'Do your thing...
Note that I likely missed some events that would trigger a recalculation, but this should cover the scenario of just opening it.
So, I found a means for this to work:
Do Until Application.CalculationState = xlDone
Application.Calculate
While Application.CalculationState <> xlDone
MsgBox Application.CalculationState
DoEvents
Wend
Loop
It was a solution I sort of applied from Siddharth Rout : Wait until Application.Calculate has finished
Thank you everyone for your help!
I'm using Excel VBA and have a worksheet_change event like so:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target = Range("rel_type") Then
--some code
End If
End Sub
That code works great when I make a change to the named range "rel_type". However if I insert a row anywhere else in the spreadsheet, I get run-time error 13 - type mismatch on the first line of that Sub. Does anybody know a workaround? I'm not that familiar with the Worksheet_Change event and can't seem to find good documentation (or at least documentation that references why this error would occur). Thanks.
Is this what you are trying?
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not Intersect(Target, Range("rel_type")) Is Nothing Then
Application.EnableEvents = False
'--some code
End If
LetsContinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume LetsContinue
End Sub
FOLLOWUP
Yes, that's exactly what I needed! Thanks! It worked like a charm. I was not familiar with Intersect or the EnableEvents option, so I learned a lot here--I appreciate it. – rryanp 16 secs ago
INTERSECT: The Intersect Method will return a Range Object that represents the intersection of two, or more, ranges.
See this link
Topic: Intersect Method [Excel 2003 VBA Language Reference]
Link: Intersect - MSDN
ENABLEEVENTS: You have to use the EnableEvents property to prevent any probable endless loops which the VBA code might initiate. When you set this property to False, VBA will not raise any events and the Worksheet_Change event will run only once. Also you should always be sure to set EnableEvents property back to True to enable events to be called normally the next time.
HTH
Sid