Passed
Push — master ( 2d8465...2affa2 )
by Guangyu
17:45 queued 10s
created

excelexporters.combinedequipmentsaving.sum_list()   A

Complexity

Conditions 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
import base64
2
import uuid
3
import os
4
from openpyxl.chart import (
5
    PieChart,
6
    LineChart,
7
    BarChart,
8
    Reference,
9
)
10
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
11
from openpyxl.drawing.image import Image
12
from openpyxl import Workbook
13
from openpyxl.chart.label import DataLabelList
14
15
####################################################################################################################
16
# PROCEDURES
17
# Step 1: Validate the report data
18
# Step 2: Generate excel file
19
# Step 3: Encode the excel file bytes to Base64
20
####################################################################################################################
21
22
23 View Code Duplication
def export(report,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
24
           name,
25
           reporting_start_datetime_local,
26
           reporting_end_datetime_local,
27
           period_type):
28
    ####################################################################################################################
29
    # Step 1: Validate the report data
30
    ####################################################################################################################
31
    if report is None:
32
        return None
33
    print(report)
34
35
    ####################################################################################################################
36
    # Step 2: Generate excel file from the report data
37
    ####################################################################################################################
38
    filename = generate_excel(report,
39
                              name,
40
                              reporting_start_datetime_local,
41
                              reporting_end_datetime_local,
42
                              period_type)
43
    ####################################################################################################################
44
    # Step 3: Encode the excel file to Base64
45
    ####################################################################################################################
46
    try:
47
        with open(filename, 'rb') as binary_file:
48
            binary_file_data = binary_file.read()
49
    except IOError as ex:
50
        pass
51
52
    # Base64 encode the bytes
53
    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...
54
    # get the Base64 encoded data using human-readable characters.
55
    base64_message = base64_encoded_data.decode('utf-8')
56
    # delete the file from server
57
    try:
58
        os.remove(filename)
59
    except NotImplementedError as ex:
60
        pass
61
    return base64_message
62
63
64
def generate_excel(report,
65
                   name,
66
                   reporting_start_datetime_local,
67
                   reporting_end_datetime_local,
68
                   period_type):
69
    wb = Workbook()
70
    ws = wb.active
71
72
    # Row height
73
    ws.row_dimensions[1].height = 102
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
80
    ws.column_dimensions['B'].width = 25.0
81
82
    for i in range(ord('C'), ord('L')):
83
        ws.column_dimensions[chr(i)].width = 15.0
84
85
    # Font
86
    name_font = Font(name='Constantia', size=15, bold=True)
87
    title_font = Font(name='宋体', size=15, bold=True)
88
    data_font = Font(name='Franklin Gothic Book', size=11)
89
90
    table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
91
    f_border = Border(left=Side(border_style='medium', color='00000000'),
92
                      right=Side(border_style='medium', color='00000000'),
93
                      bottom=Side(border_style='medium', color='00000000'),
94
                      top=Side(border_style='medium', color='00000000')
95
                      )
96
    b_border = Border(
97
        bottom=Side(border_style='medium', color='00000000'),
98
    )
99
100
    b_c_alignment = Alignment(vertical='bottom',
101
                              horizontal='center',
102
                              text_rotation=0,
103
                              wrap_text=True,
104
                              shrink_to_fit=False,
105
                              indent=0)
106
    c_c_alignment = Alignment(vertical='center',
107
                              horizontal='center',
108
                              text_rotation=0,
109
                              wrap_text=True,
110
                              shrink_to_fit=False,
111
                              indent=0)
112
    b_r_alignment = Alignment(vertical='bottom',
113
                              horizontal='right',
114
                              text_rotation=0,
115
                              wrap_text=True,
116
                              shrink_to_fit=False,
117
                              indent=0)
118
    c_r_alignment = Alignment(vertical='bottom',
119
                              horizontal='center',
120
                              text_rotation=0,
121
                              wrap_text=True,
122
                              shrink_to_fit=False,
123
                              indent=0)
124
125
    # Img
126
    img = Image("excelexporters/myems.png")
127
    img.width = img.width * 0.85
128
    img.height = img.height * 0.85
129
    # img = Image("myems.png")
130
    ws.add_image(img, 'B1')
131
132
    # Title
133
    ws.row_dimensions[3].height = 60
134
135
    ws['B3'].font = name_font
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'].font = name_font
141
    ws['C3'] = name
142
143
    ws['D3'].font = name_font
