Excel VBA: Generate N Number of Sheets Based on Cel Value - vba

I want to create a macro that will generate N number of template sheets based on the value of a cel. For example, User inputs 4 into this particular cell and it subsequently generates 4 new sheets in the workbook of this template.
I've searched all through Stack overflow for a question that matches mine but none do. The closest I found was this and although the inital headline question asks generally the same question, when going into detail the user who asked this changes their question to"insert number of cells based on a cell value". Still I used this as a starting point.
Sub CreateSheets()
Dim facilitiesNum As Integer
facilitiesNum = Range("B2").Value
sheetsNeeded = facilitiesNum
With ThisWorkbook.Sheets
For i = sheetsNeeded To Master.Range("B2").Value2
.Item("TemplateSheet").Copy After:=.Item(.Count)
.Item(.Count).Name = sheetsNeeded
Next
End With
End Sub
I am new to VBA so I could be very off syntax-wise but in pseudocode my goal is
numberOfTemplates = cell value
numSheetsNeeded = numberOfTemplates
For i = numSheetsNeeded To NumOfTemp:
create sheets using numSheetsNeeded as reference for how many need to be
generated
How do I go about doing this?

If you just want to add new sheets this should be enough
Sub CreateSheets()
Dim facilitiesNum As Long
facilitiesNum = Range("B2").Value
With ThisWorkbook.Sheets
For i = 1 To facilitiesNum
.Item("TemplateSheet").Copy After:=.Item(.Count)
.Item(.Count).Name = i
Next i
End With
end sub

Related

User Choice and loops vba

I'm trying to establish the logic for creating a navigation menu for a budget tracking system: it has 12 sheets for each budget line with 12 monthly tables per sheet.
The navigation menu is based on two combo boxes, one listing the sheets, and the other the names of the months - when a user selects where to go, the sheet and first cell in the chosen table activate.
What I'm looking for is a more effective way to organize this than writing 144 distinct if-then conditions accounting for every possible listindex combination the user might choose. The Select Case approach also works, but it is equally voluminous in scope...
I have been investigating using loops for the purpose - e.g. ListIndex values can be defined in a loop, but I'm coming up short on ideas for the overarching concept.
Thank you in advance!
Here I set up a workbook with 12 worksheets one for each month. Each worksheet has 12 tables on it. When the user selects a worksheet from the dropdown (cboWorkSheets) the second drop down (cboTables) list is cleared and then all the table names from the selected worksheet is added to back to the list.
When a user selects a table name from cboTables the worksheet referenced by cboWorkSheets is searched for that table. The first cell in the table's databody range is then selected.
Option Explicit
Private Sub cboTables_Change()
Dim ws As Worksheet
Dim tbl As ListObject
Set ws = Worksheets(cboWorkSheets.Value)
Set tbl = ws.ListObjects(cboTables.Value)
ws.Activate
tbl.DataBodyRange.Cells(1, 1).Select
End Sub
Private Sub cboWorkSheets_Change()
Dim ws As Worksheet
Dim tbl As ListObject
Set ws = Worksheets(cboWorkSheets.Value)
cboTables.Clear
For Each tbl In ws.ListObjects
cboTables.AddItem tbl.Name
Next
End Sub
Private Sub UserForm_Initialize()
cboWorkSheets.List = Array("Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5", "Sheet6", "Sheet7", "Sheet8", "Sheet9", "Sheet10", "Sheet11", "Sheet12")
End Sub
Doing the sheet selection is pretty straightforward. Just create an array that will hold the sheet name that corresponds to the ListIndex. Something like this
Dim myArray(11) As String
myArray(0) = "a"
myArray(1) = "b"
myArray(2) = "c"
...
myArray(10) = "k"
myArray(11) = "l"
Worksheets(myArray(ComboBox1.ListIndex)).Activate
If the person selects the 5th ComboBox element, sheet "e" would be activated.
Selecting the table cell is a bit more problematic since it depends on where on the sheet the tables are located. If they are spaced equidistantly apart, you can use a simple math formula. That is, if the January table starts at E7, Feb at E27, Mar at e47, then it is a simple matter of using the listindex to calculate the starting row. Eg:
Worksheets(myArray(ComboBox1.ListIndex)).Cells(7 + ComboBox2.ListIndex * 20, "E").Select
Hope this helps. :)
As general interest, this is the functional version of the code for a proof of concept file I built around #Tim's example, given above. Here goes:
In Module1:
Sub ComboBox1_Change()
Dim sheets_array(0 To 2) As Variant
sheets_array(0) = "Sheet1"
sheets_array(1) = "Sheet2"
sheets_array(2) = "Sheet3"
With UserForm1.ComboBox1
.Clear
.List = sheets_array
.Style = fmStyleDropDownCombo
End With
Call ComboBox2_Change
UserForm1.Show
End Sub
Sub ComboBox2_Change()
Dim monthsarray(0 To 3) As Variant
monthsarray(0) = "April"
monthsarray(1) = "May"
monthsarray(2) = "June"
With UserForm1.ComboBox2
.Clear
.List = monthsarray
.Style = fmStyleDropDownCombo
End With
End Sub
In the UserForm1 code window:
Private Sub ComboBox1_Change()
With UserForm1.ComboBox1
Worksheets(.List(.ListIndex)).Activate
End With
End Sub
Private Sub ComboBox2_Change()
With Worksheets(UserForm1.ComboBox1.ListIndex)
.Select
.Cells(7 + UserForm1.ComboBox2.ListIndex * 20, "E").Select
End With
End Sub
#Thomas Inzina, your solution is considerably more elegant and I hope I can think about programming at your level at some point.

