Good morning,
I am using the following code:
Sub CABsheet()
Dim i As Long
Dim xNumber As Long
Dim xName As String
Dim ws As Worksheet
Application.ScreenUpdating = False
Set ws = Sheets("CAB1")
xNumber = Sheets("NIM & BADGER").Range("R27").Value
For i = 1 To Number
ws.Copy After:=ActiveWorkbook.Sheets(ws.Index + i - 1)
ActiveSheet.Name = "CAB" & i + 1
Next
ws.Activate
Application.ScreenUpdating = True
End Sub
but I am getting an error saying, that the sheet under this name already exists.
when I use a bit changed code like this:
Sub CABsheet()
Dim i As Long
Dim xNumber As Long
Dim xName As String
Dim ws As Worksheet
Application.ScreenUpdating = False
Set ws = Sheets("CAB1")
xNumber = Sheets("NIM & BADGER").Range("R27").Value
For i = 2 To Number
ws.Copy After:=ActiveWorkbook.Sheets(ws.Index + (i - 2))
ActiveSheet.Name = "CAB" & (i + 1) + 2
Next
ws.Activate
Application.ScreenUpdating = True
End Sub
then an error is gone, and everything seems to be alright but...
... i am getting numeration from CAB5 onwards instead of CAB 2
If I change a bit of my code again...
For i = 2 To xNumber
ws.Copy After:=ActiveWorkbook.Sheets(ws.Index + (i - 1))
ActiveSheet.Name = "CAB" & i + 2
Next
then order is wrong.
The tabs are from CAB4 onwards.
I need them from CAB2 onwards.
I can't remove +2 because the debugger shows me an error, that the name already been taken.
What can I fix in this code?
In your very first code example you
Dim xNumber As Long
you set a value for it
xNumber = Sheets("NIM & BADGER").Range("R27").Value
and then you use the variable Number instead of xNumber in your loop:
For i = 2 To Number
The variable Number is not declared nor initialized with a value and therefore it is 0.
So this cannot work. Make sure you use Option Explicit so you get notified if you use a worng variable name that was not declared.
I also recommend not to use ActiveSheet
Option Explicit
Public Sub CABsheet()
Application.ScreenUpdating = False
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("CAB1")
Dim xNumber As Long
xNumber = ThisWorkbook.Worksheets("NIM & BADGER").Range("R27").Value
Dim i As Long
For i = 1 To xNumber
ws.Copy After:=ThisWorkbook.Sheets(ws.Index + i - 1)
ThisWorkbook.Sheets(ws.Index + i).Name = "CAB" & i + 1
Next
ws.Activate
Application.ScreenUpdating = True
End Sub
Before running the code:
After running the code:
You could also built in a test if the worksheet already exists and ask the user if it should be deleted:
Option Explicit
Public Sub CABsheet()
Application.ScreenUpdating = False
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("CAB1")
Dim xNumber As Long
xNumber = 10
Dim i As Long
For i = 1 To xNumber
ws.Copy After:=ThisWorkbook.Sheets(ws.Index + i - 1)
If WorksheetExists("CAB" & i + 1) Then
If MsgBox("Worksheet '" & "CAB" & i + 1 & "' already exists. Do you want to delete it?", vbExclamation + vbYesNo) = vbYes Then
Application.DisplayAlerts = False
ThisWorkbook.Sheets("CAB" & i + 1).Delete
Application.DisplayAlerts = True
ThisWorkbook.Sheets(ws.Index + i).Name = "CAB" & i + 1
End If
Else
ThisWorkbook.Sheets(ws.Index + i).Name = "CAB" & i + 1
End If
Next
ws.Activate
Application.ScreenUpdating = True
End Sub
Public Function WorksheetExists(ByVal WorksheetName As String, Optional ByVal InWorkbook As Workbook) As Boolean
If InWorkbook Is Nothing Then
Set InWorkbook = ThisWorkbook
End If
On Error Resume Next
Dim ws As Worksheet
Set ws = InWorkbook.Worksheets(WorksheetName)
On Error GoTo 0
WorksheetExists = Not ws Is Nothing
End Function
Related
I came across the below code when looking for ways to sequentially add sheets using VBA. This code works great and does exactly what I need it to do up until it reaches the 10th worksheet. Once it reaches the 10th sheet ( i.e., "Combined-10" ), it throws an error when attempting to advance to the 11th sheet etc. I'm fairly new to VBA and do not know how to correct this. I'm simply needing help fixing this issue so that the worksheet continues to advance to the next sequential sheet once it reaches sheet number 10. Any help would be much appreciated!
Link to original code:
Adding Sheets With Sequential Names
Adding Sheets With Sequential Names
Option Explicit
Sub GetAvailableSheeName()
Dim sht As Worksheet
Dim temp_sht
Dim sht_name, last_sht As String
Dim shtNumber
Dim temp_counter, loop_i, counter, num As Integer
Const Available_sht As String = "Combined-"
temp_counter = 0
For Each sht In ThisWorkbook.Worksheets
If LCase(Left(sht.name, Len(Available_sht))) = LCase(Available_sht) Then
shtNumber = Split(sht.name, "-")(1)
If IsNumeric(shtNumber) Then
If shtNumber > temp_counter Then
temp_counter = shtNumber
last_sht = sht.name
End If
Else
sht_name = sht.name
End If
Else
sht_name = sht.name
End If
Next sht
If temp_counter = 0 Then
ThisWorkbook.Sheets.Add(After:=Sheets(sht_name)).name = "Combined-1"
Else
ThisWorkbook.Sheets.Add(After:=Sheets(last_sht)).name = "Combined-" & temp_counter + 1
For loop_i = 1 To temp_counter + 1
For Each sht In ThisWorkbook.Worksheets
counter = 0
If LCase("Combined-") & loop_i = LCase(sht.name) Then
counter = 1
Exit For
End If
Next sht
If counter = 0 Then
If loop_i = 1 Then
ThisWorkbook.Sheets.Add(Before:=Sheets(1)).name = "Combined-" & loop_i
Else
num = loop_i - 1
ThisWorkbook.Sheets.Add(After:=Sheets("Combined-" & num)).name = "Combined-" & loop_i
End If
End If
Next loop_i
End If
End Sub
Add Worksheets With Sequential Names
Compact
Sub GetAvailableSheetName()
On Error GoTo ClearError
Dim ws As Worksheet
Dim n As Long
Dim wsName As String
Do
n = n + 1
wsName = "Combined-" & n
Set ws = ThisWorkbook.Worksheets(wsName)
Loop
WorksheetNaming:
On Error Resume Next
ThisWorkbook.Worksheets .Add(After:=ThisWorkbook _
.Sheets(ThisWorkbook.Sheets.Count)).Name = wsName
On Error GoTo 0
Exit Sub
ClearError:
Resume WorksheetNaming
End Sub
Argumented
Sub AddSequentialSheetNameTEST()
AddSequentialSheetName ThisWorkbook, "Combined-"
MsgBox "Added the worksheet '" & ActiveSheet.Name, vbInformation
End Sub
Sub AddSequentialSheetName( _
ByVal wb As Workbook, _
Optional ByVal Prefix As String = "Sheet", _
Optional ByVal Suffix As String = "")
On Error GoTo ClearError
Dim ws As Worksheet
Dim n As Long
Dim wsName As String
Do
n = n + 1
wsName = Prefix & n & Suffix
Set ws = wb.Worksheets(wsName)
Loop
WorksheetNaming:
On Error Resume Next
wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name = wsName
On Error GoTo 0
Exit Sub
ClearError:
Resume WorksheetNaming
End Sub
My Master Report in fold.xlsm has a range of file and corresponding worksheets with tab names that correspond to the client and the type of data on that tab (indicated by variables xWs_Tax, xWs_Ins, etc.)
After storing these it then opens the corresponding client workbook.(replaced with fname.xlsx below)
The code is supposed to delete all worksheets NOT matching these stored names that include the client number in them. But I can't seem to get it to work. Either it deletes all the tabs or it does nothing at all depending on how I fiddle with it. Does anything jump out at you below or am I using bad code maybe? Do I need to do more then just declare Dim xWs As Worksheet ?
Here is where the variables are stored:
Dim xWs_ins As String
Dim xWs_tax As String
Dim xWs_ucc As String
Dim xWs_loc As String
Dim rc As String
rc = Range("P40")
For i = 41 To (rc + 40)
Workbooks("Master Report in fold.xlsm").Activate
MsgBox$ Range("J" & i)
xWs_ins = Range("J" & i)
xWs_tax = Range("K" & i)
xWs_ucc = Range("L" & i)
xWs_loc = Range("M" & i)
Workbooks.Open filename:= for example "20 Investor Certification - Master Servicers.xlsx
Dim xWs As Worksheet
'' Application.ScreenUpdating = False
'' Application.DisplayAlerts = False
For Each xWs In Application.ActiveWorkbook
If xWs.Name <> xWs_ins And xWs.Name <> xWs_tax And xWs.Name <> xWs_ucc And xWs.Name <> xWs_loc Then
xWs.Delete
End If
Next
'' Application.DisplayAlerts = True
'' Application.ScreenUpdating = True
ActiveWorkbook.Save
Next i
Delete Unwanted Sheets
There are unclear 'items' addressed in OP's comments and marked with ??? in the code.
Option Explicit
Sub deleteUnwanted()
Dim swb As Workbook: Set swb = Workbooks("Master Report in fold.xlsm")
' The worksheet name is unknown??? ("Sheet1")
Dim sws As Worksheet: sws = swb.Worksheets("Sheet1")
Dim sCell As Range
Dim srg As Range
Dim dwb As Workbook
Dim dsh As Object ' There is no 'Sheet' object.
Dim dArr As Variant
Dim dshCount As Long
' The workbook and worksheet are unknown??? (sws)
Dim rc As String: rc = sws.Range("P40").Value
Application.ScreenUpdating = False
For i = 41 To (rc + 40)
n = 0
Set sCell = sws.Cells(i, "I")
Set dwb = Workbooks.Open(sCell.Value)
dshCount = dwb.Sheets.Count
ReDim dArr(1 To dshCount)
Set srg = sws.Columns("J:M").Rows(i)
For Each dsh In dwb.Sheets
If IsError(Application.Match(dsh.Name, srg, 0)) Then
n = n + 1
dArr(n) = dsh.Name
End If
Next
If n > 0 Then
ReDim Preserve dArr(1 To n)
Application.DisplayAlerts = False
dwb.Worksheets(dArr).Delete
Application.DisplayAlerts = True
End If
dwb.Close SaveChanges:=True
Next i
Application.ScreenUpdating = True
End Sub
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
Option Explicit
Sub ExtractDivFromAastocks()
Dim StockCode As String, Anchor As String
Dim ws As Worksheet
StockCode = "02800"
Anchor = "Announce Date"
Set ws = ExtractRawDivFromAastocks(StockCode)
Call CleanAastocksDiv(StockCode, ws)
End Sub
Private Function ExtractRawDivFromAastocks(StockCode As String)
Dim WsFound As Boolean
Dim i As Integer
WsFound = False
For i = 1 To Sheets.Count():
If Worksheets(i).Name = StockCode Then
WsFound = True
End If
If WsFound = True Then
Exit For
End If
Next i
If WsFound = True Then
Application.DisplayAlerts = False
Worksheets(StockCode).Delete
Application.DisplayAlerts = True
End If
Dim ws As Worksheet
Dim qt As QueryTable
Dim Website As String, Aastock As String
Aastock = "http://www.aastocks.com/en/stocks/analysis/dividend.aspx?symbol="
Website = Aastock & StockCode
Set ws = Sheets.Add(After:=Worksheets(Worksheets.Count()))
ws.Name = StockCode
Set qt = ws.QueryTables.Add( _
Connection:="URL;" & Website, _
Destination:=ws.Range("A1"))
With qt
.RefreshOnFileOpen = True
.Refresh
End With
Set ExtractRawDivFromAastocks = ws
End Function
Private Sub CleanAastocksDiv(StockCode As String, ws As Worksheet)
Dim StartRow As Integer
StartRow = Application.Match("Announce Date", ws.Range("A:A"), 0)
ws.Range("A1:" & _
ws.Cells(StartRow - 1, ws.Columns.Count()).Address).EntireRow.Delete
End Sub
The worksheet indeed has the string value in it, and I have no idea why the match fails. I have tried using the Match function on the sheet itself, it works. Could this be some kind of reference issues? The cell in the sheet doesn't seem to have weird whitespaces. It would be really great if anyone can help me with this:
Public Sub TestMe()
Dim ws As Worksheet: Set ws = Worksheets(1)
Dim StartRow As Variant
StartRow = Application.Match("Announce Date", ws.Range("A:A"), 0)
If IsError(StartRow) Then Exit Sub
If StartRow < 2 Then Exit Sub
ws.Range("A1:A" & StartRow - 1).EntireRow.Delete
End Sub
Declare StartRow as a Variant, because if Announce Date does not exist, it would return an error;
It can be checked with the IsError(StartRow) and exit if it is not the case;
If StartRow < 2 Exit Sub is needed to avoid a possible error if StartRow is 1;
I wrote this Access/VBA program. It works but only when I am not running other applications or few users are in the database. I need some ideas on streamlining the code. So it is not so system intensive. The program basically allows a user to pick a folder and then combines all worksheets in that folder in one excel document. My current idea is just to tell users to close all excel files when trying to run the program. Please Help:
Sub Excel_open()
Dim myXL As Excel.Application
Dim myXLS As Excel.Workbook
Const errExcelNotRunning = 429
On Error GoTo HandleIt
Set myXL = GetObject(, "Excel.application")
myXL.Visible = True
Set myXLS = myXL.Workbooks.Add
Call CombineWorkbooks(myXL)
HandleIt:
If Err.Number = errExcelNotRunning Then
Set myXL = CreateObject("Excel.Application")
Err.Clear
Resume Next
End If
End Sub
Sub CombineWorkbooks(myXL)
'Macro that combines the files into one folder
myXL.AskToUpdateLinks = False
myXL.DisplayAlerts = False
Dim CurFile As String, dirloc As String, strNamesheet As String
Dim DestWB As Workbook
Dim ws As Object ' allows for diffrent sheet types
'Add select the director function
dirloc = GetFolderName & "\" 'location of files not working want to select the file only
CurFile = Dir(dirloc & "*.xls*")
myXL.ScreenUpdating = False
myXL.EnableEvents = False
Set DestWB = Workbooks.Add(xlWorksheet)
Do While CurFile <> vbNullString
Dim OrigWB As Workbook
Set OrigWB = Workbooks.Open(FileName:=dirloc & CurFile, ReadOnly:=True)
'need to change a name active name is not doing it
CurFile = Left(CurFile, 4) ' This is no longer 29
'CurFile = Left(Left(CurFile, Len(CurFile) - 5), 29)
For Each ws In OrigWB.Sheets
ws.Copy After:=DestWB.Sheets(DestWB.Sheets.Count)
' Use the name to give the sheet a name
strNamesheet = Left((ws.Name), 25) & ";"
If OrigWB.Sheets.Count > 1 Then
DestWB.Sheets(DestWB.Sheets.Count).Name = strNamesheet & CurFile ' & ws.Index
Else
DestWB.Sheets(DestWB.Sheets.Count).Name = CurFile
End If
Next
OrigWB.Close SaveChanges:=False
CurFile = Dir
Loop
myXL.DisplayAlerts = False
DestWB.Sheets(1).Delete
myXL.DisplayAlerts = True
myXL.ScreenUpdating = True
myXL.EnableEvents = True
Set DestWB = Nothing
Call Delete_empty_Sheets(myXL)
Call Sort_Active_Book
MsgBox "Done"
'Call Xcombine_the_Matching
End Sub
Sub Delete_empty_Sheets(myXL)
'goes through all sheets and deletes
Reset_the_search:
For Each wsElement In Worksheets
If wsElement.Range("A2") = "" And wsElement.Range("B2") = "" Then
myXL.DisplayAlerts = False
wsElement.Delete
GoTo Reset_the_search
myXL.DisplayAlerts = True
End If
Next wsElement
End Sub
Sub Xcombine_the_Matching()
'I think I can make the order work
'change and transpose the array
Dim varStart As Variant
Dim wsCompare As Worksheet
Dim strMatch As String
'Dim varCompare As Variant
Dim strVareince As String
Dim strCurrentName As String
'you need to build a loop to solve this problem
For Each wsCompare In Worksheets
strVareince = Add_Array(Application.Transpose(wsCompare.Range("A1:Z1")))
For Each wsNompare In Worksheets
If wsNompare.Name <> strCurrentName Then
If strVareince = Add_Array(Application.Transpose(wsNompare.Range("A1:Z1"))) Then
MsgBox ("Matched with worksheet " & wsNompare.Name)
End If
End If
Next
Next
End Sub
Function array_to_string(x) As String
For Z = 1 To 26
array_to_string = array_to_string & x(Z, 1) & ";"
Next Z
End Function
Function GetFolderName(Optional OpenAt As String) As String
'Allows you to select the folder director that you want to combine
Dim lCount As Long
GetFolderName = vbNullString
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = OpenAt
.Show
For lCount = 1 To .SelectedItems.Count
GetFolderName = .SelectedItems(lCount)
Next lCount
End With
End Function
Function Add_Array(x) As String
'turns an excel document
For d = 1 To UBound(x)
Add_Array = Add_Array & x(d, 1)
Next d
End Function
Sub Read_data()
'this the
End Sub
Sub Sort_Active_Book()
Dim i As Integer
Dim j As Integer
Dim iAnswer As VbMsgBoxResult
'
' Prompt the user as which direction they wish to
' sort the worksheets.
'
iAnswer = MsgBox("Sort Sheets in Ascending Order?" & Chr(10) _
& "Clicking No will sort in Descending Order", _
vbYesNoCancel + vbQuestion + vbDefaultButton1, "Sort Worksheets")
For i = 1 To Sheets.Count
For j = 1 To Sheets.Count - 1
'
' If the answer is Yes, then sort in ascending order.
'
If iAnswer = vbYes Then
If UCase$(Sheets(j).Name) > UCase$(Sheets(j + 1).Name) Then
Sheets(j).Move After:=Sheets(j + 1)
End If
'
' If the answer is No, then sort in descending order.
'
ElseIf iAnswer = vbNo Then
If UCase$(Sheets(j).Name) < UCase$(Sheets(j + 1).Name) Then
Sheets(j).Move After:=Sheets(j + 1)
End If
End If
Next j
Next i
End Sub
You are passing your Excel Application object into your subroutines, but not using it fully, neither are you explicitly referencing the libraries:
Sub CombineWorkbooks(myXL)
Dim DestWB As Excel.Workbook ' <<<
Set DestWB = myXL.Workbooks.Add(xlWorksheet) ' <<<
End Sub
Run through your code and fix all of these first, then test & supply more feedback on what the precise symptoms of the problems are.