qrpa 1.0.22__tar.gz → 1.0.23__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qrpa might be problematic. Click here for more details.
- {qrpa-1.0.22 → qrpa-1.0.23}/PKG-INFO +1 -1
- {qrpa-1.0.22 → qrpa-1.0.23}/pyproject.toml +1 -1
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/fun_excel.py +13 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/shein_daily_report_model.py +1 -1
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/shein_excel.py +245 -230
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa.egg-info/PKG-INFO +1 -1
- {qrpa-1.0.22 → qrpa-1.0.23}/README.md +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/RateLimitedSender.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/__init__.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/db_migrator.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/fun_base.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/fun_file.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/fun_web.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/fun_win.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/shein_lib.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/shein_sqlite.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/shein_ziniao.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/time_utils.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/time_utils_example.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa/wxwork.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa.egg-info/SOURCES.txt +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa.egg-info/dependency_links.txt +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/qrpa.egg-info/top_level.txt +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/setup.cfg +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/setup.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/tests/test_db_migrator.py +0 -0
- {qrpa-1.0.22 → qrpa-1.0.23}/tests/test_wxwork.py +0 -0
|
@@ -2454,6 +2454,19 @@ def batch_excel_operations(excel_path, operations):
|
|
|
2454
2454
|
format_func(sheet, *format_args)
|
|
2455
2455
|
log(f"批量操作:格式化工作表 {sheet_name}")
|
|
2456
2456
|
|
|
2457
|
+
elif operation_type == 'delete':
|
|
2458
|
+
pass
|
|
2459
|
+
delete_sheet_if_exists(wb, sheet_name)
|
|
2460
|
+
|
|
2461
|
+
elif operation_type == 'move':
|
|
2462
|
+
pass
|
|
2463
|
+
position = args[0]
|
|
2464
|
+
move_sheet_to_position(wb, sheet_name, position)
|
|
2465
|
+
|
|
2466
|
+
elif operation_type == 'active':
|
|
2467
|
+
pass
|
|
2468
|
+
sheet.activate()
|
|
2469
|
+
|
|
2457
2470
|
# 保存所有更改
|
|
2458
2471
|
wb.save()
|
|
2459
2472
|
log(f"批量操作完成: {excel_path}")
|
|
@@ -18,12 +18,12 @@ class SheinExcel:
|
|
|
18
18
|
data_day = []
|
|
19
19
|
dict_store_manager_shein = self.config.shein_store_manager
|
|
20
20
|
dict_store_name = read_dict_from_file(self.config.shein_store_alias)
|
|
21
|
+
|
|
22
|
+
# 准备每日汇总数据
|
|
21
23
|
for record in records:
|
|
22
24
|
store_data = []
|
|
23
|
-
# store_data.append(record.store_name)
|
|
24
25
|
store_data.append(dict_store_name.get(record.store_username))
|
|
25
26
|
store_data.append(dict_store_manager_shein.get(str(record.store_username).lower(), '-'))
|
|
26
|
-
# log(dict_store_manager_shein.get(str(record.store_username).lower(),'-'))
|
|
27
27
|
store_data.append(record.sales_num)
|
|
28
28
|
store_data.append(record.sales_num_inc)
|
|
29
29
|
store_data.append(record.sales_amount)
|
|
@@ -42,148 +42,36 @@ class SheinExcel:
|
|
|
42
42
|
store_data.append(record.upload_product_num_inc)
|
|
43
43
|
store_data.append(record.sold_out_product_num)
|
|
44
44
|
store_data.append(record.shelf_off_product_num)
|
|
45
|
-
# store_data.append(record.remark) # 不要了
|
|
46
45
|
data_day.append(store_data)
|
|
47
46
|
|
|
48
47
|
excel_path = create_file_path(self.config.excel_daily_report)
|
|
49
48
|
delete_file(excel_path)
|
|
50
49
|
sheet_name_first = 'SHEIN销售部每日店铺情况'
|
|
51
|
-
# write_json_to_excel('excel_daily.json',excel_path,sheet_name_first)
|
|
52
|
-
app, wb, sheet = open_excel(excel_path, sheet_name_first)
|
|
53
|
-
delete_sheet_if_exists(wb, 'Sheet1')
|
|
54
|
-
|
|
55
|
-
las_row = len(data_day) + 4
|
|
56
|
-
log('len(las_row)', las_row)
|
|
57
|
-
sheet.range('B5').value = data_day
|
|
58
|
-
# sheet.range('3:3').api.WrapText = True
|
|
59
|
-
sheet.range(f'A5:U{las_row}').api.Font.Color = 0x000000 # 红色
|
|
60
|
-
sheet.range(f'A5:U{las_row}').api.Font.Bold = False
|
|
61
|
-
sheet.range('A1').value = f'销售部SHEIN{TimeUtils.get_current_month()}月店铺数据'
|
|
62
|
-
sheet.range('A4').value = f'{TimeUtils.format_date_cross_platform(yesterday)}\n({TimeUtils.get_chinese_weekday(yesterday)})'
|
|
63
|
-
sheet.range('A4').column_width = 16
|
|
64
|
-
sheet.range('A4').api.VerticalAlignment = -4160 # 垂直顶部对齐
|
|
65
|
-
sheet.range(f'A4:A{las_row}').merge()
|
|
66
50
|
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
# 遍历列中的每个单元格
|
|
70
|
-
for cell in column_range:
|
|
71
|
-
# 检查单元格是否有值且为负数
|
|
72
|
-
if cell.value is not None and isinstance(cell.value, (int, float)) and cell.value < 0:
|
|
73
|
-
# 设置字体颜色为红色
|
|
74
|
-
cell.font.color = (255, 0, 0) # RGB值表示红色
|
|
75
|
-
|
|
76
|
-
# 获取列数据范围
|
|
77
|
-
column_range = sheet.range(f'G5:G{las_row}')
|
|
78
|
-
# 遍历列中的每个单元格
|
|
79
|
-
for cell in column_range:
|
|
80
|
-
# 检查单元格是否有值且为负数
|
|
81
|
-
if cell.value is not None and cell.value < 0:
|
|
82
|
-
# 设置字体颜色为红色
|
|
83
|
-
cell.font.color = (255, 0, 0) # RGB值表示红色
|
|
84
|
-
|
|
85
|
-
# 获取列数据范围
|
|
86
|
-
column_range = sheet.range(f'I5:I{las_row}')
|
|
87
|
-
# 遍历列中的每个单元格
|
|
88
|
-
for cell in column_range:
|
|
89
|
-
# 检查单元格是否有值且为负数
|
|
90
|
-
if cell.value is not None and isinstance(cell.value, (int, float)) and cell.value < 0:
|
|
91
|
-
# 设置字体颜色为红色
|
|
92
|
-
cell.font.color = (255, 0, 0) # RGB值表示红色
|
|
93
|
-
|
|
94
|
-
# 获取列数据范围
|
|
95
|
-
column_range = sheet.range(f'K5:K{las_row}')
|
|
96
|
-
# 遍历列中的每个单元格
|
|
97
|
-
for cell in column_range:
|
|
98
|
-
# 检查单元格是否有值且为负数
|
|
99
|
-
if cell.value is not None and isinstance(cell.value, (int, float)) and cell.value < 0:
|
|
100
|
-
# 设置字体颜色为红色
|
|
101
|
-
cell.font.color = (255, 0, 0) # RGB值表示红色
|
|
102
|
-
|
|
103
|
-
# 处理表头
|
|
104
|
-
# 处理第一行
|
|
105
|
-
rangeOne = f'A1:U1'
|
|
106
|
-
sheet.range(rangeOne).merge()
|
|
107
|
-
sheet.range(rangeOne).api.Font.Size = 24
|
|
108
|
-
sheet.range(rangeOne).api.Font.Bold = True
|
|
109
|
-
sheet.range(rangeOne).api.HorizontalAlignment = -4108
|
|
110
|
-
sheet.range(rangeOne).api.VerticalAlignment = -4108
|
|
111
|
-
|
|
112
|
-
# 处理第二行
|
|
113
|
-
rangeTwo_part_1 = f'A2:C2'
|
|
114
|
-
rangeTwo_part_2 = f'D2:O2'
|
|
115
|
-
rangeTwo_part_3 = f'P2:U2'
|
|
116
|
-
sheet.range(rangeTwo_part_1).merge()
|
|
117
|
-
sheet.range(rangeTwo_part_2).merge()
|
|
118
|
-
sheet.range(rangeTwo_part_3).merge()
|
|
51
|
+
# 准备批量操作列表
|
|
52
|
+
operations = []
|
|
119
53
|
|
|
120
|
-
sheet
|
|
54
|
+
# 添加每日汇总sheet的操作 - 自定义操作函数
|
|
55
|
+
def write_daily_data(sheet):
|
|
56
|
+
# 写入数据到B5位置,保持原有格式
|
|
57
|
+
sheet.range('B5').value = data_day
|
|
58
|
+
# 设置标题
|
|
59
|
+
sheet.range('A1').value = f'销售部SHEIN{TimeUtils.get_current_month()}月店铺数据'
|
|
60
|
+
# 设置日期和合并
|
|
61
|
+
sheet.range('A4').value = f'{TimeUtils.format_date_cross_platform(yesterday)}\n({TimeUtils.get_chinese_weekday(yesterday)})'
|
|
121
62
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
sheet.range(rangeTwo_part_2).api.HorizontalAlignment = -4108
|
|
127
|
-
sheet.range(rangeTwo_part_2).api.VerticalAlignment = -4108
|
|
128
|
-
sheet.range(f'D2:O3').color = 0x0000FF
|
|
129
|
-
|
|
130
|
-
sheet.range('P2').value = f'上新的质量和数量'
|
|
131
|
-
sheet.range(rangeTwo_part_3).api.Font.Size = 16
|
|
132
|
-
sheet.range(rangeTwo_part_3).api.Font.Color = 0xFFFFFF
|
|
133
|
-
sheet.range(rangeTwo_part_3).api.Font.Bold = True
|
|
134
|
-
sheet.range(rangeTwo_part_3).api.HorizontalAlignment = -4108
|
|
135
|
-
sheet.range(rangeTwo_part_3).api.VerticalAlignment = -4108
|
|
136
|
-
sheet.range(f'P2:U3').color = 0x47a100
|
|
137
|
-
|
|
138
|
-
# 处理第三行
|
|
139
|
-
rangeThree = f'A3:U3'
|
|
140
|
-
sheet.range('A3').value = ['日期', '店铺', '店长', '昨日单量', '对比前日', '昨日销售额', '对比前日', '昨日访客',
|
|
141
|
-
'对比前天', '备货款A', '对比前日', '新款A', '对比前日', '在售商品', '对比前日', '待上架',
|
|
142
|
-
'对比前日', '昨日上传', '对比前日', '已售罄', '已下架']
|
|
143
|
-
sheet.range(rangeThree).api.Font.Size = 11
|
|
144
|
-
sheet.range(rangeThree).api.Font.Color = 0xFFFFFF
|
|
145
|
-
sheet.range(rangeThree).api.Font.Bold = True
|
|
146
|
-
sheet.range(rangeThree).api.HorizontalAlignment = -4108
|
|
147
|
-
sheet.range(rangeThree).api.VerticalAlignment = -4108
|
|
148
|
-
|
|
149
|
-
# 处理第4行
|
|
150
|
-
rangeFour = f'B4:U4'
|
|
151
|
-
sheet.range('B4').value = '汇总'
|
|
152
|
-
sheet.range('C4').value = '-'
|
|
153
|
-
sheet.range(rangeFour).api.Font.Size = 11
|
|
154
|
-
sheet.range(rangeThree).api.HorizontalAlignment = -4108
|
|
155
|
-
sheet.range(rangeThree).api.VerticalAlignment = -4108
|
|
156
|
-
sheet.range(f'B4:U4').color = 0x50d092
|
|
157
|
-
|
|
158
|
-
for col in range(2, 22): # 对应 C 列到 J 列
|
|
159
|
-
col_letter = xw.utils.col_name(col)
|
|
160
|
-
if col_letter not in ['A', 'B', 'C']:
|
|
161
|
-
sheet.range(f'{col_letter}4').formula = f'=SUM({col_letter}5:{col_letter}{las_row})'
|
|
162
|
-
# 所有列水平居中和垂直居中
|
|
163
|
-
sheet.range(f'{col_letter}:{col_letter}').api.HorizontalAlignment = -4108
|
|
164
|
-
sheet.range(f'{col_letter}:{col_letter}').api.VerticalAlignment = -4108
|
|
165
|
-
sheet.autofit()
|
|
166
|
-
|
|
167
|
-
range_to_border = sheet.range(f'A2:U{las_row}') # 定义范围
|
|
168
|
-
# 设置外部边框(所有边都为实线)
|
|
169
|
-
range_to_border.api.Borders(7).LineStyle = 1 # 上边框
|
|
170
|
-
range_to_border.api.Borders(8).LineStyle = 1 # 下边框
|
|
171
|
-
range_to_border.api.Borders(9).LineStyle = 1 # 左边框
|
|
172
|
-
range_to_border.api.Borders(10).LineStyle = 1 # 右边框
|
|
173
|
-
# 设置内部边框
|
|
174
|
-
range_to_border.api.Borders(1).LineStyle = 1 # 内部上边框
|
|
175
|
-
range_to_border.api.Borders(2).LineStyle = 1 # 内部下边框
|
|
176
|
-
range_to_border.api.Borders(3).LineStyle = 1 # 内部左边框
|
|
177
|
-
range_to_border.api.Borders(4).LineStyle = 1 # 内部右边框
|
|
178
|
-
|
|
179
|
-
wb.save()
|
|
180
|
-
close_excel(app, wb)
|
|
63
|
+
operations.append((sheet_name_first, 'format', write_daily_data))
|
|
64
|
+
operations.append((sheet_name_first, 'format', self._format_daily_summary_sheet, yesterday, len(data_day)))
|
|
65
|
+
operations.append(('Sheet1', 'delete'))
|
|
66
|
+
operations.append((sheet_name_first, 'move', 1))
|
|
181
67
|
|
|
68
|
+
# 获取店铺列表并准备月度数据
|
|
182
69
|
store_list = model.get_distinct_store_sales_list()
|
|
183
70
|
for store in store_list:
|
|
184
71
|
store_username = store[0]
|
|
185
72
|
store_name = dict_store_name.get(store_username)
|
|
186
73
|
records = model.get_one_month_records(TimeUtils.get_current_year(), TimeUtils.get_current_month(), store_username)
|
|
74
|
+
|
|
187
75
|
data_month = []
|
|
188
76
|
for record in records:
|
|
189
77
|
store_data = []
|
|
@@ -206,101 +94,228 @@ class SheinExcel:
|
|
|
206
94
|
store_data.append(record.upload_product_num_inc)
|
|
207
95
|
store_data.append(record.sold_out_product_num)
|
|
208
96
|
store_data.append(record.shelf_off_product_num)
|
|
209
|
-
store_data.append(record.remark)
|
|
97
|
+
# store_data.append(record.remark) # 月度数据不包含备注列,保持19列
|
|
210
98
|
data_month.append(store_data)
|
|
211
99
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
# 处理第二行
|
|
229
|
-
rangeTwo_part_1 = f'A2'
|
|
230
|
-
rangeTwo_part_2 = f'B2:M2'
|
|
231
|
-
rangeTwo_part_3 = f'N2:S2'
|
|
232
|
-
sheet.range(rangeTwo_part_2).merge()
|
|
233
|
-
sheet.range(rangeTwo_part_3).merge()
|
|
234
|
-
|
|
235
|
-
sheet.range(f'A2:A3').color = 0x47a100
|
|
236
|
-
|
|
237
|
-
sheet.range('B2').value = f'店铺的结果和稳定性'
|
|
238
|
-
sheet.range(rangeTwo_part_2).api.Font.Size = 16
|
|
239
|
-
sheet.range(rangeTwo_part_2).api.Font.Color = 0xFFFFFF
|
|
240
|
-
sheet.range(rangeTwo_part_2).api.Font.Bold = True
|
|
241
|
-
sheet.range(rangeTwo_part_2).api.HorizontalAlignment = -4108
|
|
242
|
-
sheet.range(rangeTwo_part_2).api.VerticalAlignment = -4108
|
|
243
|
-
sheet.range(f'B2:M3').color = 0x0000FF
|
|
244
|
-
|
|
245
|
-
sheet.range('N2').value = f'上新的质量和数量'
|
|
246
|
-
sheet.range(rangeTwo_part_3).api.Font.Size = 16
|
|
247
|
-
sheet.range(rangeTwo_part_3).api.Font.Color = 0xFFFFFF
|
|
248
|
-
sheet.range(rangeTwo_part_3).api.Font.Bold = True
|
|
249
|
-
sheet.range(rangeTwo_part_3).api.HorizontalAlignment = -4108
|
|
250
|
-
sheet.range(rangeTwo_part_3).api.VerticalAlignment = -4108
|
|
251
|
-
sheet.range(f'N2:S3').color = 0x47a100
|
|
252
|
-
|
|
253
|
-
# 处理第三行
|
|
254
|
-
rangeThree = f'A3:S3'
|
|
255
|
-
sheet.range('A3').value = ['日期', '昨日单量', '对比前日', '昨日销售额', '对比前日', '昨日访客', '对比前天',
|
|
256
|
-
'备货款A', '对比前日', '新款A', '对比前日', '在售商品', '对比前日', '待上架',
|
|
257
|
-
'对比前日', '昨日上传', '对比前日', '已售罄', '已下架']
|
|
258
|
-
sheet.range(rangeThree).api.Font.Size = 11
|
|
259
|
-
sheet.range(rangeThree).api.Font.Color = 0xFFFFFF
|
|
260
|
-
sheet.range(rangeThree).api.Font.Bold = True
|
|
261
|
-
sheet.range(rangeThree).api.HorizontalAlignment = -4108
|
|
262
|
-
sheet.range(rangeThree).api.VerticalAlignment = -4108
|
|
263
|
-
|
|
264
|
-
# 处理第4行
|
|
265
|
-
rangeFour = f'A4:S4'
|
|
266
|
-
sheet.range('A4').value = '汇总'
|
|
267
|
-
sheet.range(rangeFour).api.Font.Size = 11
|
|
268
|
-
sheet.range(rangeThree).api.HorizontalAlignment = -4108
|
|
269
|
-
sheet.range(rangeThree).api.VerticalAlignment = -4108
|
|
270
|
-
sheet.range(f'A4:S4').color = 0x50d092
|
|
271
|
-
|
|
272
|
-
# 原逻辑
|
|
273
|
-
sheet.range('A5').value = data_month
|
|
274
|
-
# sheet.range('3:3').api.WrapText = True
|
|
275
|
-
sheet.range('A4:T35').api.Font.Color = 0x000000
|
|
276
|
-
sheet.range('A4:T35').api.Font.Bold = False
|
|
277
|
-
sheet.range('A1').value = f'{store_name}SHEIN{TimeUtils.get_current_month()}月店铺数据'
|
|
278
|
-
|
|
279
|
-
range_to_border = sheet.range(f'A2:S{las_row}') # 定义范围
|
|
280
|
-
# 设置外部边框(所有边都为实线)
|
|
281
|
-
range_to_border.api.Borders(7).LineStyle = 1 # 上边框
|
|
282
|
-
range_to_border.api.Borders(8).LineStyle = 1 # 下边框
|
|
283
|
-
range_to_border.api.Borders(9).LineStyle = 1 # 左边框
|
|
284
|
-
range_to_border.api.Borders(10).LineStyle = 1 # 右边框
|
|
285
|
-
# 设置内部边框
|
|
286
|
-
range_to_border.api.Borders(1).LineStyle = 1 # 内部上边框
|
|
287
|
-
range_to_border.api.Borders(2).LineStyle = 1 # 内部下边框
|
|
288
|
-
range_to_border.api.Borders(3).LineStyle = 1 # 内部左边框
|
|
289
|
-
range_to_border.api.Borders(4).LineStyle = 1 # 内部右边框
|
|
290
|
-
wb.save()
|
|
291
|
-
|
|
292
|
-
for col in range(2, 20): # 对应 C 列到 J 列
|
|
293
|
-
col_letter = xw.utils.col_name(col)
|
|
294
|
-
# 所有列水平居中和垂直居中
|
|
295
|
-
sheet.range(f'{col_letter}:{col_letter}').api.HorizontalAlignment = -4108
|
|
296
|
-
sheet.range(f'{col_letter}:{col_letter}').api.VerticalAlignment = -4108
|
|
297
|
-
sheet.range(f'{col_letter}4').formula = f'=SUM({col_letter}5:{col_letter}36)'
|
|
298
|
-
|
|
299
|
-
if sheet_name_first in [sheet.name for sheet in wb.sheets]:
|
|
300
|
-
wb.sheets[sheet_name_first].activate()
|
|
301
|
-
wb.save()
|
|
302
|
-
close_excel(app, wb)
|
|
100
|
+
# 添加月度sheet操作 - 自定义操作函数
|
|
101
|
+
def write_monthly_data(sheet, data=data_month, name=store_name):
|
|
102
|
+
# 写入数据到A5位置(月度数据从A列开始)
|
|
103
|
+
sheet.range('A5').value = data
|
|
104
|
+
# 设置标题
|
|
105
|
+
sheet.range('A1').value = f'{name}SHEIN{TimeUtils.get_current_month()}月店铺数据'
|
|
106
|
+
|
|
107
|
+
operations.append((store_name, 'format', write_monthly_data))
|
|
108
|
+
operations.append((store_name, 'format', self._format_store_monthly_sheet, store_name, len(data_month)))
|
|
109
|
+
|
|
110
|
+
# 执行批量操作
|
|
111
|
+
operations.append((sheet_name_first, 'active'))
|
|
112
|
+
success = batch_excel_operations(excel_path, operations)
|
|
113
|
+
|
|
114
|
+
if success:
|
|
115
|
+
# 发送文件到企业微信
|
|
303
116
|
WxWorkBot('b30aaa8d-1a1f-4378-841a-8b0f8295f2d9').send_file(excel_path)
|
|
117
|
+
log(f"销售数据写入完成: {excel_path}")
|
|
118
|
+
else:
|
|
119
|
+
log(f"销售数据写入失败: {excel_path}")
|
|
120
|
+
|
|
121
|
+
def _format_daily_summary_sheet(self, sheet, yesterday, data_length):
|
|
122
|
+
"""格式化每日汇总sheet"""
|
|
123
|
+
las_row = data_length + 4 # 数据从第5行开始,4行header
|
|
124
|
+
|
|
125
|
+
# 设置数据区域格式(从B5开始,因为数据写入到B5)
|
|
126
|
+
sheet.range(f'B5:U{las_row}').api.Font.Color = 0x000000
|
|
127
|
+
sheet.range(f'B5:U{las_row}').api.Font.Bold = False
|
|
128
|
+
|
|
129
|
+
# 设置A4日期列的格式和合并
|
|
130
|
+
sheet.range('A4').column_width = 16
|
|
131
|
+
sheet.range('A4').api.VerticalAlignment = -4160 # 垂直顶部对齐
|
|
132
|
+
sheet.range(f'A4:A{las_row}').merge()
|
|
133
|
+
|
|
134
|
+
# 设置负数为红色(E,G,I,K列)
|
|
135
|
+
self._set_negative_numbers_red(sheet, ['E', 'G', 'I', 'K'], 5, las_row)
|
|
136
|
+
|
|
137
|
+
# 格式化表头
|
|
138
|
+
self._format_daily_header(sheet, las_row)
|
|
139
|
+
|
|
140
|
+
# 设置汇总公式和格式
|
|
141
|
+
self._set_summary_formulas(sheet, las_row)
|
|
142
|
+
|
|
143
|
+
# 设置边框
|
|
144
|
+
self._set_borders(sheet, f'A2:U{las_row}')
|
|
145
|
+
|
|
146
|
+
sheet.autofit()
|
|
147
|
+
|
|
148
|
+
def _format_store_monthly_sheet(self, sheet, store_name, data_length):
|
|
149
|
+
"""格式化店铺月度sheet"""
|
|
150
|
+
las_row = data_length + 4 # 数据从第5行开始,4行header
|
|
151
|
+
|
|
152
|
+
# 数据已经写入,现在进行格式化
|
|
153
|
+
# 设置数据区域格式(从A5开始到S列,月度数据是19列)
|
|
154
|
+
sheet.range(f'A5:S{las_row}').api.Font.Color = 0x000000
|
|
155
|
+
sheet.range(f'A5:S{las_row}').api.Font.Bold = False
|
|
156
|
+
|
|
157
|
+
# 格式化表头
|
|
158
|
+
self._format_monthly_header(sheet, las_row)
|
|
159
|
+
|
|
160
|
+
# 设置汇总公式和格式
|
|
161
|
+
self._set_monthly_summary_formulas(sheet, las_row)
|
|
162
|
+
|
|
163
|
+
# 设置边框
|
|
164
|
+
self._set_borders(sheet, f'A2:S{las_row}')
|
|
165
|
+
|
|
166
|
+
sheet.autofit()
|
|
167
|
+
|
|
168
|
+
def _set_negative_numbers_red(self, sheet, columns, start_row, end_row):
|
|
169
|
+
"""设置负数为红色"""
|
|
170
|
+
for col in columns:
|
|
171
|
+
column_range = sheet.range(f'{col}{start_row}:{col}{end_row}')
|
|
172
|
+
for cell in column_range:
|
|
173
|
+
if cell.value is not None and isinstance(cell.value, (int, float)) and cell.value < 0:
|
|
174
|
+
cell.font.color = (255, 0, 0)
|
|
175
|
+
|
|
176
|
+
def _format_daily_header(self, sheet, las_row):
|
|
177
|
+
"""格式化每日汇总表头,完全按照原始格式"""
|
|
178
|
+
# 第一行:标题
|
|
179
|
+
range_one = f'A1:U1'
|
|
180
|
+
sheet.range(range_one).merge()
|
|
181
|
+
sheet.range(range_one).api.Font.Size = 24
|
|
182
|
+
sheet.range(range_one).api.Font.Bold = True
|
|
183
|
+
sheet.range(range_one).api.HorizontalAlignment = -4108
|
|
184
|
+
sheet.range(range_one).api.VerticalAlignment = -4108
|
|
185
|
+
|
|
186
|
+
# 第二行:分类标题
|
|
187
|
+
range_two_part_1 = f'A2:C2'
|
|
188
|
+
range_two_part_2 = f'D2:O2'
|
|
189
|
+
range_two_part_3 = f'P2:U2'
|
|
190
|
+
sheet.range(range_two_part_1).merge()
|
|
191
|
+
sheet.range(range_two_part_2).merge()
|
|
192
|
+
sheet.range(range_two_part_3).merge()
|
|
193
|
+
|
|
194
|
+
sheet.range(f'A2:C3').color = 0x47a100
|
|
195
|
+
|
|
196
|
+
sheet.range('D2').value = '店铺的结果和稳定性'
|
|
197
|
+
sheet.range(range_two_part_2).api.Font.Size = 16
|
|
198
|
+
sheet.range(range_two_part_2).api.Font.Color = 0xFFFFFF
|
|
199
|
+
sheet.range(range_two_part_2).api.Font.Bold = True
|
|
200
|
+
sheet.range(range_two_part_2).api.HorizontalAlignment = -4108
|
|
201
|
+
sheet.range(range_two_part_2).api.VerticalAlignment = -4108
|
|
202
|
+
sheet.range(f'D2:O3').color = 0x0000FF
|
|
203
|
+
|
|
204
|
+
sheet.range('P2').value = '上新的质量和数量'
|
|
205
|
+
sheet.range(range_two_part_3).api.Font.Size = 16
|
|
206
|
+
sheet.range(range_two_part_3).api.Font.Color = 0xFFFFFF
|
|
207
|
+
sheet.range(range_two_part_3).api.Font.Bold = True
|
|
208
|
+
sheet.range(range_two_part_3).api.HorizontalAlignment = -4108
|
|
209
|
+
sheet.range(range_two_part_3).api.VerticalAlignment = -4108
|
|
210
|
+
sheet.range(f'P2:U3').color = 0x47a100
|
|
211
|
+
|
|
212
|
+
# 第三行:列标题
|
|
213
|
+
range_three = f'A3:U3'
|
|
214
|
+
sheet.range('A3').value = ['日期', '店铺', '店长', '昨日单量', '对比前日', '昨日销售额', '对比前日', '昨日访客',
|
|
215
|
+
'对比前天', '备货款A', '对比前日', '新款A', '对比前日', '在售商品', '对比前日', '待上架',
|
|
216
|
+
'对比前日', '昨日上传', '对比前日', '已售罄', '已下架']
|
|
217
|
+
sheet.range(range_three).api.Font.Size = 11
|
|
218
|
+
sheet.range(range_three).api.Font.Color = 0xFFFFFF
|
|
219
|
+
sheet.range(range_three).api.Font.Bold = True
|
|
220
|
+
sheet.range(range_three).api.HorizontalAlignment = -4108
|
|
221
|
+
sheet.range(range_three).api.VerticalAlignment = -4108
|
|
222
|
+
|
|
223
|
+
# 第四行:汇总行
|
|
224
|
+
range_four = f'B4:U4'
|
|
225
|
+
sheet.range('B4').value = '汇总'
|
|
226
|
+
sheet.range('C4').value = '-'
|
|
227
|
+
sheet.range(range_four).api.Font.Size = 11
|
|
228
|
+
sheet.range(range_four).api.HorizontalAlignment = -4108
|
|
229
|
+
sheet.range(range_four).api.VerticalAlignment = -4108
|
|
230
|
+
sheet.range(f'B4:U4').color = 0x50d092
|
|
231
|
+
|
|
232
|
+
def _format_monthly_header(self, sheet, las_row):
|
|
233
|
+
"""格式化月度表头,完全按照原始格式"""
|
|
234
|
+
# 第一行:标题(合并A1:S1)
|
|
235
|
+
range_one = f'A1:S1'
|
|
236
|
+
sheet.range(range_one).merge()
|
|
237
|
+
sheet.range(range_one).api.Font.Size = 24
|
|
238
|
+
sheet.range(range_one).api.Font.Bold = True
|
|
239
|
+
sheet.range(range_one).api.HorizontalAlignment = -4108
|
|
240
|
+
sheet.range(range_one).api.VerticalAlignment = -4108
|
|
241
|
+
|
|
242
|
+
# 第二行:分类标题
|
|
243
|
+
range_two_part_1 = f'A2'
|
|
244
|
+
range_two_part_2 = f'B2:M2'
|
|
245
|
+
range_two_part_3 = f'N2:S2'
|
|
246
|
+
sheet.range(range_two_part_2).merge()
|
|
247
|
+
sheet.range(range_two_part_3).merge()
|
|
248
|
+
|
|
249
|
+
sheet.range(f'A2:A3').color = 0x47a100
|
|
250
|
+
|
|
251
|
+
sheet.range('B2').value = '店铺的结果和稳定性'
|
|
252
|
+
sheet.range(range_two_part_2).api.Font.Size = 16
|
|
253
|
+
sheet.range(range_two_part_2).api.Font.Color = 0xFFFFFF
|
|
254
|
+
sheet.range(range_two_part_2).api.Font.Bold = True
|
|
255
|
+
sheet.range(range_two_part_2).api.HorizontalAlignment = -4108
|
|
256
|
+
sheet.range(range_two_part_2).api.VerticalAlignment = -4108
|
|
257
|
+
sheet.range(f'B2:M3').color = 0x0000FF
|
|
258
|
+
|
|
259
|
+
sheet.range('N2').value = '上新的质量和数量'
|
|
260
|
+
sheet.range(range_two_part_3).api.Font.Size = 16
|
|
261
|
+
sheet.range(range_two_part_3).api.Font.Color = 0xFFFFFF
|
|
262
|
+
sheet.range(range_two_part_3).api.Font.Bold = True
|
|
263
|
+
sheet.range(range_two_part_3).api.HorizontalAlignment = -4108
|
|
264
|
+
sheet.range(range_two_part_3).api.VerticalAlignment = -4108
|
|
265
|
+
sheet.range(f'N2:S3').color = 0x47a100
|
|
266
|
+
|
|
267
|
+
# 第三行:列标题
|
|
268
|
+
range_three = f'A3:S3'
|
|
269
|
+
sheet.range('A3').value = ['日期', '昨日单量', '对比前日', '昨日销售额', '对比前日', '昨日访客', '对比前天',
|
|
270
|
+
'备货款A', '对比前日', '新款A', '对比前日', '在售商品', '对比前日', '待上架',
|
|
271
|
+
'对比前日', '昨日上传', '对比前日', '已售罄', '已下架']
|
|
272
|
+
sheet.range(range_three).api.Font.Size = 11
|
|
273
|
+
sheet.range(range_three).api.Font.Color = 0xFFFFFF
|
|
274
|
+
sheet.range(range_three).api.Font.Bold = True
|
|
275
|
+
sheet.range(range_three).api.HorizontalAlignment = -4108
|
|
276
|
+
sheet.range(range_three).api.VerticalAlignment = -4108
|
|
277
|
+
|
|
278
|
+
# 第四行:汇总行
|
|
279
|
+
range_four = f'A4:S4'
|
|
280
|
+
sheet.range('A4').value = '汇总'
|
|
281
|
+
sheet.range(range_four).api.Font.Size = 11
|
|
282
|
+
sheet.range(range_four).api.HorizontalAlignment = -4108
|
|
283
|
+
sheet.range(range_four).api.VerticalAlignment = -4108
|
|
284
|
+
sheet.range(f'A4:S4').color = 0x50d092
|
|
285
|
+
|
|
286
|
+
def _set_summary_formulas(self, sheet, las_row):
|
|
287
|
+
"""设置汇总公式"""
|
|
288
|
+
for col in range(2, 22): # B列到U列(跳过A列日期)
|
|
289
|
+
col_letter = xw.utils.col_name(col)
|
|
290
|
+
if col_letter not in ['A', 'B', 'C']: # A列是日期,B列是汇总,C列是-
|
|
291
|
+
sheet.range(f'{col_letter}4').formula = f'=SUM({col_letter}5:{col_letter}{las_row})'
|
|
292
|
+
# 所有列水平居中和垂直居中
|
|
293
|
+
sheet.range(f'{col_letter}:{col_letter}').api.HorizontalAlignment = -4108
|
|
294
|
+
sheet.range(f'{col_letter}:{col_letter}').api.VerticalAlignment = -4108
|
|
295
|
+
|
|
296
|
+
def _set_monthly_summary_formulas(self, sheet, las_row):
|
|
297
|
+
"""设置月度汇总公式"""
|
|
298
|
+
for col in range(2, 20): # B列到S列(对应原始代码的 2 到 20)
|
|
299
|
+
col_letter = xw.utils.col_name(col)
|
|
300
|
+
# 所有列水平居中和垂直居中
|
|
301
|
+
sheet.range(f'{col_letter}:{col_letter}').api.HorizontalAlignment = -4108
|
|
302
|
+
sheet.range(f'{col_letter}:{col_letter}').api.VerticalAlignment = -4108
|
|
303
|
+
# 设置汇总公式(原始代码使用固定的36行)
|
|
304
|
+
sheet.range(f'{col_letter}4').formula = f'=SUM({col_letter}5:{col_letter}36)'
|
|
305
|
+
|
|
306
|
+
def _set_borders(self, sheet, range_str):
|
|
307
|
+
"""设置边框"""
|
|
308
|
+
range_to_border = sheet.range(range_str)
|
|
309
|
+
# 设置外部边框
|
|
310
|
+
range_to_border.api.Borders(7).LineStyle = 1 # 上边框
|
|
311
|
+
range_to_border.api.Borders(8).LineStyle = 1 # 下边框
|
|
312
|
+
range_to_border.api.Borders(9).LineStyle = 1 # 左边框
|
|
313
|
+
range_to_border.api.Borders(10).LineStyle = 1 # 右边框
|
|
314
|
+
# 设置内部边框
|
|
315
|
+
range_to_border.api.Borders(1).LineStyle = 1 # 内部上边框
|
|
316
|
+
range_to_border.api.Borders(2).LineStyle = 1 # 内部下边框
|
|
317
|
+
range_to_border.api.Borders(3).LineStyle = 1 # 内部左边框
|
|
318
|
+
range_to_border.api.Borders(4).LineStyle = 1 # 内部右边框
|
|
304
319
|
|
|
305
320
|
def format_bak_advice(self, excel_path, sheet_name, mode):
|
|
306
321
|
app, wb, sheet = open_excel(excel_path, sheet_name)
|
|
@@ -411,10 +426,10 @@ class SheinExcel:
|
|
|
411
426
|
|
|
412
427
|
header = []
|
|
413
428
|
for store_username, excel_data in dict_1.items():
|
|
414
|
-
store_name = dict_store.get(store_username)
|
|
415
|
-
sheet_name = store_name
|
|
416
|
-
write_data(excel_path_1, sheet_name, excel_data)
|
|
417
|
-
self.format_jit(excel_path_1, sheet_name)
|
|
429
|
+
# store_name = dict_store.get(store_username)
|
|
430
|
+
# sheet_name = store_name
|
|
431
|
+
# write_data(excel_path_1, sheet_name, excel_data)
|
|
432
|
+
# self.format_jit(excel_path_1, sheet_name)
|
|
418
433
|
header = excel_data[0]
|
|
419
434
|
summary_excel_data_1 += excel_data[1:]
|
|
420
435
|
|
|
@@ -431,10 +446,10 @@ class SheinExcel:
|
|
|
431
446
|
|
|
432
447
|
header = []
|
|
433
448
|
for store_username, excel_data in dict_2.items():
|
|
434
|
-
store_name = dict_store.get(store_username)
|
|
435
|
-
sheet_name = store_name
|
|
436
|
-
write_data(excel_path_2, sheet_name, excel_data)
|
|
437
|
-
self.format_jit(excel_path_2, sheet_name)
|
|
449
|
+
# store_name = dict_store.get(store_username)
|
|
450
|
+
# sheet_name = store_name
|
|
451
|
+
# write_data(excel_path_2, sheet_name, excel_data)
|
|
452
|
+
# self.format_jit(excel_path_2, sheet_name)
|
|
438
453
|
header = excel_data[0]
|
|
439
454
|
summary_excel_data_2 += excel_data[1:]
|
|
440
455
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|