excelexporters.spaceenergyitem.export()   B
last analyzed

Complexity

Conditions 5

Size

Total Lines 46
Code Lines 32

Duplication

Lines 46
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 32
dl 46
loc 46
rs 8.6453
c 0
b 0
f 0
cc 5
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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