Macro to go to a worksheet [duplicate] - excel

This question already has an answer here:
Excel Find a sheet based on name
(1 answer)
Closed 8 years ago.
I have an excel workbook with a lot of sheet tabs, and to make navigating it easier for user's I've added a macro to bring up an input box so that they can type in the sheet they want to go to.
It works but the problem is that if they type in a sheet name incorrectly it does nothing, the input box goes away, and the user is left on the same sheet they were already on. What I would like it to do is if a user types in a sheet name that doesn't exist for it to bring up a box with a list of all the tabs and allow them to choose from the list. Barring that, at least a message box informing them they entered a non-existent sheet name and to try again, and to then go back to the input box rather than it disappearing. Here's the code I've been working with so far-
If that's not possible, I'd rather have it just bring up a list of available sheets in the first place and forget the input box altogether. My thought was that it would be nice to type in the needed sheet rather than having to sort through the list every time, but it'd be preferable to nothing happening.
Sub GotoSheet()
Dim sSheet As String
sSheet = InputBox( _
Prompt:="Sheet name or number?", _
Title:="Input Sheet")
On Error Resume Next
If Val(sSheet) > 0 Then
Worksheets(Val(sSheet)).Activate
Else
Worksheets(sSheet).Activate
End If
End Sub

If you would like a list of available sheets to pop up so you can choose one just make a quick UserForm, insert a ListBox (a ComboBox would work as well, I prefer a ListBox visually), and have it populate on userform_initialize:
Private Sub UserForm_Initialize()
Dim WS As Worksheet
For Each WS In Worksheets
ListBox1.AddItem WS.Name
Next WS
End Sub
Make sure the MultiSelect property is set to 0 for single select then create an ok button that goes to the selected sheet:
Private Sub CommandButton1_Click()
Sheets(ListBox1.Value).Activate
Unload Me
End Sub
Then create a button or whatever to show the form.

I believe the root of your problem at the moment is On Error Resume Next. This is causing the sub to simply exit when your else statement encounters an error, such as the sheet does not exist. Instead you need to handle that error through the use of something like On Error GoTo. As in:
Sub GotoSheet()
Dim sSheet As String
sSheet = InputBox( _
Prompt:="Sheet name or number?", _
Title:="Input Sheet")
On Error GoTo noSheet
If Val(sSheet) > 0 Then
Worksheets(Val(sSheet)).Activate
Exit Sub
Else
Worksheets(sSheet).Activate
Exit Sub
End If
noSheet:
'Enter your code to display a warning that the sheet does not exist
'and/or bring up a selection box of all sheets
End Sub
Here is some more information on the On Error statement, which may be of use: https://msdn.microsoft.com/en-us/library/aa266173%28v=vs.60%29.aspx

This will do it for you and handles all error without the need to use On Error statement.
Function Validate(SheetName As String) As Boolean
For i = 1 To ThisWorkbook.Worksheets.Count
If SheetName = ThisWorkbook.Worksheets(i).Name Then
Validate = True
Exit Function
Else
Validate = False
End If
Next
End Function
Sub GotoSheet()
Dim sSheet As String
sSheet = InputBox( _
Prompt:="Sheet name or number?", _
Title:="Input Sheet")
Do While Validate(sSheet) = False
'This if statement is true when the user click cancel or x button
If sSheet = "" Then
Exit Do
End If
MsgBox (sSheet & " does not exist. Please enter a valid sheet name.")
sSheet = InputBox( _
Prompt:="Sheet name or number?", _
Title:="Input Sheet")
Loop
If sSheet <> "" Then
Worksheets(sSheet).Activate
End If
End Sub

Related

Delete Worksheets based on Checkbox

