Issues (1577)

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