Issues (1656)

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