I am currently trying to write a piece of code where someone is able to use a checkbox to choose which worksheets they would like to keep and what they would like removed. Here is what that looks like:
(currently debating if I should turn this into a userform but i would still be stuck at this point).
What I would like to do is if the checkbox is unchecked (false) on the worksheet called "Setup", delete the worksheet and move onto the next if statement. From the code below, I am prompt with the run-time error '1004': Unable to get the OLEObjects property of the worksheet class. I have checked and the Checkbox name is the same as what I have in my code.
Sub DeleteSheetCB()
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox1") = False Then
ThisWorkbook.Worksheets("Program Information").Delete
End If
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox2") = False Then
ThisWorkbook.Worksheets("Spend and Trx Data").Delete
End If
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox3") = False Then
ThisWorkbook.Worksheets("Requirements").Delete
End If
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox4") = False Then
ThisWorkbook.Worksheets("TMC Overview").Delete
End If
End Sub
Thank you in advance
EDIT:
I was able to get this piece of code to delete sheets but if possible, would someone be able to sense check this for me please?
Sub DeleteSheetCB()
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 1").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("Program Information").Delete
Else: End If
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 2").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("Spend and Trx Data").Delete
Else: End If
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 3").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("Requirements").Delete
Else: End If
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 4").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("TMC Overview").Delete
Else: End If
End Sub
The main thing I'd take from your second code is:
It will give you a warning before it deletes each sheet
You'll get a subscript out of range error if the sheet has already been deleted.
You have to update your code if you add a new tick box.
The code below assumes the caption of the checkbox is exactly the same as the name of the sheet to be deleted.
Sub DeleteSheetCB()
Dim chkBox As CheckBox
Dim sMissing As String
With ThisWorkbook.Worksheets("Setup")
For Each chkBox In .CheckBoxes 'Look at all checkboxes in Setup sheet.
If chkBox.Value = 1 Then 'If it's ticked.
If WorksheetExists(chkBox.Caption) Then 'Check worksheet exists.
Application.DisplayAlerts = False 'Turn off warnings about deleting a sheet.
ThisWorkbook.Worksheets(chkBox.Caption).Delete
Application.DisplayAlerts = True 'Turn on warnings about deleting a sheet.
Else
sMissing = sMissing & "- " & chkBox.Caption & vbCr
End If
End If
Next chkBox
End With
If sMissing <> "" Then
MsgBox "These sheet(s) could not be deleted as they were already missing: " & vbCr & vbCr & sMissing
End If
End Sub
Public Function WorksheetExists(SheetName As String) As Boolean
Dim wrkSht As Worksheet
On Error Resume Next
Set wrkSht = ThisWorkbook.Worksheets(SheetName) 'Try and set a reference to the sheet.
WorksheetExists = (Err.Number = 0) 'Was an error thrown?
On Error GoTo 0
End Function
Might also be worth mentioning that you can rename your checkboxes:
Select a check box so the Shape Format ribbon becomes visible.
Click Selection Pane under the Arrange section.
A sidebar will appear showing the shapes on the sheet. You can rename or change their visibility here.
chkRemoveProgramInfo makes more sense than Check Box 1.

Using a variable/ComboBox to search for a variable and then select a relevant Tab in a TabStrip

