Passed
Push — master ( 02289f...d6a19b )
by Guangyu
08:58 queued 15s
created

is_base_period_timestamp_exists()   A

Complexity

Conditions 4

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 8
dl 11
loc 11
rs 10
c 0
b 0
f 0
cc 4
nop 1
1
import base64
2
import gettext
3
import os
4
import re
5
import uuid
6
7
import openpyxl.utils.cell as format_cell
8
from openpyxl import Workbook
9
from openpyxl.chart import PieChart, LineChart, Reference
10
from openpyxl.chart.label import DataLabelList
11
from openpyxl.drawing.image import Image
12
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
13
14
15
####################################################################################################################
16
# PROCEDURES
17
# Step 1: Validate the report data
18
# Step 2: Generate excel file
19
# Step 3: Encode the excel file to Base64
20
####################################################################################################################
21
22
23 View Code Duplication
def export(report,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
24
           name,
25
           base_period_start_datetime_local,
26
           base_period_end_datetime_local,
27
           reporting_start_datetime_local,
28
           reporting_end_datetime_local,
29
           period_type,
30
           language):
31
    ####################################################################################################################
32
    # Step 1: Validate the report data
33
    ####################################################################################################################
34
    if report is None:
35
        return None
36
    print(report)
37
38
    ####################################################################################################################
39
    # Step 2: Generate excel file from the report data
40
    ####################################################################################################################
41
    filename = generate_excel(report,
42
                              name,
43
                              base_period_start_datetime_local,
44
                              base_period_end_datetime_local,
45
                              reporting_start_datetime_local,
46
                              reporting_end_datetime_local,
47
                              period_type,
48
                              language)
49
    ####################################################################################################################
50
    # Step 3: Encode the excel file to Base64
51
    ####################################################################################################################
52
    binary_file_data = b''
53
    try:
54
        with open(filename, 'rb') as binary_file:
55
            binary_file_data = binary_file.read()
56
    except IOError as ex:
57
        print(str(ex))
58
59
    # Base64 encode the bytes
60
    base64_encoded_data = base64.b64encode(binary_file_data)
61
    # get the Base64 encoded data using human-readable characters.
62
    base64_message = base64_encoded_data.decode('utf-8')
63
    # delete the file from server
64
    try:
65
        os.remove(filename)
66
    except NotImplementedError as ex:
67
        print(str(ex))
68
    return base64_message
69
70
71
def generate_excel(report,
72
                   name,
73
                   base_period_start_datetime_local,
74
                   base_period_end_datetime_local,
75
                   reporting_start_datetime_local,
76
                   reporting_end_datetime_local,
77
                   period_type,
78
                   language):
79
    locale_path = './i18n/'
80
    if language == 'zh_CN':
81
        trans = gettext.translation('myems', locale_path, languages=['zh_CN'])
82
    elif language == 'de':
83
        trans = gettext.translation('myems', locale_path, languages=['de'])
84
    elif language == 'en':
85
        trans = gettext.translation('myems', locale_path, languages=['en'])
86
    else:
87
        trans = gettext.translation('myems', locale_path, languages=['en'])
88
    trans.install()
89
    _ = trans.gettext
90
91
    wb = Workbook()
92
    ws = wb.active
93
    ws.title = "SpaceEnergyItem"
94
95
    # Row height
96
    ws.row_dimensions[1].height = 102
97
    for i in range(2, 2000 + 1):
98
        ws.row_dimensions[i].height = 42
99
100
    # Col width
101
    ws.column_dimensions['A'].width = 1.5
102
103
    ws.column_dimensions['B'].width = 25.0
104
105
    for i in range(ord('C'), ord('Z')):
106
        ws.column_dimensions[chr(i)].width = 15.0
107
108
    # Font
109
    name_font = Font(name='Arial', size=15, bold=True)
110
    title_font = Font(name='Arial', size=15, bold=True)
111
112
    table_fill = PatternFill(fill_type='solid', fgColor='90ee90')
113
    f_border = Border(left=Side(border_style='medium'),
114
                      right=Side(border_style='medium'),
115
                      bottom=Side(border_style='medium'),
116
                      top=Side(border_style='medium')
117
                      )
118
    b_border = Border(
119
        bottom=Side(border_style='medium'),
120
    )
121
122
    b_c_alignment = Alignment(vertical='bottom',
123
                              horizontal='center',
124
                              text_rotation=0,
125
                              wrap_text=True,
126
                              shrink_to_fit=False,
127
                              indent=0)
128
    c_c_alignment = Alignment(vertical='center',
129
                              horizontal='center',
130
                              text_rotation=0,
131
                              wrap_text=True,
132
                              shrink_to_fit=False,
133
                              indent=0)
