PasteSpecial method of Range class failed when I added password protection - excel

The following macro works fine without the 1st and 3rd lines emphasised (i.e. password protection). When I add the code the macro works the first time but if I open the file again, it returns a run time error 'pastespecial method of range class failed' at the line second line emphasised. The purpose of the macro is to open a purchase order template, increment the purchase order number by one, complete a second log file with date, purchase order number and user name and re-save the purchase order template under a different file name:
Private Sub Workbook_Open()
If ThisWorkbook.ReadOnly Then
MsgBox "Please use dropdown arrow next to filename within SharePoint and select 'Edit in Microsoft Office Excel' instead."
ThisWorkbook.Close
End If
Range("L14") = Range("L14") + 1
ActiveWorkbook.Save
Range("L14").Copy
Workbooks.Open Filename:="\\ehfnp01\users\gminter\My Documents\PO Log Elite\PO Log Elite.xls"
Workbooks("PO Log Elite.xls").Activate
Dim lst As Long
With ActiveWorkbook.Sheets("Sheet1")
*.Unprotect Password:="2"*
lst = .Range("B" & Rows.Count).End(xlUp).Row + 1
**.Range("B" & lst).PasteSpecial xlPasteValuesAndNumberFormats**
End With
With ActiveWorkbook.Sheets("Sheet1")
lst = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & lst) = Now
End With
With ActiveWorkbook.Sheets("Sheet1")
lst = .Range("C" & Rows.Count).End(xlUp).Row + 1
.Range("C" & lst).Value = Environ("Username")
*.Protect Password:="2"*
End With
ActiveWorkbook.Save
ActiveWorkbook.Close
ThisFile = Application.DefaultFilePath & "\" & Range("G14").Value & Range("L14").Text
ActiveWorkbook.SaveAs Filename:=ThisFile
Range("L15") = Now
Range("E20").Value = Environ("Username")
ScreenUpdating = False
Set Rng = Intersect(ActiveSheet.UsedRange, Range("e20"))
For Each C In Rng
C.Value = StrConv(C.Value, vbUpperCase)
Next
ScreenUpdating = True
Cells.Locked = False
Range("G14:N15,E20:N20").Locked = True
ActiveSheet.Protect Password:="1"
Dim x As Integer
On Error Resume Next
With ActiveWorkbook.VBProject
For x = .VBComponents.Count To 1 Step -1
.VBComponents.Remove .VBComponents(x)
Next x
For x = .VBComponents.Count To 1 Step -1
.VBComponents(x).CodeModule.DeleteLines _
1, .VBComponents(x).CodeModule.CountOfLines
Next x
End With
On Error GoTo 0
End Sub
Any help would be greatly appreciated as I can't find any similar examples of this.

What happens when you explicitly declare your Objects/Variables and then work with them? That ways you do the copy just before you paste. This will ensure that the clipboard doesn't get cleared for any reason which Excel is unfortunately famous for...
Private Sub Workbook_Open()
Dim rng As Range
Dim newWb As Workbook, wb As Workbook
Dim lst As Long
If ThisWorkbook.ReadOnly Then
MsgBox "Please use dropdown arrow next to filename within SharePoint and select 'Edit in Microsoft Office Excel' instead."
ThisWorkbook.Close
Exit Sub '<~~ ?
End If
Set rng = ThisWorkbook.Sheets("Sheet1").Range("L14")
rng.Value = rng.Value + 1
ThisWorkbook.Save
Set newWb = Workbooks.Open(Filename:="\\ehfnp01\users\gminter\My Documents\PO Log Elite\PO Log Elite.xls")
Set wb = Workbooks("PO Log Elite.xls")
With wb.Sheets("Sheet1")
.Unprotect Password:="2"
lst = .Range("B" & .Rows.Count).End(xlUp).Row + 1
rng.Copy '<~~ Do the copy here
.Range("B" & lst).PasteSpecial xlPasteValuesAndNumberFormats
End With
'
'~~> Rest of the code
'
End Sub

Related

Why are deleted rows reappearing in an excel table when the filter in removed in VBA?