The setup is this: I have a UserForm that is TabStrip for each of several service providing companies (Each company has select groups of individuals that receive a bill). On the TabStrip is a ComboBox and 12 TextBox objects (one for each month of a year). I have a defined global variable that gets passed between all my UserForms that is one of the groups receiving a bill.
My Goal: I would like the ComboBox list be populated based on the currently selected Tab. I also would like to, if possible, perform a search upon the Initialization of the UserForm for the current variable and match it against the ComboBox values. If the variable is not located in the ComboBox it should cycle to the next Tab and perform the search again. It should do this until the variable is located and then activate that Tab and select that value from the ComboBox.
This is a picture of my current UserForm setup. Hopefully it helps convey my intent a little better. Userform Image
This should work:
Option Explicit
Private Sub UserForm_Initialize()
Call PriSubPopulateCombobox
End Sub
Private Sub TabStrip1_Change()
Call PriSubPopulateCombobox
End Sub
Private Sub PriSubPopulateCombobox()
'Declarations.
Dim RngCostumerList As Range
Dim RngRangeTarget As Range
Dim WksWorksheet As Worksheet
Dim CbxCombobox As ComboBox
Dim TbsTabstrip As TabStrip
'Setting variables.
Set CbxCombobox = Me.ComboBox1
Set TbsTabstrip = Me.TabStrip1
'Setting WksWorksheet according to the value of TbsTabstrip.
Select Case TbsTabstrip.Value
Case Is = 0
Set WksWorksheet = Worksheets("KDDI")
Case Is = 1
Set WksWorksheet = Worksheets("NTT West")
Case Is = 2
Set WksWorksheet = Worksheets("OT Net")
Case Is = 3
Set WksWorksheet = Worksheets("Advanced Pay")
End Select
'Setting RngCostumerList.
With WksWorksheet
Set RngCostumerList = .Range(.Range("A2"), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1))
End With
'Clearing CbxCombobox.
CbxCombobox.Clear
'Filling CbxCombobox.
For Each RngRangeTarget In RngCostumerList
CbxCombobox.AddItem RngRangeTarget.Value
Next
End Sub
Place it in the form module. Check if the variables are set properly and otherwise change them.
Report any question you have or bug you've eventually encountered. If it worked, please mark the answer as accepted.
EDIT: selecting a tag before initializing.
I came up with two ways to do it. Using a Select Case statement we have this solution:
Private Sub UserForm_Initialize()
'Declaration.
Dim StrCostumer As String
'Setting the variable.
StrCostumer = "Advanced Pay"
'Activating the tab accordingly to StrCostumer.
Select Case StrCostumer
Case Is = "KDDI"
Me.TabStrip1.Value = 0
Case Is = "NTT West"
Me.TabStrip1.Value = 1
Case Is = "OT Net"
Me.TabStrip1.Value = 2
Case Is = "Advanced Pay"
Me.TabStrip1.Value = 3
Case Else
MsgBox "No valid costumer found", vbCritical, "Error"
End Select
'Calling PriSubPopulateCombobox.
Call PriSubPopulateCombobox
End Sub
Pro: it is quite strightfoward therefore easy to check. Con: it needs to be edited everytime there is a new entry.
The second solution checks every tab caption until it find the wanted costumer:
Private Sub UserForm_Initialize()
'Declarations.
Dim StrCostumer As String
Dim BytCostumer As Byte
'Setting the variable.
StrCostumer = "Advanced Pay"
'If an error occurs during the searching, it will probably be cause by an overflow. _
Whatever the reason, in such case the search is terminated.
On Error GoTo CP_No_Tab_Found
For BytCostumer = 0 To Me.TabStrip1.Tabs.Count
'If the wanted costumer is found, the tab is selected.
If Me.TabStrip1.Object(BytCostumer).Caption = StrCostumer Then
Me.TabStrip1.Value = BytCostumer
GoTo CP_Tab_Found
End If
Next
CP_No_Tab_Found:
MsgBox "No valid costumer found", vbCritical, "Error"
CP_Tab_Found:
On Error GoTo 0
'Calling PriSubPopulateCombobox.
Call PriSubPopulateCombobox
End Sub
Pro: it doesn't need to be edited for new entries. Con: it's a little more complicated to read.
In both cases you can set StrCostumer to match a public variable or a cell's value or whatever. In both cases if no tag matching StrCostumer is found, a critical message pops out and the form is showed anyway.

Find a value, look for last column of matching value in another workbook