144
    ws['D3'].alignment = b_r_alignment
145
    ws['D3'] = 'Period:'
146
    ws['E3'].border = b_border
147
    ws['E3'].alignment = b_c_alignment
148
    ws['E3'].font = name_font
149
    ws['E3'] = period_type
150
151
    ws['F3'].font = name_font
152
    ws['F3'].alignment = b_r_alignment
153
    ws['F3'] = 'Date:'
154
    ws['G3'].alignment = b_c_alignment
155
    ws['G3'].font = name_font
156
    ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local
157
    ws['G3'].border = b_border
158
    ws.merge_cells("G3:H3")
159
160
    if "reporting_period" not in report.keys() or \
161
            "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0:
162
        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...
163
        wb.save(filename)
164
165
        return filename
166
167
    ##################################
168
169
    current_row_number = 6
170
171
    reporting_period_data = report['reporting_period']
172
173
    has_names_data_flag = True
174
175
    if "names" not in reporting_period_data.keys() or \
176
            reporting_period_data['names'] is None or \
177
            len(reporting_period_data['names']) == 0:
178
        has_names_data_flag = False
179
180
    if has_names_data_flag:
181
        ws['B' + str(current_row_number)].font = title_font
182
        ws['B' + str(current_row_number)] = name + ' 报告期节约'
183
184
        current_row_number += 1
185
186
        category = reporting_period_data['names']
187
        ca_len = len(category)
188
189
        ws.row_dimensions[current_row_number].height = 75
190
        ws['B' + str(current_row_number)].fill = table_fill
191
        ws['B' + str(current_row_number)].border = f_border
192
193
        col = 'C'
194
195
        for i in range(0, ca_len):
196
            ws[col + str(current_row_number)].fill = table_fill
197
            ws[col + str(current_row_number)].font = name_font
198
            ws[col + str(current_row_number)].alignment = c_c_alignment
199
            ws[col + str(current_row_number)].border = f_border
200
            ws[col + str(current_row_number)] = \
201
                reporting_period_data['names'][i] + " (基线-实际) (" + reporting_period_data['units'][i] + ")"
202
203
            col = chr(ord(col) + 1)
204
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)] = '吨标准煤 (基线-实际) (TCE)'
210
211
        col = chr(ord(col) + 1)
212
213
        ws[col + str(current_row_number)].fill = table_fill
214
        ws[col + str(current_row_number)].font = name_font
215
        ws[col + str(current_row_number)].alignment = c_c_alignment
216
        ws[col + str(current_row_number)].border = f_border
217
        ws[col + str(current_row_number)] = '吨二氧化碳排放 (基线-实际) (TCO2E)'
218
219
        col = chr(ord(col) + 1)
220
221
        current_row_number += 1
222
223
        ws['B' + str(current_row_number)].font = title_font
224
        ws['B' + str(current_row_number)].alignment = c_c_alignment
225
        ws['B' + str(current_row_number)].border = f_border
226
        ws['B' + str(current_row_number)] = '节约'
227
228
        col = 'C'
229
230
        for i in range(0, ca_len):
231
            ws[col + str(current_row_number)].font = name_font
232
            ws[col + str(current_row_number)].alignment = c_c_alignment
233
            ws[col + str(current_row_number)].border = f_border
234
            ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_saving'][i], 2)
235
236
            col = chr(ord(col) + 1)
237
238
        ws[col + str(current_row_number)].font = name_font
239
        ws[col + str(current_row_number)].alignment = c_c_alignment
240
        ws[col + str(current_row_number)].border = f_border
241
        ws[col + str(current_row_number)] = round(reporting_period_data['total_in_kgce_saving'] / 1000, 2)
242
243
        col = chr(ord(col) + 1)
244
245
        ws[col + str(current_row_number)].font = name_font
246
        ws[col + str(current_row_number)].alignment = c_c_alignment
247
        ws[col + str(current_row_number)].border = f_border
248
        ws[col + str(current_row_number)] = round(reporting_period_data['total_in_kgco2e_saving'] / 1000, 2)
249
250
        col = chr(ord(col) + 1)
251
252
        current_row_number += 1
253
254
        ws['B' + str(current_row_number)].font = title_font
255
        ws['B' + str(current_row_number)].alignment = c_c_alignment
256
        ws['B' + str(current_row_number)].border = f_border
257
        ws['B' + str(current_row_number)] = '环比'
258
259
        col = 'C'
260
261
        for i in range(0, ca_len):
