• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru: Creating PDF Documents With Python

    July 27, 2020 Mike Larsen

    I’m often asked to create reports for my business partners. The format of the report depends on who made the request. If the financial team made the request, I may produce an Excel file. The CEO may want to report quarterly sales to their shareholders. In that case, I may produce a PDF using the company letterhead.

    In a prior article, I showed how to create Excel files using Db2 tables. Now I’m going to show how to create PDF documents using Db2 tables.

    This story contains code, which you can download here.

    I always start by making sure all Python packages are up to date on my IBM i. I use ACS (Access Client Solutions) to update and install Python packages as shown in Figure 1.

    Figure 1. Install and update Python packages (partial listing).

    Next, I install the packages I’m using in my Python script. I’m using ibm_db to connect to a Db2 table and fpdf to generate the PDF. To install these packages, I execute the commands in Figure 2 using an SSH terminal like Putty or Mobaxterm.

    pip3 install ibm_db
    pip3 install fpdf
    
    Figure 2. Install Python packages.

    Now that all packages are installed and up to date, I’m ready to write some code!

    I start by importing packages I’m using in my script (Figure 3). In addition to using ibm_db and fpdf, I’m also using the datetime module so I can print the date and time in the footer of the report.

    from fpdf import FPDF
    import ibm_db_dbi as db2
    from datetime import datetime
    
    Figure 3. Import packages.

    I’m printing the date and time in the format of month, day, year, hour, minute, second as shown in Figure 4.

    # datetime object containing current date and time
    now = datetime.now()
    dt_string = now.strftime("%m/%d/%Y %H:%M:%S") 
    
    Figure 4. Format the date.

    The fpdf package allows me to set up a header (Figure 5) and footer (Figure 6) for my report.  Once I define them in my script, they’re executed automatically for each new page of my report.  I’ll show each of these and explain what they’re doing.

    # - - - -
    # first line of the header
           
    # Logo
    # fpdf.image(name, x = None, y = None, w = 0, h = 0, type = '', link = '')        
      self.image('/home/MLARSEN/logo_sample.png', 10, 8, 20, 20)
            
    # Arial bold 15
      self.set_font('Arial', 'B', 15)
            
    # fpdf.cell(w, h = 0, txt = '', border = 0, ln = 0, 
    #              align = '', fill = False, link = '')
    # Title
    #
    # width = 40, height = 10, border = 0 (no border), 
    # ln = 0 (0: to the right,
    #         1: to the beginning of the next line,
    #         2: below), align = Center  
    
    self.cell(40, 10, 'Employee listing', 0, 0, 'C')
            
    # - - - -
    # second line of the header        
      self.set_font('Arial','U', 14.0)
    
      self.cell(30, 10, txt = 'First name', border = 1, ln = 0)
      self.cell(12, 10, txt = 'MI', border = 1, ln = 0)
      self.cell(30, 10, txt = 'Last name', border = 1, ln = 0)
      self.cell(30, 10, txt = 'Department', border = 1, ln = 0)
      self.cell(30, 10, txt = 'Phone no.', border = 1, ln = 0)
      self.cell(30, 10, txt = 'Job title', border = 1, ln = 0) 
    
    Figure 5. Report header.

    I have two lines in my header. On the first line, I have a logo that is pulled in from a file in the IFS.  I set the font to Arial 15 and make the text bold. Then I specify the tile of the report, Employee listing, and center it on the page.

    The second line of the header contains my column headings to match the columns I’m loading from a Db2 table.  The report in this example is producing an employee listing from a sample table on my IBM i.

    # Position at 1.5 cm from bottom
      self.set_y(-15)
           
    # Arial italic 8
      self.set_font('Arial', 'I', 8)
            
    # Page number
      self.cell(0, 10, 'Page ' + str(self.page_no()) + '/{nb}', 0, 0, 'C')
            
    # date/time
      self.cell(0, 10, dt_string, 0, 0, 'R')
    
    Figure 6. Report footer.

    For the footer, I define where on the page it should print and what font I’m using.  I also print the page number, date, and time.  The page number is printed at the center of the page and the date/time is printed at the right.

    With the header and footer in place, I’m ready to start loading the report with data from the employee table.  I start by connecting to the database, then I define and execute a cursor (Figure 7).

    conn = db2.connect()
    
    cursor = conn.cursor()
    
    cursor.execute("Select FirstNme, MidInit, LastName, WorkDept, PhoneNo, Job "
                   " From Sample.Employee ")
    
    Figure 7. Retrieve data from Employee table.

    I loop through my cursor and start printing the employees to the report (Figure 8). To make this a little more interesting, I change the font color to red when an employee has a title of MANAGER and I also use a blue font color for the first employee printed. I did this for illustrative purposes to show some additional features of fpdf.

    for row in cursor:
        
        # color can either be RGB as I did below, or you can use hex:
        #
        # pdf.set_text_color(*hex2dec('#8B6914'))
            
        if row[5].strip() == 'MANAGER':
            pdf.set_text_color(253, 7, 7)   # red
        elif lineNumber == 0:
            pdf.set_text_color(0, 0, 255)   # blue
        else:
            pdf.set_text_color(0, 0, 0)     # black
    
        pdf.cell(30, 10, txt = row[0], border = 1, ln = 0)
        pdf.cell(12, 10, txt = row[1], border = 1, ln = 0)
        pdf.cell(30, 10, txt = row[2], border = 1, ln = 0)
        pdf.cell(30, 10, txt = row[3], border = 1, ln = 0)
        pdf.cell(30, 10, txt = row[4], border = 1, ln = 0)
        pdf.cell(30, 10, txt = row[5], border = 1, ln = 0)
    
    Figure 8. Print detail lines.

    I created a summary line at the end of the report that gives a total of the number of employees printed. I also added a digital signature to the end of the report. The signature is pulled from a file in the IFS and I used the x and y coordinates to make it print on the right side of the report.

    pdf.set_text_color(0, 0, 0)     # black 
    
    pdf.cell(50, 10, txt = 'Number of Employees', border = 0, ln = 0)
    pdf.cell(12, 10, txt = str(lineNumber), border = 0, ln = 0)
    
    # create a line break.  default is 'mm' - millimeters
            
    pdf.ln(10)
    
    # get the current x and y coordinates
    
    x = pdf.get_x() + 100       # +100 moves it over horizontally to the right
    y = pdf.get_y()
    
    # fpdf.image(name, x = None, y = None, w = 0, h = 0, type = '', link = '')
    
    pdf.image('/home/MLARSEN/mike_larsen_signature.png', x, y, 50, 15)
    
    Figure 9. Print summary line.

    The last piece of code creates the PDF document in the IFS (Figure 10).

    # 'F' = file
    pdf.output("createPdf3c.pdf", 'F')
    
    Figure 10. Create the PDF in the IFS.

    I run the Python script in an SSH terminal (Figure 11) and open the PDF to review the report.  I’m only showing the first and last pages of the report (Figures 12 and 13).

    python3 createPdf3c.py
    
    Figure 11. Run the Python script.

    Figure 12. First page of Employee report.

     

    Figure 13. Last page of Employee report.

    With a short Python script, I built a nice report that lives in the IFS. From here, I could email it out to whoever needs it. Hopefully, this example will get you started creating your own PDF’s using Python. The complete code for the Python script used in this article is available for download.

    Mike Larsen is a Project Manager and Senior developer at Central Park Data Systems and has been working with IBM i systems for over 20 years. He specializes in RPG, CL, and SQL and recently has been working with Python. Current projects have given Mike the opportunity to generate PDFs and Excel files using Python. He has also built processes to call RPG programs from Python and execute Python scripts from RPG.

    RELATED STORY

    Guru: Creating Excel Spreadsheets With Python

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guru, Access Client Solutions, ACS, CL, DB2, FHG, Four Hundred Guru, IBM i, IFS, PDF, Python, RPG, SQL, SSH

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Kisco Extends Two Factor Authentication To Green Screens Some Insight Into Utility Pricing On Entry Power Iron

    4 thoughts on “Guru: Creating PDF Documents With Python”

    • Kent Grizzell says:
      July 27, 2020 at 10:38 am

      Am I overlooking the download link?

      Reply
      • Mike says:
        August 10, 2020 at 11:07 am

        Kent, the link to download the code is there now.

        Reply
    • Reynaldo Dandreb Medilla says:
      August 2, 2020 at 9:53 am

      great share Mike, thanks

      Reply
    • Ajay says:
      August 5, 2020 at 9:53 am

      Where can i find the source code?

      Reply

    Leave a Reply Cancel reply

TFH Volume: 30 Issue: 44

This Issue Sponsored By

  • TL Ashford
  • Profound Logic Software
  • RPG & DB2 Summit
  • Raz-Lee Security
  • Kisco Information Systems

Table of Contents

  • Power Systems Slump Is Not As Bad As It Looks
  • Some Insight Into Utility Pricing On Entry Power Iron
  • Guru: Creating PDF Documents With Python
  • Kisco Extends Two Factor Authentication To Green Screens
  • IBM i PTF Guide, Volume 22, Number 30

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • To Comfort The Afflicted And Afflict The Comfortable
  • How FalconStor Is Reinventing Itself, And Why IBM Noticed
  • Guru: When Procedure Driven RPG Really Works
  • Vendors Fill In The Gaps With IBM’s New MFA Solution
  • IBM i PTF Guide, Volume 27, Number 27
  • With Power11, Power Systems “Go To Eleven”
  • With Subscription Price, IBM i P20 And P30 Tiers Get Bigger Bundles
  • Izzi Buys CNX, Eyes Valence Port To System Z
  • IBM i Shops “Attacking” Security Concerns, Study Shows
  • IBM i PTF Guide, Volume 27, Number 26

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle