Issues (1577)

myems-api/excelexporters/spaceincome.py (3 issues)

1
import base64
2
from core.utilities import get_translation
3
import os
4
import re
5
import uuid
6
from decimal import Decimal
7
import openpyxl.utils.cell as format_cell
8
from openpyxl import Workbook
9
from openpyxl.chart import PieChart, LineChart, Reference
10
from openpyxl.chart.label import DataLabelList
11
from openpyxl.drawing.image import Image
12
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
13
from core.utilities import round2
14
15
####################################################################################################################
16
# PROCEDURES
17
# Step 1: Validate the report data
18
# Step 2: Generate excel file
19
# Step 3: Encode the excel file to Base64
20
####################################################################################################################
21
22
23 View Code Duplication
def export(report,
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
24
           name,
25
           base_period_start_datetime_local,
26
           base_period_end_datetime_local,
27
           reporting_start_datetime_local,
28
           reporting_end_datetime_local,
29
           period_type,
30
           language):
31
    ####################################################################################################################
32
    # Step 1: Validate the report data
33
    ####################################################################################################################
34
    if report is None:
35
        return None
36
    print(report)
37
38
    ####################################################################################################################
39
    # Step 2: Generate excel file from the report data
40
    ####################################################################################################################
41
    filename = generate_excel(report,
42
                              name,
43
                              base_period_start_datetime_local,
44
                              base_period_end_datetime_local,
45
                              reporting_start_datetime_local,
46
                              reporting_end_datetime_local,
47
                              period_type,
48
                              language)
49
    ####################################################################################################################
50
    # Step 3: Encode the excel file to Base64
51
    ####################################################################################################################
52
    binary_file_data = b''
53
    try:
54
        with open(filename, 'rb') as binary_file:
55
            binary_file_data = binary_file.read()
56
    except IOError as ex:
57
        print(str(ex))
58
59
    # Base64 encode the bytes
60
    base64_encoded_data = base64.b64encode(binary_file_data)
61
    # get the Base64 encoded data using human-readable characters.
62
    base64_message = base64_encoded_data.decode('utf-8')
63
    # delete the file from server
64
    try:
65
        os.remove(filename)
66
    except NotImplementedError as ex:
67
        print(str(ex))
68
    return base64_message
69
70
71
def generate_excel(report,
72
                   name,
73
                   base_period_start_datetime_local,
74
                   base_period_end_datetime_local,
75
                   reporting_start_datetime_local,
76
                   reporting_end_datetime_local,
77
                   period_type,
78
                   language):
79
    trans = get_translation(language)
80
    trans.install()
81
    _ = trans.gettext
82
    wb = Workbook()
83
    ws = wb.active
84
    ws.title = "SpaceIncome"
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(7, 10 + 1):
189
            ws.row_dimensions[i].height = 0.1
190
    else:
191
        ws['B7'].font = title_font
192
        ws['B7'] = name + ' ' + _('Reporting Period Income')
193
        category = reporting_period_data['names']
194
        ca_len = len(category)
195
196
        ws.row_dimensions[8].height = 60
197
        ws['B8'].fill = table_fill
198
        ws['B8'].border = f_border
199
200
        ws['B9'].font = title_font
201
        ws['B9'].alignment = c_c_alignment
202
        ws['B9'] = _('Total')
203
        ws['B9'].border = f_border
204
205
        ws['B10'].font = title_font
206
        ws['B10'].alignment = c_c_alignment
207
        ws['B10'] = _('Per Unit Area')
208
        ws['B10'].border = f_border
209
210
        ws['B11'].font = title_font
211
        ws['B11'].alignment = c_c_alignment
212
        ws['B11'] = _('Increment Rate')
213
        ws['B11'].border = f_border
214
215
        col = ''
216
217
        for i in range(0, ca_len):
218
            col = chr(ord('C') + i)
219
220
            ws[col + '8'].fill = table_fill
221
            ws[col + '8'].font = name_font
222
            ws[col + '8'].alignment = c_c_alignment
223
            ws[col + '8'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
224
            ws[col + '8'].border = f_border
225
226
            ws[col + '9'].font = name_font
227
            ws[col + '9'].alignment = c_c_alignment
228
            ws[col + '9'] = round2(reporting_period_data['subtotals'][i], 2)
229
            ws[col + '9'].border = f_border
230
231
            ws[col + '10'].font = name_font
232
            ws[col + '10'].alignment = c_c_alignment
233
            ws[col + '10'] = round2(reporting_period_data['subtotals_per_unit_area'][i], 2) \
234
                if reporting_period_data['subtotals_per_unit_area'][i] is not None else ''
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
            if reporting_period_data['total_per_unit_area'] is not None else ''
260
        ws[col + '10'].border = f_border
261
262
        ws[col + '11'].font = name_font
263
        ws[col + '11'].alignment = c_c_alignment
264
        ws[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[col + '11'].border = f_border
267
268
    ####################################################################################################################
269
    current_row_number = 13
270
    if "subtotals" not in reporting_period_data.keys() or \
271
            reporting_period_data['subtotals'] is None or \
272
            len(reporting_period_data['subtotals']) == 0:
273
        pass
274
    else:
275
        ws['B' + str(current_row_number)].font = title_font
276
        ws['B' + str(current_row_number)] = name + ' ' + _('Incomes by Energy Category')
277
278
        current_row_number += 1
279
280
        table_start_row_number = current_row_number
281
282
        ws['B' + str(current_row_number)].fill = table_fill
283
        ws['B' + str(current_row_number)].font = name_font
284
        ws['B' + str(current_row_number)].alignment = c_c_alignment
285
        ws['B' + str(current_row_number)].border = f_border
286
287
        ws['C' + str(current_row_number)].fill = table_fill
288
        ws['C' + str(current_row_number)].font = name_font
289
        ws['C' + str(current_row_number)].alignment = c_c_alignment
290
        ws['C' + str(current_row_number)].border = f_border
291
        ws['C' + str(current_row_number)] = _('Incomes')
292
293
        ws['D' + str(current_row_number)].fill = table_fill
294
        ws['D' + str(current_row_number)].font = name_font
295
        ws['D' + str(current_row_number)].alignment = c_c_alignment
296
        ws['D' + str(current_row_number)].border = f_border
297
        ws['D' + str(current_row_number)] = _('Proportion')
298
299
        current_row_number += 1
300
301
        ca_len = len(reporting_period_data['names'])
302
        total = Decimal(0.0)
303
        for i in range(0, ca_len):
304
            total = reporting_period_data['subtotals'][i] + total
305
306
        for i in range(0, ca_len):
307
            ws['B' + str(current_row_number)].font = title_font
308
            ws['B' + str(current_row_number)].alignment = c_c_alignment
309
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i]
310
            ws['B' + str(current_row_number)].border = f_border
311
312
            ws['C' + str(current_row_number)].font = title_font
313
            ws['C' + str(current_row_number)].alignment = c_c_alignment
314
            ws['C' + str(current_row_number)].border = f_border
315
            ws['C' + str(current_row_number)] = round2(reporting_period_data['subtotals'][i], 2)
316
317
            ws['D' + str(current_row_number)].font = title_font
318
            ws['D' + str(current_row_number)].alignment = c_c_alignment
319
            ws['D' + str(current_row_number)].border = f_border
320
            ws['D' + str(current_row_number)] = '{:.2%}'.format(reporting_period_data['subtotals'][i] / total) \
321
                if total > Decimal(0.0) else '-'
322
323
            current_row_number += 1
324
325
        table_end_row_number = current_row_number - 1
326
327
        pie = PieChart()
328
        pie.title = name + ' ' + _('Incomes by Energy Category')
329
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
330
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
331
        pie.add_data(pie_data, titles_from_data=True)
332
        pie.set_categories(labels)
333
        pie.height = 6.6
334
        pie.width = 9
335
        s1 = pie.series[0]
336
        s1.dLbls = DataLabelList()
337
        s1.dLbls.showCatName = False
338
        s1.dLbls.showVal = False
339
        s1.dLbls.showPercent = True
340
        table_cell = 'E' + str(table_start_row_number)
341
        ws.add_chart(pie, table_cell)
342
343
        if ca_len < 4:
344
            current_row_number = current_row_number - ca_len + 4
345
346
        current_row_number += 1
347
348
    ####################################################################################################################
349
    table_start_draw_flag = current_row_number + 1
350
351
    if "timestamps" not in reporting_period_data.keys() or \
352
            reporting_period_data['timestamps'] is None or \
353
            len(reporting_period_data['timestamps']) == 0:
354
        pass
355
    else:
356
        if not is_base_period_timestamp_exists_flag:
357
            reporting_period_data = report['reporting_period']
358
            times = reporting_period_data['timestamps']
359
            ca_len = len(report['reporting_period']['names'])
360
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
361
            ws['B' + str(current_row_number)].font = title_font
362
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
363
364
            current_row_number += 1
365
            # 1: Stand for blank line  2: Stand for title
366
            current_row_number += ca_len * 6 + real_timestamps_len * 6 + 1 + 2
367
            table_start_row_number = current_row_number
368
369
            time = times[0]
370
            has_data = False
371
372
            if len(time) > 0:
373
                has_data = True
374
375
            if has_data:
376
377
                ws.row_dimensions[current_row_number].height = 60
378
                current_col_number = 2
379
                col = format_cell.get_column_letter(current_col_number)
380
                ws[col + str(current_row_number)].fill = table_fill
381
                ws[col + str(current_row_number)].font = title_font
382
                ws[col + str(current_row_number)].border = f_border
383
                ws[col + str(current_row_number)].alignment = c_c_alignment
384
                ws[col + str(current_row_number)] = _('Datetime')
385
386
                for i in range(0, ca_len):
387
                    current_col_number += 1
388
                    col = format_cell.get_column_letter(current_col_number)
389
390
                    ws[col + str(current_row_number)].fill = table_fill
391
                    ws[col + str(current_row_number)].font = title_font
392
                    ws[col + str(current_row_number)].alignment = c_c_alignment
393
                    ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \
394
                        " (" + reporting_period_data['units'][i] + ")"
395
                    ws[col + str(current_row_number)].border = f_border
396
397
                current_col_number += 1
398
                col = format_cell.get_column_letter(current_col_number)
399
                ws[col + str(current_row_number)].fill = table_fill
400
                ws[col + str(current_row_number)].font = title_font
401
                ws[col + str(current_row_number)].alignment = c_c_alignment
402
                ws[col + str(current_row_number)] = _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
403
                ws[col + str(current_row_number)].border = f_border
404
405
                current_row_number += 1
406
407
                for i in range(0, len(time)):
408
                    current_col_number = 2
409
                    col = format_cell.get_column_letter(current_col_number)
410
411
                    ws[col + str(current_row_number)].font = title_font
412
                    ws[col + str(current_row_number)].alignment = c_c_alignment
413
                    ws[col + str(current_row_number)] = time[i]
414
                    ws[col + str(current_row_number)].border = f_border
415
416
                    total = Decimal(0.0)
417
418
                    for j in range(0, ca_len):
419
                        current_col_number += 1
420
                        col = format_cell.get_column_letter(current_col_number)
421
422
                        ws[col + str(current_row_number)].font = title_font
423
                        ws[col + str(current_row_number)].alignment = c_c_alignment
424
                        ws[col + str(current_row_number)] = round2(reporting_period_data['values'][j][i], 2)
425
                        total += reporting_period_data['values'][j][i]
426
                        ws[col + str(current_row_number)].border = f_border
427
428
                    current_col_number += 1
429
                    col = format_cell.get_column_letter(current_col_number)
430
                    ws[col + str(current_row_number)].font = title_font
431
                    ws[col + str(current_row_number)].alignment = c_c_alignment
432
                    ws[col + str(current_row_number)] = round2(total, 2)
433
                    ws[col + str(current_row_number)].border = f_border
434
435
                    current_row_number += 1
436
437
                table_end_row_number = current_row_number - 1
438
439
                current_col_number = 2
440
                col = format_cell.get_column_letter(current_col_number)
441
442
                ws[col + str(current_row_number)].font = title_font
443
                ws[col + str(current_row_number)].alignment = c_c_alignment
444
                ws[col + str(current_row_number)] = _('Subtotal')
445
                ws[col + str(current_row_number)].border = f_border
446
447
                subtotals = Decimal(0.0)
448
449
                for i in range(0, ca_len):
450
                    current_col_number += 1
451
                    col = format_cell.get_column_letter(current_col_number)
452
                    ws[col + str(current_row_number)].font = title_font
453
                    ws[col + str(current_row_number)].alignment = c_c_alignment
454
                    ws[col + str(current_row_number)] = round2(reporting_period_data['subtotals'][i], 2)
455
                    subtotals += reporting_period_data['subtotals'][i]
456
                    ws[col + str(current_row_number)].border = f_border
457
458
                    # line
459
                    line = LineChart()
460
                    line.title = _('Reporting Period Income') + ' - ' \
461
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
462
                    labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
463
                    line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
464
                                          max_row=table_end_row_number)