262
            ws[col + str(current_row_number)].font = name_font
263
            ws[col + str(current_row_number)].alignment = c_c_alignment
264
            ws[col + str(current_row_number)].border = f_border
265
            ws[col + str(current_row_number)] = str(
266
                round(reporting_period_data['increment_rates_saving'][i] * 100, 2)) + '%' \
267
                if reporting_period_data['increment_rates_saving'][i] is not None else '-'
268
269
            col = chr(ord(col) + 1)
270
271
        ws[col + str(current_row_number)].font = name_font
272
        ws[col + str(current_row_number)].alignment = c_c_alignment
273
        ws[col + str(current_row_number)].border = f_border
274
        ws[col + str(current_row_number)] = str(
275
            round(reporting_period_data['increment_rate_in_kgce_saving'] * 100, 2)) + '%' \
276
            if reporting_period_data['increment_rate_in_kgce_saving'] is not None else '-'
277
278
        col = chr(ord(col) + 1)
279
280
        ws[col + str(current_row_number)].font = name_font
281
        ws[col + str(current_row_number)].alignment = c_c_alignment
282
        ws[col + str(current_row_number)].border = f_border
283
        ws[col + str(current_row_number)] = str(
284
            round(reporting_period_data['increment_rate_in_kgco2e_saving'] * 100, 2)) + '%' \
285
            if reporting_period_data['increment_rate_in_kgco2e_saving'] is not None else '-'
286
287
        col = chr(ord(col) + 1)
288
289
        current_row_number += 2
290
291
        ws['B' + str(current_row_number)].font = title_font
292
        ws['B' + str(current_row_number)] = name + ' 吨标准煤(TCE)占比'
293
294
        current_row_number += 1
295
        table_start_row_number = current_row_number
296
        chart_start_row_number = current_row_number
297
298
        ws.row_dimensions[current_row_number].height = 60
299
        ws['B' + str(current_row_number)].fill = table_fill
300
        ws['B' + str(current_row_number)].border = f_border
301
302
        ws['C' + str(current_row_number)].fill = table_fill
303
        ws['C' + str(current_row_number)].font = name_font
304
        ws['C' + str(current_row_number)].alignment = c_c_alignment
305
        ws['C' + str(current_row_number)].border = f_border
306
        ws['C' + str(current_row_number)] = '节约'
307
308
        ws['D' + str(current_row_number)].fill = table_fill
309
        ws['D' + str(current_row_number)].font = name_font
310
        ws['D' + str(current_row_number)].alignment = c_c_alignment
311
        ws['D' + str(current_row_number)].border = f_border
312
        ws['D' + str(current_row_number)] = '吨标准煤(TCE) 节约占比'
313
314
        current_row_number += 1
315
316
        subtotals_in_kgce_saving_sum = sum_list(reporting_period_data['subtotals_in_kgce_saving'])
317
318
        for i in range(0, ca_len):
319
            ws['B' + str(current_row_number)].font = title_font
320
            ws['B' + str(current_row_number)].alignment = c_c_alignment
321
            ws['B' + str(current_row_number)].border = f_border
322
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i]
323
324
            ws['C' + str(current_row_number)].font = name_font
325
            ws['C' + str(current_row_number)].alignment = c_c_alignment
326
            ws['C' + str(current_row_number)].border = f_border
327
            ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals_in_kgce_saving'][i] / 1000, 3)
328
329
            ws['D' + str(current_row_number)].font = name_font
330
            ws['D' + str(current_row_number)].alignment = c_c_alignment
331
            ws['D' + str(current_row_number)].border = f_border
332
            ws['D' + str(current_row_number)] = \
333
                str(round(abs(reporting_period_data['subtotals_in_kgce_saving'][i]) /
334
                          subtotals_in_kgce_saving_sum * 100, 2)) + '%'
335
336
            current_row_number += 1
337
338
        table_end_row_number = current_row_number - 1
339
340
        if ca_len < 4:
341
            current_row_number = current_row_number - ca_len + 4
342
343
        current_row_number += 1
344
345
        pie = PieChart()
346
        pie.title = name + ' 吨标准煤(TCE)占比'
347
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
348
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
349
        pie.add_data(pie_data, titles_from_data=True)
350
        pie.set_categories(labels)
351
        pie.height = 7.25
352
        pie.width = 9
353
        s1 = pie.series[0]
354
        s1.dLbls = DataLabelList()
355
        s1.dLbls.showCatName = False
