VBA Code to Create Sheets based on the values in column A - excel

I am looking for a code to create sheets with the name in column A. I have used this code but it is not fulfulling my requirement. The code is ;
Private Sub CommandButton1_Click()
Dim sheetCount As Integer
Dim sheetName As String
Dim workbookCount As Integer
With ActiveWorkbook
sheetCount = Sheets(1).Range("A2").End(xlDown).Row
For i = 2 To sheetCount Step 1
sheetName = .Sheets(1).Range("A" & i).Value
workbookCount = .Worksheets.Count
.Sheets.Add After:=Sheets(workbookCount)
.Sheets(i).Name = sheetName
'.Sheets(i).Range("A" & i, "F" & i).Value = .Sheets("sample").Range("A" & i, "F" & i).Value
Next
End With
Worksheets(1).Activate
End Sub
Upon running this code in first go, it creates sheets with the text present in column A. But the problem is when i entered new text in that column, it makes previous sheets as well. I am looking for a code which only create the sheets with the new text being entered in the column and donot make sheets which are already made. Kindly help me out on this as i tried too much but didnt find any code.
Thanks

This works for me, and is tested: Note, if you try to use a name like "History" that is reserved you will get an error. I am not aware of all the reserved names.
Private Sub CommandButton1_Click()
Dim lastRow As Long
Dim sheetName As String
Dim workbookCount As Long
Dim ws As Worksheet
Dim match As Boolean
lastRow = Sheets("Sheet1").Range("A2").End(xlDown).Row
For i = 2 To lastRow
match = False
sheetName = Sheets("Sheet1").Cells(i, 1).Text
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = sheetName Then
match = True
End If
Next
If match = False Then
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = sheetName
End If
Next i
End Sub
Edit: Added Screen Shots

You can try thi function:
Function SheetExists(SheetName As String) As Boolean
Dim Test As Boolean
On Error Resume Next
Test = Sheets(SheetName).Range("A1").Select
If Test Then
SheetExists = True
Else
SheetExists = False
End If
End Function
Using the function this way:
Sub test()
If SheetExists("MySheet") Then
MsgBox "Sheet exists"
Else
MsgBox "Sheet is missing"
End If
End Sub

I usually have these two helper functions in my workbooks / personal workbook
Option Explicit
Function getSheetWithDefault(name As String, Optional wb As Excel.Workbook) As Excel.Worksheet
If wb Is Nothing Then
Set wb = ThisWorkbook
End If
If Not sheetExists(name, wb) Then
wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count)).name = name
End If
Set getSheetWithDefault = wb.Sheets(name)
End Function
Function sheetExists(name As String, Optional wb As Excel.Workbook) As Boolean
Dim sheet As Excel.Worksheet
If wb Is Nothing Then
Set wb = ThisWorkbook
End If
sheetExists = False
For Each sheet In wb.Worksheets
If sheet.name = name Then
sheetExists = True
Exit Function
End If
Next sheet
End Function
To create the worksheets you just iterate over the sheet names and use the getSheetwithDefault function
The following code demonstrate this:
sub createSheets()
dim cursor as Range: set cursor = Sheets("Sheet1").Range("A2")
while not isEmpty(cursor)
getSheetWithDefault(name:=cursor.value)
set cursor = cursor.offset(RowOffset:=1)
wend
end

Related

copy and rename a worksheet in excel VBA