465
                    line.add_data(line_data, titles_from_data=True)
466
                    line.set_categories(labels)
467
                    line_data = line.series[0]
468
                    line_data.marker.symbol = "auto"
469
                    line_data.smooth = True
470
                    line.x_axis.crosses = 'min'
471
                    line.height = 8.25
472
                    line.width = 24
473
                    chart_col = 'B'
474
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
475
                    ws.add_chart(line, chart_cell)
476
477
                current_col_number += 1
478
                col = format_cell.get_column_letter(current_col_number)
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)] = round2(subtotals, 2)
482
                ws[col + str(current_row_number)].border = f_border
483
484
                current_row_number += 2
485
        else:
486
            base_period_data = report['base_period']
487
            reporting_period_data = report['reporting_period']
488
            base_period_timestamps = base_period_data['timestamps']
489
            reporting_period_timestamps = reporting_period_data['timestamps']
490
            # Tip:
491
            #     base_period_data['names'] == reporting_period_data['names']
492
            #     base_period_data['units'] == reporting_period_data['units']
493
            base_period_data_ca_len = len(base_period_data['names'])
494
            reporting_period_data_ca_len = len(reporting_period_data['names'])
495
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
496
            ws['B' + str(current_row_number)].font = title_font
497
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
498
499
            current_row_number += 1
