0
votes

I've a pdf report generated with iText containing a PdfPTable added to MultiColumnText, sometimes becomes so large that it will be split on more than one page.

Currently the MultiColumnText has been divided by two columns and MultiColumnText fills the PdfPTable vertically Like:

Page-1
+--+--+
|T1|T5|
+--+--+
|T2|T6|
+--+--+
|T3|T7|
+--+--+
|T4|T8|
+--+--+

Page-2
+---+---+
|T9 |T13|
+---+---+
|T10|T14|
+---+---+
|T11|T15|
+---+---+
|T12|T16|
+---+---+

....I want to make this:

Page-1
+--+--+
|T1|T2|
+--+--+
|T3|T4|
+--+--+
|T5|T6|
+--+--+
|T7|T8|
+--+--+

Page-2
+---+---+
|T9 |T10|
+---+---+
|T11|T12|
+---+---+
|T13|T14|
+---+---+
|T15|T16|
+---+---+

The code is:

/**
 * Initializes the fonts and collections.
 * Creates a PDF document.
 * 
 * @param from as a Date
 * @param to as a Date
 * @param weeklyComplianceMap as a Map for print weekly compliance
 * @param monthlyComplianceMap as a Map for print monthly compliance
 * @param calLogList as a List for calculate the add event
 * @param locale Locale in case you want to create a Calendar in another language
 * @throws DocumentException, IOException, ParseException
 * @return ByteArrayOutputStream of PDF output
 */
public ByteArrayOutputStream createPdf(Date from, Date to, Map<String, Integer> weeklyComplianceMap,
        Map<String, Double> monthlyComplianceMap, List<InjectionLogInfo> calLogList, Locale locale) 
        throws DocumentException, ParseException, IOException {

    calendar = new GregorianCalendar();
    calendar.setTime(from);

    BaseFont bf_normal = BaseFont.createFont(
            "C:/Windows/Fonts/arial.ttf", BaseFont.WINANSI,
            BaseFont.EMBEDDED);
    small = new Font(bf_normal, 8);
    normal = new Font(bf_normal, 11);
    BaseFont bf_bold = BaseFont.createFont(
            "C:/Windows/Fonts/arialbd.ttf", BaseFont.WINANSI,
            BaseFont.EMBEDDED);
    smallBold = new Font(bf_bold, 10);
    normalBold = new Font(bf_bold, 12);
    bigBold = new Font(bf_bold, 14);

    document = new Document(PageSize.A4, 20, 20, 40, 30);
    baos = new ByteArrayOutputStream();
    writer = PdfWriter.getInstance(document, baos);

    ResourceBundle rb = ResourceBundle.getBundle("com.resources.messages", locale);

    Paragraph hText = new Paragraph(rb.getString("lbl.calendar.view"), bigBold);
    hText.setAlignment(Element.ALIGN_CENTER);

    Chunk c1 = new Chunk(rb.getString("lbl.document.generated") + " ", normal);
    Chunk c2 = new Chunk(fdf.format(new Date()), normal);
    Chunk c3 = new Chunk(" " + rb.getString("lbl.at") + " ", normal);
    Chunk c4 = new Chunk(tdf.format(new Date()), normal);
    Chunk c5 = new Chunk(new VerticalPositionMark(), 500f, false);
    Chunk c6 = new Chunk(rb.getString("lbl.page") + " ", normal);

    Phrase fText = new Phrase();
    fText.add(c1);fText.add(c2);fText.add(c3);
    fText.add(c4);fText.add(c5);fText.add(c6);

    HeaderFooter header = new HeaderFooter(hText, false);
    HeaderFooter footer = new HeaderFooter(fText, true);
    document.setHeader(header);
    document.setFooter(footer);

    document.open();
    document.leftMargin();

    mct = new MultiColumnText();
    mct.addRegularColumns(document.left(), document.right(), 20, 2);
    mct.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);

    for (int month = 0; month < monthsBetween(from, to, Calendar.MONTH); month++) {
        // create a table with 8 columns
        float[] colsWidth = {35f, 35f, 35f, 35f, 35f, 35f, 35f, 50f};
        table = new PdfPTable(colsWidth);
        table.setWidthPercentage(100);

        // add the name of the month
        table.getDefaultCell().setBackgroundColor(Color.WHITE);
        table.addCell(getMonthCell(calendar, locale));

        Double monAdh = monthlyComplianceMap.get(mdf.format(calendar.getTime()));           
        table.addCell(getMonthlyAdherence(monAdherence));

        // add the name of the days
        String[] days = getDayNames();
        for (String day : days) {
            table.addCell(getDayNamesCell(day, locale));
        }

        int day = 1;
        int position = 2;
        int dayofWeek = calendar.get(Calendar.DAY_OF_WEEK);
        int daysinMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

        // add empty cells
        int rc = 0;
        while (position != dayofWeek) {
            rc++;
            position = (position % 7) + 1;
            table.addCell("");
        }

        // add cells for each day
        while (day <= daysinMonth) {                
            calendar = new GregorianCalendar(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), day++);
            table.addCell(getDayCell(calLogList, calendar, locale));

            if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
                rc++;
                String week = (calendar.get(Calendar.WEEK_OF_YEAR)-1) + ", " + calendar.get(Calendar.YEAR);

                if (null != weeklyComplianceMap) {
                    wa = weeklyComplianceMap.get(week);
                    table.addCell(getDayAdherenceCell(weekAdherence));
                } else {
                    String weekAdherence = "0%";
                    table.addCell(getDayAdherenceCell(weekAdherence));
                }
            }
        }

        if (9 < rc)
            table.setSpacingAfter(20);
        else
            table.setSpacingAfter(40);

        // complete the table
        table.completeRow();

        // add the table to MultiColumnText object
        mct.addElement(table);

        // increment the day by 1
        calendar.add(Calendar.DATE, 1);
    }
    document.add(mct);
    document.newPage();

    document.close();

    return baos;
}

