Search code examples
pythonimagepdfcalendar

Producing a printable calendar with Python


How can I produce a printable PDF file (US letter sized) such that each page represents a month and is partitioned such that each day of the month gets a box of equal size? What if I want to skip weekends and just display weekdays?

What Python modules would I use to accomplish the following?:

  1. Producing an image with the resolution of a US letter
  2. Iterating through each day of the month with the option to skip specific days (e.g., all weekends)
  3. Partitioning the image such that each day of the month is listed in a box of fixed size
  4. Repeating steps 2-3 for all months in a given year
  5. Producing a pdf as the output

Solution

  • You could do it with 3 packages. 'Reportlab' for producing the pdf, 'calendar' for getting the month as lists of lists, and python binding for 'Ghostscript' to transform the pdf produced into a png.

    You would start by getting the data from the calendar package, using Reportlab to produce a page of US letter size. The table can be manipulated to have a grid, have each cell a box of the same size and alter the text font, size, and alignment.

    You could leave it at that if you just want a pdf, or you can convert this pdf into a image using Ghostscript python bindings. Or if you like you can just run 'Ghostscript' using system('gs ...'). Also Ghostscript must be installed for the python 'Ghostscript' package to work.

    If you want to filter out all weekends then you can use good old fashioned list manipulation on the calendar data for that.

    Here is a example of how you could produce the pdf. I'm not going to do a whole year just a single month, and I'm not going to bother filtering out the zeros.

    from reportlab.lib.units import inch
    from reportlab.lib import colors
    from reportlab.lib.pagesizes import letter
    from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
    from reportlab.graphics.shapes import Drawing
    
    import calendar
    
    doc = SimpleDocTemplate('calendar.pdf', pagesize=letter)
    
    cal = [['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']]
    cal.extend(calendar.monthcalendar(2011,9))
    
    
    table = Table(cal, 7*[inch], len(cal) * [inch])
    
    table.setStyle(TableStyle([
            ('FONT', (0, 0), (-1, -1), 'Helvetica'),
            ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
            ('BOX', (0, 0), (-1, -1), 0.25, colors.green),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ]))
    
    #create the pdf with this
    doc.build([table])
    

    If you want another page add PageBreak() followed by the next calendar to the list passed to doc.build(). PageBreak is part of reportlab.platypus.

    And to convert the pdf to png

    import ghostscript
    
    args = ['gs', #it seems not to matter what is put in 1st position
            '-dSAFER',
            '-dBATCH',
            '-dNOPAUSE',
            '-sDEVICE=png16m',
            '-r100',
            '-sOutputFile=calendar.png',
            'calendar.pdf']
    
    ghostscript.Ghostscript(*args)
    

    Both reportlab and ghostscript packages are available through the use of pip. I created the above in a 'virtualenv' environment.

    ReportLab http://www.reportlab.com/software/opensource/rl-toolkit/

    Ghostscript python bindings https://bitbucket.org/htgoebel/python-ghostscript

    calendar is part of the standard python library.