500
            # 1: Stand for blank line  2: Stand for title
501
            current_row_number += reporting_period_data_ca_len * 6 + real_timestamps_len * 6 + 1 + 2
502
            table_start_row_number = current_row_number
503
504
            has_data = False
505
506
            if len(base_period_timestamps[0]) or len(reporting_period_timestamps[0]) > 0:
507
                has_data = True
508
509
            if has_data:
510
                ws.row_dimensions[current_row_number].height = 60
511
                current_col_number = 2
512
                col = format_cell.get_column_letter(current_col_number)
513
                ws[col + str(current_row_number)].fill = table_fill
514
                ws[col + str(current_row_number)].font = title_font
515
                ws[col + str(current_row_number)].border = f_border
516
                ws[col + str(current_row_number)].alignment = c_c_alignment
517
                ws[col + str(current_row_number)] = _('Base Period') + " - " + _('Datetime')
518
519
                for i in range(0, base_period_data_ca_len):
520
                    current_col_number += 1
521
                    col = format_cell.get_column_letter(current_col_number)
522
523
                    ws[col + str(current_row_number)].fill = table_fill
524
                    ws[col + str(current_row_number)].font = title_font
525
                    ws[col + str(current_row_number)].alignment = c_c_alignment
526
                    ws[col + str(current_row_number)] = _('Base Period') + " - " + base_period_data['names'][i] + \
527
                        " (" + base_period_data['units'][i] + ")"
528
                    ws[col + str(current_row_number)].border = f_border
529
530
                current_col_number += 1
531
                col = format_cell.get_column_letter(current_col_number)
532
                ws[col + str(current_row_number)].fill = table_fill
533
                ws[col + str(current_row_number)].font = title_font
534
                ws[col + str(current_row_number)].alignment = c_c_alignment
535
                ws[col + str(current_row_number)] = _('Base Period') + " - " \
536
                    + _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
537
                ws[col + str(current_row_number)].border = f_border
538
539
                current_col_number += 1
540
                col = format_cell.get_column_letter(current_col_number)
541
542
                ws[col + str(current_row_number)].fill = table_fill
543
                ws[col + str(current_row_number)].font = title_font
544
                ws[col + str(current_row_number)].border = f_border
545
                ws[col + str(current_row_number)].alignment = c_c_alignment
546
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " + _('Datetime')
547
548
                for i in range(0, reporting_period_data_ca_len):
549
                    current_col_number += 1
550
                    col = format_cell.get_column_letter(current_col_number)
551
                    ws[col + str(current_row_number)].fill = table_fill
552
                    ws[col + str(current_row_number)].font = title_font
553
                    ws[col + str(current_row_number)].alignment = c_c_alignment
554
                    ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
555
                        + reporting_period_data['names'][i] + " (" + \
556
                        reporting_period_data['units'][i] + ")"
557
                    ws[col + str(current_row_number)].border = f_border
558
559
                current_col_number += 1
560
                col = format_cell.get_column_letter(current_col_number)
561
                ws[col + str(current_row_number)].fill = table_fill
562
                ws[col + str(current_row_number)].font = title_font
563
                ws[col + str(current_row_number)].alignment = c_c_alignment
564
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
565
                    + _('Total') + '(' + report['reporting_period']['total_unit'] + ')'
566
                ws[col + str(current_row_number)].border = f_border
567
568
                current_row_number += 1
569
570
                max_timestamps_len = len(base_period_timestamps[0]) \
571
                    if len(base_period_timestamps[0]) >= len(reporting_period_timestamps[0]) \
572
                    else len(reporting_period_timestamps[0])
573
574
                for i in range(0, max_timestamps_len):
575
                    current_col_number = 2
