# -*- coding: utf-8 -*-
"""
Some utility functions for user convenience
"""
# Standard library imports
import io
import os
import csv
import webbrowser
import datetime
from tkinter import Tk
from tkinter.filedialog import asksaveasfilename
# Third party imports
from tabulate import tabulate
from openpyxl import Workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.utils import get_column_letter
[docs]def send_emails(mitglieder, to='', method='bcc', email1=True, email2=True,
open_browser=True):
"""
Send emails to several members.
Args:
mitglieder (list): The List contents can be either
:class:`~pynami.schemas.SearchMitglied` or
:class:`~pynami.schemas.Mitglied`
to (:obj:`str`, optional): Primary recipient
method (:obj:`str`, optional): If you want to send your mails as bcc
or something else. Currently only bcc is supported.
email1 (:obj:`bool`, optional): If emails should be send to the
primary address of the members.
email2 (:obj:`bool`, optional): If emails should be send to the email
account of the member's parent.
open_browser (:obj:`bool`, optional): If :data:`True` the link is
opened directly by the system. On a computer this may open your
default mail program.
Returns:
str: The mailto link
"""
recipients = []
if email1:
recipients += [mgl.email for mgl in mitglieder if mgl.email]
if email2:
recipients += [mgl.emailVertretungsberechtigter for mgl in mitglieder
if mgl.emailVertretungsberechtigter]
url = f"mailto:{to}?{method}={','.join(set(recipients))}"
if open_browser:
webbrowser.open(url, new=1)
return url
[docs]def tabulate2x(objs, elements=None):
"""
Tabulate a list of objects by tabulating each object first
Args:
obj (list): The list of objects to tabulate. If they are not from the
same class this may not work.
elements (:obj:`list` of :obj:`str`, optional): List of keys which
should be displayed
Returns:
str: Nicely formatted tabulated output
"""
return tabulate([x.tabulate(elements=elements) for x in objs],
headers='keys')
[docs]def make_csv(data, attrs=None, includeheader=True, delimiter=','):
"""
Makes a |CSV| formatted string from a data set
Args:
data (list): Data objects. They should all belong to the same class.
attrs (:obj:`list` of `str`, optional): Attribute names for the |CSV|
table. If left empty (:data:`None`) the value of the first
:attr:`~.schemas.base.BaseModel._tabkeys` attribute in the list is
taken.
includeheader (:obj:`bool`, optional): Whether to include headers in
the output. Defaults to :data:`True`.
Returns:
str: |CSV| formatted data
"""
if not data:
return ''
if not attrs:
attrs = data[0]._tabkeys
data = [x.tabulate(attrs) for x in data]
output = io.StringIO()
w = csv.DictWriter(output, attrs, quoting=csv.QUOTE_NONNUMERIC,
delimiter=delimiter)
if includeheader:
w.writeheader()
w.writerows(data)
return output.getvalue()
[docs]def export_xlsx(data, attrs=None, includeheader=True, tableName='Tabelle1',
sheetName='Data', write_to_file=False, filepath=''):
"""
Create a Microsoft Excel Wokbook from a given dataset. The data can
optionally be saved to a file.
Args:
data (list): Data objects. They should all belong to the same class.
attrs (:obj:`list` of `str`, optional): Attribute names for the |CSV|
table. If left empty (:data:`None`) the value of the first
:attr:`~.schemas.base.BaseModel._tabkeys` attribute in the
list is taken.
includeheader (:obj:`bool`, optional): Whether to include headers in
the output. Defaults to :data:`True`.
tableName (:obj:`str`, optional): Name of the table. Defaults to
`'Tabelle1'`.
sheetName (:obj:`str`, optional): Name of the worksheet. Defaults to
`'Data'`.
write_to_file (:obj:`bool`, optional): If the workbook should be saved
to a file. Defaults to :data:`False`.
filepath (:obj:`str`, optional): Full path to the Excel file where the
data should be saved. If left empty the default savefile dialog will
be invoked via the module :mod:`tkinter`.
Returns:
:class:`~openpyxl.workbook.workbook.Workbook`: The created workbook.
"""
wb = Workbook()
if not data:
return wb
# Get headings and format data
if not attrs:
attrs = data[0]._tabkeys
data = [[getattr(x, a) for a in attrs] for x in data]
# Write data to worksheet
ws = wb.active
ws.title = sheetName
if includeheader:
ws.append(attrs)
for row in data:
ws.append(row)
for row in ws:
for cell in row:
if isinstance(cell.value, (datetime.datetime, datetime.date)):
cell.value = cell.value.strftime('%d.%m.%Y')
cell.number_format = 'dd.mm.yyyy'
# Create the table
tab = Table(displayName=tableName,
ref='A1:' + get_column_letter(ws.max_column) + str(ws.max_row))
style = TableStyleInfo(name="TableStyleLight1", showFirstColumn=False,
showLastColumn=False, showRowStripes=True,
showColumnStripes=False)
tab.tableStyleInfo = style
# Add the table to the worksheet
ws.add_table(tab)
# Optional saving as file
if write_to_file:
if not filepath:
Tk().withdraw()
filepath = asksaveasfilename(filetypes=[('Excel files', '*.xlsx')],
initialdir = os.getcwd(),
defaultextension=".xlsx")
if filepath:
wb.save(filepath)
# Return the workbook
return wb