1#!/bin/env python 2#Copyright ReportLab Europe Ltd. 2000-2017 3#see license.txt for license details 4__version__='3.3.0' 5__doc__='Test script for reportlab.tables' 6from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation 7setOutDir(__name__) 8import os,unittest 9from reportlab.platypus import Spacer, SimpleDocTemplate, Table, TableStyle, FrameBG 10from reportlab.platypus.paragraph import Paragraph 11from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 12from reportlab.lib.units import inch, cm 13from reportlab.lib import colors 14from reportlab.graphics.charts.linecharts import HorizontalLineChart 15from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin 16from reportlab.graphics.charts.barcharts import VerticalBarChart 17 18styleSheet = getSampleStyleSheet() 19 20def getTable(): 21 t = Table((('','North','South','East','West'), 22 ('Quarter 1',100,200,300,400), 23 ('Quarter 2',100,400,600,800), 24 ('Total',300,600,900,'1,200')), 25 (72,36,36,36,36), 26 (24, 16,16,18) 27 ) 28 return t 29 30def makeStyles(): 31 styles = [] 32 for i in range(5): 33 styles.append(TableStyle([('ALIGN', (1,1), (-1,-1), 'RIGHT'), 34 ('ALIGN', (0,0), (-1,0), 'CENTRE'), 35 ('HREF', (0,0), (0,0), 'www.google.com'), 36 ])) 37 for style in styles[1:]: 38 style.add('GRID', (0,0), (-1,-1), 0.25, colors.black) 39 for style in styles[2:]: 40 style.add('LINEBELOW', (0,0), (-1,0), 2, colors.black) 41 for style in styles[3:]: 42 style.add('LINEABOVE', (0, -1), (-1,-1), 2, colors.black) 43 styles[-1].add('LINEBELOW',(1,-1), (-1, -1), 2, (0.5, 0.5, 0.5)) 44 return styles 45 46def run(): 47 doc = SimpleDocTemplate(outputfile('test_platypus_tables.pdf'), pagesize=(8.5*inch, 11*inch), showBoundary=1) 48 lst = [] 49 from reportlab import Version 50 styNormal = styleSheet['Normal'] 51 styBackground = ParagraphStyle('background', parent=styNormal, backColor=colors.pink) 52 styH1 = styleSheet['Heading1'] 53 lst.append(FrameBG(color=colors.red)) 54 lst.append(Paragraph("First, a test of how tables align their content...", styH1)) 55 lst.append(Paragraph("""Generated with version %s""" % Version, 56 styNormal)) 57 lst.append(Paragraph("""In release 2.3, cells with plain text positioned their 58 text differently to cells with Paragraphs using the 59 same font. Hopefully now they are back on the same baseline""", 60 styNormal)) 61 lst.append(FrameBG(color=colors.blue)) 62 ts1 = TableStyle([ 63 ('ALIGN', (0,0), (-1,0), 'RIGHT'), 64 ('BACKGROUND', (0,0), (-1,0), colors.lightgrey), 65 ('VALIGN', (0,0), (-1,-1), 'TOP'), 66 ('GRID', (0,0), (-1,-1), 0.25, colors.black), 67 ]) 68 t1 = Table([ 69 ('plain text','plain text','shortpara','plain text', 'long para'), 70 ('Text','more text', Paragraph('Is this para level?', styBackground), 'Back to text', Paragraph('Short para again', styBackground)), 71 ('Text', 72 'more text', 73 Paragraph('Is this level?', styBackground), 74 'This is plain\ntext with line breaks\nto compare against\nthe para on right', 75 Paragraph('Long paragraph we expect to wrap over several lines accurately', styBackground)), 76 77 ]) 78 t1.setStyle(ts1) 79 lst.append(t1) 80 lst.append(FrameBG(start=False)) 81 lst.append(Spacer(0,10)) 82 lst.append(Paragraph("Now we make a table with just one cell containing a string...note how the text sits low", styNormal)) 83 lst.append(FrameBG(start=False)) 84 85 tsGrid = TableStyle([ 86 ('GRID', (0,0), (-1,-1), 0.25, colors.black), 87 ]) 88 lst.append(Table([['One cell of plain text']], style=tsGrid, colWidths=[200])) 89 90 lst.append(Spacer(0,10)) 91 lst.append(Paragraph("Now we make a table with just one cell containing a para...should be same position. Note that the overall bounding box is an approximation and lies - it always did.", styNormal)) 92 lst.append(Table([[Paragraph('One cell containing a paragraph. ÄÉ∫', styBackground)]], style=tsGrid, colWidths=[200])) 93 94 lst.append(Spacer(0,10)) 95 lst.append(Paragraph("Paragraphs jumped up post 2.1. Ideally they should align the same.", styNormal)) 96 97 98 lst.append(Spacer(0,30)) 99 lst.append(Paragraph("Now for all the tests we had before. See also the much longer test_platypus_tables_2.pdf, which for reasons unknown was split into a separate file generated by the same script", styNormal)) 100 101 styles = makeStyles() 102 for style in styles: 103 t = getTable() 104 t.setStyle(style) 105## print '--------------' 106## for rowstyle in t._cellstyles: 107## for s in rowstyle: 108## print s.alignment 109 lst.append(t) 110 lst.append(Spacer(0,12)) 111 112 t=Table([['VERTICAL Gradient Red top, grey bottom','Horizontal Gradient Blue left, green right'], 113 ['HORIZONTAL Gradient Span grey left red right', ''], 114 ['VERTICAL Gradiant Span Blue top green bottom',''], 115 ['','CLEAR']],[3.5*inch, 2.7*inch]) 116 style=TableStyle([ 117 ('SPAN', (0,1),(1,1)), 118 ('SPAN', (0,2),(0,3)), 119 ('BACKGROUND',(0,0), (0,0),['VERTICAL', colors.grey, colors.red]), 120 ('BACKGROUND',(1,0), (1,0),['HORIZONTAL', colors.blue, colors.green]), 121 ('BACKGROUND',(0,1), (1,1),['HORIZONTAL', colors.grey, colors.red]), 122 ('BACKGROUND',(0,2), (0,3),['VERTICAL', colors.blue, colors.green]) 123 ]) 124 t.setStyle(style) 125 lst.append(t) 126 127 #illustrate usage of minRowHeights idea from Jon Hinton inivatajon @ bitbucket.org 128 t=Table([['VERTICAL Red --> grey minRowHeights[0]=30','Horizontal Gradient Blue left, green right'], 129 ['HORIZONTAL Gradient Span grey left red right', ''], 130 ['VERTICAL Gradiant Span Blue top green bottom',''], 131 ['','CLEAR']],[3.5*inch, 2.7*inch],minRowHeights=(30,), spaceBefore=15) 132 style=TableStyle([ 133 ('SPAN', (0,1),(1,1)), 134 ('SPAN', (0,2),(0,3)), 135 ('VALIGN', (0,0),(-1,0),'MIDDLE'), 136 ('BACKGROUND',(0,0), (0,0),['VERTICAL', colors.grey, colors.red]), 137 ('BACKGROUND',(1,0), (1,0),['HORIZONTAL', colors.blue, colors.green]), 138 ('BACKGROUND',(0,1), (1,1),['HORIZONTAL', colors.grey, colors.red]), 139 ('BACKGROUND',(0,2), (0,3),['VERTICAL', colors.blue, colors.green]) 140 ]) 141 t.setStyle(style) 142 143 t=Table([],[3.5*inch, 2.7*inch],minRowHeights=(30,), spaceBefore=15, style=style, emptyTableAction='ignore') 144 lst.append(t) 145 doc.build(lst) 146 147class TableBarChart(_DrawingEditorMixin,Drawing): 148 def __init__(self,width=400,height=200,*args,**kw): 149 Drawing.__init__(self,width,height,*args,**kw) 150 self.width = 136 151 self.height = 140 152 self._add(self,VerticalBarChart(),name='chart',validate=None,desc=None) 153 self.chart.y = 20 154 self.chart.width = self.width - 21 155 self.chart.height = self.height - 24 156 self.chart.categoryAxis.categoryNames = ['Spring','Summer','Autumn','Winter'] 157 self.chart.categoryAxis.labels.fontSize = 7 158 159def old_tables_test(): 160 from reportlab.lib.units import inch, cm 161 from reportlab.platypus.flowables import Image, PageBreak, Spacer, XBox 162 from reportlab.platypus.paragraph import Paragraph 163 from reportlab.platypus.xpreformatted import XPreformatted 164 from reportlab.platypus.flowables import Preformatted 165 from reportlab.platypus.doctemplate import SimpleDocTemplate 166 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 167 from reportlab.platypus.tables import GRID_STYLE, BOX_STYLE, LABELED_GRID_STYLE, COLORED_GRID_STYLE, LIST_STYLE, LongTable 168 rowheights = (24, 16, 16, 16, 16) 169 rowheights2 = (24, 16, 16, 16, 30) 170 colwidths = (50, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32) 171 data = ( 172 ('', 'Jan', 'Feb', 'Mar','Apr','May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), 173 ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89), 174 ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119), 175 ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13), 176 ('Hats', 893, 912, '1,212', 643, 789, 159, 888, '1,298', 832, 453, '1,344','2,843') 177 ) 178 data2 = ( 179 ('', 'Jan', 'Feb', 'Mar','Apr','May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), 180 ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89), 181 ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119), 182 ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13), 183 ('Hats\nLarge', 893, 912, '1,212', 643, 789, 159, 888, '1,298', 832, 453, '1,344','2,843') 184 ) 185 lst = [] 186 lst_add = lst.append 187 lst_add(Paragraph("Tables", styleSheet['Heading1'])) 188 lst_add(Paragraph(__doc__, styleSheet['BodyText'])) 189 lst_add(Paragraph("The Tables (shown in different styles below) were created using the following code:", styleSheet['BodyText'])) 190 lst_add(Preformatted(""" 191 colwidths = (50, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32) 192 rowheights = (24, 16, 16, 16, 16) 193 data = ( 194 ('', 'Jan', 'Feb', 'Mar','Apr','May', 'Jun', 195 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), 196 ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89), 197 ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119), 198 ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13), 199 ('Hats', 893, 912, '1,212', 643, 789, 159, 200 888, '1,298', 832, 453, '1,344','2,843') 201 ) 202 t = Table(data, colwidths, rowheights) 203 """, styleSheet['Code'], dedent=4)) 204 lst_add(Paragraph(""" 205 You can then give the Table a TableStyle object to control its format. The first TableStyle used was 206 created as follows: 207 """, styleSheet['BodyText'])) 208 lst_add(Preformatted(""" 209GRID_STYLE = TableStyle( 210 [('GRID', (0,0), (-1,-1), 0.25, colors.black), 211 ('ALIGN', (1,1), (-1,-1), 'RIGHT')] 212 ) 213 """, styleSheet['Code'])) 214 lst_add(Paragraph(""" 215 TableStyles are created by passing in a list of commands. There are two types of commands - line commands 216 and cell formatting commands. In all cases, the first three elements of a command are the command name, 217 the starting cell and the ending cell. 218 """, styleSheet['BodyText'])) 219 lst_add(Paragraph(""" 220 Line commands always follow this with the weight and color of the desired lines. Colors can be names, 221 or they can be specified as a (R,G,B) tuple, where R, G and B are floats and (0,0,0) is black. The line 222 command names are: GRID, BOX, OUTLINE, INNERGRID, LINEBELOW, LINEABOVE, LINEBEFORE 223 and LINEAFTER. BOX and OUTLINE are equivalent, and GRID is the equivalent of applying both BOX and 224 INNERGRID. 225 """, styleSheet['BodyText'])) 226 lst_add(Paragraph(""" 227 Cell formatting commands are: 228 """, styleSheet['BodyText'])) 229 lst_add(Paragraph(""" 230 FONT - takes fontname, fontsize and (optional) leading. 231 """, styleSheet['Definition'])) 232 lst_add(Paragraph(""" 233 TEXTCOLOR - takes a color name or (R,G,B) tuple. 234 """, styleSheet['Definition'])) 235 lst_add(Paragraph(""" 236 ALIGNMENT (or ALIGN) - takes one of LEFT, RIGHT, CENTRE (or CENTER) or DECIMAL. 237 """, styleSheet['Definition'])) 238 lst_add(Paragraph(""" 239 LEFTPADDING - defaults to 6. 240 """, styleSheet['Definition'])) 241 lst_add(Paragraph(""" 242 RIGHTPADDING - defaults to 6. 243 """, styleSheet['Definition'])) 244 lst_add(Paragraph(""" 245 BOTTOMPADDING - defaults to 3. 246 """, styleSheet['Definition'])) 247 lst_add(Paragraph(""" 248 A tablestyle is applied to a table by calling Table.setStyle(tablestyle). 249 """, styleSheet['BodyText'])) 250 t = Table(data, colwidths, rowheights) 251 t.setStyle(GRID_STYLE) 252 lst_add(PageBreak()) 253 lst_add(Paragraph("This is GRID_STYLE\n", styleSheet['BodyText'])) 254 lst_add(t) 255 256 t = Table(data, colwidths, rowheights) 257 t.setStyle(BOX_STYLE) 258 lst_add(Paragraph("This is BOX_STYLE\n", styleSheet['BodyText'])) 259 lst_add(t) 260 lst_add(Paragraph(""" 261 It was created as follows: 262 """, styleSheet['BodyText'])) 263 lst_add(Preformatted(""" 264BOX_STYLE = TableStyle( 265 [('BOX', (0,0), (-1,-1), 0.50, colors.black), 266 ('ALIGN', (1,1), (-1,-1), 'RIGHT')] 267 ) 268 """, styleSheet['Code'])) 269 270 t = Table(data, colwidths, rowheights) 271 t.setStyle(LABELED_GRID_STYLE) 272 lst_add(Paragraph("This is LABELED_GRID_STYLE\n", styleSheet['BodyText'])) 273 lst_add(t) 274 t = Table(data2, colwidths, rowheights2) 275 t.setStyle(LABELED_GRID_STYLE) 276 lst_add(Paragraph("This is LABELED_GRID_STYLE ILLUSTRATES EXPLICIT LINE SPLITTING WITH NEWLINE (different heights and data)\n", styleSheet['BodyText'])) 277 lst_add(t) 278 lst_add(Paragraph(""" 279 It was created as follows: 280 """, styleSheet['BodyText'])) 281 lst_add(Preformatted(""" 282LABELED_GRID_STYLE = TableStyle( 283 [('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), 284 ('BOX', (0,0), (-1,-1), 2, colors.black), 285 ('LINEBELOW', (0,0), (-1,0), 2, colors.black), 286 ('LINEAFTER', (0,0), (0,-1), 2, colors.black), 287 ('ALIGN', (1,1), (-1,-1), 'RIGHT')] 288 ) 289 """, styleSheet['Code'])) 290 lst_add(PageBreak()) 291 292 t = Table(data, colwidths, rowheights) 293 t.setStyle(COLORED_GRID_STYLE) 294 lst_add(Paragraph("This is COLORED_GRID_STYLE\n", styleSheet['BodyText'])) 295 lst_add(t) 296 lst_add(Paragraph(""" 297 It was created as follows: 298 """, styleSheet['BodyText'])) 299 lst_add(Preformatted(""" 300COLORED_GRID_STYLE = TableStyle( 301 [('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), 302 ('BOX', (0,0), (-1,-1), 2, colors.red), 303 ('LINEBELOW', (0,0), (-1,0), 2, colors.black), 304 ('LINEAFTER', (0,0), (0,-1), 2, colors.black), 305 ('ALIGN', (1,1), (-1,-1), 'RIGHT')] 306 ) 307 """, styleSheet['Code'])) 308 309 t = Table(data, colwidths, rowheights) 310 t.setStyle(LIST_STYLE) 311 lst_add(Paragraph("This is LIST_STYLE\n", styleSheet['BodyText'])) 312 lst_add(t) 313 lst_add(Paragraph(""" 314 It was created as follows: 315 """, styleSheet['BodyText'])) 316 lst_add(Preformatted(""" 317LIST_STYLE = TableStyle( 318 [('LINEABOVE', (0,0), (-1,0), 2, colors.green), 319 ('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black), 320 ('LINEBELOW', (0,-1), (-1,-1), 2, colors.green), 321 ('ALIGN', (1,1), (-1,-1), 'RIGHT')] 322 ) 323 """, styleSheet['Code'])) 324 325 t = Table(data, colwidths, rowheights) 326 ts = TableStyle( 327 [('LINEABOVE', (0,0), (-1,0), 2, colors.green), 328 ('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black), 329 ('LINEBELOW', (0,-1), (-1,-1), 3, colors.green,'butt'), 330 ('LINEBELOW', (0,-1), (-1,-1), 1, colors.white,'butt'), 331 ('ALIGN', (1,1), (-1,-1), 'RIGHT'), 332 ('TEXTCOLOR', (0,1), (0,-1), colors.red), 333 ('BACKGROUND', (0,0), (-1,0), colors.Color(0,0.7,0.7))] 334 ) 335 t.setStyle(ts) 336 lst_add(Paragraph("This is a custom style\n", styleSheet['BodyText'])) 337 lst_add(t) 338 lst_add(Paragraph(""" 339 It was created as follows: 340 """, styleSheet['BodyText'])) 341 lst_add(Preformatted(""" 342 ts = TableStyle( 343 [('LINEABOVE', (0,0), (-1,0), 2, colors.green), 344 ('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black), 345 ('LINEBELOW', (0,-1), (-1,-1), 3, colors.green,'butt'), 346 ('LINEBELOW', (0,-1), (-1,-1), 1, colors.white,'butt'), 347 ('ALIGN', (1,1), (-1,-1), 'RIGHT'), 348 ('TEXTCOLOR', (0,1), (0,-1), colors.red), 349 ('BACKGROUND', (0,0), (-1,0), colors.Color(0,0.7,0.7))] 350 ) 351 """, styleSheet['Code'])) 352 data = ( 353 ('', 'Jan\nCold', 'Feb\n', 'Mar\n','Apr\n','May\n', 'Jun\nHot', 'Jul\n', 'Aug\nThunder', 'Sep\n', 'Oct\n', 'Nov\n', 'Dec\n'), 354 ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89), 355 ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119), 356 ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13), 357 ('Hats', 893, 912, '1,212', 643, 789, 159, 888, '1,298', 832, 453, '1,344','2,843') 358 ) 359 c = list(colwidths) 360 c[0] = None 361 c[8] = None 362 t = Table(data, c, [None]+list(rowheights[1:])) 363 t.setStyle(LIST_STYLE) 364 lst_add(Paragraph(""" 365 This is a LIST_STYLE table with the first rowheight set to None ie automatic. 366 The top row cells are split at a newline '\\n' character. The first and August 367 column widths were also set to None. 368 """, styleSheet['BodyText'])) 369 lst_add(t) 370 371 lst_add(Paragraph(""" 372 This demonstrates a number of features useful in financial statements. The first is decimal alignment; 373 with ALIGN=DECIMAL the numbers align on the points; and the points are aligned based on 374 the RIGHTPADDING, which is usually 3 points so you should set it higher. The second is multiple lines; 375 one can specify double or triple lines and control the separation if desired. Finally, the coloured 376 negative numbers were (we regret to say) done in the style; we don't have a way to conditionally 377 format numbers based on value yet. 378 """, styleSheet['BodyText'])) 379 380 381 t = Table([['Corporate Assets','Amount'], 382 ['Fixed Assets','1,234,567.89'], 383 ['Company Vehicle','1,234.8901'], 384 ['Petty Cash','42'], 385 [u'Intellectual Property\u00ae','(42,078,231.56)'], 386 ['Overdraft','(12,345)'], 387 ['Boardroom Flat Screen','60 inches'], 388 ['Net Position','Deep Sh*t.Really'] 389 ], 390 [144,72]) 391 392 ts = TableStyle( 393 [#first the top row 394 ('ALIGN', (1,1), (-1,-1), 'CENTER'), 395 ('LINEABOVE', (0,0), (-1,0), 1, colors.purple), 396 ('LINEBELOW', (0,0), (-1,0), 1, colors.purple), 397 ('FONT', (0,0), (-1,0), 'Times-Bold'), 398 399 #bottom row has a line above, and two lines below 400 ('LINEABOVE', (0,-1), (-1,-1), 1, colors.purple), #last 2 are count, sep 401 ('LINEBELOW', (0,-1), (-1,-1), 0.5, colors.purple, 1, None, None, 4,1), 402 ('LINEBELOW', (0,-1), (-1,-1), 1, colors.red), 403 ('FONT', (0,-1), (-1,-1), 'Times-Bold'), 404 405 #numbers column 406 ('ALIGN', (1,1), (-1,-1), 'DECIMAL'), 407 ('RIGHTPADDING', (1,1), (-1,-1), 36), 408 ('TEXTCOLOR', (1,4), (1,4), colors.red), 409 410 #red cell 411 ] 412 ) 413 414 t.setStyle(ts) 415 lst_add(t) 416 lst_add(Spacer(36,36)) 417 lst_add(Paragraph(""" 418 The red numbers should be aligned LEFT & BOTTOM, the blue RIGHT & TOP 419 and the green CENTER & MIDDLE. 420 """, styleSheet['BodyText'])) 421 XY = [['X00y', 'X01y', 'X02y', 'X03y', 'X04y'], 422 ['X10y', 'X11y', 'X12y', 'X13y', 'X14y'], 423 ['X20y', 'X21y', 'X22y', 'X23y', 'X24y'], 424 ['X30y', 'X31y', 'X32y', 'X33y', 'X34y']] 425 t=Table(XY, 5*[0.6*inch], 4*[0.6*inch]) 426 t.setStyle([('ALIGN',(1,1),(-2,-2),'LEFT'), 427 ('TEXTCOLOR',(1,1),(-2,-2),colors.red), 428 429 ('VALIGN',(0,0),(1,-1),'TOP'), 430 ('ALIGN',(0,0),(1,-1),'RIGHT'), 431 ('TEXTCOLOR',(0,0),(1,-1),colors.blue), 432 433 ('ALIGN',(0,-1),(-1,-1),'CENTER'), 434 ('VALIGN',(0,-1),(-1,-1),'MIDDLE'), 435 ('TEXTCOLOR',(0,-1),(-1,-1),colors.green), 436 ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), 437 ('BOX', (0,0), (-1,-1), 0.25, colors.black), 438 ]) 439 lst_add(t) 440 data = [('alignment', 'align\012alignment'), 441 ('bulletColor', 'bulletcolor\012bcolor'), 442 ('bulletFontName', 'bfont\012bulletfontname'), 443 ('bulletFontSize', 'bfontsize\012bulletfontsize'), 444 ('bulletIndent', 'bindent\012bulletindent'), 445 ('firstLineIndent', 'findent\012firstlineindent'), 446 ('fontName', 'face\012fontname\012font'), 447 ('fontSize', 'size\012fontsize'), 448 ('leading', 'leading'), 449 ('leftIndent', 'leftindent\012lindent'), 450 ('rightIndent', 'rightindent\012rindent'), 451 ('spaceAfter', 'spaceafter\012spacea'), 452 ('spaceBefore', 'spacebefore\012spaceb'), 453 ('textColor', 'fg\012textcolor\012color')] 454 t = Table(data) 455 t.setStyle([ 456 ('VALIGN',(0,0),(-1,-1),'TOP'), 457 ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), 458 ('BOX', (0,0), (-1,-1), 0.25, colors.black), 459 ]) 460 lst_add(t) 461 t = Table([ ('Attribute', 'Synonyms'), 462 ('alignment', 'align, alignment'), 463 ('bulletColor', 'bulletcolor, bcolor'), 464 ('bulletFontName', 'bfont, bulletfontname'), 465 ('bulletFontSize', 'bfontsize, bulletfontsize'), 466 ('bulletIndent', 'bindent, bulletindent'), 467 ('firstLineIndent', 'findent, firstlineindent'), 468 ('fontName', 'face, fontname, font'), 469 ('fontSize', 'size, fontsize'), 470 ('leading', 'leading'), 471 ('leftIndent', 'leftindent, lindent'), 472 ('rightIndent', 'rightindent, rindent'), 473 ('spaceAfter', 'spaceafter, spacea'), 474 ('spaceBefore', 'spacebefore, spaceb'), 475 ('textColor', 'fg, textcolor, color')]) 476 t.repeatRows = 1 477 t.setStyle([ 478 ('FONT',(0,0),(-1,1),'Times-Bold',10,12), 479 ('FONT',(0,1),(-1,-1),'Courier',8,8), 480 ('VALIGN',(0,0),(-1,-1),'MIDDLE'), 481 ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), 482 ('BOX', (0,0), (-1,-1), 0.25, colors.black), 483 ('BACKGROUND', (0, 0), (-1, 0), colors.green), 484 ('BACKGROUND', (0, 1), (-1, -1), colors.pink), 485 ('ALIGN', (0, 0), (-1, 0), 'CENTER'), 486 ('ALIGN', (0, 1), (0, -1), 'LEFT'), 487 ('ALIGN', (-1, 1), (-1, -1), 'RIGHT'), 488 ('FONT', (0, 0), (-1, 0), 'Times-Bold', 12), 489 ('ALIGN', (1, 1), (1, -1), 'CENTER'), 490 ]) 491 lst_add(t) 492 lst_add(Table(XY, 493 style=[ ('FONT',(0,0),(-1,-1),'Times-Roman', 5,6), 494 ('GRID', (0,0), (-1,-1), 0.25, colors.blue),])) 495 lst_add(Table(XY, 496 style=[ ('FONT',(0,0),(-1,-1),'Times-Roman', 10,12), 497 ('GRID', (0,0), (-1,-1), 0.25, colors.black),])) 498 lst_add(Table(XY, 499 style=[ ('FONT',(0,0),(-1,-1),'Times-Roman', 20,24), 500 ('GRID', (0,0), (-1,-1), 0.25, colors.red),])) 501 lst_add(PageBreak()) 502 data= [['00', '01', '02', '03', '04'], 503 ['10', '11', '12', '13', '14'], 504 ['20', '21', '22', '23', '24'], 505 ['30', '31', '32', '33', '34']] 506 t=Table(data,style=[ 507 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 508 ('GRID',(1,1),(-2,-2),1,colors.green), 509 ('BOX',(0,0),(1,-1),2,colors.red), 510 ('BOX',(0,0),(-1,-1),2,colors.black), 511 ('LINEABOVE',(1,2),(-2,2),1,colors.blue), 512 ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), 513 ('BACKGROUND', (0, 0), (0, 1), colors.pink), 514 ('BACKGROUND', (1, 1), (1, 2), colors.lavender), 515 ('BACKGROUND', (2, 2), (2, 3), colors.orange), 516 ('TEXTCOLOR',(0,-1),(-2,-1),colors.green), 517 ]) 518 lst_add(Paragraph("Illustrating splits: nosplit", styleSheet['BodyText'])) 519 lst_add(t) 520 lst_add(Spacer(0,6)) 521 lst_add(Paragraph("Illustrating splits: split(4in,30)", styleSheet['BodyText'])) 522 for s in t.split(4*inch,30): 523 lst_add(s) 524 lst_add(Spacer(0,6)) 525 lst_add(Spacer(0,6)) 526 lst_add(Paragraph("Illustrating splits: split(4in,36)", styleSheet['BodyText'])) 527 for s in t.split(4*inch,36): 528 lst_add(s) 529 lst_add(Spacer(0,6)) 530 lst_add(Paragraph("Illustrating splits: split(4in,56)", styleSheet['BodyText'])) 531 lst_add(Spacer(0,6)) 532 for s in t.split(4*inch,56): 533 lst_add(s) 534 lst_add(Spacer(0,6)) 535 536 lst_add(Paragraph("Illustrating splits: repeated split(4in,30)", styleSheet['BodyText'])) 537 lst_add(Spacer(0,6)) 538 S = t.split(4*inch,30) 539 s = S.pop(-1) 540 S.extend(s.split(4*inch,30)) 541 s = S.pop(-1) 542 S.extend(s.split(4*inch,30)) 543 544 for s in S: 545 lst_add(s) 546 lst_add(Spacer(0,6)) 547 548 lst_add(PageBreak()) 549 data= [['00', '01', '02', '03', '04'], 550 ['', '11', '12', '13', '14'], 551 ['20', '21', '22', '23', '24'], 552 ['30', '31', '', '33', '34']] 553 sty=[ 554 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 555 ('GRID',(1,1),(-2,-2),1,colors.green), 556 ('BOX',(0,0),(1,-1),2,colors.red), 557 ('BOX',(0,0),(-1,-1),2,colors.black), 558 ('LINEABOVE',(1,2),(-2,2),1,colors.blue), 559 ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), 560 ('BACKGROUND', (0, 0), (0, 1), colors.pink), 561 ('SPAN',(0,0),(0,1)), 562 ('BACKGROUND', (2, 2), (2, 3), colors.orange), 563 ('SPAN',(2,2),(2,3)), 564 ] 565 t=Table(data,style=sty) 566 lst_add(Paragraph("Illustrating splits with spans: nosplit", styleSheet['BodyText'])) 567 lst_add(t) 568 lst_add(Spacer(0,6)) 569 lst_add(Paragraph("Illustrating splits with spans: split(4in,30)", styleSheet['BodyText'])) 570 for s in t.split(4*inch,30): 571 lst_add(s) 572 lst_add(Spacer(0,6)) 573 lst_add(Spacer(0,6)) 574 lst_add(Paragraph("Illustrating splits with spans: split(4in,36)", styleSheet['BodyText'])) 575 for s in t.split(4*inch,36): 576 lst_add(s) 577 lst_add(Spacer(0,6)) 578 lst_add(Paragraph("Illustrating splits with spans: split(4in,56)", styleSheet['BodyText'])) 579 lst_add(Spacer(0,6)) 580 for s in t.split(4*inch,56): 581 lst_add(s) 582 lst_add(Spacer(0,6)) 583 584 data= [['00', '01', '02', '03', '04'], 585 ['', '11', '12', '13', ''], 586 ['20', '21', '22', '23', '24'], 587 ['30', '31', '', '33', ''], 588 ['40', '41', '', '43', '44']] 589 sty=[ 590 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 591 ('GRID',(1,1),(-2,-2),1,colors.green), 592 ('BOX',(0,0),(1,-1),2,colors.red), 593 ('BOX',(0,0),(-1,-1),2,colors.black), 594 ('LINEABOVE',(1,2),(-2,2),1,colors.blue), 595 ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), 596 ('BACKGROUND', (0, 0), (0, 1), colors.pink), 597 ('SPAN',(0,0),(0,1)), 598 ('BACKGROUND',(-2,1),(-1,1),colors.palegreen), 599 ('SPAN',(-2,1),(-1,1)), 600 ('BACKGROUND',(-2,3),(-1,3),colors.yellow), 601 ('SPAN',(-2,3),(-1,3)), 602 ('BACKGROUND', (2, 3), (2, 4), colors.orange), 603 ('SPAN',(2,3),(2,4)), 604 ] 605 606 t=Table(data,style=sty,repeatRows=2) 607 lst_add(Paragraph("Illustrating splits with spans and repeatRows: nosplit", styleSheet['BodyText'])) 608 lst_add(t) 609 lst_add(Spacer(0,6)) 610 if 1: 611 lst_add(Paragraph("Illustrating splits with spans and repeatRows: split(4in,30)", styleSheet['BodyText'])) 612 for s in t.split(4*inch,30): 613 lst_add(s) 614 lst_add(Spacer(0,6)) 615 lst_add(Spacer(0,6)) 616 lst_add(Paragraph("Illustrating splits with spans and repeatRows: split(4in,36)", styleSheet['BodyText'])) 617 for s in t.split(4*inch,36): 618 lst_add(s) 619 lst_add(Spacer(0,6)) 620 lst_add(Paragraph("Illustrating splits with spans and repeatRows: split(4in,56)", styleSheet['BodyText'])) 621 lst_add(Spacer(0,6)) 622 for s in t.split(4*inch,56): 623 lst_add(s) 624 lst_add(Spacer(0,6)) 625 626 lst_add(PageBreak()) 627 from reportlab.lib.testutils import testsFolder 628 I = Image(os.path.join(os.path.dirname(testsFolder),'tools','pythonpoint','demos','leftlogo.gif')) 629 I.drawHeight = 1.25*inch*I.drawHeight / I.drawWidth 630 I.drawWidth = 1.25*inch 631 #I.drawWidth = 9.25*inch #uncomment to see better messaging 632 P = Paragraph("<para align=center spaceb=3>The <b>ReportLab Left <font color=red>Logo</font></b> Image</para>", styleSheet["BodyText"]) 633 B = TableBarChart() 634 BP = Paragraph("<para align=center spaceb=3>A bar chart in a cell.</para>", styleSheet["BodyText"]) 635 636 data= [['A', 'B', 'C', Paragraph("<b>A pa<font color=red>r</font>a<i>graph</i></b><super><font color=yellow>1</font></super>",styleSheet["BodyText"]), 'D'], 637 ['00', '01', '02', [I,P], '04'], 638 ['10', '11', '12', [I,P], '14'], 639 ['20', '21', '22', '23', '24'], 640 ['30', '31', '32', '33', '34'], 641 ['40', '41', '42', [B,BP], '44']] 642 643 t=Table(data,style=[('GRID',(1,1),(-2,-2),1,colors.green), 644 ('BOX',(0,0),(1,-1),2,colors.red), 645 ('LINEABOVE',(1,2),(-2,2),1,colors.blue), 646 ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), 647 ('BACKGROUND', (0, 0), (0, 1), colors.pink), 648 ('BACKGROUND', (1, 1), (1, 2), colors.lavender), 649 ('BACKGROUND', (2, 2), (2, 3), colors.orange), 650 ('BOX',(0,0),(-1,-1),2,colors.black), 651 ('GRID',(0,0),(-1,-1),0.5,colors.black), 652 ('VALIGN',(3,0),(3,0),'BOTTOM'), 653 ('BACKGROUND',(3,0),(3,0),colors.limegreen), 654 ('BACKGROUND',(3,1),(3,1),colors.khaki), 655 ('ALIGN',(3,1),(3,1),'CENTER'), 656 ('BACKGROUND',(3,2),(3,2),colors.beige), 657 ('ALIGN',(3,2),(3,2),'LEFT'), 658 ]) 659 660 t._argW[3]=1.5*inch 661 lst_add(t) 662 663 # now for an attempt at column spanning. 664 lst_add(PageBreak()) 665 data= [['A', 'BBBBB', 'C', 'D', 'E'], 666 ['00', '01', '02', '03', '04'], 667 ['10', '11', '12', '13', '14'], 668 ['20', '21', '22', '23', '24'], 669 ['30', '31', '32', '33', '34']] 670 sty = [ 671 ('ALIGN',(0,0),(-1,-1),'CENTER'), 672 ('VALIGN',(0,0),(-1,-1),'TOP'), 673 ('GRID',(0,0),(-1,-1),1,colors.green), 674 ('BOX',(0,0),(-1,-1),2,colors.red), 675 676 #span 'BBBB' across middle 3 cells in top row 677 ('SPAN',(1,0),(3,0)), 678 #now color the first cell in this range only, 679 #i.e. the one we want to have spanned. Hopefuly 680 #the range of 3 will come out khaki. 681 ('BACKGROUND',(1,0),(1,0),colors.khaki), 682 683 ('SPAN',(0,2),(-1,2)), 684 685 686 #span 'AAA'down entire left column 687 ('SPAN',(0,0), (0, 1)), 688 ('BACKGROUND',(0,0),(0,0),colors.cyan), 689 ('TEXTCOLOR', (0,'splitfirst'), (-1,'splitfirst'), colors.cyan), 690 ('TEXTCOLOR', (0,'splitlast'), (-1,'splitlast'), colors.red), 691 ('BACKGROUND', (0,'splitlast'), (-1,'splitlast'), colors.pink), 692 ('LINEBELOW', (0,'splitlast'), (-1,'splitlast'), 1, colors.grey,'butt'), 693 ] 694 t=Table(data,style=sty, colWidths = [20] * 5, rowHeights = [20]*5) 695 lst_add(t) 696 lst_add(Spacer(18,18)) 697 698 t=Table(data,style=sty, colWidths = [20] * 5, rowHeights = [20]*5) 699 for s in t.split(4*inch,72): 700 lst_add(s) 701 lst_add(Spacer(0,6)) 702 703 # now for an attempt at percentage widths 704 lst_add(Spacer(18,18)) 705 lst_add(Paragraph("This table has colWidths=5*['14%']!", styleSheet['BodyText'])) 706 t=Table(data,style=sty, colWidths = ['14%'] * 5, rowHeights = [20]*5) 707 lst_add(t) 708 709 lst_add(Spacer(18,18)) 710 lst_add(Paragraph("This table has colWidths=['14%','10%','19%','22%','*']!", styleSheet['BodyText'])) 711 t=Table(data,style=sty, colWidths = ['14%','10%','19%','22%','*'], rowHeights = [20]*5) 712 lst_add(t) 713 714 # Mike's test example 715 lst_add(Spacer(18,18)) 716 lst_add(Paragraph('Mike\'s Spanning Example', styleSheet['Heading1'])) 717 data= [[Paragraph('World Domination: The First Five Years', styleSheet['BodyText']), ''], 718 [Paragraph('World <font color="green">Domination</font>: The First Five Years', styleSheet['BodyText']),''], 719 [Paragraph('World Domination: The First Five Years', styleSheet['BodyText']), ''], 720 ] 721 t=Table(data, style=[('SPAN',(0,0),(1,0)),('SPAN',(0,1),(1,1)),('SPAN',(0,2),(1,2)),], colWidths = [3*cm,8*cm], rowHeights = [None]*3) 722 lst_add(t) 723 724 lst_add(Spacer(18,18)) 725 lst_add(Paragraph('Mike\'s Non-spanning Example', styleSheet['Heading1'])) 726 data= [[Paragraph('World Domination: The First Five Years', styleSheet['BodyText'])], 727 [Paragraph('World <font color="magenta">Domination</font>: The First Five Years', styleSheet['BodyText'])], 728 [Paragraph('World Domination: The First Five Years', styleSheet['BodyText'])], 729 ] 730 t=Table(data, style=[], colWidths = [11*cm], rowHeights = [None]*3) 731 lst_add(t) 732 733 lst_add(Spacer(18,18)) 734 lst_add(Paragraph('xpre example', styleSheet['Heading1'])) 735 data= [ [ 736 XPreformatted('Account Details', styleSheet['Heading3']), 737 '', XPreformatted('Client Details', styleSheet['Heading3']), 738 ], #end of row 0 739 ] 740 t=Table(data, style=[], colWidths = [80,230.0,80], rowHeights = [None]*1) 741 lst_add(t) 742 743 lst_add(PageBreak()) 744 745 lst_add(Paragraph('Trying colour cycling in background', styleSheet['Heading1'])) 746 lst_add(Paragraph("This should alternate pale blue and uncolored by row", styleSheet['BodyText'])) 747 data= [['001', '01', '02', '03', '04', '05'], 748 ['002', '01', '02', '03', '04', '05'], 749 ['003', '01', '02', '03', '04', '05'], 750 ['004', '01', '02', '03', '04', '05'], 751 ['005', '01', '02', '03', '04', '05'], 752 ['006', '01', '02', '03', '04', '05'], 753 ['007', '01', '02', '03', '04', '05'], 754 ['008', '01', '02', '03', '04', '05'], 755 ['009', '01', '02', '03', '04', '05'], 756 ['010', '01', '02', '03', '04', '05'], 757 758 ] 759 t=Table(data,style=[ 760 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 761 ('ROWBACKGROUNDS', (0, 0), (-1, -1), (0xD0D0FF, None)), 762 ]) 763 lst_add(t) 764 lst_add(Spacer(0,6)) 765 lst_add(Paragraph("And this should pale blue, pale pink and None by column", styleSheet['BodyText'])) 766 t=Table(data,style=[ 767 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 768 ('COLBACKGROUNDS', (0, 0), (-1, -1), (0xD0D0FF, 0xFFD0D0, None)), 769 ]) 770 lst_add(t) 771 772 lst_add(PageBreak()) 773 lst_add(Paragraph("This spanning example illustrates automatic removal of grids and lines in spanned cells!", styleSheet['BodyText'])) 774 lst_add(Spacer(0,6)) 775 data= [['Top\nLeft', '', '02', '03', '04', '05', '06', '07'], 776 ['', '', '12', 'Span (3,1) (6,2)', '','','','17'], 777 ['20', '21', '22', '', '','','','27'], 778 ['30', '31', '32', '33', '34','35','36','37'], 779 ['40', 'In The\nMiddle', '', '', '44','45','46','47'], 780 ['50', '', '', '', '54','55','56','57'], 781 ['60', '', '', '','64', '65', 'Bottom\nRight', ''], 782 ['70', '71', '72', '73','74', '75', '', '']] 783 t=Table(data,style=[ 784 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 785 ('BACKGROUND',(0,0),(1,1),colors.palegreen), 786 ('SPAN',(0,0),(1,1)), 787 ('BACKGROUND',(-2,-2),(-1,-1), colors.pink), 788 ('SPAN',(-2,-2),(-1,-1)), 789 ('SPAN',(1,4),(3,6)), 790 ('BACKGROUND',(1,4),(3,6), colors.lightblue), 791 ('SPAN',(3,1),(6,2)), 792 ('BACKGROUND',(3,1),(6,2), colors.peachpuff), 793 ('VALIGN',(3,1),(6,2),'TOP'), 794 ('LINEABOVE', (0,2),(-1,2), 1, colors.black, 0, None, None, 2, 2), 795 ('LINEBEFORE', (3,0),(3,-1), 1, colors.black, 0, None, None, 2, 2), 796 ]) 797 lst_add(t) 798 799 lst_add(PageBreak()) 800 801 lst_add(Paragraph("und jetzt noch eine Tabelle mit 5000 Zeilen:", styleSheet['BodyText'])) 802 sty = [ ('GRID',(0,0),(-1,-1),1,colors.green), 803 ('BOX',(0,0),(-1,-1),2,colors.red), 804 ] 805 data = [[str(i), Paragraph("xx "* (i%10), styleSheet["BodyText"]), Paragraph("blah "*(i%40), styleSheet["BodyText"])] for i in range(500)] 806 t=LongTable(data, style=sty, colWidths = [50,100,200]) 807 lst_add(t) 808 809 #Yuan Hong's bug tester 810 lst_add(PageBreak()) 811 lst_add(Paragraph('Yian Hong\'s Bug Case (should not blow up)', styleSheet['Heading2'])) 812 data = ([['Col1', 'Col2', 'Col3', 'Col4', 'Col5']]+ 813 [['01', Paragraph('This is cell one that contains a paragraph.', styleSheet['Normal']), '02', '03', '04'] 814 for i in range(50)]) 815 816 t = Table(data, ['20%']*5, repeatRows=1) 817 t.setStyle(TableStyle([ 818 ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), 819 ('BOX', (0,0), (-1,-1), 0.25, colors.black), 820 ('SPAN', (0,50), (-2,50)), 821 ])) 822 823 lst_add(t) 824 lst_add(PageBreak()) 825 826 #Volker Haas' example extended 827 #the optimal row heights are the solution of an LP similar to 828 # 829 #Objective function 830 # min: 3*h0+3*h1+3*h2+2*h3; 831 # 832 #constraints 833 # h0>=12; 834 # h1>=12; 835 # h2>=12; 836 # h3>=12; 837 # h0+h1+h2>=48; 838 # h0+h1>=12; 839 # h2+h3>=60; 840 # 841 #the solution H=[12,12,24,36] 842 def makeTable(x,y): 843 return Table([ 844 ['00', '01', '02', '03', '04', '05\nline2\nline3\nline4'], 845 ['', '11', '12', x, '',''], 846 ['20', '21', y, '23', '24',''], 847 ['30', '31', '', '33', '34','35'], 848 ], 849 style=[ 850 ('TOPPADDING',(0,0),(-1,-1),0), 851 ('BOTTOMPADDING',(0,0),(-1,-1),0), 852 ('RIGHTPADDING',(0,0),(-1,-1),0), 853 ('LEFTPADDING',(0,0),(-1,-1),0), 854 ('GRID',(0,0),(-1,-1),0.5,colors.grey), 855 ('BACKGROUND', (0, 0), (0, 1), colors.pink), 856 ('SPAN',(0,0),(0,1)), 857 ('BACKGROUND', (2, 2), (2, 3), colors.orange), 858 ('SPAN',(2,2),(2,3)), 859 ('SPAN',(3,1),(4,1)), 860 ('SPAN',(5,0),(5,2)), 861 ]) 862 p_style= ParagraphStyle('Normal') 863 lst_add(makeTable( 864 Paragraph('This is a string',p_style), 865 Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style) 866 )) 867 868 lst_add(Spacer(10,10)) 869 lst_add(makeTable( 870 XPreformatted('This is a string',p_style), 871 Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style) 872 )) 873 lst_add(Spacer(10,10)) 874 lst_add(makeTable( 875 'This is a string', 876 '22\nblub\nasfd\nafd\nasdfs', 877 )) 878 lst_add(Spacer(10,10)) 879 lst_add(makeTable( 880 'This is a string', 881 Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style) 882 )) 883 SimpleDocTemplate(outputfile('test_platypus_tables_2.pdf'), showBoundary=1).build(lst) 884 885class TablesTestCase(unittest.TestCase): 886 "Make documents with tables" 887 888 def test0(self): 889 "Make a document full of tables 0" 890 run() 891 892 def test1(self): 893 "Make a document full of tables 1" 894 old_tables_test() 895 896 def test2(self): 897 '''buggy table example from Lele Gaifax https://bitbucket.org/lele/ 898 should split to two pages with the blue box on page 1 complete 899 ''' 900 from reportlab.lib.pagesizes import A4, landscape 901 902 data = [ 903 ['Date', '08 AM', '', '', '', '09 AM', '', '', '', '10 AM', '', '', '', '11 AM', '', '', '', '12 PM', '', '', '', '01 PM', '', '', '', '02 PM', '', '', '', '03 PM', '', '', '', '04 PM', '', '', '', '05 PM', '', '', '', '06 PM', '', '', '', '07 PM', '', '', '', '08 PM', '', '', '', '09 PM', '', '', '', '10 PM', '', '', '', '11 PM', '', '', ''], 904 ['04-30-2015', '', '', '', '', '09:00 AM\n:\n01:00 PM\nSupervision\nReception', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 905 ['05-01-2015', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '01:00 PM\n:\n04:00 PM\nSupervision\nInfo point 1', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 906 ['05-03-2015', '', '', '', '', '09:00 AM\n:\n01:00 PM\nSupervision\nReception', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 907 ['05-04-2015', '', '', '', '', '', '', '', '', '10:00 AM\n:\n01:00 PM\nSupervision\nInfo point 2', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '03:00 PM\n:\n05:30 PM\nSupervision\nInfo point 3', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 908 ['05-05-2015', '', '', '', '', '09:00 AM\n:\n01:00 PM\nSupervision\nReception', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 909 ['05-08-2015', '', '', '', '', '', '', '', '', '10:00 AM\n:\n01:00 PM\nSupervision\nInfo point 2', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '02:30 PM\n:\n05:30 PM\nSupervision\nInfo point 3', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 910 ['05-10-2015', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '04:00 PM\n:\n08:00 PM\nSupervision\nInfo point 2', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 911 ] 912 913 style = [ 914 ('SPAN', (1, 0), (4, 0)), 915 ('SPAN', (5, 0), (8, 0)), 916 ('SPAN', (9, 0), (12, 0)), 917 ('SPAN', (13, 0), (16, 0)), 918 ('SPAN', (17, 0), (20, 0)), 919 ('SPAN', (21, 0), (24, 0)), 920 ('SPAN', (25, 0), (28, 0)), 921 ('SPAN', (29, 0), (32, 0)), 922 ('SPAN', (33, 0), (36, 0)), 923 ('SPAN', (37, 0), (40, 0)), 924 ('SPAN', (41, 0), (44, 0)), 925 ('SPAN', (45, 0), (48, 0)), 926 ('SPAN', (49, 0), (52, 0)), 927 ('SPAN', (53, 0), (56, 0)), 928 ('SPAN', (57, 0), (60, 0)), 929 ('SPAN', (61, 0), (64, 0)), 930 ('SPAN', (1, -1), (4, -1)), 931 ('SPAN', (5, -1), (8, -1)), 932 ('SPAN', (9, -1), (12, -1)), 933 ('SPAN', (13, -1), (16, -1)), 934 ('SPAN', (17, -1), (20, -1)), 935 ('SPAN', (21, -1), (24, -1)), 936 ('SPAN', (25, -1), (28, -1)), 937 ('SPAN', (29, -1), (32, -1)), 938 ('SPAN', (33, -1), (36, -1)), 939 ('SPAN', (37, -1), (40, -1)), 940 ('SPAN', (41, -1), (44, -1)), 941 ('SPAN', (45, -1), (48, -1)), 942 ('SPAN', (49, -1), (52, -1)), 943 ('SPAN', (53, -1), (56, -1)), 944 ('SPAN', (57, -1), (60, -1)), 945 ('SPAN', (61, -1), (64, -1)), 946 ('ALIGN', (0, 0), (-1, -1), 'CENTER'), 947 ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), 948 ('SIZE', (0, 1), (0, -1), 8), 949 ('SIZE', (1, 1), (-1, -1), 6), 950 ('BOX', (5, 1), (20, 1), 1, colors.black), ('SPAN', (5, 1), (20, 1)), 951 ('BOX', (21, 2), (32, 2), 1, colors.black), ('SPAN', (21, 2), (32, 2)), 952 ('BOX', (5, 3), (20, 3), 1, colors.black), ('SPAN', (5, 3), (20, 3)), 953 ('BOX', (9, 4), (20, 4), 1, colors.black), ('SPAN', (9, 4), (20, 4)), 954 ('BOX', (29, 4), (38, 4), 1, colors.black), ('SPAN', (29, 4), (38, 4)), 955 ('BOX', (5, 5), (20, 5), 1, colors.green), ('SPAN', (5, 5), (20, 5)), 956 ('BOX', (9, 6), (20, 6), 1, colors.red), ('SPAN', (9, 6), (20, 6)), 957 ('BOX', (27, 6), (38, 6), 1, colors.blue),('SPAN', (27, 6), (38, 6)), 958 ('BOX', (33, 7), (48, 7), 1, colors.black),('SPAN', (33, 7), (48, 7)), 959 ] 960 t = Table(data, colWidths=None, rowHeights=None, style=style, repeatRows=1) 961 doc = SimpleDocTemplate(outputfile('test_platypus_tables_issue74.pdf'), showBoundary=0, pagesize=landscape(A4)) 962 doc.build([t]) 963 964 data34 = [ 965 ['001', '01', '02', '03', '04', '05'], 966 ['002', '01', '02', '03', '04', '05'], 967 ['003', '01', '02', '03', '04', '05'], 968 ['004', '01', '02', '03', '04', '05'], 969 ['005', '01', '02', '03', '04', '05'], 970 ['006', '01', '02', '03', '04', '05'], 971 ['007', '01', '02', '03', '04', '05'], 972 ['008', '01', '02', '03', '04', '05'], 973 ['009', '01', '02', '03', '04', '05'], 974 ['010', '01', '02', '03', '04', '05'], 975 ['011', '01', '02', '03', '04', '05'], 976 ['012', '01', '02', '03', '04', '05'], 977 ] 978 def test3(self): 979 '''bug reported by David VanEe <david.vanee@convergent.ca>''' 980 story = [] 981 story_add = story.append 982 ts_tables = [ 983 ('BACKGROUND',(0,0),(-1,0),colors.pink), 984 ('BACKGROUND',(0,1),(-1,1),colors.lightblue), 985 ('BACKGROUND',(0,3),(-1,3),colors.grey), 986 ('TEXTCOLOR',(0,0),(-1,0),colors.green), 987 ('TEXTCOLOR',(0,1),(-1,1),colors.red), 988 ('LINEABOVE', (0,0), (-1,0), 1, colors.purple), 989 ('LINEBELOW', (0,0), (-1,0), 2, colors.purple), 990 ('LINEABOVE', (0,1), (-1,1), 1, colors.orange), 991 ('LINEBELOW', (0,1), (-1,1), 2, colors.orange), 992 ('FONT', (2,2), (5,8), 'Times-Bold'), 993 ] 994 data = self.data34 995 from reportlab.platypus import Paragraph, Table, SimpleDocTemplate, PageBreak 996 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 997 styleSheet = getSampleStyleSheet() 998 bodyText = styleSheet['BodyText'] 999 1000 story_add(Paragraph('The whole table',bodyText)) 1001 t = Table(data, style=ts_tables, repeatRows=(1,3)) 1002 story_add(t) 1003 t = Table(data, style=ts_tables, repeatRows=(1,3)) 1004 T = t.split(4*72,90) 1005 story_add(Paragraph('The split table part 0',bodyText)) 1006 story_add(T[0]) 1007 story_add(Paragraph('The split table part 1',bodyText)) 1008 story_add(T[1]) 1009 self.assertIn(('BACKGROUND', (0, 0), (-1, 0), colors.lightblue),T[1]._bkgrndcmds) 1010 self.assertIn(('BACKGROUND', (0, 1), (-1, 1), colors.grey),T[1]._bkgrndcmds) 1011 self.assertEqual(len(T[1]._bkgrndcmds),2) 1012 1013 # do the same again with repeatRows=1 1014 story_add(PageBreak()) 1015 story_add(Paragraph('The whole table repeatRows=1',bodyText)) 1016 t = Table(data, style=ts_tables, repeatRows=1) 1017 story_add(t) 1018 t = Table(data, style=ts_tables, repeatRows=1) 1019 T = t.split(4*72,60) 1020 story_add(Paragraph('The split table (repeatRows=1) part 0',bodyText)) 1021 story_add(T[0]) 1022 story_add(Paragraph('The split table (repeatRows=1) part 1',bodyText)) 1023 story_add(T[1]) 1024 self.assertIn(('BACKGROUND', (0, 0), (-1, 0), colors.pink), T[1]._bkgrndcmds) 1025 self.assertIn(('BACKGROUND', (0, 1), (-1, 1), colors.grey), T[1]._bkgrndcmds) 1026 self.assertEqual(len(T[1]._bkgrndcmds),2) 1027 doc = SimpleDocTemplate(outputfile('test_platypus_tables_repeatrows_bgsplit.pdf'), showBoundary=0) 1028 doc.build(story) 1029 1030 def test4(self): 1031 '''test splitting row colour cycles''' 1032 story = [] 1033 story_add = story.append 1034 ts_tables = [ 1035 ('BACKGROUND',(0,0),(-1,0),colors.pink), 1036 ('BACKGROUND',(0,1),(-1,1),colors.lightblue), 1037 ('ROWBACKGROUNDS',(0,2),(-1,-1),(colors.lightgrey,None)), 1038 ('TEXTCOLOR',(0,0),(-1,0),colors.green), 1039 ('TEXTCOLOR',(0,1),(-1,1),colors.red), 1040 ('LINEABOVE', (0,0), (-1,0), 1, colors.purple), 1041 ('LINEBELOW', (0,0), (-1,0), 2, colors.purple), 1042 ('LINEABOVE', (0,1), (-1,1), 1, colors.orange), 1043 ('LINEBELOW', (0,1), (-1,1), 2, colors.orange), 1044 ('FONT', (2,2), (5,8), 'Times-Bold'), 1045 ] 1046 data = self.data34 1047 from reportlab.platypus import Paragraph, Table, SimpleDocTemplate, PageBreak 1048 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 1049 styleSheet = getSampleStyleSheet() 1050 bodyText = styleSheet['BodyText'] 1051 1052 story_add(Paragraph('The whole table',bodyText)) 1053 t = Table(data, style=ts_tables, repeatRows=2) 1054 story_add(t) 1055 t = Table(data, style=ts_tables, repeatRows=2) 1056 T = t.split(4*72,90) 1057 story_add(Paragraph('The split table part 0',bodyText)) 1058 story_add(T[0]) 1059 story_add(Paragraph('The split table part 1',bodyText)) 1060 story_add(T[1]) 1061 self.assertIn(('BACKGROUND', (0, 0), (-1, 0), colors.pink),T[1]._bkgrndcmds) 1062 self.assertIn(('BACKGROUND', (0, 1), (-1, 1), colors.lightblue),T[1]._bkgrndcmds) 1063 self.assertIn(('ROWBACKGROUNDS', (0, 2), (-1, 8), (colors.lightgrey,None)),T[1]._bkgrndcmds) 1064 self.assertEqual(len(T[1]._bkgrndcmds),3) 1065 doc = SimpleDocTemplate(outputfile('test_platypus_tables_repeatrows_bgsplit_1.pdf'), showBoundary=0) 1066 self.assertEqual(len(T[1]._bkgrndcmds),3) 1067 doc.build(story) 1068 1069 def test5(self): 1070 '''test rounded corners''' 1071 story = [] 1072 story_add = story.append 1073 ts_tables = [ 1074 ('BACKGROUND',(0,0),(-1,0),colors.pink), 1075 ('BACKGROUND',(0,1),(-1,1),colors.lightblue), 1076 ('ROWBACKGROUNDS',(0,2),(-1,-1),(colors.lightgrey,None)), 1077 ('TEXTCOLOR',(0,0),(-1,0),colors.green), 1078 ('TEXTCOLOR',(0,1),(-1,1),colors.red), 1079 ('LINEABOVE', (0,0), (-1,0), 1, colors.purple), 1080 ('LINEBELOW', (0,0), (-1,0), 2, colors.purple), 1081 ('LINEABOVE', (0,1), (-1,1), 1, colors.orange), 1082 ('LINEBELOW', (0,1), (-1,1), 2, colors.orange), 1083 ('LINEBEFORE', (0,0), (0,-1), 1, colors.red), 1084 ('LINEAFTER', (-1,0), (-1,-1), 1, colors.blue), 1085 ('LINEBELOW', (0,-1), (-1,-1), 1, colors.green), 1086 ('FONT', (2,2), (5,8), 'Times-Bold'), 1087 ] 1088 data = self.data34 1089 from reportlab.platypus import Paragraph, Table, SimpleDocTemplate, PageBreak 1090 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 1091 styleSheet = getSampleStyleSheet() 1092 bodyText = styleSheet['BodyText'] 1093 1094 story_add(Paragraph('The whole table',bodyText)) 1095 t = Table(data[:], style=ts_tables, repeatRows=2, cornerRadii=[5,6,4,3]) 1096 story_add(t) 1097 t = Table(data[:], style=ts_tables, repeatRows=2, cornerRadii=[5,6,4,5]) 1098 T = t.split(4*72,90) 1099 story_add(Paragraph('The split table part 0',bodyText)) 1100 story_add(T[0]) 1101 story_add(Paragraph('The split table part 1',bodyText)) 1102 story_add(T[1]) 1103 story_add(PageBreak()) 1104 ts2 = ts_tables+[('ROUNDEDCORNERS',[5,6,4,3])] 1105 story_add(Paragraph('Rounded corners via style',bodyText)) 1106 t = Table(data[:], style=ts2, repeatRows=2) 1107 story_add(t) 1108 t = Table(data[:], style=ts2, repeatRows=2) 1109 T = t.split(4*72,90) 1110 story_add(Paragraph('The split table part 0',bodyText)) 1111 story_add(T[0]) 1112 story_add(Paragraph('The split table part 1',bodyText)) 1113 story_add(T[1]) 1114 story_add(PageBreak()) 1115 story_add(Paragraph('Rounded corners via style overridden by instance argument',bodyText)) 1116 t = Table(data[:], style=ts2, repeatRows=2, cornerRadii=(0,3,5,0)) 1117 story_add(t) 1118 t = Table(data[:], style=ts2, repeatRows=2, cornerRadii=t._cornerRadii) 1119 T = t.split(4*72,90) 1120 story_add(Paragraph('The split table part 0',bodyText)) 1121 story_add(T[0]) 1122 story_add(Paragraph('The split table part 1',bodyText)) 1123 story_add(T[1]) 1124 story_add(Paragraph('Rounded corners double linebelow',bodyText)) 1125 ts3 = ts_tables[:] 1126 ts3.remove(('LINEBELOW', (0,-1), (-1,-1), 1, colors.green)) 1127 ts3.append(('LINEBELOW', (0,-1), (-1,-1), 1, colors.green, 1, None, None, 3,1)) 1128 t = Table(data[:], style=ts3, repeatRows=2, cornerRadii=[0,0,6,7])#[4,5,6,7]) 1129 story_add(t) 1130 doc = SimpleDocTemplate(outputfile('test_platypus_tables_rounded_corners.pdf'), showBoundary=0) 1131 doc.build(story) 1132 assert(T[0]._cornerRadii==[0,3,0,0]) 1133 assert(T[1]._cornerRadii==[0,3,5,0]) 1134 1135def makeSuite(): 1136 return makeSuiteForClasses(TablesTestCase) 1137 1138 1139#noruntests 1140if __name__ == "__main__": 1141 unittest.TextTestRunner().run(makeSuite()) 1142 printLocation() 1143