The VBA code I have has worked perfectly on two other machines and with several other worksheets without the data reappearing. I've created a macro that takes a master spreadsheet and creates a new spreadsheet for each school listed in the table. I just got a new laptop and installed Excel 365 on it. I copied the VBA code to the new machine, but when I ran it, each new worksheet still contained the data for all the schools, not just the school for that particular file. I stepped through the code, and the schools did delete, but when it got to the part where the filter was removed from the table ws.ListObjects("Data").AutoFilter.ShowAllData, all the deleted rows reappeared. I'm stumped on why this is happening - It didn't happen on the other two machines and other iterations of the file that I've used this macro on. I don't know if it's an Excel setting or a setting on this particular master file. The other two machines - one used Excel 365, and the other Excel 2016. The data is not part of PowerPivot and is not a PowerQuery, so the data only lives in the table in the worksheet.
Here is the macro:
Dim i As Integer, wb As Workbook, schools() As Variant, schools_to_delete() As Variant
Dim ws As Worksheet, rng As Range, dt As String
schools = SchoolsInList()
dt = MonthName(Month(Now)) & " " & Year(Now)
Set wb = ActiveWorkbook
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False
For i = 1 To UBound(schools)
wb.SaveCopyAs ("Galileo " & dt & " " & schools(i) & ".xlsx")
Workbooks.Open ("Galileo " & dt & " " & schools(i) & ".xlsx")
Workbooks("Galileo " & dt & " " & schools(i) & ".xlsx").Activate
Set ws = Sheets("Data")
ws.Activate
schools_to_delete = schools
schools_to_delete(i) = "x"
Set rng = ws.ListObjects("Data").DataBodyRange
With ws
.AutoFilterMode = False
ws.ListObjects("Data").Range.AutoFilter Field:=18, Criteria1:= _
Array(schools_to_delete), Operator:=xlFilterValues
ws.Range(rng.Address).SpecialCells(xlCellTypeVisible).Delete
.AutoFilterMode = False
ws.ListObjects("Data").AutoFilter.ShowAllData
End With
ActiveWorkbook.RefreshAll
Call SelectA1
ActiveWorkbook.Save
ActiveWorkbook.Close
Next i
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.DisplayAlerts = True
End Sub
Function SchoolsInList() As Variant
Dim schools() As String
Dim C As Collection
Dim r As Range
Dim i As Long
Dim last_row As Long
last_row = Cells(Rows.Count, 1).End(xlUp).Row
Set C = New Collection
On Error Resume Next
For Each r In Worksheets("Data").Range("R2:R" & last_row).Cells
C.Add r.Value, CStr(r.Value)
Next
On Error GoTo 0
ReDim A(1 To C.Count)
For i = 1 To C.Count
A(i) = C.Item(i)
Next i
SchoolsInList = A
End Function
Sub SelectA1()
Dim i As Long
For i = 1 To ActiveWorkbook.Sheets.Count
Sheets(i).Activate
ActiveWindow.ScrollColumn = 1
ActiveWindow.ScrollRow = 1
Range("A1").Select
Next i
ActiveWorkbook.Worksheets(2).Activate
End Sub
I found the problem - the .AutoFilterMode = False didn't actually clear the filters that had already been placed on the table in question. The visible data WAS deleted, but the data that was filtered before the macro was run remained, and when the ws.ListObjects("Data").AutoFilter.ShowAllData ran, it cleared the previous filter, showing the rows that had been filtered before. I added the .ShowAllData code to the beginning of the With statement to avoid the same problem at a future date.

How to dynamically change which column to filter?

