Issues (1577)

myems-api/excelexporters/spacecarbon.py (4 issues)

1
import base64
2
from core.utilities import get_translation
3
import os
4
import re
5
import uuid
6
from decimal import Decimal
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
from core.utilities import round2
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
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 View Code Duplication
def generate_excel(report,
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
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
    trans = get_translation(language)
80
    trans.install()
81
    _ = trans.gettext
82
83
    wb = Workbook()
84
    ws = wb.active
85
    ws.title = "SpaceCarbon"
86
87
    # Row height
88
    ws.row_dimensions[1].height = 102
89
    for i in range(2, 2000 + 1):
90
        ws.row_dimensions[i].height = 42
91
92
    # Col width
93
    ws.column_dimensions['A'].width = 1.5
94
95
    ws.column_dimensions['B'].width = 25.0
96
97
    for i in range(ord('C'), ord('Z')):
98
        ws.column_dimensions[chr(i)].width = 15.0
99
100
    # Font
101
    name_font = Font(name='Arial', size=15, bold=True)
102
    title_font = Font(name='Arial', size=15, bold=True)
103
104
    table_fill = PatternFill(fill_type='solid', fgColor='90ee90')
105
    f_border = Border(left=Side(border_style='medium'),
106
                      right=Side(border_style='medium'),
107
                      bottom=Side(border_style='medium'),
108
                      top=Side(border_style='medium')
109
                      )
110
    b_border = Border(
111
        bottom=Side(border_style='medium'),
112
    )
113
114
    b_c_alignment = Alignment(vertical='bottom',
115
                              horizontal='center',
116
                              text_rotation=0,
117
                              wrap_text=True,
118
                              shrink_to_fit=False,
119
                              indent=0)
120
    c_c_alignment = Alignment(vertical='center',
121
                              horizontal='center',
122
                              text_rotation=0,
123
                              wrap_text=True,
124
                              shrink_to_fit=False,
125
                              indent=0)
126
    b_r_alignment = Alignment(vertical='bottom',
127
                              horizontal='right',
128
                              text_rotation=0,
129
                              wrap_text=True,
130
                              shrink_to_fit=False,
131
                              indent=0)
132
133
    # Img
134
    img = Image("excelexporters/myems.png")
135
    ws.add_image(img, 'A1')
136
137
    # Title
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
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
        for i in range(7, 11 + 1):
191
            ws.row_dimensions[i].height = 0.1
192
    else:
193
        ws['B7'].font = title_font
194
        ws['B7'] = name + ' ' + _('Reporting Period Carbon Dioxide Emissions')
195
196
        category = reporting_period_data['names']
197
        ca_len = len(category)
198
199
        ws.row_dimensions[8].height = 60
200
        ws['B8'].fill = table_fill
201
        ws['B8'].border = f_border
202
203
        ws['B9'].font = title_font
204
        ws['B9'].alignment = c_c_alignment
205
        ws['B9'] = _('Carbon Dioxide Emissions')
206
        ws['B9'].border = f_border
207
208
        ws['B10'].font = title_font
209
        ws['B10'].alignment = c_c_alignment
210
        ws['B10'] = _('Per Unit Area')
211
        ws['B10'].border = f_border
212
213
        ws['B11'].font = title_font
214
        ws['B11'].alignment = c_c_alignment
215
        ws['B11'] = _('Increment Rate')
216
        ws['B11'].border = f_border
217
218
        col = ''
219
220
        for i in range(0, ca_len):
221
            col = chr(ord('C') + i)
222
223
            ws[col + '8'].fill = table_fill
224
            ws[col + '8'].font = name_font
225
            ws[col + '8'].alignment = c_c_alignment
226
            ws[col + '8'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
227
            ws[col + '8'].border = f_border
228
229
            ws[col + '9'].font = name_font
230
            ws[col + '9'].alignment = c_c_alignment
231
            ws[col + '9'] = round2(reporting_period_data['subtotals'][i], 2)
232
            ws[col + '9'].border = f_border
233
234
            ws[col + '10'].font = name_font
235
            ws[col + '10'].alignment = c_c_alignment
236
            ws[col + '10'] = round2(reporting_period_data['subtotals_per_unit_area'][i], 2)
237
            ws[col + '10'].border = f_border
238
239
            ws[col + '11'].font = name_font
240
            ws[col + '11'].alignment = c_c_alignment
241
            ws[col + '11'] = str(round2(reporting_period_data['increment_rates'][i] * 100, 2)) + "%" \
242
                if reporting_period_data['increment_rates'][i] is not None else "-"
243
            ws[col + '11'].border = f_border
244
245
        col = chr(ord(col) + 1)
246
247
        ws[col + '8'].fill = table_fill
248
        ws[col + '8'].font = name_font
249
        ws[col + '8'].alignment = c_c_alignment
250
        ws[col + '8'] = _('Total') + "(" + reporting_period_data['total_unit'] + ")"
251
        ws[col + '8'].border = f_border
252
253
        ws[col + '9'].font = name_font
254
        ws[col + '9'].alignment = c_c_alignment
255
        ws[col + '9'] = round2(reporting_period_data['total'], 2)
256
        ws[col + '9'].border = f_border
257
258
        ws[col + '10'].font = name_font
259
        ws[col + '10'].alignment = c_c_alignment
260
        ws[col + '10'] = round2(reporting_period_data['total_per_unit_area'], 2)
261
        ws[col + '10'].border = f_border
262
263
        ws[col + '11'].font = name_font
264
        ws[col + '11'].alignment = c_c_alignment
265
        ws[col + '11'] = str(round2(reporting_period_data['total_increment_rate'] * 100, 2)) + "%" \
266
            if reporting_period_data['total_increment_rate'] is not None else "-"
267
        ws[col + '11'].border = f_border
268
269
    ####################################################################################################################
270
    if "toppeaks" not in reporting_period_data.keys() or \
271
            reporting_period_data['toppeaks'] is None or \
272
            len(reporting_period_data['toppeaks']) == 0:
273
        for i in range(13, 19 + 1):
274
            ws.row_dimensions[i].height = 0.1
275
    else:
276
        electricity_index = -1
277
        for i in range(len(reporting_period_data['energy_category_ids'])):
278
            if reporting_period_data['energy_category_ids'][i] == 1:
279
                electricity_index = i
280
                break
281
282
        ws['B13'].font = title_font
283
        ws['B13'] = name + ' ' + _('Electricity Carbon Dioxide Emissions by Time-Of-Use')
284
285
        ws.row_dimensions[14].height = 60
286
        ws['B14'].fill = table_fill
287
        ws['B14'].font = name_font
288
        ws['B14'].alignment = c_c_alignment
289
        ws['B14'].border = f_border
290
291
        ws['C14'].fill = table_fill
292
        ws['C14'].font = name_font
293
        ws['C14'].alignment = c_c_alignment
294
        ws['C14'].border = f_border
295
        ws['C14'] = _('Electricity Carbon Dioxide Emissions by Time-Of-Use')
296
297
        ws['B15'].font = title_font
298
        ws['B15'].alignment = c_c_alignment
299
        ws['B15'] = _('TopPeak')
300
        ws['B15'].border = f_border
301
302
        ws['C15'].font = title_font
303
        ws['C15'].alignment = c_c_alignment
304
        ws['C15'].border = f_border
305
        ws['C15'] = round2(reporting_period_data['toppeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
306
307
        ws['B16'].font = title_font
308
        ws['B16'].alignment = c_c_alignment
309
        ws['B16'] = _('OnPeak')
310
        ws['B16'].border = f_border
311
312
        ws['C16'].font = title_font
313
        ws['C16'].alignment = c_c_alignment
314
        ws['C16'].border = f_border
315
        ws['C16'] = round2(reporting_period_data['onpeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
316
317
        ws['B17'].font = title_font
318
        ws['B17'].alignment = c_c_alignment
319
        ws['B17'] = _('MidPeak')
320
        ws['B17'].border = f_border
321
322
        ws['C17'].font = title_font
323
        ws['C17'].alignment = c_c_alignment
324
        ws['C17'].border = f_border
325
        ws['C17'] = round2(reporting_period_data['midpeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
326
327
        ws['B18'].font = title_font
328
        ws['B18'].alignment = c_c_alignment
329
        ws['B18'] = _('OffPeak')
330
        ws['B18'].border = f_border
331
332
        ws['C18'].font = title_font
333
        ws['C18'].alignment = c_c_alignment
334
        ws['C18'].border = f_border
335
        ws['C18'] = round2(reporting_period_data['offpeaks'][electricity_index], 2) if electricity_index >= 0 else "-"
336
337
        pie = PieChart()
338
        pie.title = name + _('Electricity Carbon Dioxide Emissions by Time-Of-Use')
339
        labels = Reference(ws, min_col=2, min_row=15, max_row=18)
340
        pie_data = Reference(ws, min_col=3, min_row=14, max_row=18)
341
        pie.add_data(pie_data, titles_from_data=True)
342
        pie.set_categories(labels)
343
        pie.height = 7.25
344
        pie.width = 9
345
        s1 = pie.series[0]
346
        s1.dLbls = DataLabelList()
347
        s1.dLbls.showCatName = False
348
        s1.dLbls.showVal = False
349
        s1.dLbls.showPercent = True
350
351
        ws.add_chart(pie, "D14")
352
353
    ####################################################################################################################
354
    current_row_number = 20
355
    if 'subtotals' not in reporting_period_data.keys() or \
356
            reporting_period_data['subtotals'] is None:
357
        pass
358
    else:
359
        ws['B' + str(current_row_number)].font = title_font
360
        ws['B' + str(current_row_number)] = name + ' ' + _('Carbon Dioxide Emissions Proportion')
361
362
        current_row_number += 1
363
        table_start_row_number = current_row_number
364
365
        ws['B' + str(current_row_number)].fill = table_fill
366
        ws['B' + str(current_row_number)].font = name_font
367
        ws['B' + str(current_row_number)].alignment = c_c_alignment
368
        ws['B' + str(current_row_number)].border = f_border
369
370
        ws['C' + str(current_row_number)].fill = table_fill
371
        ws['C' + str(current_row_number)].font = name_font
372
        ws['C' + str(current_row_number)].alignment = c_c_alignment
373
        ws['C' + str(current_row_number)].border = f_border
374
        ws['C' + str(current_row_number)] = _('Carbon Dioxide Emissions Proportion')
375
376
        current_row_number += 1
377
378
        category = reporting_period_data['names']
379
        ca_len = len(category)
380
381
        for i in range(0, ca_len):
382
            ws['B' + str(current_row_number)].font = title_font
383
            ws['B' + str(current_row_number)].alignment = c_c_alignment
384
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i] + \
385
                ' (' + reporting_period_data['units'][i] + ')'
386
            ws['B' + str(current_row_number)].border = f_border
387
388
            ws['C' + str(current_row_number)].font = title_font
389
            ws['C' + str(current_row_number)].alignment = c_c_alignment
390
            ws['C' + str(current_row_number)] = round2(reporting_period_data['subtotals'][i], 3)
391
            ws['C' + str(current_row_number)].border = f_border
392
393
            current_row_number += 1
394
395
        table_end_row_number = current_row_number - 1
396
397
        pie = PieChart()
398
        pie.title = name + ' ' + _('Carbon Dioxide Emissions Proportion')
399
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
400
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
401
        pie.add_data(pie_data, titles_from_data=True)
402
        pie.set_categories(labels)
403
        pie.height = 6.6
404
        pie.width = 9
405
        s1 = pie.series[0]
406
        s1.dLbls = DataLabelList()
407
        s1.dLbls.showCatName = False
408
        s1.dLbls.showVal = False
409
        s1.dLbls.showPercent = True
410
411
        ws.add_chart(pie, 'D' + str(table_start_row_number))
412
413
        if ca_len < 4:
414
            current_row_number = current_row_number - ca_len + 4
415
416
        current_row_number += 1
417
418
    ####################################################################################################################
419
    table_start_draw_flag = current_row_number + 1
420
421
    if "timestamps" not in reporting_period_data.keys() or \
422
            reporting_period_data['timestamps'] is None or \
423
            len(reporting_period_data['timestamps']) == 0:
424
        pass
425
    else:
426
        if not is_base_period_timestamp_exists_flag:
427
            reporting_period_data = report['reporting_period']
428
            times = reporting_period_data['timestamps']
429
            ca_len = len(report['reporting_period']['names'])
430
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
431
            ws['B' + str(current_row_number)].font = title_font
432
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
433
434
            current_row_number += 1
435
            # 1: Stand for blank line  2: Stand for title
436
            current_row_number += ca_len * 6 + real_timestamps_len * 6 + 1 + 2
437
            table_start_row_number = current_row_number
438
439
            time = times[0]
440
            has_data = False
441
442
            if len(time) > 0:
443
                has_data = True
444
445
            if has_data:
446
447
                ws.row_dimensions[current_row_number].height = 60
448
                current_col_number = 2
449
                col = format_cell.get_column_letter(current_col_number)
450
                ws[col + str(current_row_number)].fill = table_fill
451
                ws[col + str(current_row_number)].font = title_font
452
                ws[col + str(current_row_number)].border = f_border
453
                ws[col + str(current_row_number)].alignment = c_c_alignment
454
                ws[col + str(current_row_number)] = _('Datetime')
455
456
                for i in range(0, ca_len):
457
                    current_col_number += 1
458
                    col = format_cell.get_column_letter(current_col_number)
459
460
                    ws[col + str(current_row_number)].fill = table_fill
461
                    ws[col + str(current_row_number)].font = title_font
462
                    ws[col + str(current_row_number)].alignment = c_c_alignment
463
                    ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \
464
                        " (" + reporting_period_data['units'][i] + ")"
465
                    ws[col + str(current_row_number)].border = f_border
466
467
                current_col_number += 1
468
                col = format_cell.get_column_letter(current_col_number)
469
                ws[col + str(current_row_number)].fill = table_fill
470
                ws[col + str(current_row_number)].font = title_font
471
                ws[col + str(current_row_number)].alignment = c_c_alignment
472
                ws[col + str(current_row_number)] = _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
473
                ws[col + str(current_row_number)].border = f_border
474
475
                current_row_number += 1
476
477
                for i in range(0, len(time)):
478
                    current_col_number = 2
479
                    col = format_cell.get_column_letter(current_col_number)
480
481
                    ws[col + str(current_row_number)].font = title_font
482
                    ws[col + str(current_row_number)].alignment = c_c_alignment
483
                    ws[col + str(current_row_number)] = time[i]
484
                    ws[col + str(current_row_number)].border = f_border
485
486
                    total = Decimal(0.0)
487
488
                    for j in range(0, ca_len):
489
                        current_col_number += 1
490
                        col = format_cell.get_column_letter(current_col_number)
491
492
                        ws[col + str(current_row_number)].font = title_font
493
                        ws[col + str(current_row_number)].alignment = c_c_alignment
494
                        ws[col + str(current_row_number)] = round2(reporting_period_data['values'][j][i], 2)
495
                        total += reporting_period_data['values'][j][i]
496
                        ws[col + str(current_row_number)].border = f_border
497
498
                    current_col_number += 1
499
                    col = format_cell.get_column_letter(current_col_number)
500
                    ws[col + str(current_row_number)].font = title_font
501
                    ws[col + str(current_row_number)].alignment = c_c_alignment
502
                    ws[col + str(current_row_number)] = round2(total, 2)
503
                    ws[col + str(current_row_number)].border = f_border
504
505
                    current_row_number += 1
506
507
                table_end_row_number = current_row_number - 1
508
509
                current_col_number = 2
510
                col = format_cell.get_column_letter(current_col_number)
511
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)] = _('Subtotal')
515
                ws[col + str(current_row_number)].border = f_border
516
517
                subtotals = Decimal(0.0)
518
519
                for i in range(0, ca_len):
520
                    current_col_number += 1
521
                    col = format_cell.get_column_letter(current_col_number)
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(reporting_period_data['subtotals'][i], 2)
525
                    subtotals += reporting_period_data['subtotals'][i]
526
                    ws[col + str(current_row_number)].border = f_border
527
528
                    # line
529
                    line = LineChart()
530
                    line.title = _('Reporting Period Carbon Dioxide Emissions') + ' - ' \
531
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
532
                    labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
533
                    line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
534
                                          max_row=table_end_row_number)
535
                    line.add_data(line_data, titles_from_data=True)
536
                    line.set_categories(labels)
537
                    line_data = line.series[0]
538
                    line_data.marker.symbol = "auto"
539
                    line_data.smooth = True
540
                    line.x_axis.crosses = 'min'
541
                    line.height = 8.25
542
                    line.width = 24
543
                    chart_col = 'B'
544
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
545
                    ws.add_chart(line, chart_cell)
546
547
                current_col_number += 1
548
                col = format_cell.get_column_letter(current_col_number)
549
                ws[col + str(current_row_number)].font = title_font
550
                ws[col + str(current_row_number)].alignment = c_c_alignment
551
                ws[col + str(current_row_number)] = round2(subtotals, 2)
552
                ws[col + str(current_row_number)].border = f_border
553
554
                current_row_number += 2
555
        else:
556
            base_period_data = report['base_period']
557
            reporting_period_data = report['reporting_period']
558
            base_period_timestamps = base_period_data['timestamps']
559
            reporting_period_timestamps = reporting_period_data['timestamps']
560
            # Tip:
561
            #     base_period_data['names'] == reporting_period_data['names']
562
            #     base_period_data['units'] == reporting_period_data['units']
563
            base_period_data_ca_len = len(base_period_data['names'])
564
            reporting_period_data_ca_len = len(reporting_period_data['names'])
565
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
566
            ws['B' + str(current_row_number)].font = title_font
567
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
568
569
            current_row_number += 1
570
            # 1: Stand for blank line  2: Stand for title
571
            current_row_number += reporting_period_data_ca_len * 6 + real_timestamps_len * 6 + 1 + 2
572
            table_start_row_number = current_row_number
573
574
            has_data = False
575
576
            if len(base_period_timestamps[0]) or len(reporting_period_timestamps[0]) > 0:
577
                has_data = True
578
579
            if has_data:
580
                ws.row_dimensions[current_row_number].height = 60
581
                current_col_number = 2
582
                col = format_cell.get_column_letter(current_col_number)
583
                ws[col + str(current_row_number)].fill = table_fill
584
                ws[col + str(current_row_number)].font = title_font
585
                ws[col + str(current_row_number)].border = f_border
586
                ws[col + str(current_row_number)].alignment = c_c_alignment
587
                ws[col + str(current_row_number)] = _('Base Period') + " - " + _('Datetime')
588
589
                for i in range(0, base_period_data_ca_len):
590
                    current_col_number += 1
591
                    col = format_cell.get_column_letter(current_col_number)
592
593
                    ws[col + str(current_row_number)].fill = table_fill
594
                    ws[col + str(current_row_number)].font = title_font
595
                    ws[col + str(current_row_number)].alignment = c_c_alignment
596
                    ws[col + str(current_row_number)] = _('Base Period') + " - " + base_period_data['names'][i] + \
597
                        " (" + base_period_data['units'][i] + ")"
598
                    ws[col + str(current_row_number)].border = f_border
599
600
                current_col_number += 1
601
                col = format_cell.get_column_letter(current_col_number)
602
                ws[col + str(current_row_number)].fill = table_fill
603
                ws[col + str(current_row_number)].font = title_font
604
                ws[col + str(current_row_number)].alignment = c_c_alignment
605
                ws[col + str(current_row_number)] = _('Base Period') + " - " \
606
                    + _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
607
                ws[col + str(current_row_number)].border = f_border
608
609
                current_col_number += 1
610
                col = format_cell.get_column_letter(current_col_number)
611
612
                ws[col + str(current_row_number)].fill = table_fill
613
                ws[col + str(current_row_number)].font = title_font
614
                ws[col + str(current_row_number)].border = f_border
615
                ws[col + str(current_row_number)].alignment = c_c_alignment
616
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " + _('Datetime')
617
618
                for i in range(0, reporting_period_data_ca_len):
619
                    current_col_number += 1
620
                    col = format_cell.get_column_letter(current_col_number)
621
                    ws[col + str(current_row_number)].fill = table_fill
622
                    ws[col + str(current_row_number)].font = title_font
623
                    ws[col + str(current_row_number)].alignment = c_c_alignment
624
                    ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
625
                        + reporting_period_data['names'][i] + " (" + \
626
                        reporting_period_data['units'][i] + ")"
627
                    ws[col + str(current_row_number)].border = f_border
628
629
                current_col_number += 1
630
                col = format_cell.get_column_letter(current_col_number)
631
                ws[col + str(current_row_number)].fill = table_fill
632
                ws[col + str(current_row_number)].font = title_font
633
                ws[col + str(current_row_number)].alignment = c_c_alignment
634
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
635
                    + _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
636
                ws[col + str(current_row_number)].border = f_border
637
638
                current_row_number += 1
639
640
                max_timestamps_len = len(base_period_timestamps[0]) \
641
                    if len(base_period_timestamps[0]) >= len(reporting_period_timestamps[0]) \
642
                    else len(reporting_period_timestamps[0])
643
644
                for i in range(0, max_timestamps_len):
645
                    current_col_number = 2
646
                    col = format_cell.get_column_letter(current_col_number)
647
                    ws[col + str(current_row_number)].font = title_font
648
                    ws[col + str(current_row_number)].alignment = c_c_alignment
649
                    ws[col + str(current_row_number)] = base_period_timestamps[0][i] \
650
                        if i < len(base_period_timestamps[0]) else None
651
                    ws[col + str(current_row_number)].border = f_border
652
653
                    base_period_total = Decimal(0.0)
654
655
                    for j in range(0, base_period_data_ca_len):
656
                        current_col_number += 1
657
                        col = format_cell.get_column_letter(current_col_number)
658
659
                        ws[col + str(current_row_number)].font = title_font
660
                        ws[col + str(current_row_number)].alignment = c_c_alignment
661
                        ws[col + str(current_row_number)] = round2(base_period_data['values'][j][i], 2) \
662
                            if i < len(base_period_data['values'][j]) else None
663
                        if i < len(base_period_timestamps[0]):
664
                            base_period_total += base_period_data['values'][j][i]
665
                        ws[col + str(current_row_number)].border = f_border
666
667
                    current_col_number += 1
668
                    col = format_cell.get_column_letter(current_col_number)
669
                    ws[col + str(current_row_number)].font = title_font
670
                    ws[col + str(current_row_number)].alignment = c_c_alignment
671
                    ws[col + str(current_row_number)] = round2(base_period_total, 2) \
672
                        if i < len(base_period_timestamps[0]) else None
673
                    ws[col + str(current_row_number)].border = f_border
674
675
                    current_col_number += 1
676
                    col = format_cell.get_column_letter(current_col_number)
677
678
                    ws[col + str(current_row_number)].font = title_font
679
                    ws[col + str(current_row_number)].alignment = c_c_alignment
680
                    ws[col + str(current_row_number)] = reporting_period_timestamps[0][i] \
681
                        if i < len(reporting_period_timestamps[0]) else None
682
                    ws[col + str(current_row_number)].border = f_border
683
684
                    reporting_period_total = Decimal(0.0)
685
686
                    for j in range(0, reporting_period_data_ca_len):
687
                        current_col_number += 1
688
                        col = format_cell.get_column_letter(current_col_number)
689
690
                        ws[col + str(current_row_number)].font = title_font
691
                        ws[col + str(current_row_number)].alignment = c_c_alignment
692
                        ws[col + str(current_row_number)] = round2(reporting_period_data['values'][j][i], 2) \
693
                            if i < len(reporting_period_data['values'][j]) else None
694
                        if i < len(reporting_period_timestamps[0]):
695
                            reporting_period_total += reporting_period_data['values'][j][i]
696
                        ws[col + str(current_row_number)].border = f_border
697
698
                    current_col_number += 1
699
                    col = format_cell.get_column_letter(current_col_number)
700
                    ws[col + str(current_row_number)].font = title_font
701
                    ws[col + str(current_row_number)].alignment = c_c_alignment
702
                    ws[col + str(current_row_number)] = round2(reporting_period_total, 2) \
703
                        if i < len(reporting_period_timestamps[0]) else None
704
                    ws[col + str(current_row_number)].border = f_border
705
706
                    current_row_number += 1
707
708
                current_col_number = 2
709
                col = format_cell.get_column_letter(current_col_number)
710
                ws[col + str(current_row_number)].font = title_font
711
                ws[col + str(current_row_number)].alignment = c_c_alignment
712
                ws[col + str(current_row_number)] = _('Subtotal')
713
                ws[col + str(current_row_number)].border = f_border
714
715
                base_period_subtotals = Decimal(0.0)
716
717
                for i in range(0, base_period_data_ca_len):
718
                    current_col_number += 1
719
                    col = format_cell.get_column_letter(current_col_number)
720
                    ws[col + str(current_row_number)].font = title_font
721
                    ws[col + str(current_row_number)].alignment = c_c_alignment
722
                    ws[col + str(current_row_number)] = round2(base_period_data['subtotals'][i], 2)
723
                    base_period_subtotals += base_period_data['subtotals'][i]
724
                    ws[col + str(current_row_number)].border = f_border
725
726
                current_col_number += 1
727
                col = format_cell.get_column_letter(current_col_number)
728
                ws[col + str(current_row_number)].font = title_font
729
                ws[col + str(current_row_number)].alignment = c_c_alignment
730
                ws[col + str(current_row_number)] = round2(base_period_subtotals, 2)
731
                ws[col + str(current_row_number)].border = f_border
732
733
                current_col_number += 1
734
                col = format_cell.get_column_letter(current_col_number)
735
736
                ws[col + str(current_row_number)].font = title_font
737
                ws[col + str(current_row_number)].alignment = c_c_alignment
738
                ws[col + str(current_row_number)] = _('Subtotal')
739
                ws[col + str(current_row_number)].border = f_border
740
741
                reporting_period_subtotals = Decimal(0.0)
742
743
                for i in range(0, reporting_period_data_ca_len):
744
                    current_col_number += 1
745
                    col = format_cell.get_column_letter(current_col_number)
746
                    ws[col + str(current_row_number)].font = title_font
747
                    ws[col + str(current_row_number)].alignment = c_c_alignment
748
                    ws[col + str(current_row_number)] = round2(reporting_period_data['subtotals'][i], 2)
749
                    reporting_period_subtotals += reporting_period_data['subtotals'][i]
750
                    ws[col + str(current_row_number)].border = f_border
751
752
                current_col_number += 1
753
                col = format_cell.get_column_letter(current_col_number)
754
                ws[col + str(current_row_number)].font = title_font
755
                ws[col + str(current_row_number)].alignment = c_c_alignment
756
                ws[col + str(current_row_number)] = round2(reporting_period_subtotals, 2)
757
                ws[col + str(current_row_number)].border = f_border
758
759
                for i in range(0, reporting_period_data_ca_len):
760
                    # line
761
                    line = LineChart()
762
                    line.title = _('Base Period Carbon Dioxide Emissions') + " / " \
763
                        + _('Reporting Period Carbon Dioxide Emissions') + ' - ' \
764
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
765
                    labels = Reference(ws, min_col=2 + base_period_data_ca_len + 1 + 1,
766
                                       min_row=table_start_row_number + 1,
767
                                       max_row=table_start_row_number + len(reporting_period_timestamps[0]))
768
                    base_line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
769
                                               max_row=table_start_row_number + len(reporting_period_timestamps[0]))
770
                    reporting_line_data = Reference(ws, min_col=3 + base_period_data_ca_len + 1 + 1 + i,
771
                                                    min_row=table_start_row_number,
772
                                                    max_row=table_start_row_number
773
                                                    + len(reporting_period_timestamps[0]))
774
                    line.add_data(base_line_data, titles_from_data=True)
775
                    line.add_data(reporting_line_data, titles_from_data=True)
776
                    line.set_categories(labels)
777
                    for j in range(len(line.series)):
778
                        line.series[j].marker.symbol = "auto"
779
                        line.series[j].smooth = True
780
                    line.x_axis.crosses = 'min'
781
                    line.height = 8.25
782
                    line.width = 24
783
                    chart_col = 'B'
784
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
785
                    ws.add_chart(line, chart_cell)
786
787
                current_row_number += 2
788
789
    ####################################################################################################################
790
    if "child_space" not in report.keys() or "energy_category_names" not in report['child_space'].keys() or \
791
            len(report['child_space']["energy_category_names"]) == 0 \
792
            or 'child_space_names_array' not in report['child_space'].keys() \
793
            or report['child_space']['energy_category_names'] is None \
794
            or len(report['child_space']['child_space_names_array']) == 0 \
795
            or len(report['child_space']['child_space_names_array'][0]) == 0:
796
        pass
797
    else:
798
        child = report['child_space']
799
800
        ws['B' + str(current_row_number)].font = title_font
801
        ws['B' + str(current_row_number)] = name + ' ' + _('Child Spaces Data')
802
803
        current_row_number += 1
804
        table_start_row_number = current_row_number
805
806
        ws.row_dimensions[current_row_number].height = 60
807
        ws['B' + str(current_row_number)].fill = table_fill
808
        ws['B' + str(current_row_number)].font = name_font
809
        ws['B' + str(current_row_number)].alignment = c_c_alignment
810
        ws['B' + str(current_row_number)].border = f_border
811
        ws['B' + str(current_row_number)] = _('Child Space')
812
        ca_len = len(child['energy_category_names'])
813
814
        col = ''
815
816
        for i in range(0, ca_len):
817
            col = chr(ord('C') + i)
818
            ws[col + str(current_row_number)].fill = table_fill
819
            ws[col + str(current_row_number)].font = name_font
820
            ws[col + str(current_row_number)].alignment = c_c_alignment
821
            ws[col + str(current_row_number)].border = f_border
822
            ws[col + str(current_row_number)] = child['energy_category_names'][i] + ' ' + '(' + child['units'][i] + ')'
823
824
        col = chr(ord(col) + 1)
825
        ws[col + str(current_row_number)].fill = table_fill
826
        ws[col + str(current_row_number)].font = name_font
827
        ws[col + str(current_row_number)].alignment = c_c_alignment
828
        ws[col + str(current_row_number)].border = f_border
829
        ws[col + str(current_row_number)] = _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
830
831
        space_len = len(child['child_space_names_array'][0])
832
833
        for i in range(0, space_len):
834
            current_row_number += 1
835
            row = str(current_row_number)
836
837
            ws['B' + row].font = title_font
838
            ws['B' + row].alignment = c_c_alignment
839
            ws['B' + row] = child['child_space_names_array'][0][i]
840
            ws['B' + row].border = f_border
841
842
            col = ''
843
            periodic_sum = 0
844
845
            for j in range(0, ca_len):
846
                col = chr(ord('C') + j)
847
                ws[col + row].font = name_font
848
                ws[col + row].alignment = c_c_alignment
849
                periodic_sum += child['subtotals_array'][j][i]
850
                ws[col + row] = round2(child['subtotals_array'][j][i], 2)
851
                ws[col + row].border = f_border
852
853
            col = chr(ord(col) + 1)
854
            ws[col + row].font = name_font
855
            ws[col + row].alignment = c_c_alignment
856
            ws[col + row] = round2(periodic_sum, 2)
857
            ws[col + row].border = f_border
858
859
        table_end_row_number = current_row_number
860
        current_row_number += 1
861
        chart_start_row_number = current_row_number
862
863
        # Pie
864
        for i in range(0, ca_len):
865
            pie = PieChart()
866
            labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
867
            pie_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
868
                                 max_row=table_end_row_number)
869
            pie.add_data(pie_data, titles_from_data=True)
870
            pie.set_categories(labels)
871
            pie.height = 6.6
872
            pie.width = 8
873
            pie.title = ws.cell(column=3 + i, row=table_start_row_number).value
874
            s1 = pie.series[0]
875
            s1.dLbls = DataLabelList()
876
            s1.dLbls.showCatName = False
877
            s1.dLbls.showVal = False
878
            s1.dLbls.showPercent = True
879
            if i % 2 == 0:
880
                chart_cell = 'B' + str(chart_start_row_number)
881
            else:
882
                chart_cell = 'E' + str(chart_start_row_number)
883
                chart_start_row_number += 5
884
            ws.add_chart(pie, chart_cell)
885
886
        current_row_number = chart_start_row_number
887
888
        if ca_len % 2 == 1:
889
            current_row_number += 5
890
891
        current_row_number += 1
892
    ####################################################################################################################
893
    current_sheet_parameters_row_number = table_start_draw_flag + len(reporting_period_data['names']) * 6 + 1
894
    if 'parameters' not in report.keys() or \
895
            report['parameters'] is None or \
896
            'names' not in report['parameters'].keys() or \
897
            report['parameters']['names'] is None or \
898
            len(report['parameters']['names']) == 0 or \
899
            'timestamps' not in report['parameters'].keys() or \
900
            report['parameters']['timestamps'] is None or \
901
            len(report['parameters']['timestamps']) == 0 or \
902
            'values' not in report['parameters'].keys() or \
903
            report['parameters']['values'] is None or \
904
            len(report['parameters']['values']) == 0 or \
905
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
906
        pass
907
    else:
908
        ################################################################################################################
909
        # new worksheet
910
        ################################################################################################################
911
912
        parameters_data = report['parameters']
913
        parameters_names_len = len(parameters_data['names'])
914
915
        file_name = "Space"+re.sub(r'[^A-Z]', '', ws.title.strip('S')) + "_"
916
        parameters_ws = wb.create_sheet(file_name + _('Parameters'))
917
918
        parameters_timestamps_data_max_len = \
919
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
920
921
        # Row height
922
        parameters_ws.row_dimensions[1].height = 102
923
        for i in range(2, 7 + 1):
924
            parameters_ws.row_dimensions[i].height = 42
925
926
        for i in range(8, parameters_timestamps_data_max_len + 10):
927
            parameters_ws.row_dimensions[i].height = 60
928
929
        # Col width
930
        parameters_ws.column_dimensions['A'].width = 1.5
931
932
        parameters_ws.column_dimensions['B'].width = 25.0
933
934
        for i in range(3, 12 + parameters_names_len * 3):
935
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
936
937
        # Img
938
        img = Image("excelexporters/myems.png")
939
        parameters_ws.add_image(img, 'A1')
940
941
        # Title
942
        parameters_ws['B3'].alignment = b_r_alignment
943
        parameters_ws['B3'] = _('Name') + ':'
944
        parameters_ws['C3'].border = b_border
945
        parameters_ws['C3'].alignment = b_c_alignment
946
        parameters_ws['C3'] = name
947
948
        parameters_ws['D3'].alignment = b_r_alignment
949
        parameters_ws['D3'] = _('Period Type') + ':'
950
        parameters_ws['E3'].border = b_border
951
        parameters_ws['E3'].alignment = b_c_alignment
952
        parameters_ws['E3'] = period_type
953
954
        parameters_ws['B4'].alignment = b_r_alignment
955
        parameters_ws['B4'] = _('Reporting Start Datetime') + ':'
956
        parameters_ws['C4'].border = b_border
957
        parameters_ws['C4'].alignment = b_c_alignment
958
        parameters_ws['C4'] = reporting_start_datetime_local
959
960
        parameters_ws['D4'].alignment = b_r_alignment
961
        parameters_ws['D4'] = _('Reporting End Datetime') + ':'
962
        parameters_ws['E4'].border = b_border
963
        parameters_ws['E4'].alignment = b_c_alignment
964
        parameters_ws['E4'] = reporting_end_datetime_local
965
966
        parameters_ws_current_row_number = 6
967
968
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
969
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + _('Parameters')
970
971
        parameters_ws_current_row_number += 1
972
973
        parameters_table_start_row_number = parameters_ws_current_row_number
974
975
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
976
977
        parameters_ws_current_row_number += 1
978
979
        table_current_col_number = 2
980
981
        for i in range(0, parameters_names_len):
982
983
            if len(parameters_data['timestamps'][i]) == 0:
984
                continue
985
986
            col = format_cell.get_column_letter(table_current_col_number)
987
988
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
989
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
990
991
            col = format_cell.get_column_letter(table_current_col_number + 1)
992
993
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
994
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
995
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
996
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
997
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
998
999
            table_current_row_number = parameters_ws_current_row_number
1000
1001
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
1002
                col = format_cell.get_column_letter(table_current_col_number)
1003
1004
                parameters_ws[col + str(table_current_row_number)].border = f_border
1005
                parameters_ws[col + str(table_current_row_number)].font = title_font
1006
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
1007
                parameters_ws[col + str(table_current_row_number)] = value
1008
1009
                col = format_cell.get_column_letter(table_current_col_number + 1)
1010
1011
                parameters_ws[col + str(table_current_row_number)].border = f_border
1012
                parameters_ws[col + str(table_current_row_number)].font = title_font
1013
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
1014
                parameters_ws[col + str(table_current_row_number)] = round2(parameters_data['values'][i][j], 2)
1015
1016
                table_current_row_number += 1
1017
1018
            table_current_col_number = table_current_col_number + 3
1019
1020
        ################################################################################################################
1021
        # parameters chart and parameters table
1022
        ################################################################################################################
1023
1024
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
1025
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + _('Parameters')
1026
1027
        current_sheet_parameters_row_number += 1
1028
1029
        chart_start_row_number = current_sheet_parameters_row_number
1030
1031
        col_index = 0
1032
1033
        for i in range(0, parameters_names_len):
1034
1035
            if len(parameters_data['timestamps'][i]) == 0:
1036
                continue
1037
1038
            line = LineChart()
1039
            data_col = 3 + col_index * 3
1040
            labels_col = 2 + col_index * 3
1041
            col_index += 1
1042
            line.title = _('Parameters') + ' - ' + \
1043
                parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
1044
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
1045
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
1046
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
1047
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
1048
            line.add_data(line_data, titles_from_data=True)
1049
            line.set_categories(labels)
1050
            line_data = line.series[0]
1051
            line_data.marker.symbol = "auto"
1052
            line_data.smooth = True
1053
            line.x_axis.crosses = 'min'
1054
            line.height = 8.25
1055
            line.width = 24
1056
            chart_col = 'B'
1057
            chart_cell = chart_col + str(chart_start_row_number)
1058
            chart_start_row_number += 6
1059
            ws.add_chart(line, chart_cell)
1060
1061
        current_sheet_parameters_row_number = chart_start_row_number
1062
1063
        current_sheet_parameters_row_number += 1
1064
    ####################################################################################################################
1065
    filename = str(uuid.uuid4()) + '.xlsx'
1066
    wb.save(filename)
1067
1068
    return filename
1069
1070
1071
def reporting_period_values_periodic_sum(reporting_period_data, periodic_index, ca_len):
1072
    periodic_sum = Decimal(0.0)
1073
    for i in range(0, ca_len):
1074
        periodic_sum += reporting_period_data['values'][i][periodic_index]
1075
1076
    return periodic_sum
1077
1078
1079
def timestamps_data_all_equal_0(lists):
1080
    for i, value in enumerate(list(lists)):
1081
        if len(value) > 0:
1082
            return False
1083
1084
    return True
1085
1086
1087
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
1088
    max_len = 0
1089
    for i, value in enumerate(list(parameters_timestamps_lists)):
1090
        if len(value) > max_len:
1091
            max_len = len(value)
1092
1093
    return max_len
1094
1095
1096
def timestamps_data_not_equal_0(lists):
1097
    number = 0
1098
    for i, value in enumerate(list(lists)):
1099
        if len(value) > 0:
1100
            number += 1
1101
    return number
1102
1103
1104 View Code Duplication
def is_base_period_timestamp_exists(base_period_data):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
1105
    timestamps = base_period_data['timestamps']
1106
1107
    if len(timestamps) == 0:
1108
        return False
1109
1110
    for timestamp in timestamps:
1111
        if len(timestamp) > 0:
1112
            return True
1113
1114
    return False
1115