134
    b_r_alignment = Alignment(vertical='bottom',
135
                              horizontal='right',
136
                              text_rotation=0,
137
                              wrap_text=True,
138
                              shrink_to_fit=False,
139
                              indent=0)
140
    # Img
141
    img = Image("excelexporters/myems.png")
142
    ws.add_image(img, 'A1')
143
144
    # Title
145
    ws.row_dimensions[3].height = 60
146
147
    ws['B3'].alignment = b_r_alignment
148
    ws['B3'] = _('Name') + ':'
149
    ws['C3'].border = b_border
150
    ws['C3'].alignment = b_c_alignment
151
    ws['C3'] = name
152
153
    ws['D3'].alignment = b_r_alignment
154
    ws['D3'] = _('Period Type') + ':'
155
    ws['E3'].border = b_border
156
    ws['E3'].alignment = b_c_alignment
157
    ws['E3'] = period_type
158
159
    ws['B4'].alignment = b_r_alignment
160
    ws['B4'] = _('Reporting Start Datetime') + ':'
161
    ws['C4'].border = b_border
162
    ws['C4'].alignment = b_c_alignment
163
    ws['C4'] = reporting_start_datetime_local
164
165
    ws['D4'].alignment = b_r_alignment
166
    ws['D4'] = _('Reporting End Datetime') + ':'
167
    ws['E4'].border = b_border
168
    ws['E4'].alignment = b_c_alignment
169
    ws['E4'] = reporting_end_datetime_local
170
171
    is_base_period_timestamp_exists_flag = is_base_period_timestamp_exists(report['base_period'])
172
173
    if is_base_period_timestamp_exists_flag:
174
        ws['B5'].alignment = b_r_alignment
175
        ws['B5'] = _('Base Period Start Datetime') + ':'
176
        ws['C5'].border = b_border
177
        ws['C5'].alignment = b_c_alignment
178
        ws['C5'] = base_period_start_datetime_local
179
180
        ws['D5'].alignment = b_r_alignment
181
        ws['D5'] = _('Base Period End Datetime') + ':'
182
        ws['E5'].border = b_border
183
        ws['E5'].alignment = b_c_alignment
184
        ws['E5'] = base_period_end_datetime_local
185
186
    if "reporting_period" not in report.keys() or \
187
            "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0:
188
        filename = str(uuid.uuid4()) + '.xlsx'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable str does not seem to be defined.
Loading history...
189
        wb.save(filename)
190
191
        return filename
192
193
    ####################################################################################################################
194
    current_row_number = 7
195
    reporting_period_data = report['reporting_period']
196 View Code Duplication
    if "names" not in reporting_period_data.keys() or \
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
197
            reporting_period_data['names'] is None or \
198
            len(reporting_period_data['names']) == 0:
199
        pass
200
    else:
201
        ws['B' + str(current_row_number)].font = title_font
202
        ws['B' + str(current_row_number)] = name + ' ' + _('Reporting Period Consumption')
203
204
        current_row_number += 1
205
206
        category = reporting_period_data['names']
207
        ca_len = len(category)
208
209
        ws.row_dimensions[current_row_number].height = 60
210
        ws['B' + str(current_row_number)].fill = table_fill
211
        ws['B' + str(current_row_number)].border = f_border
212
213
        col = 'C'
214
215
        for i in range(0, ca_len):
216
            ws[col + str(current_row_number)].fill = table_fill
217
            ws[col + str(current_row_number)].font = name_font
218
            ws[col + str(current_row_number)].alignment = c_c_alignment
219
            ws[col + str(current_row_number)].border = f_border
220
            ws[col + str(current_row_number)] = \
221
                reporting_period_data['names'][i] + " " + reporting_period_data['energy_category_names'][i] + \
222
                " (" + reporting_period_data['units'][i] + ")"
223
224
            col = chr(ord(col) + 1)
225
226
        current_row_number += 1
227
228
        ws['B' + str(current_row_number)].font = title_font
229
        ws['B' + str(current_row_number)].alignment = c_c_alignment
230
        ws['B' + str(current_row_number)].border = f_border
231
        ws['B' + str(current_row_number)] = _('Consumption')
232
233
        col = 'C'
234
235
        for i in range(0, ca_len):
236
            ws[col + str(current_row_number)].font = name_font
237
            ws[col + str(current_row_number)].alignment = c_c_alignment
238
            ws[col + str(current_row_number)].border = f_border
239
            ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
240
241
            col = chr(ord(col) + 1)
242
243
        current_row_number += 1
244
245
        ws['B' + str(current_row_number)].font = title_font
