PDA

View Full Version : My Approach to printing NSTableView




DavidCar
Jan 24, 2007, 11:24 AM
This is actually my answer to this question on Cocoa-Dev, but I couldn't see how to post a reply there. The existing replies mostly used HTML, and I didn't like that approach. I also couldn't find an answer I liked elsewhere on the internet.

http://lists.apple.com/archives/Cocoa-dev/2007/Jan/msg00801.html

I didn't want to learn HTML to print tabular data. This is the approach I took.

Essentially, I have a separate invisible window with a copy of the displayed NSTableView nested inside a custom NSView called MyPrintableBox. When MyPrintableBox is asked if it knowsPageRange, it calculates the needed pages from the number of rows in the table. When asked for RectForPage it returns the bounds rect but saves the page number for use in the dataSource methods. The dataSource method calls to MyPrintableBox use the dataSource methods of the displayed table to obtain the required data. Some NSTextFields associated with the displayed table needed to be duplicated near the invisible printed table, and these were updated at the time MyPrintableBox was passed to the print method. Some code here was only used while I was testing the approach with the printable window set as being visible. Of course, an NSView could be used instead of an NSBox,

I like this approach because I can initially use the same IB NSTableView and the dataSource methods used for the displayed table. I can later customize the appearance of the printed table to optimize it's printed appearance.


// Try box size w:600 h:760

@interface MyPrintableBox : NSBox {
int rows, pages, pageNum;
IBOutlet NSTextField *pageDisplay;
IBOutlet NSWindowController *dataSourceWindow;
IBOutlet NSTableView *PrintedTable;
BOOL doingPages;
}
@end

@implementation MyPrintableBox

// The print method in MyDocument requests a printable NSView from MyWindow.
// MyWindow Nib contains an extra invisible window with a copy of the displayed table nested
// within an NSBox of this custom class, MyPrintableBox. MyWindow returns MyPrintableBox
// as the printable NSView requested by MyDocument. MyWindow updates some duplicate
// NSTextFields in myPrintableBox before filling the request.
// The dataSource for the invisible table is MyPrintableBox.
// The dataSource for the displayed table is MyWindow, connected here to dataSourceWindow

int rowsPerPage = 35;

- (id) initWithCoder:(NSCoder *)decoder {
[super initWithCoder:decoder];
rows = 0;
pages = 1;
pageNum = 1;
doingPages = NO; // not needed, used for testing
return self;
}

- (void) calculatePages {
rows = [dataSourceWindow numberOfRowsInTableView:nil]; // nil is ok in my case
pages = (rows / rowsPerPage) + 1;
if (pages > 1)
if ((pages - 1) * rowsPerPage == rows)
pages = pages - 1;
}

- (BOOL) knowsPageRange:(NSRangePointer)range {
[pageDisplay setStringValue:@"Starting Pages"];
[self calculatePages];
range->location = 1;
range->length = pages;
doingPages = YES;
return YES;
}

- (NSRect) rectForPage:(int)page {
pageNum = page;
[pageDisplay setStringValue:[NSString stringWithFormat:@"Page %i of %i", page, pages]];
if (page == pages)
[PrintedTable reloadData]; // otherwise doesn't recall numberOfRowsInTableView
return [self bounds];
}

- (void) endDocument { // not needed, used for testing
[super endDocument];
doingPages = NO;
pageNum = 1;
[PrintedTable reloadData]; // otherwise doesn't recall numberOfRowsInTableView
[pageDisplay setStringValue:@"Finished Doing Pages"];
}

- (int) numberOfRowsInTableView:(NSTableView *)aTableView {
if (!doingPages) {
[self calculatePages];
pageNum = 1;
if (pageNum < pages) {
return rowsPerPage;
} else {
return (rows - ((pageNum - 1) * rowsPerPage));
}
} else if (pageNum < pages) {
return rowsPerPage;
} else
return (rows - ((pageNum - 1) * rowsPerPage));
}

- (id) tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
row:(int)rowIndex {
return [dataSourceWindow tableView:aTableView
objectValueForTableColumn:aTableColumn
row:(((pageNum - 1) * rowsPerPage) + rowIndex)];
}

@end



kainjow
Jan 24, 2007, 11:46 PM
Several comments:

1) CocoaDev.com is a wiki. They don't use HTML formatting for pages. Go read up on how to format your text: TextFormattingRules (http://www.cocoadev.com/index.pl?TextFormattingRules)

2) Didn't want to learn HTML? I don't know a single programmer who doesn't know HTML. You don't have to be a proficient XHTML 1.1 and CSS 3.0 scripter, but at least know basic HTML.

3) Please use the BBCode "code" tag if you're posting code samples on here (or on any forum). And while I'm at it, if you're posting code at CocoaDev, use %%BEGINCODE%% and %%ENDCODE%% around the code.

4) And finally, regarding your topic, I don't know why you'd ever want to print an actual NSTableView. NSTableView is a Mac OS X control that displays columned data. It isn't meant to be printed (although it can be). The printer != the screen. If you want printer functionality, format your data so it is made to fit on a page. Cocoa's documentation covers this. Yes, it may be a pain, but that's life ;)

DavidCar
Jan 25, 2007, 12:50 AM
Several comments:

1) CocoaDev.com is a wiki. They don't use HTML formatting for pages. Go read up on how to format your text: TextFormattingRules (http://www.cocoadev.com/index.pl?TextFormattingRules)

2) Didn't want to learn HTML? I don't know a single programmer who doesn't know HTML. You don't have to be a proficient XHTML 1.1 and CSS 3.0 scripter, but at least know basic HTML.

3) Please use the BBCode "code" tag if you're posting code samples on here (or on any forum). And while I'm at it, if you're posting code at CocoaDev, use %%BEGINCODE%% and %%ENDCODE%% around the code.

4) And finally, regarding your topic, I don't know why you'd ever want to print an actual NSTableView. NSTableView is a Mac OS X control that displays columned data. It isn't meant to be printed (although it can be). The printer != the screen. If you want printer functionality, format your data so it is made to fit on a page. Cocoa's documentation covers this. Yes, it may be a pain, but that's life ;)

Thanks for the suggestions. I've added the BBCode "code" tag, and corrected the initialization. In this case, it was a simple project that wasn't worth the pain of a greater effort.

sudhansusingh22
Jun 5, 2014, 03:55 AM
Hi David,
I am still not able to print table view data following your approach. It is still printing only the part of table view to page size. Can you please send me project snippets.
Thanks,

DavidCar
Jun 5, 2014, 11:56 AM
Hi David,
I am still not able to print table view data following your approach. It is still printing only the part of table view to page size. Can you please send me project snippets.
Thanks,

I wouldn't know where to find it now, in a 2007 project. sorry.