Issues (1577)

myems-api/excelexporters/energyflowdiagram.py (1 issue)

1
import base64
2
from core.utilities import get_translation
3
import os
4
import uuid
5
from openpyxl import Workbook
6
from openpyxl.drawing.image import Image
7
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
8
from core.utilities import round2
9
from decimal import Decimal
10
import plotly.graph_objects as go
11
12
13
####################################################################################################################
14
# PROCEDURES
15
# Step 1: Validate the report data
16
# Step 2: Generate excelexporters file
17
# Step 3: Encode the excelexporters file to Base64
18
####################################################################################################################
19
def export(result, name, reporting_start_datetime_local, reporting_end_datetime_local, language):
20
    ####################################################################################################################
21
    # Step 1: Validate the report data
22
    ####################################################################################################################
23
    if result is None:
24
        return None
25
26
    ####################################################################################################################
27
    # Step 2: Generate excel file from the report data
28
    ####################################################################################################################
29
    filename = generate_excel(result,
30
                              name,
31
                              reporting_start_datetime_local,
32
                              reporting_end_datetime_local,
33
                              language)
34
    ####################################################################################################################
35
    # Step 3: Encode the excel file to Base64
36
    ####################################################################################################################
37
    binary_file_data = b''
38
    try:
39
        with open(filename, 'rb') as binary_file:
40
            binary_file_data = binary_file.read()
41
    except IOError as ex:
42
        print(str(ex))
43
44
    # Base64 encode the bytes
45
    base64_encoded_data = base64.b64encode(binary_file_data)
46
    # get the Base64 encoded data using human-readable characters.
47
    base64_message = base64_encoded_data.decode('utf-8')
48
    # delete the file from server
49
    try:
50
        os.remove(filename)
51
    except NotImplementedError as ex:
52
        print(str(ex))
53
    return base64_message
54
55
56
def generate_excel(report, name, reporting_start_datetime_local, reporting_end_datetime_local, language):
57
58
    trans = get_translation(language)
59
    trans.install()
60
    _ = trans.gettext
61
62
    wb = Workbook()
63
    ws = wb.active
64
    ws.title = "EnergyFlowDiagram"
65
66
    # Energy Flow Diagram Data Structure
67
    nodes = list()
68
    target = list()
69
    values = list()
70
    node_value = list()
71
    source = list()
72
    labels = list()
73
    color = ['rgba(25,202,173, 0.8)', 'rgba(140,199,181, 0.8)', 'rgba(160,238,225, 0.8)', 'rgba(190,231,233, 0.8)',
74
             'rgba(190,237,199,0.8)', 'rgba(109,91,7,0.8)', 'rgba(27,167,4,0.8)', 'rgba(108,234,12,0.8)',
75
             'rgba(202,217,14,0.8)', 'rgba(70,6,12,0.8)', 'rgba(246,10,15,0.8)', 'rgba(240,5,15,0.8)']
76
    node_color_list = list()
77
    for key, node in enumerate(report['nodes']):
78
        nodes.append(node['name'])
79
        node_value.append(Decimal(0.0))
80
        node_color_list.append(color[key % len(color)])
81
    for link in report['links']:
82
        source.append(nodes.index(link['source']))
83
        target.append(nodes.index(link['target']))
84
        link_value = Decimal(link['value']) if link['value'] is not None else Decimal(0.0)
85
        values.append(link_value)
86
        node_value[nodes.index(link['source'])] = node_value[nodes.index(link['source'])] - link_value
87
        node_value[nodes.index(link['target'])] = node_value[nodes.index(link['target'])] + link_value
88
    for key, value in enumerate(nodes):
89
        labels.append(value + ':' + str(node_value[key].copy_abs()))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable str does not seem to be defined.
Loading history...
90
91
    # Row height
92
    ws.row_dimensions[1].height = 102
93
    for i in range(2, 5 + 1):
94
        ws.row_dimensions[i].height = 42
95
96
    for i in range(6, len(report['links']) + 15):
97
        ws.row_dimensions[i].height = 60
98
99
    # Col width
100
    ws.column_dimensions['A'].width = 1.5
101
102
    ws.column_dimensions['B'].width = 25.0
103
104
    for i in range(ord('C'), ord('L')):
105
        ws.column_dimensions[chr(i)].width = 15.0
106
107
    # Font
108
    name_font = Font(name='Arial', size=15, bold=True)
109
    title_font = Font(name='Arial', size=15, bold=True)
110
111
    table_fill = PatternFill(fill_type='solid', fgColor='90ee90')
