I am a bit new to VBA still, I got this code from another post on this forum but its a bit old and hasn't had a reply for 3 years.
I am running into a problem, I have the sheet protected and a button to run the code. when the sheet it protected I get an error saying it cant be run on a protected sheet. If I remove the .SpecialCells(xlConstants) from the set shNames line it will run but then I get a type mismatch error on the line If Not Evaluate("ISREF('" & NmSTR & "'!A1)") And wsMASTER.Range("G" & Nm.Row).Value = "Proceed" Then. The code works fine when unprotected. Thanks for your help
I am running into a problem, I have the sheet protected and a button to run the code. when the sheet it protected I get an error saying it cant be run on a protected sheet. If I remove the .SpecialCells(xlConstants) from the set shNames line it will run but then I get a type mismatch error on the line If Not Evaluate("ISREF('" & NmSTR & "'!A1)") And wsMASTER.Range("G" & Nm.Row).Value = "Proceed" Then. The code works fine when unprotected. Thanks for your help
VBA Code:
Option Explicit
Sub EvalSheetSummaryContractor()
'Create copies of a template sheet using text on a master sheet in a specific column
Dim wsMASTER As Worksheet, wsTEMP As Worksheet, wasVISIBLE As Boolean
Dim shNAMES As Range, Nm As Range, NmSTR As String
Application.ScreenUpdating = False 'stops the screen updating and make the code run faster
With ThisWorkbook 'keep focus in this workbook
Set wsTEMP = .Sheets("Template") 'sheet to be copied
wasVISIBLE = (wsTEMP.Visible = xlSheetVisible) 'check if it's hidden or not
If Not wasVISIBLE Then wsTEMP.Visible = xlSheetVisible 'make it visible
Set wsMASTER = .Sheets("SUMMARY - CONTRACTORS") 'sheet with names
'range to find names to be checked
Set shNAMES = wsMASTER.Range("B4:B153").SpecialCells(xlConstants) 'or xlFormulas
For Each Nm In shNAMES 'check one name at a time
NmSTR = FixStringForSheetName(CStr(Nm.Text)) 'use UDF to create a legal sheetname
If Not Evaluate("ISREF('" & NmSTR & "'!A1)") And wsMASTER.Range("G" & Nm.Row).Value = "Proceed" Then 'if sheet does not exist and pre-requisite is proceed...
wsTEMP.Copy After:=Sheets("Ranking") '...create it from template
ActiveSheet.Name = NmSTR '...rename it
End If
Next Nm
'orders the sheets the same as they appear on the summary page
Dim MasterOrder As Collection
Set MasterOrder = New Collection
On Error Resume Next
For Each Nm In shNAMES 'checks one name at a time
MasterOrder.Add Sheets(Nm.Value), CStr(Nm.Value) 'checks where those sheets are in the master list
Next Nm
On Error GoTo 0
Dim i As Long
For i = 1 To MasterOrder.Count 'puts new sheets into a new collection
Sheets(MasterOrder(i).Name).Move After:=Sheets(.Sheets.Count) 'moves the sheets to the end of all other sheets in order they appear on the summary page
Next i
wsMASTER.Activate 'return to the master sheet
If Not wasVISIBLE Then wsTEMP.Visible = xlSheetHidden 'hide the template if necessary
Application.ScreenUpdating = True 'update screen one time at the end
End With
End Sub
Function FixStringForSheetName(shSTR As String) As String
'replace each forbidden character with something acceptable
shSTR = Replace(shSTR, ":", "")
shSTR = Replace(shSTR, "?", "")
shSTR = Replace(shSTR, "*", "")
shSTR = Replace(shSTR, "/", "-")
shSTR = Replace(shSTR, "\", "-")
shSTR = Replace(shSTR, "[", "(")
shSTR = Replace(shSTR, "]", ")")
'sheet names can only be 31 characters
FixStringForSheetName = Trim(Left(shSTR, 31))
End Function