Passed
Push — master ( 5501ba...4103db )
by Guangyu
16:55 queued 12s
created

excelexporters.shopfloorsaving.generate_excel()   F

Complexity

Conditions 67

Size

Total Lines 721
Code Lines 540

Duplication

Lines 721
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 540
dl 721
loc 721
rs 0
c 0
b 0
f 0
cc 67
nop 5

How to fix   Long Method    Complexity   

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.shopfloorsaving.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.

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