356
        s1.dLbls.showVal = True
357
        s1.dLbls.showPercent = True
358
        ws.add_chart(pie, 'E' + str(chart_start_row_number))
359
360
        ws['B' + str(current_row_number)].font = title_font
361
        ws['B' + str(current_row_number)] = name + ' 吨二氧化碳排放(TCO2E)占比'
362
363
        current_row_number += 1
364
        table_start_row_number = current_row_number
365
        chart_start_row_number = current_row_number
366
367
        ws.row_dimensions[current_row_number].height = 60
368
        ws['B' + str(current_row_number)].fill = table_fill
369
        ws['B' + str(current_row_number)].border = f_border
370
371
        ws['C' + str(current_row_number)].fill = table_fill
372
        ws['C' + str(current_row_number)].font = name_font
373
        ws['C' + str(current_row_number)].alignment = c_c_alignment
374
        ws['C' + str(current_row_number)].border = f_border
375
        ws['C' + str(current_row_number)] = '节约'
376
377
        ws['D' + str(current_row_number)].fill = table_fill
378
        ws['D' + str(current_row_number)].font = name_font
379
        ws['D' + str(current_row_number)].alignment = c_c_alignment
380
        ws['D' + str(current_row_number)].border = f_border
381
        ws['D' + str(current_row_number)] = '吨二氧化碳排放(TCO2E) 节约占比'
382
383
        current_row_number += 1
384
385
        subtotals_in_kgco2e_saving_sum = sum_list(reporting_period_data['subtotals_in_kgco2e_saving'])
386
387
        for i in range(0, ca_len):
388
            ws['B' + str(current_row_number)].font = title_font
389
            ws['B' + str(current_row_number)].alignment = c_c_alignment
390
            ws['B' + str(current_row_number)].border = f_border
391
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i]
392
393
            ws['C' + str(current_row_number)].font = name_font
394
            ws['C' + str(current_row_number)].alignment = c_c_alignment
395
            ws['C' + str(current_row_number)].border = f_border
396
            ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals_in_kgco2e_saving'][i] / 1000, 3)
397
398
            ws['D' + str(current_row_number)].font = name_font
399
            ws['D' + str(current_row_number)].alignment = c_c_alignment
400
            ws['D' + str(current_row_number)].border = f_border
401
            ws['D' + str(current_row_number)] = \
402
                str(round(abs(reporting_period_data['subtotals_in_kgco2e_saving'][i]) /
403
                          subtotals_in_kgco2e_saving_sum * 100, 2)) + '%'
404
405
            current_row_number += 1
406
407
        table_end_row_number = current_row_number - 1
408
409
        if ca_len < 4:
410
            current_row_number = current_row_number - ca_len + 4
411
412
        current_row_number += 1
413
414
        pie = PieChart()
415
        pie.title = name + ' 吨二氧化碳排放(TCO2E)占比'
416
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
417
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
418
        pie.add_data(pie_data, titles_from_data=True)
419
        pie.set_categories(labels)
420
        pie.height = 7.25
421
        pie.width = 9
422
        s1 = pie.series[0]
423
        s1.dLbls = DataLabelList()
424
        s1.dLbls.showCatName = False
425
        s1.dLbls.showVal = True
426
        s1.dLbls.showPercent = True
427
        ws.add_chart(pie, 'E' + str(chart_start_row_number))
428
429
    #############################################
430
431
    has_values_saving_data = True
432
    has_timestamps_data = True
433
434
    if 'values_saving' not in reporting_period_data.keys() or \
435
            reporting_period_data['values_saving'] is None or \
436
            len(reporting_period_data['values_saving']) == 0:
437
        has_values_saving_data = False
438
439
    if 'timestamps' not in reporting_period_data.keys() or \
440
            reporting_period_data['timestamps'] is None or \
441
            len(reporting_period_data['timestamps']) == 0 or \
442
            len(reporting_period_data['timestamps'][0]) == 0:
443
        has_timestamps_data = False
444
445
    if has_values_saving_data and has_timestamps_data:
446
        ca_len = len(reporting_period_data['names'])
447
        time = reporting_period_data['timestamps'][0]
448
449
        ws['B' + str(current_row_number)].font = title_font
450
        ws['B' + str(current_row_number)] = name + ' 详细数据'
451
452
        current_row_number += 1
453
454
        chart_start_row_number = current_row_number
455
456
        current_row_number += ca_len * 6
457
        table_start_row_number = current_row_number
