Issues (1656)

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