246
        ws['B' + str(current_row_number)].alignment = c_c_alignment
247
        ws['B' + str(current_row_number)].border = f_border
248
        ws['B' + str(current_row_number)] = _('Per Unit Area')
249
250
        col = 'C'
251
252
        for i in range(0, ca_len):
253
            ws[col + str(current_row_number)].font = name_font
254
            ws[col + str(current_row_number)].alignment = c_c_alignment
255
            ws[col + str(current_row_number)].border = f_border
256
            ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_per_unit_area'][i], 2)
257
258
            col = chr(ord(col) + 1)
259
260
        current_row_number += 1
261
262
        ws['B' + str(current_row_number)].font = title_font
263
        ws['B' + str(current_row_number)].alignment = c_c_alignment
264
        ws['B' + str(current_row_number)].border = f_border
265
        ws['B' + str(current_row_number)] = _('Increment Rate')
266
267
        col = 'C'
268
269
        for i in range(0, ca_len):
270
            ws[col + str(current_row_number)].font = name_font
271
            ws[col + str(current_row_number)].alignment = c_c_alignment
272
            ws[col + str(current_row_number)].border = f_border
273
            ws[col + str(current_row_number)] = str(
274
                round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \
275
                if reporting_period_data['increment_rates'][i] is not None else '-'
276
277
            col = chr(ord(col) + 1)
278
279
        current_row_number += 2
280
281
        category_dict = group_by_category(reporting_period_data['energy_category_names'])
282
283
        for category_dict_name, category_dict_values in category_dict.items():
284
285
            ws['B' + str(current_row_number)].font = title_font
286
            ws['B' + str(current_row_number)] = name + ' ' + category_dict_name + ' ' + \
287
                '(' + reporting_period_data['units'][category_dict_values[0]] + ') by Energy Item'
288
289
            current_row_number += 1
290
            table_start_row_number = current_row_number
291
292
            ws['B' + str(current_row_number)].fill = table_fill
293
            ws['B' + str(current_row_number)].border = f_border
294
295
            ws['C' + str(current_row_number)].font = name_font
296
            ws['C' + str(current_row_number)].fill = table_fill
297
            ws['C' + str(current_row_number)].alignment = c_c_alignment
298
            ws['C' + str(current_row_number)].border = f_border
299
            ws['C' + str(current_row_number)] = _('Consumption')
300
301
            current_row_number += 1
302
303
            for i in category_dict_values:
304
                ws['B' + str(current_row_number)].font = title_font
305
                ws['B' + str(current_row_number)].alignment = c_c_alignment
306
                ws['B' + str(current_row_number)].border = f_border
307
                ws['B' + str(current_row_number)] = \
308
                    reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
309
                ws['C' + str(current_row_number)].font = name_font
310
                ws['C' + str(current_row_number)].alignment = c_c_alignment
311
                ws['C' + str(current_row_number)].border = f_border
312
                ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 3)
313
314
                current_row_number += 1
315
316
            table_end_row_number = current_row_number - 1
317
318
            pie = PieChart()
319
            pie.title = name + ' ' + category_dict_name + ' ' + \
320
                '(' + reporting_period_data['units'][category_dict_values[0]] + ') by Energy Item'
321
            labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
322
            pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
323
            pie.add_data(pie_data, titles_from_data=True)
324
            pie.set_categories(labels)
325
            pie.height = 6.6
326
            pie.width = 9
327
            s1 = pie.series[0]
328
            s1.dLbls = DataLabelList()
329
            s1.dLbls.showCatName = False
330
            s1.dLbls.showVal = True
331
            s1.dLbls.showPercent = True
332
            ws.add_chart(pie, 'D' + str(table_start_row_number))
333
334
            if len(category_dict_values) < 4:
335
                current_row_number = current_row_number - len(category_dict_values) + 4
336
337
            current_row_number += 1
338
339
    ####################################################################################################################
340
    chart_start_row_number = current_row_number
341
342
    has_values_data = True
343
    has_timestamps_data = True
344
345
    if 'values' not in reporting_period_data.keys() or \
346
            reporting_period_data['values'] is None or \
347
            len(reporting_period_data['values']) == 0:
348
        has_values_data = False
349
350
    if 'timestamps' not in reporting_period_data.keys() or \
351
            reporting_period_data['timestamps'] is None or \
352
            len(reporting_period_data['timestamps']) == 0 or \
353
            len(reporting_period_data['timestamps'][0]) == 0:
354
        has_timestamps_data = False
355
356
    if not is_base_period_timestamp_exists_flag:
357
        if has_values_data and has_timestamps_data:
358
            ca_len = len(reporting_period_data['names'])
359
            time = reporting_period_data['timestamps'][0]
360
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
361
            ws['B' + str(current_row_number)].font = title_font
362
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
363
364
            current_row_number += 1
365
366
            chart_start_row_number = current_row_number
367
368
            # 1: Stand for blank line  2: Stand for title
369
            current_row_number += ca_len * 6 + real_timestamps_len * 6 + 1 + 2
370
            table_start_row_number = current_row_number
371
372
            ws.row_dimensions[current_row_number].height = 60
373
            ws['B' + str(current_row_number)].fill = table_fill
374
            ws['B' + str(current_row_number)].font = title_font
375
            ws['B' + str(current_row_number)].alignment = c_c_alignment
376
            ws['B' + str(current_row_number)].border = f_border
377
            ws['B' + str(current_row_number)] = _('Datetime')
378
379
            col = 'C'
380
381
            for i in range(0, ca_len):
382
                ws[col + str(current_row_number)].fill = table_fill
383
                ws[col + str(current_row_number)].font = title_font
384
                ws[col + str(current_row_number)].alignment = c_c_alignment
385
                ws[col + str(current_row_number)].border = f_border
386
                ws[col + str(current_row_number)] = \
387
                    reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
388
                col = chr(ord(col) + 1)
389
390
            current_row_number += 1
391
392
            for i in range(0, len(time)):
393
                ws['B' + str(current_row_number)].font = title_font
394
                ws['B' + str(current_row_number)].alignment = c_c_alignment
395
                ws['B' + str(current_row_number)].border = f_border
396
                ws['B' + str(current_row_number)] = time[i]
397
398
                col = 'C'
399
                for j in range(0, ca_len):
400
                    ws[col + str(current_row_number)].font = title_font
401
                    ws[col + str(current_row_number)].alignment = c_c_alignment
402
                    ws[col + str(current_row_number)].border = f_border
403
                    ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \
404
                        if reporting_period_data['values'][j][i] is not None else 0.00
405
                    col = chr(ord(col) + 1)
406
407
                current_row_number += 1
408
409
            table_end_row_number = current_row_number - 1
410
411
            ws['B' + str(current_row_number)].font = title_font
412
            ws['B' + str(current_row_number)].alignment = c_c_alignment
413
            ws['B' + str(current_row_number)].border = f_border
414
            ws['B' + str(current_row_number)] = _('Subtotal')
415
416
            col = 'C'
417
418
            for i in range(0, ca_len):
419
                ws[col + str(current_row_number)].font = title_font
420
                ws[col + str(current_row_number)].alignment = c_c_alignment
421
                ws[col + str(current_row_number)].border = f_border
422
                ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
423
                col = chr(ord(col) + 1)
424
425
            current_row_number += 2
426
427
            for i in range(0, ca_len):
428
                line = LineChart()
429
                line.title = _('Reporting Period Consumption') + ' - ' \
430
                    + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
431
                labels = Reference(ws, min_col=2,
432
                                   min_row=table_start_row_number + 1,
433
                                   max_row=table_end_row_number)
434
                reporting_line_data = Reference(ws, min_col=3 + i,
435
                                                min_row=table_start_row_number,
436
                                                max_row=table_end_row_number)
437
                line.add_data(reporting_line_data, titles_from_data=True)
438
                line.set_categories(labels)
439
                reporting_line_data = line.series[0]
440
                reporting_line_data.marker.symbol = "circle"
441
                reporting_line_data.smooth = True
442
                line.x_axis.crosses = 'min'
443
                line.height = 8.25
444
                line.width = 24
445
                line.dLbls = DataLabelList()
446
                line.dLbls.dLblPos = 't'
447
                line.dLbls.showVal = True
448
                line.dLbls.showPercent = False
449
                chart_col = 'B'
450
                chart_cell = chart_col + str(chart_start_row_number)
451
                chart_start_row_number += 6
452
                ws.add_chart(line, chart_cell)
453
454
    else:
455
        if has_values_data and has_timestamps_data:
456
            base_period_data = report['base_period']
457
            reporting_period_data = report['reporting_period']
458
            base_period_timestamps = base_period_data['timestamps']
459
            reporting_period_timestamps = reporting_period_data['timestamps']
460
            # Tip:
461
            #     base_period_data['names'] == reporting_period_data['names']
462
            #     base_period_data['units'] == reporting_period_data['units']
463
            base_period_data_ca_len = len(base_period_data['names'])
464
            reporting_period_data_ca_len = len(reporting_period_data['names'])
465
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
466
            ws['B' + str(current_row_number)].font = title_font
467
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
468
            current_row_number += 1
469
470
            chart_start_row_number = current_row_number
471
472
            # 1: Stand for blank line  2: Stand for title
473
            current_row_number += reporting_period_data_ca_len * 6 + real_timestamps_len * 6 + 1 + 2
474
            table_start_row_number = current_row_number
475
476
            ws.row_dimensions[current_row_number].height = 60
477
            current_col_number = 2
478
            col = format_cell.get_column_letter(current_col_number)
479
            ws[col + str(current_row_number)].fill = table_fill
480
            ws[col + str(current_row_number)].font = title_font
481
            ws[col + str(current_row_number)].alignment = c_c_alignment
482
            ws[col + str(current_row_number)].border = f_border
483
            ws[col + str(current_row_number)] = _('Base Period') + " - " + _('Datetime')
484
485
            for i in range(0, base_period_data_ca_len):
486
                current_col_number += 1
487
                col = format_cell.get_column_letter(current_col_number)
488
489
                ws[col + str(current_row_number)].fill = table_fill
490
                ws[col + str(current_row_number)].font = title_font
491
                ws[col + str(current_row_number)].alignment = c_c_alignment
492
                ws[col + str(current_row_number)] = _('Base Period') + " - " + base_period_data['names'][i] + \
493
                    " (" + base_period_data['units'][i] + ")"
494
                ws[col + str(current_row_number)].border = f_border
495
496
            current_col_number += 1
497
            col = format_cell.get_column_letter(current_col_number)
498
499
            ws[col + str(current_row_number)].fill = table_fill
500
            ws[col + str(current_row_number)].font = title_font
501
            ws[col + str(current_row_number)].border = f_border
502
            ws[col + str(current_row_number)].alignment = c_c_alignment
503
            ws[col + str(current_row_number)] = _('Reporting Period') + " - " + _('Datetime')
504
505
            for i in range(0, reporting_period_data_ca_len):
506
                current_col_number += 1
507
                col = format_cell.get_column_letter(current_col_number)
508
                ws[col + str(current_row_number)].fill = table_fill
509
                ws[col + str(current_row_number)].font = title_font
510
                ws[col + str(current_row_number)].alignment = c_c_alignment
511
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
512
                    + reporting_period_data['names'][i] + " (" + \
513
                    reporting_period_data['units'][i] + ")"
514
                ws[col + str(current_row_number)].border = f_border
515
516
            current_row_number += 1
517
518
            max_timestamps_len = len(base_period_timestamps[0]) \
519
                if len(base_period_timestamps[0]) >= len(reporting_period_timestamps[0]) \
520
                else len(reporting_period_timestamps[0])
521
522
            for i in range(0, max_timestamps_len):
523
                current_col_number = 2
524
                col = format_cell.get_column_letter(current_col_number)
525
                ws[col + str(current_row_number)].font = title_font
526
                ws[col + str(current_row_number)].alignment = c_c_alignment
527
                ws[col + str(current_row_number)] = base_period_timestamps[0][i] \
528
                    if i < len(base_period_timestamps[0]) else None
529
                ws[col + str(current_row_number)].border = f_border
530
531
                for j in range(0, base_period_data_ca_len):
532
                    current_col_number += 1
533
                    col = format_cell.get_column_letter(current_col_number)
534
535
                    ws[col + str(current_row_number)].font = title_font
536
                    ws[col + str(current_row_number)].alignment = c_c_alignment
537
                    ws[col + str(current_row_number)] = round(base_period_data['values'][j][i], 2) \
538
                        if i < len(base_period_data['values'][j]) else None
539
                    ws[col + str(current_row_number)].border = f_border
540
                current_col_number += 1
541
                col = format_cell.get_column_letter(current_col_number)
542
543
                ws[col + str(current_row_number)].font = title_font
544
                ws[col + str(current_row_number)].alignment = c_c_alignment
545
                ws[col + str(current_row_number)] = reporting_period_timestamps[0][i] \
546
                    if i < len(reporting_period_timestamps[0]) else None
547
                ws[col + str(current_row_number)].border = f_border
548
549
                for j in range(0, reporting_period_data_ca_len):
550
                    current_col_number += 1
551
                    col = format_cell.get_column_letter(current_col_number)
552
553
                    ws[col + str(current_row_number)].font = title_font
554
                    ws[col + str(current_row_number)].alignment = c_c_alignment
555
                    ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \
556
                        if i < len(reporting_period_data['values'][j]) else None
557
                    ws[col + str(current_row_number)].border = f_border
558
559
                current_row_number += 1
560
561
            current_col_number = 2
562
            col = format_cell.get_column_letter(current_col_number)
563
564
            ws[col + str(current_row_number)].font = title_font
565
            ws[col + str(current_row_number)].alignment = c_c_alignment
566
            ws[col + str(current_row_number)] = _('Subtotal')
567
            ws[col + str(current_row_number)].border = f_border
568
569
            for i in range(0, base_period_data_ca_len):
570
                current_col_number += 1
571
                col = format_cell.get_column_letter(current_col_number)
572
                ws[col + str(current_row_number)].font = title_font
573
                ws[col + str(current_row_number)].alignment = c_c_alignment
574
                ws[col + str(current_row_number)] = round(base_period_data['subtotals'][i], 2)
575
                ws[col + str(current_row_number)].border = f_border
576
577
            current_col_number += 1
578
            col = format_cell.get_column_letter(current_col_number)
579
580
            ws[col + str(current_row_number)].font = title_font
581
            ws[col + str(current_row_number)].alignment = c_c_alignment
582
            ws[col + str(current_row_number)] = _('Subtotal')
583
            ws[col + str(current_row_number)].border = f_border
584
585
            for i in range(0, reporting_period_data_ca_len):
586
                col = chr(ord(col) + 1)
587
                ws[col + str(current_row_number)].font = title_font
588
                ws[col + str(current_row_number)].alignment = c_c_alignment
589
                ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
590
                ws[col + str(current_row_number)].border = f_border
591
592
            current_row_number += 2
593
594
            for i in range(0, reporting_period_data_ca_len):
595
                line = LineChart()
596
                line.title = _('Base Period Consumption') + ' / ' \
597
                    + _('Reporting Period Consumption') + ' - '  \
598
                    + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
599
                labels = Reference(ws, min_col=2 + base_period_data_ca_len + 1,
600
                                   min_row=table_start_row_number + 1,
601
                                   max_row=table_start_row_number + len(reporting_period_timestamps[0]))
602
                base_line_data = Reference(ws, min_col=3 + i,
603
                                           min_row=table_start_row_number,
604
                                           max_row=table_start_row_number + len(reporting_period_timestamps[0]))
605
                reporting_line_data = Reference(ws, min_col=3 + base_period_data_ca_len + 1 + i,
606
                                                min_row=table_start_row_number,
607
                                                max_row=table_start_row_number + len(reporting_period_timestamps[0]))
608
                line.add_data(base_line_data, titles_from_data=True)
609
                line.add_data(reporting_line_data, titles_from_data=True)
610
                line.set_categories(labels)
611
                for j in range(len(line.series)):
612
                    line.series[j].marker.symbol = "circle"
613
                    line.series[j].smooth = True
614
                line.x_axis.crosses = 'min'
615
                line.height = 8.25
616
                line.width = 24
617
                line.dLbls = DataLabelList()
618
                line.dLbls.dLblPos = 't'
619
                line.dLbls.showVal = True
620
                line.dLbls.showPercent = False
621
                chart_col = 'B'
622
                chart_cell = chart_col + str(chart_start_row_number)
623
                chart_start_row_number += 6
624
                ws.add_chart(line, chart_cell)
625
626
    ####################################################################################################################
627
    if "child_space" not in report.keys() or "energy_item_names" not in report['child_space'].keys() or \
628
            len(report['child_space']["energy_item_names"]) == 0 \
629
            or 'child_space_names_array' not in report['child_space'].keys() \
630
            or report['child_space']['child_space_names_array'] is None \
631
            or len(report['child_space']['child_space_names_array']) == 0 \
632
            or len(report['child_space']['child_space_names_array'][0]) == 0:
633
        pass
634
    else:
635
        child = report['child_space']
636
637
        ws['B' + str(current_row_number)].font = title_font
638
        ws['B' + str(current_row_number)] = name + ' ' + _('Child Spaces Data')
639
640
        current_row_number += 1
641
        table_start_row_number = current_row_number
642
643
        ws.row_dimensions[current_row_number].height = 60
644
        ws['B' + str(current_row_number)].fill = table_fill
645
        ws['B' + str(current_row_number)].font = name_font
646
        ws['B' + str(current_row_number)].alignment = c_c_alignment
647
        ws['B' + str(current_row_number)].border = f_border
648
        ws['B' + str(current_row_number)] = _('Child Space')
649
        ca_len = len(child['energy_item_names'])
650
651
        for i in range(0, ca_len):
652
            row = chr(ord('C') + i)
653
            ws[row + str(current_row_number)].fill = table_fill
654
            ws[row + str(current_row_number)].font = name_font
655
            ws[row + str(current_row_number)].alignment = c_c_alignment
656
            ws[row + str(current_row_number)].border = f_border
657
            ws[row + str(current_row_number)] = \
658
                reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
659
660
        space_len = len(child['child_space_names_array'][0])
661
662
        for i in range(0, space_len):
663
            current_row_number += 1
664
            row = str(current_row_number)
665
666
            ws['B' + row].font = title_font
667
            ws['B' + row].alignment = c_c_alignment
668
            ws['B' + row] = child['child_space_names_array'][0][i]
669
            ws['B' + row].border = f_border
670
671
            for j in range(0, ca_len):
672
                col = chr(ord('C') + j)
673
                ws[col + row].font = name_font
674
                ws[col + row].alignment = c_c_alignment
675
                ws[col + row] = round(child['subtotals_array'][j][i], 2)
676
                ws[col + row].border = f_border
677
678
        table_end_row_number = current_row_number
679
        current_row_number += 1
680
        pie_start_row_number = current_row_number
681
682
        # Pie
683
        for i in range(0, ca_len):
684
            pie = PieChart()
685
            labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1,
686
                               max_row=table_end_row_number)
687
            pie_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
688
                                 max_row=table_end_row_number)
689
            pie.add_data(pie_data, titles_from_data=True)
690
            pie.set_categories(labels)
691
            pie.height = 6.6
692
            pie.width = 8
693
            pie.title = ws.cell(column=3 + i, row=table_start_row_number).value
694
            s1 = pie.series[0]
695
            s1.dLbls = DataLabelList()
696
            s1.dLbls.showCatName = False
697
            s1.dLbls.showVal = True
698
            s1.dLbls.showPercent = True
699
            if i % 2 == 0:
700
                chart_cell = 'B' + str(pie_start_row_number)
701
            else:
702
                chart_cell = 'E' + str(pie_start_row_number)
703
                pie_start_row_number += 5
704
            ws.add_chart(pie, chart_cell)
705
706
        current_row_number = pie_start_row_number
707
        if ca_len % 2 == 1:
708
            current_row_number += 5
709
710
        current_row_number += 1
711
    ####################################################################################################################
712
    current_sheet_parameters_row_number = chart_start_row_number + 1
713
    if 'parameters' not in report.keys() or \
714
            report['parameters'] is None or \
715
            'names' not in report['parameters'].keys() or \
716
            report['parameters']['names'] is None or \
717
            len(report['parameters']['names']) == 0 or \
718
            'timestamps' not in report['parameters'].keys() or \
719
            report['parameters']['timestamps'] is None or \
720
            len(report['parameters']['timestamps']) == 0 or \
721
            'values' not in report['parameters'].keys() or \
722
            report['parameters']['values'] is None or \
723
            len(report['parameters']['values']) == 0 or \
724
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
725
        pass
726
    else:
727
        ################################################################################################################
728
        # new worksheet
729
        ################################################################################################################
730
731
        parameters_data = report['parameters']
732
        parameters_names_len = len(parameters_data['names'])
733
734
        file_name = "Space"+re.sub(r'[^A-Z]', '', ws.title.strip('S')) + "_"
735
        parameters_ws = wb.create_sheet(file_name + _('Parameters'))
736
737
        parameters_timestamps_data_max_len = \
738
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
739
740
        # Row height
741
        parameters_ws.row_dimensions[1].height = 102
742
        for i in range(2, 7 + 1):
743
            parameters_ws.row_dimensions[i].height = 42
744
745
        for i in range(8, parameters_timestamps_data_max_len + 10):
746
            parameters_ws.row_dimensions[i].height = 60
747
748
        # Col width
749
        parameters_ws.column_dimensions['A'].width = 1.5
750
751
        parameters_ws.column_dimensions['B'].width = 25.0
752
753
        for i in range(3, 12 + parameters_names_len * 3):
754
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
755
756
        # Img
757
        img = Image("excelexporters/myems.png")
758
        parameters_ws.add_image(img, 'A1')
759
760
        # Title
761
        parameters_ws['B3'].alignment = b_r_alignment
762
        parameters_ws['B3'] = _('Name') + ':'
763
        parameters_ws['C3'].border = b_border
764
        parameters_ws['C3'].alignment = b_c_alignment
765
        parameters_ws['C3'] = name
766
767
        parameters_ws['D3'].alignment = b_r_alignment
768
        parameters_ws['D3'] = _('Period Type') + ':'
769
        parameters_ws['E3'].border = b_border
770
        parameters_ws['E3'].alignment = b_c_alignment
771
        parameters_ws['E3'] = period_type
772
773
        parameters_ws['B4'].alignment = b_r_alignment
774
        parameters_ws['B4'] = _('Reporting Start Datetime') + ':'
775
        parameters_ws['C4'].border = b_border
776
        parameters_ws['C4'].alignment = b_c_alignment
777
        parameters_ws['C4'] = reporting_start_datetime_local
778
779
        parameters_ws['D4'].alignment = b_r_alignment
780
        parameters_ws['D4'] = _('Reporting End Datetime') + ':'
781
        parameters_ws['E4'].border = b_border
782
        parameters_ws['E4'].alignment = b_c_alignment
783
        parameters_ws['E4'] = reporting_end_datetime_local
784
785
        parameters_ws_current_row_number = 6
786
787
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
788
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + _('Parameters')
789
790
        parameters_ws_current_row_number += 1
791
792
        parameters_table_start_row_number = parameters_ws_current_row_number
793
794
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
795
796
        parameters_ws_current_row_number += 1
797
798
        table_current_col_number = 2
799
800
        for i in range(0, parameters_names_len):
801
802
            if len(parameters_data['timestamps'][i]) == 0:
803
                continue
804
805
            col = format_cell.get_column_letter(table_current_col_number)
806
807
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
808
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
809
810
            col = format_cell.get_column_letter(table_current_col_number + 1)
811
812
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
813
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
814
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
815
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
816
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
817
818
            table_current_row_number = parameters_ws_current_row_number
819
820
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
821
                col = format_cell.get_column_letter(table_current_col_number)
822
823
                parameters_ws[col + str(table_current_row_number)].border = f_border
824
                parameters_ws[col + str(table_current_row_number)].font = title_font
825
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
826
                parameters_ws[col + str(table_current_row_number)] = value
827
828
                col = format_cell.get_column_letter(table_current_col_number + 1)
829
830
                parameters_ws[col + str(table_current_row_number)].border = f_border
831
                parameters_ws[col + str(table_current_row_number)].font = title_font
832
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
833
                parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
834
835
                table_current_row_number += 1
836
837
            table_current_col_number = table_current_col_number + 3
838
839
        ################################################################################################################
840
        # parameters chart and parameters table
841
        ################################################################################################################
842
843
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
844
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + _('Parameters')
845
846
        current_sheet_parameters_row_number += 1
847
848
        chart_start_row_number = current_sheet_parameters_row_number
849
850
        col_index = 0
851
852
        for i in range(0, parameters_names_len):
853
854
            if len(parameters_data['timestamps'][i]) == 0:
855
                continue
856
857
            line = LineChart()
858
            data_col = 3 + col_index * 3
859
            labels_col = 2 + col_index * 3
860
            col_index += 1
861
            line.title = _('Parameters') + ' - ' + \
862
                parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
863
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
864
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
865
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
866
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
867
            line.add_data(line_data, titles_from_data=True)
868
            line.set_categories(labels)
869
            line_data = line.series[0]
870
            line_data.marker.symbol = "circle"
871
            line_data.smooth = True
872
            line.x_axis.crosses = 'min'
873
            line.height = 8.25
874
            line.width = 24
875
            line.dLbls = DataLabelList()
876
            line.dLbls.dLblPos = 't'
877
            line.dLbls.showVal = False
878
            line.dLbls.showPercent = False
879
            chart_col = 'B'
880
            chart_cell = chart_col + str(chart_start_row_number)
881
            chart_start_row_number += 6
882
            ws.add_chart(line, chart_cell)
883
884
        current_sheet_parameters_row_number = chart_start_row_number
885
886
        current_sheet_parameters_row_number += 1
887
    ####################################################################################################################
888
    filename = str(uuid.uuid4()) + '.xlsx'
889
    wb.save(filename)
890
891
    return filename
892
893
894
def group_by_category(category_list):
895
    category_dict = dict()
896
    for i, value in enumerate(category_list):
897
        if value not in category_dict.keys():
898
            category_dict[value] = list()
899
        category_dict[value].append(i)
900
    return category_dict
901
902
903
def timestamps_data_all_equal_0(lists):
904
    for i, value in enumerate(list(lists)):
905
        if len(value) > 0:
906
            return False
907
908
    return True
909
910
911
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
912
    max_len = 0
913
    for i, value in enumerate(list(parameters_timestamps_lists)):
914
        if len(value) > max_len:
915
            max_len = len(value)
916
917
    return max_len
918
919
920
def timestamps_data_not_equal_0(lists):
921
    number = 0
922
    for i, value in enumerate(list(lists)):
923
        if len(value) > 0:
924
            number += 1
925
    return number
926
927
928 View Code Duplication
def is_base_period_timestamp_exists(base_period_data):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
929
    timestamps = base_period_data['timestamps']
930
931
    if len(timestamps) == 0:
932
        return False
933
934
    for timestamp in timestamps:
935
        if len(timestamp) > 0:
936
            return True
937
938
    return False
939