18 KiB
layout | type | title | date | tags |
---|---|---|---|---|
post | handbook | ReportLab 101 | 2013-10-29 | coding pdf reportlab |
Style
เราจะใช้เพียงแค่ font TH Sarabun New ครับ โดยจะมีให้เลือกแค่ 2 แบบ:-
- TH Sarabun New
- TH Sarabun New Bold
ส่วนแต่ละส่วนนั้น สามารถจัดการ style โดยการออกแบบ Style ของแต่ละส่วนก่อน เช่น ให้หัวกระดาษเป็นอย่างนึง, เนื้อหาอย่างนึง, ในตารางอีกแบบนึง, คำอธิบายใต้ตารางอีกแบบนึง เป็นต้น พยายามจัดการให้มันไม่ต้องมีแบบมาก เพราะ (1)ง่ายต่อการอ่าน code (2)ง่ายต่อต่อการแก้ไข (3)ไม่ฟุ่มเฟือย
เท่าที่ดูวิธีที่ง่ายที่สุดคือ ใช้ ParagraphStyle
โดยเราสามารถจัดการได้โดย import ParagraphStyle
ด้านบนของ file ก่อน
from core.views.pdfs import Paragraph, ParagraphStyle
จากนั้นเราก็จะสามารถกำหนด style ของตัวเองได้
style_x1 = ParagraphStyle(name="style_name",
fontName='TH Sarabun New',
fontSize=16,
alignment=TA_CENTER,
leading=16,
spaceAfter=8,)
name="xxx"
เป็นสิ่งที่จำเป็นสำหรับ ParagraphStyle
นอกนั้นก็กำหนดตามต้องการ ตรง TA_CENTER
แปลว่า ให้มันอยู่ตรงกลาง ซึ่งก็ยังมี TA_LEFT
, TA_RIGHT
, TA_JUSTIFY
ตามชื่อ โดยถ้าต้องการใช้ค่าพวกนี้ก็ต้อง import ด้วย เช่น
from reportlab.lib.enums import TA_CENTER, TA_LEFT
ที่ผ่านมาคือ การตั้งว่า style เราจะมีอะไรบ้างต่อไปก็จะเป็นการใช้ style หลักๆแล้วเราจะใช้ Python List (ก็อารมณ์ array นั่นแหละ) ในการเก็บข้อมูลแต่ละชุดๆไป จะอารมณ์ประมาณว่า
lines = [] # เริ่ม declare list ก่อน
lines.append(Paragraph("บรรทัดแรก", style_x1)) # อันนี้เหมือนเพิ่ม element ใน list
lines.append(Paragraph("บรรทัดที่สอง", style_x1)) # อันนี้เหมือนเพิ่ม element ใน list ต่อไป
เราก็จะได้ประมาณว่า
บรรทัดแรก
บรรทัดที่สอง
มันจะตรงกลางนะ แต่พิมในนี้ลำบาก ก็เลยทำเป็นเป็นแค่ตัวอย่าง
Color
การกำหนดสีจากที่ใช้ colors.lightgrey
อะไรไปก็ยังสามารถกำหนดสีเองได้โดย
from reportlab.lib.colors import Color
red50transparent = Color(100, 0, 0, alpha=0.5)
โดย Color(สีแดง, สีเขียว, สีฟ้า, alpha=1)
โดยแต่ละสีมีค่าตั้งแต่ 0-255 และ alpha ก็มีค่าตั้งแต 0-1 (1 คือ ทึบ, 0 คือ ใสทะลุปรุโปร่ง) จากนั้นก็เอา red50transparent
ไปแทนที่ colors.lightgrey
ได้เลย
ข้อสังเกต
- การขึ้นบรรทัดใหม่ถ้าเป็น Paragraph เดียวกันมันจะตัดขึ้นบรรทัดใหม่ให้เอง โดยใช้ช่องว่างเป็นตัวตัด มันใช้ได้ดีกับภาษาอังกฤษ แต่ไม่ใช่ภาษาไทย ดังนั้นเราต้องตัดคำเองครับ ถ้าคิดว่าตัวอักษรมันมีจำนวนไม่แน่นอน เผื่อไว้เลยครับ ดีกว่ากลายเป็นฉีกคำประหลาดๆ ให้ด้านหลังว่างไว้เยอะหน่อยยังดีกว่ามาก
- การขึ้นบรรทัดใหม่ สามารถใช้ html tag
เป็นตัวขึ้นบรรทัดใหม่ได้เลย - แต่ละ Paragraph จะขึ้นบรรทัดใหม่เสมอ ค่ามันจะขึ้นกับ spaceBefore กับ spaceAfter
Table
ตารางเป็นอีกส่วนที่มีความซับซ้อนพอสมควรในกรณีที่มี cell รวมกัน แต่ถ้าตามปกติก็ง่ายๆ ไม่มีอะไร มาดูตัวอย่างง่ายๆ แล้วค่อยไล่อธิบายบางทีอาจจะเข้าใจง่ายกว่า
data = [
['top\nLeft', '10', '20', '30'],
['01', '11', '21'],
['02', '12', '22', '32'],
['03', '13', '23', '33'],
['04', '14', '24', '34'],
]
t = Table(data, style=[
('FONTNAME', (0,0), (-1,-1), 'TH Sarabun New Bold'),
('GRID', (0,0), (-1,-1), 0.5 , colors.grey),
('BACKGROUND',(0,0),(1,1),colors.palegreen),
('SPAN',(0,0),(1,1)),
('BACKGROUND',(-2,-2),(-1,-1), colors.red),
('SPAN',(-2,-2),(-1,-1)),
])
lines.append(t)
data นั้นจะเป็นตัวเก็บข้อมูลไว้แสดงในตารางโดยจะเป็น list 2 หรือ 3 มิติ เรียกไม่ถูกเหมือนกัน แต่มันจะซ้อนกันอย่างนั้น โดยระดับแรกจะเป็นตัวข้อมูลแสดงของ row และระดับที่ 2 ก็คือจะเป็นตัวข้อมูลในระดับ column ของแต่ละ row โดยข้อมูลนั้นจะใช้ Table
เป็นตัวแปลงให้เป็นตาราง (ซึ่งก็ต้อง import อีกนั่นแหละ)
from core.views.pdfs import Table
หลังจากนั้นก็ต้องไปต่อใน lines เหมือนกับที่ทำกับ Paragraph ไม่มีผิดครับ ความสับสนของตารางมันจะอยู่ตรงที่ style มากกว่า มาดูผลโดยประมาณกันก่อนว่า มันจะได้ ตารางใน pdf ยังไงกันแน่
top Left | 20 | 30 | |
12 | |||
02 | 12 | 22 | 32 |
03 | 13 | 23 | |
04 | 14 |
ตารางจะเริ่มที่มุมบนซ้าย -- เริ่มด้วย column 0 และ row 0 --> (0, 0) ตามที่เห็นก็สีมั่วๆนะครับ ขี้เกียจครับ อย่างที่เห็นชัดๆ คือ จะมี cell merge กันอยู่ 2 ที่ คือ
- มุมซ้ายบน ตำแหน่ง
(col, row) (0, 0)
ถึง(1, 1)
- มุมขวาล่าง ตำแหน่ง
(col, row) (2, 3)
ถึง(3, 4)
หรือมองอีกมุม (ขวาล่าง) คือ(-2,-2),(-1,-1)
จริงๆ ก็จะเห็นชัดเจนกว่า style มันเนี่ย ตรงที่ cell merge กัน ถูกกำหนดด้วย
('BACKGROUND',(0,0),(1,1),colors.palegreen),
('SPAN',(0,0),(1,1)),
BACKGROUND
ก็ไม่ได้เกี่ยวอะไรกับเค้า เพียงแค่บอกสีครับ SPAN เป็นตัวบอกว่า เราจะรวม cell ไหนถึงตรงไหนกันแน่ โดยข้อมูลจะเป็นข้อมูลของ cell แรกเสมอครับ
จัดตำแหน่ง
ถ้าต้องการจะจัดตำแหน่งอักษรของแต่ละ cell ก็เพิ่มใน style ของ Table ได้
('ALIGN',(0,0),(0,0),'CENTER'),
('VALIGN',(0,0),(0,0),'MIDDLE'),
ALIGN
คือ จัดตำแหน่งแนวนอน มีค่าเป็นLEFT
,RIGHT
,CENTER
-- ค่า default เป็นLEFT
VALIGN
คือ จัดตำแหน่งแนวนอน มีค่าเป็นTOP
,MIDDLE
,BOTTOM
-- ค่า default เป็นBOTTOM
ในกรณีที่ต้องการจัดการตำแหน่งของ cell ที่มีการรวม cell กำหนดตำแหน่งแค่ cell ที่มีข้อมูล (มุมขวาบน) ก็พอ
ข้อสังเกต
SPAN
สามารถกำหนด ตำแหน่งค่าติดลบได้('SPAN',(-2,-2),(-1,-1))
<< โดยจะเป็นการคิดจากมุมขวาล่างมา ตรงข้ามกับค่าบวกที่คิดจากมุมซ้ายบนSPAN
จะไม่สนใจข้อมูลที่อยู่ในตำแหน่งอื่นเลย นอกจากตัวมุมบนขวาของที่รวม -- ตัวอื่นจะอารมณ์ถูกทับไปเลย โดยสังเกตได้จากตัวอย่าง row ที่ 2 กลายเป็นว่า 01, 11 หายไปเลย โดยตำแหน่ง 21 ก็ไม่ได้เปลี่ยนไป- ถ้า list มีไม่ครบในตาราง ตรงที่ขาดไปก็จะเป็นช่องว่าง
- การขึ้นบรรทัดใหม่ในตารางใช้ escape key
\n
ไม่ใช่<br/>
เหมือนในParagraph
- พวก
SPAN
ใน style ไม่ได้ต้องเรียงลำดับอะไรครับ จัดยังไงก็ได้ มันอ่านรู้เรื่อง แต่ที่ควรจะทำให้มันเป็นจากบนลงล่าง เป็นระบบหน่อยก็เพราะแค่เราจะกลับไปแก้ลำบากขึ้นเยอะ ถ้ามันไล่ไม่ได้ง่ายๆครับ
เท่านี้ก็น่าจะพอได้ idea ไปลองแล้วหล่ะ
การแก้ใน .py
ใครใช้รายงานไหน จริงๆ ก็น่าจะมีอะไรอยู่ใน file พอสมควรแล้วครับ แต่ส่วนที่ต้องแก้ คือ ส่วนของ
def prep_to_pdf(self, context):
lines = []
......
.....
...
..
return render_to_pdf(lines)
แค่ส่วนจุดๆๆ นี้แหละครับ ที่ต้องแก้ไข (ซึ่งชื่อตัวแปร lines ก็เปลี่ยนได้ตามชอบใจครับ ที่ใช้ lines เพราะจะได้สอดคล้องกับตัวอย่างด้านบน)
การใช้คำสั่งต่างๆ
โดยมากแล้วจะเป็นการเปรียบเทียบคำสั่งต่างๆ ของ templatetag ที่เห็นใน .html กับที่ต้องเขียนใน python (.py) ใน html นั้นจะมีการเรียกใช้งานตัวแปรและ function ที่ต่างออกไปจากปกติ
{{date}}
{{ }}
ไว้สำหรับแสดงผลตัวแปรนั้นเป็น string
{{date|month_full_th}}
| เป็นการบ่งบอกว่า มีการใช้ function กับตัวแปร date โดยเราจะสามารถดูได้ว่า function นี้คืออะไรได้จากการ import function ข้างบน ซึ่งใน templatetag
จะใช้คำสั่ง { % load yyyyy % }
การใช้งาน function พวกนี้ใน python code นั้นจะสามารถทำได้โดย
from core.templatetags.extratags import intcomma2, intword_th, month_full_th
thb = 1423.223
print u'ราคา %s' % intcomma2(thb)
# จะได้ผลลัพธ์เป็น
ราคา 1,423.22
คำสั่งอ้างอิง
templatetags ที่ใช้ใน .html ก็มีแตกต่างกันออกไปแต่หลักๆก็จะมีอยู่ 2 ที่ด้วยกันคือ
-
report_tags
-- ส่วนใหญ่จะเป็นการแปลงค่าแสดงผลที่เกี่ยวกับโรงเรียนทั้งหมด เช่น แสดงรอบ แสดงชั้นเป็นต้นfrom school.templatetags.report_tags import *
-
extra_tags
-- เป็นการแปลงค่าเพื่อแสดงผลทั่วๆไป เช่น ใน , ในหลักพัน การพิมวันที่เป็นภาษาไทย หรือพิมจำนวนเงินเป็นภาษาไทยfrom core.templatetags.extra_tags import *
รายละเอียดของคำสั่งมีดังนี้
file | function | description |
---|---|---|
report_tags | school.templatetags.report_tags | |
shift_display | แปลงค่า
| |
coarse_grade_display | แสดงชั้นปีแบบคร่าวๆ โดยจะใช้ค่าชั้นปีแบบใดก็ได้ ผลเป็นแบบหยาบเสมอ โดยจะแสดงเป็น
| |
fine_grade_display | แสดงชั้นปีแบบเจาะจงชั้นปี โดยจะแสดงเป็น
| |
course_display | แสดงหลักสูตรของสายวิชาชีพของแต่ละห้อง | |
education_level_display | แสดงวุฒิที่ได้รับการบรรจุของบุคลากร เช่น ป.เอก (ครู) ป.เอก | |
extra_tags | core.templatetags.extra_tags | |
intcomma2 | เติม , ให้กับหลักพัน และถ้าค่าเป็นทศนิยมก็จะตัดเหลือแค่ 2 หลักให้อัตโนมัติ | |
intword_th | แสดงจำนวนเงินเป็นภาษาไทย | |
date_abbv_th | 11 พ.ย. 2556 | |
date_full_th | 5 ธันวาคม 2556 | |
month_abbv_th | ม.ค. 2556 | |
month_full_th | กุมภาพันธ์ 2556 | |
year_th | 2556 | |
system_status_display |