458
459
        ws.row_dimensions[current_row_number].height = 60
460
        ws['B' + str(current_row_number)].fill = table_fill
461
        ws['B' + str(current_row_number)].font = title_font
462
        ws['B' + str(current_row_number)].alignment = c_c_alignment
463
        ws['B' + str(current_row_number)].border = f_border
464
        ws['B' + str(current_row_number)] = '日期时间'
465
466
        col = 'C'
467
468
        for i in range(0, ca_len):
469
            ws[col + str(current_row_number)].fill = table_fill
470
            ws[col + str(current_row_number)].font = title_font
471
            ws[col + str(current_row_number)].alignment = c_c_alignment
472
            ws[col + str(current_row_number)].border = f_border
473
            ws[col + str(current_row_number)] = \
474
                reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
475
            col = chr(ord(col) + 1)
476
477
        current_row_number += 1
478
479
        for i in range(0, len(time)):
480
            ws['B' + str(current_row_number)].font = title_font
481
            ws['B' + str(current_row_number)].alignment = c_c_alignment
482
            ws['B' + str(current_row_number)].border = f_border
483
            ws['B' + str(current_row_number)] = time[i]
484
485
            col = 'C'
486
            for j in range(0, ca_len):
487
                ws[col + str(current_row_number)].font = title_font
488
                ws[col + str(current_row_number)].alignment = c_c_alignment
489
                ws[col + str(current_row_number)].border = f_border
490
                ws[col + str(current_row_number)] = round(reporting_period_data['values_saving'][j][i], 2) \
491
                    if reporting_period_data['values_saving'][j][i] is not None else 0.00
492
                col = chr(ord(col) + 1)
493
494
            current_row_number += 1
495
496
        table_end_row_number = current_row_number - 1
497
498
        ws['B' + str(current_row_number)].font = title_font
499
        ws['B' + str(current_row_number)].alignment = c_c_alignment
500
        ws['B' + str(current_row_number)].border = f_border
501
        ws['B' + str(current_row_number)] = '小计'
502
503
        col = 'C'
504
505
        for i in range(0, ca_len):
506
            ws[col + str(current_row_number)].font = title_font
507
            ws[col + str(current_row_number)].alignment = c_c_alignment
508
            ws[col + str(current_row_number)].border = f_border
509
            ws[col + str(current_row_number)] = round(reporting_period_data['subtotals_saving'][i], 2)
510
            col = chr(ord(col) + 1)
511
512
        current_row_number += 2
513
514
        format_time_width_number = 1.0
515
        min_len_number = 1.0
516
        min_width_number = 11.0  # format_time_width_number * min_len_number + 4 and min_width_number > 11.0
517
518
        if period_type == 'hourly':
519
            format_time_width_number = 4.0
520
            min_len_number = 2
521
            min_width_number = 12.0
522
        elif period_type == 'daily':
523
            format_time_width_number = 2.5
524
            min_len_number = 4
525
            min_width_number = 14.0
526
        elif period_type == 'monthly':
527
            format_time_width_number = 2.1
528
            min_len_number = 4
529
            min_width_number = 12.4
530
        elif period_type == 'yearly':
531
            format_time_width_number = 1.5
532
            min_len_number = 5
533
            min_width_number = 11.5
534
535
        for i in range(0, ca_len):
536
            line = LineChart()
537
            line.title = '报告期节约 - ' + \
538
                         reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
539
            labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
540
            line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number)
541
            line.add_data(line_data, titles_from_data=True)
542
            line.set_categories(labels)
543
            line_data = line.series[0]
544
            line_data.marker.symbol = "circle"
545
            line_data.smooth = True
546
            line.height = 8.25
547
            line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number
548
            if line.width > 24:
549
                line.width = 24
550
            line.x_axis.crosses = 'min'
551
            line.dLbls = DataLabelList()
552
            line.dLbls.dLblPos = 't'
553
            line.dLbls.showVal = True
554
            line.dLbls.showPercent = False
555
            chart_col = 'B'
556
            chart_cell = chart_col + str(chart_start_row_number)
557
            chart_start_row_number += 6
558
            ws.add_chart(line, chart_cell)
559
560
    filename = str(uuid.uuid4()) + '.xlsx'
561
    wb.save(filename)
562
563
    return filename
564
565
566
def sum_list(lists):
567
    total = 0
568
569
    for i in range(0, len(lists)):
570
        total += abs(lists[i])
571
572
    return total
573