qrpa 1.0.24__py3-none-any.whl → 1.0.26__py3-none-any.whl

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/shein_excel.py CHANGED
@@ -1,16 +1,1245 @@
1
1
  from .fun_excel import *
2
- from .fun_base import log, calculate_star_symbols
2
+ from .fun_base import *
3
3
  from .fun_file import read_dict_from_file, read_dict_from_file_ex, write_dict_to_file, write_dict_to_file_ex, delete_file
4
4
  from .time_utils import TimeUtils
5
5
  from .wxwork import WxWorkBot
6
6
  from .shein_daily_report_model import SheinStoreSalesDetailManager, SheinStoreSalesDetail
7
7
 
8
+ import pandas as pd
9
+ import numpy as np
10
+
8
11
  class SheinExcel:
9
12
 
10
13
  def __init__(self, config):
11
14
  self.config = config
12
15
  pass
13
16
 
17
+ def dealReturn(self, sheet):
18
+ # 遍历可用行
19
+ used_range_row = sheet.range('A1').expand('down')
20
+ last_row = len(used_range_row)
21
+
22
+ col_0 = find_column_by_data(sheet, 1, '实际退货/报废总数')
23
+ if last_row < 3:
24
+ fm = f'=SUM({col_0}3:{col_0}3)'
25
+ else:
26
+ fm = f'=SUM({col_0}3:{col_0}{last_row})'
27
+
28
+ sheet.range(f'{col_0}2').formula = fm
29
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
30
+
31
+ for i, cell in enumerate(used_range_row):
32
+ row = i + 1
33
+ if row < 3:
34
+ continue
35
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
36
+ sheet.range(f'{row}:{row}').font.size = 11
37
+
38
+ used_range_col = sheet.range('A1').expand('right')
39
+ for j, cell in enumerate(used_range_col):
40
+ col = j + 1
41
+ col_name = index_to_column_name(col)
42
+ col_val = sheet.range(f'{col_name}1').value
43
+ if col_val not in ['']:
44
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
45
+
46
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
47
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
48
+
49
+ if '时间' in col_val:
50
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
51
+
52
+ if '月份' == col_val:
53
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm'
54
+
55
+ # # 设置标题栏字体颜色与背景色
56
+ # sheet.range(f'{col_name}1').color = (252,228,214)
57
+ # sheet.range(f'{col_name}1').font.size = 12
58
+ # sheet.range(f'{col_name}1').font.bold = True
59
+ # sheet.range(f'{col_name}1').font.color = (0,0, 0)
60
+
61
+ # 所有列水平居中和垂直居中
62
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
63
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
64
+
65
+ # 水平对齐:
66
+ # -4108:居中
67
+ # -4131:左对齐
68
+ # -4152:右对齐
69
+
70
+ # 垂直对齐:
71
+ # -4108:居中
72
+ # -4160:顶部对齐
73
+ # -4107:底部对齐
74
+
75
+ add_borders(sheet)
76
+
77
+ # 获取第一行和第二行
78
+ rows = sheet.range('1:2')
79
+ # 设置字体名称
80
+ rows.font.name = '微软雅黑'
81
+ # 设置字体大小
82
+ rows.font.size = 11
83
+ # 设置字体加粗
84
+ rows.font.bold = True
85
+ # 设置标题栏字体颜色与背景色
86
+ rows.color = (252, 228, 214)
87
+ # 设置行高
88
+ rows.row_height = 30
89
+
90
+ def dealReplenish(self, sheet):
91
+ # 遍历可用行
92
+ used_range_row = sheet.range('A1').expand('down')
93
+ last_row = len(used_range_row)
94
+ # 获取最后一行的索引
95
+ last_col = index_to_column_name(sheet.range('A1').end('right').column)
96
+ # last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
97
+
98
+ col_3 = find_column_by_data(sheet, 1, '总金额')
99
+ if last_row < 3:
100
+ fm = f'=SUM({col_3}3:{col_3}3)'
101
+ else:
102
+ fm = f'=SUM({col_3}3:{col_3}{last_row})'
103
+
104
+ sheet.range(f'{col_3}2').formula = fm
105
+ sheet.range(f'{col_3}2').font.color = (255, 0, 0)
106
+
107
+ for i, cell in enumerate(used_range_row):
108
+ row = i + 1
109
+ if row < 3:
110
+ continue
111
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
112
+ sheet.range(f'{row}:{row}').font.size = 11
113
+
114
+ used_range_col = sheet.range('A1').expand('right')
115
+ for j, cell in enumerate(used_range_col):
116
+ col = j + 1
117
+ col_name = index_to_column_name(col)
118
+ col_val = sheet.range(f'{col_name}1').value
119
+ if col_val not in ['']:
120
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
121
+
122
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
123
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
124
+
125
+ if '时间' in col_val:
126
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
127
+
128
+ if '月份' == col_val:
129
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm'
130
+
131
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
132
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
133
+ # 所有列水平居中和垂直居中
134
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
135
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
136
+
137
+ add_borders(sheet)
138
+
139
+ # === 批量字体设置 ===
140
+ if last_row > 3:
141
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
142
+ data_range.api.Font.Name = "Calibri"
143
+ data_range.api.Font.Size = 11
144
+
145
+ # 获取第一行和第二行
146
+ rows = sheet.range('1:2')
147
+ # 设置字体名称
148
+ rows.font.name = '微软雅黑'
149
+ # 设置字体大小
150
+ rows.font.size = 11
151
+ # 设置字体加粗
152
+ rows.font.bold = True
153
+ # 设置标题栏字体颜色与背景色
154
+ rows.color = (252, 228, 214)
155
+ # 设置行高
156
+ rows.row_height = 30
157
+
158
+ def dealSheinStock(self, sheet):
159
+ col_0 = find_column_by_data(sheet, 1, '期末库存数量')
160
+ col_1 = find_column_by_data(sheet, 1, '期末库存金额')
161
+ col_2 = find_column_by_data(sheet, 1, '单价成本')
162
+ col_3 = find_column_by_data(sheet, 1, '希音仓成本总额')
163
+
164
+ col_4 = find_column_by_data(sheet, 1, '期初库存数量')
165
+ col_5 = find_column_by_data(sheet, 1, '期初库存金额')
166
+
167
+ col_6 = find_column_by_data(sheet, 1, '入库数量')
168
+ col_7 = find_column_by_data(sheet, 1, '入库金额')
169
+ col_8 = find_column_by_data(sheet, 1, '出库数量')
170
+ col_9 = find_column_by_data(sheet, 1, '出库金额')
171
+
172
+ col_10 = find_column_by_data(sheet, 1, '出库成本总额')
173
+ col_11 = find_column_by_data(sheet, 1, '出库利润')
174
+ col_12 = find_column_by_data(sheet, 1, '出库利润率')
175
+
176
+ # 遍历可用行
177
+ used_range_row = sheet.range('A1').expand('down')
178
+ last_row = len(used_range_row)
179
+ # # 获取最后一行的索引
180
+ last_col = index_to_column_name(sheet.range('A1').end('right').column)
181
+ # last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
182
+ if last_row > 2:
183
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
184
+ sheet.range(f'{col_0}2').font.color = (225, 0, 0)
185
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
186
+ sheet.range(f'{col_1}2').font.color = (225, 0, 0)
187
+ sheet.range(f'{col_3}2').formula = f'=SUM({col_3}3:{col_3}{last_row})'
188
+ sheet.range(f'{col_3}2').font.color = (255, 0, 0)
189
+
190
+ sheet.range(f'{col_4}2').formula = f'=SUM({col_4}3:{col_4}{last_row})'
191
+ sheet.range(f'{col_4}2').font.color = (225, 0, 0)
192
+ sheet.range(f'{col_5}2').formula = f'=SUM({col_5}3:{col_5}{last_row})'
193
+ sheet.range(f'{col_5}2').font.color = (225, 0, 0)
194
+
195
+ sheet.range(f'{col_6}2').formula = f'=SUM({col_6}3:{col_6}{last_row})'
196
+ sheet.range(f'{col_6}2').font.color = (225, 0, 0)
197
+ sheet.range(f'{col_7}2').formula = f'=SUM({col_7}3:{col_7}{last_row})'
198
+ sheet.range(f'{col_7}2').font.color = (225, 0, 0)
199
+ sheet.range(f'{col_8}2').formula = f'=SUM({col_8}3:{col_8}{last_row})'
200
+ sheet.range(f'{col_8}2').font.color = (225, 0, 0)
201
+ sheet.range(f'{col_9}2').formula = f'=SUM({col_9}3:{col_9}{last_row})'
202
+ sheet.range(f'{col_9}2').font.color = (225, 0, 0)
203
+
204
+ sheet.range(f'{col_10}2').formula = f'=SUM({col_10}3:{col_10}{last_row})'
205
+ sheet.range(f'{col_10}2').font.color = (225, 0, 0)
206
+
207
+ sheet.range(f'{col_11}2').formula = f'=SUM({col_11}3:{col_11}{last_row})'
208
+ sheet.range(f'{col_11}2').font.color = (225, 0, 0)
209
+
210
+ if last_row > 3:
211
+ # 设置毛利润和毛利润率列公式与格式
212
+ sheet.range(f'{col_3}3').formula = f'={col_0}3*{col_2}3'
213
+ # AutoFill 快速填充到所有行(3 到 last_row)
214
+ sheet.range(f'{col_3}3').api.AutoFill(sheet.range(f'{col_3}3:{col_3}{last_row}').api)
215
+
216
+ sheet.range(f'{col_10}3').formula = f'={col_8}3*{col_2}3'
217
+ sheet.range(f'{col_10}3').api.AutoFill(sheet.range(f'{col_10}3:{col_10}{last_row}').api)
218
+
219
+ sheet.range(f'{col_11}3').formula = f'={col_9}3-{col_10}3'
220
+ sheet.range(f'{col_11}3').api.AutoFill(sheet.range(f'{col_11}3:{col_11}{last_row}').api)
221
+
222
+ sheet.range(f'{col_12}3').number_format = '0.00%'
223
+ sheet.range(f'{col_12}3').formula = f'=IF({col_9}3 > 0,{col_11}3/{col_9}3,0)'
224
+ sheet.range(f'{col_12}3').api.AutoFill(sheet.range(f'{col_12}3:{col_12}{last_row}').api)
225
+
226
+ used_range_col = sheet.range('A1').expand('right')
227
+ for j, cell in enumerate(used_range_col):
228
+ col = j + 1
229
+ col_name = index_to_column_name(col)
230
+ col_val = sheet.range(f'{col_name}1').value
231
+ if col_val not in ['']:
232
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
233
+
234
+ if col_val in ['业务单号']:
235
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
236
+
237
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or ('利润' in col_val and '率' not in col_val):
238
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
239
+
240
+ if '时间' in col_val:
241
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
242
+
243
+ if '月份' == col_val:
244
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm'
245
+
246
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
247
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
248
+ # 所有列水平居中和垂直居中
249
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
250
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
251
+
252
+ add_borders(sheet)
253
+
254
+ # === 批量字体设置 ===
255
+ if last_row > 3:
256
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
257
+ data_range.api.Font.Name = "Calibri"
258
+ data_range.api.Font.Size = 11
259
+
260
+ set_title_style(sheet)
261
+
262
+ def dealSalesPercentageExcel(self, sheet):
263
+ col_0 = find_column_by_data(sheet, 1, '商家SKU')
264
+ col_1 = find_column_by_data(sheet, 1, '售出数量')
265
+ col_2 = find_column_by_data(sheet, 1, '销量占比')
266
+ col_3 = find_column_by_data(sheet, 1, '售出金额')
267
+ col_4 = find_column_by_data(sheet, 1, '销售额占比')
268
+ col_5 = find_column_by_data(sheet, 1, '利润')
269
+ col_6 = find_column_by_data(sheet, 1, '利润占比')
270
+ col_7 = find_column_by_data(sheet, 1, 'SKU图片')
271
+
272
+ # 遍历可用行
273
+ used_range_row = sheet.range('B1').expand('down')
274
+ last_row = len(used_range_row)
275
+ if last_row > 2:
276
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
277
+ sheet.range(f'{col_1}2').font.color = (255, 0, 0)
278
+ sheet.range(f'{col_3}2').formula = f'=SUM({col_3}3:{col_3}{last_row})'
279
+ sheet.range(f'{col_3}2').font.color = (255, 0, 0)
280
+ sheet.range(f'{col_5}2').formula = f'=SUM({col_5}3:{col_5}{last_row})'
281
+ sheet.range(f'{col_5}2').font.color = (255, 0, 0)
282
+ # sheet.range(f'{col_7}1:{col_7}2').merge()
283
+
284
+ for i, cell in enumerate(used_range_row):
285
+ row = i + 1
286
+ if row < 3:
287
+ continue
288
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
289
+ sheet.range(f'{row}:{row}').font.size = 11
290
+
291
+ sheet.range(f'{col_2}{row}').formula = f'={col_1}{row}/{col_1}2'
292
+ sheet.range(f'{col_4}{row}').formula = f'={col_3}{row}/{col_3}2'
293
+ sheet.range(f'{col_6}{row}').formula = f'={col_5}{row}/{col_5}2'
294
+
295
+ used_range_col = sheet.range('A1').expand('right')
296
+ for j, cell in enumerate(used_range_col):
297
+ col = j + 1
298
+ col_name = index_to_column_name(col)
299
+ col_val = sheet.range(f'{col_name}1').value
300
+ if col_val not in ['']:
301
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
302
+
303
+ if col_val in ['占比']:
304
+ sheet.range(f'{col_name}:{col_name}').number_format = '0.00%'
305
+
306
+ if ('价' in col_val or '成本' in col_val or '金额' in col_val or '利润' == col_val):
307
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
308
+
309
+ if '时间' in col_val:
310
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
311
+
312
+ # # 设置标题栏字体颜色与背景色
313
+ # sheet.range(f'{col_name}1').color = (252,228,214)
314
+ # sheet.range(f'{col_name}1').font.size = 12
315
+ # sheet.range(f'{col_name}1').font.bold = True
316
+ # sheet.range(f'{col_name}1').font.color = (0,0, 0)
317
+
318
+ # 所有列水平居中和垂直居中
319
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
320
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
321
+
322
+ # 水平对齐:
323
+ # -4108:居中
324
+ # -4131:左对齐
325
+ # -4152:右对齐
326
+
327
+ # 垂直对齐:
328
+ # -4108:居中
329
+ # -4160:顶部对齐
330
+ # -4107:底部对齐
331
+
332
+ add_borders(sheet)
333
+
334
+ # 获取第一行和第二行
335
+ rows = sheet.range('1:2')
336
+ # 设置字体名称
337
+ rows.font.name = '微软雅黑'
338
+ # 设置字体大小
339
+ rows.font.size = 11
340
+ # 设置字体加粗
341
+ rows.font.bold = True
342
+ # 设置标题栏字体颜色与背景色
343
+ rows.color = (252, 228, 214)
344
+ # 设置行高
345
+ rows.row_height = 30
346
+
347
+ def dealMonthNoSettleMentExcel(self, sheet):
348
+ col_0 = find_column_by_data(sheet, 1, '数量')
349
+ col_2 = find_column_by_data(sheet, 1, '金额')
350
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
351
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
352
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
353
+ col_8 = find_column_by_data(sheet, 1, '成本总额')
354
+
355
+ # 设置格式
356
+ used_range_col = sheet.range('A1').expand('right')
357
+ for j, cell in enumerate(used_range_col):
358
+ col = j + 1
359
+ col_name = index_to_column_name(col)
360
+ col_val = sheet.range(f'{col_name}1').value
361
+ if col_val not in ['']:
362
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
363
+
364
+ if col_val in ['业务单号']:
365
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
366
+
367
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
368
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
369
+
370
+ if '时间' in col_val:
371
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
372
+
373
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
374
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
375
+ # 所有列水平居中和垂直居中
376
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
377
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
378
+
379
+ # 批量设置公式
380
+ last_col = index_to_column_name(sheet.range('A1').end('right').column) # 获取最后一行的索引
381
+ last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
382
+ if last_row > 2:
383
+ # 第3行公式(填一次)
384
+ sheet.range(f'{col_8}2').formula = f'=SUM({col_8}3:{col_8}{last_row})'
385
+ sheet.range(f'{col_8}2').font.color = (255, 0, 0)
386
+ # AutoFill 快速填充到所有行(3 到 last_row)
387
+ sheet.range(f'{col_8}3').formula = f'={col_3}3*{col_0}3'
388
+
389
+ if last_row > 3:
390
+ sheet.range(f'{col_8}3').api.AutoFill(sheet.range(f'{col_8}3:{col_8}{last_row}').api)
391
+
392
+ sheet.range(f'{col_4}1').column_width = 0
393
+
394
+ # 批量设置边框
395
+ add_borders(sheet)
396
+
397
+ if last_row > 2:
398
+ # === 批量字体设置 ===
399
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
400
+ data_range.api.Font.Name = "Calibri"
401
+ data_range.api.Font.Size = 11
402
+
403
+ set_title_style(sheet)
404
+
405
+ def dealMonthBackDetailExcel(self, sheet, summary=0):
406
+ col_0 = find_column_by_data(sheet, 1, '数量')
407
+ col_2 = find_column_by_data(sheet, 1, '金额')
408
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
409
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
410
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
411
+ col_8 = find_column_by_data(sheet, 1, '成本总额')
412
+
413
+ # 设置格式
414
+ used_range_col = sheet.range('A1').expand('right')
415
+ for j, cell in enumerate(used_range_col):
416
+ col = j + 1
417
+ col_name = index_to_column_name(col)
418
+ col_val = sheet.range(f'{col_name}1').value
419
+ if col_val not in ['']:
420
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
421
+
422
+ if col_val in ['业务单号']:
423
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
424
+
425
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
426
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
427
+
428
+ if '时间' in col_val:
429
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
430
+
431
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
432
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
433
+ # 所有列水平居中和垂直居中
434
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
435
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
436
+
437
+ # 批量设置公式
438
+ last_col = index_to_column_name(sheet.range('A1').end('right').column) # 获取最后一行的索引
439
+ last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
440
+ if summary == 1:
441
+ if last_row > 1:
442
+ sheet.range(f'{col_8}2').formula = f'={col_3}2*{col_0}2'
443
+ if last_row > 2:
444
+ # AutoFill 快速填充到所有行(3 到 last_row)
445
+ sheet.range(f'{col_8}3').api.AutoFill(sheet.range(f'{col_8}3:{col_8}{last_row}').api)
446
+ else:
447
+ if last_row > 2:
448
+ # 合计行设置
449
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
450
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
451
+
452
+ sheet.range(f'{col_2}2').formula = f'=SUM({col_2}3:{col_2}{last_row})'
453
+ sheet.range(f'{col_2}2').font.color = (255, 0, 0)
454
+
455
+ sheet.range(f'{col_8}2').formula = f'=SUM({col_8}3:{col_8}{last_row})'
456
+ sheet.range(f'{col_8}2').font.color = (255, 0, 0)
457
+
458
+ # AutoFill 快速填充到所有行(3 到 last_row)
459
+ sheet.range(f'{col_8}3').formula = f'={col_3}3*{col_0}3'
460
+
461
+ if last_row > 3:
462
+ sheet.range(f'{col_8}3').api.AutoFill(sheet.range(f'{col_8}3:{col_8}{last_row}').api)
463
+
464
+ set_title_style(sheet)
465
+
466
+ sheet.range(f'{col_4}1').column_width = 0
467
+
468
+ # 批量设置边框
469
+ add_borders(sheet)
470
+
471
+ if last_row > 3:
472
+ # === 批量字体设置 ===
473
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
474
+ data_range.api.Font.Name = "Calibri"
475
+ data_range.api.Font.Size = 11
476
+
477
+ def dealMonthSalesDetailExcel(self, sheet):
478
+ col_0 = find_column_by_data(sheet, 1, '数量')
479
+ col_1 = find_column_by_data(sheet, 1, '利润')
480
+ col_2 = find_column_by_data(sheet, 1, '金额')
481
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
482
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
483
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
484
+ col_6 = find_column_by_data(sheet, 1, '售出数量')
485
+ col_7 = find_column_by_data(sheet, 1, '售出金额')
486
+
487
+ # 设置格式
488
+ used_range_col = sheet.range('A1').expand('right')
489
+ for j, cell in enumerate(used_range_col):
490
+ col = j + 1
491
+ col_name = index_to_column_name(col)
492
+ col_val = sheet.range(f'{col_name}1').value
493
+ if col_val not in ['']:
494
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
495
+
496
+ if col_val in ['业务单号']:
497
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
498
+
499
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
500
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
501
+
502
+ if '时间' in col_val:
503
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
504
+
505
+ # 水平对齐: # -4108:居中 # -4131:左对齐 # -4152:右对齐
506
+ # 垂直对齐: # -4108:居中 # -4160:顶部对齐 # -4107:底部对齐
507
+ # 所有列水平居中和垂直居中
508
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
509
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
510
+
511
+ # 批量设置公式
512
+ last_col = index_to_column_name(sheet.range('A1').end('right').column) # 获取最后一行的索引
513
+ last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
514
+ if last_row > 2:
515
+ # 第3行公式(填一次)
516
+ sheet.range(
517
+ f'{col_1}3').formula = f'=IF(AND(ISNUMBER({col_3}3),{col_5}3="收入结算"),{col_2}3-{col_3}3*{col_0}3,0)'
518
+ sheet.range(f'{col_6}3').formula = f'=IF(AND(ISNUMBER({col_3}3),{col_5}3="收入结算"),{col_0}3,0)'
519
+ sheet.range(f'{col_7}3').formula = f'=IF(AND(ISNUMBER({col_3}3),{col_5}3="收入结算"),{col_2}3,0)'
520
+
521
+ if last_row > 3:
522
+ # AutoFill 快速填充到所有行(3 到 last_row)
523
+ sheet.range(f'{col_1}3').api.AutoFill(sheet.range(f'{col_1}3:{col_1}{last_row}').api)
524
+ sheet.range(f'{col_6}3').api.AutoFill(sheet.range(f'{col_6}3:{col_6}{last_row}').api)
525
+ sheet.range(f'{col_7}3').api.AutoFill(sheet.range(f'{col_7}3:{col_7}{last_row}').api)
526
+
527
+ # 合计行设置
528
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
529
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
530
+
531
+ sheet.range(f'{col_2}2').formula = f'=SUM({col_2}3:{col_2}{last_row})'
532
+ sheet.range(f'{col_2}2').font.color = (255, 0, 0)
533
+
534
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
535
+ sheet.range(f'{col_1}2').font.color = (255, 0, 0)
536
+
537
+ sheet.range(f'{col_6}2').formula = f'=SUM({col_6}3:{col_6}{last_row})'
538
+ sheet.range(f'{col_6}2').font.color = (255, 0, 0)
539
+
540
+ sheet.range(f'{col_7}2').formula = f'=SUM({col_7}3:{col_7}{last_row})'
541
+ sheet.range(f'{col_7}2').font.color = (255, 0, 0)
542
+
543
+ sheet.range(f'{col_4}1').column_width = 0
544
+
545
+ # 批量设置边框
546
+ add_borders(sheet)
547
+
548
+ if last_row > 3:
549
+ # === 批量字体设置 ===
550
+ data_range = sheet.range(f'A3:{last_col}{last_row}')
551
+ data_range.api.Font.Name = "Calibri"
552
+ data_range.api.Font.Size = 11
553
+ log(f'设置字体: A3:{col_7}{last_row}')
554
+
555
+ # 获取第一行和第二行
556
+ rows = sheet.range('1:2')
557
+ # 设置字体名称
558
+ rows.font.name = '微软雅黑'
559
+ # 设置字体大小
560
+ rows.font.size = 11
561
+ # 设置字体加粗
562
+ rows.font.bold = True
563
+ # 设置标题栏字体颜色与背景色
564
+ rows.color = (252, 228, 214)
565
+ # 设置行高
566
+ rows.row_height = 30
567
+
568
+ def calc_month_sales_percentage(self, month_data):
569
+ df = pd.DataFrame(data=month_data[2:], columns=month_data[:1][0])
570
+
571
+ # 确保 "商家SKU" 是字符串
572
+ df["商家SKU"] = df["商家SKU"].astype(str).str.strip()
573
+
574
+ # 确保 "数量", "金额", "单价成本" 是数值类型
575
+ df["售出数量"] = pd.to_numeric(df["售出数量"], errors="coerce")
576
+ df["售出金额"] = pd.to_numeric(df["售出金额"], errors="coerce")
577
+ df["单价成本"] = pd.to_numeric(df["单价成本"], errors="coerce")
578
+
579
+ # 重新计算利润
580
+ df["利润"] = np.where(
581
+ df["结算类型"] == "收入结算",
582
+ df["售出金额"] - (df["单价成本"] * df["售出数量"]),
583
+ 0
584
+ )
585
+
586
+ # 进行分组统计(求和)
587
+ summary = df.groupby("商家SKU", as_index=False).agg({
588
+ "售出数量": "sum",
589
+ "售出金额": "sum",
590
+ "利润" : "sum",
591
+ "SKU图片" : "first"
592
+ })
593
+
594
+ # 计算总值
595
+ total_quantity = summary["售出数量"].sum()
596
+ total_amount = summary["售出金额"].sum()
597
+ total_profit = summary["利润"].sum()
598
+
599
+ # 计算占比
600
+ summary["销量占比"] = summary["售出数量"] / total_quantity * 100
601
+ summary["销售额占比"] = summary["售出金额"] / total_amount * 100
602
+ summary["利润占比"] = summary["利润"] / total_profit * 100
603
+
604
+ # 确保显示 2 位小数,并加上百分号
605
+ summary["销量占比"] = summary["销量占比"].map(lambda x: f"{x:.2f}%")
606
+ summary["销售额占比"] = summary["销售额占比"].map(lambda x: f"{x:.2f}%")
607
+ summary["利润占比"] = summary["利润占比"].map(lambda x: f"{x:.2f}%")
608
+
609
+ # 重新排序列
610
+ summary = summary[["SKU图片", "商家SKU", "售出数量", "销量占比", "售出金额", "销售额占比", "利润", "利润占比"]]
611
+ summary_list = summary.values.tolist()
612
+
613
+ summary_list.insert(0, ['', '合计', '', '', '', '', '', '']) # 把表头插入到数据列表的第一行
614
+ # 添加标题行(表头)
615
+ header = summary.columns.tolist()
616
+ summary_list.insert(0, header) # 把表头插入到数据列表的第一行
617
+
618
+ return summary_list
619
+
620
+ def dealMonthSalesDetailExcel_old(self, sheet):
621
+ col_0 = find_column_by_data(sheet, 1, '数量')
622
+ col_1 = find_column_by_data(sheet, 1, '利润')
623
+ col_2 = find_column_by_data(sheet, 1, '金额')
624
+ col_3 = find_column_by_data(sheet, 1, '单价成本')
625
+ col_4 = find_column_by_data(sheet, 1, 'SKU图片')
626
+ col_5 = find_column_by_data(sheet, 1, '结算类型')
627
+ col_6 = find_column_by_data(sheet, 1, '售出数量')
628
+ col_7 = find_column_by_data(sheet, 1, '售出金额')
629
+ # 遍历可用行
630
+ used_range_row = sheet.range('A1').expand('down')
631
+ last_row = len(used_range_row)
632
+ for i, cell in enumerate(used_range_row):
633
+ row = i + 1
634
+ if row < 3:
635
+ continue
636
+ sheet.range(f'{row}:{row}').font.name = 'Calibri'
637
+ sheet.range(f'{row}:{row}').font.size = 11
638
+ range0 = f'{col_0}{row}'
639
+ range2 = f'{col_2}{row}'
640
+ range3 = f'{col_3}{row}'
641
+ range5 = f'{col_5}{row}'
642
+ # 设置毛利润和毛利润率列公式与格式
643
+ sheet.range(
644
+ f'{col_1}{row}').formula = f'=IF(AND(ISNUMBER({range3}),{range5}="收入结算"),{range2}-{range3}*{range0},0)'
645
+ sheet.range(f'{col_6}{row}').formula = f'=IF(AND(ISNUMBER({range3}),{range5}="收入结算"),{range0},0)'
646
+ sheet.range(f'{col_7}{row}').formula = f'=IF(AND(ISNUMBER({range3}),{range5}="收入结算"),{range2},0)'
647
+ log(f'处理公式: {row}/{last_row}')
648
+
649
+ if last_row > 2:
650
+ sheet.range(f'{col_0}2').formula = f'=SUM({col_0}3:{col_0}{last_row})'
651
+ sheet.range(f'{col_0}2').font.color = (255, 0, 0)
652
+ sheet.range(f'{col_2}2').formula = f'=SUM({col_2}3:{col_2}{last_row})'
653
+ sheet.range(f'{col_2}2').font.color = (255, 0, 0)
654
+ sheet.range(f'{col_1}2').formula = f'=SUM({col_1}3:{col_1}{last_row})'
655
+ sheet.range(f'{col_1}2').font.color = (255, 0, 0)
656
+ sheet.range(f'{col_6}2').formula = f'=SUM({col_6}3:{col_6}{last_row})'
657
+ sheet.range(f'{col_6}2').font.color = (255, 0, 0)
658
+ sheet.range(f'{col_7}2').formula = f'=SUM({col_7}3:{col_7}{last_row})'
659
+ sheet.range(f'{col_7}2').font.color = (255, 0, 0)
660
+ sheet.range(f'{col_4}1').column_width = 0
661
+ # # 设置计算模式为自动计算
662
+ # sheet.api.Application.Calculation = -4105 # -4105 代表自动计算模式
663
+ # # 手动触发一次计算
664
+ # sheet.api.Calculate()
665
+
666
+ used_range_col = sheet.range('A1').expand('right')
667
+ for j, cell in enumerate(used_range_col):
668
+ col = j + 1
669
+ col_name = index_to_column_name(col)
670
+ col_val = sheet.range(f'{col_name}1').value
671
+ if col_val not in ['']:
672
+ sheet.range(f'{col_name}:{col_name}').autofit() # 列宽自适应
673
+
674
+ if col_val in ['业务单号']:
675
+ sheet.range(f'{col_name}:{col_name}').number_format = '@'
676
+
677
+ if '价' in col_val or '成本' in col_val or '金额' in col_val or '利润' in col_val:
678
+ sheet.range(f'{col_name}:{col_name}').number_format = '¥#,##0.00'
679
+
680
+ if '时间' in col_val:
681
+ sheet.range(f'{col_name}:{col_name}').number_format = 'yyyy-mm-dd hh:mm:ss'
682
+
683
+ # # 设置标题栏字体颜色与背景色
684
+ # sheet.range(f'{col_name}1').color = (252,228,214)
685
+ # sheet.range(f'{col_name}1').font.size = 12
686
+ # sheet.range(f'{col_name}1').font.bold = True
687
+ # sheet.range(f'{col_name}1').font.color = (0,0, 0)
688
+
689
+ # 所有列水平居中和垂直居中
690
+ sheet.range(f'{col_name}:{col_name}').api.HorizontalAlignment = -4108
691
+ sheet.range(f'{col_name}:{col_name}').api.VerticalAlignment = -4108
692
+
693
+ # 水平对齐:
694
+ # -4108:居中
695
+ # -4131:左对齐
696
+ # -4152:右对齐
697
+
698
+ # 垂直对齐:
699
+ # -4108:居中
700
+ # -4160:顶部对齐
701
+ # -4107:底部对齐
702
+
703
+ add_borders(sheet)
704
+
705
+ # 获取第一行和第二行
706
+ rows = sheet.range('1:2')
707
+ # 设置字体名称
708
+ rows.font.name = '微软雅黑'
709
+ # 设置字体大小
710
+ rows.font.size = 11
711
+ # 设置字体加粗
712
+ rows.font.bold = True
713
+ # 设置标题栏字体颜色与背景色
714
+ rows.color = (252, 228, 214)
715
+ # 设置行高
716
+ rows.row_height = 30
717
+
718
+ def write_month_sales_detail(self, store_username, store_name, ledger_list, shein_stock_list, shein_replenish_list, shein_return_list, shein_back_list, shein_no_settlement_list):
719
+ last_month = TimeUtils.get_last_month()
720
+
721
+ supplierName = ''
722
+
723
+ excel_path_month = str(self.config.excel_shein_finance_month_report).replace('#store_name#', store_name)
724
+
725
+ month_data = [[
726
+ '平台SKU', '商家SKU', '属性集', '数量', '单价', '金额', '单价成本', '利润', '售出数量', '售出金额', '添加时间',
727
+ '业务单号', '单据号', '变动类型', '结算类型', 'SKC', '供方货号', '供应商名称', 'SKU图片',
728
+ ], ['合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']]
729
+ log('len(ledger_list)', len(ledger_list))
730
+ for month_item in ledger_list:
731
+ row_item = []
732
+ supplierName = month_item['supplierName']
733
+ platform_sku = month_item['sku']
734
+ row_item.append(platform_sku)
735
+ supplier_sku = month_item['supplierSku'] if month_item['supplierSku'] else '-'
736
+ row_item.append(supplier_sku)
737
+ row_item.append(month_item['suffixZh'])
738
+ row_item.append(month_item['quantity'])
739
+ row_item.append(month_item['cost'])
740
+ row_item.append(month_item['amount'])
741
+ row_item.append(month_item['cost_price'])
742
+ row_item.append('')
743
+ row_item.append(
744
+ month_item['quantity'] if month_item['cost_price'] and month_item['settleTypeName'] == '收入结算' else 0)
745
+ row_item.append(
746
+ month_item['amount'] if month_item['cost_price'] and month_item['settleTypeName'] == '收入结算' else 0)
747
+ row_item.append(month_item['addTime'])
748
+ row_item.append(month_item['businessNo'])
749
+ row_item.append(month_item['billNo'])
750
+ row_item.append(month_item['displayChangeTypeName'])
751
+ row_item.append(month_item['settleTypeName'])
752
+ row_item.append(month_item['skc'])
753
+ row_item.append(month_item['supplierCode'])
754
+ row_item.append(month_item['supplierName'])
755
+ row_item.append(month_item['sku_img'])
756
+ month_data.append(row_item)
757
+
758
+ sheet_name = f'{last_month}月销售明细'
759
+
760
+ write_data(excel_path_month, sheet_name, sort_by_column(month_data, 1, 2, False), ['L'])
761
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
762
+ set_title_style(sheet, 2)
763
+ set_body_style(sheet, 3)
764
+ add_borders(sheet)
765
+ format_to_money(sheet, ['单价', '金额', '利润'])
766
+ format_to_datetime(sheet, ['时间'])
767
+ add_formula_for_column(sheet, '利润', '=IF(AND(ISNUMBER(G3),O3="收入结算"),F3-G3*D3,0)', 3)
768
+ add_formula_for_column(sheet, '售出数量', '=IF(AND(ISNUMBER(G3),O3="收入结算"),D3,0)', 3)
769
+ add_formula_for_column(sheet, '售出金额', '=IF(AND(ISNUMBER(G3),O3="收入结算"),F3,0)', 3)
770
+ add_sum_for_cell(sheet, ['数量', '金额', '利润', '售出数量', '售出金额'])
771
+ column_to_left(sheet, ['平台SKU', '商家SKU', '属性集'])
772
+ column_to_right(sheet, ['单价', '金额', '利润'])
773
+ hidden_columns(sheet, ['SKU图片'])
774
+ close_excel(app, wb)
775
+
776
+ summary_list = self.calc_month_sales_percentage(month_data)
777
+
778
+ sheet_name = f'{last_month}月销售占比'
779
+
780
+ write_data(excel_path_month, sheet_name, sort_by_column(summary_list, 6, 2))
781
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
782
+ set_title_style(sheet, 2)
783
+ set_body_style(sheet, 3)
784
+ add_borders(sheet)
785
+ format_to_money(sheet, ['金额', '利润'])
786
+ format_to_percent(sheet, ['占比'])
787
+ add_sum_for_cell(sheet, ['利润', '售出数量', '售出金额'])
788
+ column_to_left(sheet, ['商家SKU'])
789
+ column_to_right(sheet, ['金额', '利润'])
790
+ InsertImageV2(sheet, ['SKU图片'], 'shein', 90, None, None, True, 3)
791
+ close_excel(app, wb)
792
+
793
+ stock_data = [[
794
+ '月份', 'SKC', '供方货号', '平台SKU', '商家SKU', '属性集', '期初库存数量', '期初库存金额', '入库数量',
795
+ '入库金额', '出库数量', '出库金额', '期末库存数量', '期末库存金额', '单价成本', '出库成本总额',
796
+ '希音仓成本总额', '出库利润', '出库利润率', '供应商名称', '店铺账号', '店铺别名'
797
+ ], [
798
+ '合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''
799
+ ]]
800
+
801
+ for stock_item in shein_stock_list:
802
+ row_item = []
803
+ row_item.append(stock_item['reportDate'])
804
+ row_item.append(stock_item['skc'])
805
+ row_item.append(stock_item['supplierCode'])
806
+ row_item.append(stock_item['skuCode'])
807
+ row_item.append(stock_item['supplierSku'])
808
+ row_item.append(stock_item['suffixZh'])
809
+ row_item.append(stock_item['beginBalanceCnt'])
810
+ row_item.append(stock_item['beginBalanceAmount'])
811
+ row_item.append(stock_item['inCnt'])
812
+ row_item.append(stock_item['inAmount'])
813
+ row_item.append(stock_item['outCnt'])
814
+ row_item.append(stock_item['outAmount'])
815
+ row_item.append(stock_item['endBalanceCnt'])
816
+ row_item.append(stock_item['endBalanceAmount'])
817
+ row_item.append(stock_item['cost_price'])
818
+ row_item.append('')
819
+ row_item.append('')
820
+ row_item.append('')
821
+ row_item.append('')
822
+ row_item.append(stock_item['supplierName'])
823
+ row_item.append(store_username)
824
+ row_item.append(store_name)
825
+ stock_data.append(row_item)
826
+
827
+ sheet_name = f'{last_month}月库存结余'
828
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_库存结余.json', {store_username: stock_data[:1] + stock_data[2:]}, [store_username])
829
+
830
+ write_data(excel_path_month, sheet_name, sort_by_column(stock_data, 11, 2))
831
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
832
+ set_title_style(sheet, 2)
833
+ set_body_style(sheet, 3)
834
+ add_borders(sheet)
835
+ format_to_money(sheet, ['金额', '总额', '成本', '出库利润'])
836
+ column_to_right(sheet, ['金额', '总额', '成本', '出库利润'])
837
+ format_to_percent(sheet, ['利润率'])
838
+ column_to_left(sheet, ['供方货号', '平台SKU', '商家SKU', '属性集'])
839
+ add_sum_for_cell(sheet, ['期初库存数量', '期初库存金额', '入库数量', '入库金额', '出库数量', '出库金额', '期末库存数量', '期末库存金额', '出库成本总额', '希音仓成本总额', '出库利润'])
840
+ add_formula_for_column(sheet, '出库成本总额', '=K3*O3', 3)
841
+ add_formula_for_column(sheet, '希音仓成本总额', '=M3*O3', 3)
842
+ add_formula_for_column(sheet, '出库利润', '=L3-P3', 3)
843
+ add_formula_for_column(sheet, '出库利润率', '=IF(L3 > 0,R3/L3,0)', 3)
844
+ sheet.autofit()
845
+ close_excel(app, wb)
846
+
847
+ replenish_data = [[
848
+ "补扣款单号", "款项类型", "补扣款分类", "对单类型", "关联单据", "单价", "数量", "总金额", "币种", "创建时间",
849
+ "单据状态", "关联报账单", "拒绝原因", "确认/拒绝时间", "操作人", "会计日期", "是否可报账", "申诉单号",
850
+ "公司主体", "出口模式", "备注", "供货商名称", "店铺账号", "店铺别名"
851
+ ], [
852
+ "合计", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
853
+ ]]
854
+
855
+ for replenish_item in shein_replenish_list:
856
+ row_item = []
857
+ row_item.append(replenish_item['replenishNo'])
858
+ row_item.append(replenish_item['replenishTypeName'])
859
+ row_item.append(replenish_item['categoryName'])
860
+ row_item.append(replenish_item['toOrderTypeName'])
861
+ row_item.append(replenish_item['relationNo'])
862
+ row_item.append(replenish_item['unitPrice'])
863
+ row_item.append(replenish_item['quantity'])
864
+ row_item.append(replenish_item['amount'])
865
+ row_item.append(replenish_item['currencyCode'])
866
+ row_item.append(replenish_item['addTime'])
867
+ row_item.append(replenish_item['replenishStatusName'])
868
+ row_item.append(replenish_item['reportOrderNo'])
869
+ row_item.append(replenish_item['refuseReason'])
870
+ row_item.append(replenish_item['decisionTime'])
871
+ row_item.append(replenish_item['operator'])
872
+ row_item.append(replenish_item['accountDate'])
873
+ row_item.append(replenish_item['reportableName'])
874
+ row_item.append(replenish_item['billNo'])
875
+ row_item.append(replenish_item['companyName'])
876
+ row_item.append(replenish_item['exportingModeName'])
877
+ row_item.append(replenish_item['remark'])
878
+ row_item.append(supplierName)
879
+ row_item.append(store_username)
880
+ row_item.append(store_name)
881
+ replenish_data.append(row_item)
882
+
883
+ sheet_name = f'{last_month}月补扣款列表'
884
+
885
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_补扣款列表.json', {store_username: replenish_data[:1] + replenish_data[2:]}, [store_username])
886
+
887
+ write_data(excel_path_month, sheet_name, replenish_data)
888
+
889
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
890
+ set_title_style(sheet, 2)
891
+ set_body_style(sheet, 3)
892
+ add_borders(sheet)
893
+ format_to_money(sheet, ['金额', '单价'])
894
+ column_to_right(sheet, ['金额', '单价'])
895
+ format_to_datetime(sheet, ['时间'])
896
+ add_sum_for_cell(sheet, ['总金额'])
897
+ sheet.autofit()
898
+ close_excel(app, wb)
899
+
900
+ return_data = [[
901
+ "退货单号", "退货计划单号", "处理类型", "发起原因", "说明", "状态", "退货方式", "退货仓库", "商家货号", "SKC",
902
+ "待退货总数", "实际退货/报废总数", "签收时间", "创建时间", "运单号", "退货联系人", "联系人手机号", "退货地址"
903
+ ], [
904
+ "合计", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
905
+ ]]
906
+
907
+ if len(shein_return_list) > 0:
908
+ log(shein_return_list)
909
+ for return_item in shein_return_list:
910
+ row_item = []
911
+ log(return_item)
912
+ row_item.append(return_item['returnOrderNo'])
913
+ row_item.append(return_item['returnPlanNo'])
914
+ row_item.append(return_item['returnOrderTypeName'])
915
+ row_item.append(return_item['returnReasonTypeName'])
916
+ row_item.append(return_item['returnReason'])
917
+ row_item.append(return_item['returnOrderStatusName'])
918
+ row_item.append(return_item['returnWayTypeName'])
919
+ row_item.append(return_item['warehouseName'])
920
+ row_item.append(','.join(return_item['supplierCodeList']))
921
+ row_item.append(','.join(return_item['skcNameList']))
922
+ row_item.append(return_item['waitReturnQuantity'])
923
+ row_item.append(return_item['returnQuantity'])
924
+ row_item.append(return_item['signTime'])
925
+ row_item.append(return_item['addTime'])
926
+ row_item.append(return_item['expressNoList'])
927
+ row_item.append(return_item['sellerContract'])
928
+ row_item.append(return_item['sellerContractPhone'])
929
+ row_item.append(return_item['returnAddress'])
930
+ return_data.append(row_item)
931
+
932
+ sheet_name = f'{last_month}月退货与报废单列表'
933
+
934
+ write_data(excel_path_month, sheet_name, return_data, ['O', 'Q'])
935
+
936
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
937
+ set_title_style(sheet, 2)
938
+ set_body_style(sheet, 3)
939
+ add_borders(sheet)
940
+ format_to_datetime(sheet, ['时间'])
941
+ add_sum_for_cell(sheet, ['实际退货/报废总数'])
942
+ sheet.autofit()
943
+ close_excel(app, wb)
944
+
945
+ ###############################退供#######################################
946
+ month_data = [[
947
+ '平台SKU', '商家SKU', '属性集', '数量', '单价', '金额', '单价成本', '成本总额', '添加时间', '业务单号',
948
+ '单据号', '变动类型', '结算类型', 'SKC', '供方货号', '供应商名称', '店铺账号', '店铺别名', 'SKU图片',
949
+ ], ['合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']]
950
+ log('len(back_list)', len(shein_back_list))
951
+ for month_item in shein_back_list:
952
+ row_item = []
953
+ platform_sku = month_item['sku']
954
+ row_item.append(platform_sku)
955
+ supplier_sku = month_item['supplierSku'] if month_item['supplierSku'] else '-'
956
+ row_item.append(supplier_sku)
957
+ row_item.append(month_item['suffixZh'])
958
+ row_item.append(month_item['quantity'])
959
+ row_item.append(month_item['cost'])
960
+ row_item.append(month_item['amount'])
961
+ row_item.append(month_item['cost_price'])
962
+ row_item.append('')
963
+ row_item.append(month_item['addTime'])
964
+ row_item.append(month_item['businessNo'])
965
+ row_item.append(month_item['billNo'])
966
+ row_item.append(month_item['displayChangeTypeName'])
967
+ row_item.append(month_item['settleTypeName'])
968
+ row_item.append(month_item['skc'])
969
+ row_item.append(month_item['supplierCode'])
970
+ row_item.append(month_item['supplierName'])
971
+ row_item.append(store_username)
972
+ row_item.append(store_name)
973
+ row_item.append(month_item['sku_img'])
974
+ month_data.append(row_item)
975
+
976
+ sheet_name = f'{last_month}月退供明细'
977
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_退供列表.json', {store_username: month_data[:1] + month_data[2:]}, [store_username])
978
+ write_data(excel_path_month, sheet_name, sort_by_column(month_data, 2, 2))
979
+
980
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
981
+ set_title_style(sheet, 2)
982
+ set_body_style(sheet, 3)
983
+ add_borders(sheet)
984
+ format_to_money(sheet, ['金额', '单价', '总额'])
985
+ column_to_right(sheet, ['金额', '单价', '总额'])
986
+ format_to_datetime(sheet, ['时间'])
987
+ add_sum_for_cell(sheet, ['数量', '金额', '成本总额'])
988
+ add_formula_for_column(sheet, '成本总额', '=G3*D3', 3)
989
+ hidden_columns(sheet, ['SKU图片'])
990
+ sheet.autofit()
991
+ close_excel(app, wb)
992
+
993
+ ###############################不结算#######################################
994
+ month_data = [[
995
+ '平台SKU', '商家SKU', '属性集', '数量', '单价', '金额', '单价成本', '成本总额', '添加时间', '业务单号',
996
+ '单据号', '变动类型', '结算类型', 'SKC', '供方货号', '供应商名称', '店铺账号', '店铺别名', 'SKU图片',
997
+ ], ['合计', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''
998
+ ]]
999
+ log('len(shein_no_settlement_list)', len(shein_no_settlement_list))
1000
+ for month_item in shein_no_settlement_list:
1001
+ row_item = []
1002
+ platform_sku = month_item['sku']
1003
+ row_item.append(platform_sku)
1004
+ supplier_sku = month_item['supplierSku'] if month_item['supplierSku'] else '-'
1005
+ row_item.append(supplier_sku)
1006
+ row_item.append(month_item['suffixZh'])
1007
+ row_item.append(month_item['quantity'])
1008
+ row_item.append(month_item['cost'])
1009
+ row_item.append(month_item['amount'])
1010
+ row_item.append(month_item['cost_price'])
1011
+ row_item.append('')
1012
+ row_item.append(month_item['addTime'])
1013
+ row_item.append(month_item['businessNo'])
1014
+ row_item.append(month_item['billNo'])
1015
+ row_item.append(month_item['displayChangeTypeName'])
1016
+ row_item.append(month_item['settleTypeName'])
1017
+ row_item.append(month_item['skc'])
1018
+ row_item.append(month_item['supplierCode'])
1019
+ row_item.append(month_item['supplierName'])
1020
+ row_item.append(store_username)
1021
+ row_item.append(store_name)
1022
+ row_item.append(month_item['sku_img'])
1023
+ month_data.append(row_item)
1024
+
1025
+ sheet_name = f'{last_month}月不结算明细'
1026
+
1027
+ write_dict_to_file_ex(f'{self.config.auto_dir}/shein/cache/sheet_{last_month}_不结算列表.json', {store_username: month_data[:1] + month_data[2:]}, [store_username])
1028
+
1029
+ write_data(excel_path_month, sheet_name, sort_by_column(month_data, 2, 2))
1030
+
1031
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
1032
+ set_title_style(sheet, 2)
1033
+ set_body_style(sheet, 3)
1034
+ add_borders(sheet)
1035
+ format_to_money(sheet, ['金额', '单价', '总额'])
1036
+ column_to_right(sheet, ['金额', '单价', '总额'])
1037
+ format_to_datetime(sheet, ['时间'])
1038
+ add_sum_for_cell(sheet, ['数量', '金额', '成本总额'])
1039
+ add_formula_for_column(sheet, '成本总额', '=G3*D3', 3)
1040
+ hidden_columns(sheet, ['SKU图片'])
1041
+ sheet.autofit()
1042
+ close_excel(app, wb)
1043
+
1044
+ sheet_name = f'{last_month}月利润汇总'
1045
+ # 建立利润汇总sheet页
1046
+ write_json_to_excel('excel_json_profit_detail.json', excel_path_month, sheet_name)
1047
+
1048
+ # 填入数据 销售数量
1049
+ app, wb, sheet = open_excel(excel_path_month, sheet_name)
1050
+ delete_sheet_if_exists(wb, 'Sheet1')
1051
+ move_sheet_to_position(wb, sheet_name, 1)
1052
+ wb.save()
1053
+ sheet.activate()
1054
+
1055
+ target_month = find_column_by_data(sheet, 2, last_month)
1056
+ sheet.range(f'{target_month}3').value = f"='{last_month}月销售明细'!I2"
1057
+ sheet.range(f'{target_month}4').number_format = f"¥#,##0.00;¥-#,##0.00"
1058
+ sheet.range(f'{target_month}4').value = f"='{last_month}月销售明细'!J2"
1059
+ sheet.range(f'{target_month}5').number_format = f"¥#,##0.00;¥-#,##0.00"
1060
+ sheet.range(f'{target_month}5').value = f"='{last_month}月销售明细'!H2"
1061
+ sheet.range(f'{target_month}6').number_format = f"¥#,##0.00;¥-#,##0.00"
1062
+ # sheet.range(f'{target_month}6').value = f"=-'{last_month}月退货与报废单列表'!L2 * 3"
1063
+ sheet.range(f'{target_month}7').number_format = f"¥#,##0.00;¥-#,##0.00"
1064
+ sheet.range(f'{target_month}7').value = f"=-'{last_month}月补扣款列表'!H2"
1065
+ sheet.range(f'{target_month}8').number_format = f"¥#,##0.00;¥-#,##0.00"
1066
+ sheet.range(f'{target_month}9').number_format = f"¥#,##0.00;¥-#,##0.00"
1067
+ sheet.range(f'{target_month}9').value = f"=SUM({target_month}5:{target_month}8)"
1068
+ sheet.range(f'{target_month}10').number_format = f"¥#,##0.00;¥-#,##0.00"
1069
+ sheet.range(f'{target_month}10').value = f"='{last_month}月库存结余'!J2"
1070
+ sheet.range('A1').value = f'2025年{last_month}月 shein 利润汇总表 {store_name}'
1071
+ sheet.range(f'{target_month}:{target_month}').autofit()
1072
+ wb.save()
1073
+ close_excel(app, wb)
1074
+
1075
+ def write_summary_algorithm_1(self):
1076
+ excel_path = self.config.excel_shein_finance_month_report_summary
1077
+
1078
+ sheet_name = '总表-算法1'
1079
+ dict_store_manager_shein = read_dict_from_file(self.config.shein_store_alias)
1080
+ total_data = []
1081
+ header = ['店铺账号', '店铺别名']
1082
+ for mall_id, excel_data in dict_store_manager_shein.items():
1083
+ total_data += [[mall_id, excel_data]]
1084
+
1085
+ log(total_data)
1086
+ filtered_value = [header] + total_data
1087
+ log(filtered_value)
1088
+ filtered_value = add_suffixed_column(filtered_value, '店长', '')
1089
+ filtered_value = add_suffixed_column(filtered_value, '出库金额', '')
1090
+ filtered_value = add_suffixed_column(filtered_value, '出库成本', '')
1091
+ filtered_value = add_suffixed_column(filtered_value, '不结算金额', '')
1092
+ filtered_value = add_suffixed_column(filtered_value, '不结算成本', '')
1093
+ filtered_value = add_suffixed_column(filtered_value, '实际出库金额', '')
1094
+ filtered_value = add_suffixed_column(filtered_value, '实际出库成本', '')
1095
+ filtered_value = add_suffixed_column(filtered_value, '补扣款', '')
1096
+ filtered_value = add_suffixed_column(filtered_value, '线下运费', '')
1097
+ filtered_value = add_suffixed_column(filtered_value, '侵权扣款', '')
1098
+ filtered_value = add_suffixed_column(filtered_value, '希音仓成本总额', '')
1099
+ filtered_value = add_suffixed_column(filtered_value, '毛利', '')
1100
+
1101
+ # 匹配店铺店长
1102
+ dict_store_manager_shein = read_dict_from_file(self.config.shein_store_alias)
1103
+ for row in filtered_value:
1104
+ mall_name = row[0]
1105
+ if mall_name == '店铺账号':
1106
+ continue
1107
+ row[2] = dict_store_manager_shein.get(str(mall_name).lower())
1108
+ self.write_to_one(filtered_value, excel_path, sheet_name)
1109
+
1110
+ def write_summary_algorithm_2(self):
1111
+ excel_path = self.config.excel_shein_finance_month_report_summary
1112
+
1113
+ app, wb, sheet = open_excel(excel_path, 2)
1114
+
1115
+ sheet_name = '总表-算法2'
1116
+ # 将目标工作表移动到第一个工作表之前
1117
+ sheet.api.Move(Before=wb.sheets[0].api)
1118
+ wb.save()
1119
+ close_excel(app, wb)
1120
+
1121
+ dict_store_manager_shein = read_dict_from_file(self.config.shein_store_alias)
1122
+ total_data = []
1123
+ header = ['店铺账号', '店铺别名']
1124
+ for mall_id, excel_data in dict_store_manager_shein.items():
1125
+ total_data += [[mall_id, excel_data]]
1126
+
1127
+ filtered_value = [header] + total_data
1128
+ filtered_value = add_suffixed_column(filtered_value, '店长', '')
1129
+ filtered_value = add_suffixed_column(filtered_value, '出库金额', '')
1130
+ filtered_value = add_suffixed_column(filtered_value, '出库成本', '')
1131
+ filtered_value = add_suffixed_column(filtered_value, '退供金额', '')
1132
+ filtered_value = add_suffixed_column(filtered_value, '退供成本', '')
1133
+ filtered_value = add_suffixed_column(filtered_value, '实际出库金额', '')
1134
+ filtered_value = add_suffixed_column(filtered_value, '实际出库成本', '')
1135
+ filtered_value = add_suffixed_column(filtered_value, '补扣款', '')
1136
+ filtered_value = add_suffixed_column(filtered_value, '线下运费', '')
1137
+ filtered_value = add_suffixed_column(filtered_value, '侵权扣款', '')
1138
+ filtered_value = add_suffixed_column(filtered_value, '希音仓成本总额', '')
1139
+ filtered_value = add_suffixed_column(filtered_value, '毛利', '')
1140
+
1141
+ # 匹配店铺店长
1142
+ for row in filtered_value:
1143
+ mall_name = row[0]
1144
+ if mall_name == '店铺账号':
1145
+ continue
1146
+ row[2] = dict_store_manager_shein.get(str(mall_name).lower())
1147
+ self.write_to_one(filtered_value, excel_path, sheet_name)
1148
+
1149
+ def sumary_part(self):
1150
+ excel_path = self.config.excel_shein_finance_month_report_summary
1151
+ src_directory = f'{self.config.auto_dir}/shein/cache'
1152
+ for file in os.listdir(src_directory):
1153
+ # 检查是否为文件且符合命名模式
1154
+ if file.startswith(f"sheet_{TimeUtils.get_last_month()}") and file.endswith(".json"):
1155
+ file_path = os.path.join(src_directory, file)
1156
+ filename = os.path.basename(file_path) # 获取 "tool.py"
1157
+ name = os.path.splitext(filename)[0]
1158
+ sheet_name = name.split('_')[2]
1159
+ dict = read_dict_from_file(file_path)
1160
+ total_data = []
1161
+ header = []
1162
+ for mall_id, excel_data in dict.items():
1163
+ header = excel_data[0]
1164
+ if len(excel_data) > 1:
1165
+ total_data += excel_data[1:]
1166
+
1167
+ filtered_value = [header] + total_data
1168
+ self.write_to_one(filtered_value, excel_path, f'{sheet_name}-汇总-{TimeUtils.get_last_month()}月')
1169
+
1170
+ def write_to_one(self, data, excel_path, sheet_name="Sheet1", header_column=None):
1171
+ write_data(excel_path, sheet_name, data)
1172
+ app, wb, sheet = open_excel(excel_path, sheet_name)
1173
+ add_borders(sheet)
1174
+ format_to_money(sheet, ['金额', '成本'])
1175
+ format_to_datetime(sheet, ['时间'])
1176
+ if '库存结余' in sheet_name:
1177
+ format_to_percent(sheet, ['利润率'])
1178
+ format_to_month(sheet, ['月份'])
1179
+ add_formula_for_column(sheet, '出库成本总额', f'=IF(ISNUMBER(O2),K2*O2,0)', 2)
1180
+ add_formula_for_column(sheet, '希音仓成本总额', f'=IF(ISNUMBER(O2),M2*O2,0)', 2)
1181
+ add_formula_for_column(sheet, '出库利润', f'=L2-P2', 2)
1182
+ add_formula_for_column(sheet, '出库利润率', f'=IF(L2 > 0,R2/L2,0)', 2)
1183
+ if '退供列表' in sheet_name:
1184
+ add_formula_for_column(sheet, '成本总额', f'=IF(ISNUMBER(G2),D2*G2,0)', 2)
1185
+ if '不结算列表' in sheet_name:
1186
+ add_formula_for_column(sheet, '成本总额', f'=IF(ISNUMBER(G2),D2*G2,0)', 2)
1187
+ if '总表-算法1' in sheet_name:
1188
+ format_to_money(sheet, ['补扣款', '线下运费', '侵权扣款', '毛利'])
1189
+ add_formula_for_column(sheet, '出库金额',
1190
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!L:L)",
1191
+ 2)
1192
+ add_formula_for_column(sheet, '出库成本',
1193
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!P:P)",
1194
+ 2)
1195
+ add_formula_for_column(sheet, '不结算金额',
1196
+ f"=SUMIF('不结算列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'不结算列表-汇总-{TimeUtils.get_last_month()}月'!F:F)",
1197
+ 2)
1198
+ add_formula_for_column(sheet, '不结算成本',
1199
+ f"=SUMIF('不结算列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'不结算列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1200
+ 2)
1201
+ add_formula_for_column(sheet, '实际出库金额', f"=D2-F2", 2)
1202
+ add_formula_for_column(sheet, '实际出库成本', f"=E2-G2", 2)
1203
+ add_formula_for_column(sheet, '补扣款',
1204
+ f"=SUMIF('补扣款列表-汇总-{TimeUtils.get_last_month()}月'!W:W,'总表-算法1'!A:A,'补扣款列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1205
+ 2)
1206
+ add_formula_for_column(sheet, '希音仓成本总额',
1207
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!Q:Q)",
1208
+ 2)
1209
+ add_formula_for_column(sheet, '毛利', f"=H2-I2-J2-K2-L2", 2)
1210
+ # 全是公式 无法排序
1211
+
1212
+ if '总表-算法2' in sheet_name:
1213
+ format_to_money(sheet, ['补扣款', '线下运费', '侵权扣款', '毛利'])
1214
+ add_formula_for_column(sheet, '出库金额',
1215
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!L:L)",
1216
+ 2)
1217
+ add_formula_for_column(sheet, '出库成本',
1218
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!P:P)",
1219
+ 2)
1220
+ add_formula_for_column(sheet, '退供金额',
1221
+ f"=SUMIF('退供列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'退供列表-汇总-{TimeUtils.get_last_month()}月'!F:F)",
1222
+ 2)
1223
+ add_formula_for_column(sheet, '退供成本',
1224
+ f"=SUMIF('退供列表-汇总-{TimeUtils.get_last_month()}月'!Q:Q,'总表-算法1'!A:A,'退供列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1225
+ 2)
1226
+ add_formula_for_column(sheet, '实际出库金额', f"=D2-F2", 2)
1227
+ add_formula_for_column(sheet, '实际出库成本', f"=E2-G2", 2)
1228
+ add_formula_for_column(sheet, '补扣款',
1229
+ f"=SUMIF('补扣款列表-汇总-{TimeUtils.get_last_month()}月'!W:W,'总表-算法1'!A:A,'补扣款列表-汇总-{TimeUtils.get_last_month()}月'!H:H)",
1230
+ 2)
1231
+ add_formula_for_column(sheet, '希音仓成本总额',
1232
+ f"=SUMIF('库存结余-汇总-{TimeUtils.get_last_month()}月'!U:U,'总表-算法1'!A:A,'库存结余-汇总-{TimeUtils.get_last_month()}月'!Q:Q)",
1233
+ 2)
1234
+ add_formula_for_column(sheet, '毛利', f"=H2-I2-J2-K2-L2", 2)
1235
+
1236
+ move_sheet_to_position(wb, '总表-算法1', 1)
1237
+ move_sheet_to_position(wb, '总表-算法2', 1)
1238
+
1239
+ set_title_style(sheet, 1)
1240
+ wb.save()
1241
+ close_excel(app, wb)
1242
+
14
1243
  def format_funds(self, sheet):
15
1244
  beautify_title(sheet)
16
1245
  column_to_right(sheet, ['金额', '汇总'])