VBA for setting up the printing pages per sheet

Aurum1

New Member
Joined
Aug 7, 2024
Messages
1
Office Version
  1. 365
Platform
  1. Windows
Hello,
We in our group have to deal with soffisticated excels the GMP environment requires to print these excel sheets out also using formula view. This is quite a time consuming work. Therefore I have tried to wrtie a macro with chatgpt that helps to adjust the page for printing aoutomatically. So the first part translates the sheet into formula view, adjusts the column width automatically so that no formula is cut off, sets the printing area to the last used row and cell as well as implements headers and lines. This works surprizingly well:
Sub ShowFormulasAndAutoFitWithPrintAreaAndHeaders()
Dim ws As Worksheet
Dim formulaRange As Range
Dim lastRow As Long
Dim lastCol As Long
Dim printRange As Range
Dim minRow As Long
Dim maxRow As Long
Dim minCol As Long
Dim maxCol As Long
Dim rng As Range
Dim cell As Range
Dim cellData As Variant
Dim i As Long, j As Long

Application.ScreenUpdating = False ' Turn off screen updating to speed up the macro
Application.Calculation = xlCalculationManual ' Turn off automatic calculation to speed up the macro

On Error GoTo ErrorHandler ' Set up error handling

' Loop through all sheets in the workbook
For Each ws In ThisWorkbook.Worksheets
' Define the range where we will place the formulas as text
Set formulaRange = ws.UsedRange

' Iterate through each cell in the used range of the worksheet
For Each cell In formulaRange
' Check if the cell contains a formula
If cell.HasFormula Then
' Display the formula as text in the cell
cell.Value = "'" & cell.Formula
End If
Next cell

' AutoFit columns to adjust for the longest formula in each column
ws.UsedRange.Columns.AutoFit

' Adjust the columns further to remove excessive space
Dim col As Range
For Each col In ws.UsedRange.Columns
col.ColumnWidth = Application.WorksheetFunction.Max(col.ColumnWidth, 15) ' Minimum width for readability
Next col

' Check if UsedRange is valid and has content
If Not ws.UsedRange Is Nothing Then
' Initialize min and max values
minRow = ws.Rows.Count
maxRow = 1
minCol = ws.Columns.Count
maxCol = 1

' Use an array to check cells in the used range for formatting
cellData = ws.UsedRange.Value

For i = LBound(cellData, 1) To UBound(cellData, 1)
For j = LBound(cellData, 2) To UBound(cellData, 2)
If Not IsEmpty(cellData(i, j)) Or _
ws.Cells(i, j).DisplayFormat.Interior.ColorIndex <> xlNone Or _
ws.Cells(i, j).DisplayFormat.Borders(xlEdgeBottom).LineStyle <> xlNone Then
If i < minRow Then minRow = i
If i > maxRow Then maxRow = i
If j < minCol Then minCol = j
If j > maxCol Then maxCol = j
End If
Next j
Next i

' Define the print area based on the detected bounding box
If minRow <= maxRow And minCol <= maxCol Then
Set printRange = ws.Range(ws.Cells(minRow, minCol), ws.Cells(maxRow, maxCol))
ws.PageSetup.PrintArea = printRange.Address
Else
' If no valid print area found, set to empty range
ws.PageSetup.PrintArea = ""
End If

' Configure page setup to include headers, gridlines, and print settings
With ws.PageSetup
.PrintGridlines = True ' Print gridlines
.PrintHeadings = True ' Print row and column headings
.Orientation = xlPortrait ' or xlLandscape
.FitToPagesWide = 1
.FitToPagesTall = False ' Adjust as needed
End With
End If
Next ws

' Restore default settings
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

' Inform the user that the process is complete
MsgBox "Formulas displayed, columns auto-fitted, print area set, and headers included.", vbInformation
Exit Sub ' Exit before hitting the error handler

ErrorHandler:
' Restore default settings in case of error
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
MsgBox "An error occurred: " & Err.Description, vbExclamation
End Sub

Now comes the tricky part. i want the macro to go for each sheet and prepare it for printing. The logic should be fir the content to a din A4 page and scale down from 100% to 50% by looking if the content fits into the page or not. IF not than switch from portrait to landscape and repeate. If not than create two pages and go back to 100% and distribute the content evently to the two pages, if not than scale down to 95%, 90%...50%, if that does not work create three pages and distribute the content evenly 33% for each page. This however doe not work properly. Chatgpt is not able to create a logic that works. The pages are scaled to max view and often one column is displayed per page:
Sub OptimizeScaleAndDistributeSheets()
Dim ws As Worksheet
Dim printArea As Range
Dim contentWidth As Double
Dim contentHeight As Double
Dim pageWidth As Double
Dim pageHeight As Double
Dim numPagesWide As Integer
Dim numPagesTall As Integer
Dim bestScale As Double
Dim scalePercent As Double
Dim scaleList As Variant
Dim scaleIndex As Integer
Dim portraitPageWidth As Double
Dim portraitPageHeight As Double
Dim landscapePageWidth As Double
Dim landscapePageHeight As Double
Dim currentOrientation As XlPageOrientation
Dim fitFound As Boolean
Dim totalPages As Integer
Dim maxPages As Integer
Dim rowsPerPage As Long
Dim colsPerPage As Long
Dim lastRow As Long
Dim lastCol As Long

