Hey i am using fpdf in python for showing a list the, Below is my code:
from fpdf import FPDF pdf = FPDF("L", 'mm', 'Legal') pdf.add_page() pdf.set_font('helvetica', 'B', 16) headers = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7'] body = [ ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'], ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] ] print(pdf.w) print(pdf.get_x()) for r in headers: pdf.cell(70, 10, f'{r}') pdf.set_font('helvetica', '', 16) for d in range(len(body)): row = body[d] for i in range(len(row)): if i == len(row)-1: pdf.cell(70, 10, f'{row[i]}', 0, ln=1) else: pdf.cell(70, 10, f'{row[i]}', 0) # pdf.cell(5, 10, '') pdf.output('/home/chandan/Documents/tournament.pdf')
Note: the length of header and body is always same
the column H6,H7 are out of margin, so how an i make one pdf page show 5 columns and the rest of the columns show in next page Now the pdf page looks like this Now how can i achieve that
Advertisement
Answer
We’re going to need some simple math and, most importantly, some clear ideas about how we want to print the columns/rows and the individual cells.
First, we need to decide how many rows and columns we want to print per page.
I’ll call this the “print resolution”. Our table of input data can be any size (row by height), but it must be displayed, say, in a grid no bigger than 5 rows by 10 columns per page, so our resolution is “5 rows by 10 columns per page”.
Next, we need to find the print-able area of a page to figure out how big to make those rows and columns.
FPDF tell us the overall dimensions of the page with pdf.w
and pdf.h
, and it also tells us the margins that are set, with pdf.t_margin
(for top margin) and so on for the left (l_margin
), right (r_margin
), and bottom (b_margin
):
The overall width minus the left and right margins tells us how much space we have on the page to fit the 10 columns we picked earlier.
The overall height minus the top and bottom margins tells us how much space we have on the page to fit the 5 rows.
Having picked our print resolution and knowing those printable dimensions we can now figure out how big to make each cell:
Printable-width / 10
equals the width the individual cells need to be to completely fill the grid on the page.Printable-height / 5
gives us the same for the cell’s height.
So, let’s just print a grid 5 rows by 10 columns that evenly fills the page:
from fpdf import FPDF from my_table import table pdf = FPDF("L", "mm", "Letter") pdf.set_font("Arial", "", 16) # Set desired "resolution" of printed grid rows_per_page = 5 cols_per_page = 10 # Calculate dimensions of print-able area print_h = pdf.h - pdf.t_margin - pdf.b_margin print_w = pdf.w - pdf.l_margin - pdf.r_margin # Actual size of grid cells on the page is available space divided by desired resolution, in each dimension c_h = print_h / rows_per_page c_w = print_w / cols_per_page # Add a page and draw a border to visualize the page pdf.add_page() pdf.set_draw_color(255, 0, 0) pdf.set_line_width(1) pdf.rect(0, 0, pdf.w, pdf.h, "D") pdf.set_draw_color(0, 0, 0) pdf.set_line_width(0.2) pdf.rect(0.5, 0.5, pdf.w - 0.5, pdf.h - 0.5, "D") for i in range(rows_per_page): for j in range(cols_per_page): # Create "A1 Notation" for our reference char = chr(65 + j) # "A", then "B", ... s = f"{char}{i+1}" pdf.cell(c_w, c_h, s, border=1, ln=0, align="C") pdf.ln() pdf.output("simple_5-by-10.pdf", dest="F")
and I get:
I’ve decided to use pdf.ln()
at the end of printing a line of cells as it doesn’t take any logic: since we’re outside the loop of columns we definitely know that we’ve finished that row and need to move to the beginning of the next line.
Now that we have a nice looking grid with a desired resolution, we can move on to dealing with a table of information that is bigger than our print resolution, and how to deal with the overflow.
I think of what we’re about to do as picking a batch of rows that fit on a page, then moving across those rows from left-to-right printing the batch of columns that fit on a page:
- Set the row-counter to 0
- Start at the row-counter of the table, and select the next number-of-rows-per-page rows.
- Set the column-counter to 0
- Start at the column-counter of the table, and select the next number-of-columns-per-page columns.
- Print all the cells in that range of rows and columns.
- Advance the column counter, and repeat steps 4 & 5 till all columns have been printed.
- Advance the row counter, and repeat steps 2 – 6 till all rows have been printed.
# Same as above... c_h = print_h / rows_per_page c_w = print_w / cols_per_page # Get table's dimensions num_rows = len(table) num_cols = len(table[0]) # Track how far "down" the table we've moved row_offset = 0 while row_offset < num_rows: # Limit this batch of rows to either the maximum (rows_per_page), unless we're at the end of the table, limit to the remaining of rows row_max = row_offset + rows_per_page if row_max > num_rows: row_max = num_rows # Track how far "across" this batch of rows we've moved col_offset = 0 while col_offset < num_cols: # Limit this batch of columns to the either the maximum (columns_per_page), unless we're at the end of the batch of rows, limit to the remaining columns col_max = col_offset + cols_per_page if col_max > num_cols: col_max = num_cols # Ready to actually start printing, so create page pdf.add_page() # Print a grid of cells, no bigger than rows_per_page-high by cols_per_page-wide for i in range(row_offset, row_max): for j in range(col_offset, col_max): cell_value = table[i][j] pdf.cell(c_w, c_h, cell_value, border=1, ln=0, align="C") pdf.ln() # Advance to the right, "across" the batch of rows, for the next batch of columns col_offset += cols_per_page # Advance "down" the table, for the next batch of rows row_offset += rows_per_page pdf.output("span_cols.pdf", dest="F")
If I give it this table:
table = [ ['A1' , 'B1' , 'C1' , 'D1' , 'E1' , 'F1' , 'G1' , 'H1' , 'I1' , 'J1' , 'K1' , 'L1'], ['A2' , 'B2' , 'C2' , 'D2' , 'E2' , 'F2' , 'G2' , 'H2' , 'I2' , 'J2' , 'K2' , 'L2'], ['A3' , 'B3' , 'C3' , 'D3' , 'E3' , 'F3' , 'G3' , 'H3' , 'I3' , 'J3' , 'K3' , 'L3'], ['A4' , 'B4' , 'C4' , 'D4' , 'E4' , 'F4' , 'G4' , 'H4' , 'I4' , 'J4' , 'K4' , 'L4'], ['A5' , 'B5' , 'C5' , 'D5' , 'E5' , 'F5' , 'G5' , 'H5' , 'I5' , 'J5' , 'K5' , 'L5'], ['A6' , 'B6' , 'C6' , 'D6' , 'E6' , 'F6' , 'G6' , 'H6' , 'I6' , 'J6' , 'K6' , 'L6'], ['A7' , 'B7' , 'C7' , 'D7' , 'E7' , 'F7' , 'G7' , 'H7' , 'I7' , 'J7' , 'K7' , 'L7'], ['A8' , 'B8' , 'C8' , 'D8' , 'E8' , 'F8' , 'G8' , 'H8' , 'I8' , 'J8' , 'K8' , 'L8'], ['A9' , 'B9' , 'C9' , 'D9' , 'E9' , 'F9' , 'G9' , 'H9' , 'I9' , 'J9' , 'K9' , 'L9'], ['A10', 'B10', 'C10', 'D10', 'E10', 'F10', 'G10', 'H10', 'I10', 'J10', 'K10', 'L10'], ['A11', 'B11', 'C11', 'D11', 'E11', 'F11', 'G11', 'H11', 'I11', 'J11', 'K11', 'L11'], ['A12', 'B12', 'C12', 'D12', 'E12', 'F12', 'G12', 'H12', 'I12', 'J12', 'K12', 'L12'] ]
and pick the same resolution of 5 rows by 10 columns, I get the following:
I don’t have the time or energy to show how to handle the header, but I think a simple if i == 0 then header-style else normal-style
check to see if your dealing with the first row. And, include the header with the data, don’t try to handle/print them as separate data structures (that’ll mess up the math).
I was also thinking that if you want the header on each page, check out the section on Headers, Footers in the FPDF tutorial. I’m not sure how adding a header will affect the margins, so play around and see.