find out cell address having = sheet name

I'm just a beginner for VBA but advance in MS excel. that's why I am very much interested to learn VBA.
ok this is my first question here
Actully i need to format excel sheet where file name is = sheet1 name and it is somewhere in column "A" so I want to select & delete all the rows above this cell & below untill there is a blank cell/row.
I have tried much with InStr & find function but no succeed. Also try to find cell address like B5 but could no do that.
Welcome to StackOverflow. As you have already been informed by newguy, when posting a question you should also show what you have tried so far... some piece of code, printscreens, etc.
Your explanation was not that clear (at least to me), but based on what I have understood, I have made a small code sample for you to get you started. I have broken down the code into the function blocks, so that you can better understand what they are trying to achieve.
Here is the code:
'the following function will find cell with the specific text
Private Function FindCell(ws As Worksheet, strToSearch As String, Optional sColumn As String = "A") As Integer
Dim iCounter As Integer
'as you do not know where exactly it exists, we loop from first cell in the particular row
'to the very last celll
With ws
For iCounter = 1 To .Range("A65000").End(xlUp).Row ' or .UsedRange.Rows.Count, or any other method
If .Range(sColumn & iCounter).Value = strToSearch Then
'yay, we have found the cell!
'pass out the reference
FindCell = iCounter
'now call exit function as we no longer need to continue searching for the cell (we have already found it!)
Exit Function
End If
Next iCounter
End With
'in case the cell does not exist, we can return -1
FindCell = -1
End Function
'the following cell will search the very first cell to the top (starting from specific row), which is blank / empty
Private Function FindEmptyCell(ws As Worksheet, iStartRow As Integer, Optional sColumn As String = "A") As Integer
'This function does the same, as if you have selected specific cell
'and then pressed left Ctrl + Up arrow at the same time
'Try it!
'You can do the same with Right + Left + Bottom arrow as well
FindEmptyCell = ws.Range(sColumn & iStartRow).End(xlUp).Row + 1
End Function
Private Sub EraseRows()
Dim iStartCell As Integer
Dim iEndCell As Integer
On Error GoTo 0
'First let's find the "bottom" cell which is the cell with the specific text you are looking for
iEndCell = FindCell(ActiveSheet, "TextIAmLookingFor")
'now let's see find the top blank cell (so that we get the range of from - to that you want to erase)
iStartCell = FindEmptyCell(ActiveSheet, iEndCell)
'now we can delete the rows!
'iEndCell-1 because you don't want to erase the cell with your search string, right?
ActiveSheet.Rows(CStr(iStartCell) & ":" & CStr(iEndCell - 1)).EntireRow.Delete (xlUp)
End Sub

