Tuesday, October 21, 2008

Taking the View to PDF example to the next step.

As promised, here are some enhancements to make the PDF of a view a little nicer on the eyes.

The example agent enclosed improves on the previous version by;

  • handling a view with one category or a flat view
  • handling a view that has hidden, icon and total detail columns
  • adding a header image (from SuperNTF)
  • adding a footer with page numbers
I thought about updating the Pdf Document Library to allow a bit better control of cell padding and border colours of tables. In the end I decided against it. I really wanted to use what I had already created to prove that even with limited functionality you can still produce something that looks good enough.

Remember, if you have complicated reports or want fine grained control then write directly to iText. I also wanted to demonstrate that the PDF generation side is the easy bit. This means that you can spend more time writing the domino parts and tweeking for your formats than writing the PDF stuff.

The code is attached here and extracts below.

// get the date time for the report

DateTime dt = session.createDateTime("Today");

dt.setNow();


// the generic data object

PdfData data = new PdfData();


// where to put the file

PdfDocumentConfig config = new PdfDocumentConfig("Text",

"ViewByTitle.pdf", "c:\\pdfs");


/*

* Set up some of the styles that

* we will use in the pdf document.

*/


// the style for the database and view title

Style styleViewTitle = new Style("viewTitle", Style.TYPEFACE_HELVETICA,

18);

styleViewTitle.setDecoration(Style.DECORATION_BOLD);

styleViewTitle.setAlign(Style.ALIGN_CENTER);

styleViewTitle.setBackgroundColour(232, 232, 232);

styleViewTitle.setColor(0, 94, 187);


// the style for the date stamp

Style styleDate = new Style("date", Style.TYPEFACE_HELVETICA, 10);

styleDate.setAlign(Style.ALIGN_RIGHT);

styleDate.setBackgroundColour(Color.RED);


// the style for the view column titles

Style styleColumnTitle = new Style("columnsTitle",

Style.TYPEFACE_HELVETICA, 12);

styleColumnTitle.setDecoration(Style.DECORATION_BOLD);

styleColumnTitle.setBackgroundColour(232, 232, 232);

styleColumnTitle.setColor(0, 94, 187);


// the style for the column categories

Style styleColumnCat = new Style("columnsCat", Style.TYPEFACE_HELVETICA,

12);

styleColumnCat.setDecoration(Style.DECORATION_BOLD);

styleColumnCat.setBackgroundColour(247, 247, 247);

styleColumnCat.setColor(255, 153, 0);


// the default style for the view data

Style styleViewDefault = new Style("default", Style.TYPEFACE_HELVETICA,

10);


/*

* set header image - used the image from the superNTF nsf

*/

HeaderImage headerImage = new HeaderImage();

headerImage.addImage("c:\\pdfs\\BrandBanner.gif");

headerImage.setImageScale(HeaderImage.IMAGE_NO_SCALE, false);


// create a header to write the date into

HeaderTwoColumns header = new HeaderTwoColumns(50, 50);

header.setLeftColumn(new CellElement("", styleDate));

header.setRightColumn(new CellElement(dt.getDateOnly(), styleDate));

header.setStyle(styleDate);

header.setHeight(100);


// create a footer

FooterTwoColumns footer = new FooterTwoColumns(50, 50);

footer.setLeftColumn(new CellElement(

"http://palmerweb.blogspot.com - http://www.scius.com.au"));

footer.setRightColumn(new CellElement("", styleDate));

footer.setStyle(styleViewDefault);

footer.setPageNum(new PageNumbersElement(styleDate));

footer.includePageNumbers(true,

FooterTwoColumns.PAGE_NUMBERS_RIGHT);


// getting the notes handles

AgentContext ctx = session.getAgentContext();

Database db = ctx.getCurrentDatabase();


// this is the view

View viewMembers = db.getView("vw-docsbytitle");

// read the columns to get the report headings

Vector cols = viewMembers.getColumns();


// filter out the columns that we are not interested in

// such as icons, hidden, total details and categories

Vector colsToRead = new Vector();

for (int x = 0; x < cols.size(); x++) {

ViewColumn col = (ViewColumn) cols.get(x);

if (col.isIcon() == false && col.isCategory() == false

&& col.isHidden() == false

&& col.isHideDetail() == false) {

colsToRead.add(col);

}

}


// create a table based on the number of columns

