Issues (1577)

excelexporters/combinedequipmentincome.py (4 issues)

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