Excel: How to program to have Excel read a cells contents then switch open a new worksheet?

I'm very new to programming (1 day experience) and I am trying to build an interactive database but I keep running into issues with having a certain part work.
I want Excel to read the value selected in a certain cell and based on the value in that cell then have it open to a separate sheet, where I can begin another set of data entry.
I have tried a number of different options but as of now, my code looks like this:
Dim inputWks As Worksheet
Set inputWks = ("Input")
With inputWks
If Range("D13").contents = "Yes" Then
ActiveWorkbook.Sheets("Sheets2").activate
End If
End With
I know this is a simple question but I have not been able to have this work..
try this
Sub DoIt()
Dim inputWks As Worksheet
Set inputWks = ActiveWorkbook.Sheets("Input")
With inputWks
If Range("D13").Cells(1, 1) = "Yes" Then
ActiveWorkbook.Sheets("Sheets2").Activate
End If
End With
End Sub

dynamically select sheet from the inputprompt and print to a file

i have 3 sheets in my workbook namely sheet1 ,sheet3 and sheet2 when i enter a values from in the inputpromt say (eg:1,2 ) i split it and store it in an array it must dynamically select the sheet1 and sheet2 and print values to a file.
i have done a pseudo below can any one
Sub example()
Dim Ran As Range
Dim cnt as String
Open "D:\temp\test.txt" For Output As #1
Dim myarray() As String
Dim holder As String
dim ab as Strig
ab="this is sample data"
holder = InputBox("Enter your choice eg:1,2")
myarray = Split(holder, ",")
Dim name, country,birth As String
For i = 1 To UBound(myarray)
If i = 1 Or i = 2 Then
name = Sheets(i).Range("Z12").Value
country= Sheets(i).Range("PQ26").Value
birth = Sheets(i).Range("ab24").Value
ab=ab & name & country & birth
Print #1, ab
End If
Next i
end Sub
****in the inputbox if i give value as 1,2 then it must select values from sheet 1 and sheet2****
I am guessing you that you are trying to understand InputBox and how to split a string such as “1, 2” and process the separate values as sheet numbers.
Sheet numbers mean nothing to the user so I do not believe this is a good approach. You need to offer the user a list of worksheet tabs from which they can select.
There is InputBox and Application.InputBox. These are different and I do not like either. They come from the earliest versions of VB and were probably originally a direct match to MS-DOS’s console input. With one exception, there are much better approaches. The one exception is the ability to input a range with Application.InputBox for which I do not know a convenient alternative.
In the code below I use InputBox. You may think I have overdone the validation but what if the user enters “A”? Your code would assume “A” was a sheet number but Excel would assume it was a worksheet name and stop execution with a subscript error. You must check for any error that will cause your code to stop with a run-time error.
Instead of either InputBox you should use a User Form. There are on-line tutorials to get you started. With a User Form you have several choices including:
A List box, with multiple selection enabled, containing the names of every permitted worksheet.
A column of radio buttons, one per permitted worksheet. These would be unlinked so the user could select several.
A command button for each permitted worksheet which the user could click in turn.
All of these choices are much user-friendlier than InputBox.
Step through the code below with F8 and study what it does. Come back with questions if necessary but the more you can understand on your own the faster you will develop.
Option Explicit
' Please indent your macros consistently. This makes them much easier ri read
Sub example()
Dim Ran As Range
Dim cnt As String
Dim myarray() As String
Dim ab As String
' Variables I have added or which are replacements for yours.
Dim Answer As String
Dim AllValuesGood As Boolean
Dim InxMA As Long
Dim InxSht As Long
Dim Question As String
' I like to keep all my Dim statements together at the top.
' This makes them easier to find.
Dim name, country, birth As String
' I have output to the Immediate window which is simpler when
' experimenting.
'Open "D:\temp\test.txt" For Output As #1
Question = "Enter your choice eg: ""1"" or ""1,2"""
' You omitted the code to check the Answer
Do While True
Answer = InputBox(Question, "Experiment with Input box")
' Have a string but user could have typed anything
If Answer = "" Then
' Cannot tell if user has clicked Cancel or if user clicked Return
' before entering value. Have to assume Cancel
Debug.Print "User clicked Cancel"
Exit Sub
Else
AllValuesGood = True ' Assume good answer until find otherwise
myarray = Split(Answer, ",")
For InxMA = 0 To UBound(myarray)
If IsNumeric(myarray(InxMA)) Then
InxSht = Val(myarray(InxMA))
If InxSht < 1 Or InxSht > 2 Then
' Sheet number outside permitted range
AllValuesGood = False
Exit For
End If
Else
' Non-numeric sheet number
AllValuesGood = False
'Debug.Assert False
Exit For
End If
Next
End If
If AllValuesGood Then
' Have good answer. Exit Do-Loop to print sheets
Exit Do
Else
' An invalid sheet number has been found
Question = "Click cancel to exit or enter ""1"" or ""2"" or ""1, 2"""
' Loop to repeat Input
End If
Loop ' Until have good answer
' If get here Answer is a list of good sheet number
For InxMA = 0 To UBound(myarray)
InxSht = Val(myarray(InxMA))
' I have not created sample worksheets with data in Z12, PQ26 and ab24
' but this shows the code you need
'With Worksheets(InxSht)
' name = .Range("Z12").Value
' country = .Range("PQ26").Value
' birth = .Range("ab24").Value
'Next
name = "Name" & InxSht
country = "Country" & InxSht
birth = "Birth" & InxSht
' Have to initialise ab here because need new value per sheet
ab = "this is sample data"
ab = ab & name & country & birth
Debug.Print ab
' The value of ab will be messy because you have no spaces between words.
'Print #1, ab
Next InxMA
End Sub

