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

excelexporters.spaceenergyitem.export()   B

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
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