Passed
Push — master ( 9dd008...c3a7b3 )
by Guangyu
31:28 queued 10:11
created

excelexporters.shopfloorcost   F

Complexity

Total Complexity 84

Size/Duplication

Total Lines 845
Duplicated Lines 24.97 %

Importance

Changes 0
Metric Value
wmc 84
eloc 616
dl 211
loc 845
rs 1.984
c 0
b 0
f 0

6 Functions

Rating   Name   Duplication   Size   Complexity  
A decimal_to_column() 19 19 5
A get_parameters_timestamps_lists_max_len() 0 7 3
F generate_excel() 153 734 66
B export() 39 39 5
A timestamps_data_all_equal_0() 0 6 3
A column_to_decimal() 0 6 2

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.shopfloorcost 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
def generate_excel(report,
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
    # for i in range(2, 37 + 1):
125
    #     ws.row_dimensions[i].height = 30
126
    #
127
    # for i in range(38, 90 + 1):
128
    #     ws.row_dimensions[i].height = 30
129
130
    # Col width
131
    ws.column_dimensions['A'].width = 1.5
132
133
    ws.column_dimensions['B'].width = 25.0
134
135
    for i in range(ord('C'), ord('L')):
136
        ws.column_dimensions[chr(i)].width = 15.0
137
138
    # Font
139
    name_font = Font(name='Constantia', size=15, bold=True)
140
    title_font = Font(name='宋体', size=15, bold=True)
141
    data_font = Font(name='Franklin Gothic Book', size=11)
142
143
    table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
144
    f_border = Border(left=Side(border_style='medium', color='00000000'),
145
                      right=Side(border_style='medium', color='00000000'),
146
                      bottom=Side(border_style='medium', color='00000000'),
147
                      top=Side(border_style='medium', color='00000000')
148
                      )
149
    b_border = Border(
150
        bottom=Side(border_style='medium', color='00000000'),
151
    )
152
153
    b_c_alignment = Alignment(vertical='bottom',
154
                              horizontal='center',
155
                              text_rotation=0,
156
                              wrap_text=True,
157
                              shrink_to_fit=False,
158
                              indent=0)
159
    c_c_alignment = Alignment(vertical='center',
160
                              horizontal='center',
161
                              text_rotation=0,
162
                              wrap_text=True,
163
                              shrink_to_fit=False,
164
                              indent=0)
165
    b_r_alignment = Alignment(vertical='bottom',
166
                              horizontal='right',
167
                              text_rotation=0,
168
                              wrap_text=True,
169
                              shrink_to_fit=False,
170
                              indent=0)
171
    c_r_alignment = Alignment(vertical='bottom',
172
                              horizontal='center',
173
                              text_rotation=0,
174
                              wrap_text=True,
175
                              shrink_to_fit=False,
176
                              indent=0)
177
178
    # Img
179
    img = Image("excelexporters/myems.png")
180
    img.width = img.width * 0.85
181
    img.height = img.height * 0.85
182
    # img = Image("myems.png")
183
    ws.add_image(img, 'B1')
184
185
    # Title
186
    ws.row_dimensions[3].height = 60
187
188
    ws['B3'].font = name_font
189
    ws['B3'].alignment = b_r_alignment
190
    ws['B3'] = 'Name:'
191
    ws['C3'].border = b_border
192
    ws['C3'].alignment = b_c_alignment
193
    ws['C3'].font = name_font
194
    ws['C3'] = name
195
196
    ws['D3'].font = name_font
197
    ws['D3'].alignment = b_r_alignment
198
    ws['D3'] = 'Period:'
199
    ws['E3'].border = b_border
200
    ws['E3'].alignment = b_c_alignment
201
    ws['E3'].font = name_font
202
    ws['E3'] = period_type
203
204
    ws['F3'].font = name_font
205
    ws['F3'].alignment = b_r_alignment
206
    ws['F3'] = 'Date:'
207
    ws['G3'].alignment = b_c_alignment
208
    ws['G3'].font = name_font
209
    ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local
210
    ws.merge_cells("G3:H3")
211
212
    if "reporting_period" not in report.keys() or \
213
            "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0:
214
        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...
215
        wb.save(filename)
216
217
        return filename
218
219
    #################################################
220
221
    reporting_period_data = report['reporting_period']
222
223
    has_energy_data_flag = True
224
    if "names" not in reporting_period_data.keys() or \
225
            reporting_period_data['names'] is None or \
226
            len(reporting_period_data['names']) == 0:
227
        has_energy_data_flag = False
228
229 View Code Duplication
    if has_energy_data_flag:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
230
        ws['B6'].font = title_font
231
        ws['B6'] = name + ' 报告期成本'
232
233
        category = reporting_period_data['names']
234
        ca_len = len(category)
235
236
        ws.row_dimensions[7].height = 60
237
        ws['B7'].fill = table_fill
238
        ws['B7'].border = f_border
239
240
        ws['B8'].font = title_font
241
        ws['B8'].alignment = c_c_alignment
242
        ws['B8'] = '成本'
243
        ws['B8'].border = f_border
244
245
        ws['B9'].font = title_font
246
        ws['B9'].alignment = c_c_alignment
247
        ws['B9'] = '单位面积值'
248
        ws['B9'].border = f_border
249
250
        ws['B10'].font = title_font
251
        ws['B10'].alignment = c_c_alignment
252
        ws['B10'] = '环比'
253
        ws['B10'].border = f_border
254
255
        col = 'B'
256
257
        for i in range(0, ca_len):
258
            col = chr(ord('C') + i)
259
            ws[col + '7'].fill = table_fill
260
            ws[col + '7'].font = name_font
261
            ws[col + '7'].alignment = c_c_alignment
262
            ws[col + '7'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
263
            ws[col + '7'].border = f_border
264
265
            ws[col + '8'].font = name_font
266
            ws[col + '8'].alignment = c_c_alignment
267
            ws[col + '8'] = round(reporting_period_data['subtotals'][i], 2)
268
            ws[col + '8'].border = f_border
269
270
            ws[col + '9'].font = name_font
271
            ws[col + '9'].alignment = c_c_alignment
272
            ws[col + '9'] = round(reporting_period_data['subtotals_per_unit_area'][i], 2)
273
            ws[col + '9'].border = f_border
274
275
            ws[col + '10'].font = name_font
276
            ws[col + '10'].alignment = c_c_alignment
277
            ws[col + '10'] = str(round(reporting_period_data['increment_rates'][i] * 100, 2)) + "%" \
278
                if reporting_period_data['increment_rates'][i] is not None else "-"
279
            ws[col + '10'].border = f_border
280
281
        end_col = chr(ord(col) + 1)
282
        ws[end_col + '7'].fill = table_fill
283
        ws[end_col + '7'].font = name_font
284
        ws[end_col + '7'].alignment = c_c_alignment
285
        ws[end_col + '7'] = "总计 (" + reporting_period_data['total_unit'] + ")"
286
        ws[end_col + '7'].border = f_border
287
288
        ws[end_col + '8'].font = name_font
289
        ws[end_col + '8'].alignment = c_c_alignment
290
        ws[end_col + '8'] = round(reporting_period_data['total'], 2)
291
        ws[end_col + '8'].border = f_border
292
293
        ws[end_col + '9'].font = name_font
294
        ws[end_col + '9'].alignment = c_c_alignment
295
        ws[end_col + '9'] = round(reporting_period_data['total_per_unit_area'], 2)
296
        ws[end_col + '9'].border = f_border
297
298
        ws[end_col + '10'].font = name_font
299
        ws[end_col + '10'].alignment = c_c_alignment
300
        ws[end_col + '10'] = str(round(reporting_period_data['total_increment_rate'] * 100, 2)) + "%" \
301
            if reporting_period_data['total_increment_rate'] is not None else "-"
302
        ws[end_col + '10'].border = f_border
303
304
    else:
305
        for i in range(6, 10 + 1):
306
            ws.row_dimensions[i].height = 0.1
307
308
    #################################################
309
310
    has_ele_peak_flag = True
311
    if "toppeaks" not in reporting_period_data.keys() or \
312
            reporting_period_data['toppeaks'] is None or \
313
            len(reporting_period_data['toppeaks']) == 0:
314
        has_ele_peak_flag = False
315
316
    if has_ele_peak_flag:
317
        ws['B12'].font = title_font
318
        ws['B12'] = name + '分时用电成本'
319
320
        ws['B13'].fill = table_fill
321
        ws['B13'].font = name_font
322
        ws['B13'].alignment = c_c_alignment
323
        ws['B13'].border = f_border
324
325
        ws['C13'].fill = table_fill
326
        ws['C13'].font = name_font
327
        ws['C13'].alignment = c_c_alignment
328
        ws['C13'].border = f_border
329
        ws['C13'] = '分时用电成本'
330
331
        ws['D13'].fill = table_fill
332
        ws['D13'].font = name_font
333
        ws['D13'].alignment = c_c_alignment
334
        ws['D13'].border = f_border
335
        ws['D13'] = '分时用电成本占比'
336
337
        wssum = round(reporting_period_data['toppeaks'][0], 2) + round(reporting_period_data['onpeaks'][0], 2) + round(
338
            reporting_period_data['midpeaks'][0], 2) + round(reporting_period_data['offpeaks'][0], 2)
339
340
        ws['B14'].font = title_font
341
        ws['B14'].alignment = c_c_alignment
342
        ws['B14'] = '尖'
343
        ws['B14'].border = f_border
344
345
        ws['C14'].font = title_font
346
        ws['C14'].alignment = c_c_alignment
347
        ws['C14'].border = f_border
348
        ws['C14'] = round(reporting_period_data['toppeaks'][0], 2)
349
350
        ws['D14'].font = title_font
351
        ws['D14'].alignment = c_c_alignment
352
        ws['D14'].border = f_border
353
        ws['D14'] = '{:.2%}'.format(round(reporting_period_data['toppeaks'][0], 2) / wssum) \
354
            if wssum is not None and wssum != 0 else "0.00%"
355
356
        ws['B15'].font = title_font
357
        ws['B15'].alignment = c_c_alignment
358
        ws['B15'] = '峰'
359
        ws['B15'].border = f_border
360
361
        ws['C15'].font = title_font
362
        ws['C15'].alignment = c_c_alignment
363
        ws['C15'].border = f_border
364
        ws['C15'] = round(reporting_period_data['onpeaks'][0], 2)
365
366
        ws['D15'].font = title_font
367
        ws['D15'].alignment = c_c_alignment
368
        ws['D15'].border = f_border
369
        ws['D15'] = '{:.2%}'.format(round(reporting_period_data['onpeaks'][0], 2) / wssum) \
370
            if wssum is not None and wssum != 0 else "0.00%"
371
372
        ws['B16'].font = title_font
373
        ws['B16'].alignment = c_c_alignment
374
        ws['B16'] = '平'
375
        ws['B16'].border = f_border
376
377
        ws['C16'].font = title_font
378
        ws['C16'].alignment = c_c_alignment
379
        ws['C16'].border = f_border
380
        ws['C16'] = round(reporting_period_data['midpeaks'][0], 2)
381
382
        ws['D16'].font = title_font
383
        ws['D16'].alignment = c_c_alignment
384
        ws['D16'].border = f_border
385
        ws['D16'] = '{:.2%}'.format(round(reporting_period_data['midpeaks'][0], 2) / wssum) \
386
            if wssum is not None and wssum != 0 else "0.00%"
387
388
        ws['B17'].font = title_font
389
        ws['B17'].alignment = c_c_alignment
390
        ws['B17'] = '谷'
391
        ws['B17'].border = f_border
392
393
        ws['C17'].font = title_font
394
        ws['C17'].alignment = c_c_alignment
395
        ws['C17'].border = f_border
396
        ws['C17'] = round(reporting_period_data['offpeaks'][0], 2)
397
398
        ws['D17'].font = title_font
399
        ws['D17'].alignment = c_c_alignment
400
        ws['D17'].border = f_border
401
        ws['D17'] = '{:.2%}'.format(round(reporting_period_data['offpeaks'][0], 2) / wssum) \
402
            if wssum is not None and wssum != 0 else "0.00%"
403
404
        pie = PieChart()
405
        pie.title = name + '分时用电成本'
406
        labels = Reference(ws, min_col=2, min_row=14, max_row=17)
407
        pie_data = Reference(ws, min_col=3, min_row=13, max_row=17)
408
        pie.add_data(pie_data, titles_from_data=True)
409
        pie.set_categories(labels)
410
        pie.height = 6.6
411
        pie.width = 9
412
        s1 = pie.series[0]
413
        s1.dLbls = DataLabelList()
414
        s1.dLbls.showCatName = False
415
        s1.dLbls.showVal = True
416
        s1.dLbls.showPercent = True
417
        ws.add_chart(pie, "E13")
418
419
    else:
420
        for i in range(12, 18 + 1):
421
            ws.row_dimensions[i].height = 0.1
422
423
    ################################################
424
425
    current_row_number = 19
426
427
    has_subtotals_data_flag = True
428
    if "subtotals" not in reporting_period_data.keys() or \
429
            reporting_period_data['subtotals'] is None or \
430
            len(reporting_period_data['subtotals']) == 0:
431
        has_subtotals_data_flag = False
432
433 View Code Duplication
    if has_subtotals_data_flag:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
434
        ws['B' + str(current_row_number)].font = title_font
435
        ws['B' + str(current_row_number)] = name + ' 成本占比'
436
437
        current_row_number += 1
438
439
        table_start_row_number = current_row_number
440
441
        ws['B' + str(current_row_number)].fill = table_fill
442
        ws['B' + str(current_row_number)].font = name_font
443
        ws['B' + str(current_row_number)].alignment = c_c_alignment
444
        ws['B' + str(current_row_number)].border = f_border
445
446
        ws['C' + str(current_row_number)].fill = table_fill
447
        ws['C' + str(current_row_number)].font = name_font
448
        ws['C' + str(current_row_number)].alignment = c_c_alignment
449
        ws['C' + str(current_row_number)].border = f_border
450
        ws['C' + str(current_row_number)] = '成本'
451
452
        ws['D' + str(current_row_number)].fill = table_fill
453
        ws['D' + str(current_row_number)].font = name_font
454
        ws['D' + str(current_row_number)].alignment = c_c_alignment
455
        ws['D' + str(current_row_number)].border = f_border
456
        ws['D' + str(current_row_number)] = '成本占比'
457
458
        current_row_number += 1
459
460
        ca_len = len(reporting_period_data['names'])
461
        wssum = 0
462
        for i in range(0, ca_len):
463
            wssum = round(reporting_period_data['subtotals'][i], 2) + wssum
464
        for i in range(0, ca_len):
465
            ws['B' + str(current_row_number)].font = title_font
466
            ws['B' + str(current_row_number)].alignment = c_c_alignment
467
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i]
468
            ws['B' + str(current_row_number)].border = f_border
469
470
            ws['C' + str(current_row_number)].font = title_font
471
            ws['C' + str(current_row_number)].alignment = c_c_alignment
472
            ws['C' + str(current_row_number)].border = f_border
473
            ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
474
475
            ws['D' + str(current_row_number)].font = title_font
476
            ws['D' + str(current_row_number)].alignment = c_c_alignment
477
            ws['D' + str(current_row_number)].border = f_border
478
            ws['D' + str(current_row_number)] = '{:.2%}'.format(round(reporting_period_data['subtotals'][i], 2) /
479
                                                                wssum) if wssum is not None and wssum != 0 else "0.00%"
480
481
            current_row_number += 1
482
483
        table_end_row_number = current_row_number - 1
484
485
        pie = PieChart()
486
        pie.title = name + ' 成本占比'
487
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
488
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
489
        pie.add_data(pie_data, titles_from_data=True)
490
        pie.set_categories(labels)
491
        pie.height = 6.6
492
        pie.width = 9
493
        s1 = pie.series[0]
494
        s1.dLbls = DataLabelList()
495
        s1.dLbls.showCatName = False
496
        s1.dLbls.showVal = True
497
        s1.dLbls.showPercent = True
498
        table_cell = 'E' + str(table_start_row_number)
499
        ws.add_chart(pie, table_cell)
500
501
        if ca_len < 4:
502
            current_row_number = current_row_number - ca_len + 4
503
504
    else:
505
        for i in range(21, 29 + 1):
506
            current_row_number = 30
507
            ws.row_dimensions[i].height = 0.1
508
509
    ###############################################
510
511
    current_row_number += 1
512
513
    has_detail_data_flag = True
514
515
    table_start_draw_flag = current_row_number + 1
516
517
    if "timestamps" not in reporting_period_data.keys() or \
518
            reporting_period_data['timestamps'] is None or \
519
            len(reporting_period_data['timestamps']) == 0:
520
        has_detail_data_flag = False
521
522
    if has_detail_data_flag:
523
        reporting_period_data = report['reporting_period']
524
        times = reporting_period_data['timestamps']
525
        ca_len = len(report['reporting_period']['names'])
526
        parameters_names_len = len(report['parameters']['names'])
527
        parameters_parameters_datas_len = 0
528
        for i in range(0, parameters_names_len):
529
            if len(report['parameters']['timestamps'][i]) == 0:
530
                continue
531
            parameters_parameters_datas_len += 1
532
533
        ws['B' + str(current_row_number)].font = title_font
534
        ws['B' + str(current_row_number)] = name + ' 详细数据'
535
536
        detail_data_table_start_row_number = current_row_number + (ca_len + parameters_parameters_datas_len) * 6 + 3
537
        current_row_number = detail_data_table_start_row_number
538
539
        time = times[0]
540
        has_data = False
541
542
        if len(time) > 0:
543
            has_data = True
544
545
        if has_data:
546
547
            ws.row_dimensions[current_row_number].height = 60
548
            ws['B' + str(current_row_number)].fill = table_fill
549
            ws['B' + str(current_row_number)].border = f_border
550
            ws['B' + str(current_row_number)].font = title_font
551
            ws['B' + str(current_row_number)].alignment = c_c_alignment
552
            ws['B' + str(current_row_number)] = '日期时间'
553
554
            col = 'B'
555
556
            for i in range(0, ca_len):
557
                col = chr(ord('C') + i)
558
559
                ws[col + str(current_row_number)].fill = table_fill
560
                ws[col + str(current_row_number)].font = title_font
561
                ws[col + str(current_row_number)].alignment = c_c_alignment
562
                ws[col + str(current_row_number)] = \
563
                    reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
564
                ws[col + str(current_row_number)].border = f_border
565
566
            end_col = chr(ord(col) + 1)
567
568
            ws[end_col + str(current_row_number)].fill = table_fill
569
            ws[end_col + str(current_row_number)].font = title_font
570
            ws[end_col + str(current_row_number)].alignment = c_c_alignment
571
            ws[end_col + str(current_row_number)] = "总计 (" + reporting_period_data['total_unit'] + ")"
572
            ws[end_col + str(current_row_number)].border = f_border
573
574
            current_row_number += 1
575
576
            for i in range(0, len(time)):
577
                ws['B' + str(current_row_number)].font = title_font
578
                ws['B' + str(current_row_number)].alignment = c_c_alignment
579
                ws['B' + str(current_row_number)] = time[i]
580
                ws['B' + str(current_row_number)].border = f_border
581
582
                col = 'B'
583
584
                every_day_total = 0
585
586
                for j in range(0, ca_len):
587
                    col = chr(ord('C') + j)
588
589
                    ws[col + str(current_row_number)].font = title_font
590
                    ws[col + str(current_row_number)].alignment = c_c_alignment
591
                    value = round(reporting_period_data['values'][j][i], 2)
592
                    every_day_total += value
593
                    ws[col + str(current_row_number)] = value
594
                    ws[col + str(current_row_number)].border = f_border
595
596
                end_col = chr(ord(col) + 1)
597
                ws[end_col + str(current_row_number)].font = title_font
598
                ws[end_col + str(current_row_number)].alignment = c_c_alignment
599
                ws[end_col + str(current_row_number)] = round(every_day_total, 2)
600
                ws[end_col + str(current_row_number)].border = f_border
601
602
                current_row_number += 1
603
604
            table_end_row_number = current_row_number - 1
605
606
            ws['B' + str(current_row_number)].font = title_font
607
            ws['B' + str(current_row_number)].alignment = c_c_alignment
608
            ws['B' + str(current_row_number)] = '小计'
609
            ws['B' + str(current_row_number)].border = f_border
610
611
            col = 'B'
612
613
            for i in range(0, ca_len):
614
                col = chr(ord('C') + i)
615
                ws[col + str(current_row_number)].font = title_font
616
                ws[col + str(current_row_number)].alignment = c_c_alignment
617
                ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
618
                ws[col + str(current_row_number)].border = f_border
619
620
                # line
621
                line = LineChart()
622
                line.title = '报告期成本 - ' + \
623
                             reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
624
                labels = Reference(ws, min_col=2, min_row=detail_data_table_start_row_number + 1,
625
                                   max_row=table_end_row_number)
626
                line_data = Reference(ws, min_col=3 + i, min_row=detail_data_table_start_row_number,
627
                                      max_row=table_end_row_number)
628
                line.add_data(line_data, titles_from_data=True)
629
                line.set_categories(labels)
630
                line_data = line.series[0]
631
                line_data.marker.symbol = "circle"
632
                line_data.smooth = True
633
                line.x_axis.crosses = 'min'
634
                line.height = 8.25
635
                line.width = 24
636
                line.dLbls = DataLabelList()
637
                line.dLbls.dLblPos = 't'
638
                line.dLbls.showVal = True
639
                line.dLbls.showPercent = False
640
                chart_col = 'B'
641
                chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
642
                ws.add_chart(line, chart_cell)
643
644
            end_col = chr(ord(col) + 1)
645
            ws[end_col + str(current_row_number)].font = title_font
646
            ws[end_col + str(current_row_number)].alignment = c_c_alignment
647
            ws[end_col + str(current_row_number)] = round(reporting_period_data['total'], 2)
648
            ws[end_col + str(current_row_number)].border = f_border
649
650
            current_row_number += 1
651
652
    else:
653
        for i in range(30, 69 + 1):
654
            current_row_number = 70
655
            ws.row_dimensions[i].height = 0.1
656
    ##########################################
657
    has_parameters_names_and_timestamps_and_values_data = True
658
659
    ca_len = len(report['reporting_period']['names'])
660
    current_sheet_parameters_row_number = table_start_draw_flag + ca_len * 6
661
    if 'parameters' not in report.keys() or \
662
            report['parameters'] is None or \
663
            'names' not in report['parameters'].keys() or \
664
            report['parameters']['names'] is None or \
665
            len(report['parameters']['names']) == 0 or \
666
            'timestamps' not in report['parameters'].keys() or \
667
            report['parameters']['timestamps'] is None or \
668
            len(report['parameters']['timestamps']) == 0 or \
669
            'values' not in report['parameters'].keys() or \
670
            report['parameters']['values'] is None or \
671
            len(report['parameters']['values']) == 0 or \
672
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
673
        has_parameters_names_and_timestamps_and_values_data = False
674
    if has_parameters_names_and_timestamps_and_values_data:
675
676
        ###############################
677
        # new worksheet
678
        ###############################
679
680
        parameters_data = report['parameters']
681
682
        parameters_names_len = len(parameters_data['names'])
683
684
        parameters_ws = wb.create_sheet('相关参数')
685
686
        parameters_timestamps_data_max_len = \
687
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
688
689
        # Row height
690
        parameters_ws.row_dimensions[1].height = 102
691
        for i in range(2, 7 + 1):
692
            parameters_ws.row_dimensions[i].height = 42
693
694
        for i in range(8, parameters_timestamps_data_max_len + 10):
695
            parameters_ws.row_dimensions[i].height = 60
696
697
        # Col width
698
        parameters_ws.column_dimensions['A'].width = 1.5
699
700
        parameters_ws.column_dimensions['B'].width = 25.0
701
702
        for i in range(3, 12 + parameters_names_len * 3):
703
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
704
705
        # Img
706
        img = Image("excelexporters/myems.png")
707
        img.width = img.width * 0.85
708
        img.height = img.height * 0.85
709
        # img = Image("myems.png")
710
        parameters_ws.add_image(img, 'B1')
711
712
        # Title
713
        parameters_ws.row_dimensions[3].height = 60
714
715
        parameters_ws['B3'].font = name_font
716
        parameters_ws['B3'].alignment = b_r_alignment
717
        parameters_ws['B3'] = 'Name:'
718
        parameters_ws['C3'].border = b_border
719
        parameters_ws['C3'].alignment = b_c_alignment
720
        parameters_ws['C3'].font = name_font
721
        parameters_ws['C3'] = name
722
723
        parameters_ws['D3'].font = name_font
724
        parameters_ws['D3'].alignment = b_r_alignment
725
        parameters_ws['D3'] = 'Period:'
726
        parameters_ws['E3'].border = b_border
727
        parameters_ws['E3'].alignment = b_c_alignment
728
        parameters_ws['E3'].font = name_font
729
        parameters_ws['E3'] = period_type
730
731
        parameters_ws['F3'].font = name_font
732
        parameters_ws['F3'].alignment = b_r_alignment
733
        parameters_ws['F3'] = 'Date:'
734
        parameters_ws['G3'].border = b_border
735
        parameters_ws['G3'].alignment = b_c_alignment
736
        parameters_ws['G3'].font = name_font
737
        parameters_ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local
738
        parameters_ws.merge_cells("G3:H3")
739
740
        parameters_ws_current_row_number = 6
741
742
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
743
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' 相关参数'
744
745
        parameters_ws_current_row_number += 1
746
747
        parameters_table_start_row_number = parameters_ws_current_row_number
748
749
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
750
751
        parameters_ws_current_row_number += 1
752
753
        table_current_col_number = 'B'
754
755
        for i in range(0, parameters_names_len):
756
757
            if len(parameters_data['timestamps'][i]) == 0:
758
                continue
759
760
            parameters_ws[table_current_col_number + str(parameters_ws_current_row_number - 1)].fill = table_fill
761
            parameters_ws[table_current_col_number + str(parameters_ws_current_row_number - 1)].border = f_border
762
763
            col = decimal_to_column(column_to_decimal(table_current_col_number) + 1)
764
765
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
766
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
767
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
768
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
769
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
770
771
            table_current_row_number = parameters_ws_current_row_number
772
773
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
774
                col = table_current_col_number
775
776
                parameters_ws[col + str(table_current_row_number)].border = f_border
777
                parameters_ws[col + str(table_current_row_number)].font = title_font
778
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
779
                parameters_ws[col + str(table_current_row_number)] = value
780
781
                col = decimal_to_column(column_to_decimal(col) + 1)
782
783
                parameters_ws[col + str(table_current_row_number)].border = f_border
784
                parameters_ws[col + str(table_current_row_number)].font = title_font
785
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
786
                parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
787
788
                table_current_row_number += 1
789
790
            table_current_col_number = decimal_to_column(column_to_decimal(table_current_col_number) + 3)
791
792
        ########################################################
793
        # parameters chart and parameters table
794
        ########################################################
795
796
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
797
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' 相关参数'
798
799
        current_sheet_parameters_row_number += 1
800
801
        chart_start_row_number = current_sheet_parameters_row_number
802
803
        col_index = 0
804
805
        for i in range(0, parameters_names_len):
806
807
            if len(parameters_data['timestamps'][i]) == 0:
808
                continue
809
810
            line = LineChart()
811
            data_col = 3 + col_index * 3
812
            labels_col = 2 + col_index * 3
813
            col_index += 1
814
            line.title = '相关参数 - ' + \
815
                         parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
816
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
817
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
818
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
819
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
820
            line.add_data(line_data, titles_from_data=True)
821
            line.set_categories(labels)
822
            line_data = line.series[0]
823
            line_data.marker.symbol = "circle"
824
            line_data.smooth = True
825
            line.x_axis.crosses = 'min'
826
            line.height = 8.25
827
            line.width = 24
828
            line.dLbls = DataLabelList()
829
            line.dLbls.dLblPos = 't'
830
            line.dLbls.showVal = False
831
            line.dLbls.showPercent = False
832
            chart_col = 'B'
833
            chart_cell = chart_col + str(chart_start_row_number)
834
            chart_start_row_number += 6
835
            ws.add_chart(line, chart_cell)
836
837
        current_sheet_parameters_row_number = chart_start_row_number
838
839
        current_sheet_parameters_row_number += 1
840
841
    filename = str(uuid.uuid4()) + '.xlsx'
842
    wb.save(filename)
843
844
    return filename
845