qrpa 1.1.29__tar.gz → 1.1.31__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.1.29 → qrpa-1.1.31}/PKG-INFO +1 -1
- {qrpa-1.1.29 → qrpa-1.1.31}/pyproject.toml +1 -1
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/fun_excel.py +27 -3
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/shein_excel.py +282 -12
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/shein_lib.py +3607 -3242
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa.egg-info/PKG-INFO +1 -1
- {qrpa-1.1.29 → qrpa-1.1.31}/README.md +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/RateLimitedSender.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/__init__.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/db_migrator.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/feishu_bot_app.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/feishu_client.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/feishu_logic.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/fun_base.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/fun_file.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/fun_web.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/fun_win.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/mysql_module/__init__.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/mysql_module/shein_ledger_model.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/mysql_module/shein_product_model.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/mysql_module/shein_return_order_model.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/shein_daily_report_model.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/shein_mysql.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/shein_sqlite.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/shein_ziniao.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/temu_chrome.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/temu_excel.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/temu_lib.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/time_utils.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/time_utils_example.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa/wxwork.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa.egg-info/SOURCES.txt +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa.egg-info/dependency_links.txt +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/qrpa.egg-info/top_level.txt +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/setup.cfg +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/setup.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/tests/test_db_migrator.py +0 -0
- {qrpa-1.1.29 → qrpa-1.1.31}/tests/test_wxwork.py +0 -0
|
@@ -2060,7 +2060,7 @@ def pre_format_columns_safe(sheet, columns, data_rows):
|
|
|
2060
2060
|
|
|
2061
2061
|
def post_format_columns_safe(sheet, columns, data_rows):
|
|
2062
2062
|
"""
|
|
2063
|
-
|
|
2063
|
+
后格式化函数:在写入数据后确认列格式并强制转换为文本
|
|
2064
2064
|
|
|
2065
2065
|
Args:
|
|
2066
2066
|
sheet: Excel工作表对象
|
|
@@ -2080,8 +2080,32 @@ def post_format_columns_safe(sheet, columns, data_rows):
|
|
|
2080
2080
|
# 只对实际有数据的行进行格式化
|
|
2081
2081
|
if data_rows > 0:
|
|
2082
2082
|
range_str = f'{col_name}1:{col_name}{data_rows}'
|
|
2083
|
-
sheet.range(range_str)
|
|
2084
|
-
|
|
2083
|
+
target_range = sheet.range(range_str)
|
|
2084
|
+
|
|
2085
|
+
# 设置格式为文本
|
|
2086
|
+
target_range.number_format = '@'
|
|
2087
|
+
|
|
2088
|
+
# 关键步骤:读取数据并重新写入,触发文本转换
|
|
2089
|
+
# 这样可以将已经写入的数字转换为文本格式
|
|
2090
|
+
values = target_range.value
|
|
2091
|
+
if values is not None:
|
|
2092
|
+
# 处理单个值的情况
|
|
2093
|
+
if not isinstance(values, list):
|
|
2094
|
+
if values != '':
|
|
2095
|
+
target_range.value = str(values)
|
|
2096
|
+
# 处理列表的情况(单列多行)
|
|
2097
|
+
elif len(values) > 0:
|
|
2098
|
+
# 检查是否是二维数组(实际上单列应该是一维数组)
|
|
2099
|
+
if isinstance(values[0], list):
|
|
2100
|
+
# 二维数组,取第一列
|
|
2101
|
+
converted_values = [[str(row[0]) if row[0] is not None and row[0] != '' else row[0]] for row in values]
|
|
2102
|
+
else:
|
|
2103
|
+
# 一维数组
|
|
2104
|
+
converted_values = [[str(val)] if val is not None and val != '' else [val] for val in values]
|
|
2105
|
+
# 重新写入(这次会按照文本格式写入)
|
|
2106
|
+
target_range.value = converted_values
|
|
2107
|
+
|
|
2108
|
+
log(f'后格式化并转换成功: {range_str}')
|
|
2085
2109
|
|
|
2086
2110
|
except Exception as e:
|
|
2087
2111
|
log(f'后格式化列 {col_name} 失败: {e},继续处理其他列')
|
|
@@ -2828,28 +2828,298 @@ class SheinExcel:
|
|
|
2828
2828
|
(sheet_name, 'move', 1),
|
|
2829
2829
|
])
|
|
2830
2830
|
|
|
2831
|
+
def merge_finance_details_to_summary(self, source_dir, start_date, end_date, output_dir=None):
|
|
2832
|
+
"""
|
|
2833
|
+
将多个店铺的财务收支明细Excel文件合并到一个汇总Excel中
|
|
2834
|
+
|
|
2835
|
+
Args:
|
|
2836
|
+
source_dir: 源文件目录路径
|
|
2837
|
+
start_date: 开始日期,格式: YYYY-MM-DD
|
|
2838
|
+
end_date: 结束日期,格式: YYYY-MM-DD
|
|
2839
|
+
output_dir: 输出目录,默认为None则使用source_dir
|
|
2840
|
+
|
|
2841
|
+
Returns:
|
|
2842
|
+
汇总Excel文件路径
|
|
2843
|
+
"""
|
|
2844
|
+
import os
|
|
2845
|
+
import glob
|
|
2846
|
+
|
|
2847
|
+
# 确定输出目录
|
|
2848
|
+
if output_dir is None:
|
|
2849
|
+
output_dir = source_dir
|
|
2850
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
2851
|
+
|
|
2852
|
+
# 提取月份(从start_date中提取)
|
|
2853
|
+
from datetime import datetime
|
|
2854
|
+
start_dt = datetime.strptime(start_date, '%Y-%m-%d')
|
|
2855
|
+
month_str = f"{start_dt.month}月"
|
|
2856
|
+
|
|
2857
|
+
# 生成输出文件名
|
|
2858
|
+
output_filename = f'希音财务月报POP-{month_str}.xlsx'
|
|
2859
|
+
output_path = os.path.join(output_dir, output_filename)
|
|
2860
|
+
|
|
2861
|
+
log(f'开始合并财务收支明细: {source_dir}')
|
|
2862
|
+
|
|
2863
|
+
# 查找所有匹配的Excel文件
|
|
2864
|
+
pattern = os.path.join(source_dir, f'finance_details_*_{start_date}_{end_date}.xlsx')
|
|
2865
|
+
excel_files = glob.glob(pattern)
|
|
2866
|
+
|
|
2867
|
+
if len(excel_files) == 0:
|
|
2868
|
+
log(f'未找到匹配的文件: {pattern}')
|
|
2869
|
+
raise Exception(f'未找到匹配的财务收支明细文件')
|
|
2870
|
+
|
|
2871
|
+
log(f'找到 {len(excel_files)} 个Excel文件待合并')
|
|
2872
|
+
|
|
2873
|
+
# 读取所有Excel文件并合并数据
|
|
2874
|
+
all_detail_data = []
|
|
2875
|
+
store_list = [] # 存储店铺账号列表
|
|
2876
|
+
header = None
|
|
2877
|
+
|
|
2878
|
+
for idx, excel_file in enumerate(excel_files):
|
|
2879
|
+
log(f'读取文件 {idx + 1}/{len(excel_files)}: {os.path.basename(excel_file)}')
|
|
2880
|
+
|
|
2881
|
+
# 从文件名中提取店铺账号
|
|
2882
|
+
filename = os.path.basename(excel_file)
|
|
2883
|
+
# 格式: finance_details_{store_username}_{start_date}_{end_date}.xlsx
|
|
2884
|
+
parts = filename.replace('.xlsx', '').split('_')
|
|
2885
|
+
if len(parts) >= 5:
|
|
2886
|
+
store_username = parts[2] # finance_details_{store_username}_...
|
|
2887
|
+
store_list.append(store_username)
|
|
2888
|
+
else:
|
|
2889
|
+
log(f'警告:无法从文件名提取店铺账号: {filename}')
|
|
2890
|
+
store_username = 'unknown'
|
|
2891
|
+
store_list.append(store_username)
|
|
2892
|
+
|
|
2893
|
+
# 读取Excel文件
|
|
2894
|
+
try:
|
|
2895
|
+
df = pd.read_excel(excel_file, sheet_name=0)
|
|
2896
|
+
|
|
2897
|
+
if idx == 0:
|
|
2898
|
+
# 第一个文件,保存表头
|
|
2899
|
+
header = df.columns.tolist()
|
|
2900
|
+
log(f'表头列数: {len(header)}')
|
|
2901
|
+
|
|
2902
|
+
# 读取数据(跳过表头)
|
|
2903
|
+
data_rows = df.values.tolist()
|
|
2904
|
+
log(f'读取到 {len(data_rows)} 行数据')
|
|
2905
|
+
|
|
2906
|
+
# 添加到总数据中
|
|
2907
|
+
all_detail_data.extend(data_rows)
|
|
2908
|
+
|
|
2909
|
+
except Exception as e:
|
|
2910
|
+
log(f'读取文件失败: {excel_file}, 错误: {str(e)}')
|
|
2911
|
+
continue
|
|
2912
|
+
|
|
2913
|
+
log(f'合并完成,总共 {len(all_detail_data)} 行数据')
|
|
2914
|
+
|
|
2915
|
+
dict_store_manager_shein = self.config.shein_store_manager
|
|
2916
|
+
dict_store_name = read_dict_from_file(self.config.shein_store_alias)
|
|
2917
|
+
|
|
2918
|
+
# 在"金额"列后面添加"ERP成本"和"成本总额"两列
|
|
2919
|
+
if header:
|
|
2920
|
+
# 查找"金额"列和"商家SKU"列的位置
|
|
2921
|
+
amount_col_idx = None
|
|
2922
|
+
sku_col_idx = None
|
|
2923
|
+
business_no_col_idx = None # 业务单号列索引
|
|
2924
|
+
|
|
2925
|
+
for i, col_name in enumerate(header):
|
|
2926
|
+
if '金额' in str(col_name):
|
|
2927
|
+
amount_col_idx = i
|
|
2928
|
+
if '商家SKU' in str(col_name) or 'SKU' in str(col_name):
|
|
2929
|
+
sku_col_idx = i
|
|
2930
|
+
if '店铺名称' in str(col_name):
|
|
2931
|
+
store_name_idx = i
|
|
2932
|
+
if '店长' in str(col_name):
|
|
2933
|
+
store_manager_idx = i
|
|
2934
|
+
if '业务单号' in str(col_name):
|
|
2935
|
+
business_no_col_idx = i
|
|
2936
|
+
|
|
2937
|
+
if amount_col_idx is not None:
|
|
2938
|
+
# 在"金额"列后面插入两列
|
|
2939
|
+
new_header = header[:amount_col_idx + 1] + ['ERP成本', '成本总额'] + header[amount_col_idx + 1:]
|
|
2940
|
+
log(f'在第{amount_col_idx + 1}列(金额)后面插入"ERP成本"和"成本总额"两列')
|
|
2941
|
+
|
|
2942
|
+
# 业务单号列在插入新列后的索引需要调整
|
|
2943
|
+
if business_no_col_idx is not None and business_no_col_idx > amount_col_idx:
|
|
2944
|
+
business_no_col_idx_adjusted = business_no_col_idx + 2 # 因为插入了2列
|
|
2945
|
+
else:
|
|
2946
|
+
business_no_col_idx_adjusted = business_no_col_idx
|
|
2947
|
+
|
|
2948
|
+
# 处理数据行:在相应位置插入ERP成本和成本总额
|
|
2949
|
+
new_data = []
|
|
2950
|
+
for row_idx, row in enumerate(all_detail_data):
|
|
2951
|
+
# 转换为list(如果是tuple)
|
|
2952
|
+
row_list = list(row)
|
|
2953
|
+
|
|
2954
|
+
store_username = row_list[0]
|
|
2955
|
+
store_name = dict_store_name.get(store_username)
|
|
2956
|
+
store_manager = dict_store_manager_shein.get(str(store_username).lower(), '-')
|
|
2957
|
+
row_list[1] = store_name
|
|
2958
|
+
row_list[2] = store_manager
|
|
2959
|
+
|
|
2960
|
+
# 获取商家SKU
|
|
2961
|
+
sku = None
|
|
2962
|
+
if sku_col_idx is not None and sku_col_idx < len(row_list):
|
|
2963
|
+
sku = row_list[sku_col_idx]
|
|
2964
|
+
|
|
2965
|
+
# 获取ERP成本
|
|
2966
|
+
erp_cost = ''
|
|
2967
|
+
if sku and self.bridge:
|
|
2968
|
+
try:
|
|
2969
|
+
erp_cost = self.bridge.get_sku_cost(str(sku), self.config.erp_source)
|
|
2970
|
+
except Exception as e:
|
|
2971
|
+
log(f'获取SKU成本失败: {sku}, 错误: {str(e)}')
|
|
2972
|
+
|
|
2973
|
+
# 在"金额"列后面插入两列数据
|
|
2974
|
+
new_row = row_list[:amount_col_idx + 1] + [erp_cost, ''] + row_list[amount_col_idx + 1:]
|
|
2975
|
+
new_data.append(new_row)
|
|
2976
|
+
|
|
2977
|
+
# 每1000行输出一次进度
|
|
2978
|
+
if (row_idx + 1) % 1000 == 0:
|
|
2979
|
+
log(f'处理进度: {row_idx + 1}/{len(all_detail_data)}')
|
|
2980
|
+
|
|
2981
|
+
# 更新表头和数据
|
|
2982
|
+
header = new_header
|
|
2983
|
+
all_detail_data = new_data
|
|
2984
|
+
log(f'ERP成本数据处理完成,新表头列数: {len(header)}')
|
|
2985
|
+
if business_no_col_idx_adjusted is not None:
|
|
2986
|
+
log(f'业务单号列已转换为字符串格式,列索引: {business_no_col_idx_adjusted}')
|
|
2987
|
+
else:
|
|
2988
|
+
log('警告:未找到"金额"列,无法添加ERP成本和成本总额列')
|
|
2989
|
+
|
|
2990
|
+
# 准备汇总表数据
|
|
2991
|
+
summary_header = ['店铺账号', '店铺别名', '店长', '出库金额', '出库成本', '备货作业费',
|
|
2992
|
+
'代收服务费', '订单履约服务费', '订单退货', '退货处理费', '退货单履约服务费', '利润']
|
|
2993
|
+
summary_data = [summary_header]
|
|
2994
|
+
|
|
2995
|
+
# 为每个店铺创建一行(其他字段留空,由公式计算)
|
|
2996
|
+
for store_username in store_list:
|
|
2997
|
+
store_name = dict_store_name.get(store_username)
|
|
2998
|
+
store_manager = dict_store_manager_shein.get(str(store_username).lower(), '-')
|
|
2999
|
+
row = [store_username, store_name, store_manager, '', '', '', '', '', '', '', '', '']
|
|
3000
|
+
summary_data.append(row)
|
|
3001
|
+
|
|
3002
|
+
# 写入Excel文件
|
|
3003
|
+
log(f'开始写入汇总Excel: {output_path}')
|
|
3004
|
+
|
|
3005
|
+
# 查找需要格式化为文本的列
|
|
3006
|
+
text_format_columns = []
|
|
3007
|
+
str_keywords = ['业务单号']
|
|
3008
|
+
|
|
3009
|
+
def col_idx_to_letter(idx):
|
|
3010
|
+
"""将列索引转换为Excel列字母 (0->A, 1->B, ..., 25->Z, 26->AA, ...)"""
|
|
3011
|
+
result = ''
|
|
3012
|
+
idx += 1 # Excel列从1开始
|
|
3013
|
+
while idx > 0:
|
|
3014
|
+
idx -= 1
|
|
3015
|
+
result = chr(65 + idx % 26) + result
|
|
3016
|
+
idx //= 26
|
|
3017
|
+
return result
|
|
3018
|
+
|
|
3019
|
+
for col_idx, col_name in enumerate(header):
|
|
3020
|
+
col_name_str = str(col_name)
|
|
3021
|
+
# 检查列名是否包含需要保持为文本的关键词
|
|
3022
|
+
if any(keyword in col_name_str for keyword in str_keywords):
|
|
3023
|
+
col_letter = col_idx_to_letter(col_idx)
|
|
3024
|
+
text_format_columns.append(col_letter)
|
|
3025
|
+
log(f'列"{col_name}"(第{col_idx}列,Excel列{col_letter})将格式化为文本')
|
|
3026
|
+
|
|
3027
|
+
log(f'共{len(text_format_columns)}列需要格式化为文本: {text_format_columns}')
|
|
3028
|
+
|
|
3029
|
+
# 使用batch_excel_operations批量写入和格式化
|
|
3030
|
+
operations = [
|
|
3031
|
+
('财务收支明细', 'write', [header] + all_detail_data, text_format_columns),
|
|
3032
|
+
('财务收支明细', 'format', self.format_check_order),
|
|
3033
|
+
('总表', 'write', summary_data),
|
|
3034
|
+
('总表', 'format', self.format_check_order),
|
|
3035
|
+
('Sheet1', 'delete'),
|
|
3036
|
+
('总表', 'move', 1),
|
|
3037
|
+
]
|
|
3038
|
+
|
|
3039
|
+
batch_excel_operations(output_path, operations)
|
|
3040
|
+
|
|
3041
|
+
log(f'合并完成,文件已保存: {output_path}')
|
|
3042
|
+
return output_path
|
|
3043
|
+
|
|
2831
3044
|
def format_check_order(self, sheet):
|
|
2832
|
-
if sheet.name == '收支明细':
|
|
3045
|
+
if sheet.name == '收支明细' or sheet.name == '财务收支明细':
|
|
2833
3046
|
beautify_title(sheet)
|
|
2834
3047
|
add_borders(sheet)
|
|
2835
3048
|
format_to_datetime(sheet, ['时间'])
|
|
2836
3049
|
format_to_date(sheet, ['日期'])
|
|
2837
|
-
format_to_money(sheet, ['金额', '成本'])
|
|
2838
|
-
column_to_right(sheet, ['金额', '成本'])
|
|
3050
|
+
format_to_money(sheet, ['金额', '成本', 'ERP成本', '成本总额'])
|
|
3051
|
+
column_to_right(sheet, ['金额', '成本', 'ERP成本', '成本总额'])
|
|
2839
3052
|
column_to_left(sheet, ['货号', '商家SKU'])
|
|
2840
|
-
|
|
3053
|
+
|
|
3054
|
+
# 将业务单号列格式化为文本格式
|
|
3055
|
+
try:
|
|
3056
|
+
from .fun_excel import find_column_by_data
|
|
3057
|
+
business_no_col = find_column_by_data(sheet, 1, '业务单号')
|
|
3058
|
+
if business_no_col:
|
|
3059
|
+
# 设置整列为文本格式
|
|
3060
|
+
last_row = sheet.range('A' + str(sheet.cells.last_cell.row)).end('up').row
|
|
3061
|
+
sheet.range(f'{business_no_col}2:{business_no_col}{last_row}').number_format = '@'
|
|
3062
|
+
log(f'业务单号列({business_no_col})已设置为文本格式')
|
|
3063
|
+
except Exception as e:
|
|
3064
|
+
log(f'设置业务单号列格式失败: {str(e)}')
|
|
3065
|
+
|
|
3066
|
+
# 为成本总额列添加公式
|
|
3067
|
+
# 成本总额 = 数量 * ERP成本
|
|
3068
|
+
try:
|
|
3069
|
+
# 查找"数量"列和"ERP成本"列的位置
|
|
3070
|
+
from .fun_excel import find_column_by_data
|
|
3071
|
+
quantity_col = find_column_by_data(sheet, 1, '商品数量')
|
|
3072
|
+
erp_cost_col = find_column_by_data(sheet, 1, 'ERP成本')
|
|
3073
|
+
|
|
3074
|
+
log("数量,ERP成本", quantity_col, erp_cost_col)
|
|
3075
|
+
if quantity_col and erp_cost_col:
|
|
3076
|
+
# 添加公式:成本总额 = 数量 * ERP成本
|
|
3077
|
+
add_formula_for_column(sheet, '成本总额', f'=IF(ISNUMBER({erp_cost_col}2),{quantity_col}2*{erp_cost_col}2,"-")')
|
|
3078
|
+
log('成本总额公式已添加')
|
|
3079
|
+
except Exception as e:
|
|
3080
|
+
log(f'添加成本总额公式失败: {str(e)}')
|
|
2841
3081
|
|
|
2842
3082
|
if sheet.name == '总表':
|
|
2843
3083
|
beautify_title(sheet)
|
|
2844
3084
|
add_borders(sheet)
|
|
2845
3085
|
format_to_money(sheet, ['金额', '成本', '费', '订单退货', '利润'])
|
|
2846
3086
|
column_to_right(sheet, ['金额', '成本', '费', '订单退货', '利润'])
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
3087
|
+
|
|
3088
|
+
# 使用财务收支明细sheet的引用
|
|
3089
|
+
detail_sheet = '财务收支明细' if '财务收支明细' in [s.name for s in sheet.book.sheets] else '收支明细'
|
|
3090
|
+
|
|
3091
|
+
# 查找财务收支明细sheet中各列的位置
|
|
3092
|
+
from .fun_excel import find_column_by_data
|
|
3093
|
+
detail_ws = None
|
|
3094
|
+
for ws in sheet.book.sheets:
|
|
3095
|
+
if ws.name == detail_sheet:
|
|
3096
|
+
detail_ws = ws
|
|
3097
|
+
break
|
|
3098
|
+
|
|
3099
|
+
if detail_ws:
|
|
3100
|
+
# 查找关键列的位置
|
|
3101
|
+
amount_col = find_column_by_data(detail_ws, 1, '金额') # 金额列
|
|
3102
|
+
cost_total_col = find_column_by_data(detail_ws, 1, '成本总额') # 成本总额列
|
|
3103
|
+
store_col = find_column_by_data(detail_ws, 1, '店铺账号') # 店铺账号列
|
|
3104
|
+
type_col = find_column_by_data(detail_ws, 1, '收支类型') # 收支类型列
|
|
3105
|
+
bill_type_col = find_column_by_data(detail_ws, 1, '账单类型') # 账单类型列
|
|
3106
|
+
|
|
3107
|
+
log(f'找到列位置: 金额={amount_col}, 成本总额={cost_total_col}, 店铺账号={store_col}, 收支类型={type_col}, 账单类型={bill_type_col}')
|
|
3108
|
+
|
|
3109
|
+
# 使用找到的列位置生成公式
|
|
3110
|
+
if amount_col and store_col and type_col:
|
|
3111
|
+
add_formula_for_column(sheet, '出库金额', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"收入")')
|
|
3112
|
+
|
|
3113
|
+
if cost_total_col and store_col and type_col:
|
|
3114
|
+
# 使用成本总额列
|
|
3115
|
+
add_formula_for_column(sheet, '出库成本', f'=SUMIFS({detail_sheet}!{cost_total_col}:{cost_total_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"收入")')
|
|
3116
|
+
|
|
3117
|
+
if amount_col and store_col and type_col and bill_type_col:
|
|
3118
|
+
add_formula_for_column(sheet, '备货作业费', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"支出",{detail_sheet}!{bill_type_col}:{bill_type_col},"备货作业费")')
|
|
3119
|
+
add_formula_for_column(sheet, '代收服务费', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"支出",{detail_sheet}!{bill_type_col}:{bill_type_col},"代收服务费")')
|
|
3120
|
+
add_formula_for_column(sheet, '订单履约服务费', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"支出",{detail_sheet}!{bill_type_col}:{bill_type_col},"订单履约服务费")')
|
|
3121
|
+
add_formula_for_column(sheet, '订单退货', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"支出",{detail_sheet}!{bill_type_col}:{bill_type_col},"订单退货")')
|
|
3122
|
+
add_formula_for_column(sheet, '退货处理费', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"支出",{detail_sheet}!{bill_type_col}:{bill_type_col},"退货处理费")')
|
|
3123
|
+
add_formula_for_column(sheet, '退货单履约服务费', f'=SUMIFS({detail_sheet}!{amount_col}:{amount_col},{detail_sheet}!{store_col}:{store_col},A2,{detail_sheet}!{type_col}:{type_col},"支出",{detail_sheet}!{bill_type_col}:{bill_type_col},"退货单履约服务费")')
|
|
3124
|
+
|
|
2855
3125
|
add_formula_for_column(sheet, '利润', '=D2-E2-F2-G2-H2-I2-J2-K2')
|