I am very new to VBA. The goal is to look for the numeric value in Cell A3 of Workbook1.Sheet1. This is the search field:
I need to search for a match of that value in Column A of Workbook2.sheet1 then look for the last empty column of that row with the matching search value, and select it.
I have been searching for cells.find formula that may be similar and help me get the code done, but the ones I searched only provide an already specified value.
What i am looking for is a vba code that will search for whatever value is entered in the Range("C3") of workbook1.sheet1 when you click the macro, regardless if a match exists in workbook2.sheet1 or not.
Here's the code i have so far. The cells.find is giving me a run-time error 91 with "Object variable or with block variable not set", highlighting the cells.find part.
If IsEmpty(Range("C3").Value) = True Then
MsgBox "PLEASE Enter TICKET # FIRST"
GoTo Lastline
Else: GoTo Search
End If
Search:
ActiveSheet.Range("C5").Select
Set wbFrom = Workbooks.Open("C:\Users\user\Downloads\Database.xlsx")
Cells.Find(What:=Selection, After:=ActiveCell, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Select
Selection.End(xlToRight).Offset(1, 0).Select
Lastline:
End Sub
You need a button click event sub procedure within the Workbook2.sheet1's code sheet. The code sheet is accessed by right-clicking the button in Design Mode and choosing View Code.
The following is an example procedure; your own may vary depending on what you are presented with after you right-click the worksheet button.
I feel that too many people rely on range.Find when other more suitable options are available. In this case (locating a search criteria in a single column) the worksheet's Match function seems more appropriate.
Option Explicit
Private Sub CommandButton1_Click()
If IsEmpty(Range("C3")) Then
MsgBox "PLEASE Enter TICKET # FIRST"
Exit Sub
End If
Dim m As Variant, wbFrom As Workbook
Set wbFrom = Workbooks.Open("C:\Users\user\Downloads\Database.xlsx")
With wbFrom.Worksheets("sheet1")
m = Application.Match(Range("C3").Value, .Range("A:A"), 0)
If Not IsError(m) Then
'there is almost always something better than .Select but that is what you asked for
.Cells(m, .Columns.Count).End(xlToLeft).Offset(0, 1).Select
Else
MsgBox "search term not found"
End If
End With
End Sub
Please note that this code uses Range("C3").Value without parent worksheet reference. This is because it is inherited through being on a worksheet's private code sheet. Coding like this is not appropriate in a public module code sheet.
A lot of things could go wrong without properly qualifying objects and variables.
Also you actually don't need to use Goto here:
'/* declare variables */
Dim wbFrom As Workbook, r As Range, whattofind As String
If IsEmpty(Sheet1.Range("C3").Value) = True Then
MsgBox "PLEASE Enter TICKET # FIRST"
Else
whattofind = Sheet1.Range("C3").Value '/* sheet1 of the current workbook */
Set wbFrom = Workbooks.Open("C:\Users\user\Downloads\Database.xlsx")
'/* make use of the object you set */
With wbFrom.Sheets(1) '/* refer to Sheet1 as mentioned */
Set r = .Range("A:A").Find(whattofind) '/* search Column A only, change to suit */
If Not r Is Nothing Then '/* check first if something is found */
r.End(xlToRight).Select '/* select last cell in the row
Else
'/* inform if nothing is found */
Msgbox "Item not found"
End If
End With
End If
No way to test ATM, but I hope this helps.
Something like this should do :
Sub GoTo_Ticket()
Dim WbFrom As Workbook
Dim TickNum As Range: Set TickNum = ActiveSheet.Range("C3")
If IsEmpty(TickNum) Then
MsgBox "PLEASE Enter TICKET # FIRST"
Exit Sub
End If
Set WbFrom = Workbooks.Open("C:\Users\user\Downloads\Database.xlsx")
Lrow = Application.Match(TickNum.Value, WbFrom.Sheets("sheet1").Range("A:A"), 0)
WbFrom.Sheets("sheet1").Cells(Lrow, 9999).End(xlToLeft).Offset(0, 1).Select
End Sub
Please note that it is not handling situations where the ticket number is not found.

Using VBA userform to select ranges on multiple sheets - sheet changes back to original activesheet

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

1004 error on excel 2013 textbox VBA

I want to run a simple script which I would further enhance. I had something similar working for autofilters yesterday but I misplaced it and am having a hard time to find a solution. I want to use an active x textbox to filter a pivot table. I have tried changing the location of the module as well as using acitveworkbook and activesheet and me but all seem to return a 1004 error. I can confirm the textbox is on the page as well as the pivot table. This is office 13.
Private Sub TextBox1_Change()
ActiveSheet.PivotTables("PivotTable2").PivotFields("Agency").ClearAllFilters
ActiveSheet.PivotTables("PivotTable2").PivotFields("Agency").CurrentPage = ActiveSheet.TextBox1.Text
End Sub
I believe the solution I had yesterday had something to do with activating the textbox. But cant quite rememeber.
Any help would be much appreciated.
Your subroutine must be placed in the Worksheet's code module. I believe the error is happening because the _Change event fires with every keystroke, so it is very likely that the first keystroke creates a TextBox1.Text value which does not correspond with any of the PivotItems in that PivotField.
You could do something like this. Use the _GotFocus event to provide an input prompt. That subroutine will then implicitly raise the TextBox1_Change event by assigning the input value to the TextBox1.Text.
Private Sub TextBox1_GotFocus()
Dim str$
str = InputBox("Please enter a value", "Pivot Field filter")
TextBox1.Text = str
End Sub
I temporarily disable error handling (On Error Resume Next) to assign the filter. Then I check to see if an error happened, and you can (optionally) inform the user that they supplied an invalid criteria.
Sub TextBox1_Change()
Dim pt As PivotTable
Dim fld As PivotField
Set pt = PivotTables("PivotTable2") 'Modify as needed
Set fld = pt.PivotFields("Agency")
With fld
.ClearAllFilters
On Error Resume Next
.CurrentPage = TextBox1.Text
.Orientation = xlPageField
.Position = 1
If Err.Number <> 0 Then
'you may want to include a prompt here, i.e.:
MsgBox "Invalid Filter!", vbInformation
Exit Sub
End If
On Error GoTo 0
End With
End Sub

Resources