Get all Sheet Names of open workbook VBA - excel

I have the below macro which lists all the worksheet names in the current(host) workbook.
I would like to adapt this code so it targets an active/open workbook, which has its workbook name & extension referenced in cell C1.
range("C1").value
Please can someone let me know how I adapt the below code.
Sub ListSheets()
Dim ws As Worksheet
Dim x As Integer
x = 1
Sheets("Sheet1").Range("A:A").Clear
For Each ws In Worksheets
Sheets("Sheet1").Cells(x, 1) = ws.Name
x = x + 1
Next ws
End Sub

This should do the job but you don't need the extension of the workbook just the name.
Sub ListSheets()
Dim ws As Worksheet
Dim x As Integer
Dim wbk As Workbook
Dim wbkName As String
x = 1
wbkName = ThisWorkbook.Sheets("Sheet1").Range("C1").Value
ThisWorkbook.Sheets("Sheet1").Range("A:A").Clear
Set wbk = Application.Workbooks(wbkName)
For Each ws In wbk.Worksheets
ThisWorkbook.Sheets("Sheet1").Cells(x, 1) = ws.Name
x = x + 1
Next ws
End Sub

Sub ListSheets()
Dim inputwb As Workbook
Dim ws As Worksheet, source As Worksheet
Dim LRow As Long
' Change source sheet if it is NOT always the active worksheet
' or activate the source sheet first with Workbooks("NAME").Sheets(INDEX).Activate (not preferable)
Set source = ActiveSheet
On Error Resume Next
Set inputwb = Workbooks(Cells(1, 1).Value)
If err.Number <> 0 Then
MsgBox "Could not find workbook " & Cells(1, 1).Value & ". Subroutine execution stopped."
Exit Sub
End If
On Error GoTo 0
ThisWorkbook.Sheets("Sheet1").Range("A:A").Clear
LRow = 1
For Each ws In inputwb.Worksheets
ThisWorkbook.Sheets("Sheet1").Cells(LRow, 1) = ws.Name
LRow = LRow + 1
Next ws
End Sub

Related

Save Selected Sheets in another workbook

Wondering why I can't do :
For i = 1 To ThisWorkbook.Sheets.Count
If ThisWorkbook.Sheets(i).Name <> "DO NOT SAVE" Then ThisWorkbook.Sheets(i).Select Replace:=False
Next i
Selection.Copy
what would be the best way to save all sheets which does not match DO NOT SAVE name in another wb ?
Try this:
Sub Tester()
Dim ws As Worksheet, arr(), i As Long
ReDim arr(0 To ThisWorkbook.Worksheets.Count - 2)
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "DO NOT SAVE" Then
arr(i) = ws.Name
i = i + 1
End If
Next ws
Worksheets(arr).Copy
End Sub
A Reflection on the Sheets' Visibility
To export a single sheet to a new workbook, the sheet has to be visible.
To export multiple sheets (using an array of sheet names) to a new workbook, at least one of the sheets has to be visible, while very hidden sheets will not get exported (no error though).
In a given workbook, the following procedure will copy all its sheets, except the ones whose names are in a given array (Exceptions), to a new workbook if at least one of the sheets is visible.
Before copying, it will 'convert' the very hidden sheets to hidden and after the copying, it will 'convert' the originals and copies to very hidden.
Option Explicit
Sub ExportSheets( _
ByVal wb As Workbook, _
ByVal Exceptions As Variant)
Dim shCount As Long: shCount = wb.Sheets.Count
Dim SheetNames() As String: ReDim SheetNames(1 To shCount)
Dim sh As Object
Dim coll As Object
Dim Item As Variant
Dim n As Long
Dim VisibleFound As Boolean
Dim VeryHiddenFound As Boolean
For Each sh In wb.Sheets
If IsError(Application.Match(sh.Name, Exceptions, 0)) Then
Select Case sh.Visible
Case xlSheetVisible
If Not VisibleFound Then VisibleFound = True
Case xlSheetHidden ' do nothing
Case xlSheetVeryHidden
If Not VeryHiddenFound Then
Set coll = New Collection
VeryHiddenFound = True
End If
coll.Add sh.Name
End Select
n = n + 1
SheetNames(n) = sh.Name
End If
Next sh
If n = 0 Then
MsgBox "No sheet found.", vbExclamation
Exit Sub
End If
If Not VisibleFound Then
MsgBox "No visible sheet found.", vbExclamation
Exit Sub
End If
If n < shCount Then ReDim Preserve SheetNames(1 To n) ' n - actual count
If VeryHiddenFound Then ' convert to hidden
For Each Item In coll
wb.Sheets(Item).Visible = xlSheetHidden
Next Item
End If
wb.Sheets(SheetNames).Copy ' copy to new workbook
If VeryHiddenFound Then ' revert to very hidden
Dim dwb As Workbook: Set dwb = Workbooks(Workbooks.Count)
For Each Item In coll
wb.Sheets(Item).Visible = xlSheetVeryHidden
dwb.Sheets(Item).Visible = xlSheetVeryHidden
Next Item
End If
MsgBox "Sheets exported: " & n, vbInformation
End Sub
Sub ExportSheetsTEST()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
ExportSheets wb, Array("DO NOT SAVE")
End Sub
Alternatively you could use the following snippet:
Sub CopyWorkbook()
Dim i As Integer
For i = 1 To ThisWorkbook.Sheets.Count
If ThisWorkbook.Sheets(i).Name <> "DO NOT SAVE" Then
Dim rng As Range
Windows("SOURCE WORKBOOK").Activate
rng = ThisWorkbook.Sheets(i).Cells
rng.Copy Before:=Workbooks("TARGET WORKBOOK").Sheets(i)
End If
Next i
End Sub