112
    f_border = Border(left=Side(border_style='medium'),
113
                      right=Side(border_style='medium'),
114
                      bottom=Side(border_style='medium'),
115
                      top=Side(border_style='medium')
116
                      )
117
    b_border = Border(
118
        bottom=Side(border_style='medium'),
119
    )
120
121
    b_c_alignment = Alignment(vertical='bottom',
122
                              horizontal='center',
123
                              text_rotation=0,
124
                              wrap_text=True,
125
                              shrink_to_fit=False,
126
                              indent=0)
127
    c_c_alignment = Alignment(vertical='center',
128
                              horizontal='center',
129
                              text_rotation=0,
130
                              wrap_text=True,
131
                              shrink_to_fit=False,
132
                              indent=0)
133
    b_r_alignment = Alignment(vertical='bottom',
134
                              horizontal='right',
135
                              text_rotation=0,
136
                              wrap_text=True,
137
                              shrink_to_fit=False,
138
                              indent=0)
139
140
    # Img
141
    img = Image("excelexporters/myems.png")
142
    ws.add_image(img, 'A1')
143
144
    # Title
145
    ws['B3'].alignment = b_r_alignment
146
    ws['B3'] = _('Name') + ':'
147
    ws['C3'].border = b_border
148
    ws['C3'].alignment = b_c_alignment
149
    ws['C3'] = name
150
151
    ws['B4'].alignment = b_r_alignment
152
    ws['B4'] = _('Reporting Start Datetime') + ':'
153
    ws['C4'].border = b_border
154
    ws['C4'].alignment = b_c_alignment
155
    ws['C4'] = reporting_start_datetime_local
156
157
    ws['B5'].alignment = b_r_alignment
158
    ws['B5'] = _('Reporting End Datetime') + ':'
159
    ws['C5'].border = b_border
160
    ws['C5'].alignment = b_c_alignment
161
    ws['C5'] = reporting_end_datetime_local
162
163
    # Title
164
    ws['B6'].border = f_border
165
    ws['B6'].font = name_font
166
    ws['B6'].alignment = c_c_alignment
167
    ws['B6'].fill = table_fill
168
    ws['B6'] = _('Name')
169
170
    ws['C6'].border = f_border
171
    ws['C6'].alignment = c_c_alignment
172
    ws['C6'].font = name_font
173
    ws['C6'].fill = table_fill
174
    ws['C6'] = _('Name')
175
176
    ws['D6'].border = f_border
177
    ws['D6'].alignment = c_c_alignment
178
    ws['D6'].font = name_font
179
    ws['D6'].fill = table_fill
180
    ws['D6'] = _('Value')
181
182
    current_row_number = 7
183
    for i in range(0, len(report['links'])):
184
185
        ws['B' + str(current_row_number)].font = title_font
186
        ws['B' + str(current_row_number)].border = f_border
187
        ws['B' + str(current_row_number)].alignment = c_c_alignment
188
        ws['B' + str(current_row_number)] = report['links'][i]['source']
189
190
        ws['C' + str(current_row_number)].font = title_font
191
        ws['C' + str(current_row_number)].border = f_border
192
        ws['C' + str(current_row_number)].alignment = c_c_alignment
193
        ws['C' + str(current_row_number)] = report['links'][i]['target']
194
195
        ws['D' + str(current_row_number)].font = title_font
196
        ws['D' + str(current_row_number)].border = f_border
197
        ws['D' + str(current_row_number)].alignment = c_c_alignment
198
        ws['D' + str(current_row_number)] = round2(report['links'][i]['value'], 2)
199
200
        current_row_number += 1
201
202
    fig = go.Figure(data=[go.Sankey(
203
        valueformat=".0f",
204
        valuesuffix="TWh",
205
        # Define nodes
206
        node=dict(pad=15, thickness=15, line=dict(color="black", width=0.5), label=labels, color=node_color_list),
207
        # Add links
208
        link=dict(source=source, target=target, value=values)
209
    )])
210
211
    fig.update_layout(title_text=name, font_size=10)
212
    
213
    # Save image file
214
    fig.write_image("sankey.png")  
215
216
    # Insert image
217
    img = Image("sankey.png")
218
    ws.add_image(img, 'B' + str(current_row_number))
219
220
    current_row_number += 1
221
222
    filename = str(uuid.uuid4()) + '.xlsx'
223
    wb.save(filename)
224
225
    # Delete image file
226
    os.remove("sankey.png")
227
    return filename
228