import base64 import uuid import os import datetime from openpyxl.styles import PatternFill, Border, Side, Alignment, Font from decimal import Decimal from openpyxl.drawing.image import Image from openpyxl import Workbook ######################################################################################################################## # PROCEDURES # Step 1: Validate the report data # Step 2: Generate excel file # Step 3: Encode the excel file bytes to Base64 ######################################################################################################################## def export(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type): #################################################################################################################### # Step 1: Validate the report data #################################################################################################################### if report is None: return None print(report) #################################################################################################################### # Step 2: Generate excel file from the report data #################################################################################################################### filename = generate_excel(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type) #################################################################################################################### # Step 3: Encode the excel file to Base64 #################################################################################################################### binary_file_data = b'' try: with open(filename, 'rb') as binary_file: binary_file_data = binary_file.read() except IOError as ex: pass # Base64 encode the bytes base64_encoded_data = base64.b64encode(binary_file_data) # get the Base64 encoded data using human-readable characters. base64_message = base64_encoded_data.decode('utf-8') # delete the file from server try: os.remove(filename) except NotImplementedError as ex: pass return base64_message def generate_excel(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type): wb = Workbook() ws = wb.active ws.title = "TenantBill" # Row height for i in range(1, 11 + 1): ws.row_dimensions[i].height = 0.1 ws.row_dimensions[12].height = 30.0 ws.row_dimensions[13].height = 10.0 ws.merge_cells('B13:I13') for i in range(14, 23 + 1): ws.row_dimensions[i].height = 0.1 ws.row_dimensions[24].height = 20.0 ws.row_dimensions[25].height = 10.0 ws.merge_cells('B25:I25') for i in range(26, 35 + 1): ws.row_dimensions[i].height = 0.1 for i in range(36, 41 + 1): ws.row_dimensions[i].height = 20.0 ws.row_dimensions[42].height = 10.0 ws.merge_cells('B42:I42') for i in range(43, 52 + 1): ws.row_dimensions[i].height = 0.1 # Col width ws.column_dimensions['A'].width = 1.5 for i in range(ord('B'), ord('J')): ws.column_dimensions[chr(i)].width = 16 ws.column_dimensions['J'].width = 1.5 # merge cell ws.merge_cells('C12:H12') ws.merge_cells('C24:I24') # Font notice_font = Font(name='宋体', size=20, bold=True) name_font = Font(name='Constantia', size=12, bold=True) title_font = Font(name='宋体', size=11, bold=True) data_font = Font(name='Franklin Gothic Book', size=11) table_fill = PatternFill(fill_type='solid', fgColor='1F497D') f_border = Border(left=Side(border_style='medium', color='00000000'), right=Side(border_style='medium', color='00000000'), bottom=Side(border_style='medium', color='00000000'), top=Side(border_style='medium', color='00000000') ) c_c_alignment = Alignment(vertical='center', horizontal='center', text_rotation=0, wrap_text=False, shrink_to_fit=False, indent=0) b_r_alignment = Alignment(vertical='bottom', horizontal='right', text_rotation=0, wrap_text=False, shrink_to_fit=False, indent=0) b_l_alignment = Alignment(vertical='bottom', horizontal='left', text_rotation=0, wrap_text=False, shrink_to_fit=False, indent=0) ws['C12'].font = notice_font ws['C12'].alignment = c_c_alignment ws['C12'] = '付款通知书' # img img = Image("excelexporters/myemslogo.png") img.width = 117 img.height = 117 ws.add_image(img, 'I12') has_lease_number_data_flag = True if "tenant" not in report.keys() or \ report['tenant'] is None or \ 'lease_number' not in report['tenant'].keys() or \ report['tenant']['lease_number'] is None: has_lease_number_data_flag = False ws.row_dimensions[24].height = 0.1 if has_lease_number_data_flag: ws['B24'].font = name_font ws['B24'].alignment = b_r_alignment ws['B24'] = '租赁合同号码:' ws['C24'].alignment = b_l_alignment ws['C24'].font = name_font ws['C24'] = report['tenant']['lease_number'] has_tenant_data_flag = True if "tenant" not in report.keys() or \ report['tenant'] is None: has_tenant_data_flag = False for i in range(36, 41 + 1): ws.row_dimensions[i].height = 0.1 if has_tenant_data_flag: report_tenant_data = report['tenant'] for i in range(36, 41 + 1): ws.merge_cells('C{}:D{}'.format(i, i)) ws['C' + str(i)].alignment = b_l_alignment ws['C' + str(i)].font = name_font ws['C36'] = report_tenant_data['name'] ws.merge_cells('E36:I36') ws['C37'] = report_tenant_data['rooms'] ws['C38'] = report_tenant_data['floors'] ws['C39'] = report_tenant_data['buildings'] ws['C40'] = report_tenant_data['email'] ws['C41'] = report_tenant_data['phone'] for i in range(37, 41 + 1): ws.merge_cells('E{}:G{}'.format(i, i)) ws.merge_cells('H{}:I{}'.format(i, i)) ws['E' + str(i)].alignment = b_r_alignment ws['E' + str(i)].font = name_font ws['H' + str(i)].alignment = b_l_alignment ws['H' + str(i)].font = name_font ws['E37'] = '账单号码:' ws['E38'] = '租赁合同号码:' ws['E39'] = '账单日期:' ws['E40'] = '付款到期日:' ws['E41'] = '应付款金额:' # Simulated data ws['H37'] = '' ws['H38'] = report_tenant_data['lease_number'] ws['H39'] = datetime.datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') ws['H40'] = datetime.datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') ws['H41'] = report['reporting_period']['currency_unit'] + \ str(round(report['reporting_period']['total_cost'] if 'reporting_period' in report.keys() and 'total_cost' in report['reporting_period'].keys() and report['reporting_period']['total_cost'] is not None else 0, 2)) has_reporting_period_data_flag = True if 'reporting_period' not in report.keys() \ or report['reporting_period'] is None: has_reporting_period_data_flag = False if has_reporting_period_data_flag: ws.row_dimensions[53].height = 25.0 for i in range(ord('B'), ord('J')): ws[chr(i) + '53'].fill = table_fill ws[chr(i) + '53'].font = title_font ws[chr(i) + '53'].alignment = c_c_alignment ws[chr(i) + '53'].border = f_border ws['B53'] = '能耗分类' ws['C53'] = '结算期开始日期' ws['D53'] = '结算期结束日期' ws['E53'] = '数量' ws['F53'] = '单位' ws['G53'] = '金额' ws['H53'] = '税率' ws['I53'] = '税额' reporting_period_data = report['reporting_period'] names = reporting_period_data['names'] ca_len = len(names) if names is not None else 0 for i in range(54, 54 + ca_len): ws.row_dimensions[i].height = 20.0 for j in range(ord('B'), ord('J')): ws[chr(j) + str(i)].font = title_font ws[chr(j) + str(i)].alignment = c_c_alignment ws[chr(j) + str(i)].border = f_border if chr(j) == 'B': ws[chr(j) + str(i)] = reporting_period_data['names'][i - 54] elif chr(j) == 'C': ws[chr(j) + str(i)] = datetime.datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') elif chr(j) == 'D': ws[chr(j) + str(i)] = datetime.datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') elif chr(j) == 'E': ws[chr(j) + str(i)] = round(reporting_period_data['subtotals_input'][i - 54], 3) elif chr(j) == 'F': ws[chr(j) + str(i)] = reporting_period_data['units'][i - 54] elif chr(j) == 'G': ws[chr(j) + str(i)] = round(reporting_period_data['subtotals_cost'][i - 54], 2) elif chr(j) == 'H': # Simulated data ws[chr(j) + str(i)] = 0 elif chr(j) == 'I': # Simulated data ws[chr(j) + str(i)] = 0 ws.row_dimensions[54 + ca_len].height = 10.0 ws.merge_cells('B{}:H{}'.format((54 + ca_len), (54 + ca_len))) current_row_number = 54 + ca_len + 1 for i in range(current_row_number, current_row_number + 3): ws.row_dimensions[i].height = 20.0 ws['B' + str(i)].alignment = b_r_alignment ws['B' + str(i)].font = name_font ws['H' + str(i)].alignment = b_l_alignment ws['H' + str(i)].font = name_font ws.merge_cells('B{}:G{}'.format(i, i)) ws.merge_cells('H{}:I{}'.format(i, i)) ws['B' + str(current_row_number)] = '小计:' ws['H' + str(current_row_number)] = report['reporting_period']['currency_unit'] + str( round(report['reporting_period']['total_cost'] if 'reporting_period' in report.keys() and 'total_cost' in report['reporting_period'].keys() and report['reporting_period']['total_cost'] is not None else 0, 2)) current_row_number += 1 # Simulated data taxes = Decimal(0.00) ws['B' + str(current_row_number)] = '增值税销项税金:' ws['H' + str(current_row_number)] = report['reporting_period']['currency_unit'] + str(round(taxes, 2)) current_row_number += 1 ws['B' + str(current_row_number)] = '应付金额合计:' ws['H' + str(current_row_number)] = report['reporting_period']['currency_unit'] + str( round(report['reporting_period']['total_cost'] + taxes if 'reporting_period' in report.keys() and 'total_cost' in report['reporting_period'].keys() and report['reporting_period']['total_cost'] is not None else 0 + taxes, 2)) filename = str(uuid.uuid4()) + '.xlsx' wb.save(filename) return filename