Автоматизация создания счетов-фактур в Python: от шаблона Excel к PDF
Генерация счетов-фактур — одна из самых распространённых задач в бизнес-приложениях. Будь то разработка ERP-системы, платформы электронной коммерции или внутреннего инструмента для выставления счетов, ручное создание счетов быстро становится неэффективным по мере роста числа клиентов.
Распространённый подход — разрабатывать счета в Excel, программно заполнять их данными, а затем экспортировать в PDF-файлы для распространения. Это сочетает гибкость шаблонов Excel с переносимостью и профессиональным видом PDF-документов.
В этой статье вы узнаете, как построить автоматизированный процесс создания счетов с помощью библиотеки Free Spire.XLS для Python. Мы возьмём шаблон счёта в Excel, заполним его информацией о клиенте и товарах, а затем экспортируем готовый счёт напрямую в PDF.
Почему стоит использовать шаблоны Excel для счетов?
Многие разработчики пытаются генерировать счета непосредственно в PDF. Хотя это работает, часто требует построения макетов, форматирования таблиц, позиционирования текста и расчёта итогов в коде.
Шаблоны Excel имеют ряд преимуществ:
Просты в изменении для бизнес-пользователей
Встроенная поддержка формул и вычислений
Привычная среда проектирования
Не нужно жёстко прописывать макеты в коде
Простой экспорт в PDF
Вместо того чтобы воссоздавать макет счёта в коде, вы можете позволить Excel заниматься форматированием, в то время как ваше приложение сосредоточится на предоставлении данных.
Процесс выглядит так:
Данные счёта
↓
Шаблон Excel
↓
Заполнение ячеек
↓
Пересчёт формул
↓
Экспорт в PDF
Проектирование шаблона счёта
Наш шаблон счёта содержит три раздела:
Верхняя часть счёта
Верхняя часть включает информацию о компании и реквизиты счёта.
Эти ячейки будут заполняться программно.
Позиции счёта
Раздел позиций начинается со строки 16 и реализован как таблица Excel .
Этот выбор важен, поскольку таблицы Excel предоставляют несколько встроенных возможностей:
Автоматическое чередование цветов строк
Автоматическое распространение формул
Динамическое расширение таблицы
Упрощённое обслуживание
Например:
Шаблон уже содержит формулы для расчёта итогов по строкам.
Итоговый раздел
Нижний раздел содержит формулы для:
Промежуточного итога
Налога
Общего итога
Вот как выглядит мой шаблон:
Установка Free Spire.XLS для Python
Установите библиотеку с помощью pip:
pip install spire.xls.free
Загрузка шаблона счёта
Сначала загрузите шаблон Excel в книгу.
from spire.xls import *
from spire.xls.common import *
workbook = Workbook()
workbook.LoadFromFile("InvoiceTemplate.xlsx")
sheet = workbook.Worksheets[0]
На этом этапе всё форматирование, формулы и определения таблиц из шаблона доступны.
Определение данных счёта
В реальных приложениях данные счёта обычно поступают из базы данных, API или ERP-системы.
В этом примере мы сохраним данные в словаре Python.
invoice = {
"company_name": "ABC Corporation",
"address_1": "123 Main Street",
"address_2": "New York, NY 10001",
"phone": "+1 (555) 123-4567",
"invoice_number": "INV-2026-001",
"customer_id": "CUST-1001",
"items": [
{
"qty": 2,
"description": "Laptop Computer",
"unit_price": 899.00
},
{
"qty": 1,
"description": "Wireless Mouse",
"unit_price": 29.99
},
{
"qty": 3,
"description": "USB-C Cable",
"unit_price": 12.50
}
]
}
Эта структура очень похожа на данные, возвращаемые многими бизнес-системами.
Заполнение информации о счёте
Далее заполним верхнюю часть счёта.
sheet.Range["C7"].Text = invoice["company_name"]
sheet.Range["C8"].Text = invoice["address_1"]
sheet.Range["C9"].Text = invoice["address_2"]
sheet.Range["C10"].Text = invoice["phone"]
sheet.Range["E8"].Text = invoice["invoice_number"]
sheet.Range["E9"].Text = invoice["customer_id"]
Эти значения заменяют заполнители, определённые в шаблоне.
Заполнение позиций счёта
Таблица позиций начинается со строки 16.
Мы можем записать каждую позицию в рабочий лист с помощью простого цикла.
start_row = 16
for index, item in enumerate(invoice["items"]):
row = start_row + index
sheet.Range[f"B{row}"].NumberValue = item["qty"]
sheet.Range[f"C{row}"].Text = item["description"]
sheet.Range[f"D{row}"].NumberValue = item["unit_price"]
Поскольку в шаблоне уже есть формулы для столбца «Line Total», нет необходимости вычислять суммы в коде.
Excel выполняет вычисления автоматически.
Почему стоит использовать таблицу Excel для позиций счёта?
Одна из самых больших проблем при генерации счетов — обработка переменного количества товаров.
Традиционные шаблоны часто требуют от разработчиков:
Вручную копировать формулы
Дублировать форматирование
Пересчитывать диапазоны
Обновлять итоги
Таблицы Excel устраняют большую часть этой сложности.
При вставке новых строк:
Чередование цветов строк сохраняется
Формулы автоматически распространяются на новые строки
Ссылки на таблицу обновляются автоматически
Итоги продолжают работать корректно
В результате приложению нужно только сосредоточиться на вставке данных.
Такое разделение обязанностей делает код гораздо чище и проще в обслуживании.
Обработка более шести позиций счёта
Наш шаблон резервирует шесть строк для товаров.
Если счёт содержит более шести позиций, можно динамически добавить дополнительные строки.
base_rows = 6
if len(invoice["items"]) > base_rows:
sheet.InsertRow(
22,
len(invoice["items"]) - base_rows
)
Поскольку список товаров реализован как таблица Excel, новые вставленные строки автоматически наследуют форматирование и формулы таблицы.
Никакого дополнительного кода для стилизации не требуется.
Пересчёт формул
Перед экспортом пересчитайте все формулы в книге.
workbook.CalculateAllValue()
Это гарантирует, что итоги по строкам, промежуточные итоги, налоги и общие итоги будут отражать актуальные данные.
Управление макетом страницы и масштабированием PDF
Перед экспортом счёта в PDF часто стоит настроить параметры страницы рабочего листа.
Без правильной конфигурации в сгенерированном PDF могут быть большие поля, избыточные отступы или содержимое, неоправданно уменьшенное в масштабе.
Следующие настройки помогают максимально использовать полезную площадь страницы и обеспечить чистое отображение счёта.
sheet.PageSetup.LeftMargin = 0.0
sheet.PageSetup.RightMargin = 0.0
sheet.PageSetup.TopMargin = 0.0
sheet.PageSetup.BottomMargin = 0.0
# Вместить рабочий лист на одну страницу
workbook.ConverterSetting.SheetFitToPage = True
Эти настройки:
Убирают ненужные поля
Максимизируют доступное пространство
Улучшают читаемость
Дают более профессиональный вид PDF
Обработка длинных счетов
Если счёт может содержать много товаров и занимать несколько страниц, размещение всего листа на одной странице обычно нежелательно, потому что содержимое становится слишком мелким.
В этом случае настройте лист на соответствие ширине страницы, разрешив неограниченную высоту.
sheet.PageSetup.FitToPagesWide = 1
sheet.PageSetup.FitToPagesTall = 0
Это указывает Excel:
Уместить счёт в пределах ширины одной страницы
Автоматически создавать дополнительные страницы по вертикали при необходимости
В результате длинные счета остаются читаемыми, сохраняя исходное форматирование.
Экспорт счёта в PDF
Наконец, сохраните книгу как PDF-документ.
workbook.SaveToFile(
"Invoice.pdf",
FileFormat.PDF
)
Поскольку макет листа уже оптимизирован, экспортированный PDF сохраняет предполагаемый внешний вид счёта.
Сгенерированная PDF-счет выглядит так:
Полный пример
from spire.xls import Workbook, FileFormat
# Создание книги
workbook = Workbook()
workbook.LoadFromFile(r"C:\Users\Administrator\Desktop\invoice-template.xlsx")
# Получение рабочего листа
sheet = workbook.Worksheets[0]
# ==========================================
# Данные счёта
# ==========================================
invoice = {
"company_name": "ABC Corporation",
"address_1": "123 Main Street",
"address_2": "New York, NY 10001",
"phone": "+1 (555) 123-4567",
"invoice_number": "INV-2026-001",
"customer_id": "CUST-1001",
"items": [
{
"qty": 2,
"description": "Laptop Computer",
"unit_price": 899.00
},
{
"qty": 1,
"description": "Wireless Mouse",
"unit_price": 29.99
},
{
"qty": 3,
"description": "USB-C Cable",
"unit_price": 12.50
}
]
}
# ==========================================
# Заполнение информации о счёте
# ==========================================
# C7-C10
sheet.Range["C7"].Text = invoice["company_name"]
sheet.Range["C8"].Text = invoice["address_1"]
sheet.Range["C9"].Text = invoice["address_2"]
sheet.Range["C10"].Text = invoice["phone"]
# E8-E9
sheet.Range["E8"].Text = invoice["invoice_number"]
sheet.Range["E9"].Text = invoice["customer_id"]
# ==========================================
# Заполнение позиций счёта
# ==========================================
start_row = 16
for index, item in enumerate(invoice["items"]):
row = start_row + index
sheet.Range[f"B{row}"].NumberValue = item["qty"]
sheet.Range[f"C{row}"].Text = item["description"]
sheet.Range[f"D{row}"].NumberValue = item["unit_price"]
# ==========================================
# Пересчёт формул
# ==========================================
workbook.CalculateAllValue()
# ==========================================
# Экспорт в PDF
# ==========================================
sheet.PageSetup.LeftMargin = 0.0
sheet.PageSetup.RightMargin = 0.0
sheet.PageSetup.TopMargin = 0.0
sheet.PageSetup.BottomMargin = 0.0
# Вместить лист на одну страницу
workbook.ConverterSetting.SheetFitToPage = True
# Для длинного счёта, превышающего одну страницу, установите FitToPagesTall = 0,
# чтобы разрешить размещение на нескольких страницах по вертикали
# sheet.PageSetup.FitToPagesWide = 1
# sheet.PageSetup.FitToPagesTall = 0
workbook.SaveToFile(
"Invoice.pdf",
FileFormat.PDF
)
workbook.Dispose()
Заключение
Использование Excel в качестве движка для шаблонов счетов может значительно упростить генерацию счетов. Храня макеты, формулы и форматирование в электронной таблице, разработчики могут сосредоточиться на предоставлении данных, а не на управлении деталями представления.
Сочетание шаблона Excel с Free Spire.XLS для Python позволяет автоматизировать весь процесс — от заполнения данных счёта до создания профессиональных PDF-документов — с удивительно небольшим количеством кода.
Когда раздел позиций счёта реализован как таблица Excel, решение становится ещё более поддерживаемым. Форматирование, формулы и расширение таблицы обрабатываются автоматически, что упрощает поддержку счетов любого размера, сохраняя вашу кодовую базу чистой и простой.



