From 02f3aec483b4c192fa996712282649311bd316bd Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Tue, 2 Mar 2021 13:46:22 +0800 Subject: [PATCH 01/26] added shopfloorcost exporper --- myems-api/excelexporters/shopfloorcost.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 myems-api/excelexporters/shopfloorcost.py diff --git a/myems-api/excelexporters/shopfloorcost.py b/myems-api/excelexporters/shopfloorcost.py new file mode 100644 index 00000000..588048a1 --- /dev/null +++ b/myems-api/excelexporters/shopfloorcost.py @@ -0,0 +1,12 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + BarChart, + Reference, + ) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList From 28ae913f03e0dd003983cae84f7dbcc79ab9a58d Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Tue, 2 Mar 2021 13:55:21 +0800 Subject: [PATCH 02/26] added shopfloorcost exporper --- myems-api/excelexporters/shopfloorcost.py | 152 ++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/myems-api/excelexporters/shopfloorcost.py b/myems-api/excelexporters/shopfloorcost.py index 588048a1..3b88f2d2 100644 --- a/myems-api/excelexporters/shopfloorcost.py +++ b/myems-api/excelexporters/shopfloorcost.py @@ -10,3 +10,155 @@ from openpyxl.styles import PatternFill, Border, Side, Alignment, Font from openpyxl.drawing.image import Image from openpyxl import Workbook from openpyxl.chart.label import DataLabelList + + +#################################################################################################################### +# 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # for i in range(2, 37 + 1): + # ws.row_dimensions[i].height = 30 + # + # for i in range(38, 69 + 1): + # ws.row_dimensions[i].height = 30 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") From c493c797ad013349e68f27000a28db2b148c6e46 Mon Sep 17 00:00:00 2001 From: Caozhenhui <823914102@qq.com> Date: Tue, 2 Mar 2021 20:25:48 +0800 Subject: [PATCH 03/26] 2021/3/2 --- myems-api/excelexporters/shopfloorload.py | 444 ++++++++++++++++++++++ myems-api/reports/shopfloorload.py | 8 +- 2 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 myems-api/excelexporters/shopfloorload.py diff --git a/myems-api/excelexporters/shopfloorload.py b/myems-api/excelexporters/shopfloorload.py new file mode 100644 index 00000000..33701bb8 --- /dev/null +++ b/myems-api/excelexporters/shopfloorload.py @@ -0,0 +1,444 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + LineChart, + Reference, +) +from openpyxl.chart.label import DataLabelList +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +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 + + + #################################################################################################################### + # 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=False, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + 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) + # c_r_alignment = Alignment(vertical='bottom', + # horizontal='center', + # text_rotation=0, + # wrap_text=False, + # shrink_to_fit=False, + # indent=0) + + # Img + img = Image("excelexporters/myems.png") + # img = Image("myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + ws.add_image(img, 'B1') + + # Title + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + ################################################# + # First: 统计分析 + # 6: title + # 7: table title + # 8~ca_len table_data + ################################################# + reporting_period_data = report['reporting_period'] + + has_energy_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_energy_data_flag = False + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + if has_energy_data_flag: + ws['B6'].font = title_font + ws['B6'] = name + ' 统计分析' + + category = reporting_period_data['names'] + + # table_title + ws['B7'].fill = table_fill + ws['B7'].font = title_font + ws['B7'].alignment = c_c_alignment + ws['B7'] = '报告期' + ws['B7'].border = f_border + + ws['C7'].font = title_font + ws['C7'].alignment = c_c_alignment + ws['C7'] = '平均负荷' + ws['C7'].border = f_border + + ws['D7'].font = title_font + ws['D7'].alignment = c_c_alignment + ws['D7'] = '最大负荷' + ws['D7'].border = f_border + + ws['E7'].font = title_font + ws['E7'].alignment = c_c_alignment + ws['E7'] = '负荷系数' + ws['E7'].border = f_border + + # table_data + + for i, value in enumerate(category): + row = i*2 + 8 + ws['B' + str(row)].font = name_font + ws['B' + str(row)].alignment = c_c_alignment + ws['B' + str(row)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + "/H )" + ws['B' + str(row)].border = f_border + + ws['B' + str(row + 1)].font = name_font + ws['B' + str(row + 1)].alignment = c_c_alignment + ws['B' + str(row + 1)] = "环比" + ws['B' + str(row + 1)].border = f_border + + ws['C' + str(row)].font = name_font + ws['C' + str(row)].alignment = c_c_alignment + ws['C' + str(row)] = round(reporting_period_data['averages'][i], 2) \ + if reporting_period_data['averages'][i] is not None else '' + ws['C' + str(row)].border = f_border + ws['C' + str(row)].number_format = '0.00' + + ws['C' + str(row + 1)].font = name_font + ws['C' + str(row + 1)].alignment = c_c_alignment + ws['C' + str(row + 1)] = str(round(reporting_period_data['averages_increment_rate'][i] * 100, 2)) + "%" \ + if reporting_period_data['averages_increment_rate'][i] is not None else '0.00%' + ws['C' + str(row + 1)].border = f_border + + ws['D' + str(row)].font = name_font + ws['D' + str(row)].alignment = c_c_alignment + ws['D' + str(row)] = round(reporting_period_data['maximums'][i], 2) \ + if reporting_period_data['maximums'][i] is not None else '' + ws['D' + str(row)].border = f_border + ws['D' + str(row)].number_format = '0.00' + + ws['D' + str(row + 1)].font = name_font + ws['D' + str(row + 1)].alignment = c_c_alignment + ws['D' + str(row + 1)] = str(round(reporting_period_data['maximums_increment_rate'][i] * 100, 2)) + "%" \ + if reporting_period_data['maximums_increment_rate'][i] is not None else '0.00%' + ws['D' + str(row + 1)].border = f_border + + ws['E' + str(row)].font = name_font + ws['E' + str(row)].alignment = c_c_alignment + ws['E' + str(row)] = round(reporting_period_data['factors'][i], 2) \ + if reporting_period_data['factors'][i] is not None else '' + ws['E' + str(row)].border = f_border + ws['E' + str(row)].number_format = '0.00' + + ws['E' + str(row + 1)].font = name_font + ws['E' + str(row + 1)].alignment = c_c_alignment + ws['E' + str(row + 1)] = str(round(reporting_period_data['factors_increment_rate'][i] * 100, 2)) + "%" \ + if reporting_period_data['factors_increment_rate'][i] is not None else '0.00%' + ws['E' + str(row + 1)].border = f_border + + ################################################# + # Second: 报告期单位面积消耗 + # 9 + ca_len * 2: title + # 10 + ca_len * 2: table title + # row_title + 2 ~ row_title + 2 + ca_len : table_data + ################################################# + + if has_energy_data_flag: + names = reporting_period_data['names'] + ca_len = len(names) + row_title = 9 + ca_len * 2 + + for i in range(row_title + 2, row_title + 2 + ca_len): + ws.row_dimensions[i].height = 62 + + ws['B' + str(row_title)].font = title_font + ws['B' + str(row_title)] = name + ' 单位面积值' + ws['D' + str(row_title)].font = title_font + ws['D' + str(row_title)] = str(report['shopfloor']['area']) + 'M²' + + category = reporting_period_data['names'] + + # table_title + ws['B' + str(row_title + 1)].fill = table_fill + ws['B' + str(row_title + 1)].font = title_font + ws['B' + str(row_title + 1)].alignment = c_c_alignment + ws['B' + str(row_title + 1)] = '报告期' + ws['B' + str(row_title + 1)].border = f_border + + ws['C' + str(row_title + 1)].font = title_font + ws['C' + str(row_title + 1)].alignment = c_c_alignment + ws['C' + str(row_title + 1)] = '平均负荷' + ws['C' + str(row_title + 1)].border = f_border + + ws['D' + str(row_title + 1)].font = title_font + ws['D' + str(row_title + 1)].alignment = c_c_alignment + ws['D' + str(row_title + 1)] = '最大负荷' + ws['D' + str(row_title + 1)].border = f_border + + ws['E' + str(row_title + 1)].font = title_font + ws['E' + str(row_title + 1)].alignment = c_c_alignment + ws['E' + str(row_title + 1)] = '负荷系数' + ws['E' + str(row_title + 1)].border = f_border + + # table_data + + for i, value in enumerate(category): + row_data = row_title + 2 + i + ws['B' + str(row_data)].font = name_font + ws['B' + str(row_data)].alignment = c_c_alignment + ws['B' + str(row_data)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][ + i] + "/H/M²)" + ws['B' + str(row_data)].border = f_border + + ws['C' + str(row_data)].font = name_font + ws['C' + str(row_data)].alignment = c_c_alignment + if reporting_period_data['averages_per_unit_area'][i] \ + or reporting_period_data['averages_per_unit_area'][i] == 0: + ws['C' + str(row_data)] = round(reporting_period_data['averages_per_unit_area'][i], 2) + ws['C' + str(row_data)].border = f_border + ws['C' + str(row_data)].number_format = '0.00' + + ws['D' + str(row_data)].font = name_font + ws['D' + str(row_data)].alignment = c_c_alignment + if reporting_period_data['maximums_per_unit_area'][i] \ + or reporting_period_data['maximums_per_unit_area'][i] == 0: + ws['D' + str(row_data)] = round(reporting_period_data['maximums_per_unit_area'][i], 2) + ws['D' + str(row_data)].border = f_border + ws['D' + str(row_data)].number_format = '0.00' + + ws['E' + str(row_data)].font = name_font + ws['E' + str(row_data)].alignment = c_c_alignment + ws['E' + str(row_data)] = "平均负荷与最大负荷的比值" + ws['E' + str(row_data)].border = f_border + + ######################################################## + # Third: 详细数据 + # row_sat+row_title~ row_sat+row_title+time_len: line + # row_sat+1+row_title: table title + # i + row_sat + 2 + 6 * ca_len~: table_data + ######################################################## + has_timestamps_flag = True + if "timestamps" not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0: + has_timestamps_flag = False + + if has_timestamps_flag: + timestamps = reporting_period_data['timestamps'][0] + names = reporting_period_data['names'] + ca_len = len(names) + time_len = len(timestamps) + # title + row_title = 6 * ca_len + # row_st == row_statistical analysis table + row_sat = 12 + 3 * ca_len + + ws['B' + str(row_sat+row_title)].font = title_font + ws['B' + str(row_sat+row_title)] = name + ' 详细数据' + # table_title + ws['B' + str(row_sat+1+row_title)].fill = table_fill + ws['B' + str(row_sat+1+row_title)].font = name_font + ws['B' + str(row_sat+1+row_title)].alignment = c_c_alignment + ws['B' + str(row_sat+1+row_title)] = "日期时间" + ws['B' + str(row_sat+1+row_title)].border = f_border + + for i in range(0, ca_len): + col_average = chr(ord('C') + i) + col_maximum = chr(ord('C') + i + ca_len) + + ws[col_average + str(row_sat + 1 + row_title)].font = name_font + ws[col_average + str(row_sat + 1 + row_title)].alignment = c_c_alignment + ws[col_average + str(row_sat + 1 + row_title)] = names[i] + " 平均负荷(" + reporting_period_data['units'][ + i] + "/H)" + ws[col_average + str(row_sat + 1 + row_title)].border = f_border + + ws[col_maximum + str(row_sat + 1 + row_title)].font = name_font + ws[col_maximum + str(row_sat + 1 + row_title)].alignment = c_c_alignment + ws[col_maximum + str(row_sat + 1 + row_title)] = names[i] + " 最大负荷(" + reporting_period_data['units'][ + i] + "/H)" + ws[col_maximum + str(row_sat + 1 + row_title)].border = f_border + # table_date + for i in range(0, time_len): + rows = i + row_sat + 2 + 6 * ca_len + + ws['B' + str(rows)].font = name_font + ws['B' + str(rows)].alignment = c_c_alignment + ws['B' + str(rows)] = timestamps[i] + ws['B' + str(rows)].border = f_border + + for index in range(0, ca_len): + + col_average = chr(ord('C') + index * 2) + col_maximum = chr(ord('C') + index * 2 + 1) + + ws[col_average + str(rows)].font = name_font + ws[col_average + str(rows)].alignment = c_c_alignment + ws[col_average + str(rows)] = reporting_period_data['sub_averages'][index][i] \ + if reporting_period_data['sub_maximums'][index] is not None else '' + ws[col_average + str(rows)].number_format = '0.00' + ws[col_average + str(rows)].border = f_border + + ws[col_maximum + str(rows)].font = name_font + ws[col_maximum + str(rows)].alignment = c_c_alignment + ws[col_maximum + str(rows)] = reporting_period_data['sub_maximums'][index][i] \ + if reporting_period_data['sub_maximums'][index] is not None else '' + ws[col_maximum + str(rows)].number_format = '0.00' + ws[col_maximum + str(rows)].border = f_border + + # LineChart + for i in range(0, ca_len): + + lc = LineChart() + lc.title = "报告期 最大负荷" + lc.style = 10 + lc.x_axis.majorTickMark = 'in' + lc.y_axis.majorTickMark = 'in' + lc.smooth = True + lc.x_axis.crosses = 'min' + lc.height = 8.25 + lc.width = 24 + lc.dLbls = DataLabelList() + lc.dLbls.dLblPos = 't' + lc.dLbls.showVal = True + times = Reference(ws, min_col=2, min_row=row_sat + 2 + row_title, + max_row=row_sat + 2 + row_title + time_len) + lc_data = Reference(ws, min_col=3 + ca_len, min_row=row_sat + 1 + row_title, + max_row=row_sat + 1 + row_title + time_len) + lc.add_data(lc_data, titles_from_data=True) + lc.set_categories(times) + ser = lc.series[0] + ser.marker.symbol = "diamond" + ser.marker.size = 5 + chart_col = 'B' + chart_cell = str(row_sat + 6 * i) + ws.add_chart(lc, chart_col + chart_cell) + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename diff --git a/myems-api/reports/shopfloorload.py b/myems-api/reports/shopfloorload.py index 4735eb86..d6663559 100644 --- a/myems-api/reports/shopfloorload.py +++ b/myems-api/reports/shopfloorload.py @@ -5,7 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal - +import excelexporters.shopfloorload class Reporting: @staticmethod @@ -546,4 +546,10 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.shopfloorload.export(result, + shopfloor['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) resp.body = json.dumps(result) From 0d6c14b999abf4a04db4541abb5f320ef5de2014 Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Wed, 3 Mar 2021 11:47:26 +0800 Subject: [PATCH 04/26] Added 'excelexporters.combinedequipmentenergyitem.export()' method --- myems-api/reports/combinedequipmentenergyitem.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/myems-api/reports/combinedequipmentenergyitem.py b/myems-api/reports/combinedequipmentenergyitem.py index bccdf7c0..5e25004a 100644 --- a/myems-api/reports/combinedequipmentenergyitem.py +++ b/myems-api/reports/combinedequipmentenergyitem.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.combinedequipmentenergyitem class Reporting: @@ -516,4 +517,11 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.combinedequipmentenergyitem.export(result, + combined_equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) From f0589cbb97c07f6028a5e30e8c4136d1a1d4d05a Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Wed, 3 Mar 2021 11:48:07 +0800 Subject: [PATCH 05/26] Implemented the CombinedEquipmentEnergyItem Excel Exporter --- .../combinedequipmentenergyitem.py | 464 ++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 myems-api/excelexporters/combinedequipmentenergyitem.py diff --git a/myems-api/excelexporters/combinedequipmentenergyitem.py b/myems-api/excelexporters/combinedequipmentenergyitem.py new file mode 100644 index 00000000..83d50974 --- /dev/null +++ b/myems-api/excelexporters/combinedequipmentenergyitem.py @@ -0,0 +1,464 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, +) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList + + +#################################################################################################################### +# 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################## + + current_row_number = 6 + + reporting_period_data = report['reporting_period'] + + has_names_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_names_data_flag = False + + if has_names_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期消耗' + + current_row_number += 1 + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " " + reporting_period_data['energy_category_names'][i] + \ + " (" + reporting_period_data['units'][i] + ")" + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '消耗' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + # ws['B' + str(current_row_number)].font = title_font + # ws['B' + str(current_row_number)].alignment = c_c_alignment + # ws['B' + str(current_row_number)].border = f_border + # ws['B' + str(current_row_number)] = '单位面积值' + # + # col = 'C' + # + # for i in range(0, ca_len): + # ws[col + str(current_row_number)].font = name_font + # ws[col + str(current_row_number)].alignment = c_c_alignment + # ws[col + str(current_row_number)].border = f_border + # ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_per_unit_area'][i], 2) + # + # col = chr(ord(col) + 1) + # + # current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '环比' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = str( + round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \ + if reporting_period_data['increment_rates'][i] is not None else '-' + + col = chr(ord(col) + 1) + + current_row_number += 2 + + category_dict = group_by_category(reporting_period_data['energy_category_names']) + + for category_dict_name, category_dict_values in category_dict.items(): + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = \ + name + ' ' + category_dict_name + ' (' + reporting_period_data['units'][category_dict_values[0]] + \ + ') 分项消耗占比' + + current_row_number += 1 + table_start_row_number = current_row_number + + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + ws['C' + str(current_row_number)].font = name_font + ws['C' + str(current_row_number)].fill = table_fill + ws['C' + str(current_row_number)].alignment = c_c_alignment + ws['C' + str(current_row_number)].border = f_border + ws['C' + str(current_row_number)] = '消耗' + + current_row_number += 1 + + for i in category_dict_values: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + ws['C' + str(current_row_number)].font = name_font + ws['C' + str(current_row_number)].alignment = c_c_alignment + ws['C' + str(current_row_number)].border = f_border + ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 3) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + pie = PieChart() + pie.title = \ + name + ' ' + category_dict_name + ' (' + reporting_period_data['units'][category_dict_values[0]] + \ + ') 分项消耗占比' + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 9 + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + ws.add_chart(pie, 'D' + str(table_start_row_number)) + + if len(category_dict_values) < 4: + current_row_number = current_row_number - len(category_dict_values) + 4 + + current_row_number += 1 + + ##################################### + + has_values_data = True + has_timestamps_data = True + + if 'values' not in reporting_period_data.keys() or \ + reporting_period_data['values'] is None or \ + len(reporting_period_data['values']) == 0: + has_values_data = False + + if 'timestamps' not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0 or \ + len(reporting_period_data['timestamps'][0]) == 0: + has_timestamps_data = False + + if has_values_data and has_timestamps_data: + ca_len = len(reporting_period_data['names']) + time = reporting_period_data['timestamps'][0] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 详细数据' + + current_row_number += 1 + + chart_start_row_number = current_row_number + + current_row_number += ca_len * 6 + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '日期时间' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + col = chr(ord(col) + 1) + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = time[i] + + col = 'C' + for j in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \ + if reporting_period_data['values'][j][i] is not None else 0.00 + col = chr(ord(col) + 1) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '小计' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + col = chr(ord(col) + 1) + + current_row_number += 2 + + format_time_width_number = 1.0 + min_len_number = 1.0 + min_width_number = 11.0 # format_time_width_number * min_len_number + 4 and min_width_number > 11.0 + + if period_type == 'hourly': + format_time_width_number = 4.0 + min_len_number = 2 + min_width_number = 12.0 + elif period_type == 'daily': + format_time_width_number = 2.5 + min_len_number = 4 + min_width_number = 14.0 + elif period_type == 'monthly': + format_time_width_number = 2.1 + min_len_number = 4 + min_width_number = 12.4 + elif period_type == 'yearly': + format_time_width_number = 1.5 + min_len_number = 5 + min_width_number = 11.5 + + for i in range(0, ca_len): + line = LineChart() + line.title = '报告期消耗 - ' + \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number + if line.width > 24: + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + +def group_by_category(category_list): + category_dict = dict() + for i, value in enumerate(category_list): + if value not in category_dict.keys(): + category_dict[value] = list() + category_dict[value].append(i) + return category_dict From 43a18a60464704f863181f378a894098934d494d Mon Sep 17 00:00:00 2001 From: "13621160019@163.com" <13621160019@163.com> Date: Wed, 3 Mar 2021 13:24:46 +0800 Subject: [PATCH 06/26] added excel exporter of combinedequipmentitem report --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae7fa1c4..d42ff0b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added +- added excel exporter of combinedequipmentitem report. - added excel exporter of equipmentenergyitem report. - added excel exporter of equipmentenergycategory report. - added excel exporter of shopfloorenergyitem report. From f1d95e30371b4ceef826ab5ad4f0b9f798d51682 Mon Sep 17 00:00:00 2001 From: "13621160019@163.com" <13621160019@163.com> Date: Wed, 3 Mar 2021 14:11:22 +0800 Subject: [PATCH 07/26] added excel exporter of combinedequipmentenergycategory report --- myems-api/reports/combinedequipmentenergycategory.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/myems-api/reports/combinedequipmentenergycategory.py b/myems-api/reports/combinedequipmentenergycategory.py index 82d7170d..91a62864 100644 --- a/myems-api/reports/combinedequipmentenergycategory.py +++ b/myems-api/reports/combinedequipmentenergycategory.py @@ -551,9 +551,10 @@ class Reporting: "values": parameters_data['values'] } - result['excel_bytes_base64'] = excelexporters.combinedequipmentenergycategory.export(result, - combined_equipment['name'], - reporting_start_datetime_local, - reporting_end_datetime_local, - period_type) + result['excel_bytes_base64'] = \ + excelexporters.combinedequipmentenergycategory.export(result, + combined_equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) resp.body = json.dumps(result) From 25a96729aeee1d812b683bc5d6daf316649d7908 Mon Sep 17 00:00:00 2001 From: Caozhenhui <823914102@qq.com> Date: Wed, 3 Mar 2021 16:04:49 +0800 Subject: [PATCH 08/26] 2021/3/3 --- myems-api/excelexporters/shopfloorload.py | 23 +++++++-------- myems-api/reports/shopfloorload.py | 35 ++++++++++++----------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/myems-api/excelexporters/shopfloorload.py b/myems-api/excelexporters/shopfloorload.py index 33701bb8..3c71925a 100644 --- a/myems-api/excelexporters/shopfloorload.py +++ b/myems-api/excelexporters/shopfloorload.py @@ -30,7 +30,6 @@ def export(report, if report is None: return None - #################################################################################################################### # Step 2: Generate excel file from the report data #################################################################################################################### @@ -211,7 +210,7 @@ def generate_excel(report, # table_data for i, value in enumerate(category): - row = i*2 + 8 + row = i * 2 + 8 ws['B' + str(row)].font = name_font ws['B' + str(row)].alignment = c_c_alignment ws['B' + str(row)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + "/H )" @@ -358,14 +357,14 @@ def generate_excel(report, # row_st == row_statistical analysis table row_sat = 12 + 3 * ca_len - ws['B' + str(row_sat+row_title)].font = title_font - ws['B' + str(row_sat+row_title)] = name + ' 详细数据' + ws['B' + str(row_sat + row_title)].font = title_font + ws['B' + str(row_sat + row_title)] = name + ' 详细数据' # table_title - ws['B' + str(row_sat+1+row_title)].fill = table_fill - ws['B' + str(row_sat+1+row_title)].font = name_font - ws['B' + str(row_sat+1+row_title)].alignment = c_c_alignment - ws['B' + str(row_sat+1+row_title)] = "日期时间" - ws['B' + str(row_sat+1+row_title)].border = f_border + ws['B' + str(row_sat + 1 + row_title)].fill = table_fill + ws['B' + str(row_sat + 1 + row_title)].font = name_font + ws['B' + str(row_sat + 1 + row_title)].alignment = c_c_alignment + ws['B' + str(row_sat + 1 + row_title)] = "日期时间" + ws['B' + str(row_sat + 1 + row_title)].border = f_border for i in range(0, ca_len): col_average = chr(ord('C') + i) @@ -392,27 +391,25 @@ def generate_excel(report, ws['B' + str(rows)].border = f_border for index in range(0, ca_len): - col_average = chr(ord('C') + index * 2) col_maximum = chr(ord('C') + index * 2 + 1) ws[col_average + str(rows)].font = name_font ws[col_average + str(rows)].alignment = c_c_alignment ws[col_average + str(rows)] = reporting_period_data['sub_averages'][index][i] \ - if reporting_period_data['sub_maximums'][index] is not None else '' + if reporting_period_data['sub_maximums'][index] is not None else '' ws[col_average + str(rows)].number_format = '0.00' ws[col_average + str(rows)].border = f_border ws[col_maximum + str(rows)].font = name_font ws[col_maximum + str(rows)].alignment = c_c_alignment ws[col_maximum + str(rows)] = reporting_period_data['sub_maximums'][index][i] \ - if reporting_period_data['sub_maximums'][index] is not None else '' + if reporting_period_data['sub_maximums'][index] is not None else '' ws[col_maximum + str(rows)].number_format = '0.00' ws[col_maximum + str(rows)].border = f_border # LineChart for i in range(0, ca_len): - lc = LineChart() lc.title = "报告期 最大负荷" lc.style = 10 diff --git a/myems-api/reports/shopfloorload.py b/myems-api/reports/shopfloorload.py index d6663559..fa67ee6a 100644 --- a/myems-api/reports/shopfloorload.py +++ b/myems-api/reports/shopfloorload.py @@ -7,6 +7,7 @@ from core import utilities from decimal import Decimal import excelexporters.shopfloorload + class Reporting: @staticmethod def __init__(): @@ -66,7 +67,7 @@ class Reporting: try: base_start_datetime_utc = datetime.strptime(base_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_START_DATETIME") @@ -77,7 +78,7 @@ class Reporting: try: base_end_datetime_utc = datetime.strptime(base_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_END_DATETIME") @@ -95,7 +96,7 @@ class Reporting: try: reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_START_DATETIME") @@ -108,7 +109,7 @@ class Reporting: try: reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_END_DATETIME") @@ -278,10 +279,10 @@ class Reporting: period_type) base[energy_category_id]['factor'] = \ (base[energy_category_id]['average'] / base[energy_category_id]['maximum'] - if (base[energy_category_id]['average'] is not None and - base[energy_category_id]['maximum'] is not None and - base[energy_category_id]['maximum'] > Decimal(0.0)) - else None) + if (base[energy_category_id]['average'] is not None and + base[energy_category_id]['maximum'] is not None and + base[energy_category_id]['maximum'] > Decimal(0.0)) + else None) for row_shopfloor_periodically in rows_shopfloor_periodically: current_datetime_local = row_shopfloor_periodically[0].replace(tzinfo=timezone.utc) + \ @@ -511,11 +512,11 @@ class Reporting: result['reporting_period']['sub_maximums'].append(reporting[energy_category_id]['sub_maximums']) result['reporting_period']['averages'].append(reporting[energy_category_id]['average']) result['reporting_period']['averages_per_unit_area'].append( - reporting[energy_category_id]['average'] / shopfloor['area'] - if reporting[energy_category_id]['average'] is not None and - shopfloor['area'] is not None and - shopfloor['area'] > Decimal(0.0) - else None) + reporting[energy_category_id]['average'] / shopfloor['area'] + if reporting[energy_category_id]['average'] is not None and + shopfloor['area'] is not None and + shopfloor['area'] > Decimal(0.0) + else None) result['reporting_period']['averages_increment_rate'].append( (reporting[energy_category_id]['average'] - base[energy_category_id]['average']) / base[energy_category_id]['average'] if (base[energy_category_id]['average'] is not None and @@ -548,8 +549,8 @@ class Reporting: # export result to Excel file and then encode the file to base64 string result['excel_bytes_base64'] = excelexporters.shopfloorload.export(result, - shopfloor['name'], - reporting_start_datetime_local, - reporting_end_datetime_local, - period_type) + shopfloor['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) resp.body = json.dumps(result) From 8bebedf6f1bdf5d6188c572aec3bd8b448f1684a Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Wed, 3 Mar 2021 16:38:12 +0800 Subject: [PATCH 09/26] added shopfloorcost master --- myems-api/excelexporters/shopfloorcost.py | 400 +++++++++++++++++++++- myems-api/reports/shopfloorcost.py | 8 +- 2 files changed, 404 insertions(+), 4 deletions(-) diff --git a/myems-api/excelexporters/shopfloorcost.py b/myems-api/excelexporters/shopfloorcost.py index 3b88f2d2..aadf8544 100644 --- a/myems-api/excelexporters/shopfloorcost.py +++ b/myems-api/excelexporters/shopfloorcost.py @@ -3,6 +3,7 @@ import uuid import os from openpyxl.chart import ( PieChart, + LineChart, BarChart, Reference, ) @@ -11,7 +12,6 @@ from openpyxl.drawing.image import Image from openpyxl import Workbook from openpyxl.chart.label import DataLabelList - #################################################################################################################### # PROCEDURES # Step 1: Validate the report data @@ -66,6 +66,7 @@ def generate_excel(report, reporting_start_datetime_local, reporting_end_datetime_local, period_type): + wb = Workbook() ws = wb.active @@ -77,7 +78,7 @@ def generate_excel(report, # for i in range(2, 37 + 1): # ws.row_dimensions[i].height = 30 # - # for i in range(38, 69 + 1): + # for i in range(38, 90 + 1): # ws.row_dimensions[i].height = 30 # Col width @@ -157,8 +158,401 @@ def generate_excel(report, ws['F3'].font = name_font ws['F3'].alignment = b_r_alignment ws['F3'] = 'Date:' - ws['G3'].border = b_border ws['G3'].alignment = b_c_alignment ws['G3'].font = name_font ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################################# + + reporting_period_data = report['reporting_period'] + + has_energy_data_flag = True + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_energy_data_flag = False + + if has_energy_data_flag: + ws['B6'].font = title_font + ws['B6'] = name+' 报告期成本' + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[7].height = 60 + ws['B7'].fill = table_fill + ws['B7'].border = f_border + + ws['B8'].font = title_font + ws['B8'].alignment = c_c_alignment + ws['B8'] = '成本' + ws['B8'].border = f_border + + ws['B9'].font = title_font + ws['B9'].alignment = c_c_alignment + ws['B9'] = '单位面积能耗' + ws['B9'].border = f_border + + ws['B10'].font = title_font + ws['B10'].alignment = c_c_alignment + ws['B10'] = '环比' + ws['B10'].border = f_border + + col = 'B' + + for i in range(0, ca_len): + col = chr(ord('C') + i) + ws[col + '7'].fill = table_fill + ws[col + '7'].font = name_font + ws[col + '7'].alignment = c_c_alignment + ws[col + '7'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + ws[col + '7'].border = f_border + + ws[col + '8'].font = name_font + ws[col + '8'].alignment = c_c_alignment + ws[col + '8'] = round(reporting_period_data['subtotals'][i], 2) + ws[col + '8'].border = f_border + + ws[col + '9'].font = name_font + ws[col + '9'].alignment = c_c_alignment + ws[col + '9'] = round(reporting_period_data['subtotals_per_unit_area'][i], 2) + ws[col + '9'].border = f_border + + ws[col + '10'].font = name_font + ws[col + '10'].alignment = c_c_alignment + ws[col + '10'] = str(round(reporting_period_data['increment_rates'][i] * 100, 2)) + "%" \ + if reporting_period_data['increment_rates'][i] is not None else "-" + ws[col + '10'].border = f_border + + end_col = chr(ord(col)+1) + ws[end_col + '7'].fill = table_fill + ws[end_col + '7'].font = name_font + ws[end_col + '7'].alignment = c_c_alignment + ws[end_col + '7'] = "总计 (" + reporting_period_data['total_unit'] + ")" + ws[end_col + '7'].border = f_border + + ws[end_col + '8'].font = name_font + ws[end_col + '8'].alignment = c_c_alignment + ws[end_col + '8'] = round(reporting_period_data['total'], 2) + ws[end_col + '8'].border = f_border + + ws[end_col + '9'].font = name_font + ws[end_col + '9'].alignment = c_c_alignment + ws[end_col + '9'] = round(reporting_period_data['total_per_unit_area'], 2) + ws[end_col + '9'].border = f_border + + ws[end_col + '10'].font = name_font + ws[end_col + '10'].alignment = c_c_alignment + ws[end_col + '10'] = str(round(reporting_period_data['total_increment_rate'] * 100, 2)) + "%" \ + if reporting_period_data['total_increment_rate'] is not None else "-" + ws[end_col + '10'].border = f_border + + else: + for i in range(6, 10 + 1): + ws.row_dimensions[i].height = 0.1 + + ################################################# + + has_ele_peak_flag = True + if "toppeaks" not in reporting_period_data.keys() or \ + reporting_period_data['toppeaks'] is None or \ + len(reporting_period_data['toppeaks']) == 0: + has_ele_peak_flag = False + + if has_ele_peak_flag: + ws['B12'].font = title_font + ws['B12'] = name+' 分时电耗' + + ws['B13'].fill = table_fill + ws['B13'].font = name_font + ws['B13'].alignment = c_c_alignment + ws['B13'].border = f_border + + ws['C13'].fill = table_fill + ws['C13'].font = name_font + ws['C13'].alignment = c_c_alignment + ws['C13'].border = f_border + ws['C13'] = '分时电耗' + + ws['B14'].font = title_font + ws['B14'].alignment = c_c_alignment + ws['B14'] = '尖' + ws['B14'].border = f_border + + ws['C14'].font = title_font + ws['C14'].alignment = c_c_alignment + ws['C14'].border = f_border + ws['C14'] = round(reporting_period_data['toppeaks'][0], 2) + + ws['B15'].font = title_font + ws['B15'].alignment = c_c_alignment + ws['B15'] = '峰' + ws['B15'].border = f_border + + ws['C15'].font = title_font + ws['C15'].alignment = c_c_alignment + ws['C15'].border = f_border + ws['C15'] = round(reporting_period_data['onpeaks'][0], 2) + + ws['B16'].font = title_font + ws['B16'].alignment = c_c_alignment + ws['B16'] = '平' + ws['B16'].border = f_border + + ws['C16'].font = title_font + ws['C16'].alignment = c_c_alignment + ws['C16'].border = f_border + ws['C16'] = round(reporting_period_data['midpeaks'][0], 2) + + ws['B17'].font = title_font + ws['B17'].alignment = c_c_alignment + ws['B17'] = '谷' + ws['B17'].border = f_border + + ws['C17'].font = title_font + ws['C17'].alignment = c_c_alignment + ws['C17'].border = f_border + ws['C17'] = round(reporting_period_data['offpeaks'][0], 2) + + pie = PieChart() + pie.title = name+' 分时电耗' + labels = Reference(ws, min_col=2, min_row=14, max_row=17) + pie_data = Reference(ws, min_col=3, min_row=13, max_row=17) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 9 + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + ws.add_chart(pie, "D13") + + else: + for i in range(12, 18 + 1): + ws.row_dimensions[i].height = 0.1 + + ################################################ + + current_row_number = 19 + + has_subtotals_data_flag = True + if "subtotals" not in reporting_period_data.keys() or \ + reporting_period_data['subtotals'] is None or \ + len(reporting_period_data['subtotals']) == 0: + has_subtotals_data_flag = False + + if has_subtotals_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 成本占比' + + current_row_number += 1 + + table_start_row_number = current_row_number + + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = name_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + + ws['C' + str(current_row_number)].fill = table_fill + ws['C' + str(current_row_number)].font = name_font + ws['C' + str(current_row_number)].alignment = c_c_alignment + ws['C' + str(current_row_number)].border = f_border + ws['C' + str(current_row_number)] = '成本占比' + + current_row_number += 1 + + ca_len = len(reporting_period_data['names']) + + for i in range(0, ca_len): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = reporting_period_data['names'][i] + ws['B' + str(current_row_number)].border = f_border + + ws['C' + str(current_row_number)].font = title_font + ws['C' + str(current_row_number)].alignment = c_c_alignment + ws['C' + str(current_row_number)].border = f_border + ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + pie = PieChart() + pie.title = name + ' 成本占比' + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 9 + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + table_cell = 'D' + str(table_start_row_number) + ws.add_chart(pie, table_cell) + + if ca_len < 4: + current_row_number = current_row_number - ca_len + 4 + + else: + for i in range(21, 29 + 1): + current_row_number = 30 + ws.row_dimensions[i].height = 0.1 + + ############################################### + + current_row_number += 1 + + has_detail_data_flag = True + + table_start_draw_flag = current_row_number + 1 + + if "timestamps" not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0: + has_detail_data_flag = False + + if has_detail_data_flag: + reporting_period_data = report['reporting_period'] + times = reporting_period_data['timestamps'] + ca_len = len(report['reporting_period']['names']) + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name+' 详细数据' + + table_start_row_number = (current_row_number + 1) + ca_len * 6 + current_row_number = table_start_row_number + + time = times[0] + has_data = False + + if len(time) > 0: + has_data = True + + if has_data: + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = '日期时间' + + col = 'B' + + for i in range(0, ca_len): + col = chr(ord('C') + i) + + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \ + " (" + reporting_period_data['units'][i] + ")" + ws[col + str(current_row_number)].border = f_border + + end_col = chr(ord(col) + 1) + + ws[end_col + str(current_row_number)].fill = table_fill + ws[end_col + str(current_row_number)].font = title_font + ws[end_col + str(current_row_number)].alignment = c_c_alignment + ws[end_col + str(current_row_number)] = "总计 (" + reporting_period_data['total_unit'] + ")" + ws[end_col + str(current_row_number)].border = f_border + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = time[i] + ws['B' + str(current_row_number)].border = f_border + + col = 'B' + + every_day_total = 0 + + for j in range(0, ca_len): + col = chr(ord('C') + j) + + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + value = round(reporting_period_data['values'][j][i], 2) + every_day_total += value + ws[col + str(current_row_number)] = value + ws[col + str(current_row_number)].border = f_border + + end_col = chr(ord(col) + 1) + ws[end_col + str(current_row_number)].font = title_font + ws[end_col + str(current_row_number)].alignment = c_c_alignment + ws[end_col + str(current_row_number)] = round(every_day_total, 2) + ws[end_col + str(current_row_number)].border = f_border + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = '小计' + ws['B' + str(current_row_number)].border = f_border + + col = 'B' + + for i in range(0, ca_len): + col = chr(ord('C') + i) + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + ws[col + str(current_row_number)].border = f_border + + # line + line = LineChart() + line.title = '报告期成本 - ' + ws.cell(column=3+i, row=table_start_row_number).value + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(table_start_draw_flag + 6 * i) + ws.add_chart(line, chart_cell) + + end_col = chr(ord(col) + 1) + ws[end_col + str(current_row_number)].font = title_font + ws[end_col + str(current_row_number)].alignment = c_c_alignment + ws[end_col + str(current_row_number)] = round(reporting_period_data['total'], 2) + ws[end_col + str(current_row_number)].border = f_border + + current_row_number += 1 + + else: + for i in range(30, 69 + 1): + current_row_number = 70 + ws.row_dimensions[i].height = 0.1 + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename diff --git a/myems-api/reports/shopfloorcost.py b/myems-api/reports/shopfloorcost.py index ca169a6c..374ac1d1 100644 --- a/myems-api/reports/shopfloorcost.py +++ b/myems-api/reports/shopfloorcost.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.shopfloorcost class Reporting: @@ -529,5 +530,10 @@ class Reporting: "timestamps": parameters_data['timestamps'], "values": parameters_data['values'] } - + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.shopfloorcost.export(result, + shopfloor['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) resp.body = json.dumps(result) From 78f02914dc392dc44b46a519b306ba4b8634605e Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Thu, 4 Mar 2021 12:03:10 +0800 Subject: [PATCH 10/26] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- myems-api/excelexporters/shopfloorcost.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/myems-api/excelexporters/shopfloorcost.py b/myems-api/excelexporters/shopfloorcost.py index aadf8544..54bcc5b7 100644 --- a/myems-api/excelexporters/shopfloorcost.py +++ b/myems-api/excelexporters/shopfloorcost.py @@ -269,7 +269,8 @@ def generate_excel(report, if has_ele_peak_flag: ws['B12'].font = title_font - ws['B12'] = name+' 分时电耗' + ws['B12'] = name+'分时用电成本' + ws['B13'].fill = table_fill ws['B13'].font = name_font @@ -280,7 +281,7 @@ def generate_excel(report, ws['C13'].font = name_font ws['C13'].alignment = c_c_alignment ws['C13'].border = f_border - ws['C13'] = '分时电耗' + ws['C13'] = '分时用电成本' ws['B14'].font = title_font ws['B14'].alignment = c_c_alignment @@ -323,7 +324,7 @@ def generate_excel(report, ws['C17'] = round(reporting_period_data['offpeaks'][0], 2) pie = PieChart() - pie.title = name+' 分时电耗' + pie.title = name+'分时用电成本' labels = Reference(ws, min_col=2, min_row=14, max_row=17) pie_data = Reference(ws, min_col=3, min_row=13, max_row=17) pie.add_data(pie_data, titles_from_data=True) From 9134e88153aa428bd9dfe3f2ee5f319157ad4229 Mon Sep 17 00:00:00 2001 From: Caozhenhui <823914102@qq.com> Date: Thu, 4 Mar 2021 14:35:27 +0800 Subject: [PATCH 11/26] Remove the load factor per unit area[B --- myems-api/excelexporters/shopfloorload.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/myems-api/excelexporters/shopfloorload.py b/myems-api/excelexporters/shopfloorload.py index 3c71925a..1058b26e 100644 --- a/myems-api/excelexporters/shopfloorload.py +++ b/myems-api/excelexporters/shopfloorload.py @@ -299,11 +299,6 @@ def generate_excel(report, ws['D' + str(row_title + 1)] = '最大负荷' ws['D' + str(row_title + 1)].border = f_border - ws['E' + str(row_title + 1)].font = title_font - ws['E' + str(row_title + 1)].alignment = c_c_alignment - ws['E' + str(row_title + 1)] = '负荷系数' - ws['E' + str(row_title + 1)].border = f_border - # table_data for i, value in enumerate(category): @@ -330,11 +325,6 @@ def generate_excel(report, ws['D' + str(row_data)].border = f_border ws['D' + str(row_data)].number_format = '0.00' - ws['E' + str(row_data)].font = name_font - ws['E' + str(row_data)].alignment = c_c_alignment - ws['E' + str(row_data)] = "平均负荷与最大负荷的比值" - ws['E' + str(row_data)].border = f_border - ######################################################## # Third: 详细数据 # row_sat+row_title~ row_sat+row_title+time_len: line From 18a3e8e7d8fc75a23af9969ced011753d6148823 Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 14:53:50 +0800 Subject: [PATCH 12/26] Added 'excelexporters.equipmentoutput.export()' method --- myems-api/reports/equipmentoutput.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/myems-api/reports/equipmentoutput.py b/myems-api/reports/equipmentoutput.py index ace130c6..15e2f3bf 100644 --- a/myems-api/reports/equipmentoutput.py +++ b/myems-api/reports/equipmentoutput.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.equipmentoutput class Reporting: @@ -469,4 +470,11 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.equipmentoutput.export(result, + equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) From c9fad53977e4ef79ad054460c90717369654b022 Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 14:54:38 +0800 Subject: [PATCH 13/26] Implemented the EquipmentOutput Excel Exporter --- myems-api/excelexporters/equipmentoutput.py | 396 ++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 myems-api/excelexporters/equipmentoutput.py diff --git a/myems-api/excelexporters/equipmentoutput.py b/myems-api/excelexporters/equipmentoutput.py new file mode 100644 index 00000000..a384fcd5 --- /dev/null +++ b/myems-api/excelexporters/equipmentoutput.py @@ -0,0 +1,396 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, +) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList + + +#################################################################################################################### +# 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################## + + current_row_number = 6 + + reporting_period_data = report['reporting_period'] + + has_names_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_names_data_flag = False + + if has_names_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期产出' + + current_row_number += 1 + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '产出' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + # ws['B' + str(current_row_number)].font = title_font + # ws['B' + str(current_row_number)].alignment = c_c_alignment + # ws['B' + str(current_row_number)].border = f_border + # ws['B' + str(current_row_number)] = '单位面积值' + # + # col = 'C' + # + # for i in range(0, ca_len): + # ws[col + str(current_row_number)].font = name_font + # ws[col + str(current_row_number)].alignment = c_c_alignment + # ws[col + str(current_row_number)].border = f_border + # ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_per_unit_area'][i], 2) + # + # col = chr(ord(col) + 1) + # + # current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '环比' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = str( + round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \ + if reporting_period_data['increment_rates'][i] is not None else '-' + + col = chr(ord(col) + 1) + + current_row_number += 2 + + #################################### + + has_values_data = True + has_timestamps_data = True + + if 'values' not in reporting_period_data.keys() or \ + reporting_period_data['values'] is None or \ + len(reporting_period_data['values']) == 0: + has_values_data = False + + if 'timestamps' not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0 or \ + len(reporting_period_data['timestamps'][0]) == 0: + has_timestamps_data = False + + if has_values_data and has_timestamps_data: + ca_len = len(reporting_period_data['names']) + time = reporting_period_data['timestamps'][0] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 详细数据' + + current_row_number += 1 + + chart_start_row_number = current_row_number + + current_row_number += ca_len * 6 + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '日期时间' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + col = chr(ord(col) + 1) + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = time[i] + + col = 'C' + for j in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \ + if reporting_period_data['values'][j][i] is not None else 0.00 + col = chr(ord(col) + 1) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '小计' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + col = chr(ord(col) + 1) + + current_row_number += 2 + + format_time_width_number = 1.0 + min_len_number = 1.0 + min_width_number = 11.0 # format_time_width_number * min_len_number + 4 and min_width_number > 11.0 + + if period_type == 'hourly': + format_time_width_number = 4.0 + min_len_number = 2 + min_width_number = 12.0 + elif period_type == 'daily': + format_time_width_number = 2.5 + min_len_number = 4 + min_width_number = 14.0 + elif period_type == 'monthly': + format_time_width_number = 2.1 + min_len_number = 4 + min_width_number = 12.4 + elif period_type == 'yearly': + format_time_width_number = 1.5 + min_len_number = 5 + min_width_number = 11.5 + + for i in range(0, ca_len): + line = LineChart() + line.title = '报告期产出 - ' + \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number + if line.width > 24: + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + From 14bfb16cdae37c4e072a8b8dd8b7f28451bb5d44 Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Thu, 4 Mar 2021 15:55:01 +0800 Subject: [PATCH 14/26] Fix some errors and add data ratio --- myems-api/excelexporters/shopfloorcost.py | 53 ++++++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/myems-api/excelexporters/shopfloorcost.py b/myems-api/excelexporters/shopfloorcost.py index 54bcc5b7..300d75ee 100644 --- a/myems-api/excelexporters/shopfloorcost.py +++ b/myems-api/excelexporters/shopfloorcost.py @@ -198,7 +198,7 @@ def generate_excel(report, ws['B9'].font = title_font ws['B9'].alignment = c_c_alignment - ws['B9'] = '单位面积能耗' + ws['B9'] = '单位面积值' ws['B9'].border = f_border ws['B10'].font = title_font @@ -271,7 +271,6 @@ def generate_excel(report, ws['B12'].font = title_font ws['B12'] = name+'分时用电成本' - ws['B13'].fill = table_fill ws['B13'].font = name_font ws['B13'].alignment = c_c_alignment @@ -283,6 +282,15 @@ def generate_excel(report, ws['C13'].border = f_border ws['C13'] = '分时用电成本' + ws['D13'].fill = table_fill + ws['D13'].font = name_font + ws['D13'].alignment = c_c_alignment + ws['D13'].border = f_border + ws['D13'] = '分时用电成本比' + + wssum = round(reporting_period_data['toppeaks'][0], 2)+round(reporting_period_data['onpeaks'][0], 2)\ + + round(reporting_period_data['midpeaks'][0], 2)+round(reporting_period_data['offpeaks'][0], 2) + ws['B14'].font = title_font ws['B14'].alignment = c_c_alignment ws['B14'] = '尖' @@ -293,6 +301,11 @@ def generate_excel(report, ws['C14'].border = f_border ws['C14'] = round(reporting_period_data['toppeaks'][0], 2) + ws['D14'].font = title_font + ws['D14'].alignment = c_c_alignment + ws['D14'].border = f_border + ws['D14'] = '{:.2%}'.format(round(reporting_period_data['toppeaks'][0], 2)/wssum) + ws['B15'].font = title_font ws['B15'].alignment = c_c_alignment ws['B15'] = '峰' @@ -303,6 +316,11 @@ def generate_excel(report, ws['C15'].border = f_border ws['C15'] = round(reporting_period_data['onpeaks'][0], 2) + ws['D15'].font = title_font + ws['D15'].alignment = c_c_alignment + ws['D15'].border = f_border + ws['D15'] = '{:.2%}'.format(round(reporting_period_data['onpeaks'][0], 2)/wssum) + ws['B16'].font = title_font ws['B16'].alignment = c_c_alignment ws['B16'] = '平' @@ -313,6 +331,11 @@ def generate_excel(report, ws['C16'].border = f_border ws['C16'] = round(reporting_period_data['midpeaks'][0], 2) + ws['D16'].font = title_font + ws['D16'].alignment = c_c_alignment + ws['D16'].border = f_border + ws['D16'] = '{:.2%}'.format(round(reporting_period_data['midpeaks'][0], 2)/wssum) + ws['B17'].font = title_font ws['B17'].alignment = c_c_alignment ws['B17'] = '谷' @@ -323,6 +346,11 @@ def generate_excel(report, ws['C17'].border = f_border ws['C17'] = round(reporting_period_data['offpeaks'][0], 2) + ws['D17'].font = title_font + ws['D17'].alignment = c_c_alignment + ws['D17'].border = f_border + ws['D17'] = '{:.2%}'.format(round(reporting_period_data['offpeaks'][0], 2)/wssum) + pie = PieChart() pie.title = name+'分时用电成本' labels = Reference(ws, min_col=2, min_row=14, max_row=17) @@ -336,7 +364,7 @@ def generate_excel(report, s1.dLbls.showCatName = False s1.dLbls.showVal = True s1.dLbls.showPercent = True - ws.add_chart(pie, "D13") + ws.add_chart(pie, "E13") else: for i in range(12, 18 + 1): @@ -369,12 +397,20 @@ def generate_excel(report, ws['C' + str(current_row_number)].font = name_font ws['C' + str(current_row_number)].alignment = c_c_alignment ws['C' + str(current_row_number)].border = f_border - ws['C' + str(current_row_number)] = '成本占比' + ws['C' + str(current_row_number)] = '成本' + + ws['D' + str(current_row_number)].fill = table_fill + ws['D' + str(current_row_number)].font = name_font + ws['D' + str(current_row_number)].alignment = c_c_alignment + ws['D' + str(current_row_number)].border = f_border + ws['D' + str(current_row_number)] = '成本占比' current_row_number += 1 ca_len = len(reporting_period_data['names']) - + wssum = 0 + for i in range(0, ca_len): + wssum = round(reporting_period_data['subtotals'][i], 2) + wssum for i in range(0, ca_len): ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)].alignment = c_c_alignment @@ -386,6 +422,11 @@ def generate_excel(report, ws['C' + str(current_row_number)].border = f_border ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + ws['D' + str(current_row_number)].font = title_font + ws['D' + str(current_row_number)].alignment = c_c_alignment + ws['D' + str(current_row_number)].border = f_border + ws['D' + str(current_row_number)] = '{:.2%}'.format(round(reporting_period_data['subtotals'][i], 2) / wssum) + current_row_number += 1 table_end_row_number = current_row_number - 1 @@ -403,7 +444,7 @@ def generate_excel(report, s1.dLbls.showCatName = False s1.dLbls.showVal = True s1.dLbls.showPercent = True - table_cell = 'D' + str(table_start_row_number) + table_cell = 'E' + str(table_start_row_number) ws.add_chart(pie, table_cell) if ca_len < 4: From 187f1d33a062fb9ede2ffac0327ad345a170bd77 Mon Sep 17 00:00:00 2001 From: "13621160019@163.com" <13621160019@163.com> Date: Thu, 4 Mar 2021 18:34:52 +0800 Subject: [PATCH 15/26] added excel exporter of shopfloorcost report --- myems-api/excelexporters/shopfloorcost.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myems-api/excelexporters/shopfloorcost.py b/myems-api/excelexporters/shopfloorcost.py index 300d75ee..9cc3730e 100644 --- a/myems-api/excelexporters/shopfloorcost.py +++ b/myems-api/excelexporters/shopfloorcost.py @@ -286,7 +286,7 @@ def generate_excel(report, ws['D13'].font = name_font ws['D13'].alignment = c_c_alignment ws['D13'].border = f_border - ws['D13'] = '分时用电成本比' + ws['D13'] = '分时用电成本占比' wssum = round(reporting_period_data['toppeaks'][0], 2)+round(reporting_period_data['onpeaks'][0], 2)\ + round(reporting_period_data['midpeaks'][0], 2)+round(reporting_period_data['offpeaks'][0], 2) From 2f5c9673de670790cf0cff0685a2fe63b11d0a03 Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 19:55:57 +0800 Subject: [PATCH 16/26] Added 'excelexporters.combinedequipmentoutput.export()' method --- myems-api/reports/combinedequipmentoutput.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/myems-api/reports/combinedequipmentoutput.py b/myems-api/reports/combinedequipmentoutput.py index e97b3b07..60e30665 100644 --- a/myems-api/reports/combinedequipmentoutput.py +++ b/myems-api/reports/combinedequipmentoutput.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.combinedequipmentoutput class Reporting: @@ -478,4 +479,11 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.combinedequipmentoutput.export(result, + combined_equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) From 413077a6ee4b6dae9bf32612704db6037528f92e Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 19:57:00 +0800 Subject: [PATCH 17/26] Implemented the CombinedEquipmentOutput Excel Exporter --- .../excelexporters/combinedequipmentoutput.py | 394 ++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 myems-api/excelexporters/combinedequipmentoutput.py diff --git a/myems-api/excelexporters/combinedequipmentoutput.py b/myems-api/excelexporters/combinedequipmentoutput.py new file mode 100644 index 00000000..3e58cb6c --- /dev/null +++ b/myems-api/excelexporters/combinedequipmentoutput.py @@ -0,0 +1,394 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, +) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList + + +#################################################################################################################### +# 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################## + + current_row_number = 6 + + reporting_period_data = report['reporting_period'] + + has_names_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_names_data_flag = False + + if has_names_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期产出' + + current_row_number += 1 + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '消耗' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + # ws['B' + str(current_row_number)].font = title_font + # ws['B' + str(current_row_number)].alignment = c_c_alignment + # ws['B' + str(current_row_number)].border = f_border + # ws['B' + str(current_row_number)] = '单位面积值' + # + # col = 'C' + # + # for i in range(0, ca_len): + # ws[col + str(current_row_number)].font = name_font + # ws[col + str(current_row_number)].alignment = c_c_alignment + # ws[col + str(current_row_number)].border = f_border + # ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_per_unit_area'][i], 2) + # + # col = chr(ord(col) + 1) + # + # current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '环比' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = str( + round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \ + if reporting_period_data['increment_rates'][i] is not None else '-' + + col = chr(ord(col) + 1) + + current_row_number += 2 + + ##################################### + + has_values_data = True + has_timestamps_data = True + + if 'values' not in reporting_period_data.keys() or \ + reporting_period_data['values'] is None or \ + len(reporting_period_data['values']) == 0: + has_values_data = False + + if 'timestamps' not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0 or \ + len(reporting_period_data['timestamps'][0]) == 0: + has_timestamps_data = False + + if has_values_data and has_timestamps_data: + ca_len = len(reporting_period_data['names']) + time = reporting_period_data['timestamps'][0] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 详细数据' + + current_row_number += 1 + + chart_start_row_number = current_row_number + + current_row_number += ca_len * 6 + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '日期时间' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + col = chr(ord(col) + 1) + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = time[i] + + col = 'C' + for j in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \ + if reporting_period_data['values'][j][i] is not None else 0.00 + col = chr(ord(col) + 1) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '小计' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + col = chr(ord(col) + 1) + + current_row_number += 2 + + format_time_width_number = 1.0 + min_len_number = 1.0 + min_width_number = 11.0 # format_time_width_number * min_len_number + 4 and min_width_number > 11.0 + + if period_type == 'hourly': + format_time_width_number = 4.0 + min_len_number = 2 + min_width_number = 12.0 + elif period_type == 'daily': + format_time_width_number = 2.5 + min_len_number = 4 + min_width_number = 14.0 + elif period_type == 'monthly': + format_time_width_number = 2.1 + min_len_number = 4 + min_width_number = 12.4 + elif period_type == 'yearly': + format_time_width_number = 1.5 + min_len_number = 5 + min_width_number = 11.5 + + for i in range(0, ca_len): + line = LineChart() + line.title = '报告期产出 - ' + \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number + if line.width > 24: + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename From 1d2923e915a3434faf31d18d932afae47ddfdc3f Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 20:18:38 +0800 Subject: [PATCH 18/26] Change the cell name 'consume' to 'output' --- myems-api/excelexporters/combinedequipmentoutput.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myems-api/excelexporters/combinedequipmentoutput.py b/myems-api/excelexporters/combinedequipmentoutput.py index 3e58cb6c..aa19a56d 100644 --- a/myems-api/excelexporters/combinedequipmentoutput.py +++ b/myems-api/excelexporters/combinedequipmentoutput.py @@ -207,7 +207,7 @@ def generate_excel(report, ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)].alignment = c_c_alignment ws['B' + str(current_row_number)].border = f_border - ws['B' + str(current_row_number)] = '消耗' + ws['B' + str(current_row_number)] = '产出' col = 'C' From 9048dac16cb6f847f37695eb1d4111c48b9c2aba Mon Sep 17 00:00:00 2001 From: Caozhenhui <823914102@qq.com> Date: Thu, 4 Mar 2021 20:25:32 +0800 Subject: [PATCH 19/26] Implemented the combinedequipmentload Excel Exporter --- .../excelexporters/combinedequipmentload.py | 368 ++++++++++++++++++ myems-api/excelexporters/shopfloorload.py | 60 +-- myems-api/reports/combinedequipmentload.py | 24 +- 3 files changed, 415 insertions(+), 37 deletions(-) create mode 100644 myems-api/excelexporters/combinedequipmentload.py diff --git a/myems-api/excelexporters/combinedequipmentload.py b/myems-api/excelexporters/combinedequipmentload.py new file mode 100644 index 00000000..fc8a1764 --- /dev/null +++ b/myems-api/excelexporters/combinedequipmentload.py @@ -0,0 +1,368 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + LineChart, + Reference, +) +from openpyxl.chart.label import DataLabelList +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +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 + + #################################################################################################################### + # 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=False, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + 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) + # c_r_alignment = Alignment(vertical='bottom', + # horizontal='center', + # text_rotation=0, + # wrap_text=False, + # shrink_to_fit=False, + # indent=0) + + # Img + img = Image("excelexporters/myems.png") + # img = Image("myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + ws.add_image(img, 'B1') + + # Title + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + ################################################# + # First: 统计分析 + # 6: title + # 7: table title + # 8~2*ca_len table_data + ################################################# + reporting_period_data = report['reporting_period'] + + has_energy_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_energy_data_flag = False + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + if has_energy_data_flag: + ws['B6'].font = title_font + ws['B6'] = name + ' 统计分析' + + category = reporting_period_data['names'] + + # table_title + ws['B7'].fill = table_fill + ws['B7'].font = title_font + ws['B7'].alignment = c_c_alignment + ws['B7'] = '报告期' + ws['B7'].border = f_border + + ws['C7'].font = title_font + ws['C7'].alignment = c_c_alignment + ws['C7'] = '平均负荷' + ws['C7'].border = f_border + + ws['D7'].font = title_font + ws['D7'].alignment = c_c_alignment + ws['D7'] = '最大负荷' + ws['D7'].border = f_border + + ws['E7'].font = title_font + ws['E7'].alignment = c_c_alignment + ws['E7'] = '负荷系数' + ws['E7'].border = f_border + + # table_data + + for i, value in enumerate(category): + row = i * 2 + 8 + ws['B' + str(row)].font = name_font + ws['B' + str(row)].alignment = c_c_alignment + ws['B' + str(row)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + "/H )" + ws['B' + str(row)].border = f_border + + ws['B' + str(row + 1)].font = name_font + ws['B' + str(row + 1)].alignment = c_c_alignment + ws['B' + str(row + 1)] = "环比" + ws['B' + str(row + 1)].border = f_border + + ws['C' + str(row)].font = name_font + ws['C' + str(row)].alignment = c_c_alignment + ws['C' + str(row)] = round(reporting_period_data['averages'][i], 2) \ + if reporting_period_data['averages'][i] is not None else '' + ws['C' + str(row)].border = f_border + ws['C' + str(row)].number_format = '0.00' + + ws['C' + str(row + 1)].font = name_font + ws['C' + str(row + 1)].alignment = c_c_alignment + ws['C' + str(row + 1)] = str(round(reporting_period_data['averages_increment_rate'][i] * 100, 2)) + "%" \ + if reporting_period_data['averages_increment_rate'][i] is not None else '0.00%' + ws['C' + str(row + 1)].border = f_border + + ws['D' + str(row)].font = name_font + ws['D' + str(row)].alignment = c_c_alignment + ws['D' + str(row)] = round(reporting_period_data['maximums'][i], 2) \ + if reporting_period_data['maximums'][i] is not None else '' + ws['D' + str(row)].border = f_border + ws['D' + str(row)].number_format = '0.00' + + ws['D' + str(row + 1)].font = name_font + ws['D' + str(row + 1)].alignment = c_c_alignment + ws['D' + str(row + 1)] = str(round(reporting_period_data['maximums_increment_rate'][i] * 100, 2)) + "%" \ + if reporting_period_data['maximums_increment_rate'][i] is not None else '0.00%' + ws['D' + str(row + 1)].border = f_border + + ws['E' + str(row)].font = name_font + ws['E' + str(row)].alignment = c_c_alignment + ws['E' + str(row)] = round(reporting_period_data['factors'][i], 2) \ + if reporting_period_data['factors'][i] is not None else '' + ws['E' + str(row)].border = f_border + ws['E' + str(row)].number_format = '0.00' + + ws['E' + str(row + 1)].font = name_font + ws['E' + str(row + 1)].alignment = c_c_alignment + ws['E' + str(row + 1)] = str(round(reporting_period_data['factors_increment_rate'][i] * 100, 2)) + "%" \ + if reporting_period_data['factors_increment_rate'][i] is not None else '0.00%' + ws['E' + str(row + 1)].border = f_border + + ######################################################## + # Third: 详细数据 + # row_sat~ row_sat + 6*cal_len: line + # row_da: table title + # row_da + 1~: table_data + ######################################################## + has_timestamps_flag = True + if "timestamps" not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0: + has_timestamps_flag = False + + if has_timestamps_flag: + timestamps = reporting_period_data['timestamps'][0] + names = reporting_period_data['names'] + ca_len = len(names) + time_len = len(timestamps) + # row_lines == the number of rows of lines + row_lines = 6 * ca_len + # row_sat == the number of rows of statistical analysis table + row_sat = 9 + 2 * ca_len + # row_da == the number of rows of Detailed data + row_da = row_sat + row_lines + 1 + + ws['B' + str(row_da)].font = title_font + ws['B' + str(row_da)] = name + ' 详细数据' + # table_title + ws['B' + str(row_da + 1)].fill = table_fill + ws['B' + str(row_da + 1)].font = name_font + ws['B' + str(row_da + 1)].alignment = c_c_alignment + ws['B' + str(row_da + 1)] = "日期时间" + ws['B' + str(row_da + 1)].border = f_border + + for i in range(0, ca_len): + col_average = chr(ord('C') + i) + col_maximum = chr(ord('C') + i + ca_len) + + ws[col_average + str(row_da + 1)].font = name_font + ws[col_average + str(row_da + 1)].alignment = c_c_alignment + ws[col_average + str(row_da + 1)] = names[i] + " 平均负荷(" + reporting_period_data['units'][ + i] + "/H)" + ws[col_average + str(row_da + 1)].border = f_border + + ws[col_maximum + str(row_da + 1)].font = name_font + ws[col_maximum + str(row_da + 1)].alignment = c_c_alignment + ws[col_maximum + str(row_da + 1)] = names[i] + " 最大负荷(" + reporting_period_data['units'][ + i] + "/H)" + ws[col_maximum + str(row_da + 1)].border = f_border + # table_date + for i in range(0, time_len): + rows = i + row_da + 2 + + ws['B' + str(rows)].font = name_font + ws['B' + str(rows)].alignment = c_c_alignment + ws['B' + str(rows)] = timestamps[i] + ws['B' + str(rows)].border = f_border + + for index in range(0, ca_len): + col_average = chr(ord('C') + index) + col_maximum = chr(ord(col_average) + ca_len ) + + ws[col_average + str(rows)].font = name_font + ws[col_average + str(rows)].alignment = c_c_alignment + ws[col_average + str(rows)] = reporting_period_data['sub_averages'][index][i] \ + if reporting_period_data['sub_maximums'][index] is not None else '' + ws[col_average + str(rows)].number_format = '0.00' + ws[col_average + str(rows)].border = f_border + + ws[col_maximum + str(rows)].font = name_font + ws[col_maximum + str(rows)].alignment = c_c_alignment + ws[col_maximum + str(rows)] = reporting_period_data['sub_maximums'][index][i] \ + if reporting_period_data['sub_maximums'][index] is not None else '' + ws[col_maximum + str(rows)].number_format = '0.00' + ws[col_maximum + str(rows)].border = f_border + + # LineChart + for i in range(0, ca_len): + lc = LineChart() + lc.title = "报告期 最大负荷" + lc.style = 10 + lc.x_axis.majorTickMark = 'in' + lc.y_axis.majorTickMark = 'in' + lc.smooth = True + lc.x_axis.crosses = 'min' + lc.height = 8.25 + lc.width = 24 + lc.dLbls = DataLabelList() + lc.dLbls.dLblPos = 't' + lc.dLbls.showVal = True + times = Reference(ws, min_col=2, min_row=row_da + 2, + max_row=row_da + 2 + time_len) + lc_data = Reference(ws, min_col=3 + ca_len + i, min_row=row_da + 1, + max_row=row_da + 1 + time_len) + lc.add_data(lc_data, titles_from_data=True) + lc.set_categories(times) + ser = lc.series[0] + ser.marker.symbol = "diamond" + ser.marker.size = 5 + chart_col = 'B' + chart_cell = str(row_sat + 6 * i) + ws.add_chart(lc, chart_col + chart_cell) + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename diff --git a/myems-api/excelexporters/shopfloorload.py b/myems-api/excelexporters/shopfloorload.py index 1058b26e..2b5cf625 100644 --- a/myems-api/excelexporters/shopfloorload.py +++ b/myems-api/excelexporters/shopfloorload.py @@ -327,9 +327,9 @@ def generate_excel(report, ######################################################## # Third: 详细数据 - # row_sat+row_title~ row_sat+row_title+time_len: line - # row_sat+1+row_title: table title - # i + row_sat + 2 + 6 * ca_len~: table_data + # row_sat~ row_sat + 6*cal_len: line + # row_da: table title + # row_da + 1~: table_data ######################################################## has_timestamps_flag = True if "timestamps" not in reporting_period_data.keys() or \ @@ -342,38 +342,40 @@ def generate_excel(report, names = reporting_period_data['names'] ca_len = len(names) time_len = len(timestamps) - # title - row_title = 6 * ca_len - # row_st == row_statistical analysis table - row_sat = 12 + 3 * ca_len + # row_lines == the number of rows of lines + row_lines = 6 * ca_len + # row_sat == the number of rows of statistical analysis table + row_sat = 9 + 2 * ca_len + # row_da == the number of rows of Detailed data + row_da = row_sat + row_lines + 1 - ws['B' + str(row_sat + row_title)].font = title_font - ws['B' + str(row_sat + row_title)] = name + ' 详细数据' + ws['B' + str(row_da)].font = title_font + ws['B' + str(row_da)] = name + ' 详细数据' # table_title - ws['B' + str(row_sat + 1 + row_title)].fill = table_fill - ws['B' + str(row_sat + 1 + row_title)].font = name_font - ws['B' + str(row_sat + 1 + row_title)].alignment = c_c_alignment - ws['B' + str(row_sat + 1 + row_title)] = "日期时间" - ws['B' + str(row_sat + 1 + row_title)].border = f_border + ws['B' + str(row_da + 1)].fill = table_fill + ws['B' + str(row_da + 1)].font = name_font + ws['B' + str(row_da + 1)].alignment = c_c_alignment + ws['B' + str(row_da + 1)] = "日期时间" + ws['B' + str(row_da + 1)].border = f_border for i in range(0, ca_len): col_average = chr(ord('C') + i) col_maximum = chr(ord('C') + i + ca_len) - ws[col_average + str(row_sat + 1 + row_title)].font = name_font - ws[col_average + str(row_sat + 1 + row_title)].alignment = c_c_alignment - ws[col_average + str(row_sat + 1 + row_title)] = names[i] + " 平均负荷(" + reporting_period_data['units'][ + ws[col_average + str(row_da + 1)].font = name_font + ws[col_average + str(row_da + 1)].alignment = c_c_alignment + ws[col_average + str(row_da + 1)] = names[i] + " 平均负荷(" + reporting_period_data['units'][ i] + "/H)" - ws[col_average + str(row_sat + 1 + row_title)].border = f_border + ws[col_average + str(row_da + 1)].border = f_border - ws[col_maximum + str(row_sat + 1 + row_title)].font = name_font - ws[col_maximum + str(row_sat + 1 + row_title)].alignment = c_c_alignment - ws[col_maximum + str(row_sat + 1 + row_title)] = names[i] + " 最大负荷(" + reporting_period_data['units'][ + ws[col_maximum + str(row_da + 1)].font = name_font + ws[col_maximum + str(row_da + 1)].alignment = c_c_alignment + ws[col_maximum + str(row_da + 1)] = names[i] + " 最大负荷(" + reporting_period_data['units'][ i] + "/H)" - ws[col_maximum + str(row_sat + 1 + row_title)].border = f_border + ws[col_maximum + str(row_da + 1)].border = f_border # table_date for i in range(0, time_len): - rows = i + row_sat + 2 + 6 * ca_len + rows = i + row_da + 2 ws['B' + str(rows)].font = name_font ws['B' + str(rows)].alignment = c_c_alignment @@ -381,8 +383,8 @@ def generate_excel(report, ws['B' + str(rows)].border = f_border for index in range(0, ca_len): - col_average = chr(ord('C') + index * 2) - col_maximum = chr(ord('C') + index * 2 + 1) + col_average = chr(ord('C') + index) + col_maximum = chr(ord(col_average) + ca_len) ws[col_average + str(rows)].font = name_font ws[col_average + str(rows)].alignment = c_c_alignment @@ -412,10 +414,10 @@ def generate_excel(report, lc.dLbls = DataLabelList() lc.dLbls.dLblPos = 't' lc.dLbls.showVal = True - times = Reference(ws, min_col=2, min_row=row_sat + 2 + row_title, - max_row=row_sat + 2 + row_title + time_len) - lc_data = Reference(ws, min_col=3 + ca_len, min_row=row_sat + 1 + row_title, - max_row=row_sat + 1 + row_title + time_len) + times = Reference(ws, min_col=2, min_row=row_da + 2, + max_row=row_da + 2 + time_len) + lc_data = Reference(ws, min_col=3 + ca_len + i, min_row=row_da + 1, + max_row=row_da + 1 + time_len) lc.add_data(lc_data, titles_from_data=True) lc.set_categories(times) ser = lc.series[0] diff --git a/myems-api/reports/combinedequipmentload.py b/myems-api/reports/combinedequipmentload.py index de0ad444..e47d9752 100644 --- a/myems-api/reports/combinedequipmentload.py +++ b/myems-api/reports/combinedequipmentload.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.combinedequipmentload class Reporting: @@ -69,7 +70,7 @@ class Reporting: try: base_start_datetime_utc = datetime.strptime(base_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_START_DATETIME") @@ -80,7 +81,7 @@ class Reporting: try: base_end_datetime_utc = datetime.strptime(base_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_END_DATETIME") @@ -98,7 +99,7 @@ class Reporting: try: reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_START_DATETIME") @@ -111,7 +112,7 @@ class Reporting: try: reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_END_DATETIME") @@ -269,10 +270,10 @@ class Reporting: period_type) base[energy_category_id]['factor'] = \ (base[energy_category_id]['average'] / base[energy_category_id]['maximum'] - if (base[energy_category_id]['average'] is not None and - base[energy_category_id]['maximum'] is not None and - base[energy_category_id]['maximum'] > Decimal(0.0)) - else None) + if (base[energy_category_id]['average'] is not None and + base[energy_category_id]['maximum'] is not None and + base[energy_category_id]['maximum'] > Decimal(0.0)) + else None) for row_combined_equipment_periodically in rows_combined_equipment_periodically: current_datetime_local = row_combined_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ @@ -523,4 +524,11 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.combinedequipmentload.export(result, + combined_equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) From 7796eeed5f358692b3713fdc3da533cb2c856fad Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 20:31:13 +0800 Subject: [PATCH 20/26] Implemented the SpaceOutput Excel Exporter --- myems-api/excelexporters/spaceoutput.py | 484 ++++++++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100644 myems-api/excelexporters/spaceoutput.py diff --git a/myems-api/excelexporters/spaceoutput.py b/myems-api/excelexporters/spaceoutput.py new file mode 100644 index 00000000..6554dd86 --- /dev/null +++ b/myems-api/excelexporters/spaceoutput.py @@ -0,0 +1,484 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, +) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList + + +#################################################################################################################### +# 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################## + + current_row_number = 6 + + reporting_period_data = report['reporting_period'] + + has_names_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_names_data_flag = False + + if has_names_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期产出' + + current_row_number += 1 + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '产出' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '单位面积值' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_per_unit_area'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '环比' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = str( + round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \ + if reporting_period_data['increment_rates'][i] is not None else '-' + + col = chr(ord(col) + 1) + + current_row_number += 2 + + ##################################### + + has_child_flag = True + + if "child_space" not in report.keys() or "energy_category_names" not in report['child_space'].keys() or \ + len(report['child_space']["energy_category_names"]) == 0 \ + or 'child_space_names_array' not in report['child_space'].keys() \ + or report['child_space']['child_space_names_array'] is None \ + or len(report['child_space']['child_space_names_array']) == 0 \ + or len(report['child_space']['child_space_names_array'][0]) == 0: + has_child_flag = False + + if has_child_flag: + child = report['child_space'] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 子空间数据' + + current_row_number += 1 + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + ca_len = len(child['energy_category_names']) + + for i in range(0, ca_len): + row = chr(ord('C') + i) + ws[row + str(current_row_number)].fill = table_fill + ws[row + str(current_row_number)].font = name_font + ws[row + str(current_row_number)].alignment = c_c_alignment + ws[row + str(current_row_number)].border = f_border + ws[row + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + space_len = len(child['child_space_names_array'][0]) + + for i in range(0, space_len): + current_row_number += 1 + row = str(current_row_number) + + ws['B' + row].font = name_font + ws['B' + row].alignment = c_c_alignment + ws['B' + row] = child['child_space_names_array'][0][i] + ws['B' + row].border = f_border + + for j in range(0, ca_len): + col = chr(ord('C') + j) + ws[col + row].font = name_font + ws[col + row].alignment = c_c_alignment + ws[col + row] = round(child['subtotals_array'][j][i], 2) + ws[col + row].border = f_border + + table_end_row_number = current_row_number + current_row_number += 1 + pie_start_row_number = current_row_number + + # Pie + for i in range(0, ca_len): + pie = PieChart() + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, + max_row=table_end_row_number) + pie_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, + max_row=table_end_row_number) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 8 + pie.title = ws.cell(column=3 + i, row=table_start_row_number).value + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + chart_cell = '' + if i % 2 == 0: + chart_cell = 'B' + str(pie_start_row_number) + else: + chart_cell = 'E' + str(pie_start_row_number) + pie_start_row_number += 5 + ws.add_chart(pie, chart_cell) + + current_row_number = pie_start_row_number + if ca_len % 2 == 1: + current_row_number += 5 + + current_row_number += 1 + ####################### + + has_values_data = True + has_timestamps_data = True + + if 'values' not in reporting_period_data.keys() or \ + reporting_period_data['values'] is None or \ + len(reporting_period_data['values']) == 0: + has_values_data = False + + if 'timestamps' not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0 or \ + len(reporting_period_data['timestamps'][0]) == 0: + has_timestamps_data = False + + if has_values_data and has_timestamps_data: + ca_len = len(reporting_period_data['names']) + time = reporting_period_data['timestamps'][0] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 详细数据' + + current_row_number += 1 + + chart_start_row_number = current_row_number + + current_row_number += ca_len * 6 + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '日期时间' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + col = chr(ord(col) + 1) + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = time[i] + + col = 'C' + for j in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \ + if reporting_period_data['values'][j][i] is not None else 0.00 + col = chr(ord(col) + 1) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '小计' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + col = chr(ord(col) + 1) + + current_row_number += 2 + + format_time_width_number = 1.0 + min_len_number = 1.0 + min_width_number = 11.0 # format_time_width_number * min_len_number + 4 and min_width_number > 11.0 + + if period_type == 'hourly': + format_time_width_number = 4.0 + min_len_number = 2 + min_width_number = 12.0 + elif period_type == 'daily': + format_time_width_number = 2.5 + min_len_number = 4 + min_width_number = 14.0 + elif period_type == 'monthly': + format_time_width_number = 2.1 + min_len_number = 4 + min_width_number = 12.4 + elif period_type == 'yearly': + format_time_width_number = 1.5 + min_len_number = 5 + min_width_number = 11.5 + + for i in range(0, ca_len): + line = LineChart() + line.title = '报告期产出 - ' + \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number + if line.width > 24: + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + + From 22ba6615f4c4a3c72a57441e17583544d39a9082 Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Thu, 4 Mar 2021 20:34:03 +0800 Subject: [PATCH 21/26] Added 'excelexporters.spaceoutput.export()' method --- myems-api/reports/spaceoutput.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/myems-api/reports/spaceoutput.py b/myems-api/reports/spaceoutput.py index 63bd26ed..a1dc983b 100644 --- a/myems-api/reports/spaceoutput.py +++ b/myems-api/reports/spaceoutput.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.spaceoutput class Reporting: @@ -68,7 +69,7 @@ class Reporting: try: base_start_datetime_utc = datetime.strptime(base_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_START_DATETIME") @@ -79,7 +80,7 @@ class Reporting: try: base_end_datetime_utc = datetime.strptime(base_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_END_DATETIME") @@ -97,7 +98,7 @@ class Reporting: try: reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_START_DATETIME") @@ -110,7 +111,7 @@ class Reporting: try: reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_END_DATETIME") @@ -226,7 +227,7 @@ class Reporting: " tbl_points po, tbl_sensors_points sepo " " WHERE sp.id = %s AND sp.id = spse.space_id AND spse.sensor_id = se.id " " AND se.id = sepo.sensor_id AND sepo.point_id = po.id " - " ORDER BY po.id ", (space['id'], )) + " ORDER BY po.id ", (space['id'],)) rows_points = cursor_system.fetchall() if rows_points is not None and len(rows_points) > 0: for row in rows_points: @@ -238,7 +239,7 @@ class Reporting: cursor_system.execute(" SELECT po.id, po.name, po.units, po.object_type " " FROM tbl_spaces sp, tbl_spaces_points sppo, tbl_points po " " WHERE sp.id = %s AND sp.id = sppo.space_id AND sppo.point_id = po.id " - " ORDER BY po.id ", (space['id'], )) + " ORDER BY po.id ", (space['id'],)) rows_points = cursor_system.fetchall() if rows_points is not None and len(rows_points) > 0: for row in rows_points: @@ -251,7 +252,7 @@ class Reporting: cursor_system.execute(" SELECT id, name " " FROM tbl_spaces " " WHERE parent_space_id = %s " - " ORDER BY id ", (space['id'], )) + " ORDER BY id ", (space['id'],)) rows_child_spaces = cursor_system.fetchall() if rows_child_spaces is not None and len(rows_child_spaces) > 0: for row in rows_child_spaces: @@ -545,4 +546,11 @@ class Reporting: result['child_space']['subtotals_array'].append( child_space_data[energy_category_id]['subtotals']) + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.spaceoutput.export(result, + space['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) From 80601589eb010fa0ce21c3ab0ccfe484a0747ae7 Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Thu, 4 Mar 2021 20:44:38 +0800 Subject: [PATCH 22/26] Implemented the combinedequipmentcost Excel export --- .../excelexporters/combinedequipmentcost.py | 585 ++++++++++++++++++ myems-api/reports/combinedequipmentcost.py | 8 +- 2 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 myems-api/excelexporters/combinedequipmentcost.py diff --git a/myems-api/excelexporters/combinedequipmentcost.py b/myems-api/excelexporters/combinedequipmentcost.py new file mode 100644 index 00000000..4c05e4a3 --- /dev/null +++ b/myems-api/excelexporters/combinedequipmentcost.py @@ -0,0 +1,585 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, + ) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList + +#################################################################################################################### +# 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 + #################################################################################################################### + 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 + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # for i in range(2, 37 + 1): + # ws.row_dimensions[i].height = 30 + # + # for i in range(38, 90 + 1): + # ws.row_dimensions[i].height = 30 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, 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') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period" not in report.keys() or \ + "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################################# + + reporting_period_data = report['reporting_period'] + + has_energy_data_flag = True + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_energy_data_flag = False + + if has_energy_data_flag: + ws['B6'].font = title_font + ws['B6'] = name+' 报告期成本' + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[7].height = 60 + ws['B7'].fill = table_fill + ws['B7'].border = f_border + + ws['B8'].font = title_font + ws['B8'].alignment = c_c_alignment + ws['B8'] = '成本' + ws['B8'].border = f_border + + ws['B9'].font = title_font + ws['B9'].alignment = c_c_alignment + ws['B9'] = '环比' + ws['B9'].border = f_border + + col = 'B' + + for i in range(0, ca_len): + col = chr(ord('C') + i) + ws[col + '7'].fill = table_fill + ws[col + '7'].font = name_font + ws[col + '7'].alignment = c_c_alignment + ws[col + '7'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + ws[col + '7'].border = f_border + + ws[col + '8'].font = name_font + ws[col + '8'].alignment = c_c_alignment + ws[col + '8'] = round(reporting_period_data['subtotals'][i], 2) + ws[col + '8'].border = f_border + + ws[col + '9'].font = name_font + ws[col + '9'].alignment = c_c_alignment + ws[col + '9'] = str(round(reporting_period_data['increment_rates'][i] * 100, 2)) + "%" \ + if reporting_period_data['increment_rates'][i] is not None else "-" + ws[col + '9'].border = f_border + + end_col = chr(ord(col)+1) + ws[end_col + '7'].fill = table_fill + ws[end_col + '7'].font = name_font + ws[end_col + '7'].alignment = c_c_alignment + ws[end_col + '7'] = "总计 (" + reporting_period_data['total_unit'] + ")" + ws[end_col + '7'].border = f_border + + ws[end_col + '8'].font = name_font + ws[end_col + '8'].alignment = c_c_alignment + ws[end_col + '8'] = round(reporting_period_data['total'], 2) + ws[end_col + '8'].border = f_border + + ws[end_col + '9'].font = name_font + ws[end_col + '9'].alignment = c_c_alignment + ws[end_col + '9'] = str(round(reporting_period_data['total_increment_rate'] * 100, 2)) + "%" \ + if reporting_period_data['total_increment_rate'] is not None else "-" + ws[end_col + '9'].border = f_border + + else: + for i in range(6, 9 + 1): + ws.row_dimensions[i].height = 0.1 + + ################################################# + + has_ele_peak_flag = True + if "toppeaks" not in reporting_period_data.keys() or \ + reporting_period_data['toppeaks'] is None or \ + len(reporting_period_data['toppeaks']) == 0: + has_ele_peak_flag = False + + if has_ele_peak_flag: + ws['B12'].font = title_font + ws['B12'] = name+'分时用电成本' + + ws['B13'].fill = table_fill + ws['B13'].font = name_font + ws['B13'].alignment = c_c_alignment + ws['B13'].border = f_border + + ws['C13'].fill = table_fill + ws['C13'].font = name_font + ws['C13'].alignment = c_c_alignment + ws['C13'].border = f_border + ws['C13'] = '分时用电成本' + + ws['D13'].fill = table_fill + ws['D13'].font = name_font + ws['D13'].alignment = c_c_alignment + ws['D13'].border = f_border + ws['D13'] = '分时用电成本占比' + + wssum = round(reporting_period_data['toppeaks'][0], 2)+round(reporting_period_data['onpeaks'][0], 2)\ + + round(reporting_period_data['midpeaks'][0], 2)+round(reporting_period_data['offpeaks'][0], 2) + + ws['B14'].font = title_font + ws['B14'].alignment = c_c_alignment + ws['B14'] = '尖' + ws['B14'].border = f_border + + ws['C14'].font = title_font + ws['C14'].alignment = c_c_alignment + ws['C14'].border = f_border + ws['C14'] = round(reporting_period_data['toppeaks'][0], 2) + + ws['D14'].font = title_font + ws['D14'].alignment = c_c_alignment + ws['D14'].border = f_border + ws['D14'] = '{:.2%}'.format(round(reporting_period_data['toppeaks'][0], 2)/wssum) + + ws['B15'].font = title_font + ws['B15'].alignment = c_c_alignment + ws['B15'] = '峰' + ws['B15'].border = f_border + + ws['C15'].font = title_font + ws['C15'].alignment = c_c_alignment + ws['C15'].border = f_border + ws['C15'] = round(reporting_period_data['onpeaks'][0], 2) + + ws['D15'].font = title_font + ws['D15'].alignment = c_c_alignment + ws['D15'].border = f_border + ws['D15'] = '{:.2%}'.format(round(reporting_period_data['onpeaks'][0], 2)/wssum) + + ws['B16'].font = title_font + ws['B16'].alignment = c_c_alignment + ws['B16'] = '平' + ws['B16'].border = f_border + + ws['C16'].font = title_font + ws['C16'].alignment = c_c_alignment + ws['C16'].border = f_border + ws['C16'] = round(reporting_period_data['midpeaks'][0], 2) + + ws['D16'].font = title_font + ws['D16'].alignment = c_c_alignment + ws['D16'].border = f_border + ws['D16'] = '{:.2%}'.format(round(reporting_period_data['midpeaks'][0], 2)/wssum) + + ws['B17'].font = title_font + ws['B17'].alignment = c_c_alignment + ws['B17'] = '谷' + ws['B17'].border = f_border + + ws['C17'].font = title_font + ws['C17'].alignment = c_c_alignment + ws['C17'].border = f_border + ws['C17'] = round(reporting_period_data['offpeaks'][0], 2) + + ws['D17'].font = title_font + ws['D17'].alignment = c_c_alignment + ws['D17'].border = f_border + ws['D17'] = '{:.2%}'.format(round(reporting_period_data['offpeaks'][0], 2)/wssum) + + pie = PieChart() + pie.title = name+'分时用电成本' + labels = Reference(ws, min_col=2, min_row=14, max_row=17) + pie_data = Reference(ws, min_col=3, min_row=13, max_row=17) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 9 + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + ws.add_chart(pie, "E13") + + else: + for i in range(12, 18 + 1): + ws.row_dimensions[i].height = 0.1 + + ################################################ + + current_row_number = 19 + + has_subtotals_data_flag = True + if "subtotals" not in reporting_period_data.keys() or \ + reporting_period_data['subtotals'] is None or \ + len(reporting_period_data['subtotals']) == 0: + has_subtotals_data_flag = False + + if has_subtotals_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 成本占比' + + current_row_number += 1 + + table_start_row_number = current_row_number + + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = name_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + + ws['C' + str(current_row_number)].fill = table_fill + ws['C' + str(current_row_number)].font = name_font + ws['C' + str(current_row_number)].alignment = c_c_alignment + ws['C' + str(current_row_number)].border = f_border + ws['C' + str(current_row_number)] = '成本' + + ws['D' + str(current_row_number)].fill = table_fill + ws['D' + str(current_row_number)].font = name_font + ws['D' + str(current_row_number)].alignment = c_c_alignment + ws['D' + str(current_row_number)].border = f_border + ws['D' + str(current_row_number)] = '成本占比' + + current_row_number += 1 + + ca_len = len(reporting_period_data['names']) + wssum = 0 + for i in range(0, ca_len): + wssum = round(reporting_period_data['subtotals'][i], 2) + wssum + for i in range(0, ca_len): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = reporting_period_data['names'][i] + ws['B' + str(current_row_number)].border = f_border + + ws['C' + str(current_row_number)].font = title_font + ws['C' + str(current_row_number)].alignment = c_c_alignment + ws['C' + str(current_row_number)].border = f_border + ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + + ws['D' + str(current_row_number)].font = title_font + ws['D' + str(current_row_number)].alignment = c_c_alignment + ws['D' + str(current_row_number)].border = f_border + ws['D' + str(current_row_number)] = '{:.2%}'.format(round(reporting_period_data['subtotals'][i], 2) / wssum) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + pie = PieChart() + pie.title = name + ' 成本占比' + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 9 + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + table_cell = 'E' + str(table_start_row_number) + ws.add_chart(pie, table_cell) + + if ca_len < 4: + current_row_number = current_row_number - ca_len + 4 + + else: + for i in range(21, 29 + 1): + current_row_number = 30 + ws.row_dimensions[i].height = 0.1 + + ############################################### + + current_row_number += 1 + + has_detail_data_flag = True + + table_start_draw_flag = current_row_number + 1 + + if "timestamps" not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0: + has_detail_data_flag = False + + if has_detail_data_flag: + reporting_period_data = report['reporting_period'] + times = reporting_period_data['timestamps'] + ca_len = len(report['reporting_period']['names']) + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name+' 详细数据' + + table_start_row_number = (current_row_number + 1) + ca_len * 6 + current_row_number = table_start_row_number + + time = times[0] + has_data = False + + if len(time) > 0: + has_data = True + + if has_data: + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = '日期时间' + + col = 'B' + + for i in range(0, ca_len): + col = chr(ord('C') + i) + + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \ + " (" + reporting_period_data['units'][i] + ")" + ws[col + str(current_row_number)].border = f_border + + end_col = chr(ord(col) + 1) + + ws[end_col + str(current_row_number)].fill = table_fill + ws[end_col + str(current_row_number)].font = title_font + ws[end_col + str(current_row_number)].alignment = c_c_alignment + ws[end_col + str(current_row_number)] = "总计 (" + reporting_period_data['total_unit'] + ")" + ws[end_col + str(current_row_number)].border = f_border + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = time[i] + ws['B' + str(current_row_number)].border = f_border + + col = 'B' + + every_day_total = 0 + + for j in range(0, ca_len): + col = chr(ord('C') + j) + + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + value = round(reporting_period_data['values'][j][i], 2) + every_day_total += value + ws[col + str(current_row_number)] = value + ws[col + str(current_row_number)].border = f_border + + end_col = chr(ord(col) + 1) + ws[end_col + str(current_row_number)].font = title_font + ws[end_col + str(current_row_number)].alignment = c_c_alignment + ws[end_col + str(current_row_number)] = round(every_day_total, 2) + ws[end_col + str(current_row_number)].border = f_border + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)] = '小计' + ws['B' + str(current_row_number)].border = f_border + + col = 'B' + + for i in range(0, ca_len): + col = chr(ord('C') + i) + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2) + ws[col + str(current_row_number)].border = f_border + + # line + line = LineChart() + line.title = '报告期成本 - ' + ws.cell(column=3+i, row=table_start_row_number).value + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(table_start_draw_flag + 6 * i) + ws.add_chart(line, chart_cell) + + end_col = chr(ord(col) + 1) + ws[end_col + str(current_row_number)].font = title_font + ws[end_col + str(current_row_number)].alignment = c_c_alignment + ws[end_col + str(current_row_number)] = round(reporting_period_data['total'], 2) + ws[end_col + str(current_row_number)].border = f_border + + current_row_number += 1 + + else: + for i in range(30, 69 + 1): + current_row_number = 70 + ws.row_dimensions[i].height = 0.1 + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename diff --git a/myems-api/reports/combinedequipmentcost.py b/myems-api/reports/combinedequipmentcost.py index 5aadb3f7..ed366dcb 100644 --- a/myems-api/reports/combinedequipmentcost.py +++ b/myems-api/reports/combinedequipmentcost.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.combinedequipmentcost class Reporting: @@ -516,5 +517,10 @@ class Reporting: "timestamps": parameters_data['timestamps'], "values": parameters_data['values'] } - + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.combinedequipmentcost.export(result, + combined_equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) resp.body = json.dumps(result) From bf9e256d396bb3f02ea457ca20055ec06e267096 Mon Sep 17 00:00:00 2001 From: Caozhenhui <823914102@qq.com> Date: Thu, 4 Mar 2021 20:46:50 +0800 Subject: [PATCH 23/26] fixd pep8 --- myems-api/excelexporters/combinedequipmentload.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myems-api/excelexporters/combinedequipmentload.py b/myems-api/excelexporters/combinedequipmentload.py index fc8a1764..b4057c48 100644 --- a/myems-api/excelexporters/combinedequipmentload.py +++ b/myems-api/excelexporters/combinedequipmentload.py @@ -319,7 +319,7 @@ def generate_excel(report, for index in range(0, ca_len): col_average = chr(ord('C') + index) - col_maximum = chr(ord(col_average) + ca_len ) + col_maximum = chr(ord(col_average) + ca_len) ws[col_average + str(rows)].font = name_font ws[col_average + str(rows)].alignment = c_c_alignment From 739ab78949b428e64d7d84ef8af8135fea64029f Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Fri, 5 Mar 2021 11:36:38 +0800 Subject: [PATCH 24/26] Delete comment code --- .../excelexporters/combinedequipmentoutput.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/myems-api/excelexporters/combinedequipmentoutput.py b/myems-api/excelexporters/combinedequipmentoutput.py index aa19a56d..3277b082 100644 --- a/myems-api/excelexporters/combinedequipmentoutput.py +++ b/myems-api/excelexporters/combinedequipmentoutput.py @@ -221,23 +221,6 @@ def generate_excel(report, current_row_number += 1 - # ws['B' + str(current_row_number)].font = title_font - # ws['B' + str(current_row_number)].alignment = c_c_alignment - # ws['B' + str(current_row_number)].border = f_border - # ws['B' + str(current_row_number)] = '单位面积值' - # - # col = 'C' - # - # for i in range(0, ca_len): - # ws[col + str(current_row_number)].font = name_font - # ws[col + str(current_row_number)].alignment = c_c_alignment - # ws[col + str(current_row_number)].border = f_border - # ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_per_unit_area'][i], 2) - # - # col = chr(ord(col) + 1) - # - # current_row_number += 1 - ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)].alignment = c_c_alignment ws['B' + str(current_row_number)].border = f_border From ceaa72a883c0f30be7e4d2fb07ce55e6bf444012 Mon Sep 17 00:00:00 2001 From: YangZhang-GitHub <2533471770@qq.com> Date: Fri, 5 Mar 2021 11:51:53 +0800 Subject: [PATCH 25/26] Change the subspace location --- myems-api/excelexporters/spaceoutput.py | 175 ++++++++++++------------ 1 file changed, 88 insertions(+), 87 deletions(-) diff --git a/myems-api/excelexporters/spaceoutput.py b/myems-api/excelexporters/spaceoutput.py index 6554dd86..80fed3c1 100644 --- a/myems-api/excelexporters/spaceoutput.py +++ b/myems-api/excelexporters/spaceoutput.py @@ -257,93 +257,6 @@ def generate_excel(report, current_row_number += 2 - ##################################### - - has_child_flag = True - - if "child_space" not in report.keys() or "energy_category_names" not in report['child_space'].keys() or \ - len(report['child_space']["energy_category_names"]) == 0 \ - or 'child_space_names_array' not in report['child_space'].keys() \ - or report['child_space']['child_space_names_array'] is None \ - or len(report['child_space']['child_space_names_array']) == 0 \ - or len(report['child_space']['child_space_names_array'][0]) == 0: - has_child_flag = False - - if has_child_flag: - child = report['child_space'] - - ws['B' + str(current_row_number)].font = title_font - ws['B' + str(current_row_number)] = name + ' 子空间数据' - - current_row_number += 1 - table_start_row_number = current_row_number - - ws.row_dimensions[current_row_number].height = 60 - ws['B' + str(current_row_number)].fill = table_fill - ws['B' + str(current_row_number)].border = f_border - ca_len = len(child['energy_category_names']) - - for i in range(0, ca_len): - row = chr(ord('C') + i) - ws[row + str(current_row_number)].fill = table_fill - ws[row + str(current_row_number)].font = name_font - ws[row + str(current_row_number)].alignment = c_c_alignment - ws[row + str(current_row_number)].border = f_border - ws[row + str(current_row_number)] = \ - reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" - - space_len = len(child['child_space_names_array'][0]) - - for i in range(0, space_len): - current_row_number += 1 - row = str(current_row_number) - - ws['B' + row].font = name_font - ws['B' + row].alignment = c_c_alignment - ws['B' + row] = child['child_space_names_array'][0][i] - ws['B' + row].border = f_border - - for j in range(0, ca_len): - col = chr(ord('C') + j) - ws[col + row].font = name_font - ws[col + row].alignment = c_c_alignment - ws[col + row] = round(child['subtotals_array'][j][i], 2) - ws[col + row].border = f_border - - table_end_row_number = current_row_number - current_row_number += 1 - pie_start_row_number = current_row_number - - # Pie - for i in range(0, ca_len): - pie = PieChart() - labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, - max_row=table_end_row_number) - pie_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, - max_row=table_end_row_number) - pie.add_data(pie_data, titles_from_data=True) - pie.set_categories(labels) - pie.height = 6.6 - pie.width = 8 - pie.title = ws.cell(column=3 + i, row=table_start_row_number).value - s1 = pie.series[0] - s1.dLbls = DataLabelList() - s1.dLbls.showCatName = False - s1.dLbls.showVal = True - s1.dLbls.showPercent = True - chart_cell = '' - if i % 2 == 0: - chart_cell = 'B' + str(pie_start_row_number) - else: - chart_cell = 'E' + str(pie_start_row_number) - pie_start_row_number += 5 - ws.add_chart(pie, chart_cell) - - current_row_number = pie_start_row_number - if ca_len % 2 == 1: - current_row_number += 5 - - current_row_number += 1 ####################### has_values_data = True @@ -475,6 +388,94 @@ def generate_excel(report, chart_start_row_number += 6 ws.add_chart(line, chart_cell) + ##################################### + + has_child_flag = True + + if "child_space" not in report.keys() or "energy_category_names" not in report['child_space'].keys() or \ + len(report['child_space']["energy_category_names"]) == 0 \ + or 'child_space_names_array' not in report['child_space'].keys() \ + or report['child_space']['child_space_names_array'] is None \ + or len(report['child_space']['child_space_names_array']) == 0 \ + or len(report['child_space']['child_space_names_array'][0]) == 0: + has_child_flag = False + + if has_child_flag: + child = report['child_space'] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 子空间数据' + + current_row_number += 1 + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 60 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + ca_len = len(child['energy_category_names']) + + for i in range(0, ca_len): + row = chr(ord('C') + i) + ws[row + str(current_row_number)].fill = table_fill + ws[row + str(current_row_number)].font = name_font + ws[row + str(current_row_number)].alignment = c_c_alignment + ws[row + str(current_row_number)].border = f_border + ws[row + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + space_len = len(child['child_space_names_array'][0]) + + for i in range(0, space_len): + current_row_number += 1 + row = str(current_row_number) + + ws['B' + row].font = name_font + ws['B' + row].alignment = c_c_alignment + ws['B' + row] = child['child_space_names_array'][0][i] + ws['B' + row].border = f_border + + for j in range(0, ca_len): + col = chr(ord('C') + j) + ws[col + row].font = name_font + ws[col + row].alignment = c_c_alignment + ws[col + row] = round(child['subtotals_array'][j][i], 2) + ws[col + row].border = f_border + + table_end_row_number = current_row_number + current_row_number += 1 + pie_start_row_number = current_row_number + + # Pie + for i in range(0, ca_len): + pie = PieChart() + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, + max_row=table_end_row_number) + pie_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, + max_row=table_end_row_number) + pie.add_data(pie_data, titles_from_data=True) + pie.set_categories(labels) + pie.height = 6.6 + pie.width = 8 + pie.title = ws.cell(column=3 + i, row=table_start_row_number).value + s1 = pie.series[0] + s1.dLbls = DataLabelList() + s1.dLbls.showCatName = False + s1.dLbls.showVal = True + s1.dLbls.showPercent = True + chart_cell = '' + if i % 2 == 0: + chart_cell = 'B' + str(pie_start_row_number) + else: + chart_cell = 'E' + str(pie_start_row_number) + pie_start_row_number += 5 + ws.add_chart(pie, chart_cell) + + current_row_number = pie_start_row_number + if ca_len % 2 == 1: + current_row_number += 5 + + current_row_number += 1 + filename = str(uuid.uuid4()) + '.xlsx' wb.save(filename) From b782ea91a96ac49208a9a2125fb9acd332ef4ff5 Mon Sep 17 00:00:00 2001 From: Caozhenhui <823914102@qq.com> Date: Fri, 5 Mar 2021 12:44:44 +0800 Subject: [PATCH 26/26] fixd the detail table column order --- myems-api/excelexporters/combinedequipmentload.py | 10 +++++----- myems-api/excelexporters/shopfloorload.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/myems-api/excelexporters/combinedequipmentload.py b/myems-api/excelexporters/combinedequipmentload.py index b4057c48..f7908202 100644 --- a/myems-api/excelexporters/combinedequipmentload.py +++ b/myems-api/excelexporters/combinedequipmentload.py @@ -294,8 +294,8 @@ def generate_excel(report, ws['B' + str(row_da + 1)].border = f_border for i in range(0, ca_len): - col_average = chr(ord('C') + i) - col_maximum = chr(ord('C') + i + ca_len) + col_average = chr(ord('C') + 2 * i) + col_maximum = chr(ord('D') + 2 * i) ws[col_average + str(row_da + 1)].font = name_font ws[col_average + str(row_da + 1)].alignment = c_c_alignment @@ -318,8 +318,8 @@ def generate_excel(report, ws['B' + str(rows)].border = f_border for index in range(0, ca_len): - col_average = chr(ord('C') + index) - col_maximum = chr(ord(col_average) + ca_len) + col_average = chr(ord('C') + 2 * index) + col_maximum = chr(ord('D') + 2 * index) ws[col_average + str(rows)].font = name_font ws[col_average + str(rows)].alignment = c_c_alignment @@ -351,7 +351,7 @@ def generate_excel(report, lc.dLbls.showVal = True times = Reference(ws, min_col=2, min_row=row_da + 2, max_row=row_da + 2 + time_len) - lc_data = Reference(ws, min_col=3 + ca_len + i, min_row=row_da + 1, + lc_data = Reference(ws, min_col=2 + 2 * (i+1), min_row=row_da + 1, max_row=row_da + 1 + time_len) lc.add_data(lc_data, titles_from_data=True) lc.set_categories(times) diff --git a/myems-api/excelexporters/shopfloorload.py b/myems-api/excelexporters/shopfloorload.py index 2b5cf625..3a972e34 100644 --- a/myems-api/excelexporters/shopfloorload.py +++ b/myems-api/excelexporters/shopfloorload.py @@ -359,8 +359,8 @@ def generate_excel(report, ws['B' + str(row_da + 1)].border = f_border for i in range(0, ca_len): - col_average = chr(ord('C') + i) - col_maximum = chr(ord('C') + i + ca_len) + col_average = chr(ord('C') + 2 * i) + col_maximum = chr(ord('D') + 2 * i) ws[col_average + str(row_da + 1)].font = name_font ws[col_average + str(row_da + 1)].alignment = c_c_alignment @@ -383,8 +383,8 @@ def generate_excel(report, ws['B' + str(rows)].border = f_border for index in range(0, ca_len): - col_average = chr(ord('C') + index) - col_maximum = chr(ord(col_average) + ca_len) + col_average = chr(ord('C') + 2 * index) + col_maximum = chr(ord('D') + 2 * index) ws[col_average + str(rows)].font = name_font ws[col_average + str(rows)].alignment = c_c_alignment @@ -416,7 +416,7 @@ def generate_excel(report, lc.dLbls.showVal = True times = Reference(ws, min_col=2, min_row=row_da + 2, max_row=row_da + 2 + time_len) - lc_data = Reference(ws, min_col=3 + ca_len + i, min_row=row_da + 1, + lc_data = Reference(ws, min_col=2 + 2 * (i+1), min_row=row_da + 1, max_row=row_da + 1 + time_len) lc.add_data(lc_data, titles_from_data=True) lc.set_categories(times)