I need to create copies of entire workbooks (as there are other sheets, formatting, etc. I want to preserve) and then delete out rows of data that do not equal the current cl.value. The column headers will always be in row 1. The worksheet can have a varying amount of columns (i.e. A:D, A:F, A:G, etc.) and the end user can select any column to split by.
Referencing a cell works but if try to make it dynamic (based on user selection mentioned above) in the following part of the code:
Workbooks.Open Filename:=FName
'Delete Rows
'REFERENCING ACTUAL CELL WORKS
'Range("A1").AutoFilter 1, "<>" & cl.Value
'BELOW DOES NOT WORK
Range(ColHead).AutoFilter 1, "<>" & cl.Value
I get a
Run-time error '1004': Method 'Range' of object'_Global' Failed
Full Code Below:
Sub DisplayUserFormSplitWb()
UserFormSplitWb.Show
End Sub
Private Sub BtnOK_Click()
Call SplitWbMaster.SplitWbToFiles
End Sub
Private Sub UserForm_Initialize()
Dim SplitOptions As Range
Set SplitOptions = ActiveSheet.Range("A1", ActiveSheet.Range("A1").End(xlToRight))
SplitWbCol.List = Application.Transpose(SplitOptions.Value)
End Sub
Sub SplitWbToFiles()
Dim cl As Range
Dim OrigWs As Worksheet
Dim Subtitle As String
Dim ColValue As String
Dim ColStr As String
Dim ColNum As Long
Set OrigWs = ActiveSheet
ColValue = UserFormSplitWb.SplitWbCol.Value
Set ColHead = Rows(1).Find(What:=ColValue, LookAt:=xlWhole)
Set OffCol = ColHead.Offset(1, 0)
ColStr = Split(ColHead.Address, "$")(1)
ColNum = ColHead.Column
If OrigWs.FilterMode Then OrigWs.ShowAllData
With CreateObject("scripting.dictionary")
For Each cl In OrigWs.Range(OffCol, OrigWs.Range(ColStr & Rows.Count).End(xlUp))
If Not .exists(cl.Value) Then
.Add cl.Value, Nothing
'Turn off screen and alerts
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Create workbook copy
FPath = "U:\"
Subtitle = UserFormSplitWb.SplitWbSubtitle.Value
FName = FPath & cl.Value & "_" & Subtitle & ".xlsx"
ActiveWorkbook.SaveCopyAs Filename:=FName
Workbooks.Open Filename:=FName
'Delete Rows
'REFERENCING ACTUAL CELL WORKS
'Range("A1").AutoFilter 1, "<>" & cl.Value
'BELOW DOES NOT WORK
Range(ColHead).AutoFilter 1, "<>" & cl.Value
ActiveSheet.ListObjects(1).DataBodyRange.Delete
Range(ColHead).AutoFilter
Range(ColHead).AutoFilter
'Rename sheet
ActiveSheet.Name = Left(cl.Value, 31)
'Refresh save and close
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close False
End If
Next cl
End With
Application.ScreenUpdating = True
Application.DisplayAlerts = True
MsgBox "Splitting is complete. Please check your Computer (U:) drive.", vbOKOnly, "Run Macro"
End Sub
To anyone who might stumble upon this question -
I have found that using the below code solves my issue:
ActiveSheet.Range("A1", ActiveSheet.Range("A1").End(xlToRight)).AutoFilter ColNum, "<>" & cl.Value
where:
Dim ColNum As Long
ColNum = ColHead.Column

Code Runs Only If Visual Basic Editor is Open

