Issues (1656)

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

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