excelexporters.storeenergyitem.generate_excel()   F
last analyzed

Complexity

Conditions 70

Size

Total Lines 717
Code Lines 541

Duplication

Lines 717
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 541
dl 717
loc 717
rs 0
c 0
b 0
f 0
cc 70
nop 8

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like excelexporters.storeenergyitem.generate_excel() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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