Hi i am trying to copy from a master template and rename a the copy worksheet in excel VBA i was using Date which worked great but now I am trying to rename the copy of the master to DATA 1 and then the next time the new sheet would be DATA 2
Private Sub Workbook_Open()
Dim iThisMonth As Integer, iLastMonth As Integer
Dim datLastRun As Date
Dim rCheckCell As Range
Set rCheckCell = Sheets("master").Range("A5")
Set Target = Range("V16")
On Error Resume Next
datLastRun = CDate(rCheckCell.Value)
iLastMonth = Month(datLastRun)
On Error GoTo 0
If Target.Value = "yes" Then
MsgBox "Call Peter"
Call Peter
rCheckCell.Value = Format(Now(), "dd/mmm/yy")
End If
End Sub
Macro Code
Sub Peter()
Sheets("Master").Visible = True
Sheets("Master").Copy After:=Worksheets(Worksheets.Count)
NewPageName = Data1
ActiveWindow.ActiveSheet.Name = NewPageName
End Sub
Create a basic function like below which will give you the next available name. For example, if there is a worksheet with the name Data1 and Data2, then the below function will return Data3
Private Function NewDataName() As String
Dim ws As Worksheet
Dim i As Long: i = 1
Dim shtname As String
Do
'~~> Create a worksheet name
shtname = "DATA" & i
'~~> Check if we already have a worksheet with that name
On Error Resume Next
Set ws = ThisWorkbook.Sheets(shtname)
On Error GoTo 0
'~~> If no worksheet with that name then return name
If ws Is Nothing Then
NewDataName = shtname
Exit Do
Else
i = i + 1
Set ws = Nothing
End If
Loop
End Function
And the usage will be like
Sub Peter()
Sheets("Master").Visible = True
Sheets("Master").Copy After:=Worksheets(Worksheets.Count)
ActiveWindow.ActiveSheet.Name = NewDataName
End Sub

Create a new sheet from a template sheet

