I cannot figure out why Application.CommandBars("Standard").Controls("&Undo") is disabled in a particular sheet.
I also tried to explicitely enable it with:
Application.CommandBars("Standard").Controls("&Undo").Enabled = True
But still no results:
Dim lastAction As String
If Application.CommandBars("Standard").Controls("&Undo").Enabled = True Then
MsgBox "It works"
lastAction = Application.CommandBars("Standard").Controls("&Undo").List(1)
If Left(lastAction, 5) = "Paste" Then
Application.ScreenUpdating = False
Application.EnableEvents = False
Call MasterPageFixer
Application.ScreenUpdating = True
Application.EnableEvents = True
Else
Exit Sub
End If
End If
Any idea about how to programmatically make sure that this sheet could keep the possibility of accessing the undo list?
The Application.CommandBars("Standard").Controls("&Undo").Enabled refers to the standard arrows for "Undo" in Excel. These are not per sheet, but per application, as the line says. They arrows are enabled/disabled if there is a possibility to use them. Thus, the "disabled" stands only if there is nothing to be "undone". E.g., check the following steps:
Open a new Excel workbook and run this in the Immediate window. You will see False:
This is because there is nothing to be "undone":
Then, if you write some text in the excel cells and run the code from the immediate window again, you will see True. Additionally, the arrow will look like this:
Related
So I have looked at various questions similar to this but they don't seem to work or are unanswered:
Run macro when slicer change
how to run a macro while clicking on a value in slicer in excel vba
My Question:
When i click one of the options in the slicer i want it to automatically run one of the macros but it doesn't work, when i run it manually it works, but clicking on the slicer's option doesn't
Sub updateFoodSlicer()
With ActiveWorkbook.SlicerCaches("Slicker_TABLE_StackChart")
.SlicerItems("food").Selected = True
.SlicerItems("fruit").Selected = False
.SlicerItems("drink").Selected = False
End With
With ActiveSheet.PivotTables(Foods_StackChart").PivotFields("FOODS")
.PivotItems(">0").Visible = False
.PivotItems(">2").Visible = False
.PivotItems(">4").Visible = False
.PivotItems(">6").Visible = True
.PivotItems(">8").Visible = True
End With
End Sub
Thats my macro, when i click run it works, but i want it so that when i click the option "food" from the slicer i want it to make columns >6, and >8 visible only
By checking out those above stackoverflow question I realized you need an event so I added that, but still it doesn't work:
Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)
If ActiveWorkbook.SlicerCaches("Slicker_TABLE_StackChart").SlicerItems("food").Selected = True Then
Call updateFoodSlicer()
End If
End Sub
----------------------------
Sub updateFoodSlicer()
With ActiveWorkbook.SlicerCaches("Slicker_TABLE_StackChart")
.SlicerItems("food").Selected = True
.SlicerItems("fruit").Selected = False
.SlicerItems("drink").Selected = False
End With
With ActiveSheet.PivotTables(Foods_StackChart").PivotFields("FOODS")
.PivotItems(">0").Visible = False
.PivotItems(">2").Visible = False
.PivotItems(">4").Visible = False
.PivotItems(">6").Visible = True
.PivotItems(">8").Visible = True
End With
End Sub
EDIT:
Follow up, so I added into the Sheets tab so the macro would run, but now I get the error: method visible of object pivotitem failed
I have tried various solution from online, yet none seem to work
My macro generates a series of reports that are 60 columns wide. I want users to be able to review the reports on screen before printing them or going on to another segment of the macro.
it there a way to set a scrollarea, have user review it, and then have the respond to a message box to continue the routine?
I tried this:
Sub reviewdata()
' Application.ScreenUpdating = False
Worksheets("Fin. Stmts").ScrollArea = ""
Application.Goto Reference:="monthlydata"
ActiveCell.Offset(2, 1).Select
ActiveWindow.FreezePanes = True
Worksheets("data. Stmts").ScrollArea = "monthlydata"
If MsgBox("End Review", vbOKOnly) = vbOK Then
End If
ActiveWindow.FreezePanes = False
Worksheets("data. Stmts").ScrollArea = ""
End Sub
the problem is that once the if, then statement is executed the user can not move around the worksheet since the routine needs a response to continue.
any insights are most appreciated.
thanks.
You can Use a Dummy Variable:
Dim dummy As Range
Set dummy = Application.InputBox("Scroll and Check. After That Select Ok!", "This is Specially created so that you can", Default:="A1", Type:=8)
Input Box that Takes in Range Allows you to Scroll in Background. Keep hitting Ok in and nothing will change, code will run as it is running at the moment.
This is a little clumsy but it sort of gets what you want. Instead of using a MsgBox use and InputBox as a range, which will allow the user to click around and scroll, as you describe. Whenever they hit okay/cancel, the macro will continue.
So probably replace your MsgBox line of code with....
Dim boom As Variant
boom = Application.InputBox("When you're done hit ""Cancel""... (""OK"" might lead to problems...)", _
"Scroll around and look at stuff", _
, , , , , 8)
I would recommend doing two macros instead, but this probably does what you need.
You can show that message in a small userform and call that userform in modeless state as shown below.
UserForm1.Show vbModeless
This way you will be able to navigate in the sheet with that message still showing.
You can also put the rest of the code in the button click event as shown below.
Option Explicit
Private Sub CommandButton1_Click()
ActiveWindow.FreezePanes = False
Worksheets("data. Stmts").ScrollArea = ""
Unload Me
End Sub
I'm new to VBA and have been trying to write a code that hides and unhides rows based on the input value of a certain cell address. However, it doesn't work and I don't why. I have posted my code below:
Sub Hide()
If Worksheets("IS").Range("B8").Value = "Show All" Then
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
End If
If Worksheets("IS").Range("B8").Value = "Just Revenue" Then
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("28:165").EntireRow.Hidden = True
End If
If Worksheets("IS").Range("B8").Value = "Just Expenses" Then
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("12:27").EntireRow.Hidden = True
Worksheets("IS").Rows("160:165").EntireRow.Hidden = True
End If
If Worksheets("IS").Range("B8").Value = "Just Cogs" Then
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("12:27").EntireRow.Hidden = True
Worksheets("IS").Rows("64:165").EntireRow.Hidden = True
End If
If Worksheets("IS").Range("B8").Value = "Just Totals" Then
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("12:25").EntireRow.Hidden = True
Worksheets("IS").Rows("28:61").EntireRow.Hidden = True
Worksheets("IS").Rows("64:91").EntireRow.Hidden = True
Worksheets("IS").Rows("93:155").EntireRow.Hidden = True
End If
End Sub
Any help with why my code doesn't work or any tips to improve it would be much appreciative.
Rewriting for Worksheet_Change:
In your VBE, paste this code into the code sheet for the "IS" worksheet (double click it in the Project - VBAProject pane. If the Project - VBAProject pane is not visible in your VBE, go to View>>Project Explorer):
Private Sub Worksheet_Change(ByVal Target As Range)
'Ensure that we don't trigger another change event while this code is running
Application.EnableEvents = False
'Check if cell B8 triggered this change:
If Not Intersect(Target, Range("B8")) Is Nothing Then
'B8 changed... which means B8 is "Target" variable
Select Case Target.Value
Case "Show All"
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Case "Just Revenue"
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("28:165").EntireRow.Hidden = True
Case "Just Expenses"
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("12:27").EntireRow.Hidden = True
Worksheets("IS").Rows("160:165").EntireRow.Hidden = True
Case "Just Cogs"
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("12:27").EntireRow.Hidden = True
Worksheets("IS").Rows("64:165").EntireRow.Hidden = True
Case "Just Totals"
Worksheets("IS").Rows("12:165").EntireRow.Hidden = False
Worksheets("IS").Rows("12:25").EntireRow.Hidden = True
Worksheets("IS").Rows("28:61").EntireRow.Hidden = True
Worksheets("IS").Rows("64:91").EntireRow.Hidden = True
Worksheets("IS").Rows("93:155").EntireRow.Hidden = True
End Select
End If
'Turn events back on so this code triggers again
Application.EnableEvents = True
End Sub
There are quite a few events that we can hook VBA to (SelectionChange, DoubleClick, Workbook_Close, etc). In this case we are hooking to Worksheet_Change().
This code gets triggered every time this worksheet experiences a change. The Target variable will hold the range that triggered the event. So we test to see if that Target intersects with Range("B8") which means B8 was changed. Then we perform the code inside the If block.
I switched your If/ElseIf over to a Select/Case just because it makes for cleaner code since we are testing a single condition (the value of B8) over and over again.
In this code we also toggle off the Excel Applications EnableEvents feature. This feature is what allowed this Worksheet_Change() to get triggered in the first place. Often times in the code we make more changes to the worksheet (hiding rows or columns, for instance) which will trigger the application to run Worksheet_Change() again... while it's running Worksheet_Change() already. This can cause code to run superfluously and, often, cause an endless loop that makes excel crash.
This code needs to be pasted on the sheet where you want are wanting to execute the code. You will not need to qualify your ranges with the sheets once the code is there as well.
You can just refer directly to your range without the Worksheets("IS"). as so:
Rows("so and so").EntireRow.Hidden = True
You can also just refer to your TargetRange by variable now like so:
If MyTarget = "Just Revenue" Then
I inserted one of your conditions in the code as an example
Option Explicit
Private Sub worksheet_change(ByVal target As Range)
Dim MyTarget As Range
Set MyTarget = Range("B8")
If Not Intersect(target, MyTarget) Is Nothing Then
Application.EnableEvents = False
'Your CODE HERE
If MyTarget = "Show All" Then
Rows("12:165").EntireRow.Hidden = False
End If
Application.EnableEvents = True
End If
End Sub
I want to disable cell editing (direct typing into cell) but want to update that cell through code without protecting worksheet
Does anyone have any idea?
In the worksheet's code module:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("A1:A10"), Target) Is Nothing Then
Application.EnableEvents = False
Target.ClearContents '// Assuming you want to keep it blank
Application.EnableEvents = True
End If
End Sub
Then in your code whenever you want to change a value, just disable events before hand:
'// Will be deleted
Range("A5").Value = "TEST"
'// Will not be deleted
Application.EnableEvents = False
Range("A5").Value = "TEST AGAIN"
Application.EnableEvents = True
I had a similar issue and found a workaround. For whatever reason I couldn't get my macros to run correctly with the sheets protected so what I did is as a code to Pop up a message box for any cells that I didn't want the user to change. Then I added "Application.DisplayAlerts = False" to the beginning of any codes that needed to modify those cells and reset the alerts back to True at the end of those codes.
In Excel 2010 the method described below, the ScreenUpdating works correctly. But in 2007, it doesnt flip and the worksheet operations are visually being seen.
VBA Usage:
Dim scrup As Boolean: scrup = DisableScreenUpdating(Application.ScreenUpdating)
Method Declaration:
Function DisableScreenUpdating(val As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''
' Disable ScreenUpdating, for seemless operation
If val Then
Application.ScreenUpdating = False
End If
'''''''''''''''''''''''''''''''''''''''''''''''''
DisableScreenUpdating = val
End Function
Question:
What am i missing in 2007 that 2010 is either assuming or is working correctly?
Still tracking down the bug cause it is still happening on 1 version of the file but other two versions it will not. The Versions all have the same code-base but based on various settings change representation to the end-user(s).
NOTE:
Please DO NOT focus on the "Why i am doing this", and more of what situations would cause the ScreenUpdating method to NOT be changed from True to False.
You could try eliminating the conditional and see if the problems is still there. That ways you'd know if it has something to do with conditional or not or 'val'.
Function DisableScreenUpdating() As Boolean
Application.ScreenUpdating = False
DisableScreenUpdating = True
End Function
Assuming this makes your bug go away, I'd then focus on the call....
DisableScreenUpdating(Application.ScreenUpdating)
Perhaps the bug something to do with reading the ScreenUpdating property, followed shortly by write. That's just a guess though.
Also, I'd search your project for any other usage of Application.ScreenUpdating. There may be some other code causing the updating to return to True.
For one thing, is there a function to enable ScreenUpdating? Your code only disables it. Here is your code modified with code that I use:
Dim scrup As Boolean: scrup = DisableScreenUpdating(Not Application.ScreenUpdating)
'Disable ScreenUpdating, for seemless operation
Function DisableScreenUpdating(val As Boolean) As Boolean
With Application
If .ScreenUpdating = val Then 'Gets rid of flashes for changing it to the same
.ScreenUpdating = Not val
End If
'Doesn't matter what happens above, this is based on what Excel would send back
DisableScreenUpdating = Not .ScreenUpdating
End With
End Function
I have seen the bug...yet the statement works, only the VBA-editor doesnt see changes.
However you can see the change by assigning a variable and then read it in the VBA-editor.
>Sub testing()
>Dim i As Long
>
>Application.ScreenUpdating = False
>i = Application.ScreenUpdating
>MsgBox "Assigned to i...real value = " & CBool(i)
>
>Application.ScreenUpdating = True
>i = Application.ScreenUpdating
>MsgBox "Value of Application.ScreenUpdating = " & CBool(i)
>End Sub