I have an Excel that functions as a sort of decision tool, where questions are being asked and one needs to navigate through the workbook with buttons.
I have made a macro to function as a "go back" button, which activates the previously active sheet and hides the one you are on now. It works, but it keeps showing the navigation buttons from the first sheet. The text from the correct sheet does appear. If I go to another sheet and back, the data appears correct.
Is there a way to refresh the sheet so the correct information shows up, or is this a problem to do with the buttons and the macros behind them?
The macro I have used for the go back button:
(in workbook):
Sub Workbook_SheetDeactivate(ByVal sh As Object)
LastSheet = sh.Name
End Sub
(in module):
Global LastSheet As String
Sub goback()
Sheets(LastSheet).Visible = True
Sheets(LastSheet).Activate
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
With ws
If .Name <> "BM" Then
.Range("H9:R31").Font.Color = RGB(255, 255, 255)
End If
End With
Next ws
Sheets(LastSheet).Visible = False
End Sub
Even though there are no calculations, I did try including ActiveSheet.EnableCalculation but that did nothing.
Any help would be greatly appreciated.
Maybe I am reading this incorrectly but is the issue that the buttons are not dissapearing? if so this may help:
Sub hidebutton()
Dim sh As Shape
For Each sh In Sheet1.Shapes
If sh.Name = "Button 1" Then
sh.Visible = True
End If
Next
End Sub
Related
I have the code below attached to a button on a userform in Excel. There are other parts of the code that perform advanced filtering and I use the code below to clear the filter before re-applying the filter, to make it run much faster. It works just fine as long as wsDataSchool is the active sheet or some other sheet is active. However, if there is a CHART sheet active before I click the button then I get an error saying ShowAllData failed. This is super weird and I can't find anything about it. Any ideas as to why this is happening or how to fix it?
If wsDataSchool.FilterMode = True Then
wsDataSchool.ShowAllData
End If
Add a test maybe then. This tests if current sheet is a chart sheet and if so then activates the target sheet by codename.
Option Explicit
Public Sub test()
If wsDataSchool.FilterMode Then
Select Case ActiveSheet.Type
Case -4167
wsDataSchool.ShowAllData
Case Else
wsDataSchool.Activate
wsDataSchool.ShowAllData
End Select
End If
End Sub
Although ugly, if you then need to return to a Chart sheet if in a chart sheet you could as follows:
Public Sub test1()
Application.ScreenUpdating = True
Dim ws As Chart
If wsDataSchool.FilterMode Then
Select Case ActiveSheet.Type
Case -4167
wsDataSchool.ShowAllData
Case Else
Set ws = ActiveSheet
wsDataSchool.Activate
wsDataSchool.ShowAllData
ws.Activate
End Select
End If
Application.ScreenUpdating = False
End Sub
I have a userform which has multiple RefEdit controls. I need the user to select ranges from multiple sheets and the userform has to be complete before the rest of the code can run.
Issue: The activesheet is "Sheet1" when the userform is initiated. Each time I select a range on "Sheet2" and click into the next RefEdit the visible Excel sheet returns to "Sheet1". I'd like the sheet to remain on "Sheet2", since clicking between the sheets significantly increases the time it takes to select the data.
Because I need the userform to be completed before continuing with my code, using "vbModeless" doesn't appear to work.
I've tried to step through the userform events which appeared to be relevant but none were activated when I entered the RefEdit, selected the data, or left the RefEdit.
Thanks in advance for any help!
Edit: Using some input from the responses and doing some more research I think I've figured out the problem and a work around.
RefEdit events such as Change or Exit (I tried all of them I think) don't appear to trigger when a change occurs in the control. So I couldn't write code to manipulate the activesheet when I changed the control. A workaround found here: http://peltiertech.com/refedit-control-alternative/ uses a textbox and inputbox to simulate a RefEdit control and will actually trigger when changes are made! Code is below. To add other "RefEdit" controls you should repeat the code in the Userform_Initialize event for each control, then add another TextBox1_DropButtonClick and update TextBox1 to the name of the new control. In use when the control updates the workbook jumps to the previous activesheet and then returns the desired activesheet. Not as smooth as I'd like but much better than it was.
Code:
Private Sub CancelButton_Click()
Unload Me
End
End Sub
Private Sub OKButton_Click()
UserForm1.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
End
End Sub
Private Sub UserForm_Initialize()
Me.TextBox1.DropButtonStyle = fmDropButtonStyleReduce
Me.TextBox1.ShowDropButtonWhen = fmShowDropButtonWhenAlways
End Sub
Private Sub TextBox1_DropButtonClick()
Dim ASheet As String ' Active sheet
Me.Hide
'Use input box to allow user to select a range
On Error Resume Next
Me.TextBox1.Value = Application.InputBox("Select the range containing your data", _
"Select Chart Data", Me.TextBox1.Text, Me.Left + 2, _
Me.Top - 86, , , 0)
On Error GoTo 0
'Check if there is a sheet name - if the range selected is on the activesheet the output of the inputbox doesn't have a sheet name.
If InStr(1, Me.TextBox1.Value, "!", vbTextCompare) > 0 Then ' there is a sheet name
ASheet = Replace(Split(Me.TextBox1.Value, "!")(0), "=", "") ' extract sheet name
Else ' there is no sheet name
Me.TextBox1.Value = "=" & ActiveSheet.Name & "!" & Replace(Me.TextBox1.Value, "=", "") ' add active sheet name to inputbox output
ASheet = ActiveSheet.Name
End If
Worksheets(ASheet).Activate ' set the active sheet
Me.Show
End Sub
Have you tried something as simple as:
Sheets("Sheet2").Select
somewhere in the beginning of your form code ?
Since you haven't posted your code, it's hard to provide a good answer.
Hope this helps a little :)
This form module worked for me.
Private Sub CommandButton1_Click() 'Cancel Button
Unload Me
End Sub
Private Sub CommandButton2_Click() 'GO Button
Dim newSheet As Worksheet
abc = Split(RefEdit1.Value, "!")
cbn = abc(0)
Unload Me
Set newSheet = Worksheets(abc(0))
newSheet.Activate
End Sub
New here and I just started to teach myself coding. I have a workbook that has roughly 14 tabs/worksheets for employees to enter their hours worked per day. On a "Summary" tab and want to create a macro button for each employee to click on to view his/her tab. These employee tabs are hidden and all I want the action to do is unhide and then hide when the employee clicks their button.
Unfortunately, I receive an Ambiguous Error message and I created a module per employee. I assume I need to somehow "stack" code, but again am totally new to coding. Below is a sample of my code
Private Sub ShowHideWorksheets()
Sheets("EMPLOYEE 1").Visible = Not Sheets("EMPLOYEE 1").Visible
End Sub
you need to correctly put it behind a button. When you insert the button into the page, right click it and assign macro. The code would look like
Sub Button1_Click()
Sheets("EMPLOYEE 1").Visible = Not Sheets("EMPLOYEE 1").Visible
End Sub
Basically you wish to toggle visibility for a worksheet.
Assuming that you know which Sheet is going to be triggered, it is something like this:
Public Sub TriggerSheetVisibility(worksheetname as string)
Dim ws as WorkSheet
On Error Resume Next 'To avoid subscript out of range error if a worksheetname is passed that doesn't exit
Set ws = Worksheets(worksheetname)
On Error Goto 0
If Not ws Is Nothing Then 'Only when the worksheet exists, we can execute the rest of this sub:
If ws.Visible = True then
ws.Visible = False
Else
ws.Visible = True
End If
End If
End Sub
Also see https://msdn.microsoft.com/en-us/library/office/ff197786.aspx
This is also an acceptable approach? Prolly long winded though
Private Sub CommandButton1_Click()
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Sheets
If sheet.Name <> CommandButton1.Caption Then
sheet.Visible = False
End If
If sheet.Name = CommandButton1.Caption Then
sheet.Visible = True
End If
Next sheet
End Sub
However I like this better due to the fact you only need one button
Private Sub CommandButton1_Click()
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Sheets
If sheet.Name <> Environ("USERNAME") Then
sheet.Visible = False
End If
If sheet.Name = Environ("USERNAME") Then
sheet.Visible = True
End If
Next sheet
End Sub
If you change Private to Public it should work. I'm presuming you're just creating macros at this point to get base functionality to work. You can hide (as the code you've posted) and unhide like this:
' This first macro actually just makes the worksheet visible and then
' invisible each time you execute it - so I'm not sure if
' that's what you're after
Public Sub ShowHideWorksheets()
Sheets("EMPLOYEE 1").Visible = Not Sheets("EMPLOYEE 1").Visible
End Sub
' If it's invisible you can do this.
Public Sub ShowWorksheets()
Sheets("EMPLOYEE 1").Visible = True
End Sub
' Basically that should give you an idea of how to proceed.
I have a file that someone made and I was tasked with simply adding an autoupdater function that updates the cell next to the dropdown menu.
The way the dropdown menu is created is by going to data validation and selecting list and make list in cell. The values are read from elsewhere.
Now, what I tried was to loop over all shapes like this:
Dim dd As DropDown
Dim i As Integer
Debug.Print Sheet1.DropDowns.Count
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Dim s As Shape
For Each s In ws.Shapes
Debug.Print CStr(s.Type)
Next
Next
End Sub
This prints the following:4 is a comment, 8 is a control form
444444444444444444444444444
8
So even though I have many drop down menus none come out when I loop over them.
I wanted to make it so that anyone can add a dropdown box and my code would attach an OnAction Sub that fills in the cell next to the dropdown box so the user can add as many boxes they want, but they have to only remember to keep the cell next to it, to the right for example, empty as it will be overridden.
Dim sh As Shape
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
For Each sh In ws.Shapes
If sh.Type = msoFormControl Then
If sh.FormControlType = xlListBox Then
sh.OLEFormat.Object.OnAction = "UpdateLBCell"
End If
End If
Next
Next
The original code above causes an object error on the innermost line.
Am I just stupid or is it not possible to loop over these dropdown boxes?
If it is impossible, can I make some other dropdown single select boxes that fit inside a cell? Combobox I tried, but they lie on top and dont match.
Any insight in alternative ways to do this is very appreciated as well.
I put a list validation on a few cells, then ran this code
Sub Test()
Dim dd As DropDown
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Dim s As Shape
For Each s In ws.Shapes
Debug.Print CStr(s.Type), s.Top, s.Left
s.Visible = msoCTrue '<<<<
Next
Next
End Sub
Before and after (yellow cells have data validation):
So it seems as though if you have a "list" data validation set up, Excel manages a single (normally invisible and empty) drop-down which is typically positioned at the current active cell. It's only made visible when that's also one of the cells with validation set up.
EDIT: here's an example of how you could handle updates to cells with drop-down DV lists in a generic way -
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Range
On Error GoTo haveError
Application.EnableEvents = False
For Each c In Target.Cells
If HasDVList(c) Then
c.Offset(0, 1) = Now
End If
Next c
haveError:
Application.EnableEvents = True
End Sub
'does a cell have DV list?
Function HasDVList(rng As Range)
Dim v
On Error Resume Next
v = rng.Cells(1).Validation.Type
On Error GoTo 0
HasDVList = (v = 3)
End Function
The Shape should be Visible, whether the cell is "clicked-on" or not. I put a single DV dropdown on a sheet and ran:
Sub ShapeLister()
Dim s As Shape
For Each s In ActiveSheet.Shapes
MsgBox s.Type & vbCrLf & s.Name
Next s
End Sub
and got:
Try this on a fresh worksheet and tell us what you see.
I have a workbook with about 50 sheets to be refreshed in a certain order (to avoid #rfr errors, since the sheets build off of one another).
The refresh is done via the EPM add in for Excel. I have activated the FPMXLclient functions and have attempted to write some code. I am very inexperienced with coding and logic. In the workbook the macro needs to start at the last tab, wait for the sheet to refresh, then move on to the next tab (and so on...). Below is an example of some of the VBA code I have written:
Dim refreshList
refreshList = Array("BS Analytic", "Balance Sheet")
'There are more than just the 2 in the array (~50)
Sub test_loop()
Dim I
For I = LBound(refreshList) To UBound(refreshList)
MsgBox refreshList(I)
Next I
End Sub
'Vba to refresh data
Dim client As New EPMAddInAutomation
Sub Refresh_Click()
client.Refresh
End Sub
Sub AFTER_REFRESH()
MsgBox "done"
End Sub
Other info: This involves BPC and SAP too.
Assuming that your addin refreshes the active sheet, something like this in your loop might work:
Dim Sh As Worksheet
Set Sh = WorkSheets(RefreshList(I))
Sh.Activate
Client.Refresh
Why not have each sheet number in the array refreshList and then use For each I in refreshList. That will then propagate the refreshList in the order for each update. If it is also moving from the last sheet backwards you could always do the following:
Sub Refresh_Click
Dim refreshList() As Integer
reDim refreshList(50)
for i = 0 to 49
refreshList(i) = 50 - i
next
For each I in refreshList
Sheets(I).EnableCalculation = false
Sheets(I).EnableCalculation = true
Next
MsgBox "Done"
End Sub