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

decimal_to_column()   A

Complexity

Conditions 5

Size

Total Lines 19
Code Lines 14

Duplication

Lines 19
Ratio 100 %

Importance

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