How to collect data from multiple sheets by using sheet names

Thanks for the response!
however the code which you sent started from the beginning of the workbook. but it should not be.
For example, a workbook contains sheets (only user knows the sheet name, so we can't give the sheet name on the code) as following
Summary/Version/AA/BB/CC/DD/Final
If beginsheet=AA then the code should start collecting data from AA and if endsheet = DD then the code should stop collecting data at Final. Only till DD is valid.
So how can we achieve this.
You can do a FOR - EACH: For each theSheets in ActiveWorkbook.Sheets
For each theSheets in ActiveWorkbook.Sheets
Sheets(theSheets.Name).Select
msgbox(theSheets.Name)
next
I put the MSGBOX just to show the name of the sheet. Also the Select is not necessary I put it there just to show how it changes from sheet to sheet.
If you don't want to search all sheets (each sheet) but a specified number of sheets, you can assign the sheets names to a collection and the iterate that collection; in that case you have to know the names of the sheets.
sorry I did not get your first question...
Well, I don't know how practical this solution will be for you purpose but you could do the following:
When you open the workbook create CheckBoxes with the names of the Sheets:
Private Sub Workbook_Open()
Dim row As Integer
row = 14
For Each mysheets In ActiveWorkbook.Sheets
ActiveSheet.CheckBoxes.Add(20, row, 50, 20).Select
With Selection
.Caption = mysheets.Name
.Value = xlOff
.LinkedCell = "C" & ToRow
.Display3DShading = False
End With
row = row + 50
Next
End Sub
Have the users select the Sheets that apply.
Fill a collection with the "Text" of the selected CheckBoxes (which will be the names of the sheets)
Iterate through the sheets in the collection
Dim allSelectedSheets As New Collection
Public Sub FindSelectedCkBox()
For Each ckbox In ActiveSheet.CheckBoxes
If ckbox.Value > 0 Then
allSelectedSheets.Add ckbox.Text
End If
Next
iterateThroughSheets
End Sub
Sub iterateThroughSheets()
For Each theSheets In allSelectedSheets
ActiveWorkbook.Sheets(theSheets).Select
Next
End Sub
Make sure to remove the CheckBoxes when opening the Book so you don't end up with duplicates.