/**
 * Creates a PdfPCell with the name of the month
 * 
 * @param calendar a date
 * @param locale a locale
 * @return a PdfPCell with rowspan 7, containing the name of the month
 */
public PdfPCell getMonthCell(Calendar calendar, Locale locale) {
    PdfPCell cell = new PdfPCell();
    cell.setColspan(7);
    cell.setMinimumHeight(30);
    cell.setBackgroundColor(Color.GRAY);

    Paragraph p = new Paragraph(String.format(locale, "%1$tB %1$tY", calendar), normalBold);
    p.setAlignment(Element.ALIGN_LEFT);
    cell.addElement(p);
    return cell;
}

/**
 * Creates a PdfPCell for a month
 * 
 * @param string adherence of a month
 * @return a PdfPCell
 */
private PdfPCell getMonthlyAdherence(String adherence) {
    PdfPCell cell = new PdfPCell();
    cell.setMinimumHeight(35);
    //cell.setBorderColorLeft(Color.GRAY);
    cell.setBackgroundColor(Color.GRAY);

    Paragraph p = new Paragraph(adherence, smallBold);
    p.setAlignment(Element.ALIGN_RIGHT);
    cell.addElement(p);
    return cell;
}

/**
 * Creates a PdfPCell with the name of the day
 * 
 * @param day name of a day
 * @param locale a locale
 * @return a PdfPCell, containing the name of the day
 */
public PdfPCell getDayNamesCell(String day, Locale locale) {
    PdfPCell cell = new PdfPCell();
    cell.setPadding(3);
    cell.setBackgroundColor(Color.LIGHT_GRAY);

    Paragraph p = new Paragraph(day, smallBold);
    p.setAlignment(Element.ALIGN_CENTER);
    cell.addElement(p);
    return cell;
}

/**
 * Creates a PdfPCell for a specific day
 * 
 * @param calendar a date
 * @param locale a locale
 * @return a PdfPCell
 */
public PdfPCell getDayCell(List<InjectionLogInfo> calLogList, Calendar calendar, Locale locale) {
    PdfPCell cell = new PdfPCell();
    cell.setPadding(3);

    // set the content in the language of the locale
    Chunk chunk = new Chunk(String.format(locale, "%1$te", calendar), small);

    // a paragraph with the day
    Paragraph p = new Paragraph(chunk);
    p.setAlignment(Element.ALIGN_CENTER);
    cell.addElement(p);
    return cell;
}

/**
 * Creates a PdfPCell for a week
 * 
 * @param string adherence of a week
 * @return a PdfPCell
 */
public PdfPCell getDayAdherenceCell(String adherence) {
    PdfPCell cell = new PdfPCell();
    cell.setPadding(3);

    // set the adherence for each week
    Chunk chunk = new Chunk(adherence, small);

    // a paragraph with the adherence
    Paragraph p = new Paragraph(chunk);
    p.setAlignment(Element.ALIGN_CENTER);
    cell.addElement(p);
    return cell;
}

/**
 * Retrieves a Day Names for a single week
 * 
 * @return a String array of day names
 */
public String[] getDayNames() {
    DateFormatSymbols symbols = new DateFormatSymbols();
    String[] dayNames = symbols.getShortWeekdays();

    List<String> stringList = new ArrayList<String>();

    for (String string : dayNames) {
        if (string != null && string.length() > 0) {
            stringList.add(string);
        }
    }

    if (stringList.size() > 0) {
        String one = stringList.get(0);
        stringList.remove(0);
        stringList.add(one);
        stringList.add("%");
    }

    dayNames = stringList.toArray(new String[stringList.size()]);
    return dayNames;
}

I stuck with this so any help is very appreciated.
Thanks.

1

1 Answers

0
votes

I think you are using new PdfPtable(1) per MultiColumnText. change it to new PdfPtable(2) to get 2 columns table per 1 MultiColumnText.