FPDF object has no attribute 'epw'

1k Views Asked by At

I want to create a table using the 'FPDF' library, but python gives me an error 'CreateTablePDF' object has no attribute 'epw' There is my code:

import pathlib
from os.path import join

from fpdf import FPDF


class CreateTablePDF(FPDF):
    def __init__(self):
        super(CreateTablePDF, self).__init__()
        src_dir = f'{pathlib.Path(__file__).parent.parent.parent.parent.absolute()}'

        font_dir = join(src_dir, 'common', 'fonts')
        font_arial = join(font_dir, "arial.ttf")

        self.add_font("Arial", "", font_arial, uni=True)
        self.set_font("Arial", size=8)

    def create_table_from_rows(self, rows):
        once = True
        line_height = self.font_size * 1.5
        col_width = self.epw / 3
        for row in rows:
            for datum in row:
                if datum != None:
                    if once:
                        self.set_fill_color(230, 230, 230)
                        self.multi_cell(col_width, line_height, datum, border=1, ln=3, max_line_height=self.font_size, fill=True)
                    else:
                        self.multi_cell(col_width, line_height, datum, border=1, ln=3, max_line_height=self.font_size)
                    col_width = self.epw / 3
            once = False
            col_width = self.epw / 10
            self.ln(line_height)

I tried to install 'FPDF2', but it never worked, although it is in the class that is installed on my computer, here

def __init__(
    self,
    orientation: _Orientation = ...,
    unit: _Unit | float = ...,
    format: _Format | tuple[float, float] = ...,
    font_cache_dir: str | Literal["DEPRECATED"] = ...,
) -> None: ...
...
def epw(self) -> float: ...
@property
...

(I apologize for my poor English, I used Google translator)

2

There are 2 best solutions below

0
On

Yeah, the 'epw' variable does not exist in the FPDF ParentClass, but you can easily define the 'epw' attribute in the init method of your CreateTablePDF class.

import pathlib
from os.path import join
from fpdf import FPDF

class CreateTablePDF(FPDF):
    def __init__(self):
        super(CreateTablePDF, self).__init__()
        src_dir = f'{pathlib.Path(__file__).parent.parent.parent.parent.absolute()}'
        font_dir = join(src_dir, 'common', 'fonts')
        font_arial = join(font_dir, "arial.ttf")
        self.add_font("Arial", "", font_arial, uni=True)
        self.set_font("Arial", size=8)
        # NEW
        self.page_width = self.w - 2 * 1.5 #how much it is up to you
        self.epw = self.page_width / 3

OK, even after solving the "epw" problem, there are other errors in your code.
In sequence:

  1. No page open, you need to call add_page() first
  2. TypeError: FPDF.multi_cell() got two unexpected keyword argument 'ln' and 'max_line_height' (even if they seem to exist in the definition)

Therefore, I have changed your snippet to make it work. Here's my version, in which I simply create a pdf file containing a table with 'ciao','hello','hola' in its 3 rows.

    def create_table_from_rows(self, rows):
        once = True
        line_height = self.font_size * 1.5
        col_width = self.epw / 3

        self.add_page() #add a new page before creating the table

        for row in rows:
            for datum in row:
                if datum != None:
                    if once:
                        self.set_fill_color(230, 230, 230)
                        self.multi_cell(col_width, line_height, datum, border=1, fill=True)
                    else:
                        self.multi_cell(col_width, line_height, datum, border=1)
                col_width = self.epw / 3
            once = False
            col_width = self.epw / 10
            self.ln(line_height)

        

a = CreateTablePDF()
a.create_table_from_rows((['ciao','hello','hola'],))
a.output('table.pdf', 'F')

N.B. If you want to insert numbers into the table, your class method is not correct, you should modify it, to avoid this common AttributeError:
'int' object has no attribute 'replace'in line => s=txt.replace("\r",'') of /your_python_lib_path_/fpdf/fpdf.py

    def create_table_from_rows(self, rows):
        once = True
        line_height = self.font_size * 1.5
        col_width = self.epw / 3
        self.add_page() 
        for row in rows:
            for datum in row:
                if datum is not None:
                     self.set_fill_color(230, 230, 230)
                     txt = str(datum) #convert to a string
                     self.multi_cell(col_width, line_height, txt.replace("\r", ""), border=1) #remove any carriage returns (\r) using the replace() method.
                else:
                    self.multi_cell(col_width, line_height, "", border=1) #without 'ln' and 'max_line_height' for now
                col_width = self.epw / 3
            once = False
            col_width = self.epw / 10
            self.ln(line_height)

a = CreateTablePDF()
a.create_table_from_rows(([1,2,3],))
a.output('table_nums.pdf', 'F')

You can start from here to design your custom table. Bye!

0
On

.epw & .eph properties only appeared in version 2.3.0 of fpdf2: https://github.com/py-pdf/fpdf2/blob/master/CHANGELOG.md#230---2021-01-29

Make sure that you have installed the latest version of fpdf2:

pip install --upgrade fpdf2