Время прочтения: 3 мин.
Отчёт – это особая форма представления данных. Он позволяет пользователю познакомиться с отобранными, агрегированными и особо оформленными данными. На сегодняшний день формирование и представление отчетов все еще является актуальной формой доведения до пользователя информации.
В этой статье рассматривается один из способов автоматического формирования отчета в формате файла MS WORD, начиная от непосредственного запроса к данным БД MSSQL и заканчивая его оформлением. В качестве инструментария используется python и модуль docx.
Для начала ознакомимся с используемыми данными. В БД имеются 3 таблицы с данными о товарах, покупателях и продажах.
Для начала нам понадобится импортировать в код необходимые модули:
from docx import Document
import pandas as pd
import pandas.io.sql as psql
import matplotlib.pyplot as plt
from io import BytesIO
import pyodbc
Создаем соединение и формируем запрос. На данном этапе пользователю следует определиться с составом запрашиваемых запросом данных исходя из имеющейся задачи, т.е. на каком этапе производятся расчеты, агрегирование и/или фильтрация данных. В нашем случае будут запрашиваться данные всех продаж с привязкой к ФИО покупателя и данным о товаре. Обработка данных будет производится с помощью модуля pandas.
cnxn = pyodbc.connect("Driver={SQL Server Native Client 11.0};"
"Server=S1;"
"Database=test;"
"uid=sa;pwd=pass;"
"Trusted_Connection=yes;")
cursor = cnxn.cursor()
sql = '''select
c.name
,p.*
from [dbo].[sales] s
join [dbo].[customers] c
on c.id = s.customer
join [dbo].[product] p
on s.product = p.id'''
Полученные данные отправляем в dataframe, закрываем соединение
df = psql.read_sql_query(sql,cnxn)
cnxn.close()
del df['id'] # ненужный столбец df
Следующий этап – непосредственно создание документа.
document = Document() # создается объект
# добавляем первый заголовок
document.add_heading('Отчет о продажах', 0)
# добавляем простой текст с переменными из
# данных таблицы (названия магазинов)
shop_list = ', '.join(df['shop'].unique().tolist())
p = document.add_paragraph('Отчет о продажах в магазинах: ')
# к тексту добавим сам список, выделяем жирным шрифтом
p.add_run(shop_list).bold = True
Формируем таблицу о всех продажах – аналог входных данных запроса.
document.add_heading('Общие продажи', level=1) # заголовок
rows, columns = df.shape # размеры dataframe
table = document.add_table(rows=1, cols=columns) # создаем таблицу
table.style = "Colorful List Accent 1" # определяем стиль
# формируем заголовки таблицы
hdr_cells = table.rows[0].cells
for i in range(columns):
hdr_cells[i].text = list(df.columns.values)[i]
# заполняем данными из dataframe
for row in range(rows):
row_cells = table.add_row().cells
row_data = df.iloc[row].tolist()
for column in range(columns):
row_cells[column].text = str(row_data[column])
На выходе получается следующий документ.
Какой же отчет бывает без графиков. Для примера, создадим график затрат в разрезе клиентов.
# заголовок
document.add_heading(' ', 0)
document.add_heading('График общих затрат покупателей', 0)
# пустой объект, куда будет помещен plot
memfile = BytesIO()
fig = plt.figure()
# данные для графика: клиенты и суммы затрат
plt.plot(df.groupby('name')['price'].sum())
fig.savefig(memfile)
document.add_picture(memfile) # размещение в документе
document.save('demo.docx') # публикация в файловой системе
На выходе получаем.
Это далеко не все возможности модуля docx, позволяющие произвести верстку документа «на лету» с использованием данных, взятых непосредственно из БД и агрегированных с помощью Python. Более подробную информацию о верстке, использовании стилей, вставке объектов и т.п. можно ознакомится на сайте разработчиков https://python-docx.readthedocs.io.