Using worksheet position and range.value

I've got a code that generates a workbook by copying and moving selected worksheets into a new workbook.
The first page of this new workbook is a summary page. On this i want to pull data from the subsequent worksheets by using the range.value method.
However can I use this when referencing the worksheet location for example
Dim wb As Workbook, wbAll As Workbook
Dim ws As Worksheet
Set wbAll = Workbooks.Add
On Error Resume Next
For t = 1 To 100
Set wb = Workbooks("Book" & t)
For Each ws In wb.Sheets
ws.Move after:=wbAll.Sheets(Sheets.Count)
Next
Next
Workbooks("Book" & t).Activate
ActiveWorkbook.Sheets("Sheet1").Select
'compile worksheets into list
Dim wss As Worksheet
Dim x As Integer
On Error Resume Next
x = 17
Sheets("Sheet1").Range("c17:E46").ClearContents
For Each wss In ActiveWorkbook.Worksheets
If wss.Name <> "Sheet1" Then
Sheets("Sheet1").Cells(x, 3) = wss.Name
x = x + 1
End If
Next wss
'COMPILE COSTS
ActiveWorkbook.Sheet1.Range("C17").Value = ActiveWorkbook.Worksheet(2).Range("Q118").Value
ActiveWorkbook.Sheet1.Range("C18").Value = ActiveWorkbook.Worksheet(3).Range("Q118").Value
.
.
ActiveWorkbook.Sheet1.Range("C45").Value = ActiveWorkbook.Worksheet(30).Range("Q118").Value
ActiveWorkbook.Sheet1.Range("C46").Value = ActiveWorkbook.Worksheet(31).Range("Q118").Value
'Compile WBS
ActiveWorkbook.Sheet1.Range("D17").Value = ActiveWorkbook.Worksheet(2).Range("D10").Value
ActiveWorkbook.Sheet1.Range("D18").Value = ActiveWorkbook.Worksheet(3).Range("D10").Value
.
.
ActiveWorkbook.Sheet1.Range("D45").Value = ActiveWorkbook.Worksheet(30).Range("D10").Value
ActiveWorkbook.Sheet1.Range("D46").Value = ActiveWorkbook.Worksheet(31).Range("D10").Value
'Week Number name
ActiveWorkbook.Sheet1.Range("C10").Value = ActiveWorkbook.Worksheet(2).Range("D4").Value
'Supplier Name
ActiveWorkbook.Sheet1.Range("C12").Value = ActiveWorkbook.Worksheet(2).Range("D5").Value
This however gives me an error message of object defined error
This may help:
EDIT: updated to show using links instead of copying the values from the sheet.
Sub Tester()
Dim wb As Workbook, wbAll As Workbook
Dim ws As Worksheet
Dim wss As Worksheet
Dim x As Integer, wsSummary, t As Long
Set wbAll = Workbooks.Add
For t = 1 To 100
Set wb = Nothing
On Error Resume Next 'ignore any error
Set wb = Workbooks("Book" & t)
On Error GoTo 0 'cancel OERN as soon as possible
If Not wb Is Nothing Then
For Each ws In wb.Sheets
ws.Move after:=wbAll.Sheets(wbAll.Sheets.Count)
Next
End If
Next
'Workbooks("Book" & t).Activate 'not sure what this is for?
'ActiveWorkbook.Sheets("Sheet1").Select
'compile worksheets into list
x = 17
Set wsSummary = wbAll.Sheets("Sheet1")
wsSummary.Range("C17:E46").ClearContents
For Each wss In wbAll.Worksheets
If wss.Name <> wsSummary.Name Then
With wsSummary.Rows(x)
'.Cells(3).Value = wss.Name
InsertLink .Cells(5), wss.Range("A1"), "=SheetName({1})"
'.Cells(4).Value = wss.Range("Q118").Value
InsertLink .Cells(4), wss.Range("Q118") 'create a link
'.Cells(5).Value = wss.Range("D10").Value
InsertLink .Cells(5), wss.Range("D10")
'etc etc
End With
x = x + 1
End If
Next wss
End Sub
'UDF to return the sheet name
Function SheetName(c As Range)
Application.Volatile
SheetName = c.Parent.Name
End Function
'Insert a worksheet formula into a cell (rngDest), where the precedents
' are either a single cell/range or an array of cells/ranges (SourceRange)
' sTemplate is an optional string template for the formula
' eg. "=SUM({1},{2})" where {1} and {2} are ranges in SourceRange
' Empty template defaults to "={1}"
'Useage:
' InsertLink sht1.Range("A1"), Array(sht1.Range("B1"), sht1.Range("C1")), "=SUM({1},{2})"
Sub InsertLink(rngDest As Range, SourceRange As Variant, Optional sTemplate As String)
Dim i As Long, sAddress As String, arrTmp As Variant
If sTemplate = "" Then sTemplate = "={1}" 'default is a simple linking formula
'got a single range, or an array of ranges?
If TypeName(SourceRange) = "Range" Then
arrTmp = Array(SourceRange) 'make an array from the single range
Else
arrTmp = SourceRange 'use as-is
End If
'loop over the input range(s) and build the formula
For i = LBound(arrTmp) To UBound(arrTmp)
sAddress = ""
If rngDest.Parent.Name <> arrTmp(i).Parent.Name Then
sAddress = "'" & arrTmp(i).Parent.Name & "'!"
End If
sAddress = sAddress & arrTmp(i).Address(False, False)
sTemplate = Replace(sTemplate, "{" & CStr(i + 1) & "}", sAddress)
Next i
rngDest.Formula = sTemplate 'assign the formula
End Sub

