Skip to content

Commit db5bf1e

Browse files
committed
add ReportLab sample
1 parent d76966c commit db5bf1e

File tree

7 files changed

+262
-1
lines changed

7 files changed

+262
-1
lines changed

click-sample/requirements-dev.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
--index https://mirrors.aliyun.com/pypi/simple
2-
black>=20.0
2+
black>=20.8b1
33
isort>=5.6.0
44
pytest>=6.1.0

reportlab-sample/README.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ReportLab Sample
2+
3+
use reportlab to write pdf.
4+
5+
[ReportLab Tutorial](http://wiki.li3huo.com/ReportLab)
6+
7+
## Running on host
8+
9+
```bash
10+
# create virtual env
11+
$ virtualenv venv -p python3.7 && source venv/bin/activate
12+
$ pip install --upgrade pip && \
13+
pip install -r requirements.txt && \
14+
pip install -r requirements-dev.txt
15+
```
16+
17+
```bash
18+
# running command
19+
python addons_reportlab.py
20+
```

reportlab-sample/addons_reportlab.py

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# https://docs.worldviz.com/vizard/latest/addons_reportlab.htm
2+
import os
3+
4+
from reportlab.graphics.charts.barcharts import VerticalBarChart
5+
from reportlab.graphics.charts.legends import Legend
6+
# from reportlab.graphics.charts.textlabels import Label
7+
from reportlab.graphics.shapes import Drawing # , string
8+
from reportlab.lib import colors, pagesizes
9+
from reportlab.lib.styles import getSampleStyleSheet
10+
from reportlab.lib.units import inch
11+
from reportlab.platypus import (Image, Paragraph, SimpleDocTemplate, Spacer,
12+
Table, TableStyle)
13+
14+
# This is your data collected from your Vizard experiment
15+
subject1 = "Tom"
16+
subject2 = "Ana"
17+
results1 = [15, 23, 42, 56, 76]
18+
results2 = [34, 67, 94, 31, 56]
19+
20+
21+
# take the data and make ready for paragraph
22+
def dataToParagraph(name, data):
23+
24+
p = (
25+
"<strong>Subject name: </strong>"
26+
+ name
27+
+ "<br/>"
28+
+ "<strong>Data: </strong> ("
29+
)
30+
for i in range(len(data)):
31+
p += str(data[i])
32+
if i != len(data) - 1:
33+
p += ", "
34+
else:
35+
p += ")"
36+
return p
37+
38+
39+
# take the data and convert to list of strings ready for table
40+
def dataToTable(name, data):
41+
42+
data = [str(x) for x in data]
43+
data.insert(0, name)
44+
return data
45+
46+
47+
# create the table for our document
48+
def myTable(tabledata):
49+
50+
# first define column and row size
51+
colwidths = (70, 50, 50, 50, 50, 50)
52+
rowheights = (25, 20, 20)
53+
54+
t = Table(tabledata, colwidths, rowheights)
55+
56+
GRID_STYLE = TableStyle(
57+
[
58+
("GRID", (0, 0), (-1, -1), 0.25, colors.black),
59+
("ALIGN", (1, 1), (-1, -1), "RIGHT"),
60+
]
61+
)
62+
63+
t.setStyle(GRID_STYLE)
64+
return t
65+
66+
67+
# create a bar chart and specify positions, sizes, and colors
68+
def myBarChart(data):
69+
drawing = Drawing(400, 200)
70+
71+
bc = VerticalBarChart()
72+
bc.x = 50
73+
bc.y = 50
74+
bc.height = 125
75+
bc.width = 300
76+
bc.data = data
77+
bc.barWidth = 0.3 * inch
78+
bc.groupSpacing = 0.2 * inch
79+
80+
bc.strokeColor = colors.black
81+
82+
bc.valueAxis.valueMin = 0
83+
bc.valueAxis.valueMax = 100
84+
bc.valueAxis.valueStep = 10
85+
86+
bc.categoryAxis.labels.boxAnchor = "ne"
87+
bc.categoryAxis.labels.dx = 8
88+
bc.categoryAxis.labels.dy = -2
89+
90+
catNames = ("Trial1 Trial2 Trial3 Trial4 Trial5").split()
91+
bc.categoryAxis.categoryNames = catNames
92+
93+
bc.bars[0].fillColor = colors.blue
94+
bc.bars[1].fillColor = colors.lightblue
95+
96+
drawing.add(bc)
97+
98+
return drawing
99+
100+
101+
# add a legend for the bar chart
102+
def myBarLegend(drawing, name1, name2):
103+
"Add sample swatches to a diagram."
104+
105+
d = drawing or Drawing(400, 200)
106+
107+
swatches = Legend()
108+
swatches.alignment = "right"
109+
swatches.x = 80
110+
swatches.y = 160
111+
swatches.deltax = 60
112+
swatches.dxTextSpace = 10
113+
swatches.columnMaximum = 4
114+
items = [(colors.blue, name1), (colors.lightblue, name2)]
115+
swatches.colorNamePairs = items
116+
117+
d.add(swatches, "legend")
118+
return d
119+
120+
121+
def prepare_content():
122+
# create a list and add the elements of our document (image, paragraphs, table, chart) to it
123+
story = []
124+
125+
# define the style for our paragraph text
126+
styles = getSampleStyleSheet()
127+
styleN = styles["Normal"]
128+
129+
# First add the Vizard Logo
130+
imagePath = os.path.join(
131+
os.path.dirname(os.path.abspath(__file__)),
132+
"image/logo.png",
133+
)
134+
# 200 * 200 mm logo
135+
im = Image(imagePath, width=1 * inch, height=1 * inch)
136+
im.hAlign = "RIGHT"
137+
story.append(im)
138+
139+
# add the title
140+
story.append(Paragraph("<strong>Results for Vizard Experiment</strong>", styleN))
141+
story.append(Spacer(1, 0.25 * inch))
142+
143+
# convert data to paragraph form and then add paragraphs
144+
story.append(Paragraph(dataToParagraph(subject1, results1), styleN))
145+
story.append(Spacer(1, 0.25 * inch))
146+
story.append(Paragraph(dataToParagraph(subject2, results2), styleN))
147+
story.append(Spacer(1, 0.5 * inch))
148+
149+
# add our table - first prepare data and then pass this to myTable function
150+
tabledata = (
151+
("", "Trial 1", "Trial 2", "Trial 3", "Trial 4", "Trial 5"),
152+
dataToTable(subject1, results1),
153+
dataToTable(subject2, results2),
154+
)
155+
156+
story.append(myTable(tabledata))
157+
story.append(Spacer(1, 0.5 * inch))
158+
159+
# add our barchart and legend
160+
drawing = myBarChart([results1, results2])
161+
drawing = myBarLegend(drawing, subject1, subject2)
162+
drawing.hAlign = "CENTER"
163+
story.append(drawing)
164+
return story
165+
166+
167+
# build our document with the list of flowables we put together
168+
doc = SimpleDocTemplate("mydoc.pdf", pagesize=pagesizes.A4, topMargin=0)
169+
print(f"width={pagesizes.A4[0]}, height={pagesizes.A4[1]}")
170+
doc.build(prepare_content())

reportlab-sample/image/logo.png

6.86 KB
Loading

reportlab-sample/pdf_render.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import os
2+
import platform
3+
from io import BytesIO
4+
5+
from PIL import Image
6+
from reportlab.graphics.shapes import Drawing, Line
7+
from reportlab.lib import pagesizes, units
8+
from reportlab.pdfbase import pdfmetrics, ttfonts
9+
from reportlab.platypus import SimpleDocTemplate
10+
11+
if platform.system() == "Darwin":
12+
regular_path = os.path.join("~/Library/Fonts/Monofur for Powerline.ttf")
13+
italic_path = os.path.join("~/Library/Fonts/Monofur Italic for Powerline.ttf")
14+
15+
pdfmetrics.registerFont(ttfonts.TTFont("Bold", regular_path))
16+
pdfmetrics.registerFont(ttfonts.TTFont("Medium", regular_path))
17+
pdfmetrics.registerFont(ttfonts.TTFont("Regular", regular_path))
18+
19+
20+
# A4 页面外边距默认值 1.25 inch
21+
MARGIN = 31.7 * units.mm
22+
23+
24+
def build_pdf(flowables, pagesize=pagesizes.A4, margin=MARGIN):
25+
"""根据 flowables 中的内容生成 pdf
26+
27+
Args:
28+
flowables: content of pdf
29+
pagesize: default is pagesizes.A4
30+
Returns:
31+
store content in memory
32+
"""
33+
pdf_buffer = BytesIO()
34+
# 更多配置信息,参考 BaseDocTemplate
35+
my_doc = SimpleDocTemplate(
36+
pdf_buffer, pagesize=pagesize, leftMargin=MARGIN, rightMargin=MARGIN
37+
)
38+
39+
my_doc.build(flowables)
40+
# content = pdf_buffer.getbuffer()
41+
# pdf_buffer.close()
42+
return pdf_buffer
43+
44+
45+
def new_line(width=210 * units.mm):
46+
"""create a new line in pdf
47+
A4 = (210*mm,297*mm)
48+
"""
49+
d = Drawing(width=width, height=1)
50+
d.hAlign = "CENTER"
51+
d.add(Line(x1=MARGIN, y1=0, x2=width - MARGIN, y2=0))
52+
return d
53+
54+
55+
def load_image(fp):
56+
"""load image with PIL.Image, convert to BytesIO
57+
58+
Args:
59+
fp: Union[str, Path, BinaryIO]
60+
"""
61+
img = BytesIO()
62+
Image.open(fp).save(img, "PNG")
63+
img.seek(0)
64+
return img

reportlab-sample/requirements-dev.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
--index https://mirrors.aliyun.com/pypi/simple
2+
black>=20.8b1
3+
isort>=5.6.0
4+
# pytest>=6.1.0

reportlab-sample/requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--index https://mirrors.aliyun.com/pypi/simple
2+
reportlab>=3.5.55
3+
python-dotenv>=0.15.0

0 commit comments

Comments
 (0)