TableElement tb = new TableElement(colsToRead.size());


/*

* create the heading (repeating) rows for the table.

*/

// database and view title

RowElement rw = new RowElement();

CellElement title = new CellElement(db.getTitle() + " - "

+ viewMembers.getName() + "\n\n", styleViewTitle);

title.setCellspan((colsToRead.size()));

rw.addCell(title);

rw.setTableHeading(true);

tb.AddRow(rw);

// column headings

rw = new RowElement();

for (int x = 0; x < colsToRead.size(); x++) {

ViewColumn col = (ViewColumn) colsToRead.get(x);

rw

.addCell(new CellElement(col.getTitle() + "\n\n",

styleColumnTitle));

}

rw.setTableHeading(true);

tb.AddRow(rw);

/*

* populate the table with the view data

*/

ViewNavigator viewNav = viewMembers.createViewNav();

ViewEntry rowData = viewNav.getFirst();


while (!(rowData == null)) {


rw = new RowElement();

Vector viewCol = rowData.getColumnValues();


// check to see if this is a category

if (rowData.isCategory()) {


CellElement catCell = new CellElement("\n"

+ viewCol.get(1).toString() + "\n\n", styleColumnCat);

catCell.setCellspan(colsToRead.size());

rw.addCell(catCell);


} else if (rowData.isDocument()) {

for (int x = 0; x < colsToRead.size(); x++) {

ViewColumn col = (ViewColumn) colsToRead.get(x);

int pos = col.getPosition() - 1;

rw.addCell(new CellElement(viewCol.get(pos).toString(),

styleViewDefault));


}

}


tb.AddRow(rw);

rowData = viewNav.getNext(rowData);

}


// add the table to the data object

data.add(tb);


// overide the default layout

LayoutElement layout = new LayoutElement(LayoutElement.PAGESIZE_A4,

LayoutElement.ORIENTATION_LANDSCAPE, 10, 10, 10, 10, 40, 50);


// add the image to the layout

layout.setHeaderImage(headerImage);

layout.setFooter(footer);

layout.setHeader(header);


// configure with the config, data and layout

PdfDocument pdf = new PdfDocument(config, data, layout);


// go

pdf.createDocument();


You should be able to take the agent code and just change the view name and you'll have a nicer looking PDF of your views - providing you like the colours and images. In the course of building this examples I made a few assumptions about the number of categories, and location of hidden columns. You might need to tweek the agent code if your views have more than one category or have totals and hidden columns in different locations. Its not just a drop in and works for every scenario.

What's next ?

I guess a notes document to PDF would be a nice example, so that's what will be in the pipeline. However, impending work commitments mean that it's highly likely that it won't be in the near future.

3 comments:

  1. Thanks for this Tony...Really nice - esp your styling stuff. Will have alook at adapting some of my .pdf code having read your articles. If you want doc examples I have many, + lots of JFreechart stuff...great with iText.

    My webapps make a lot of .pdf's and I stupidly ran into JVM memory problems, because I assumed garbage collection was picking up my domino objects...Big mistake. It's worth pointing out the importance of recycle() to anyone using Java in domino.

    How goes domino down there in Sydney BTW? Up here in Darwin the Govt have moved from domino to an I.D. system...I think I might be the last NT domino developer left standing...Kind of lonely really!

    Rgds

    Nick

    ReplyDelete
  2. Hoppers,

    Thanks for the kind words. You're on the money with regards to recycling. It's been widely covered by other bloggers, so I've not much to add. JFreechart looks interesting, I saw the examples in the iText book and am thinking that I should extend the library to include a few simple graphs to get started with.

    re:Domino in Sydney, I see a couple of contracts coming up here and there on seek, but not a whole heap and seems mostly for older versions 6 & 7.

    I don't think that you are alone in being the last domino developer standing. I'd bet there are a few companies out there, who have one lonely ND developer keeping everything ticking along nicely.

    If you've seen the new stuff in the ND pipeline then you'll know that anything you can do to learn Java, Web Services (WSDLs), Javascript will stand you in good stead for future version of ND. The bonus is that it also is relevant for other technologies.

    ReplyDelete
  3. Anonymous11:47 pm

    Thanks Tony! I just want to thank you for your kindness and for sharing your experience. I was in a need of this PDF function to make printable reports of Notes view.
    I just did it by following the instructions above.
    Best regards,
    Rebecka

    ReplyDelete