VBA Excel duplicate the existing sheet with number based on the previous sheet duplicated

Regarding the last query:
VBA Excel add new sheet with number based on the previous sheet created
I would like to duplicate the existing sheet and then add it under the incremented number, although on the same basis as mentioned in my previous query. I want to have the sheet number based on the last sheet number created.
If I take into account for example this code:
Public Sub CreateSheet()
Dim wb As Workbook: Set wb = ActiveWorkbook
Dim ws As Worksheet
Dim startNmae As String: startName = "Area Map "
Dim counter As Integer: counter = 1
For Each ws In wb.Sheets
If Left(ws.Name, Len(startName)) = startName Then
counter = counter + 1
End If
Next was
Set ws = wb.Sheets.Copy
startName = startName & counter
ws.Name = startName
End Sub
I am getting an error: Expected function or variable
with debugger showing the line:
Set ws = wb.Sheets.Copy
The other approaches also weren't working
Sub Newsheets()
Dim wb As Workbook: Set wb = ActiveWorkbook
Dim ws As Worksheet
Dim startName As String: startName = "Area Map "
Dim counter As Integer: counter = 1
For Each ws In wb.Sheets
If Left(ws.Name, Len(startName)) = startName Then
counter = counter + 1
End If
Next was
Set ws = ThisWorkbook.Sheets("Area Map" & counter)
With was
.Copy After:=Sheets(Sheets.Count)
startName = startName & counter
.Name = startName
End With
End Sub
Now I am getting: Subscript out of range, for the following line
Set ws = ThisWorkbook.Sheets("Area Map" & counter)
The next option wasn't successful either:
Sub ConsecutiveNumberSheets2()
Dim ws As Worksheet, wb As Workbook
Dim i As Long
Dim startName As String: startName = "Area Map "
Dim counter As Integer: counter = 1
Set wb = ThisWorkbook
Set ws = wb.Sheets("Area Map 1")
For Each ws In wb.Sheets
If Left(ws.Name, Len(startName)) = startName Then
counter = counter + 1
End If
Next was
For i = 1 To Sheets.Count - (Sheets.Count - 1)
With Sheets("Area Map 1")
.Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = "Area Map" & counter + 1
.Select
End With
Next i
End Sub
I need to have the sheet copied under the incremented number. I would like to base the incrementation on the last existing number of the sheet. Is it possible?
One of the solution is base on total number of sheets with similar or the same name occurring throughout our workbook.
The solution can be found here:
https://www.extendoffice.com/documents/excel/5098-excel-vba-count-sheets-with-specific-name.html
If we determine the number of sheets with specific name, then copying them only once a few times won't be a problem.
The final code could look as follows:
Sub Consecutivesheetduplicate()
Dim wsr as Worksheet
Dim I As Long
Dim xCount As Integer
Set wsr = ThisWorkbook.Sheets("Area Map 1")
For I = 1 To ActiveWorkbook.Sheets.Count
If InStr(1, Sheets(I).Name, "Area") > 0 Then xCount = xCount + 1
Next
For I = 1 To Sheets.Count - (Sheets.Count - 1)
On Error Resume Next
With Sheets("Area Map 1")
.Copy After:=ActiveWorkbook.Sheets(wsr.Index + xCount + I)
ActiveSheet.Name = "Area Map " & xCount + 1
.Select
End With
Next I
End Sub

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

Counting the number of Worksheets with name that starts with specific text

I am trying to count the number of worksheets with similar names (e.g. all that start with "East").
Here's the code I'm using to count the sheets:
Dim wb As Workbook
Dim ws As Worksheet
Dim myTotal As Long
Dim wsTotal As Long
For Each wb In Workbooks
For Each ws In Worksheets
If ws.Name Like "20 Out of Court" & "*" Then myTotal = myTotal + 1
Next ws
Next wb
wsTotal = myTotal
Sometimes it doubles the worksheet total on certain machines.
Try Below codee :
Sub sample()
Dim wb As Workbook
Dim ws As Worksheet
Dim myTotal As Long
Dim wsTotal As Long
For Each wb In Workbooks
For Each ws In Worksheets
Debug.Print ws.Name
If InStr(1,left(ws.Name,4), "East", vbTextCompare) > 0 Then ' will check for start with "East"..
myTotal = myTotal + 1
End If
Next ws
Next wb
wsTotal = myTotal
End Sub

Resources