Blue Hornet
08-16-2004, 10:59 AM
Here's a modified Print Macro that I got from Smitty (pennysaver) when he posted it in answer to a question on MrExcel.com. (He won't take credit for it, saying that he picked it up himself somewhere. Whoever built it should take some credit!)
As Smitty posted it, the thing would only list Worksheets for printing, always dropped the user off at the last visible worksheet in the workbook, and exited ingloriously if started from a non-Worksheet. I wanted it to be able to print Chartsheets, and I think I have done that (but I have questions). I also trapped the error and showed the user a message for the times when the macro is started from a non-Worksheet.
What the macro does is set up a Dialogsheet with a form to record each printable sheet in the workbook, and a checkbox next to each. The user checks which sheets to print, OKs the dialog box, and the sheets are printed. Then the Dialogsheet is deleted from the workbook.
I think it can be improved some more, such as:
1. Ability to select the printer or print file for output, rather than the default printer;
2. How can I query for the Type of Sheet which is not a Worksheet? I've stumbled onto Sheet Type = 3 and Sheet Type = 4 for Charts, but why is there more than one Type for charts (depending on chart type, maybe?)?;
3. I'd like to selectively activate the 'batch printing' mode "Print all sheets with consecutive numbers", OR sheet-by-sheet, starting each page with '1', but I ran into problems when I tried to make that work, and gave it up pretty quickly.
In any case, it's a very cool tool! Thanks for posting it, Smitty.
Chris
Sub Special_Print()
' from MrExcel.com -- look at favorites
' http://www.mrexcel.com/board2/viewtopic.php?t=101102
Dim i As Integer
Dim TopPos As Integer
Dim SheetCount As Integer
Dim PrintDlg As DialogSheet
Dim CurrentSheet As Worksheet
Dim CurrentChart As Chart
Dim StartSheet As String
Dim cb As CheckBox
'Application.ScreenUpdating = False
' Check for protected workbook
If ActiveWorkbook.ProtectStructure Then
MsgBox "Workbook is protected.", vbCritical
Exit Sub
' Check for 'non-worksheet'
ElseIf ActiveSheet.Type <> xlWorksheet Then
MsgBox "You can only start this from a WorkSheet.", vbCritical
Exit Sub
End If
' Add a temporary dialog sheet
Set CurrentSheet = ActiveSheet
StartSheet = ActiveSheet.Name
Set PrintDlg = ActiveWorkbook.DialogSheets.Add
SheetCount = 0
' Add the checkboxes
TopPos = 40
For i = 1 To ActiveWorkbook.Sheets.Count
If Left(ActiveWorkbook.Sheets(i).Name, 6) = "Dialog" Then GoTo GetNextSheet
If ActiveWorkbook.Sheets(i).Type = xlWorksheet Then
Set CurrentSheet = ActiveWorkbook.Sheets(i)
GoTo GotWorksheet
ElseIf ActiveWorkbook.Sheets(i).Type = 3 _
Or ActiveWorkbook.Sheets(i).Type = 4 Then
Set CurrentChart = ActiveWorkbook.Sheets(i) 'Types 3 and 4 = Chart ... what else?
GoTo GotChart
Else
GoTo GetNextSheet
End If
' Skip empty sheets and hidden sheets
GotChart:
If CurrentChart.Visible Then
SheetCount = SheetCount + 1
PrintDlg.CheckBoxes.Add 78, TopPos, 150, 16.5
PrintDlg.CheckBoxes(SheetCount).Text = _
CurrentChart.Name
TopPos = TopPos + 13
GoTo GetNextSheet
End If
GotWorksheet:
If Application.CountA(CurrentSheet.Cells) <> 0 And _
CurrentSheet.Visible Then
SheetCount = SheetCount + 1
PrintDlg.CheckBoxes.Add 78, TopPos, 150, 16.5
PrintDlg.CheckBoxes(SheetCount).Text = _
CurrentSheet.Name
TopPos = TopPos + 13
End If
GetNextSheet:
Next i
' Move the OK and Cancel buttons
PrintDlg.Buttons.Left = 240
' Set dialog height, width, and caption
With PrintDlg.DialogFrame
.Height = Application.Max _
(68, PrintDlg.DialogFrame.Top + TopPos - 34)
.Width = 230
.Caption = "Select sheets to print"
End With
' Change tab order of OK and Cancel buttons
' so the 1st option button will have the focus
PrintDlg.Buttons("Button 2").BringToFront
PrintDlg.Buttons("Button 3").BringToFront
' Display the dialog box
CurrentSheet.Activate
Sheets(StartSheet).Activate
Application.ScreenUpdating = True
If SheetCount <> 0 Then
'Print as one print job (continuous page numbers)
' If PrintDlg.Show Then
' For Each cb In PrintDlg.CheckBoxes
' If cb.Value = xlOn Then
' Worksheets(cb.Caption).Select Replace:=False
' End If
' Next cb
' ActiveWindow.SelectedSheets.PrintOut copies:=1
' ActiveSheet.Select
' End If
'Print as separate print jobs
If PrintDlg.Show Then
For Each cb In PrintDlg.CheckBoxes
If cb.Value = xlOn Then
Sheets(cb.Caption).Activate
ActiveSheet.PrintOut
' ActiveSheet.PrintPreview 'for debugging
End If
Next cb
End If
Else
MsgBox "All worksheets are empty."
End If
' Delete temporary dialog sheet (without a warning)
Application.DisplayAlerts = False
PrintDlg.Delete
' Reactivate original sheet
Sheets(StartSheet).Activate
End Sub
As Smitty posted it, the thing would only list Worksheets for printing, always dropped the user off at the last visible worksheet in the workbook, and exited ingloriously if started from a non-Worksheet. I wanted it to be able to print Chartsheets, and I think I have done that (but I have questions). I also trapped the error and showed the user a message for the times when the macro is started from a non-Worksheet.
What the macro does is set up a Dialogsheet with a form to record each printable sheet in the workbook, and a checkbox next to each. The user checks which sheets to print, OKs the dialog box, and the sheets are printed. Then the Dialogsheet is deleted from the workbook.
I think it can be improved some more, such as:
1. Ability to select the printer or print file for output, rather than the default printer;
2. How can I query for the Type of Sheet which is not a Worksheet? I've stumbled onto Sheet Type = 3 and Sheet Type = 4 for Charts, but why is there more than one Type for charts (depending on chart type, maybe?)?;
3. I'd like to selectively activate the 'batch printing' mode "Print all sheets with consecutive numbers", OR sheet-by-sheet, starting each page with '1', but I ran into problems when I tried to make that work, and gave it up pretty quickly.
In any case, it's a very cool tool! Thanks for posting it, Smitty.
Chris
Sub Special_Print()
' from MrExcel.com -- look at favorites
' http://www.mrexcel.com/board2/viewtopic.php?t=101102
Dim i As Integer
Dim TopPos As Integer
Dim SheetCount As Integer
Dim PrintDlg As DialogSheet
Dim CurrentSheet As Worksheet
Dim CurrentChart As Chart
Dim StartSheet As String
Dim cb As CheckBox
'Application.ScreenUpdating = False
' Check for protected workbook
If ActiveWorkbook.ProtectStructure Then
MsgBox "Workbook is protected.", vbCritical
Exit Sub
' Check for 'non-worksheet'
ElseIf ActiveSheet.Type <> xlWorksheet Then
MsgBox "You can only start this from a WorkSheet.", vbCritical
Exit Sub
End If
' Add a temporary dialog sheet
Set CurrentSheet = ActiveSheet
StartSheet = ActiveSheet.Name
Set PrintDlg = ActiveWorkbook.DialogSheets.Add
SheetCount = 0
' Add the checkboxes
TopPos = 40
For i = 1 To ActiveWorkbook.Sheets.Count
If Left(ActiveWorkbook.Sheets(i).Name, 6) = "Dialog" Then GoTo GetNextSheet
If ActiveWorkbook.Sheets(i).Type = xlWorksheet Then
Set CurrentSheet = ActiveWorkbook.Sheets(i)
GoTo GotWorksheet
ElseIf ActiveWorkbook.Sheets(i).Type = 3 _
Or ActiveWorkbook.Sheets(i).Type = 4 Then
Set CurrentChart = ActiveWorkbook.Sheets(i) 'Types 3 and 4 = Chart ... what else?
GoTo GotChart
Else
GoTo GetNextSheet
End If
' Skip empty sheets and hidden sheets
GotChart:
If CurrentChart.Visible Then
SheetCount = SheetCount + 1
PrintDlg.CheckBoxes.Add 78, TopPos, 150, 16.5
PrintDlg.CheckBoxes(SheetCount).Text = _
CurrentChart.Name
TopPos = TopPos + 13
GoTo GetNextSheet
End If
GotWorksheet:
If Application.CountA(CurrentSheet.Cells) <> 0 And _
CurrentSheet.Visible Then
SheetCount = SheetCount + 1
PrintDlg.CheckBoxes.Add 78, TopPos, 150, 16.5
PrintDlg.CheckBoxes(SheetCount).Text = _
CurrentSheet.Name
TopPos = TopPos + 13
End If
GetNextSheet:
Next i
' Move the OK and Cancel buttons
PrintDlg.Buttons.Left = 240
' Set dialog height, width, and caption
With PrintDlg.DialogFrame
.Height = Application.Max _
(68, PrintDlg.DialogFrame.Top + TopPos - 34)
.Width = 230
.Caption = "Select sheets to print"
End With
' Change tab order of OK and Cancel buttons
' so the 1st option button will have the focus
PrintDlg.Buttons("Button 2").BringToFront
PrintDlg.Buttons("Button 3").BringToFront
' Display the dialog box
CurrentSheet.Activate
Sheets(StartSheet).Activate
Application.ScreenUpdating = True
If SheetCount <> 0 Then
'Print as one print job (continuous page numbers)
' If PrintDlg.Show Then
' For Each cb In PrintDlg.CheckBoxes
' If cb.Value = xlOn Then
' Worksheets(cb.Caption).Select Replace:=False
' End If
' Next cb
' ActiveWindow.SelectedSheets.PrintOut copies:=1
' ActiveSheet.Select
' End If
'Print as separate print jobs
If PrintDlg.Show Then
For Each cb In PrintDlg.CheckBoxes
If cb.Value = xlOn Then
Sheets(cb.Caption).Activate
ActiveSheet.PrintOut
' ActiveSheet.PrintPreview 'for debugging
End If
Next cb
End If
Else
MsgBox "All worksheets are empty."
End If
' Delete temporary dialog sheet (without a warning)
Application.DisplayAlerts = False
PrintDlg.Delete
' Reactivate original sheet
Sheets(StartSheet).Activate
End Sub