Fixed: Deprecatios for Django 4.0 Changed: path instead of url_path Added: fiaxateranking command
153 lines
4.6 KiB
Python
153 lines
4.6 KiB
Python
"""
|
|
Helper to generate XLSX Spreadsheets in an uniform way.
|
|
"""
|
|
import datetime
|
|
from datetime import date
|
|
|
|
import openpyxl
|
|
from openpyxl.styles import NamedStyle, Font, Border, Side
|
|
|
|
DEFAULT_FONT = Font(name='Philosopher', size=10, bold=False, color='000000')
|
|
THIN_BORDER = Border(
|
|
bottom=Side(style='thin', color="d3d7cf"),
|
|
top=Side(style='thin', color="d3d7cf"))
|
|
XLSX_STYLES = dict()
|
|
|
|
XLSX_STYLES['Content'] = NamedStyle(
|
|
name='Content',
|
|
font=DEFAULT_FONT,
|
|
border=THIN_BORDER
|
|
)
|
|
|
|
XLSX_STYLES['Headline'] = NamedStyle(
|
|
name="Headline",
|
|
font=openpyxl.styles.Font(name='Philosopher', size=11,
|
|
bold=True, color='ffffff'),
|
|
fill=openpyxl.styles.PatternFill(fill_type='solid',
|
|
start_color='a40000',
|
|
end_color='a40000')
|
|
)
|
|
|
|
XLSX_STYLES['Date'] = NamedStyle(
|
|
name='Date',
|
|
font=DEFAULT_FONT,
|
|
border=THIN_BORDER,
|
|
number_format='dd.mm.yyyy'
|
|
)
|
|
|
|
XLSX_STYLES['Date Time'] = NamedStyle(
|
|
name='Date Time',
|
|
font=DEFAULT_FONT,
|
|
border=THIN_BORDER,
|
|
number_format='dd.mm.yyyy hh:MM'
|
|
)
|
|
|
|
XLSX_STYLES['Float'] = NamedStyle(
|
|
name='Float',
|
|
font=DEFAULT_FONT,
|
|
border=THIN_BORDER,
|
|
number_format='#,##0.00'
|
|
)
|
|
|
|
XLSX_STYLES['Integer'] = NamedStyle(
|
|
name='Integer',
|
|
font=DEFAULT_FONT,
|
|
border=THIN_BORDER,
|
|
number_format='#,##0'
|
|
)
|
|
|
|
|
|
def getattr_recursive(obj, attr_string):
|
|
"""A recusive version of gettattr. the attr_string is splitted on the ".".
|
|
|
|
:param obj: a python object.
|
|
:param attr_string: the desired attribute of the object.
|
|
:return: a getattr_recursice(obj, 'attr1.attr2') will return the value of attr2 of attr1 from obj
|
|
"""
|
|
attr_list = attr_string.split('.')
|
|
return_value = None
|
|
for attr in attr_list:
|
|
return_value = getattr(obj, attr)
|
|
obj = return_value
|
|
if isinstance(return_value, datetime.datetime):
|
|
return_value = return_value.replace(tzinfo=None)
|
|
return return_value
|
|
|
|
|
|
class Workbook(object):
|
|
workbook = None
|
|
|
|
def __init__(self):
|
|
"""Generate an XLSX Workbook in memory
|
|
|
|
:rtype: object
|
|
"""
|
|
self.workbook = openpyxl.Workbook()
|
|
[self.workbook.add_named_style(style)
|
|
for style in XLSX_STYLES.values()]
|
|
[self.workbook.remove(sheet) for sheet in self.workbook.worksheets]
|
|
|
|
def generate_sheet(self, title, columns_settings, object_list,
|
|
orientation='landscape'):
|
|
"""
|
|
|
|
:param title: Title of the Sheet
|
|
:param columns_settings: a list of dicts for the settings of each column
|
|
:param object_list: List of objects that should be added to the sheet
|
|
:param orientation: Paper Orientation 'landscape' or 'portrait'
|
|
"""
|
|
row = 1
|
|
ws = self.workbook.create_sheet()
|
|
ws.title = title
|
|
ws.syncHorizontal = True
|
|
ws.filterMode = True
|
|
|
|
# setup print orientation
|
|
ws.page_setup.fitToHeight = 0
|
|
ws.page_setup.fitToWidth = 1
|
|
if orientation == 'landscape':
|
|
ws.page_setup.orientation = ws.ORIENTATION_LANDSCAPE
|
|
else:
|
|
ws.page_setup.orientation = ws.ORIENTATION_PORTRAIT
|
|
ws.page_setup.paperSize = ws.PAPERSIZE_A4
|
|
ws.print_options.horizontalCentered = True
|
|
|
|
# setup page header
|
|
ws.oddHeader.left.text = title
|
|
ws.oddHeader.left.size = 14
|
|
ws.oddHeader.left.font = "Amerika Sans"
|
|
ws.oddHeader.left.color = "000000"
|
|
|
|
ws.oddHeader.right.text = str(date.today())
|
|
ws.oddHeader.right.size = 14
|
|
ws.oddHeader.right.font = "Amerika Sans"
|
|
ws.oddHeader.right.color = "000000"
|
|
|
|
# write table header
|
|
for column, data in enumerate(columns_settings, 1):
|
|
cell = ws.cell(column=column, row=row, value=data['title'])
|
|
cell.style = 'Headline'
|
|
row += 1
|
|
|
|
# write the table content
|
|
for line in object_list:
|
|
for column, settings in enumerate(columns_settings, 1):
|
|
cell = ws.cell(column=column, row=row,
|
|
value=getattr_recursive(line, settings['attr']))
|
|
cell.style = settings['style']
|
|
row += 1
|
|
|
|
# write table footer
|
|
for column, settings in enumerate(columns_settings, 1):
|
|
cell = ws.cell(column=column, row=row,
|
|
value=settings.get('footer'))
|
|
cell.style = settings['style']
|
|
row += 1
|
|
|
|
# set column widths
|
|
for settings in columns_settings:
|
|
ws.column_dimensions[settings['col']].width = settings['width']
|
|
|
|
def save(self, *args, **kwargs):
|
|
return self.workbook.save(*args, **kwargs)
|