576
                    col = format_cell.get_column_letter(current_col_number)
577
                    ws[col + str(current_row_number)].font = title_font
578
                    ws[col + str(current_row_number)].alignment = c_c_alignment
579
                    ws[col + str(current_row_number)] = base_period_timestamps[0][i] \
580
                        if i < len(base_period_timestamps[0]) else None
581
                    ws[col + str(current_row_number)].border = f_border
582
583
                    base_period_total = Decimal(0.0)
584
585
                    for j in range(0, base_period_data_ca_len):
586
                        current_col_number += 1
587
                        col = format_cell.get_column_letter(current_col_number)
588
589
                        ws[col + str(current_row_number)].font = title_font
590
                        ws[col + str(current_row_number)].alignment = c_c_alignment
591
                        ws[col + str(current_row_number)] = round2(base_period_data['values'][j][i], 2) \
592
                            if i < len(base_period_data['values'][j]) else None
593
                        if i < len(base_period_timestamps[0]):
594
                            base_period_total += base_period_data['values'][j][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)].font = title_font
600
                    ws[col + str(current_row_number)].alignment = c_c_alignment
601
                    ws[col + str(current_row_number)] = round2(base_period_total, 2) \
602
                        if i < len(base_period_timestamps[0]) else None
603
                    ws[col + str(current_row_number)].border = f_border
604
605
                    current_col_number += 1
606
                    col = format_cell.get_column_letter(current_col_number)
607
608
                    ws[col + str(current_row_number)].font = title_font
609
                    ws[col + str(current_row_number)].alignment = c_c_alignment
610
                    ws[col + str(current_row_number)] = reporting_period_timestamps[0][i] \
611
                        if i < len(reporting_period_timestamps[0]) else None
612
                    ws[col + str(current_row_number)].border = f_border
613
614
                    reporting_period_total = Decimal(0.0)
615
616
                    for j in range(0, reporting_period_data_ca_len):
617
                        current_col_number += 1
618
                        col = format_cell.get_column_letter(current_col_number)
619
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)] = round2(reporting_period_data['values'][j][i], 2) \
623
                            if i < len(reporting_period_data['values'][j]) else None
624
                        if i < len(reporting_period_timestamps[0]):
625
                            reporting_period_total += reporting_period_data['values'][j][i]
626
                        ws[col + str(current_row_number)].border = f_border
627
628
                    current_col_number += 1
629
                    col = format_cell.get_column_letter(current_col_number)
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)] = round2(reporting_period_total, 2) \
633
                        if i < len(reporting_period_timestamps[0]) else None
634
                    ws[col + str(current_row_number)].border = f_border
635
636
                    current_row_number += 1
637
638
                current_col_number = 2
639
                col = format_cell.get_column_letter(current_col_number)
640
                ws[col + str(current_row_number)].font = title_font
641
                ws[col + str(current_row_number)].alignment = c_c_alignment
642
                ws[col + str(current_row_number)] = _('Subtotal')
643
                ws[col + str(current_row_number)].border = f_border
644
645
                base_period_subtotals = Decimal(0.0)
646
647
                for i in range(0, base_period_data_ca_len):
648
                    current_col_number += 1
649
                    col = format_cell.get_column_letter(current_col_number)
650
                    ws[col + str(current_row_number)].font = title_font
651
                    ws[col + str(current_row_number)].alignment = c_c_alignment
652
                    ws[col + str(current_row_number)] = round2(base_period_data['subtotals'][i], 2)
653
                    base_period_subtotals += base_period_data['subtotals'][i]
654
                    ws[col + str(current_row_number)].border = f_border
655
656
                current_col_number += 1
657
                col = format_cell.get_column_letter(current_col_number)
658
                ws[col + str(current_row_number)].font = title_font
659
                ws[col + str(current_row_number)].alignment = c_c_alignment
660
                ws[col + str(current_row_number)] = round2(base_period_subtotals, 2)
661
                ws[col + str(current_row_number)].border = f_border
662
663
                current_col_number += 1
664
                col = format_cell.get_column_letter(current_col_number)
665
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)] = _('Subtotal')
669
                ws[col + str(current_row_number)].border = f_border
670
671
                reporting_period_subtotals = Decimal(0.0)
672
673
                for i in range(0, reporting_period_data_ca_len):
674
                    current_col_number += 1
675
                    col = format_cell.get_column_letter(current_col_number)
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)] = round2(reporting_period_data['subtotals'][i], 2)
679
                    reporting_period_subtotals += reporting_period_data['subtotals'][i]
680
                    ws[col + str(current_row_number)].border = f_border
681
682
                current_col_number += 1
683
                col = format_cell.get_column_letter(current_col_number)
684
                ws[col + str(current_row_number)].font = title_font
685
                ws[col + str(current_row_number)].alignment = c_c_alignment
686
                ws[col + str(current_row_number)] = round2(reporting_period_subtotals, 2)
687
                ws[col + str(current_row_number)].border = f_border
688
689
                for i in range(0, reporting_period_data_ca_len):
690
                    # line
691
                    line = LineChart()
692
                    line.title = _('Base Period Income') + " / " \
693
                        + _('Reporting Period Income') + ' - ' \
694
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
695
                    labels = Reference(ws, min_col=2 + base_period_data_ca_len + 1 + 1,
696
                                       min_row=table_start_row_number + 1,
697
                                       max_row=table_start_row_number + len(reporting_period_timestamps[0]))
698
                    base_line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
699
                                               max_row=table_start_row_number + len(reporting_period_timestamps[0]))
700
                    reporting_line_data = Reference(ws, min_col=3 + base_period_data_ca_len + 1 + 1 + i,
701
                                                    min_row=table_start_row_number,
702
                                                    max_row=table_start_row_number
703
                                                    + len(reporting_period_timestamps[0]))
704
                    line.add_data(base_line_data, titles_from_data=True)
705
                    line.add_data(reporting_line_data, titles_from_data=True)
706
                    line.set_categories(labels)
707
                    for j in range(len(line.series)):
708
                        line.series[j].marker.symbol = "auto"
709
                        line.series[j].smooth = True
710
                    line.x_axis.crosses = 'min'
711
                    line.height = 8.25
712
                    line.width = 24
713
                    chart_col = 'B'
714
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
715
                    ws.add_chart(line, chart_cell)
716
717
                current_row_number += 2
718
719
    ####################################################################################################################
720
    if "child_space" not in report.keys() or "energy_category_names" not in report['child_space'].keys() or \
721
            len(report['child_space']["energy_category_names"]) == 0 \
722
            or 'child_space_names_array' not in report['child_space'].keys() \
723
            or report['child_space']['energy_category_names'] is None \
724
            or len(report['child_space']['child_space_names_array']) == 0 \
725
            or len(report['child_space']['child_space_names_array'][0]) == 0:
726
        pass
727
    else:
728
        child = report['child_space']
729
730
        ws['B' + str(current_row_number)].font = title_font
731
        ws['B' + str(current_row_number)] = name + ' ' + _('Child Spaces Data')
732
733
        current_row_number += 1
734
        table_start_row_number = current_row_number
735
736
        ws.row_dimensions[current_row_number].height = 60
737
        ws['B' + str(current_row_number)].fill = table_fill
738
        ws['B' + str(current_row_number)].font = name_font
739
        ws['B' + str(current_row_number)].alignment = c_c_alignment
740
        ws['B' + str(current_row_number)].border = f_border
741
        ws['B' + str(current_row_number)] = _('Child Space')
742
        ca_len = len(child['energy_category_names'])
743
744
        col = ''
745
746
        for i in range(0, ca_len):
747
            col = chr(ord('C') + i)
748
            ws[col + str(current_row_number)].fill = table_fill
749
            ws[col + str(current_row_number)].font = name_font
750
            ws[col + str(current_row_number)].alignment = c_c_alignment
751
            ws[col + str(current_row_number)].border = f_border
752
            ws[col + str(current_row_number)] = child['energy_category_names'][i] + ' ' + '(' + child['units'][i] + ')'
753
754
        col = chr(ord(col) + 1)
755
        ws[col + str(current_row_number)].fill = table_fill
756
        ws[col + str(current_row_number)].font = name_font
757
        ws[col + str(current_row_number)].alignment = c_c_alignment
758
        ws[col + str(current_row_number)].border = f_border
759
        ws[col + str(current_row_number)] = _('Total') + ' (' + report['reporting_period']['total_unit'] + ')'
760
761
        space_len = len(child['child_space_names_array'][0])
762
763
        for i in range(0, space_len):
764
            current_row_number += 1
765
            row = str(current_row_number)
766
767
            ws['B' + row].font = title_font
768
            ws['B' + row].alignment = c_c_alignment
769
            ws['B' + row] = child['child_space_names_array'][0][i]
770
            ws['B' + row].border = f_border
771
772
            col = ''
773
            periodic_sum = Decimal(0.0)
774
775
            for j in range(0, ca_len):
776
                col = chr(ord('C') + j)
777
                ws[col + row].font = name_font
778
                ws[col + row].alignment = c_c_alignment
779
                periodic_sum += child['subtotals_array'][j][i]
780
                ws[col + row] = round2(child['subtotals_array'][j][i], 2)
781
                ws[col + row].border = f_border
782
783
            col = chr(ord(col) + 1)
784
            ws[col + row].font = name_font
785
            ws[col + row].alignment = c_c_alignment
786
            ws[col + row] = round2(periodic_sum, 2)
787
            ws[col + row].border = f_border
788
789
        table_end_row_number = current_row_number
790
791
        current_row_number += 1
792
793
        chart_start_row_number = current_row_number
794
795
        # Pie
796
        for i in range(0, ca_len):
797
            pie = PieChart()
798
            labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
799
            pie_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
800
                                 max_row=table_end_row_number)
801
            pie.add_data(pie_data, titles_from_data=True)
802
            pie.set_categories(labels)
803
            pie.height = 6.6
804
            pie.width = 8
805
            pie.title = ws.cell(column=3 + i, row=table_start_row_number).value
806
            s1 = pie.series[0]
807
            s1.dLbls = DataLabelList()
808
            s1.dLbls.showCatName = False
809
            s1.dLbls.showVal = False
810
            s1.dLbls.showPercent = True
811
            if i % 2 == 0:
812
                chart_cell = 'B' + str(chart_start_row_number)
813
            else:
814
                chart_cell = 'E' + str(chart_start_row_number)
815
                chart_start_row_number += 5
816
            ws.add_chart(pie, chart_cell)
817
818
        current_row_number = chart_start_row_number
819
820
        if ca_len % 2 == 1:
821
            current_row_number += 5
822
823
        current_row_number += 1
824
825
    ####################################################################################################################
826
    current_sheet_parameters_row_number = table_start_draw_flag + len(reporting_period_data['names']) * 6 + 1
827
    if 'parameters' not in report.keys() or \
828
            report['parameters'] is None or \
829
            'names' not in report['parameters'].keys() or \
830
            report['parameters']['names'] is None or \
831
            len(report['parameters']['names']) == 0 or \
832
            'timestamps' not in report['parameters'].keys() or \
833
            report['parameters']['timestamps'] is None or \
834
            len(report['parameters']['timestamps']) == 0 or \
835
            'values' not in report['parameters'].keys() or \
836
            report['parameters']['values'] is None or \
837
            len(report['parameters']['values']) == 0 or \
838
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
839
        pass
840
    else:
841
842
        ################################################################################################################
843
        # new worksheet
844
        ################################################################################################################
845
846
        parameters_data = report['parameters']
847
        parameters_names_len = len(parameters_data['names'])
848
849
        file_name = "Space"+re.sub(r'[^A-Z]', '', ws.title.strip('S')) + "_"
850
        parameters_ws = wb.create_sheet(file_name + _('Parameters'))
851
852
        parameters_timestamps_data_max_len = \
853
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
854
855
        # Row height
856
        parameters_ws.row_dimensions[1].height = 102
857
        for i in range(2, 7 + 1):
858
            parameters_ws.row_dimensions[i].height = 42
859
860
        for i in range(8, parameters_timestamps_data_max_len + 10):
861
            parameters_ws.row_dimensions[i].height = 60
862
863
        # Col width
864
        parameters_ws.column_dimensions['A'].width = 1.5
865
866
        parameters_ws.column_dimensions['B'].width = 25.0
867
868
        for i in range(3, 12 + parameters_names_len * 3):
869
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
870
871
        # Img
872
        img = Image("excelexporters/myems.png")
873
        parameters_ws.add_image(img, 'A1')
874
875
        # Title
876
        parameters_ws['B3'].alignment = b_r_alignment
877
        parameters_ws['B3'] = _('Name') + ':'
878
        parameters_ws['C3'].border = b_border
879
        parameters_ws['C3'].alignment = b_c_alignment
880
        parameters_ws['C3'] = name
881
882
        parameters_ws['D3'].alignment = b_r_alignment
883
        parameters_ws['D3'] = _('Period Type') + ':'
884
        parameters_ws['E3'].border = b_border
885
        parameters_ws['E3'].alignment = b_c_alignment
886
        parameters_ws['E3'] = period_type
887
888
        parameters_ws['B4'].alignment = b_r_alignment
889
        parameters_ws['B4'] = _('Reporting Start Datetime') + ':'
890
        parameters_ws['C4'].border = b_border
891
        parameters_ws['C4'].alignment = b_c_alignment
892
        parameters_ws['C4'] = reporting_start_datetime_local
893
894
        parameters_ws['D4'].alignment = b_r_alignment
895
        parameters_ws['D4'] = _('Reporting End Datetime') + ':'
896
        parameters_ws['E4'].border = b_border
897
        parameters_ws['E4'].alignment = b_c_alignment
898
        parameters_ws['E4'] = reporting_end_datetime_local
899
900
        parameters_ws_current_row_number = 6
901
902
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
903
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + _('Parameters')
904
905
        parameters_ws_current_row_number += 1
906
907
        parameters_table_start_row_number = parameters_ws_current_row_number
908
909
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
910
911
        parameters_ws_current_row_number += 1
912
913
        table_current_col_number = 2
914
915
        for i in range(0, parameters_names_len):
916
917
            if len(parameters_data['timestamps'][i]) == 0:
918
                continue
919
920
            col = format_cell.get_column_letter(table_current_col_number)
921
922
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
923
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
924
925
            col = format_cell.get_column_letter(table_current_col_number + 1)
926
927
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
928
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
929
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
930
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
931
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
932
933
            table_current_row_number = parameters_ws_current_row_number
934
935
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
936
                col = format_cell.get_column_letter(table_current_col_number)
937
938
                parameters_ws[col + str(table_current_row_number)].border = f_border
939
                parameters_ws[col + str(table_current_row_number)].font = title_font
940
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
941
                parameters_ws[col + str(table_current_row_number)] = value
942
943
                col = format_cell.get_column_letter(table_current_col_number + 1)
944
945
                parameters_ws[col + str(table_current_row_number)].border = f_border
946
                parameters_ws[col + str(table_current_row_number)].font = title_font
947
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
948
                parameters_ws[col + str(table_current_row_number)] = round2(parameters_data['values'][i][j], 2)
949
950
                table_current_row_number += 1
951
952
            table_current_col_number = table_current_col_number + 3
953
954
        ################################################################################################################
955
        # parameters chart and parameters table
956
        ################################################################################################################
957
958
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
959
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + _('Parameters')
960
961
        current_sheet_parameters_row_number += 1
962
963
        chart_start_row_number = current_sheet_parameters_row_number
964
965
        col_index = 0
966
967
        for i in range(0, parameters_names_len):
968
969
            if len(parameters_data['timestamps'][i]) == 0:
970
                continue
971
972
            line = LineChart()
973
            data_col = 3 + col_index * 3
974
            labels_col = 2 + col_index * 3
975
            col_index += 1
976
            line.title = _('Parameters') + ' - ' + \
977
                parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
978
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
979
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
980
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
981
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
982
            line.add_data(line_data, titles_from_data=True)
983
            line.set_categories(labels)
984
            line_data = line.series[0]
985
            line_data.marker.symbol = "auto"
986
            line_data.smooth = True
987
            line.x_axis.crosses = 'min'
988
            line.height = 8.25
989
            line.width = 24
990
            chart_col = 'B'
991
            chart_cell = chart_col + str(chart_start_row_number)
992
            chart_start_row_number += 6
993
            ws.add_chart(line, chart_cell)
994
995
        current_sheet_parameters_row_number = chart_start_row_number
996
997
        current_sheet_parameters_row_number += 1
998
    ####################################################################################################################
999
    filename = str(uuid.uuid4()) + '.xlsx'
1000
    wb.save(filename)
1001
1002
    return filename
1003
1004
1005
def reporting_period_values_periodic_sum(reporting_period_data, periodic_index, ca_len):
1006
    periodic_sum = Decimal(0.0)
1007
    for i in range(0, ca_len):
1008
        periodic_sum += reporting_period_data['values'][i][periodic_index]
1009
1010
    return periodic_sum
1011
1012
1013
def timestamps_data_all_equal_0(lists):
1014
    for i, value in enumerate(list(lists)):
1015
        if len(value) > 0:
1016
            return False
1017
1018
    return True
1019
1020
1021
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
1022
    max_len = 0
1023
    for i, value in enumerate(list(parameters_timestamps_lists)):
1024
        if len(value) > max_len:
1025
            max_len = len(value)
1026
1027
    return max_len
1028
1029
1030
def timestamps_data_not_equal_0(lists):
1031
    number = 0
1032
    for i, value in enumerate(list(lists)):
1033
        if len(value) > 0:
1034
            number += 1
1035
    return number
1036
1037
1038 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...
1039
    timestamps = base_period_data['timestamps']
1040
1041
    if len(timestamps) == 0:
1042
        return False
1043
1044
    for timestamp in timestamps:
1045
        if len(timestamp) > 0:
1046
            return True
1047
1048
    return False
1049