Resources

SAS® AppDev Studio 3.0 Developer's Site

TableView: Print to PDF   About It Build It  

Data Source: Other (Data is embedded within the example)

Step 1: Create a project in webAF

Create a new project named PDFPrintingApp. Select Application Project from the webAF Projects list. You can use all other default new project settings.

Note: The Swing/Application Project examples can also be run from an Applet Project. If you want to create an Applet Project, select Applet Project instead of Application Project from the Projects list. Please note that there are additional steps required for deploying your applet.

Step 2: Add components

  1. Add the components and arrange them as seen on the About It page.
  2. Create a new class that extends from the com.sas.swing.visuals.tableview.TableView class in order to support printing to PDF. The following steps will create and insert this class into the project:
    1. Select File [arrow] New.
    2. Select the Components tab, and then select Class in the list of options.
    3. For the class name field, type PDFPrintingTable. Click OK.
    4. In the Extends field, type com.sas.swing.visuals.tableview.TableView.
    5. In the Implements field, type com.sas.awt.print.PrintableInterface Click Next.
    6. Click Finish.
  3. Add the following import statements at the top of the file:
    import com.sas.swing.visuals.tableview.ColumnHeader;
    import com.sas.swing.visuals.tableview.RowHeader;
    import com.sas.swing.visuals.tableview.TableView;
    import java.awt.Component;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Panel;
    import java.awt.Rectangle;
    import java.util.ArrayList;
    import java.util.List;
    import javax.swing.SwingConstants;
    import javax.swing.table.TableColumnModel;
    
  4. The generated stub methods for the PrintableInterface now have to be deleted and replaced with the following code. Paste the following code between the braces for the class after you have deleted all the methods in the class:
    private Graphics graph;
    // Defined in com.sas.awt.print.PrintableInterface
    public java.awt.Panel getPrintOptionsPanel( )
    {
       //overwrite the following line with your own implementation
       return null;
    }
    
    // Defined in com.sas.awt.print.PrintableInterface
    public java.awt.Rectangle getPageBounds( java.awt.Graphics p1, int p2, int p3, int p4)
    {
       //overwrite the following line with your own implementation
       return null;
    }
    
    // Defined in com.sas.awt.print.PrintableInterface
    public void printInitialize( java.awt.Graphics p1)
       throws com.sas.awt.print.PrintException
    {
       graph = p1;
    }
    
    // Defined in com.sas.awt.print.PrintableInterface
    public boolean pageExists( int p1)
    {
       if (p1 == 1 && (getRowCount() > 0 && getColumnCount() > 0))
          return true;
    
       return printInfo.m_pages > (p1 - 1);
    }
    
    // Defined in com.sas.awt.print.PrintableInterface
    public void print(Graphics g, int pageIndex, int pageWidth, int pageHeight)
       throws com.sas.awt.print.PrintException
    {
       if (printInfo == null || !printInfo.pageDone)
       {
          getPageInfo(g, pageWidth, pageHeight);
       }
    
       g.setFont(printInfo.printFont);
    
       if (pageIndex - 1 >= printInfo.m_pages)
       {
          printInfo.pageDone = false;
          return;
       }
    
       if (printInfo.prevPageIndex != pageIndex - 1)
       {
          printInfo.subPageIndex++;
          if (printInfo.subPageIndex == printInfo.colSplits)
          {
             printInfo.subPageIndex = 0;
          }
       }
    
       int rowIndex = (pageIndex - 1) / (printInfo.colSplits);
    
       printSubTable(g, rowIndex, printInfo.subPageIndex);
       printInfo.prevPageIndex = pageIndex - 1;
    
       return;
    }
    
    // Defined in com.sas.awt.print.PrintableInterface
    public void printFinalize( )
    {
       printInfo = null;
    }
    
    class PrintInfo
    {
       public boolean pageDone;
       public Font printFont;
       public List colLayout;
       public List rowLayout;
       public int colSplits;
       public int rowSplits;
       public int subPageIndex;
       public int prevPageIndex;
       public int m_pages;
    
       public int pageHeight;
       public int pageWidth;
    
       public int columnHeaderHeight;
       public int rowHeaderWidth;
    
       public int heldRowTopHeight;
       public int heldRowBottomHeight;
       public int heldColumnLeftWidth;
       public int heldColumnRightWidth;
       public int heldColumnLeftCount;
       public int heldColumnRightCount;
       public int heldRowTopCount;
       public int heldRowBottomCount;
    
       public int heldRowHeight;
       public int heldColumnWidth;
    }
    
    private PrintInfo printInfo;
    
    /**
     *
     * @param g
     * @param pageFormat
     */
    private void getPageInfo(Graphics g, int pageWidth, int pageHeight)
    {
       if (printInfo == null)
       printInfo = new PrintInfo();
       printInfo.subPageIndex = 0;
       printInfo.colLayout = null;
       printInfo.colSplits = 0;
       printInfo.subPageIndex = 0;
       printInfo.prevPageIndex = 0;
    
       printInfo.printFont = getFont();
       g.setFont(printInfo.printFont);
    
       TableColumnModel tableColumnModel = tableHeader.getColumnModel();
       int colCount = tableColumnModel.getColumnCount();
       int columnMargin = tableColumnModel.getColumnMargin();
    
       printInfo.heldRowTopHeight = getRowHeader().getTopHeldHeight();
       printInfo.heldRowBottomHeight = getRowHeader().getBottomHeldHeight();
       printInfo.heldColumnLeftWidth = getColumnHeader().getLeadingHeldWidth();
       printInfo.heldColumnRightWidth = getColumnHeader().getTrailingHeldWidth();
       printInfo.heldColumnLeftCount = 0;
       printInfo.heldColumnRightCount = 0;
       if (getColumnHeader() != null)
       {
          printInfo.heldColumnLeftCount =
    	     getColumnHeader().getHeldIndices(SwingConstants.LEADING).size();
          printInfo.heldColumnRightCount =
    	     getColumnHeader().getHeldIndices(SwingConstants.TRAILING).size();
       }
       printInfo.heldRowTopCount = getRowHeader().getHeldIndices(SwingConstants.TOP).size();
       printInfo.heldRowBottomCount =
          getRowHeader().getHeldIndices(SwingConstants.BOTTOM).size();
    
       printInfo.heldRowHeight = printInfo.heldRowTopHeight + printInfo.heldRowBottomHeight;
       printInfo.heldColumnWidth =
          printInfo.heldColumnLeftWidth + printInfo.heldColumnRightWidth;
    
       printInfo.columnHeaderHeight = getTableHeader().getHeight();
       printInfo.rowHeaderWidth = getRowHeader().getWidth();
    
       printInfo.pageHeight = pageHeight;
       printInfo.pageWidth = pageWidth;
    
       int hgt = printInfo.columnHeaderHeight + printInfo.heldRowHeight;
       int yPos = 0; // position relative to top of table
       printInfo.rowLayout = new ArrayList();
       printInfo.rowLayout.add(new Integer(0));
       printInfo.rowSplits = 0;
       int rowHgt;
       for (int row = printInfo.heldRowTopCount, rowCount = getRowCount();
          row < rowCount - printInfo.heldRowBottomCount; row++)
       {
          rowHgt = getRowHeight(row);
          if (hgt + rowHgt > printInfo.pageHeight && yPos != 0)
          {
             printInfo.rowSplits++;
             printInfo.rowLayout.add(new Integer(yPos + (printInfo.rowSplits *
                (printInfo.heldRowHeight))));
             hgt = printInfo.columnHeaderHeight + printInfo.heldRowHeight;
          }
          hgt += rowHgt;
          yPos += rowHgt;
       }
       if (hgt > 0) // if there is more columns
       {
          printInfo.rowLayout.add(new Integer(yPos + ((printInfo.rowSplits + 1) *
             printInfo.heldRowHeight)));
          printInfo.rowSplits++;
       }
    
       int wid = printInfo.rowHeaderWidth + printInfo.heldColumnWidth;
       int xPos = 0; // position relative to top of table
       printInfo.colLayout = new ArrayList();
       printInfo.colLayout.add(new Integer(0));
       printInfo.colSplits = 0;
       int colWid;
       for (int col = printInfo.heldColumnLeftCount;
          col < colCount - printInfo.heldColumnRightCount;
          col++)
       {
          colWid = tableColumnModel.getColumn(col).getWidth();
          if (wid + colWid > printInfo.pageWidth && xPos != 0)
          {
             printInfo.colSplits++;
             printInfo.colLayout.add(new Integer(xPos + (printInfo.colSplits *
                (printInfo.heldColumnWidth))));
             wid = printInfo.rowHeaderWidth + printInfo.heldColumnWidth;
          }
          wid += colWid;
          xPos += colWid;
       }
       if (wid > 0) // if there is more columns
       {
          printInfo.colLayout.add(new Integer(xPos + ((printInfo.colSplits + 1) *
             printInfo.heldColumnWidth)));
          printInfo.colSplits++;
       }
    
       printInfo.m_pages = printInfo.rowSplits * printInfo.colSplits;
       printInfo.pageDone = true;
    }
    
    /**
     *
     * @param g
     * @param pageFormat
     * @param rowIndex
     * @param columnIndex
     */
    private void printSubTable(Graphics g, int rowIndex, int columnIndex)
    {
       int pageLeft = ((Integer)printInfo.colLayout.get(columnIndex)).intValue();
       int pageRight = ((Integer)printInfo.colLayout.get(columnIndex + 1)).intValue();
       int pageWidth = pageRight - pageLeft;
       int pageTop = ((Integer)printInfo.rowLayout.get(rowIndex)).intValue();
       int pageBottom = ((Integer)printInfo.rowLayout.get(rowIndex + 1)).intValue();
       int pageHeight = pageBottom - pageTop;
    
       //print origin
       Graphics g2 = g.create(0, 0, printInfo.rowHeaderWidth, printInfo.columnHeaderHeight);
       Component origin = getOriginComponent();
       origin.print(g2);
       g2.dispose();
    
       //print table header

    g2 = g.create(0, 0, pageWidth + printInfo.rowHeaderWidth, pageHeight + printInfo.columnHeaderHeight); g2.translate(-pageLeft, 0); g2.translate(printInfo.rowHeaderWidth, 0); ColumnHeader header = getColumnHeader(); g2.translate(columnIndex * (printInfo.heldColumnWidth), 0); g2.setClip(pageLeft - (columnIndex * printInfo.heldColumnWidth), 0, pageWidth, printInfo.columnHeaderHeight); header.print(g2); g2.dispose(); //print row header

    g2 = g.create(0, 0, pageWidth + printInfo.rowHeaderWidth, pageHeight + printInfo.columnHeaderHeight); g2.translate(0, -pageTop); g2.translate(0, printInfo.columnHeaderHeight); RowHeader rowHeader = getRowHeader(); g2.translate(0, rowIndex * (printInfo.heldRowHeight)); g2.setClip(0, pageTop - (rowIndex * printInfo.heldRowHeight), printInfo.rowHeaderWidth, pageHeight); rowHeader.print(g2); g2.dispose(); //print table data

    g2 = g.create(0, 0, pageWidth + printInfo.rowHeaderWidth, pageHeight + printInfo.columnHeaderHeight); g2.translate(-pageLeft, -pageTop); g2.translate(printInfo.rowHeaderWidth, 0); g2.translate(0, printInfo.columnHeaderHeight); g2.translate(columnIndex * (printInfo.heldColumnWidth), rowIndex * (printInfo.heldRowHeight)); g2.setClip(pageLeft - (columnIndex * printInfo.heldColumnWidth), pageTop - (rowIndex * printInfo.heldRowHeight), pageWidth, pageHeight); print(g2); g2.dispose(); }

  5. Compile the PDFPrintingTable class so that it can be inserted into the project.
  6. Now the PDFPrintingTable needs to be added to the project. Select the Project Classes tab in the Project Navigator. If you expand the Default Package node, you should see the PDFPrintingTable class that was created. Drag and Drop the table onto the project frame.
  7. When adding the JDBCConnection, drag it from the component toolbar and drop it onto the PDFTableView in order to create a JDBCToTableModelAdapter and establish it as the model for the JDBCToTableModelAdapter. Since the JDBCConnection is a non-visual component, you will need to drop the JDBCConnection onto the PDFTableView from the Components tab of the Project Navigator (Window [arrow] Project Navigator [arrow] Components). Add the JButton anywhere on panel, this button will be used to print the table.
    Component Name Icon Icon Tab Location
    JDBCConnection JDBC Connection SAS JDBC
    JButton JButton icon Selector
    JDBCToTableModelAdapter JDBCToTableModelAdapter image SAS JDBC (automatically created by dropping JDBCConnection)
  8. Set property values.

    Component Name Property Name Property Value
    JDBCToTableModelAdapter1 queryStatement select * from sashelp.class (from customizer or property sheet)
    JDBCToTableModelAdapter1 formattedDataUsed true (from property sheet)
    JDBCConnection1 Select a driver SAS IOM JDBC Driver from customizer
    JDBCConnection1 driverClass com.sas.rio.MVADriver (SAS IOM JDBC Driver from customizer)
    JButton1 text Print to PDF...
  9. Add the code shown below to the event handler for the JButton1 actionPerformed event. To add the event handler, right mouse click on JButton1 in the project navigator and select Handle Event from the context menu. Select Write your own code from the first choice box that asks which type of handler to create. Next, click on the link in the Interaction Description text area and select the actionPerformed event for the JButton1 component. Click Source and add the following code in the source file:
    String acrobatLocation = "C:\\Program Files\\Adobe\\Acrobat 5.0\\Reader\\AcroRd32.exe";
    
    //Get a PrintJob object

    com.sas.awt.print.PDFGraphics pdfGraphics = new com.sas.awt.print.PDFGraphics(acrobatLocation); com.sas.awt.print.PrintJob pj = com.sas.awt.print.PrintJob.getPrintJob(pdfGraphics); pj.setPrintable(PDFPrintingTable1); try { pj.print(); } catch (com.sas.awt.print.PrintException pe) { pe.printStackTrace(); }

  10. (Optional) Make sure the font set on the table will print in PDF correctly. This step may not be needed, but is recommended so that the PDFGraphics will use the correct font. Paste the following code into the postInit() method of the application:
    java.awt.Font font = new java.awt.Font("SansSerif", java.awt.Font.PLAIN, 11);
    
    PDFPrintingTable1.setFont(font);
    PDFPrintingTable1.getColumnHeader().setFont(font);
    PDFPrintingTable1.getRowHeader().setFont(font);
    
    PDFPrintingTable1.getColumnHeader().sizeColumnsToFit();
    PDFPrintingTable1.getRowHeader().sizeRowsToFit(true, true);
    

    Note: The PDFGraphics has a problem that causes the table to print incorrectly if a column or row are held in more then one area. That is, the table will print fine if only columns are held and are all held on the left or right or if only rows are held and they are held on the top or bottom. Only one area of the table can have something held, otherwise there will be problems when the table is printed to PDF.

Step 3: Finish the Project

  1. Build the project.
  2. Start the IOM Spawner by selecting Start Menu [arrow] SAS AppDev Studio [arrow] Services [arrow] SAS V9.1 [arrow] Start SAS V9.1 IOM Spawner.
  3. Execute the project.

If you created an Applet Project and you would like to deploy it then see Deploying with JSASNetCopy. The following articles may also be helpful: