timestamps_data_not_equal_0()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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