table/table_schedule
Create a weekly booking plan for the meeting rooms of a company.
Download Java Code Switch to PHP Code Show Output
/*
* Table schedule:
* Create a weekly booking plan for the meeting rooms of a company
*
* For the weekly bookings of the meeting rooms in a company, create a table
* with each cell representing a period of time on a day of the week for a
* certain meeting room. If a meeting room is booked for a certain period of
* time on a certain day of the week the corresponding cells will be colorized
* and provided with some booking text.
* Use the "colwidth" and "rowheight" options of add_table_cell() to create the
* table as a kind of grid with unique and fixed column width and row height.
* Use the "fitmethod=auto" option to decrease the font size if the booking text
* is too large to fit completely into the cell.
* Use the "matchbox" option of add_table_cell() to colorize cells.
*
* The table is to be spread over two pages with a defined row being the last
* one on the first page. Use the "return" option of add_table_cell() to force
* fit_table() to a break after having placed the last row containing the cell.
*
* Required software: PDFlib/PDFlib+PDI/PPS 9
* Required data: none
*/
package com.pdflib.cookbook.pdflib.table;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Locale;
import com.pdflib.pdflib;
import com.pdflib.PDFlibException;
public class table_schedule
{
public static void main (String argv[])
{
/* This is where the data files are. Adjust as necessary. */
String searchpath = "../input";
String outfile = "table_schedule.pdf";
String title = "Table Schedule";
pdflib p = null;
int exitcode = 0;
int row, col, tf=-1, tbl=-1;
int i, j, t, regularfont, boldfont;
String tlcell_opts;
String fittab_opts, tfcell_opts;
String result;
final double pagewidth = 842, pageheight = 595;
final double fontsize = 12;
final double capheight = 8.5;
final int margin = 4;
final double rowheight1 = 16, rowheight2 = 32;
final String leading = "120%";
final int dayspan = 5, timespan=3, mroomspan = 2, croomspan=3;
final double tstart = 5, tend = 22, tbreak = 12;
/* The table coordinates are fixed */
final int llx = 50, urx = (int) pagewidth - llx;
final int lly = 120, ury = (int) pageheight - lly;
final int yoffset = 15;
final int yheading = ury + 2 * yoffset;
final int ycontinued = lly - yoffset;
/* The widths of the first and the other columns is fixed */
final int cwfirst = 50, cwother = 30;
final int maxdays = 6;
final String days [] = {
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
final int maxrooms = 5;
final String rooms [] = {
"M1", "M2", "C1", "C2", "C3"
};
final int idxDay = 0, idxStart = 1, idxEnd = 2, idxRoom = 3;
final int idxText = 4, idxColor = 5;
final int maxbookings = 6;
final String bookings [] [] = {
/* day, start, end, room, text, color */
{"1", "8", "12", "1", "Company Meeting", "rgb 0.8 0.36 0.36"},
{"2", "11", "20", "4", "Technical Workgroup", "rgb 1.0 0.84 0.0"},
{"4", "8", "16", "2", "QM Meeting", "rgb 0.0 0.8 0.82"},
{"5", "10", "12", "4", "Admin Training", "rgb 0.6 0.8 0.92"},
{"5", "14", "18", "4", "Admin Training", "rgb 0.6 0.8 0.92"},
{"6", "14", "22", "5", "Admin Training", "rgb 0.6 0.8 0.92"}
};
try {
p = new pdflib();
p.set_option("searchpath={" + searchpath + "}");
/* This means we must check return values of load_font() etc. */
p.set_option("errorpolicy=return");
if (p.begin_document(outfile, "") == -1)
throw new Exception("Error: " + p.get_errmsg());
p.set_info("Creator", "PDFlib Cookbook");
p.set_info("Title", title);
/* Load the bold and regular styles of a font */
boldfont = p.load_font("NotoSerif-Bold", "unicode", "");
if (boldfont == -1)
throw new Exception("Error: " + p.get_errmsg());
regularfont = p.load_font("NotoSerif-Regular", "unicode", "");
if (regularfont == -1)
throw new Exception("Error: " + p.get_errmsg());
/* Start the output page */
p.begin_page_ext(pagewidth, pageheight, "");
/* Output the heading */
p.setfont(boldfont, fontsize);
p.fit_textline("Booking Schedule", llx, yheading, "");
/* Prepare the general option list for adding a Textflow.
* For an exact vertical alignment of Textflow and text lines note the
* following:
* The height of an uppercase letter is exactly represented by the
* capheight value of the font. For this reason use the capheight in the
* font size specification. For example, a capheight of 8.5 will
* approximately result in a font size of 12 points.
* "alignment=center" centers the text.
* "leading" specifies the distance between to text lines.
*/
final String tf_opts = "font=" + regularfont + " alignment=center" +
" fontsize={capheight=" + capheight + "} leading=" + leading;
/* -------------------------------------------------------------------
* Add the Textflow cell containing the time heading which spans three
* rows
* -------------------------------------------------------------------
*/
col = 1; row = 1;
/* Add the Textflow to be placed in the heading cell */
tf = p.add_textflow(-1, "Time\nfrom\nto", tf_opts);
if (tf == -1)
throw new Exception("Error: " + p.get_errmsg());
/* Prepare the option list for adding the Textflow cell
*
* The first line of the Textflow should be aligned with the baseline of
* the text lines. At the same time, the text lines should have the same
* distance from the top cell border as the Textflow. To avoid any space
* from the top add the Textflow cell using
* "fittextflow={firstlinedist=capheight}".
* "colwidth" defines the width of the first column the cell is spanned.
* "rowheight" defines the row height.
* "margin" adds some empty space between the text and the cell borders.
* "colspan" defines the number of columns the cell is spanned.
*/
tfcell_opts =
"textflow=" + tf +
" fittextflow={firstlinedist=capheight fitmethod=auto}" +
" colwidth=" + cwfirst +
" rowheight=" + rowheight1 +
" margin=" + margin +
" rowspan=" + timespan;
tbl = p.add_table_cell(tbl, col, row, "", tfcell_opts);
if (tbl == -1)
throw new Exception("Error: " + p.get_errmsg());
/* -------------------------------------------------------------------
* Add the text line cells containing the days of the week headings in
* the first row, spanning several columns each
* -------------------------------------------------------------------
*/
col = 2; row = 1;
/* Prepare the option list:
* "position={center top}" positions the text on the top left.
* "fitmethod=auto" decreases the font size of the text if it is too
* large to fit completely into the cell instead of increasing the row
* height.
* The height of an uppercase letter is exactly represented by the
* capheight value of the font. For this reason use the capheight in the
* font size specification. For example, to match a row height of 16,
* you could use a capheight of 8.5 and a margin of 4.
* "fitmethod=auto" will decrease the font size, if necessary, until the
* text line fits completely into the cell.
* "colwidth" defines the width of the first column the cell is spanned.
* "rowheight" defines the row height.
* "margin" adds some empty space between the text and the cell borders.
* "colspan" defines the number of columns the cell is spanned.
*/
tlcell_opts = "fittextline={position={center top} fitmethod=auto" +
" font=" + boldfont + " fontsize={capheight=" + capheight + "}} " +
" colwidth=" + cwother +
" rowheight=" + rowheight1 +
" margin=" + margin +
" colspan=" + dayspan;
/* Add the table cells containing the days of the week */
for (i = 0; i < maxdays; i++)
{
tbl = p.add_table_cell(tbl, col, row, days[i], tlcell_opts);
if (tbl == -1)
throw new Exception("Error adding cell: " + p.get_errmsg());
col += dayspan;
}
/* --------------------------------------------------------------------
* In the second row below each day of the week, add the "Meeting Room"
* and "Conference Room" Textflow heading cells. The two cells together
* span the same number of columns as spanned by the day of the week.
* --------------------------------------------------------------------
*/
col = 2; row = 2;
/* Loop over the number of days of the week */
for (i = 0; i < maxdays; i++)
{
/* Add the "Meeting Room" Textflow */
tf = p.add_textflow(-1, "Meeting Room", tf_opts);
if (tf == -1)
throw new Exception("Error: " + p.get_errmsg());
/* Add the "Meeting Room" Textflow cell */
tfcell_opts = "textflow=" + tf +
" fittextflow={firstlinedist=capheight fitmethod=auto}" +
" colwidth=" + cwother +
" rowheight=" + rowheight2 +
" margin=" + margin +
" colspan=" + mroomspan;
tbl = p.add_table_cell(tbl, col, row, "", tfcell_opts);
if (tbl == -1)
throw new Exception("Error: " + p.get_errmsg());
col += mroomspan;
/* Add the "Conference Room" Textflow */
tf = p.add_textflow(-1, "Conference Room", tf_opts);
if (tf == -1)
throw new Exception("Error: " + p.get_errmsg());
/* Add the "Conference Room" Textflow cell */
tfcell_opts = "textflow=" + tf +
" fittextflow={firstlinedist=capheight fitmethod=auto}" +
" colwidth=" + cwother +
" rowheight=" + rowheight2 +
" margin=" + margin +
" colspan=" + croomspan;
tbl = p.add_table_cell(tbl, col, row, "", tfcell_opts);
if (tbl == -1)
throw new Exception("Error: " + p.get_errmsg());
col += croomspan;
}
/* ---------------------------------------------------------------------
* In the third row below the "Meeting Room" and "Conference Room" cells
* for each day of the week add five text line heading cells containing
* the names of the meeting rooms.
* ---------------------------------------------------------------------
*/
col = 2; row = 3;
/* Prepare the option list for adding the cells */
tlcell_opts = "fittextline={position={center top} fitmethod=auto" +
" font=" + regularfont + " fontsize={capheight=" + capheight + "}}"+
" colwidth=" + cwother +
" rowheight=" + rowheight1 +
" margin=" + margin;
/* Loop over the number of days of the week */
for (i = 0; i < maxdays; i++)
{
/* Add the cells with the names of the room */
for (j = 0; j < maxrooms; j++) {
tbl = p.add_table_cell(tbl, col++, row, rooms[j], tlcell_opts);
if (tbl == -1)
throw new Exception("Error adding cell: " + p.get_errmsg());
}
}
/* --------------------------------------------------------------
* In the first column add the Textflow cells containing the time
* intervals, one cell for each hour
* --------------------------------------------------------------
*/
col = 1; row = 4;
/* For outputting the time of the day, initialize the maximum number
* of fraction digits to two
*/
NumberFormat form = NumberFormat.getInstance(Locale.US);
form.setMaximumFractionDigits(2);
form.setMinimumFractionDigits(2);
/* Loop over all time intervals */
for (i = 1, t = (int) tstart; i <= tend - tstart; i++, t++)
{
/* Format the current time interval to a maximum of two fraction
* digits
*/
BigDecimal value = new BigDecimal(t);
BigDecimal roundedValue =
value.setScale(2, RoundingMode.HALF_UP);
String text = roundedValue.toString() + "\n";
value = new BigDecimal(t+1);
roundedValue = value.setScale(2, RoundingMode.HALF_UP);
text += roundedValue.toString();
/* Add the time interval Textflow */
tf = p.add_textflow(-1, text, tf_opts);
if (tf == -1)
throw new Exception("Error: " + p.get_errmsg());
/* Prepare the option list for adding the time interval headings */
tfcell_opts = "textflow=" + tf +
" fittextflow={firstlinedist=capheight fitmethod=auto}" +
" colwidth=" + cwfirst +
" rowheight=" + rowheight2 +
" margin=" + margin;
/* We want to spread the table over two pages. The last row placed
* on the first page should be the one representing a defined time
* interval, e.g. of 12-13. To accomplish this use the "return"
* option of add_table_cell() when adding the respective cell. This
* signals to fit_table() to return after having placed the
* corresponding table row, and we can fit the following table rows
* in a subsequent call on the second page.
*/
if (t == tbreak)
tfcell_opts += " return break";
/* Add the time interval Textflow cell */
tbl = p.add_table_cell(tbl, col, row++, "", tfcell_opts);
if (tbl == -1)
throw new Exception("Error adding cell: " + p.get_errmsg());
}
/* -----------------------------------------------------------------
* For each booking item add a text line cell containing the booking
* text and colorize it. Place the cell according to the day of the
* week, time interval and meeting room affected.
* -----------------------------------------------------------------
*/
/* Loop over all bookings */
for (i = 0; i < maxbookings; i++) {
/* Read the attributes of the current booking */
int start = Integer.valueOf(bookings[i][idxStart]).intValue();
int end = Integer.valueOf(bookings[i][idxEnd]).intValue();
int day = Integer.valueOf(bookings[i][idxDay]).intValue();
int room = Integer.valueOf(bookings[i][idxRoom]).intValue();
String text = bookings[i][idxText];
/* Get the column and row as well as the number of rows spanned by
* the cell
*/
int rowspan = 1;
col = 2 + ((day - 1) * dayspan) + (room - 1);
row = 4 + (start - (int) tstart);
if (end != start)
rowspan = end - start;
/* Prepare the option list for adding the booking item cell */
String opts = "fittextline={position={center} " +
" fitmethod=auto font=" + regularfont + " orientate=west" +
" fontsize={capheight=" + capheight + "}} " +
" colwidth=" + cwother +
" rowheight=" + rowheight2 +
" margin=" + margin +
" rowspan=" + rowspan +
" matchbox={fillcolor={" + bookings[i][idxColor] + "}}";
tbl = p.add_table_cell(tbl, col, row, text, opts);
if (tbl == -1)
throw new Exception("Error adding cell: " + p.get_errmsg());
}
/* ------------------------------------
* Place the table on one or more pages
* ------------------------------------
*/
/* Prepare the option list for fitting the table.
* "header=3" will repeat the first three rows at the beginning of
* each new page. The "stroke" option will stroke lines with two
* different line widths. The table frame as well as each vertical
* line to the right of a day-of-the-week cell is stroked with a
* line width of 1, all other lines are stroked with a line width of
* 0.3.
*/
fittab_opts = "header=3 stroke={" +
"{line=frame linewidth=1} {line=other linewidth=0.3} ";
for (i = 0; i < maxdays; i++)
fittab_opts += "{line=vert" + (1+i*maxrooms) + " linewidth=1} ";
fittab_opts += "}";
/* Loop until all of the table is placed; create new pages as long as
* more table instances need to be placed
*/
do {
/* Place the table instance */
result = p.fit_table(tbl, llx, lly, urx, ury, fittab_opts);
if (result.equals("_error"))
throw new Exception ("Couldn't place table: " +
p.get_errmsg());
/* A return value of "break" has been explicitly specified in
* add_table_cell() when adding the cell for a certain time interval
* after which a new page shall be started.
*/
if (result.equals("_boxfull") || result.equals("break")) {
p.setfont(regularfont, fontsize);
p.fit_textline("-- Continued --", urx, ycontinued,
"position {right top}");
p.end_page_ext("");
p.begin_page_ext(pagewidth, pageheight, "");
}
} while (result.equals("_boxfull") || result.equals("break"));
p.end_page_ext("");
p.end_document("");
} catch (PDFlibException e) {
System.err.println("PDFlib exception occurred:");
System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
": " + e.get_errmsg());
exitcode = 1;
} catch (Exception e) {
System.err.println(e.toString());
exitcode = 1;
} finally {
if (p != null) {
p.delete();
}
System.exit(exitcode);
}
}
}