sandeep
sandeep

Reputation: 19

Unable To Print Multipage Print Preview With NStableView Data Cocoa App

I want to Print NSTableVIew data as multi page print preview but print preview shows only first few records rest pages are empty.I am using below code to print NStableView data.

let printInfo = NSPrintInfo.shared
printInfo.paperSize = NSSize(width: self.reporttableview.frame.width , height: 800.00)
printInfo.verticalPagination = .automatic
let operation: NSPrintOperation = NSPrintOperation(view: self.reporttableview, printInfo: printInfo)
operation.printPanel.options.insert([.showsPaperSize, .showsOrientation])
operation.run()

Above code working fine with minimum records like 30 -40 rows but when record is around 100 or more than 100 its only print first few records and rest pages are empty.Any help will be really appreciated.I have attached tableview and Print preview screen shots for better understanding.

  1. TableView Records: Table view screen shot
  2. Print Preview: Print preview screen shot You can see in above screen shot only first few pages having records rest are empty.And if I scroll table view in that case whole print Preview is empty. Empty print preview screen shot

I am not able to understand what I am doing wrong.

Upvotes: 0

Views: 265

Answers (1)

Christopher Hull
Christopher Hull

Reputation: 81

I had the same problem. I believe it is caused by the method AppKit uses to display NSTableViews efficiently. This seems to optimise, i.e. reduce, the memory load of large NSTableViews by only generating display data for about 3 "pages" of the view. To get the entire NSTableView to print, set the NSTableView instance property var usesStaticContents: Bool { get set } to true before printing (and return its value to false once printing is completed). I have tested this successfully on a table of 33 x A4 landscape pages and it works fine (although it takes ~5 seconds before the print panel is displayed).

Here is the code that worked for me:

struct ReportsDetailView: View {
        
    @Binding var reportNodes: [ReportNode]
    @State private var viewToPrint = NSView()
    @State private var printing = false

    var body: some View {
        VStack {
            ReportsDetailTableVC(reportNodes: $reportNodes, viewToPrint: $viewToPrint, printing: $printing)
            HStack {
                Spacer()
                Button("Print Report") {
                    printing = true
                    let scale: CGFloat = 800/viewToPrint.frame.width
                    let printInfo = NSPrintInfo()
                    printInfo.horizontalPagination = .automatic
                    printInfo.verticalPagination = .automatic
                    printInfo.isVerticallyCentered = true
                    printInfo.isHorizontallyCentered = true
                    printInfo.printer = NSPrinter(name: NSPrinter.printerNames[0])!
                    printInfo.paperSize = NSSize(width: 595.28, height: 841.89)
                    printInfo.topMargin = 10
                    printInfo.bottomMargin = 10
                    printInfo.leftMargin = 10
                    printInfo.rightMargin = 10
                    printInfo.orientation = .landscape
                    printInfo.scalingFactor = scale
                    let printOperation = NSPrintOperation(view: viewToPrint, printInfo: printInfo)
                    printOperation.run()
                    printing = false
                }
                .disabled(printing)
            }
            .padding(10)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

struct ReportsDetailTableVC: NSViewControllerRepresentable {
    
    @Environment(\.colorScheme) var colorScheme
    
    @Binding var reportNodes: [ReportNode]
    @Binding var viewToPrint: NSView
    @Binding var printing: Bool
    
    func makeNSViewController(context: Context) -> some NSViewController {
        let reportsDetailVC = ReportsDetailTableViewController()
        return reportsDetailVC
    }
    
    func updateNSViewController(_ nsViewController: NSViewControllerType, context: Context) {
        guard let reportsDetailVC = nsViewController as? ReportsDetailTableViewController else {return}
        reportsDetailVC.setContents(reportNodes: reportNodes)
        if printing {
            reportsDetailVC.tableView.scrollRowToVisible(0)
            reportsDetailVC.tableView.usesStaticContents = true
            reportsDetailVC.tableView.appearance = NSAppearance(named: .aqua)
            reportsDetailVC.tableView.usesAlternatingRowBackgroundColors = false
        }
        else {
            reportsDetailVC.tableView.usesStaticContents = false
            reportsDetailVC.tableView.appearance = colorScheme == .light ? NSAppearance(named: .aqua) : NSAppearance(named: .darkAqua)
            reportsDetailVC.tableView.usesAlternatingRowBackgroundColors = true
        }
        DispatchQueue.main.async {viewToPrint = reportsDetailVC.tableView}
    }
}

Upvotes: 0

Related Questions