' DIN A4 dimensions in points
portraitPageWidth = Application.InchesToPoints(8.27)
portraitPageHeight = Application.InchesToPoints(11.69)
landscapePageWidth = Application.InchesToPoints(11.69)
landscapePageHeight = Application.InchesToPoints(8.27)

' Define scale list for distribution
scaleList = Array(100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50)

' Loop through each worksheet
For Each ws In ThisWorkbook.Worksheets
On Error Resume Next
If ws.PageSetup.PrintArea <> "" Then
Set printArea = ws.Range(ws.PageSetup.PrintArea)
contentWidth = printArea.Width
contentHeight = printArea.Height

bestScale = 100
currentOrientation = ws.PageSetup.Orientation
fitFound = False

' Try fitting the content on pages from 1 to N
For Each orientation In Array(xlPortrait, xlLandscape)
ws.PageSetup.Orientation = orientation

If orientation = xlPortrait Then
pageWidth = portraitPageWidth
pageHeight = portraitPageHeight
Else
pageWidth = landscapePageWidth
pageHeight = landscapePageHeight
End If

For scaleIndex = LBound(scaleList) To UBound(scaleList)
scalePercent = scaleList(scaleIndex)
If scalePercent < 50 Then Exit For ' Do not go below 50%
ws.PageSetup.Zoom = scalePercent

numPagesWide = Application.WorksheetFunction.RoundUp(contentWidth * (scalePercent / 100) / pageWidth, 0)
numPagesTall = Application.WorksheetFunction.RoundUp(contentHeight * (scalePercent / 100) / pageHeight, 0)

totalPages = numPagesWide * numPagesTall

If totalPages <= 1 Then
bestScale = scalePercent
currentOrientation = orientation
fitFound = True
Exit For
End If
Next scaleIndex

If fitFound Then Exit For
Next orientation

' Apply the best scale and orientation
ws.PageSetup.Zoom = bestScale
ws.PageSetup.Orientation = currentOrientation

' If more than one page, distribute content evenly across pages
If totalPages > 1 Then
ws.PageSetup.Zoom = False
ws.PageSetup.FitToPagesWide = numPagesWide
ws.PageSetup.FitToPagesTall = numPagesTall

' Adjust the fit to distribute the content evenly
If currentOrientation = xlPortrait Then
rowsPerPage = Application.WorksheetFunction.RoundUp(printArea.Rows.Count / numPagesTall, 0)
colsPerPage = Application.WorksheetFunction.RoundUp(printArea.Columns.Count / numPagesWide, 0)
Else
rowsPerPage = Application.WorksheetFunction.RoundUp(printArea.Rows.Count / numPagesWide, 0)
colsPerPage = Application.WorksheetFunction.RoundUp(printArea.Columns.Count / numPagesTall, 0)
End If

lastRow = printArea.Rows.Count
lastCol = printArea.Columns.Count

For i = 1 To numPagesTall
For j = 1 To numPagesWide
ws.PageSetup.PrintArea = ws.Range(ws.Cells((i - 1) * rowsPerPage + 1, (j - 1) * colsPerPage + 1), _
ws.Cells(Application.Min(i * rowsPerPage, lastRow), Application.Min(j * colsPerPage, lastCol))).Address
Next j
Next i
End If

' Notify user
Debug.Print "Sheet '" & ws.Name & "' optimized to " & totalPages & " pages with scale " & bestScale & "% in " & IIf(currentOrientation = xlPortrait, "portrait", "landscape") & " orientation."
Else
Debug.Print "Sheet '" & ws.Name & "' does not have a print area set."
End If

On Error GoTo 0
Next ws

MsgBox "Scaling and distribution optimizations are complete for all sheets.", vbInformation
End Sub

Any ideas how to improove the code?
Regards
Aurum
 

Excel Facts

Workdays for a market open Mon, Wed, Friday?
Yes! Use "0101011" for the weekend argument in NETWORKDAYS.INTL or WORKDAY.INTL. The 7 digits start on Monday. 1 means it is a weekend.

Forum statistics

Threads
1,223,880
Messages
6,175,154
Members
452,615
Latest member
bogeys2birdies

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top