Consulting

Results 1 to 6 of 6

Thread: Creating a TOC for only visible tabs? Excel VBA

  1. #1

    Creating a TOC for only visible tabs? Excel VBA

    It's been a long time since my last visit, and I need some help...

    Can anyone tell me how one would modify the following code to only list visible sheets within the Table of Contents?

    [vba]Option Explicit

    Sub CreateTOC()
    'Declare all variables
    Dim ws As Worksheet, curws As Worksheet, shtName As String
    Dim nRow As Long, i As Long, N As Long, x As Long, tmpCount As Long
    Dim cLeft, cTop, cHeight, cWidth, cb As Shape, strMsg As String
    Dim cCnt As Long, cAddy As String, cShade As Long
    'Check if a workbook is open or not. If no workbook is open, quit.
    If ActiveWorkbook Is Nothing Then
    MsgBox "You must have a workbook open first!", vbInformation, "No Open Book"
    Exit Sub
    End If
    '-------------------------------------------------------------------------------
    cShade = 37 '<<== SET BACKGROUND COLOR DESIRED HERE
    '-------------------------------------------------------------------------------
    'Turn off events and screen flickering.
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    nRow = 4: x = 0
    'Check if sheet exists already; direct where to go if not.
    On Error Goto hasSheet
    Sheets("TOC").Activate
    'Confirm the desire to overwrite sheet if it exists already.
    If MsgBox("You already have a Table of Contents page. Would you like to overwrite it?", _
    vbYesNo + vbQuestion, "Replace TOC page?") = vbYes Then Goto createNew
    Exit Sub
    hasSheet:
    x = 1
    'Add sheet as the first sheet in the workbook.
    Sheets.Add before:=Sheets(1)
    Goto hasNew
    createNew:
    Sheets("TOC").Delete
    Goto hasSheet
    hasNew:
    'Reset error statment/redirects
    On Error Goto 0
    'Set chart sheet varible counter
    tmpCount = ActiveWorkbook.Charts.Count
    If tmpCount > 0 Then tmpCount = 1
    'Set a little formatting for the TOC sheet.
    ActiveSheet.Name = "TOC"
    With Sheets("TOC")
    .Cells.Interior.ColorIndex = cShade
    .Rows("4:65536").RowHeight = 16
    .Range("A1").Value = "Designed by VBAX"
    .Range("A1").Font.Bold = False
    .Range("A1").Font.Italic = True
    .Range("A1").Font.Name = "Arial"
    .Range("A1").Font.Size = "8"
    .Range("A2").Value = "Table of Contents"
    .Range("A2").Font.Bold = True
    .Range("A2").Font.Name = "Arial"
    .Range("A2").Font.Size = "24"
    .Range("A4").Select
    End With
    'Set variables for loop/iterations
    N = ActiveWorkbook.Sheets.Count + tmpCount
    If x = 1 Then N = N - 1
    For i = 2 To N
    With Sheets("TOC")
    'Check if sheet is a chart sheet.
    If IsChart(Sheets(i).Name) Then
    '** Sheet IS a Chart Sheet
    cCnt = cCnt + 1
    shtName = Charts(cCnt).Name
    .Range("C" & nRow).Value = shtName
    .Range("C" & nRow).Font.ColorIndex = cShade
    'Set variables for button dimensions.
    cLeft = .Range("C" & nRow).Left
    cTop = .Range("C" & nRow).Top
    cWidth = .Range("C" & nRow).Width
    cHeight = .Range("C" & nRow).RowHeight
    cAddy = "R" & nRow & "C3"
    'Add button to cell dimensions.
    Set cb = .Shapes.AddShape(msoShapeRoundedRectangle, _
    cLeft, cTop, cWidth, cHeight)
    cb.Select
    'Use older technique to add Chart sheet name to button text.
    ExecuteExcel4Macro "FORMULA(""=" & cAddy & """)"
    'Format shape to look like hyperlink and match background color (transparent).
    With Selection
    .ShapeRange.Fill.ForeColor.SchemeColor = 0
    With .Font
    .Underline = xlUnderlineStyleSingle
    .ColorIndex = 5
    End With
    .ShapeRange.Fill.Visible = msoFalse
    .ShapeRange.Line.Visible = msoFalse
    .OnAction = "Mod_Main.GotoChart"
    End With
    Else
    '** Sheet is NOT a Chart sheet.
    shtName = Sheets(i).Name
    'Add a hyperlink to A1 of each sheet.
    .Range("C" & nRow).Hyperlinks.Add _
    Anchor:=.Range("C" & nRow), Address:="#'" & _
    shtName & "'!A1", TextToDisplay:=shtName
    .Range("C" & nRow).HorizontalAlignment = xlLeft
    End If
    .Range("B" & nRow).Value = nRow - 2
    nRow = nRow + 1
    End With
    continueLoop:
    Next i
    'Perform some last minute formatting.
    With Sheets("TOC")
    .Range("C:C").EntireColumn.AutoFit
    .Range("A4").Activate
    End With
    'Turn events back on.
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    strMsg = vbNewLine & vbNewLine & "Please note: " & _
    "Charts will have hyperlinks associated with an object."
    'Toggle message box for chart existence or not, information only.
    If cCnt = 0 Then strMsg = ""
    MsgBox "Complete!" & strMsg, vbInformation, "Complete!"
    End Sub

    Public Function IsChart(cName As String) As Boolean
    'Will return True or False if sheet is a Chart sheet object or not.
    'Can be used as a worksheet function.
    Dim tmpChart As Chart
    On Error Resume Next
    'If not a chart, this line will error out.
    Set tmpChart = Charts(cName)
    'Function will be determined if the variable is now an Object or not.
    IsChart = IIf(tmpChart Is Nothing, False, True)
    End Function

    Private Sub GotoChart()
    'This routine written to be assigned to button Object for Chart sheets only
    'as Chart sheets don't have cell references to hyperlink to.
    Dim obj As Object, objName As String
    'With the button text as the Chart name, we use the Caller method to obtain it.
    Set obj = ActiveSheet.Shapes(Application.Caller)
    'The latter portion of the AlternativeText will give us the exact Chart name.
    objName = Trim(Right(obj.AlternativeText, Len(obj.AlternativeText) - _
    InStr(1, obj.AlternativeText, ": ")))
    'Then we can perform a standard Chart sheet Activate method using the variable.
    Charts(objName).Activate
    'Optional: zoom Chart sheet to fit screen.
    'Depending on screen resolution, this may need adjustment(s).
    ActiveWindow.Zoom = 80
    End Sub [/vba]

    This is brilliant code by [FONT='Calibri','sans-serif']Zack Barresse[/FONT] BTW!

    Or, if someone has a code that would work, I would be intereseted in seeing that as well.


    Thanks to all of you.

  2. #2
    Administrator
    VP-Knowledge Base
    VBAX Grand Master mdmackillop's Avatar
    Joined
    May 2004
    Location
    Scotland
    Posts
    14,489
    Location
    Try
    [VBA]
    Sub CreateTOC()
    'Declare all variables
    Dim ws As Worksheet, curws As Worksheet, shtName As String
    Dim nRow As Long, i As Long, N As Long, x As Long, tmpCount As Long
    Dim cLeft, cTop, cHeight, cWidth, cb As Shape, strMsg As String
    Dim cCnt As Long, cAddy As String, cShade As Long
    Dim Hidden As Boolean
    'Check if a workbook is open or not. If no workbook is open, quit.
    If ActiveWorkbook Is Nothing Then
    MsgBox "You must have a workbook open first!", vbInformation, "No Open Book"
    Exit Sub
    End If
    '-------------------------------------------------------------------------------
    cShade = 37 '<<== SET BACKGROUND COLOR DESIRED HERE
    '-------------------------------------------------------------------------------
    'Turn off events and screen flickering.
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    nRow = 4: x = 0
    'Check if sheet exists already; direct where to go if not.
    On Error GoTo hasSheet
    Sheets("TOC").Activate
    'Confirm the desire to overwrite sheet if it exists already.
    If MsgBox("You already have a Table of Contents page. Would you like to overwrite it?", _
    vbYesNo + vbQuestion, "Replace TOC page?") = vbYes Then GoTo createNew
    Exit Sub
    hasSheet:
    x = 1
    'Add sheet as the first sheet in the workbook.
    Sheets.Add before:=Sheets(1)
    GoTo hasNew
    createNew:
    Sheets("TOC").Delete
    GoTo hasSheet
    hasNew:
    'Reset error statment/redirects
    On Error GoTo 0
    'Set chart sheet varible counter
    tmpCount = ActiveWorkbook.Charts.Count
    If tmpCount > 0 Then tmpCount = 1
    'Set a little formatting for the TOC sheet.
    ActiveSheet.Name = "TOC"
    With Sheets("TOC")
    .Cells.Interior.ColorIndex = cShade
    .Rows("4:65536").RowHeight = 16
    .Range("A1").Value = "Designed by VBAX"
    .Range("A1").Font.Bold = False
    .Range("A1").Font.Italic = True
    .Range("A1").Font.Name = "Arial"
    .Range("A1").Font.Size = "8"
    .Range("A2").Value = "Table of Contents"
    .Range("A2").Font.Bold = True
    .Range("A2").Font.Name = "Arial"
    .Range("A2").Font.Size = "24"
    .Range("A4").Select
    End With
    'Set variables for loop/iterations
    N = ActiveWorkbook.Sheets.Count + tmpCount
    If x = 1 Then N = N - 1
    For i = 2 To N
    Hidden = False
    With Sheets("TOC")
    'Check if sheet is a chart sheet.
    If IsChart(Sheets(i).Name) Then
    '** Sheet IS a Chart Sheet
    cCnt = cCnt + 1
    shtName = Charts(cCnt).Name
    .Range("C" & nRow).Value = shtName
    .Range("C" & nRow).Font.ColorIndex = cShade
    'Set variables for button dimensions.
    cLeft = .Range("C" & nRow).Left
    cTop = .Range("C" & nRow).Top
    cWidth = .Range("C" & nRow).Width
    cHeight = .Range("C" & nRow).RowHeight
    cAddy = "R" & nRow & "C3"
    'Add button to cell dimensions.
    Set cb = .Shapes.AddShape(msoShapeRoundedRectangle, _
    cLeft, cTop, cWidth, cHeight)
    cb.Select
    'Use older technique to add Chart sheet name to button text.
    ExecuteExcel4Macro "FORMULA(""=" & cAddy & """)"
    'Format shape to look like hyperlink and match background color (transparent).
    With Selection
    .ShapeRange.Fill.ForeColor.SchemeColor = 0
    With .Font
    .Underline = xlUnderlineStyleSingle
    .ColorIndex = 5
    End With
    .ShapeRange.Fill.Visible = msoFalse
    .ShapeRange.Line.Visible = msoFalse
    .OnAction = "Mod_Main.GotoChart"
    End With
    Else
    '** Sheet is NOT a Chart sheet.
    If Sheets(i).Visible = True Then
    shtName = Sheets(i).Name
    'Add a hyperlink to A1 of each sheet.
    .Range("C" & nRow).Hyperlinks.Add _
    Anchor:=.Range("C" & nRow), Address:="#'" & _
    shtName & "'!A1", TextToDisplay:=shtName
    .Range("C" & nRow).HorizontalAlignment = xlLeft
    Else
    Hidden = True
    End If
    End If
    If Not Hidden Then
    .Range("B" & nRow).Value = nRow - 2
    nRow = nRow + 1
    End If
    End With
    continueLoop:
    Next i
    'Perform some last minute formatting.
    With Sheets("TOC")
    .Range("C:C").EntireColumn.AutoFit
    .Range("A4").Activate
    End With
    'Turn events back on.
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    strMsg = vbNewLine & vbNewLine & "Please note: " & _
    "Charts will have hyperlinks associated with an object."
    'Toggle message box for chart existence or not, information only.
    If cCnt = 0 Then strMsg = ""
    MsgBox "Complete!" & strMsg, vbInformation, "Complete!"
    End Sub
    [/VBA]
    MVP (Excel 2008-2010)

    Post a workbook with sample data and layout if you want a quicker solution.


    To help indent your macros try Smart Indent

    Please remember to mark threads 'Solved'

  3. #3
    Wow that was fast! Thank you very much!

    but, I get a compile error...

    "Sub or Function not defined"

    here:

    If IsChart(Sheets(i).Name) Then
    '** Sheet IS a Chart Sheet
    cCnt = cCnt + 1
    shtName = Charts(cCnt).Name
    .Range("C" & nRow).Value = shtName
    .Range("C" & nRow).Font.ColorIndex = cShade
    'Set variables for button dimensions.
    cLeft = .Range("C" & nRow).Left
    cTop = .Range("C" & nRow).Top
    cWidth = .Range("C" & nRow).Width
    cHeight = .Range("C" & nRow).RowHeight
    cAddy = "R" & nRow & "C3"
    'Add button to cell dimensions.
    Set cb = .Shapes.AddShape(msoShapeRoundedRectangle, _
    cLeft, cTop, cWidth, cHeight)
    cb.Select
    'Use older technique to add Chart sheet name to button text.
    ExecuteExcel4Macro "FORMULA(""=" & cAddy & """)"
    'Format shape to look like hyperlink and match background color (transparent).
    With Selection
    .ShapeRange.Fill.ForeColor.SchemeColor = 0
    With .Font
    .Underline = xlUnderlineStyleSingle
    .ColorIndex = 5
    End With
    .ShapeRange.Fill.Visible = msoFalse
    .ShapeRange.Line.Visible = msoFalse
    .OnAction = "Mod_Main.GotoChart"
    End With
    Else
    '** Sheet is NOT a Chart sheet.
    If Sheets(i).Visible = True Then
    shtName = Sheets(i).Name
    'Add a hyperlink to A1 of each sheet.
    .Range("C" & nRow).Hyperlinks.Add _
    Anchor:=.Range("C" & nRow), Address:="#'" & _
    shtName & "'!A1", TextToDisplay:=shtName
    .Range("C" & nRow).HorizontalAlignment = xlLeft
    Else
    Hidden = True
    End If
    End If
    If Not Hidden Then
    .Range("B" & nRow).Value = nRow - 2
    nRow = nRow + 1
    End If
    End With
    continueLoop:
    Next i
    'Perform some last minute formatting.
    With Sheets("TOC")
    .Range("C:C").EntireColumn.AutoFit
    .Range("A4").Activate
    End With
    'Turn events back on.
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    strMsg = vbNewLine & vbNewLine & "Please note: " & _
    "Charts will have hyperlinks associated with an object."
    'Toggle message box for chart existence or not, information only.
    If cCnt = 0 Then strMsg = ""
    MsgBox "Complete!" & strMsg, vbInformation, "Complete!"
    End Sub

  4. #4
    Administrator
    VP-Knowledge Base VBAX Grand Master mdmackillop's Avatar
    Joined
    May 2004
    Location
    Scotland
    Posts
    14,489
    Location
    I only changed this part of your code. This would not affect that line
    [VBA]
    '** Sheet is NOT a Chart sheet.
    If Sheets(i).Visible = True Then
    shtName = Sheets(i).Name
    'Add a hyperlink to A1 of each sheet.
    .Range("C" & nRow).Hyperlinks.Add _
    Anchor:=.Range("C" & nRow), Address:="#'" & _
    shtName & "'!A1", TextToDisplay:=shtName
    .Range("C" & nRow).HorizontalAlignment = xlLeft
    Else
    Hidden = True
    End If
    End If
    If Not Hidden Then
    .Range("B" & nRow).Value = nRow - 2
    nRow = nRow + 1
    End If

    [/VBA]
    MVP (Excel 2008-2010)

    Post a workbook with sample data and layout if you want a quicker solution.


    To help indent your macros try Smart Indent

    Please remember to mark threads 'Solved'

  5. #5
    Still having the same problem unfortunately.

    Could it be the dim hidden as boolean? I can't see how...

    Sorry to be a pain, I must be missing something. What you wrote looks as if it should work perfectly. I am sure I am doing something wrong on my end. All I did was cut and paste what you posted. I apologize.

    Thanks for your help. It is very much appreciated. I envy your skill!
    Brian

  6. #6
    Thank you mdmackillop! With your help, I got it to work. I've seen what you did to the original code, and I just modified it a slight differently than you did.

    Thank you so much for pointing me in the right direction! I can't thank you enough.

    Brian


    Here is the final mod:
    Option Explicit

    [VBA]Sub CreateTOC()
    'Declare all variables
    Dim ws As Worksheet, curws As Worksheet, shtName As String
    Dim nRow As Long, i As Long, N As Long, x As Long, tmpCount As Long
    Dim cLeft, cTop, cHeight, cWidth, cb As Shape, strMsg As String
    Dim cCnt As Long, cAddy As String, cShade As Long
    'Check if a workbook is open or not. If no workbook is open, quit.
    If ActiveWorkbook Is Nothing Then
    MsgBox "You must have a workbook open first!", vbInformation, "No Open Book"
    Exit Sub
    End If
    '-------------------------------------------------------------------------------
    cShade = 37 '<<== SET BACKGROUND COLOR DESIRED HERE
    '-------------------------------------------------------------------------------
    'Turn off events and screen flickering.
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    nRow = 4: x = 0
    'Check if sheet exists already; direct where to go if not.
    On Error GoTo hasSheet
    Sheets("TOC").Activate
    'Confirm the desire to overwrite sheet if it exists already.
    If MsgBox("You already have a Table of Contents page. Would you like to overwrite it?", _
    vbYesNo + vbQuestion, "Replace TOC page?") = vbYes Then GoTo createNew
    Exit Sub
    hasSheet:
    x = 1
    'Add sheet as the first sheet in the workbook.
    Sheets.Add before:=Sheets(1)
    GoTo hasNew
    createNew:
    Sheets("TOC").Delete
    GoTo hasSheet
    hasNew:
    'Reset error statment/redirects
    On Error GoTo 0
    'Set chart sheet varible counter
    tmpCount = ActiveWorkbook.Charts.Count
    If tmpCount > 0 Then tmpCount = 1
    'Set a little formatting for the TOC sheet.
    ActiveSheet.Name = "TOC"
    With Sheets("TOC")
    .Cells.Interior.ColorIndex = cShade
    .Rows("4:65536").RowHeight = 16
    .Range("A1").Value = "Designed by VBAX"
    .Range("A1").Font.Bold = False
    .Range("A1").Font.Italic = True
    .Range("A1").Font.Name = "Arial"
    .Range("A1").Font.Size = "8"
    .Range("A2").Value = "Table of Contents"
    .Range("A2").Font.Bold = True
    .Range("A2").Font.Name = "Arial"
    .Range("A2").Font.Size = "24"
    .Range("A4").Select
    End With
    'Set variables for loop/iterations
    N = ActiveWorkbook.Sheets.Count + tmpCount
    If x = 1 Then N = N - 1
    For i = 2 To N
    With Sheets("TOC")
    'Check if sheet is a chart sheet.
    If IsChart(Sheets(i).Name) Then
    '** Sheet IS a Chart Sheet
    cCnt = cCnt + 1
    shtName = Charts(cCnt).Name
    .Range("C" & nRow).Value = shtName
    .Range("C" & nRow).Font.ColorIndex = cShade
    'Set variables for button dimensions.
    cLeft = .Range("C" & nRow).Left
    cTop = .Range("C" & nRow).Top
    cWidth = .Range("C" & nRow).Width
    cHeight = .Range("C" & nRow).RowHeight
    cAddy = "R" & nRow & "C3"
    'Add button to cell dimensions.
    Set cb = .Shapes.AddShape(msoShapeRoundedRectangle, _
    cLeft, cTop, cWidth, cHeight)
    cb.Select
    'Use older technique to add Chart sheet name to button text.
    ExecuteExcel4Macro "FORMULA(""=" & cAddy & """)"
    'Format shape to look like hyperlink and match background color (transparent).
    With Selection
    .ShapeRange.Fill.ForeColor.SchemeColor = 0
    With .Font
    .Underline = xlUnderlineStyleSingle
    .ColorIndex = 5
    End With
    .ShapeRange.Fill.Visible = msoFalse
    .ShapeRange.Line.Visible = msoFalse
    .OnAction = "Mod_Main.GotoChart"
    End With
    Else
    '** Sheet is NOT a Chart sheet.
    If Sheets(i).Visible = True Then
    shtName = Sheets(i).Name
    'Add a hyperlink to A1 of each sheet.
    .Range("C" & nRow).Hyperlinks.Add _
    Anchor:=.Range("C" & nRow), Address:="#'" & _
    shtName & "'!A1", TextToDisplay:=shtName
    .Range("C" & nRow).HorizontalAlignment = xlLeft
    Else

    End If
    End If
    If Sheets(i).Visible = True Then
    .Range("B" & nRow).Value = nRow - 3
    nRow = nRow + 1
    Else
    End If
    End With
    continueLoop:
    Next i
    'Perform some last minute formatting.
    With Sheets("TOC")
    .Range("C:C").EntireColumn.AutoFit
    .Range("A4").Activate
    End With
    'Turn events back on.
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    strMsg = vbNewLine & vbNewLine & "Please note: " & _
    "Charts will have hyperlinks associated with an object."
    'Toggle message box for chart existence or not, information only.
    If cCnt = 0 Then strMsg = ""
    MsgBox "Complete!" & strMsg, vbInformation, "Complete!"
    End Sub

    Public Function IsChart(cName As String) As Boolean
    'Will return True or False if sheet is a Chart sheet object or not.
    'Can be used as a worksheet function.
    Dim tmpChart As Chart
    On Error Resume Next
    'If not a chart, this line will error out.
    Set tmpChart = Charts(cName)
    'Function will be determined if the variable is now an Object or not.
    IsChart = IIf(tmpChart Is Nothing, False, True)
    End Function

    Private Sub GotoChart()
    'This routine written to be assigned to button Object for Chart sheets only
    'as Chart sheets don't have cell references to hyperlink to.
    Dim obj As Object, objName As String
    'With the button text as the Chart name, we use the Caller method to obtain it.
    Set obj = ActiveSheet.Shapes(Application.Caller)
    'The latter portion of the AlternativeText will give us the exact Chart name.
    objName = Trim(Right(obj.AlternativeText, Len(obj.AlternativeText) - _
    InStr(1, obj.AlternativeText, ": ")))
    'Then we can perform a standard Chart sheet Activate method using the variable.
    Charts(objName).Activate
    'Optional: zoom Chart sheet to fit screen.
    'Depending on screen resolution, this may need adjustment(s).
    ActiveWindow.Zoom = 80
    End Sub
    [/VBA]

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •