Passed
Push — master ( 414b30...be43ee )
by Guangyu
14:19 queued 13s
created

is_base_period_timestamp_exists()   A

Complexity

Conditions 4

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Importance

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