Navigate until there is no sheet left - vba

I have a task for school. On my worksheet there is a button with next sheet and previous sheet. But I want that it always checks if possible to move to the next sheet.
For example, three sheets. I start on sheet 1 and click next. Then on sheet 2 I click next. I'm on sheet 3 and I click next, so a message box comes up "there are no sheets left." but if I add another sheet it needs to move on to sheet 4.
Here is the code that I already have:
If ActiveSheet.Index = Worksheets.Count Then
Worksheets(1).Select
Else
ActiveSheet.Previous.Select
End If

If ActiveSheet.Index <> Worksheets.Count Then
ActiveSheet.Next.Select
Else
MsgBox "There are no more sheets left."
End If

if you aim to simply add Command Button to every page then you would have to copy this code in each of the command buttons on all pages(design mode-doubleclick the command button)
Private Sub CommandButton1_Click()
Dim sheetnum As Integer
sheetnum = ActiveSheet.Index
If sheetnum = ThisWorkbook.Sheets.Count Then
ThisWorkbook.Sheets(1).Activate
MsgBox "You are at last sheet returning to the first sheet."
Else
ThisWorkbook.Sheets(sheetnum + 1).Activate
End If
End Sub
Or you would have to create a module and call function from command button.
Like this:
In CommandButton code on every page:
Call newpage
In Module1:
Public Sub newpage()
Dim sheetnum As Integer
sheetnum = ActiveSheet.Index
If sheetnum = ThisWorkbook.Sheets.Count Then
ThisWorkbook.Sheets(1).Activate
MsgBox "You are at last sheet returning to the first sheet."
Else
ThisWorkbook.Sheets(sheetnum + 1).Activate
End If
End Sub

Related

My VBA behaves differently when assigned to a button

