Search code examples
templatespython-2.7hyperlinkfpdf

PyFPDF create link in template


I have been able to successfully create a pdf file with the simple example found here and it worked flawlessly. I realize also that a link can be created using the write command by simply adding a few parameters. However, I am unsure as to how to (most efficiently/properly) to add it to a template. Ideally I would like to add it into the elements dictionary.

EDIT: Actually I don't even think the Template object allows for using the Write() option so there maybe no way to make a link in a Template it looks like I am going to have to write my own object if I want to have a url.

from pyfpdf import Template

#this will define the ELEMENTS that will compose the template. 
elements = [
    { 'name': 'company_logo', 'type': 'I', 'x1': 20.0, 'y1': 17.0, 'x2': 78.0, 'y2': 30.0, 'font': None, 'size': 0.0, 'bold': 0, 'italic': 0, 'underline': 0, 'foreground': 0, 'background': 0, 'align': 'I', 'text': 'logo', 'priority': 2, },
    { 'name': 'company_name', 'type': 'T', 'x1': 17.0, 'y1': 32.5, 'x2': 115.0, 'y2': 37.5, 'font': 'Arial', 'size': 12.0, 'bold': 1, 'italic': 0, 'underline': 0, 'foreground': 0, 'background': 0, 'align': 'I', 'text': '', 'priority': 2, },
    { 'name': 'box', 'type': 'B', 'x1': 15.0, 'y1': 15.0, 'x2': 185.0, 'y2': 260.0, 'font': 'Arial', 'size': 0.0, 'bold': 0, 'italic': 0, 'underline': 0, 'foreground': 0, 'background': 0, 'align': 'I', 'text': None, 'priority': 0, },
    { 'name': 'box_x', 'type': 'B', 'x1': 95.0, 'y1': 15.0, 'x2': 105.0, 'y2': 25.0, 'font': 'Arial', 'size': 0.0, 'bold': 1, 'italic': 0, 'underline': 0, 'foreground': 0, 'background': 0, 'align': 'I', 'text': None, 'priority': 2, },
    { 'name': 'line1', 'type': 'L', 'x1': 100.0, 'y1': 25.0, 'x2': 100.0, 'y2': 57.0, 'font': 'Arial', 'size': 0, 'bold': 0, 'italic': 0, 'underline': 0, 'foreground': 0, 'background': 0, 'align': 'I', 'text': None, 'priority': 3, },
    { 'name': 'barcode', 'type': 'BC', 'x1': 20.0, 'y1': 246.5, 'x2': 140.0, 'y2': 254.0, 'font': 'Interleaved 2of5 NT', 'size': 0.75, 'bold': 0, 'italic': 0, 'underline': 0, 'foreground': 0, 'background': 0, 'align': 'I', 'text': '200000000001000159053338016581200810081', 'priority': 3, },
]

#here we instantiate the template and define the HEADER
f = Template(format="A4",elements=elements,
             title="Sample Invoice")
f.add_page()

#we FILL some of the fields of the template with the information we want
#note we access the elements treating the template instance as a "dict"
f["company_name"] = "Sample Company"
f["company_logo"] = "pyfpdf/tutorial/logo.png"

#and now we render the page   
f.render("./template.pdf")

The code above is the example provided in the link.


Solution

  • So I checked out the source and it didn't seem there was anyway for a link in the templates. I added the following code:

    def write(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
              bold=False, italic=False, underline=False, align="", link='http://example.com',
             foreground=0, *args, **kwargs):
        if pdf.text_color!=rgb(foreground):
            pdf.set_text_color(*rgb(foreground))
        font = font.strip().lower()
        if font == 'arial black':
            font = 'arial'
        style = ""
        for tag in 'B', 'I', 'U':
            if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
                text = text[3:-4]
                style += tag
        if bold: style += "B"
        if italic: style += "I"
        if underline: style += "U"
        align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
        pdf.set_font(font,style,size)
        ##m_k = 72 / 2.54
        ##h = (size/m_k)
        pdf.set_xy(x1,y1)
        pdf.write(5,text,link)
    

    into templates.py and changed the line

    -                         'B': self.rect, 'BC': self.barcode, }
    +                         'B': self.rect, 'BC': self.barcode, 'W' self.write, }
    

    in the elements self handler. With this you can use a similar syntax to writing a text line in the elements dict object. Simply change type: 'T' to type: 'W' and add a link: 'http://code.google.com/p/pyfpdf/' to it or whatever link you want. I submitted this as a patch and it should be available in the next version. I left the x2 y2 in the parameters because I'm not sure if they are necessary for parsing or not but I believe the Write() method only uses x1 y1 if it's anything like the PHP version. K thx bye