Passed
Push — master ( d35f3b...b6c9eb )
by Guangyu
07:20 queued 12s
created

excelexporters.storecarbon   F

Complexity

Total Complexity 77

Size/Duplication

Total Lines 761
Duplicated Lines 94.74 %

Importance

Changes 0
Metric Value
wmc 77
eloc 559
dl 721
loc 761
rs 2.24
c 0
b 0
f 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
F generate_excel() 682 682 66
A get_parameters_timestamps_lists_max_len() 0 7 3
B export() 39 39 5
A timestamps_data_all_equal_0() 0 6 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like excelexporters.storecarbon 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.

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