<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Mouse Vs. The Python &#187; Reportlab</title>
	<atom:link href="http://www.blog.pythonlibrary.org/tag/reportlab/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.blog.pythonlibrary.org</link>
	<description>Python Programming from the Frontlines</description>
	<lastBuildDate>Sun, 08 Jan 2012 12:45:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Reportlab: Converting Hundreds of Images Into PDFs</title>
		<link>http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/</link>
		<comments>http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 01:36:41 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Reportlab]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2188</guid>
		<description><![CDATA[I was recently asked to convert a few hundred images into PDF pages. A friend of mine draws comics and my brother wanted to be able to read them on a tablet. Alas, if you had a bunch of files named something like this: 'Jia_01.Jpg', 'Jia_02.Jpg', 'Jia_09.Jpg', 'Jia_10.Jpg', 'Jia_11.Jpg', 'Jia_101.Jpg' the Android tablet would reorder [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/" data-url="http://bit.ly/xIgjvX" data-text="Reportlab: Converting Hundreds of Images Into PDFs" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/";
			reddit_title = "Reportlab: Converting Hundreds of Images Into PDFs";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/"></g:plusone></div></div><p>I was recently asked to convert a few hundred images into PDF pages. A friend of mine draws comics and my brother wanted to be able to read them on a tablet. Alas, if you had a bunch of files named something like this: </p>
<p><code><br />
'Jia_01.Jpg', 'Jia_02.Jpg', 'Jia_09.Jpg', 'Jia_10.Jpg', 'Jia_11.Jpg', 'Jia_101.Jpg'<br />
</code></p>
<p>the Android tablet would reorder them into something like this:</p>
<p><code><br />
'Jia_01.Jpg', 'Jia_02.Jpg', 'Jia_09.Jpg', 'Jia_10.Jpg', 'Jia_101.Jpg', 'Jia_11.Jpg'<br />
</code></p>
<p>And it got pretty confusing the more files you had that were out of order. Sadly, even Python sorts files this way. I tried using the <strong>glob</strong> module on the directly and then sorting the result and got the exact same issue. So the first thing I had to do was find some kind of sorting algorithm that could sort them correctly. It should be noted that Windows 7 can sort the files correctly in its file system, even though Python cannot. <span id="more-2188"></span></p>
<p>After a little searching on Google, I found the following script on <a href="# http://stackoverflow.com/questions/2669059/how-to-sort-alpha-numeric-set-in-python" target="_blank">StackOverflow</a>:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> sorted_nicely<span style="color: black;">&#40;</span> l <span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Sort the given iterable in the way that humans expect.
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    convert = <span style="color: #ff7700;font-weight:bold;">lambda</span> text: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> text.<span style="color: black;">isdigit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">else</span> text
    alphanum_key = <span style="color: #ff7700;font-weight:bold;">lambda</span> key: <span style="color: black;">&#91;</span> convert<span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'([0-9]+)'</span>, key<span style="color: black;">&#41;</span> <span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>l, key = alphanum_key<span style="color: black;">&#41;</span></pre>
<p>That worked perfectly! Now I just had to find a way to put each comic page on their own PDF page. Fortunately, the <a href="http://www.reportlab.com/software/opensource/" target="_blank">reportlab</a> library makes this pretty easy to accomplish. You just need to iterate over the images and insert them one at a time onto a page. It&#8217;s easier to just look at the code, so let&#8217;s do that:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">glob</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">platypus</span> <span style="color: #ff7700;font-weight:bold;">import</span> SimpleDocTemplate, Paragraph, Image, PageBreak
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">units</span> <span style="color: #ff7700;font-weight:bold;">import</span> inch
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> sorted_nicely<span style="color: black;">&#40;</span> l <span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    # http://stackoverflow.com/questions/2669059/how-to-sort-alpha-numeric-set-in-python
&nbsp;
    Sort the given iterable in the way that humans expect.
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    convert = <span style="color: #ff7700;font-weight:bold;">lambda</span> text: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> text.<span style="color: black;">isdigit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">else</span> text
    alphanum_key = <span style="color: #ff7700;font-weight:bold;">lambda</span> key: <span style="color: black;">&#91;</span> convert<span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'([0-9]+)'</span>, key<span style="color: black;">&#41;</span> <span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>l, key = alphanum_key<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> create_comic<span style="color: black;">&#40;</span>fname, front_cover, back_cover, path<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    filename = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>path, fname + <span style="color: #483d8b;">&quot;.pdf&quot;</span><span style="color: black;">&#41;</span>
    doc = SimpleDocTemplate<span style="color: black;">&#40;</span>filename,pagesize=letter,
                            rightMargin=<span style="color: #ff4500;">72</span>,leftMargin=<span style="color: #ff4500;">72</span>,
                            topMargin=<span style="color: #ff4500;">72</span>,bottomMargin=<span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>
    Story=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    width = <span style="color: #ff4500;">7.5</span><span style="color: #66cc66;">*</span>inch
    height = <span style="color: #ff4500;">9.5</span><span style="color: #66cc66;">*</span>inch
&nbsp;
    pictures = sorted_nicely<span style="color: black;">&#40;</span><span style="color: #dc143c;">glob</span>.<span style="color: #dc143c;">glob</span><span style="color: black;">&#40;</span>path + <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>%s*&quot;</span> <span style="color: #66cc66;">%</span> fname<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Image<span style="color: black;">&#40;</span>front_cover, width, height<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>PageBreak<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    x = <span style="color: #ff4500;">0</span>
    page_nums = <span style="color: black;">&#123;</span><span style="color: #ff4500;">100</span>:<span style="color: #483d8b;">'%s_101-200.pdf'</span>, <span style="color: #ff4500;">200</span>:<span style="color: #483d8b;">'%s_201-300.pdf'</span>,
                 <span style="color: #ff4500;">300</span>:<span style="color: #483d8b;">'%s_301-400.pdf'</span>, <span style="color: #ff4500;">400</span>:<span style="color: #483d8b;">'%s_401-500.pdf'</span>,
                 <span style="color: #ff4500;">500</span>:<span style="color: #483d8b;">'%s_end.pdf'</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> pic <span style="color: #ff7700;font-weight:bold;">in</span> pictures:
        parts = pic.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><span style="color: black;">&#41;</span>
        p = parts<span style="color: black;">&#91;</span><span style="color: #ff4500;">-1</span><span style="color: black;">&#93;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s&quot;</span> <span style="color: #66cc66;">%</span> fname<span style="color: black;">&#41;</span>
        page_num = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#91;</span><span style="color: #ff4500;">-1</span><span style="color: black;">&#93;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;page_num =&gt; &quot;</span>, page_num
&nbsp;
        im = Image<span style="color: black;">&#40;</span>pic, width, height<span style="color: black;">&#41;</span>
        Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>im<span style="color: black;">&#41;</span>
        Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>PageBreak<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> page_num <span style="color: #ff7700;font-weight:bold;">in</span> page_nums.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;%s created&quot;</span> <span style="color: #66cc66;">%</span> filename
            doc.<span style="color: black;">build</span><span style="color: black;">&#40;</span>Story<span style="color: black;">&#41;</span>
            filename = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>path, page_nums<span style="color: black;">&#91;</span>page_num<span style="color: black;">&#93;</span> <span style="color: #66cc66;">%</span> fname<span style="color: black;">&#41;</span>
            doc = SimpleDocTemplate<span style="color: black;">&#40;</span>filename,
                                    pagesize=letter,
                                    rightMargin=<span style="color: #ff4500;">72</span>,leftMargin=<span style="color: #ff4500;">72</span>,
                                    topMargin=<span style="color: #ff4500;">72</span>,bottomMargin=<span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>
            Story=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> pic
        x += <span style="color: #ff4500;">1</span>
&nbsp;
    Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Image<span style="color: black;">&#40;</span>back_cover, width, height<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    doc.<span style="color: black;">build</span><span style="color: black;">&#40;</span>Story<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;%s created&quot;</span> <span style="color: #66cc66;">%</span> filename
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    path = r<span style="color: #483d8b;">&quot;C:<span style="color: #000099; font-weight: bold;">\U</span>sers<span style="color: #000099; font-weight: bold;">\M</span>ike<span style="color: #000099; font-weight: bold;">\D</span>esktop<span style="color: #000099; font-weight: bold;">\S</span>am's Comics&quot;</span>
    front_cover = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>path, <span style="color: #483d8b;">&quot;FrontCover.jpg&quot;</span><span style="color: black;">&#41;</span>
    back_cover = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>path, <span style="color: #483d8b;">&quot;BackCover2.jpg&quot;</span><span style="color: black;">&#41;</span>
    create_comic<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Jia_&quot;</span>, front_cover, back_cover, path<span style="color: black;">&#41;</span></pre>
<p>Let&#8217;s break this down a bit. As usual, you have some necessary imports that are required for this code to work. You&#8217;ll note we also have that <strong>sorted_nicely</strong> function that we talked about earlier is in this code too. The main function is called <strong>create_comic</strong> and takes four arguments: fname, front_cover, back_cover, path. If you have used the reportlab toolkit before, then you&#8217;ll recognize the SimpleDocTemplate and the Story list as they&#8217;re straight out of the reportlab tutorial.</p>
<p>Anyway, you loop over the sorted pictures and add the image to the Story along with a PageBreak object. The reason there&#8217;s a conditional in the loop is because I discovered that if I tried to build the PDF with all 400+ images, I would run into a memory error. So I broke it up into a series of PDF documents that were 100 pages or less. At the end of the document, you have to call the <strong>doc</strong> object&#8217;s <strong>build</strong> method to actually create the PDF document.</p>
<p>Now you know how I ended up writing a whole slew of images into multiple PDF documents. Theoretically, you could use PyPdf to knit all the resulting PDFs together into one PDF, but I didn&#8217;t try it. You might end up with another memory error. I&#8217;ll leave that as an exercise for the reader.</p>
<h2>Source Code</h2>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2012/01/comic_maker.zip'>comic_maker.zip</a></li>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2012/01/comic_maker.tar'>comic_maker.tar</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Top Ten Articles of 2010</title>
		<link>http://www.blog.pythonlibrary.org/2010/12/30/top-ten-articles-of-2010/</link>
		<comments>http://www.blog.pythonlibrary.org/2010/12/30/top-ten-articles-of-2010/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 23:00:40 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[PyWin32]]></category>
		<category><![CDATA[SqlAlchemy]]></category>
		<category><![CDATA[wxPython]]></category>
		<category><![CDATA[PyPDF]]></category>
		<category><![CDATA[Reportlab]]></category>
		<category><![CDATA[Roundup]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=1480</guid>
		<description><![CDATA[A lot of websites are doing year-end retrospectives this week, so I thought you might find it interesting to know which articles on this blog were the most popular this year. Below you will find links to each article along with the page view count I got from Google Analytics: A Simple Step-by-Step Reportlab Tutorial, [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2010/12/30/top-ten-articles-of-2010/" data-url="http://bit.ly/vNQ57f" data-text="Top Ten Articles of 2010" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2010/12/30/top-ten-articles-of-2010/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div></div><p>A lot of websites are doing year-end retrospectives this week, so I thought you might find it interesting to know which articles on this blog were the most popular this year. Below you will find links to each article along with the page view count I got from Google Analytics:</p>
<ol>
<li><a href="http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/">A Simple Step-by-Step Reportlab Tutorial</a>, 9,709 page views, posted 03/08/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/02/03/another-step-by-step-sqlalchemy-tutorial-part-1-of-2/">Another Step-by-Step SqlAlchemy Tutorial</a> Part 1, 7,746 page views, posted 02/03/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/02/03/another-step-by-step-sqlalchemy-tutorial-part-2-of-2/">Another Step-by-Step SqlAlchemy Tutorial Part 2</a>, 4,858 page views, posted 02/03/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/05/15/manipulating-pdfs-with-python-and-pypdf/">Manipulating PDFs with Python and pyPdf</a>, 4,511 page views, posted 05/15/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/10/14/python-101-introspection/">Python 101: Introspection</a>, 4,473 page views, posted 10/14/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/04/04/wxpython-grid-tips-and-tricks/">wxPython: Grid Tips and Tricks</a>, 3,476 page views, posted 04/04/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/04/20/wxpython-creating-a-simple-mp3-player/">wxPython: Creating a Simple MP3 Player</a>, 3,401 page views, posted 04/20/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/07/16/python-and-microsoft-office-using-pywin32/">Python and Microsoft Office &#8211; Using PyWin32</a>, 3,323  page views, posted 07/16/2010</li>
<li><a href="http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/">wxPython and Threads</a>, 3,183  page views, posted 05/22/2010</li>
</ol>
<p>It would seem that SqlAlchemy and Reportlab are pretty popular topics. Are there any articles about either of these cool packages that you think I should write? As you can see, wxPython makes it into the top ten 3 times! What should I write about next regarding wxPython? </p>
<p>This upcoming year, I plan to write about some of the other GUI toolkits. Which one do you think I should do first? Tkinter, PySide, PyGUI or something else? What packages or standard libraries do you think I should cover? Feel free to let me know via the comments below or via my contact form (link at top). I&#8217;m looking forward to another year of Python tinkering and writing and I hope you are too! Thanks for your readership and encouragement this year!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2010/12/30/top-ten-articles-of-2010/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reportlab Tables &#8211; Creating Tables in PDFs with Python</title>
		<link>http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/</link>
		<comments>http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 02:16:12 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Python PDF Series]]></category>
		<category><![CDATA[Reportlab]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=1218</guid>
		<description><![CDATA[Back in March of this year, I wrote a simple tutorial on Reportlab, a handy 3rd party Python package that allows the developer to create PDFs programmatically. Recently, I received a request to cover how to do tables in Reportlab. Since my Reportlab article is so popular, I figured it was probably worth the trouble [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/" data-url="http://bit.ly/sf2cnJ" data-text="Reportlab Tables &#8211; Creating Tables in PDFs with Python" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/";
			reddit_title = "Reportlab Tables &#8211; Creating Tables in PDFs with Python";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/"></g:plusone></div></div><p>Back in March of this year, I wrote a <a href="http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/">simple tutorial</a> on Reportlab, a handy 3rd party Python package that allows the developer to create PDFs programmatically. Recently, I received a request to cover how to do tables in Reportlab. Since my Reportlab article is so popular, I figured it was probably worth the trouble to figure out tables. In this article, I will attempt to show you the basics of inserting tables into Reportlab generated PDFs.<span id="more-1218"></span></p>
<p>One of the few issues I have with Reportlab is their user guide. It shows some good examples, but they&#8217;re almost always incomplete. Go download the user guide <a href="http://www.reportlab.com/software/opensource/rl-toolkit/guide/">here</a> and start reading chapter seven (the chapter on tables) and you&#8217;ll quickly see the following code snippet:</p>
<pre class="python">LIST_STYLE = TableStyle<span style="color: black;">&#40;</span>
    <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'LINEABOVE'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">2</span>, colors.<span style="color: black;">green</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'LINEABOVE'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">0.25</span>, colors.<span style="color: black;">black</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'LINEBELOW'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">2</span>, colors.<span style="color: black;">green</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'ALIGN'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'RIGHT'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#41;</span></pre>
<p>Of course, this snippet is completely un-runnable and the text around it is pretty useless for figuring out how to import <strong>TableStyle</strong> and <strong>colors</strong>. It sounds like you can get all the Table stuff from the Flowable class (pg 76 &#8211; first page of chapter 7). Unfortunately, there is no &#8220;reportlab.Flowable&#8221;. You have to know that all the flowables come from something called <strong>platypus</strong>. Let&#8217;s stop here and talk about what a &#8220;flowable&#8221; is. Here what the user guide says:</p>
<p><em><br />
Flowables are things which can be drawn and which have wrap, draw and perhaps split methods. Flowable is an abstract base class for things to be drawn and an instance knows its size and draws in its own coordinate system (this requires the base API to provide an absolute coordinate system when the Flowable.draw method is called). To get an instance use f=Flowable().</em> (pg 62, section 5.3). Note that nowhere on that page does it show how to get the Flowable class. I only found out how by doing a text search of their source. Here&#8217;s the syntax:  <em>from reportlab.platypus import Flowable</em></p>
<p>It&#8217;s this sort of thing that made me almost give up on using Reportlab at all several years ago. Fortunately, my boss made me figure it out and had some real examples for me to follow. Alright, enough ranting. On with the tables tutorial!</p>
<h2>Getting Started with Reportlab Tables</h2>
<p>We&#8217;re actually going to take some of the table examples from the Reportlab User Guide and make them runnable. I&#8217;ll try to explain what&#8217;s going on in the code, but you may want to refer to the guide as well. Let&#8217;s start with the example on pg 78 entitled <em>TableStyle Cell Formatting Commands</em>. This first real example shows how to create a table with multiple colors, but no visible grid. Let&#8217;s make it runnable!</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span> <span style="color: #ff7700;font-weight:bold;">import</span> colors
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">platypus</span> <span style="color: #ff7700;font-weight:bold;">import</span> SimpleDocTemplate, Table, TableStyle
&nbsp;
doc = SimpleDocTemplate<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;simple_table.pdf&quot;</span>, pagesize=letter<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># container for the 'Flowable' objects</span>
elements = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
data= <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'00'</span>, <span style="color: #483d8b;">'01'</span>, <span style="color: #483d8b;">'02'</span>, <span style="color: #483d8b;">'03'</span>, <span style="color: #483d8b;">'04'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'10'</span>, <span style="color: #483d8b;">'11'</span>, <span style="color: #483d8b;">'12'</span>, <span style="color: #483d8b;">'13'</span>, <span style="color: #483d8b;">'14'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'20'</span>, <span style="color: #483d8b;">'21'</span>, <span style="color: #483d8b;">'22'</span>, <span style="color: #483d8b;">'23'</span>, <span style="color: #483d8b;">'24'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'30'</span>, <span style="color: #483d8b;">'31'</span>, <span style="color: #483d8b;">'32'</span>, <span style="color: #483d8b;">'33'</span>, <span style="color: #483d8b;">'34'</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
t=Table<span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
t.<span style="color: black;">setStyle</span><span style="color: black;">&#40;</span>TableStyle<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-2</span>,<span style="color: #ff4500;">-2</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">green</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'TEXTCOLOR'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">red</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
elements.<span style="color: black;">append</span><span style="color: black;">&#40;</span>t<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># write the document to disk</span>
doc.<span style="color: black;">build</span><span style="color: black;">&#40;</span>elements<span style="color: black;">&#41;</span></pre>
<p>If you run this code, you should see something like this centered along the top of your PDF:</p>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/09/table_with_no_grid.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/09/table_with_no_grid.png" alt="table_with_no_grid.png" title="table_with_no_grid.png" width="220" height="141" class="aligncenter size-full wp-image-1219" /></a></p>
<p>If you look at the code, you&#8217;ll notice that we have a series of imports. We import <strong>colors </strong>from &#8220;reportlab.lib&#8221;, <strong>letter</strong> from &#8220;reportlab.lib.pagesizes&#8221; and <strong>SimpleDocTemplate</strong>, <strong>Table</strong>, and <strong>TableStyle</strong> from &#8220;reportlab.platypus&#8221;.  The imports are pretty self-explanatory, but they also help us familiarize ourselves with the way that Reportlab&#8217;s code is laid out. If we need other Flowables, like Paragraph, we can probably assume that it would come from &#8220;reportlab.platypus&#8221; since Table is a Flowable. If you try it, you&#8217;ll see that this assumption is correct.</p>
<p>Next we create a document template using the <strong>SimpleDocTemplate</strong> class. The first argument is the path to the PDF that we want to create and the second argument is the page size. In this example, we just put in the name of the document. This will cause the script to put the PDF in the same folder that it&#8217;s run from. For reasons that I&#8217;ve never seen explained, you use a list to hold the flowables. In this code, we call our list &#8220;elements&#8221;. In the user guide, they call it &#8220;story&#8221;. </p>
<p>The <strong>data</strong> list holds the data that will go in our table. The list is a list of lists. The table will 5 columns wide (the length of the nested lists) and 4 rows tall (the number of nested lists). We pass this list into our <strong>Table</strong> class to create the Table in memory and then call our Table instance&#8217;s setStyle method to change the style. To do this, we pass it a <strong>TableStyle</strong> class, which contains the styles we want to apply. In this case, we want to apply a green background color from the cells in column 2, row 2 to column 3, row 2. Note that the columns and rows are zero-based so 0 = 1, 1 = 2, etc. Also notice that the example uses (-2, -2) rather than the much easier to understand (3, 2). This illustrates that you can also specify settings from the lower right corner instead of just doing everything from the top left. Unfortunately, the coordinate system starting on the lower right starts at (-1,-1) and that makes it a little harder to get one&#8217;s mind around.</p>
<p>Then we set the text color to red in the first two columns. I admit that I&#8217;m not quite sure how this works as the ending coordinates just don&#8217;t seem to fit with the ones for the background color. I&#8217;ll leave that to my readers to explain.</p>
<p>Finally, we append the table to our elements list and then call our document instance&#8217;s <strong>build</strong> method with the elements list as its only argument. This causes the document to be build and the PDF created. Now you have a PDF table!</p>
<h2>Adding a Grid to the Table</h2>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/09/table_with_grid.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/09/table_with_grid.png" alt="table_with_grid.png" title="table_with_grid.png" width="251" height="198" class="aligncenter size-full wp-image-1226" /></a></p>
<p>Let&#8217;s take the next example from the Reportlab documentation and see if we can get it to run too. This next example shows how to add a visible grid to the table as well as how to position the text within the cells.</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span> <span style="color: #ff7700;font-weight:bold;">import</span> colors
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter, inch
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">platypus</span> <span style="color: #ff7700;font-weight:bold;">import</span> SimpleDocTemplate, Table, TableStyle
&nbsp;
doc = SimpleDocTemplate<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;simple_table_grid.pdf&quot;</span>, pagesize=letter<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># container for the 'Flowable' objects</span>
elements = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
data= <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'00'</span>, <span style="color: #483d8b;">'01'</span>, <span style="color: #483d8b;">'02'</span>, <span style="color: #483d8b;">'03'</span>, <span style="color: #483d8b;">'04'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'10'</span>, <span style="color: #483d8b;">'11'</span>, <span style="color: #483d8b;">'12'</span>, <span style="color: #483d8b;">'13'</span>, <span style="color: #483d8b;">'14'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'20'</span>, <span style="color: #483d8b;">'21'</span>, <span style="color: #483d8b;">'22'</span>, <span style="color: #483d8b;">'23'</span>, <span style="color: #483d8b;">'24'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'30'</span>, <span style="color: #483d8b;">'31'</span>, <span style="color: #483d8b;">'32'</span>, <span style="color: #483d8b;">'33'</span>, <span style="color: #483d8b;">'34'</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
t=Table<span style="color: black;">&#40;</span>data,<span style="color: #ff4500;">5</span><span style="color: #66cc66;">*</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0.4</span><span style="color: #66cc66;">*</span>inch<span style="color: black;">&#93;</span>, <span style="color: #ff4500;">4</span><span style="color: #66cc66;">*</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0.4</span><span style="color: #66cc66;">*</span>inch<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
t.<span style="color: black;">setStyle</span><span style="color: black;">&#40;</span>TableStyle<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-2</span>,<span style="color: #ff4500;">-2</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'RIGHT'</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'TEXTCOLOR'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-2</span>,<span style="color: #ff4500;">-2</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">red</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'VALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'TOP'</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'TEXTCOLOR'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">blue</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'ALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'CENTER'</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'VALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'MIDDLE'</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'TEXTCOLOR'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">green</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'INNERGRID'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">0.25</span>, colors.<span style="color: black;">black</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BOX'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">0.25</span>, colors.<span style="color: black;">black</span><span style="color: black;">&#41;</span>,
                       <span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
elements.<span style="color: black;">append</span><span style="color: black;">&#40;</span>t<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># write the document to disk</span>
doc.<span style="color: black;">build</span><span style="color: black;">&#40;</span>elements<span style="color: black;">&#41;</span></pre>
<p>We have one new import here from the <strong>pagesizes</strong> library: <strong>inch</strong>. The &#8220;inch&#8221; just gives us a simple way to set sizes or margins in our PDF. In this case, we use it to set the table&#8217;s column widths and row heights. The next change is in <em>setStyle </em>section of the code and this is really the key to getting tables to look the way you want. The <em>TableStyle</em> class controls the look of the table completely. For example, the first two lines align the middle six cells to the right and color them red. The next two lines set the four cells in the first column to the color blue and to the text to the top of the cell. You can figure out the three lines on your own.</p>
<p>The last two lines of code draw the inner grid and the box around the grid. Then we append the table to our elements list and finally, build the document.</p>
<h2>Creating Complex Cell Values</h2>
<p>The last major example we&#8217;re going to look at is the Complex Cell Values example from the Reportlab user guide.  This one shows you to insert other Reportlab Flowables in the cells themselves. Let&#8217;s take a quick look!</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span> <span style="color: #ff7700;font-weight:bold;">import</span> colors
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter, inch
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">platypus</span> <span style="color: #ff7700;font-weight:bold;">import</span> Image, Paragraph, SimpleDocTemplate, Table
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">styles</span> <span style="color: #ff7700;font-weight:bold;">import</span> getSampleStyleSheet
&nbsp;
doc = SimpleDocTemplate<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;complex_cell_values.pdf&quot;</span>, pagesize=letter<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># container for the 'Flowable' objects</span>
elements = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
styleSheet = getSampleStyleSheet<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
I = Image<span style="color: black;">&#40;</span><span style="color: #483d8b;">'replogo.gif'</span><span style="color: black;">&#41;</span>
I.<span style="color: black;">drawHeight</span> = <span style="color: #ff4500;">1.25</span><span style="color: #66cc66;">*</span>inch<span style="color: #66cc66;">*</span>I.<span style="color: black;">drawHeight</span> / I.<span style="color: black;">drawWidth</span>
I.<span style="color: black;">drawWidth</span> = <span style="color: #ff4500;">1.25</span><span style="color: #66cc66;">*</span>inch
P0 = Paragraph<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
               &lt;b&gt;A pa&lt;font color=red&gt;r&lt;/font&gt;a&lt;i&gt;graph&lt;/i&gt;&lt;/b&gt;
               &lt;super&gt;&lt;font color=yellow&gt;1&lt;/font&gt;&lt;/super&gt;'</span><span style="color: #483d8b;">''</span>,
               styleSheet<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;BodyText&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
P = Paragraph<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
    &lt;para align=center spaceb=3&gt;The &lt;b&gt;ReportLab Left
    &lt;font color=red&gt;Logo&lt;/font&gt;&lt;/b&gt;
    Image&lt;/para&gt;'</span><span style="color: #483d8b;">''</span>,
    styleSheet<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;BodyText&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
data= <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'A'</span>, <span style="color: #483d8b;">'B'</span>, <span style="color: #483d8b;">'C'</span>, P0, <span style="color: #483d8b;">'D'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'00'</span>, <span style="color: #483d8b;">'01'</span>, <span style="color: #483d8b;">'02'</span>, <span style="color: black;">&#91;</span>I,P<span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'04'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'10'</span>, <span style="color: #483d8b;">'11'</span>, <span style="color: #483d8b;">'12'</span>, <span style="color: black;">&#91;</span>P,I<span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'14'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'20'</span>, <span style="color: #483d8b;">'21'</span>, <span style="color: #483d8b;">'22'</span>, <span style="color: #483d8b;">'23'</span>, <span style="color: #483d8b;">'24'</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #483d8b;">'30'</span>, <span style="color: #483d8b;">'31'</span>, <span style="color: #483d8b;">'32'</span>, <span style="color: #483d8b;">'33'</span>, <span style="color: #483d8b;">'34'</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
&nbsp;
t=Table<span style="color: black;">&#40;</span>data,style=<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'GRID'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-2</span>,<span style="color: #ff4500;">-2</span><span style="color: black;">&#41;</span>,<span style="color: #ff4500;">1</span>,colors.<span style="color: black;">green</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BOX'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: #ff4500;">2</span>,colors.<span style="color: black;">red</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'LINEABOVE'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-2</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,<span style="color: #ff4500;">1</span>,colors.<span style="color: black;">blue</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'LINEBEFORE'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>,<span style="color: #ff4500;">-2</span><span style="color: black;">&#41;</span>,<span style="color: #ff4500;">1</span>,colors.<span style="color: black;">pink</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, colors.<span style="color: black;">pink</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>, colors.<span style="color: black;">lavender</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>, colors.<span style="color: black;">orange</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BOX'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: #ff4500;">2</span>,colors.<span style="color: black;">black</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'GRID'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">-1</span>,<span style="color: #ff4500;">-1</span><span style="color: black;">&#41;</span>,<span style="color: #ff4500;">0.5</span>,colors.<span style="color: black;">black</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'VALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'BOTTOM'</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">limegreen</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">khaki</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'ALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'CENTER'</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'BACKGROUND'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,colors.<span style="color: black;">beige</span><span style="color: black;">&#41;</span>,
                    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'ALIGN'</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,<span style="color: #483d8b;">'LEFT'</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
t._argW<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>=<span style="color: #ff4500;">1.5</span><span style="color: #66cc66;">*</span>inch
&nbsp;
elements.<span style="color: black;">append</span><span style="color: black;">&#40;</span>t<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># write the document to disk</span>
doc.<span style="color: black;">build</span><span style="color: black;">&#40;</span>elements<span style="color: black;">&#41;</span></pre>
<p>This snippet has a couple new imports. First off, we need access to <strong>Image </strong>and <strong>Paragraph</strong>, which are part of the <strong>platypus </strong>lib. We also need to be able to use <strong>getSampleStyleSheet</strong>, so we import that from the <strong>styles </strong>lib. Paragraphs are flowables that allow us to use HTML-like syntax to style our text and insert images, although we don&#8217;t do the image insertion in this manner in this particular example. </p>
<p>Anyway, once again, the style is where the action is. In this example, we take a shortcut and pass the style directly into the Table object using its <strong>style</strong> parameter instead of using the Table&#8217;s &#8220;setStyle&#8221; method in combination with the TableStyle class. The result would have been the same if we had done it that way though. You should be able to parse the style yourself at this point. The only real difference was where we added the Paragraph and Image instances to the data list.</p>
<h2>Other Odds and Ends</h2>
<p>There are just a few other things to mention about Tables that didn&#8217;t really fit with the previous examples. Reportlab provides the ability to split tables when there are too many rows to fit on the page. This is enabled by default. According to the documentation, there is no way to split by column currently, so don&#8217;t bother trying to insert an extra-wide column.</p>
<p>The Table also has <strong>repeatRows</strong> and <strong>repeatCols</strong> parameters. The repeatRows parameter controls how many rows to repeat on a split. The repeatCols parameter is not currently implemented. To be honest, I&#8217;m not even sure why this parameter is even included. It&#8217;s been there for quite a while and it still does nothing.</p>
<h2>Wrapping Up</h2>
<p>Now you should have a good foundation for PDF table creation using the Reportlab toolkit. This article just scratches the surface of what Reportlab can do, so be sure to read the documentation, the tests and the various other examples on their website to truly understand the power within this handy toolkit.</p>
<h2>Further Reading</h2>
<ul>
<li>Reportlab <a href="http://www.reportlab.com/software/opensource/">Open Source</a></li>
<li>A Reportlab <a href=""http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/">Tutorial</a></li>
</ul>
<h2>Downloads</h2>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2010/09/reportlab_tables.zip'>reportlab_tables.zip</a></li>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2010/09/reportlab_tables.tar'>reportlab_tables.tar</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Simple Step-by-Step Reportlab Tutorial</title>
		<link>http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/</link>
		<comments>http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 01:03:23 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Python PDF Series]]></category>
		<category><![CDATA[Reportlab]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=668</guid>
		<description><![CDATA[The subtitle for this article could easily be &#8220;How To Create PDFs with Python&#8221;, but WordPress doesn&#8217;t support that. Anyway, the premier PDF library in Python is Reportlab. It is not distributed with that standard library, so you&#8217;ll need to download it if you want to run the examples in this tutorial. There will also [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/" data-url="http://bit.ly/sA7SS3" data-text="A Simple Step-by-Step Reportlab Tutorial" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/";
			reddit_title = "A Simple Step-by-Step Reportlab Tutorial";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/"></g:plusone></div></div><p>The subtitle for this article could easily be &#8220;How To Create PDFs with Python&#8221;, but WordPress doesn&#8217;t support that. Anyway, the premier PDF library in Python is <a href="http://www.reportlab.com/software/opensource/rl-toolkit/download/">Reportlab</a>. It is not distributed with that standard library, so you&#8217;ll need to download it if you want to run the examples in this tutorial. There will also be at least one example of how to put an image into a PDF, which means you&#8217;ll also need the <a href="http://www.pythonware.com/products/pil/">Python Imaging Library</a> (PIL). As I understand it, Reportlab is compatible with Python 2.x, <a href="http://ironpython.net/">IronPython</a> and <a href="http://www.jython.org/">Jython</a>. They are currently working on a port for Python 3.x (or will be soon).<span id="more-668"></span></p>
<h2>Installation</h2>
<p>Reportlab supports most of the normal Python installation methods. You have the option of downloading the source and running &#8220;python setup.py install&#8221; or running a binary installer (on Windows). There was a recent thread on their mailing list that seemed to indicate that they may also support <a href="http://pypi.python.org/pypi/pip">pip</a> soon. The threads I&#8217;ve read about Reportlab&#8217;s support of easy_install are confusing, so I&#8217;m not sure if they already support that method or not.</p>
<h2>Creating a Simple PDF</h2>
<p>Reportlab has decent documentation. What I mean by that is that the documentation gives you just enough to get started, but when you find something slightly complex to do, you get to figure it out on your own. Just recently, they added a <a href="http://www.reportlab.com/snippets/">Code Snippets</a> section to their website that will hopefully become a recipe book of cool tips and tricks and also help ameliorate this issue. But enough about that. Let&#8217;s see how to actually create something!</p>
<p>In Reportlab, the lowest-level component that&#8217;s used regularly is the <em>canvas</em> object from the <em>pdfgen</em> package. The functions in this package allow you to &#8220;paint&#8221; a document with your text, images, lines or whatever. I&#8217;ve heard some people describe this as writing in PostScript. I doubt it&#8217;s really that bad. In my experience, it&#8217;s actually a lot like using a GUI toolkit to layout widgets in specific locations. Let&#8217;s see how the canvas object works:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">pdfgen</span> <span style="color: #ff7700;font-weight:bold;">import</span> canvas
&nbsp;
c = canvas.<span style="color: black;">Canvas</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;hello.pdf&quot;</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span>,<span style="color: #ff4500;">750</span>,<span style="color: #483d8b;">&quot;Welcome to Reportlab!&quot;</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>You should end up with a PDF that looks something like this:</p>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/03/hello-pdf-screenshot.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/03/hello-pdf-screenshot-300x184.png" alt="" title="hello-pdf-screenshot" width="300" height="184" class="aligncenter size-medium wp-image-672" /></a></p>
<p>The first thing to notice about this code is that if we want to save the PDF, we need to supply a file name to the Canvas object. This can be an absolute path or a relative path. In this example, it should create the PDF in the same location that you run the script from. The next piece of the puzzle is the <em>drawString</em> method. This will draw text wherever you tell it to. When using the canvas object, it starts at the bottom left of the page, so for this example, we told it to draw the string 100 points from the left margin and 750 points from the bottom of the page (1 point = 1/72 inch). You can change this default in the Canvas constructor by passing a zero to the <em>bottomup </em>keyword argument. However, I&#8217;m not exactly sure what will happen if you do that as the Reportlab user guide isn&#8217;t clear on this topic. I think it will change the start point to the top left though. The final piece in the code above is to save your PDF.</p>
<p>That was easy! You&#8217;ve just created a really simple PDF! Note that the default Canvas size is A4, so if you happen to be American, you&#8217;ll probably want to change that to letter size. This is easy to do in Reportlab. All you need to do is the following:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">pdfgen</span> <span style="color: #ff7700;font-weight:bold;">import</span> canvas
&nbsp;
canvas = canvas.<span style="color: black;">Canvas</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'myfile.pdf'</span>, pagesize=letter<span style="color: black;">&#41;</span>
width, height = letter</pre>
<p>The main reason to grab the width and height is that you can use them for calculations to decide when to add a page break or help define margins. Let&#8217;s take a quick look at the constructor for the Canvas object to see what other options we have:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>,filename,
    pagesize=letter,
    bottomup = <span style="color: #ff4500;">1</span>,
    pageCompression=<span style="color: #ff4500;">0</span>,
    encoding=rl_config.<span style="color: black;">defaultEncoding</span>,
    verbosity=<span style="color: #ff4500;">0</span>
    encrypt=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:</pre>
<p>The above was pulled directly from the <a href="http://www.reportlab.com/docs/reportlab-userguide.pdf">Reportlab User Guide</a>, page 11. You can read about the other options in their guide if you want the full details. </p>
<p>Now let&#8217;s do something a little more complicated and useful.</p>
<h2>A Little Form, Little Function</h2>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/03/pdf-partial-form.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/03/pdf-partial-form-300x88.png" alt="" title="pdf-partial-form" width="300" height="88" class="aligncenter size-medium wp-image-677" /></a></p>
<p>In this example, we&#8217;ll create a partial printable form. As far as I can tell, Reportlab doesn&#8217;t support the fillable forms that were added to Adobe products a few years ago. Anyway, let&#8217;s take a look at some code!</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">pdfgen</span> <span style="color: #ff7700;font-weight:bold;">import</span> canvas
&nbsp;
canvas = canvas.<span style="color: black;">Canvas</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;form.pdf&quot;</span>, pagesize=letter<span style="color: black;">&#41;</span>
canvas.<span style="color: black;">setLineWidth</span><span style="color: black;">&#40;</span>.<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">setFont</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Helvetica'</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
&nbsp;
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">30</span>,<span style="color: #ff4500;">750</span>,<span style="color: #483d8b;">'OFFICIAL COMMUNIQUE'</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">30</span>,<span style="color: #ff4500;">735</span>,<span style="color: #483d8b;">'OF ACME INDUSTRIES'</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">500</span>,<span style="color: #ff4500;">750</span>,<span style="color: #483d8b;">&quot;12/12/2010&quot;</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">line</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">480</span>,<span style="color: #ff4500;">747</span>,<span style="color: #ff4500;">580</span>,<span style="color: #ff4500;">747</span><span style="color: black;">&#41;</span>
&nbsp;
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">275</span>,<span style="color: #ff4500;">725</span>,<span style="color: #483d8b;">'AMOUNT OWED:'</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">500</span>,<span style="color: #ff4500;">725</span>,<span style="color: #483d8b;">&quot;$1,000.00&quot;</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">line</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">378</span>,<span style="color: #ff4500;">723</span>,<span style="color: #ff4500;">580</span>,<span style="color: #ff4500;">723</span><span style="color: black;">&#41;</span>
&nbsp;
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">30</span>,<span style="color: #ff4500;">703</span>,<span style="color: #483d8b;">'RECEIVED BY:'</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">line</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">120</span>,<span style="color: #ff4500;">700</span>,<span style="color: #ff4500;">580</span>,<span style="color: #ff4500;">700</span><span style="color: black;">&#41;</span>
canvas.<span style="color: black;">drawString</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">120</span>,<span style="color: #ff4500;">703</span>,<span style="color: #483d8b;">&quot;JOHN DOE&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
canvas.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>This is based on an actual receipt I created at work. The main difference between this one and the previous example is the <em>canvas.line</em> code. You can use it to draw lines on your documents by passing two X/Y pairs. I&#8217;ve used this functionality to create grids, although it&#8217;s pretty tedious. Other points of interest in this code include the setLineWidth(.3) command, which tells Reportlab how thick or thin the line should be; and the setFont(&#8216;Helvetica&#8217;, 12) command, which allows us to specify a specific font and point size. </p>
<p>Our next example will build on what we&#8217;ve learned so far, but also introduce us to the concept of &#8220;flowables&#8221;.</p>
<h2>Going with the Flow</h2>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/03/pdf-form-letter.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2010/03/pdf-form-letter-300x246.png" alt="" title="pdf-form-letter" width="300" height="246" class="aligncenter size-medium wp-image-678" /></a></p>
<p>If you&#8217;re in advertising or do any kind of work with form letters, then Reportlab makes for an excellent addition to your arsenal. We use it to create form letters for people who have overdue parking tickets. The following example is based on some code I wrote for that application, although the letter is quite a bit different. (Note that the code below will not run without the Python Imaging Library)</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">enums</span> <span style="color: #ff7700;font-weight:bold;">import</span> TA_JUSTIFY
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">pagesizes</span> <span style="color: #ff7700;font-weight:bold;">import</span> letter
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">platypus</span> <span style="color: #ff7700;font-weight:bold;">import</span> SimpleDocTemplate, Paragraph, Spacer, Image
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">styles</span> <span style="color: #ff7700;font-weight:bold;">import</span> getSampleStyleSheet, ParagraphStyle
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">units</span> <span style="color: #ff7700;font-weight:bold;">import</span> inch
&nbsp;
doc = SimpleDocTemplate<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;form_letter.pdf&quot;</span>,pagesize=letter,
                        rightMargin=<span style="color: #ff4500;">72</span>,leftMargin=<span style="color: #ff4500;">72</span>,
                        topMargin=<span style="color: #ff4500;">72</span>,bottomMargin=<span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>
Story=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
logo = <span style="color: #483d8b;">&quot;python_logo.png&quot;</span>
magName = <span style="color: #483d8b;">&quot;Pythonista&quot;</span>
issueNum = <span style="color: #ff4500;">12</span>
subPrice = <span style="color: #483d8b;">&quot;99.00&quot;</span>
limitedDate = <span style="color: #483d8b;">&quot;03/05/2010&quot;</span>
freeGift = <span style="color: #483d8b;">&quot;tin foil hat&quot;</span>
&nbsp;
formatted_time = <span style="color: #dc143c;">time</span>.<span style="color: black;">ctime</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
full_name = <span style="color: #483d8b;">&quot;Mike Driscoll&quot;</span>
address_parts = <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;411 State St.&quot;</span>, <span style="color: #483d8b;">&quot;Marshalltown, IA 50158&quot;</span><span style="color: black;">&#93;</span>
&nbsp;
im = Image<span style="color: black;">&#40;</span>logo, <span style="color: #ff4500;">2</span><span style="color: #66cc66;">*</span>inch, <span style="color: #ff4500;">2</span><span style="color: #66cc66;">*</span>inch<span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>im<span style="color: black;">&#41;</span>
&nbsp;
styles=getSampleStyleSheet<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
styles.<span style="color: black;">add</span><span style="color: black;">&#40;</span>ParagraphStyle<span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">'Justify'</span>, alignment=TA_JUSTIFY<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;%s&lt;/font&gt;'</span> <span style="color: #66cc66;">%</span> formatted_time
&nbsp;
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Create return address</span>
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;%s&lt;/font&gt;'</span> <span style="color: #66cc66;">%</span> full_name
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> part <span style="color: #ff7700;font-weight:bold;">in</span> address_parts:
    ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;%s&lt;/font&gt;'</span> <span style="color: #66cc66;">%</span> part.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;Dear %s:&lt;/font&gt;'</span> <span style="color: #66cc66;">%</span> full_name.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;We would like to welcome you to our subscriber base for %s Magazine! <span style="color: #000099; font-weight: bold;">\</span>
        You will receive %s issues at the excellent introductory price of $%s. Please respond by<span style="color: #000099; font-weight: bold;">\</span>
        %s to start receiving your subscription and get the following free gift: %s.&lt;/font&gt;'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>magName,
                                                                                                issueNum,
                                                                                                subPrice,
                                                                                                limitedDate,
                                                                                                freeGift<span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Justify&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;Thank you very much and we look forward to serving you.&lt;/font&gt;'</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Justify&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;Sincerely,&lt;/font&gt;'</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">48</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;Ima Sucker&lt;/font&gt;'</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Spacer<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
doc.<span style="color: black;">build</span><span style="color: black;">&#40;</span>Story<span style="color: black;">&#41;</span></pre>
<p>Well, that&#8217;s a lot more code than our previous examples contained. We&#8217;ll need to look over it slowly to understand everything that&#8217;s going on. When you&#8217;re ready, just continue reading.</p>
<p>The first part that we need to look at are the new imports:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">enums</span> <span style="color: #ff7700;font-weight:bold;">import</span> TA_JUSTIFY
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">platypus</span> <span style="color: #ff7700;font-weight:bold;">import</span> SimpleDocTemplate, Paragraph, Spacer, Image
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">styles</span> <span style="color: #ff7700;font-weight:bold;">import</span> getSampleStyleSheet, ParagraphStyle
<span style="color: #ff7700;font-weight:bold;">from</span> reportlab.<span style="color: black;">lib</span>.<span style="color: black;">units</span> <span style="color: #ff7700;font-weight:bold;">import</span> inch</pre>
<p>From enums, we import &#8220;TA_JUSTIFY&#8221;, which allows our strings to have the <em>justified </em>format. There are a number of other constants we could import that would allow us to right or left justify our text and do other fun things. Next is the platypus (which stands for Page Layout and Typography Using Scripts) module. It contains lots of modules, but probably the most important of them are the flowables, such as Paragraph. A flowable typically has the following abilities: <em>wrap</em>, <em>draw</em> and sometimes <em>split</em>. They are used to make writing paragraphs, tables and other constructs over multiple pages easier to do.</p>
<p>The SimpleDocTemplate class allows us to set up margins, page size, filename and a bunch of other settings for our document all in one place. A Spacer is good for adding a line of blank space, like a paragraph break. The Image class utilizes the Python Image Library to allow easy insertion and manipulation of images in your PDF. </p>
<p>The getSampleStyleSheet gets a set of default styles that we can use in our PDF. ParagraphStyle is used to set our paragraph&#8217;s text alignment in this example, but it can do much more than that (see page 67 of the user guide). Finally, the <em>inch</em> is a unit of measurement to help in positioning items on your PDF. You can see this in action where we position the logo: Image(logo, 2*inch, 2*inch). This means that the logo will be two inches from the top and two inches from the left.</p>
<p>I don&#8217;t recall the reason why Reportlab&#8217;s examples use a Story list, but that&#8217;s how we&#8217;ll do it here as well. Basically you create a line of text, a table, and image or whatever and append it to the Story list. You&#8217;ll see that throughout the entire example. The first time we use it is when we add the image. Before we look at the next instance, we&#8217;ll need to look at how we add a style to our styles object:</p>
<pre class="python">styles.<span style="color: black;">add</span><span style="color: black;">&#40;</span>ParagraphStyle<span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">'Justify'</span>, alignment=TA_JUSTIFY<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre>
<p>The reason this is important is because you can use the style list to apply various paragraph alignment settings (and more) to text in your document. In the code above, we create a ParagraphStyle called &#8220;Justify&#8221;. All it does is justify our text. You&#8217;ll see an example of this later in the text. For now, let&#8217;s look at a quick example:</p>
<pre class="python">ptext = <span style="color: #483d8b;">'&lt;font size=12&gt;%s&lt;/font&gt;'</span> <span style="color: #66cc66;">%</span> formatted_time
Story.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Paragraph<span style="color: black;">&#40;</span>ptext, styles<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Normal&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre>
<p>For our first line of text, we use the Paragraph class. As you can see, the Paragraph class accepts some HTML-like tags. In this instance, we set the font&#8217;s point size to 12 and use the normal style (which is left aligned, among other things). The rest of the example is pretty much the same, just with Spacers thrown in here and there. At the end, we call <em>doc.build</em> to create the document.</p>
<h2>Wrapping Up</h2>
<p>Now you know the basics for creating PDFs in Python using Reportlab. We didn&#8217;t even scratch the surface of what all you can do with Reportlab though. Some examples include tables, graphs, paginating, color overprinting, hyperlinks, graphics and much more. I highly recommend that you download the module along with its user guide and give it a try!</p>
<p><b>Further Reading</b></p>
<ul>
<li><a href="http://www.reportlab.com/software/opensource/">Reportlab Home Page</a></li>
<li><a href="http://www.protocolostomy.com/2008/10/22/generating-reports-with-charts-using-python-reportlab/">Generating Reports with Charts</a></li>
<li><a href="http://stochasticgeometry.wordpress.com/2009/01/06/reportlab/">A series on Reportlab</a></li>
</ul>
<li><a href="http://www.magitech.org/2006/05/05/getting-started-with-reportlab/">Getting Started with Reportlab</a></li>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 2.685 seconds -->

