از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
ایجاد فاکتورهای PDF در پایتون با borb
سرفصلهای مطلب
معرفی
این فرمت سند قابل حمل (PDF) فرمت WYSIWYG (آنچه می بینید همان چیزی است که می گیرید) نیست. این برای پلتفرم-آگنوستیک، مستقل از سیستم عامل اصلی و موتورهای رندر توسعه داده شد.
برای دستیابی به این هدف، PDF ساخته شد تا از طریق چیزی بیشتر شبیه به یک زبان برنامه نویسی و متکی با آن تعامل داشته باشد. روی مجموعه ای از دستورالعمل ها و عملیات برای رسیدن به نتیجه. در واقع PDF است مستقر روی یک زبان برنامه نویسی – پست اسکریپتکه اولین دستگاه مستقل بود زبان توضیحات صفحه.
در این راهنما، ما استفاده خواهیم کرد بورب – یک کتابخانه پایتون که به خواندن، دستکاری و تولید اسناد PDF اختصاص یافته است. هم یک مدل سطح پایین (که به شما امکان میدهد به مختصات و طرحبندی دقیق در صورت استفاده از آنها دسترسی داشته باشید) و هم یک مدل سطح بالا (که در آن میتوانید محاسبات دقیق حاشیهها، موقعیتها و غیره را به یک مدیر طرحبندی واگذار کنید) ارائه میدهد. .
ما نگاهی به روش ایجاد فاکتور PDF در پایتون با استفاده از borb.
نصب borb
بورب را می توان از منبع دانلود کرد روی GitHub، یا نصب شده از طریق pip
:
$ pip install borb
ایجاد فاکتور PDF در پایتون با borb
بورب دارای دو کلاس کلیدی بصری – Document
و Page
، که نشان دهنده یک سند و صفحات درون آن است. علاوه بر این، PDF
کلاس یک API را برای بارگیری و ذخیره کردن نشان می دهد Document
ما ایجاد می کنیم.
بیایید یک را ایجاد کنیم Document()
و Page()
به عنوان یک بوم خالی که می توانیم فاکتور را به آن اضافه کنیم:
from borb.pdf.document import Document
from borb.pdf.page.page import Page
pdf = Document()
page = Page()
pdf.append_page(page)
از آنجایی که ما نمی خواهیم با محاسبه مختصات سر و کار داشته باشیم – می توانیم این را به a واگذار کنیم PageLayout
که تمام محتوا و موقعیت های آن را مدیریت می کند:
from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout
from decimal import Decimal
page_layout = SingleColumnLayout(page)
page_layout.vertical_margin = page.get_page_info().get_height() * Decimal(0.02)
در اینجا، ما از a استفاده می کنیم SingleColumnLayout
از آنجایی که همه محتوا باید در یک ستون باشد – ما سمت چپ و راست فاکتور نخواهیم داشت. ما همچنین حاشیه عمودی را در اینجا کوچکتر می کنیم. مقدار پیشفرض این است که 10 درصد بالا را برش دهید page ارتفاع به عنوان حاشیه، و ما آن را به 2٪ کاهش می دهیم، زیرا می خواهیم از این فضا برای نشان و نام شرکت استفاده کنیم.
در مورد آن، بیایید لوگوی شرکت را به طرح اضافه کنیم:
from borb.pdf.canvas.layout.image.image import Image
page_layout.add(
Image(
"https://s3.rasanegar.com/media/articles/creating-an-invoice-in-python-with-ptext-1.png",
width=Decimal(128),
height=Decimal(128),
))
در اینجا، ما یک عنصر را به طرح اضافه می کنیم – an Image()
. از طریق سازنده آن، یک URL اضافه می کنیم که به منبع تصویر اشاره می کند و آن را تنظیم می کنیم width
و height
.
در زیر تصویر، ما می خواهیم اطلاعات خیالی شرکت (نام، آدرس، وب سایت، تلفن) و همچنین اطلاعات فاکتور (شماره فاکتور، تاریخ، تاریخ سررسید) را اضافه کنیم. یک فرمت رایج برای مختصر (که اتفاقاً کد را نیز پاکتر میکند) استفاده از a است جدول برای ذخیره داده های فاکتور بیایید یک روش کمکی جداگانه برای ساخت اطلاعات فاکتور در یک جدول ایجاد کنیم، که سپس میتوانیم از آن برای اضافه کردن یک جدول به صورت حساب در روش اصلی خود استفاده کنیم:
from borb.pdf.canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable as Table
from borb.pdf.canvas.layout.text.paragraph import Paragraph
from borb.pdf.canvas.layout.layout_element import Alignment
from datetime import datetime
import random
def _build_invoice_information():
table_001 = Table(number_of_rows=5, number_of_columns=3)
table_001.add(Paragraph("(Street Address)"))
table_001.add(Paragraph("Date", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT))
now = datetime.now()
table_001.add(Paragraph("%d/%d/%d" % (now.day, now.month, now.year)))
table_001.add(Paragraph("(City, State, ZIP Code)"))
table_001.add(Paragraph("Invoice #", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT))
table_001.add(Paragraph("%d" % random.randint(1000, 10000)))
table_001.add(Paragraph("(Phone)"))
table_001.add(Paragraph("Due Date", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT))
table_001.add(Paragraph("%d/%d/%d" % (now.day, now.month, now.year)))
table_001.add(Paragraph("(Email Address)"))
table_001.add(Paragraph(" "))
table_001.add(Paragraph(" "))
table_001.add(Paragraph("(Company Website)"))
table_001.add(Paragraph(" "))
table_001.add(Paragraph(" "))
table_001.set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2))
table_001.no_borders()
return table_001
در اینجا، ما در حال ساخت یک ساده هستیم Table
دارای 5 سطر و 3 ستون ردیف ها با آدرس خیابان، شهر/ایالت، تلفن، آدرس ایمیل و وب سایت شرکت مطابقت دارند. هر ردیف خواهد داشت 0..3
مقادیر (ستون ها). هر عنصر متن به عنوان یک اضافه می شود Paragraph
، که از طریق آن را به سمت راست تراز کرده ایم Alignment.RIGHT
، و استدلال های سبک مانند را بپذیرید font
.
در نهایت، ما به تمام سلولها padding اضافه کردهایم تا مطمئن شویم که متن را بهطور نامناسبی در نزدیکی سلولها قرار نمیدهیم.
اکنون، به روش اصلی خود، می توانیم تماس بگیریم _build_invoice_information()
برای پر کردن جدول و اضافه کردن آن به طرحبندی:
page_layout = SingleColumnLayout(page)
page_layout.vertical_margin = page.get_page_info().get_height() * Decimal(0.02)
page_layout.add(
Image(
"https://s3.rasanegar.com/media/articles/creating-an-invoice-in-python-with-ptext-1.png",
width=Decimal(128),
height=Decimal(128),
))
page_layout.add(_build_invoice_information())
page_layout.add(Paragraph(" "))
اکنون، بیایید این سند PDF را به سرعت بسازیم تا ببینیم چگونه به نظر می رسد. برای این کار از PDF
مدول:
from borb.pdf.pdf import PDF
with open("output.pdf", "wb") as pdf_file_handle:
PDF.dumps(pdf_file_handle, pdf)
عالی! اکنون می خواهیم اطلاعات صورتحساب و حمل و نقل را نیز اضافه کنیم. درست مانند اطلاعات شرکت، به راحتی در یک جدول قرار می گیرد. برای اختصار، ما همچنین تصمیم می گیریم که یک تابع کمکی جداگانه برای ساخت این اطلاعات ایجاد کنیم، و سپس می توانیم به سادگی آن را در روش اصلی خود اضافه کنیم:
from borb.pdf.canvas.color.color import HexColor, X11Color
def _build_billing_and_shipping_information():
table_001 = Table(number_of_rows=6, number_of_columns=2)
table_001.add(
Paragraph(
"BILL TO",
background_color=HexColor("263238"),
font_color=X11Color("White"),
)
)
table_001.add(
Paragraph(
"SHIP TO",
background_color=HexColor("263238"),
font_color=X11Color("White"),
)
)
table_001.add(Paragraph("(Recipient Name)"))
table_001.add(Paragraph("(Recipient Name)"))
table_001.add(Paragraph("(Company Name)"))
table_001.add(Paragraph("(Company Name)"))
table_001.add(Paragraph("(Street Address)"))
table_001.add(Paragraph("(Street Address)"))
table_001.add(Paragraph("(City, State, ZIP Code)"))
table_001.add(Paragraph("(City, State, ZIP Code)"))
table_001.add(Paragraph("(Phone)"))
table_001.add(Paragraph("(Phone)"))
table_001.set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2))
table_001.no_borders()
return table_001
ما تنظیم کرده ایم background_color
از پاراگراف های اولیه به #263238
(خاکستری-آبی) برای مطابقت با رنگ لوگو، و font_color
به White
.
بیایید این را در روش اصلی نیز صدا کنیم:
page_layout.add(_build_invoice_information())
page_layout.add(Paragraph(" "))
page_layout.add(_build_billing_and_shipping_information())
هنگامی که اسکریپت را دوباره اجرا می کنیم، یک فایل PDF جدید ایجاد می شود که حاوی اطلاعات بیشتری است:
با طبقه بندی اطلاعات اولیه ما (اطلاعات شرکت و اطلاعات صورتحساب/ حمل و نقل) – می خواهیم یک توضیح جزئی اضافه کنیم. اینها کالاها/خدماتی خواهند بود که شرکت فرضی ما به شخصی ارائه کرده است و همچنین معمولاً به شکل جدولی زیر اطلاعاتی که قبلاً اضافه کرده ایم انجام می شود.
دوباره، بیایید یک تابع کمکی ایجاد کنیم که یک جدول تولید می کند و آن را با داده ها پر می کند، که بعداً می توانیم به سادگی به طرح بندی خود اضافه کنیم. روی:
from borb.pdf.canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable as Table
from borb.pdf.canvas.layout.table.table import TableCell
def _build_itemized_description_table(self):
table_001 = Table(number_of_rows=15, number_of_columns=4)
for h in ("DESCRIPTION", "QTY", "UNIT PRICE", "AMOUNT"):
table_001.add(
TableCell(
Paragraph(h, font_color=X11Color("White")),
background_color=HexColor("016934"),
)
)
odd_color = HexColor("BBBBBB")
even_color = HexColor("FFFFFF")
for row_number, item in enumerate((("Product 1", 2, 50), ("Product 2", 4, 60), ("Labor", 14, 60))):
c = even_color if row_number % 2 == 0 else odd_color
table_001.add(TableCell(Paragraph(item(0)), background_color=c))
table_001.add(TableCell(Paragraph(str(item(1))), background_color=c))
table_001.add(TableCell(Paragraph("$ " + str(item(2))), background_color=c))
table_001.add(TableCell(Paragraph("$ " + str(item(1) * item(2))), background_color=c))
for row_number in range(3, 10):
c = even_color if row_number % 2 == 0 else odd_color
for _ in range(0, 4):
table_001.add(TableCell(Paragraph(" "), background_color=c))
table_001.add(TableCell(Paragraph("Subtotal", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT,), col_span=3,))
table_001.add(TableCell(Paragraph("$ 1,180.00", horizontal_alignment=Alignment.RIGHT)))
table_001.add(TableCell(Paragraph("Discounts", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT,),col_span=3,))
table_001.add(TableCell(Paragraph("$ 177.00", horizontal_alignment=Alignment.RIGHT)))
table_001.add(TableCell(Paragraph("Taxes", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT), col_span=3,))
table_001.add(TableCell(Paragraph("$ 100.30", horizontal_alignment=Alignment.RIGHT)))
table_001.add(TableCell(Paragraph("Total", font="Helvetica-Bold", horizontal_alignment=Alignment.RIGHT ), col_span=3,))
table_001.add(TableCell(Paragraph("$ 1163.30", horizontal_alignment=Alignment.RIGHT)))
table_001.set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2))
table_001.no_borders()
return table_001
در عمل، رشتههای رمزگذاریشده مربوط به کل فرعی، مالیاتها و قیمتهای کل را با محاسبات قیمتهای واقعی جایگزین میکنید – هرچند، این به شدت بستگی دارد. روی اجرای اساسی شما Product
مدل ها ، بنابراین ما یک ایستاده برای انتزاع اضافه کرده ایم. پس از اضافه کردن این جدول به سند – می توانیم آن را دوباره بسازیم و نگاهی بیندازیم.
اکنون کل روش اصلی باید چیزی در امتداد خطوط زیر باشد:
pdf = Document()
page = Page()
pdf.append_page(page)
page_layout = SingleColumnLayout(page)
page_layout.vertical_margin = page.get_page_info().get_height() * Decimal(0.02)
page_layout.add(
Image(
"https://s3.rasanegar.com/media/articles/creating-an-invoice-in-python-with-ptext-1.png",
width=Decimal(128),
height=Decimal(128),
))
page_layout.add(_build_invoice_information())
page_layout.add(Paragraph(" "))
page_layout.add(_build_billing_and_shipping_information())
page_layout.add(_build_itemized_description_table())
with open("output2.pdf", "wb") as pdf_file_handle:
PDF.dumps(pdf_file_handle, pdf)
اجرای این قطعه کد به این نتیجه می رسد:
ایجاد طرح کلی
PDF ما انجام شده و آماده سرو است – هرچند ، ما می توانیم آن را با دو مورد کوچک اضافه کنیم. ابتدا می توانیم یک عدد اضافه کنیم طرح کلی، که به خوانندگانی مانند Adobe کمک می کند تا در PDF های شما منویی تولید کنند و تولید کنند:
from borb.pdf.page.page import DestinationType
pdf.add_outline("Your Invoice", 0, DestinationType.FIT, page_nr=0)
این add_outline()
تابع چند آرگومان را می پذیرد:
title
: عنوانی که در منوی جانبی نمایش داده می شودlevel
: چه چیزی در اعماق درخت خواهد بود. سطح 0 است root-مرحله.- چندین استدلال که یک “مقصد” را تشکیل می دهند
مقصد را می توان به عنوان اهداف لینک لینک فکر کرد. می توانید به یک کل پیوند دهید page (این همان کاری است که ما در این مثال انجام می دهیم) ، اما شما همچنین می توانید به قسمت های خاصی از a پیوند دهید page (به عنوان مثال – دقیقاً در مختصات y 350).
علاوه بر این ، شما باید مشخص کنید که چگونه خواننده باید آن را ارائه دهد page – به عنوان مثال ، آیا می خواهید به سادگی به آن پیمایش کنید page و زوم نکنیم؟ آیا میخواهید فقط یک ناحیه مورد نظر را نمایش دهید، در حالی که خواننده به طور کامل در آن منطقه خاص زوم شده است؟
در این خط کد ، ما از خواننده می خواهیم که نمایش دهد page 0 (اولین page) و مطمئن شوید که با پنجره خواننده مطابقت دارد (در صورت نیاز بزرگنمایی/کوچک کردن).
پس از افزودن طرح کلی ، باید آن را در خواننده مورد نظر خود مشاهده کنید:
با چندین صفحه – می توانید طرح کلی پیچیده تری ایجاد کنید و از طریق آنها به آنها پیوند دهید add_outline()
برای ناوبری راحت تر
جاسازی اسناد JSON در فاکتورهای PDF
از آنجایی که PDF ها (از نظر خواندن و رمزگشایی بدون ابهام) بسیار سازگار با کامپیوتر نیستند – گاهی اوقات، ممکن است بخواهیم فرمت های سازگار با کامپیوتر بیشتری را نیز اضافه کنیم. process فاکتورها به صورت خودکار
یک استاندارد فاکتور آلمانی به نام ZUGFeRD (که بعداً توسط اتحادیه اروپا تصویب شد) ما را قادر می سازد فاکتورهای PDF را با فرمت های فایل خوانا در رایانه مانند XML ایجاد کنیم – که فاکتور را توصیف می کند و به راحتی قابل تجزیه است. علاوه بر اینها، می توانید سایر اسناد مربوط به فاکتور خود مانند شرایط و توافقات، سیاست بازپرداخت و غیره را نیز درج کنید.
برای جاسازی هر نوع فایل اضافی در یک فایل PDF، با استفاده از borb – می توانیم از آن استفاده کنیم
append_embedded_file()
تابع.
بیایید ابتدا پیش برویم و یک فرهنگ لغت ایجاد کنیم تا دادههای فاکتور خود را در JSON ذخیره کنیم، که سپس آن را در یک فایل ذخیره میکنیم. invoice_json
فایل:
import json
invoice_json = {
"items": (
{
"Description": "Product1",
"Quantity": 2,
"Unit Price": 50,
"Amount": 100,
},
{
"Description": "Product2",
"Quantity": 4,
"Unit Price": 60,
"Amount": 100,
},
{
"Description": "Labor",
"Quantity": 14,
"Unit Price": 60,
"Amount": 100,
},
),
"Subtotal": 1180,
"Discounts": 177,
"Taxes": 100.30,
"Total": 1163.30,
}
invoice_json_bytes = bytes(json.dumps(invoice_json, indent=4), encoding="latin1")
اکنون، ما می توانیم به سادگی این فایل را در فاکتور PDF خود جاسازی کنیم:
pdf.append_embedded_file("invoice.json", invoice_json_bytes)
هنگامی که اسکریپت را دوباره اجرا می کنیم و سند را ذخیره می کنیم، می رویم:
نتیجه
در این راهنما، نگاهی به روش ایجاد فاکتور در پایتون با استفاده از borb انداخته ایم. سپس برای سهولت پیمایش، طرح کلی را به فایل PDF اضافه کردهایم و نگاهی به روش افزودن پیوستها/فایلهای تعبیهشده برای دسترسی برنامهای به محتویات PDF انداختهایم.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-10 22:03:05