i have created a vba script which helps me to create new sheets in my workbook every time i enter a new column. What i want to change is to create a new sheet but copying a template sheet for that new sheet.
I basically create a "home sheet" where i will divide the curriculum into lessons, then i want the script to run and create a lesson plan sheet for each lesson. Please can someone help me with this?
Sub add()
Call CreateWorksheets(Sheets("Lesson List").Range("B2:XFD2"))
End Sub
Sub CreateWorksheets(Names_Of_Sheets As Range)
Dim No_Of_Sheets_to_be_Added As Integer
Dim Sheet_Name As String
Dim i As Integer
No_Of_Sheets_to_be_Added = Names_Of_Sheets.Columns.Count
For i = 1 To No_Of_Sheets_to_be_Added
Sheet_Name = Names_Of_Sheets.Cells(1, i).Value
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets.add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count)).Name = Sheet_Name
End If
Next i
End Sub
Function Sheet_Exists(WorkSheet_Name As String) As Boolean
Dim Work_sheet As Worksheet
Sheet_Exists = False
For Each Work_sheet In ThisWorkbook.Worksheets
If Work_sheet.Name = WorkSheet_Name Then
Sheet_Exists = True
End If
Next
End Function
My edited code with me trying to use the copy function:
Sub add()
Call CreateWorksheets(Sheets("Lesson List").Range("B2:XFD2"))
End Sub
Sub CreateWorksheets(Names_Of_Sheets As Range)
Dim No_Of_Sheets_to_be_Added As Integer
Dim Sheet_Name As String
Dim i As Integer
'determine the number of sheets to create
No_Of_Sheets_to_be_Added = Names_Of_Sheets.Columns.Count
For i = 1 To No_Of_Sheets_to_be_Added
'lable each sheet
Sheet_Name = Names_Of_Sheets.Cells(1, i).Value
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets("Lesson Plan Template").Copy After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count).Name = Sheet_Name
End If
Next i
End Sub
Function Sheet_Exists(WorkSheet_Name As String) As Boolean
Dim Work_sheet As Worksheet
Sheet_Exists = False
For Each Work_sheet In ThisWorkbook.Worksheets
If Work_sheet.Name = WorkSheet_Name Then
Sheet_Exists = True
End If
Next
End Function
Although i have not tidy up the error handling and my function as suggested i did follow the suggest of adding additional steps which gave me the desirable results:
Sub Add_New_Lesson()
Call Copy_Lesson_Template(Sheets("Lesson List").Range("B2:XFD2"))
End Sub
Sub Copy_Lesson_Template(Names_Of_Sheets As Range)
Dim No_Of_Sheets_to_be_Added As Integer
Dim Sheet_Name As String
Dim i As Integer
No_Of_Sheets_to_be_Added = Names_Of_Sheets.Columns.Count
For i = 1 To No_Of_Sheets_to_be_Added
Sheet_Name = Names_Of_Sheets.Cells(1, i).Value
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets("Lesson Template").Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = (Sheet_Name)
End If
Next i
End Sub
Function Sheet_Exists(WorkSheet_Name As String) As Boolean
Dim Work_sheet As Worksheet
Sheet_Exists = False
For Each Work_sheet In ThisWorkbook.Worksheets
If Work_sheet.Name = WorkSheet_Name Then
Sheet_Exists = True
End If
Next
End Function
Check out the following solution including some proper error handling.
Sub CreateWorksheets(Names_Of_Sheets As Range)
'determine the number of sheets to create
Dim No_Of_Sheets_to_be_Added As Long
With Names_Of_Sheets
No_Of_Sheets_to_be_Added = .Resize(ColumnSize:=1).Offset(ColumnOffset:=.Columns.Count - .Column + 1).End(xlToLeft).Column - .Column + 1
End With
Dim i As Long
For i = 1 To No_Of_Sheets_to_be_Added
Dim Sheet_Name As String
Sheet_Name = Names_Of_Sheets.Cells(1, i).Value
If Not Sheet_Exists(Sheet_Name) And Sheet_Name <> vbNullString Then
Dim TemplateCopy As Worksheet
Set TemplateCopy = Nothing 'initialize (needed because we are within a loop)
On Error Goto COPY_TEMPLATE_ERROR 'if error occurs throw message
Set TemplateCopy = Worksheets("Lesson Plan Template").Copy(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
On Error Goto 0 're-enable error handling!
If Not TemplateCopy Is Nothing Then 'check if the template copy exists
On Error Goto RENAME_COPY_ERROR
TemplateCopy.Name = Sheet_Name
On Error Goto 0 're-enable error handling!
End If
End If
Next i
Exit Sub
COPY_TEMPLATE_ERROR:
MsgBox "Template worksheet could not be copied."
Resume
RENAME_COPY_ERROR:
MsgBox "Template could not be renamed to '" & Sheet_Name & "'!"
'remove the template copy that could not be renamed (or you will have orphaned template copys)
Application.DisplayAlerts = False
TemplateCopy.Delete
Application.DisplayAlerts = True
Resume
End Sub
Make sure ActiveWorkbook is what you actually mean it to be:
ActiveWorkbook is the workbook that has focus (is on top of the other windows) while the code runs. This can easily change by a single mouse click.
ThisWorkbook is the workbook this VBA code is written in. It will never change. Use this over ActiveWorkbook when ever possible. This is much more reliable.
Note that if you work with multiple workbooks, every Worksheets or Sheets object needs to start with either ActiveWorkbook.Worksheets, ThisWorkbook.Worksheets or Workbooks("your-workbook-name.xlsm").Worksheets otherwise it is not clear for VBA which one of these you actually mean and it makes a guess (and it might guess wrong).
Finally the name of your function Sheet_Exists is a bit missleading because it only works for Worksheets as it is coded right now. Make sure you know the difference:
Sheets() contains all type of sheets: Worksheet, chart sheet, etc.
Worksheets() only contains sheets of type worksheet.
So your function should be called Worksheet_Exists
Function Worksheet_Exists(WorkSheet_Name As String) As Boolean
Dim Work_sheet As Worksheet
For Each Work_sheet In ThisWorkbook.Worksheets
If Work_sheet.Name = WorkSheet_Name Then
Worksheet_Exists = True
Exit Function 'if we found the name we don't need to check further worksheets
End If
Next Work_sheet
End Function
Or it needs to be changed to work for all type of sheets:
Function Sheet_Exists(Sheet_Name As String) As Boolean
Dim Sheet As Object
For Each Sheet In ThisWorkbook.Sheets
If Sheet.Name = Sheet_Name Then
Sheet_Exists = True
Exit Function 'if we found the name we don't need to check further sheets
End If
Next Sheet
End Function

Creating New Sheets with Names from a List

I am pretty new to VBA and am having an issue with my code. I have different hotel names from cell B4 to B27. My goal is to create new worksheets and name each one with the hotel names (going down the list). I tried running the sub procedure below but I am getting an error. The error says:
"Run-time error '1004': Application-defined or object-defined error"
It refers to the line below my comment. Any thoughts on why this is occurring and how I can fix this?
Sub sheetnamefromlist()
Dim count, i As Integer
count = WorksheetFunction.CountA(Range("B4", Range("B4").End(xlDown)))
i = 4
Do While i <= count
' next line errors
Sheets.Add(after:=Sheets(Sheets.count)).Name = Sheets("LocalList").Cells(i, 2).Text
i = i + 1
Loop
Sheets("LocalList").Activate
End Sub
Here is something that I quickly wrote
Few things
Do not find last row like that. You may want to see THIS
Do not use .Text to read the value of the cell. You may want to see What is the difference between .text, .value, and .value2?
Check if the sheet exists before trying to create one else you will get an error.
Is this what you are trying?
Option Explicit
Sub sheetnamefromlist()
Dim ws As Worksheet, wsNew As Worksheet
Dim lRow As Long, i As Long
Dim NewSheetName As String
'~~> Set this to the relevant worksheet
'~~> which has the range
Set ws = ThisWorkbook.Sheets("LocalList")
With ws
'~~> Find last row
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
'~~> Loop through the range
For i = 4 To lRow
NewSheetName = .Cells(i, 2).Value2
'~~> Check if there is already a worksheet with that name
If Not SheetExists(NewSheetName) Then
'~~> Create the worksheet and name it
With ThisWorkbook
.Sheets.Add(After:=.Sheets(.Sheets.Count)).Name = NewSheetName
End With
End If
Next i
End With
End Sub
'~~> Function to check if the worksheet exists
Private Function SheetExists(shName As String) As Boolean
Dim shNew As Worksheet
On Error Resume Next
Set shNew = ThisWorkbook.Sheets(shName)
On Error GoTo 0
If Not shNew Is Nothing Then SheetExists = True
End Function
My assumptions
All cells have valid values i.e which can be used for sheet names. If not, then you will have to handle that error as well.
Workbook (not worksheet) is unprotected
Try,
Sub test()
Dim vDB As Variant
Dim rngDB As Range
Dim Ws As Worksheet, newWS As Worksheet
Dim i As Integer
Set Ws = Sheets("LocalList")
With Ws
Set rngDB = .Range("b4", .Range("b4").End(xlDown))
End With
vDB = rngDB 'Bring the contents of the range into a 2D array.
For i = 1 To UBound(vDB, 1)
Set newWS = Sheets.Add(after:=Sheets(Sheets.Count))
newWS.Name = vDB(i, 1)
Next i
End Sub
Create Worksheets from List
The following will create (and count) only worksheets with valid names.
When the worksheet is already added and the name is invalid, it will be deleted (poorly handled, but it works.)
It is assumed that the list is contiguous (no empty cells).
The Code
Option Explicit
Sub SheetNameFromList()
Const wsName As String = "LocalList"
Const FirstCell As String = "B4"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim ListCount As Long
ListCount = WorksheetFunction.CountA(ws.Range(FirstCell, _
ws.Range(FirstCell).End(xlDown)))
Dim fRow As Long: fRow = ws.Range(FirstCell).Row
Dim fCol As Long: fCol = ws.Range(FirstCell).Column
Dim i As Long, wsCount As Long
Do While i < ListCount
If addSheetAfterLast(wb, ws.Cells(fRow + i, fCol).Value) = True Then
wsCount = wsCount + 1
End If
i = i + 1
Loop
ws.Activate
MsgBox "Created " & wsCount & " new worksheet(s).", vbInformation
End Sub
Function addSheetAfterLast(WorkbookObject As Workbook, _
SheetName As String) _
As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = WorkbookObject.Worksheets(SheetName)
If Err.Number = 0 Then Exit Function
Err.Clear
WorkbookObject.Sheets.Add After:=WorkbookObject.Sheets(Sheets.count)
If Err.Number <> 0 Then Exit Function
Err.Clear
WorkbookObject.ActiveSheet.Name = SheetName
If Err.Number <> 0 Then
Application.DisplayAlerts = False
WorkbookObject.Sheets(WorkbookObject.Sheets.count).Delete
Application.DisplayAlerts = False
Exit Function
End If
addSheetAfterLast = True
End Function

populate combobox from another workbook

How can I populate a combobox from another workbook, assuming that my data are in a worksheet named "affectation" and the data are in the 1st column
My combobox is in a userform, to fill it from the activeworkbook I use this code :
Private Sub CommandButton1_Click()
Dim ws_Liste_affect As Worksheet
Set ws_Liste_affect = ActiveWorkbook.Worksheets("affectation")
Fin_Liste_affect = ws_Liste_affect.Range("A65530").End(xlUp).Row
For i = 2 To Fin_Liste_affect
UserForm1.ComboBox_affect.AddItem ws_Liste_affect.Range("A" & i)
Next
UserForm1.Show
End Sub
I wan to fill it from another workbook.
I (only) suppose that you need to populate a combo box using data from a sheet of another workbook. If my understanding is correct, please try the next code:
Private Sub CommandButton1_Click__()
Dim ws_Liste_affect As Worksheet, Fin_Liste_affect As Long, arr As Variant
Dim wbFullPath As String, wb As Workbook, boolFound As Boolean
wbFullPath = "C:\...\TheOtherWorkbook.xls"
For Each wb In Workbooks
If wb.FullName = wbfullname Then
Set ws_Liste_affect = wb.Worksheets("the other sheet")
boolFound = True: Exit For
End If
Next
If Not boolFound Then
Set wb = Workbooks.Open(vbfullpath)
Set ws_Liste_affect = wb.Worksheets("the other sheet")
End If
Fin_Liste_affect = ws_Liste_affect.Range("A" & Rows.count).End(xlUp).Row
arr = ws_liste.affect.Range("A2:A" & Fin_Liste_affect).Value
UserForm1.ComboBox_affect.List = arr
UserForm1.Show
End Sub

Sub GoFC() in module refering to more than one shtName-hyperlinked shapes to hidden sheets

completely new to VBA, would appreciate help with the following problem:
Currently using Sub GoFC() in module to hyperlink shapes on a worksheet ("Menu") to other hidden worksheets (shapes and worksheet text match)
I would like to use Sub GoFC() for shapes in more than one sheet, but the code refers only to one sheet by name. In other words I want for the worksheet "Menu" and worksheet "Menu2" to allow all the shapes in them to run the same macro.
I sincerely hope this makes sense.
This is the code in module:
Sub GoFC()
shtName=Sheets("Menu").Shapes(Application.Caller).TextFrame2.TextRange.Text
Sheets(shtName).Visible = True
Application.Goto Sheets(shtName).Range("A1")
End Sub
This is the code in the worksheet "Menu":
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim shtName As String
'shtName = Target.Name
If InStr(1, Target.SubAddress, "'") = 1 Then
Sh = Mid(Target.SubAddress, 2, Len(Target.SubAddress) - 5)
Else
Sh = Left(Target.SubAddress, InStr(1, Target.SubAddress, "!") - 1)
End If
Sheets(Sh).Visible = True
Sheets(Sh).Select
End Sub
Maybe like that
Sub GoFC()
Dim sht As Worksheet
Dim wb As Workbook
Dim shtName As String
Set wb = ActiveWorkbook
Set sht = wb.ActiveSheet
shtName = sht.Shapes(Application.Caller).TextFrame2.TextRange.Text
If Not wsExists(shtName, wb) Then wb.Sheets.Add.Name = shtName
wb.Sheets(shtName).Visible = True
wb.Sheets(shtName).Activate
wb.Sheets(shtName).Range("A1").Select
End Sub
Function wsExists(wsName As String, wb As Workbook) As Boolean
Dim ws
For Each ws In wb.Sheets
wsExists = (wsName = ws.Name): If wsExists Then Exit Function
Next ws
End Function

Resources