I have set up a Quality Check sheet which needs to store results in a separate sheet called 'Data' as a row of data, and save an archived version of the full Check Sheet in a separate workbook.
I'm quite a novice on VBA but have managed to get what I need working. My problem comes when I assign the macro to a button which is contained on my check sheet. If I press the button it copies the wrong sheet over and basically does not do what it does when I run the macro manually. Can anyone suggest anything please?
Thanks
My code is as follows:
Sub SaveForm()
' SaveForm Macro
' Saves form data to the Data Sheet
'Checks for completion of mandatory fields
If IsEmpty(Range("b3").Value) = True Then
MsgBox "Please complete 'Agent Name' before saving"
Exit Sub
ElseIf IsEmpty(Range("b4").Value) = True Then
MsgBox "Please complete 'Call ID' before saving"
Exit Sub
ElseIf IsEmpty(Range("b5").Value) = True Then
MsgBox "Please complete 'Call Length' before saving"
Exit Sub
ElseIf IsEmpty(Range("D3").Value) = True Then
MsgBox "Please complete 'Business Name' before saving"
Exit Sub
ElseIf IsEmpty(Range("D4").Value) = True Then
MsgBox "Please complete 'Date of Call' before saving"
Exit Sub
ElseIf IsEmpty(Range("D5").Value) = True Then
MsgBox "Please complete 'Time of Call' before saving"
Exit Sub
ElseIf IsEmpty(Range("b7").Value) = True Then
MsgBox "Please complete 'Assessor Name' before saving"
Exit Sub
ElseIf IsEmpty(Range("b8").Value) = True Then
MsgBox "Please complete 'Date of Assessment' before saving"
Exit Sub
End If
'Copies a range contained within the "Checksheet" and pastes
'it into the next available row on the "Data" sheet
'The reason it is in a straight row as opposed to sporadic cell
'references is because I have set the sheet up this way for simplicity
Range("M14:BP14").Copy
Sheets("Data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
ActiveWindow.ScrollRow = 1
Workbooks("Call Feedback Form V0.42.xlsm").Sheets("Checksheet").Activate
Call CopyRenameWorksheet
Workbooks("Call Feedback Form V0.42.xlsm").Sheets("Checksheet").Activate
End Sub
.
Sub CopyRenameWorksheet()
'This renames the worksheet based on cell references and archives to another workbook
Dim ws As Worksheet
Set wh = Worksheets(ActiveSheet.Name)
ActiveSheet.Copy After:=Worksheets(Sheets.Count)
If wh.Range("B3").Value <> "" Then
ActiveSheet.Name = wh.Range("B3").Value & " " & Format(wh.Range("D4").Value, ("yymmdd")) & " " & wh.Range("B4").Value
ActiveSheet.Move After:=Workbooks( _
"Archived Quality Forms.xlsx").Sheets(1)
End If
I think your problem is due to the fact that you are referencing the wrong sheet. Make sure you always fully qualify when you will be using different sheets.
I would start the Subs with
dim ws as worksheet
set ws = Worksheets("Sheetname")
and then you can change all of the ranges to be like ws.range("A1")
This way they will always reference the range on the correct sheet.
I would start by going through your code and making sure that every single reference to a range is referencing a worksheet and a range on said worksheet.
Hope it helps!
Your problem is with this line of code
Range("M14:BP14").Copy
You need to explicitly state what sheet youre referring too. Like i.e.
ThisWorkbook.Sheets("Sheet1").Range("M14:BP14").Copy

Excel VBA user form to display the sheet which is selected

I have created a userform which has a listbox (ListBox1)which list down the sheet names and I can double click on the list and it will take me to that sheet. I have a back button (CommandButton2) when I click on back button it will take me to the previous selected sheet.
I want to link my list box and back button so that when I click on back button the my listbox (ListBox1)should highlight the sheet where my back button (CommandButton2) has directed to.
Please find below my codes:
Private Sub UserForm_Initialize()
Dim Sh As Worksheet
'for each loop the add visible sheets
For Each Sh In ActiveWorkbook.Sheets
'add sheets to the listbox
Me.ListBox1.AddItem Sh.Name
Next Sh
End Sub
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
'declare the variables
' modifed code for ListBox double-click event, store the sheet name before switching to the selected item
Dim i As Long
LastSelectedSht = ActiveSheet.Name ' <-- save the current active sheet before selecting a new one
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then
Worksheets(ListBox1.List(i)).Activate
End If
Next i
End Sub
Private Sub CommandButton2_Click()
Dim TmpSht As String
TmpSht = ActiveSheet.Name ' <-- save the current active sheet
' select the previous sheet (stored in LastSelectedSht)
If LastSelectedSht = "" Then
MsgBox "Error, no sheet stored , is it your first time running ? "
Else
Sheets(LastSelectedSht).Select
End If
LastSelectedSht = TmpSht ' <-- use the temp variable to store the latest active sheet
' reset the userform
Unload Me
frmNavigation.Show
End Sub
No need for al those loops to seek selected item, you can simplify things a bit as follows:
Option Explicit
Dim LastSelectedSht As String '<--| use as UserForm scoped variable to store the name of "last" sheet selected
Private Sub UserForm_Initialize()
Dim Sh As Worksheet
With Me.ListBox1
'for each loop the add visible sheets
For Each Sh In ActiveWorkbook.Sheets
.AddItem Sh.Name 'add sheets names to the listbox
Next Sh
LastSelectedSht = ActiveSheet.Name ' <-- store the currently active sheet name as the "last" one
.Value = LastSelectedSht '<--| initialize listbox selection with the currently active sheet name
End With
End Sub
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
' modifed code for ListBox double-click event, store the sheet name before switching to the selected item
LastSelectedSht = ActiveSheet.Name
Worksheets(ListBox1.Value).Activate '<--| activate the sheet whose name has been dblclicked
End Sub
Private Sub CommandButton2_Click()
Sheets(LastSelectedSht).Activate
Me.ListBox1.Value = LastSelectedSht
' reset the userform
Unload Me
frmNavigation.Show
End Sub
This sub will change the selected item in the list box.
Private Sub SetListBox(Lbx As MSForms.ListBox, _
Itm As String)
Dim i As Integer
With Lbx
For i = 0 To .ListCount - 1
.Selected(i) = Not CBool(StrComp(.List(i), Itm))
Next i
End With
End Sub
Call it from your procedure which activates the previous worksheet with a line of code like this one.
SetListBox ListBox1, TmpSht
Make sure that TmpSht holds the name of the newly activated sheet at the time you make the call or pass the name of that sheet instead of TmpSht.

Worksheet Change to run macro

My workbook contains several sheets, each with multiple checkboxes. All checkboxes in all worksheets have the linked cell in row 80. In a worksheet called "Info" I am using countif to count the total number of times the text "TRUE" occurs in row(s) 80 for all worksheets. The total is in Info!B8.
I need to call a macro each time cell Info!b8 changes. So in other words; every time a checkbox is clicked, the linked cell changes, cell Info!b8 goes up or down and I need a macro to run.
This is the code I am using, but it doesn't do anything. I have researched this and from what I can tell it should work??
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$8" Then
Call CreateFinalWorksheet
End If
End Sub
Assuming all your CheckBoxes are of Form Controls, with a bit of altering the CheckBox Creation, you can achieve what you want without the need of LinkedCell and CountIfs etc.
Example: CreateCheckBoxes() below will create a check box for each cell in Range("D1:D5"), Name it with a prefix and the cell address, assigns the Sub CheckBoxClicked when clicked.
In Sub CheckBoxClicked(), it will go through all worksheets (except named "Info"), then increment a counter if the value of checkbox named ending D3 is 1 (ticked). After that, if threshold is met, it calls the Sub CreateFinalWorksheet().
Option Explicit
Private Const ChkBoxPrefix As String = "cbx_"
Private Const ThresholdToCreateFinalWorksheet As Long = 3
Sub CreateChkBoxes()
Dim myCBX As CheckBox, c As Range
For Each c In Range("D1:D5") 'rngCB
With c
Set myCBX = ActiveSheet.CheckBoxes.Add(Top:=.Top, Width:=.Width, Height:=.Height, Left:=.Left)
End With
With myCBX
.Name = ChkBoxPrefix & c.Address(0, 0)
.Caption = "Check Box " & c.Address(0, 0) 'strCap
.OnAction = "CheckBoxClicked" ' "CheckBox_Click"
End With
Next c
End Sub
Sub CheckBoxClicked() ' CheckBox_Click()
Dim oWS As Worksheet, lChecked As Long
On Error Resume Next ' Just in case the named CheckBox does not exist
lChecked = 0
For Each oWS In ThisWorkbook.Worksheets
If oWS.Name <> "Info" Then
' If you need to keep track of more than 1 checkbox in each worksheet, go through them
' If you need all of them to be checked before CreateFinalWorksheet, exit when a checkbox.value = 0
With oWS.CheckBoxes(ChkBoxPrefix & "D3") ' <-- Change to what you need to keep track of
lChecked = lChecked + IIf(.Value = 1, 1, 0)
End With
End If
Next
On Error GoTo 0
If lChecked >= ThresholdToCreateFinalWorksheet Then CreateFinalWorksheet
End Sub
Private Sub CreateFinalWorksheet()
Debug.Print "CreateFinalWorksheet()"
End Sub
Alternatively you put the event Sub Worksheet_Calculate() into Info module, and check if the Info!B8 is large enough to call CreateFinalWorksheet.

create a backbutton in excel vba userform to go to the previous active sheet

I have created a userform frmNavigation which has a ListBox1, which will list down all the worksheets present in my workbook and I can double click on any of worksheet listed in the listbox and go to that sheet.
Now as I have close to 50 worksheets so I double click from the list appearing in ListBox1 and go to that sheet but now I want a back button "CommandButton2" so that it can take me back to my previous active sheet.
I have created a code but its not working.
Private Sub CommandButton2_Click()
Application.ScreenUpdating = False
Dim i As Integer, Sht As String
'for loop
For i = 0 To ListBox1.ListCount - 1
'get the name of the selected sheet
If ListBox1.Selected(i) = True Then
Sht = ListBox1.List(i - 1)
End If
Next i
'select the sheet
Sheets(Sht).Select
'reset the userform
Unload Me
frmNavigation.Show
End Sub
Try the code below, I am not sure how to explain my logic of the code below, I tired my best to describe it in the code comments.
I've modified also the ListBox1_DblClick code event, to save the latest ActiveSheet before you Select the new sheet.
Code
Option Explicit
Dim LastSelectedSht As String ' Variable at module level, to store the name of the last selected sheet
'===================================================================
Private Sub CommandButton2_Click()
Dim TmpSht As String
TmpSht = ActiveSheet.Name ' <-- save the current active sheet
' select the previous sheet (stored in LastSelectedSht)
If LastSelectedSht = "" Then
MsgBox "Error, no sheet stored , is it your first time running ? "
Else
Sheets(LastSelectedSht).Select
End If
LastSelectedSht = TmpSht ' <-- use the temp variable to store the latest active sheet
' reset the userform
Unload Me
frmNavigation.Show
End Sub
'===================================================================
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
' modifed code for ListBox double-click event, store the sheet name before switching to the selected item
Dim i As Long
LastSelectedSht = ActiveSheet.Name ' <-- save the current active sheet before selecting a new one
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then
Worksheets(ListBox1.List(i)).Activate
End If
Next i
End Sub
'=================================================================
Private Sub UserForm_Activate()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
Me.ListBox1.AddItem ws.Name
Next ws
End Sub

Macro for multiple sheets doesn't work properly

Sub RunMacroOnAllSheetsToRight()
For i = ActiveSheet.Index To Sheets.Count
Call MyFunction(i)
Next i
End Sub
Function MyFunction(i)
'Code goes here
Columns("R:R").ColumnWidth = 8.1
[S1].Resize(, 14).EntireColumn.Insert
MsgBox "I'm currently on sheet " & ThisWorkbook.Sheets(i).name
End Function
I found a sample of code for running macro that should run on all sheets on the right from the active one, but it is not working, it keeps running on one sheets, but the msgbox shows me that the sheets are changed(each time it displays different name). Can you help me? I am new to vba-excel.
You need to activate each sheet. Then activate original sheet.
Sub RunMacroOnAllSheetsToRight()
Dim a As Integer
a = ActiveSheet.Index 'Save current sheet
For i = a To Sheets.Count
Call MyFunction(i)
Next i
Sheets(a).Activate 'At the end, activate original sheet
End Sub
Function MyFunction(i)
'Code goes here
Sheets(i).Activate 'Activate each sheet
Columns("R:R").ColumnWidth = 8.1
[S1].Resize(, 14).EntireColumn.Insert
MsgBox "I'm currently on sheet " & ActiveSheet.Name 'Trustworthy information
End Function