I have a really weird problem about VBA.
I tried to list circular references at activeworkbook and i have written below code for that. It only works if i press ALT+F11. So if VBA Editor window is open, code runs correctly but otherwise it is not working.
By the way, code is in a module at Addin and i call it from ribbon. You may see the code below.
Your help is highly appreciated. Bruteforce solution works. I hope someone can find decent solution than me.
Type SaveRangeCir
Val As Variant
Addr As String
Preaddress As String
Shtname As String
Workbname As String
End Type
Public OldCir() As SaveRangeCir
Sub DonguselBasvurulariBul(control As IRibbonControl)
Dim wba As Workbook
Dim ws As Worksheet
Dim wsa As Worksheet
Dim sht As Worksheet
Dim sht2 As Worksheet
Dim dummy As Worksheet
Dim Item As Range
Dim crcell As Range
Dim cll As Range
un = "Sayin " & Environ("UserName")
muyarcirc = MsgBox("Lutfen Oncelikle Dosyanizi Kaydedin" & vbNewLine & vbNewLine & _
"-->> Dosyanizi Kaydettiniz mi?", vbExclamation + vbYesNo, un)
If muyarcirc = vbno Then
muyar2 = MsgBox("Dongusel Basvuru Arama Islemi Iptal Edildi", vbInformation, un)
Exit Sub
End If
'BruteForce Solution
With Application
.DisplayAlerts = False
.ScreenUpdating = False
.EnableEvents = False
.VBE.MainWindow.Visible = True
.Wait Now + TimeValue("00:00:01")
.VBE.MainWindow.Visible = False
End With
On Error Resume Next
Set wba = ActiveWorkbook
Set wsa = wba.ActiveSheet
wba.Worksheets.Add
Set dummy = ActiveSheet
For Each sht2 In wba.Sheets
If sht2.Name = "Dongusel Basvurular" Then
sht2.Delete
End If
Next sht2
wba.Worksheets.Add
Set ws = wba.ActiveSheet
dummy.Delete
With ws
.Name = "Dongusel Basvurular"
.Range("A1") = "Dongusel Basvuru Hucresi"
.Range("B1") = "Dongusel Basvuru Hucresi Formul Degeri"
.Range("C1") = "Bagli Oldugu Alan"
.Range("D1") = "Bulundugu Sayfa"
.Range("E1") = "Bulundugu Dosya"
End With
With wba
For Each sht In .Worksheets
If sht.CodeName <> ws.CodeName Then
sht.Activate
crcell = Nothing
Do
Set crcell = sht.CircularReference
If Not crcell Is Nothing Then
ReDim Preserve OldCir(1 To crcell.Precedents.Cells.Count)
i = 0
For Each cll In crcell.Precedents
i = i + 1
OldCir(i).Addr = cll.Address
OldCir(i).Val = cll.Formula
OldCir(i).Preaddress = cll.Precedents.Address
OldCir(i).Shtname = cll.Parent.Name
OldCir(i).Workbname = cll.Parent.Parent.Name
cll.Value = cll.Value
Next cll
For j = LBound(OldCir) To UBound(OldCir)
lr = ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ws.Cells(lr, 1) = OldCir(j).Addr
ws.Cells(lr, 2) = "'" & OldCir(j).Val
ws.Cells(lr, 3) = OldCir(j).Preaddress
ws.Cells(lr, 4) = OldCir(j).Shtname
ws.Cells(lr, 5) = OldCir(j).Workbname
ws.Hyperlinks.Add Anchor:=ws.Cells(lr, 1), Address:="", SubAddress:=ws.Cells(lr, 4) & "!" & ws.Cells(lr, 1), _
ScreenTip:="Dongusel Basvuru Hucresini Gormek icin Tiklayiniz"
Next j
Else
GoTo skipsheet
End If
Erase OldCir
Set crcell = sht.CircularReference
Loop While crcell.Cells.Count > 0
lr2 = ws.Cells(Rows.Count, 1).End(xlUp).Row
For m = 2 To lr2
If ActiveSheet.Name <> ws.Cells(lr2, "D") Then
wba.Sheets(ws.Cells(m, "D")).Activate
End If
Range(ws.Cells(m, 1)).Formula = "=" & Right(ws.Cells(m, 2), Len(ws.Cells(m, 2)) - 1)
Next m
End If
skipsheet:
Next sht
If ws.Range("A2") = "" Then
ws.Delete
wsa.Activate
m1 = MsgBox("Aktif Dosyada Dongusel Basvuru Bulunamadi", vbInformation, "Sayin " & Environ("UserName"))
Else
ws.Activate
ws.Range("A1:E1").EntireColumn.AutoFit
End If
End With
Erase OldCir
Set crcell = Nothing
With Application
.DisplayAlerts = True
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
I ran into a similar problem using VBA in MS Access. I understand you are using VBA Excel but I thought I'd post my personal experience in case it helps.
I have an Access form with a button that opens another form. The button is coded with VBA. If the VBA Editor was not open when I clicked the button then the new form would open but Form_Load() wouldn't trigger. If the VBA editor was open when I clicked the button then Form_Load() triggered as intended.
I did not have On Error Resume Next hiding any errors and all my variables were set with Option Explicit.
To troubleshoot the issue, I added a number of msgboxes throughout the code to narrow down where the problem was occurring. After adding a msgbox to the Click() event of the button I realized that the connection was somehow re-established and the code no longer needed the VBA editor open. After realizing this, I deleted the msgbox from the code, closed the application, re-opened the application without the VBA editor and from then on the VBA executed as intended.
Unfortunately, I came upon a solution while troubleshooting so I cannot provide an explanation as to why this worked but sometimes an explanation is not needed as long as you get it working again!
Hope this helps.
I had the same problem
However, it appeared have been caused by first using a message box with no return variable, then extending it to include a return, ie ret = msgbox(
Deleted the message box, code worked, closed and saved the project, reopened and message box with return variable added and now it run even without the editor open.

VBA - Loop through files in a folder AND copy single cells as well as a range, if condition is met

I am currently using a piece of code to loop through files in a folder and copy certain cells from each file into a master list. There are a number of files being added into the folder every week. One of the columns in the master list includes the filenames of previously looped files. The code only loops through files that are not included in the filename list and therefore also have not previously been looped.
The code works really well and copies cells with satisfactory results however I now need to modify it to also copy a range of data (A20:H33 specifically) as well as meeting the above condition of not already being looped.
I have tried the following unsuccesfully:
Adding another varTemp to the code (As seen in the main code)
Adding a sub that can copy a range (However I have been unable to incorporate this into the code so it satisfies the not looped condition)
Using selection.copy and selection.paste however an error that I cannot workaround pops up ("Object doesn't support this property or method")
Here is the main code:
Option Explicit
Sub CopyFromFolderExample()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets(1)
Dim strFolder As String, strFile As String, r As Long, wb As Workbook
Dim varTemp(1 To 6) As Variant
Application.ScreenUpdating = False
strFolder = "D:\Other\folder\"
r = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
strFile = Dir(strFolder & "*.xl*")
Do While Len(strFile) > 0
If Not Looped(strFile, ws) Then
Application.StatusBar = "Reading data from " & strFile & "..."
Set wb = Workbooks.Add(strFolder & strFile)
With wb.Worksheets(1)
varTemp(1) = strFile
varTemp(2) = .Range("A13").Value
varTemp(3) = .Range("H8").Value
varTemp(4) = .Range("H9").Value
varTemp(5) = .Range("H37").Value
'varTemp(6) = .Range("A20:H33").Value
End With
wb.Close False
r = r + 1
ws.Range(ws.Cells(r, 1), ws.Cells(r, 6)).Formula = varTemp
End If
strFile = Dir
Loop
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub
Private Function Looped(strFile As String, ws As Worksheet) As Boolean
Dim Found As Range
Set Found = ws.Range("A:A").Find(strFile)
If Found Is Nothing Then
Looped = False
Else
Looped = True
End If
End Function
This is the snippet of code that when inserted into the main code just below tha last vartemp gives me the following error ("Object doesn't support this property or method")
.Range("A20:H33").Select
.Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ws.Activate
If ws.Range("A1") = "" Then
ws.Range("A1").Select
Selection.Paste
Else
Selection.End(xlDown).Offset(6, 0).Select
Selection.Paste
End If
Here is what I am trying to achieve:
I think that if you use a Range variable instead of a Variant to copy and paste the Range(A20:AH33) should get the job done.
Declare:
Dim rg as Range
Then replace this line of code:
varTemp(6) = .Range("A20:H33").Value
For this:
Set rg = .Range("A20:H33")
Then you can just Rg.Copy and paste whereaver you want.
Don't forget to "clear" the copybuffer after you paste the information:
Application.CutCopyMode = False
Avoid to use Selectionand Activate in your code, the reasons for it can be seen here:
How to avoid using Select in Excel VBA
and here:
https://www.businessprogrammer.com/power-excel-vba-secret-avoid-using-select/
This should do it. I've turned your array back to 5 elements, and the range is transferred separately. I've added a few new variables which you might want to give more meaningful names.
Sub CopyFromFolderExample()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets(1)
Dim strFolder As String, strFile As String, r As Long, wb As Workbook
Dim varTemp(1 To 5) As Variant, r1 As Long, r3 As Range
Application.ScreenUpdating = False
strFolder = "D:\Other\folder\"
strFile = Dir(strFolder & "*.xl*")
Do While Len(strFile) > 0
If Not Looped(strFile, ws) Then
Application.StatusBar = "Reading data from " & strFile & "..."
Set wb = Workbooks.Add(strFolder & strFile)
With wb.Worksheets(1)
varTemp(1) = strFile
varTemp(2) = .Range("A13").Value
varTemp(3) = .Range("H8").Value
varTemp(4) = .Range("H9").Value
varTemp(5) = .Range("H37").Value
Set r3 = .Range("A20:H33")
End With
With ws
r = .Range("A" & .Rows.Count).End(xlUp).Row + 1
r1 = .Range("F" & .Rows.Count).End(xlUp).Row + 1 'last used row in col F
.Range(.Cells(r, 1), .Cells(r, 5)).Value = varTemp
.Cells(r1, 6).Resize(r3.Rows.Count, r3.Columns.Count).Value = r3.Value 'transfer A20:H33
End With
wb.Close False
End If
strFile = Dir
Loop
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub

Excel macro infinite loop keeps asking for user's input and can't "step into" to debug

I am creating a few macros to do the following in Excel 2010:
1. Upon creating a new worksheet ask for what the user wants to name his/her worksheet and sets the new worksheet to the name provided; calls Sort_Active_Book and Rebuild_TOC in order
2. Sort_Active_Book: Asks the user if he/she wants to sort the workbook's worksheets in ascending/descending order and proceeds to do so.
3. Rebuild_TOC: Deletes the Table of Contents page and rebuilds it based on all the worksheets in the workbook minus the TOC itself.
My problem is Excel keeps asking me to input the name of the new worksheet to be created and does not progress any further in the code. I notice it manages to create the named worksheet and asks me if I would like to sort ascending or descending but then proceeds to ask me again the name of the new worksheet. Could anyone please point out how to fix this and provide a code fix (if possible) please?
What I have already
This code portion is from ThisWorkbook, this is what prompts the user for the name of the worksheet upon creation.
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Dim sName As String
Dim bValidName As Boolean
Dim i As Long
bValidName = False
Do While bValidName = False
sName = InputBox("Please name this new worksheet:", "New Sheet Name", Sh.Name)
If Len(sName) > 0 Then
For i = 1 To 7
sName = Replace(sName, Mid(":\/?*[]", i, 1), " ")
Next i
sName = Trim(Left(WorksheetFunction.Trim(sName), 31))
If Not Evaluate("ISREF('" & sName & "'!A1)") Then bValidName = True
End If
Loop
Sh.Name = sName
Call Sort_Active_Book
Call Rebuild_TOC
End Sub
These two macros are in "Module 1":
Sub Sort_Active_Book()
Dim TotalSheets As Integer
Dim p As Integer
Dim iAnswer As VbMsgBoxResult
' Move the TOC to the begining of the document.
Sheets("TOC").Move Before:=Sheets(1)
' Prompt the user as to 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 TotalSheets = 1 To Sheets.Count
For p = 2 To Sheets.Count - 1
' If the answer is Yes, then sort in ascending order.
If iAnswer = vbYes Then
If UCase$(Sheets(p).Name) = "TOC" Then
Sheets(p).Move Before:=Sheets(1)
ElseIf UCase$(Sheets(p).Name) > UCase$(Sheets(p + 1).Name) Then
Sheets(p).Move After:=Sheets(p + 1)
End If
' If the answer is No, then sort in descending order.
ElseIf iAnswer = vbNo Then
If UCase$(Sheets(p).Name) = "TOC" Then
Sheets(p).Move Before:=Sheets(1)
ElseIf UCase$(Sheets(p).Name) < UCase$(Sheets(p + 1).Name) Then
Sheets(p).Move After:=Sheets(p + 1)
End If
End If
Next p
Next TotalSheets
End Sub
and
Sub Rebuild_TOC()
Dim wbBook As Workbook
Dim wsActive As Worksheet
Dim wsSheet As Worksheet
Dim lnRow As Long
Dim lnPages As Long
Dim lnCount As Long
Set wbBook = ActiveWorkbook
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
' If the TOC sheet already exist delete it and add a new worksheet.
On Error Resume Next
With wbBook
.Worksheets(“TOC”).Delete
.Worksheets.Add Before:=.Worksheets(1)
End With
On Error GoTo 0
Set wsActive = wbBook.ActiveSheet
With wsActive
.Name = “TOC”
With .Range(“A1:B1”)
.Value = VBA.Array(“Table of Contents”, “Sheet # – # of Pages”)
.Font.Bold = True
End With
End With
lnRow = 2
lnCount = 1
' Iterate through the worksheets in the workbook and create sheetnames, add hyperlink
' and count & write the running number of pages to be printed for each sheet on the TOC.
For Each wsSheet In wbBook.Worksheets
If wsSheet.Name <> wsActive.Name Then
wsSheet.Activate
With wsActive
.Hyperlinks.Add .Cells(lnRow, 1), “”, _
SubAddress:=”‘” & wsSheet.Name & “‘!A1”, _
TextToDisplay:=wsSheet.Name
lnPages = wsSheet.PageSetup.Pages().Count
.Cells(lnRow, 2).Value = “‘” & lnCount & “-” & lnPages
End With
lnRow = lnRow + 1
lnCount = lnCount + 1
End If
Next wsSheet
wsActive.Activate
wsActive.Columns(“A:B”).EntireColumn.AutoFit
With Application
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub
You are creating a new sheet with sub Rebuild_TOC. Causing the newsheet macro to run again.
You will need to avoid running the newsheet macro by adding a enableevents = false and true surrounding your code when creating a new sheet for your TOC. The rest of your code appears to be working as you want it to.
Application.EnableEvents = False
With wbBook
.Worksheets("TOC").Delete
.Worksheets.Add Before:=.Worksheets(1)
End With
Application.EnableEvents = True
Why would you want to delete the TOC worksheet, why not just update it?

Resources