销售主表终极重构与跨表检索专家规则 (Skill V16)
📌 技能概述
当接收到销售“主表”以及用于检索京东买家姓名的“人名对照表”时,立即激活本技能。Agent 将作为极其严谨的数据清洗专家,在内存中调度类似 Excel 的 VLOOKUP 检索与多表关联逻辑,严格执行以下定义的 16 列重构、条件清洗、字号规范、复合排序与全行色彩渲染规则。 🚨 终极铁律:绝对不能无中生有!如出现 Agent 无法完成或缺少源数据的情况,对应单元格必须留白(全空格或保持空单元格),严禁胡乱捏造。
---
🚨 第一阶段:最高优先级——全局自动脱壳清洗工序
- 执行时机:在读取、检索、匹配或加工任意一列数据的任何单元格内容之前,必须首先无条件执行此工序。
- 清洗法则:无论面对哪个字段(如子单原始单号、拆自组合装、店铺、收货地区等),只要发现开头有
=或者整个文本被双引号"包裹(例如:="330174..."或"焦"),Agent 必须自动将它们剥离,只留下中间最纯净的明文文本,然后再进行后续的逻辑拼接、条件判断与公式生成。
---
📐 第二阶段:全局样式与字号规范
-
全局对齐:最终生成的 Excel 所有单元格(包括行表头与所有数据行)一律设置为 居中对齐。
-
默认字号:全表所有单元格的字体大小如无特殊说明,一律默认为 12 号字大小。
-
特殊列字号:以下四列强制覆盖设置为 11 号字大小:
- 第 5 列(餐饮配料)
- 第 6 列(直销)
- 第 12 列(含税金额)
- 第 13 列(不含税金额)
---
📋 第三阶段:行表头定义
生成的 Excel 必须包含以下 16 列,行表头文字必须完全一致,展示时不思考含义,仅作表头:
\["日期", "省份", "区域", "客户", "餐饮配料", "直销", "品种", "规格", "香型", "数量", "含税单价", "含税金额", "不含税金额", "备注", "订单号", "所属公司"]
---
⚙️ 第四阶段:各列核心转换与清洗逻辑
-
A列 - 日期:不进行逻辑填充,全列留白,保持全列空格或空单元格。【字号:12号】
-
B列 - 省份:提取主表【收货地区】字段的首段省份/自治区名称。无条件去掉“省”、“自治区”、“市”等所有行政后缀。【字号:12号】
- 示例:“湖南省 湘西...” ➡️
湖南;“广西壮族自治区 ...” ➡️广西;“北京市 ...” ➡️北京。
- 示例:“湖南省 湘西...” ➡️
-
C列 - 区域:严格根据 B 列已经清洗出的【省份】进行条件匹配。必须100%忽略你自带的地理常识,必须100%严格执行以下映射规则:【字号:12号】
- ① 如果包含 "吉林"、"黑龙"、"辽宁",输出:
东北 - ② 如果包含 "北京"、"天津"、"安徽"、"山东"、"内蒙"、"河北",输出:
华北(注:遇到安徽必须输出华北) - ③ 如果包含 "陕西"、"甘肃"、"宁夏"、"河南"、"青海"、"山西",输出:
西北 - ④ 如果包含 "浙江"、"福建"、"江西",输出:
华中 - ⑤ 如果包含 "云南"、"贵州"、"四川"、"重庆"、"广西"、"湖北",输出:
西南 - ⑥ 如果包含 "江苏"、"上海",输出:
华东 - ⑦ 如果包含 "新疆"、"西藏"、"海南",输出:
华南 - ⑧ 如果包含 "广东",输出:
广东 - ⑨ 如果包含 "湖南",输出:
湖南
- ① 如果包含 "吉林"、"黑龙"、"辽宁",输出:
-
D列 - 客户(直辖市防重与京东跨表VLOOKUP双轨制):【字号:12号】
-
【核心拦截:直辖市防重规则】:首先审查主表的【收货地区】。如果属于直辖市(北京、上海、重庆、天津),地理前缀强制固定为单个词(即
北京、上海、重庆、天津),绝对禁止拼接二级城市或区县名,从源头上彻底阻断出现“北京北京3305...”等重复地名的现象! -
【非直辖市地理清洗规则】:若非直辖市,地理前缀格式为
省份/自治州 + 地级市。清洗逻辑具备严格的先后顺序: ①【关键剥离顺序】:必须优先检查并剥离末尾的“地区”(两个字)后缀!确认不包含“地区”后,再剥离“市”、“县”、“区”、“盟”等单字行政后缀。严禁先切单字。(例如:“新疆塔城地区”,必须先匹配并切除“地区”变为“新疆塔城”;严禁因先切除“区”字而错误残留为“新疆塔城地”)。 ② 移除“哈尼族”、“土家族”、“苗族”、“彝族”、“壮族”、“自治州”等所有民族和自治谓称。 ③ 安全兜底防御:针对“杭州”、“温州”、“广州”等本身自带“州”字的城市,如果去掉“州”字会导致核心名变成单字(如 杭、温、广),必须强制保留“州”字。只有当去掉“州”字后剩余文本长度 >= 2 时(如“红河州”->“红河”),才允许切除。- 非直辖市示例:浙江省 杭州市 ➡️
浙江杭州;云南省 红河哈尼族彝族自治州 ➡️云南红河;广西壮族自治区 桂林市 ➡️广西桂林;新疆维吾尔自治区 塔城地区 ➡️新疆塔城。
- 非直辖市示例:浙江省 杭州市 ➡️
-
【双轨制分流拼接逻辑】:
- 渠道一:若当前行备注(店铺)为“京东”:启动跨表 VLOOKUP 检索。以本行的【子单原始单号】作为 Key,去关联的“人名对照表”中检索对应的【买家姓名/收件人】。最终拼接格式为:
地理前缀 + 检索到的人名(例如:浙江杭州张三、北京李四)。若对照表中无此单号或姓名为空,则人名留空,仅保留地理前缀。 - 渠道二:若当前行备注(店铺)为非京东渠道(淘宝、天猫、拼多多、抖音等):拼接格式严格执行:
地理前缀 + 子单原始单号(例如:云南红河5116035746666059715、北京3305519328451029988)。
- 渠道一:若当前行备注(店铺)为“京东”:启动跨表 VLOOKUP 检索。以本行的【子单原始单号】作为 Key,去关联的“人名对照表”中检索对应的【买家姓名/收件人】。最终拼接格式为:
-
-
E列 - 餐饮配料:全列所有行数据统一固定填充文本:
餐饮配料。【字号:强制 11 号】 -
F列 - 直销:全列所有行数据统一固定填充文本:
直销。【字号:强制 11 号】 -
G列 - 品种:检索主表【拆自组合装】字段(优先经过第一阶段脱壳清洗),严格按照以下优先级判定逻辑链输出:【字号:12号】
- ① 凡是出现
盐焗粉、浓缩鲜香粉、烧腊香味素、去腥增香调味油、凉拌菜调味油之一的 ➡️ 统一输出:调味品 - ② 包含 "I+G" ➡️ 输出:
I+G - ③ 包含 "呋喃酮" ➡️ 输出:
呋喃酮 - ④ 包含 "甲基环戊烯醇酮" 或 "MCP" ➡️ 输出:
MCP - ⑤ 包含 "甲基"(且不含环戊烯醇酮) ➡️ 输出:
甲基 - ⑥ 包含 "香兰素" ➡️ 输出:
香兰素 - ⑦ 上述皆不满足 ➡️ 统一输出默认值:
乙基
- ① 凡是出现
-
H列 - 规格:检索主表【拆自组合装】字段,严格按照以下特异性优先度从高到低的拦截链进行映射输出:【字号:12号】
- ① 包含 "30g*3盐焗粉" ➡️ 输出:
12KG箱 - ② 包含 "1kg凉拌菜调味油" 或 "1kg去腥增香调味油" ➡️ 输出:
1kg/瓶 - ③ 包含 "500g凉拌菜调味油" 或 "500g去腥增香调味油" ➡️ 输出:
0.5kg/瓶 - ④ 包含 "250克" ➡️ 输出:
5KG箱 - ⑤ 包含 "焦桶"、"纯桶"、"特醇桶"、"焦糖桶" 之一 ➡️ 输出:
10大小 - ⑥ 包含 {"焦","纯","特醇","I+G","香兰素","呋喃酮","甲基","焦箱","纯箱","特醇箱","甲基环戊烯醇酮","香虎粉","焦糖香瓶"} 之一 ➡️ 输出:
箱 - ⑦ 若上述均未命中 ➡️ 统一输出默认值:
箱
- ① 包含 "30g*3盐焗粉" ➡️ 输出:
-
I列 - 香型:【注意:此步骤在重构的倒数第二步统一批量操作】。直接复制主表【拆自组合装】字段的纯文本,然后严格、彻底地将文本中的
"250克"、"箱"、"瓶"、"桶"、"500g"、"1kg"、"30g*3"关键字予以剔除并剥离。(*示例*:“250克纯瓶”转换为纯;“焦箱”转换为焦`)。【字号:12号】 -
J列 - 数量:直接映射主表的【实发数量】数值。【字号:12号】
-
K列 - 含税单价:计算数值,计算公式为:
主表【单品支付金额】 / 主表【实发数量】。【字号:12号】 -
L列 - 含税金额:单元格内不填入死值,必须保留 Excel 原生计算公式字符串:
=J{行号}\*K{行号}(例如第12725行,单元格公式为=J12725\*K12725)。【字号:强制 11 号】 -
M列 - 不含税金额:单元格内必须保留 Excel 原生计算公式字符串,公式为前一列除以 1.13:
=L{行号}/1.13(例如第12690行,单元格公式为=L12690/1.13)。重中之重:针对该整列单元格,必须在 Excel 中将单元格格式设置为“数值”格式,并严格保留 2 位小数。 【字号:强制 11 号】 -
N列 - 备注:提取主表【店铺】字段,抹除所有多余文字,仅保留
淘宝、天猫、京东、拼多多、抖音这五个标准核心核心词。 -
O列 - 订单号:直接映射主表的【子单原始单号】。【字号:12号】
-
P列 - 所属公司:根据 N 列【备注】进行拦截判断:【字号:12号】
- 若备注为 "淘宝" ➡️ 输出:
肇庆香料 - 备注为其他任意店铺(天猫、京东、拼多多、抖音) ➡️ 统一输出:
华宝星湖
- 若备注为 "淘宝" ➡️ 输出:
---
📊 第五阶段:多级置顶复合排序与全行高亮渲染 (最后一步)
-
跨渠道店内多级置顶复合排序逻辑:
-
第一级大排序(店铺渠道排队):全表所有行严格按照 淘宝 ➡️ 天猫 ➡️ 京东 ➡️ 拼多多 ➡️ 抖音 的先后顺序进行大排队,形成 5 个连续的渠道区块。
-
第二级大排序(店铺内部块的三级品种置顶):在上述每一个独立的店铺区块内部,必须再执行以下细分品种排序:
- 【绝对置顶层】:凡是品种(G列)为
调味品的行,必须强制集中排在当前店铺区块的最前面。 - 【次优先层】:紧随其后排列品种(G列)
不是“乙基”的所有其他行(如香兰素、I+G、MCP、甲基等)。 - 【行垫底层】:品种(G列)为
乙基的行,必须全部排在当前店铺区块的最后面。
- 【绝对置顶层】:凡是品种(G列)为
-
-
全行高亮色彩填充规则: 必须对整行(从 A 列到 P 列,包括没有任何文字的绝对空白单元格)进行无死角底色填充:
- 天猫 店铺块所在整行:填充纯黄底色,十六进制码
#FFFF00 - 京东 店铺块所在整行:填充绿底色,十六进制码
#92D050 - 拼多多 店铺块所在整行:填充蓝底色,十六进制码
#00B0F0 - 抖音 店铺块所在整行:填充橙底色,十六进制码
#ED7D31 - 淘宝 店铺块所在整行:保持默认,不填充任何底色。
- 天猫 店铺块所在整行:填充纯黄底色,十六进制码
---
🐍 附录:Agent 内部 Code Interpreter 自动化执行参考脚本
若 Agent 在执行过程中调用 Python 进行物理建表,已将切词逻辑完美修正(多字后缀在前,单字在后):
import re
import os
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Alignment, PatternFill, Font
def clean\_shell(val):
"""全局自动脱壳清洗工序"""
if pd.isna(val): return ""
val\_str = str(val).strip()
if val\_str.startswith('='):
val\_str = val\_str.lstrip('=').strip('"')
if val\_str.startswith('"') and val\_str.endswith('"'):
val\_str = val\_str.strip('"')
return val\_str.strip()
def process\_rebuild\_engine(main\_table\_path, name\_table\_path, output\_path):
df\_main = pd.read\_csv(main\_table\_path) if main\_table\_path.endswith('.csv') else pd.read\_excel(main\_table\_path)
# 建立京东人名 VLOOKUP 字典
vlookup\_dict = {}
if name\_table\_path and os.path.exists(name\_table\_path):
df\_name = pd.read\_csv(name\_table\_path) if name\_table\_path.endswith('.csv') else pd.read\_excel(name\_table\_path)
id\_col = \[c for c in df\_name.columns if '单号' in str(c) or '订单' in str(c)]\[0]
name\_col = \[c for c in df\_name.columns if any(x in str(c) for x in \['人', '名', '姓名'])]\[0]
for \_, n\_row in df\_name.iterrows():
k = clean\_shell(n\_row.get(id\_col, ''))
v = clean\_shell(n\_row.get(name\_col, ''))
if k: vlookup\_dict\[k] = v
region\_rules = {
'东北': \['吉林', '黑龙', '辽宁'],
'华北': \['北京', '天津', '安徽', '山东', '内蒙', '河北'],
'西北': \['陕西', '甘肃', '宁夏', '河南', '青海', '山西'],
'华中': \['浙江', '福建', '江西'],
'西南': \['云南', '贵州', '四川', '重庆', '广西', '湖北'],
'华东': \['江苏', '上海'],
'华南': \['新疆', '西藏', '海南'],
'广东': \['广东'], '湖南': \['湖南']
}
parsed\_rows = \[]
for \_, row in df\_main.iterrows():
shop\_raw = clean\_shell(row.get('店铺', ''))
combo = clean\_shell(row.get('拆自组合装', ''))
addr\_raw = clean\_shell(row.get('收货地区', ''))
order\_id = clean\_shell(row.get('子单原始单号', ''))
qty = clean\_shell(row.get('实发数量', ''))
pay\_amt = clean\_shell(row.get('单品支付金额', ''))
remark = ""
for p in \['淘宝', '天猫', '京东', '拼多多', '抖音']:
if p in shop\_raw: remark = p; break
if not remark: continue
addr\_parts = addr\_raw.split()
prov\_raw = addr\_parts\[0] if len(addr\_parts) > 0 else ""
city\_raw = addr\_parts\[1] if len(addr\_parts) > 1 else ""
prov = prov\_raw.replace("省", "").replace("自治区", "").replace("市", "")
if "内蒙古" in prov: prov = "内蒙古"
elif "广西" in prov: prov = "广西"
elif "西藏" in prov: prov = "西藏"
elif "新疆" in prov: prov = "新疆"
elif "宁夏" in prov: prov = "宁夏"
# 🚨 直辖市全切断防重复前缀拦截
if prov in \["北京", "上海", "天津", "重庆"]:
geo\_prefix = prov
else:
city = city\_raw
# 🚨 完美修复:调整执行顺序,必须先判定长词“地区”,再判定单字“市县区盟”!
if city.endswith('地区'):
city = city\[:-2]
elif city.endswith(('市', '县', '区', '盟')):
city = city\[:-1]
city = re.sub(r'(哈尼族|土家族|苗族|彝族|藏族|回族|白族|傣族|景泼族|壮族|侗族|布依族|满族|蒙古族|哈萨克族|柯尔克孜族|羌族|各族|自治州|自治县)+', '', city)
if city.endswith('州') and len(city) > 2: city = city\[:-1]
geo\_prefix = f"{prov}{city}" if city else prov
region = ""
for reg, keywords in region\_rules.items():
if any(k in prov for k in keywords): region = reg; break
if remark == "京东":
person\_name = vlookup\_dict.get(order\_id, "")
customer = f"{geo\_prefix}{person\_name}"
else:
customer = f"{geo\_prefix}{order\_id}"
# 品种逻辑判定
if any(x in combo for x in \["盐焗粉", "浓缩鲜香粉", "烧腊香味素", "去腥增香调味油", "凉拌菜调味油"]): breed = "调味品"
elif "I+G" in combo: breed = "I+G"
elif "呋喃酮" in combo: breed = "呋喃酮"
elif "甲基环戊烯醇酮" in combo or "MCP" in combo: breed = "MCP"
elif "甲基" in combo: breed = "甲基"
elif "香兰素" in combo: breed = "香兰素"
else: breed = "乙基"
# 规格逻辑判定
if "30g\*3盐焗粉" in combo: spec = "12KG箱"
elif any(x in combo for x in \["1kg凉拌菜调味油", "1kg去腥增香调味油"]): spec = "1kg/瓶"
elif any(x in combo for x in \["500g凉拌菜调味油", "500g去腥增香调味油"]): spec = "0.5kg/瓶"
elif "250克" in combo: spec = "5KG箱"
elif any(x in combo for x in \["焦桶", "纯桶", "特醇桶", "焦糖桶"]): spec = "10大小"
else:
spec\_box = \["焦","纯","特醇","I+G","香兰素","呋喃酮","甲基","焦箱","纯箱","特醇箱","甲基环戊烯醇酮","香虎粉","焦糖香瓶"]
spec = "箱" if any(x in combo for x in spec\_box) else "箱"
try: unit\_price = float(pay\_amt) / float(qty) if float(qty) != 0 else ""
except: unit\_price = ""
company = "肇庆香料" if remark == "淘宝" else "华宝星湖"
parsed\_rows.append({
'日期': ' ', '省份': prov, '区域': region, '客户': customer, '餐饮配料': '餐饮配料', '直销': '直销',
'品种': breed, '规格': spec, 'combo\_raw': combo, '数量': qty, '含税单价': unit\_price,
'备注': remark, '订单号': order\_id, '所属公司': company
})
res\_df = pd.DataFrame(parsed\_rows)
if res\_df.empty: return
# 倒数第二步:批量剥离香型关键字
removals = \["250克", "箱", "瓶", "桶", "500g", "1kg", "30g\*3"]
def clean\_flavor(text):
for word in removals: text = text.replace(word, "")
return text
res\_df\['香型'] = res\_df\['combo\_raw'].apply(clean\_flavor)
res\_df = res\_df.drop(columns=\['combo\_raw'])
# 店铺与多级置顶排序权重计算
shop\_weight = {'淘宝': 1, '天猫': 2, '京东': 3, '拼多多': 4, '抖音': 5}
res\_df\['shop\_w'] = res\_df\['备注'].map(shop\_weight)
res\_df\['breed\_w'] = res\_df\['品种'].apply(lambda b: 0 if b == '调味品' else (1 if b != '乙基' else 2))
res\_df = res\_df.sort\_values(by=\['shop\_w', 'breed\_w']).reset\_index(drop=True)
res\_df = res\_df.drop(columns=\['shop\_w', 'breed\_w'])
# 生成 Excel 并渲染
wb = Workbook()
ws = wb.active
ws.title = "重构账目表"
headers = \["日期", "省份", "区域", "客户", "餐饮配料", "直销", "品种", "规格", "香型", "数量", "含税单价", "含税金额", "不含税金额", "备注", "订单号", "所属公司"]
ws.append(headers)
fills = {
'天猫': PatternFill(start\_color="FFFF00", end\_color="FFFF00", fill\_type="solid"),
'京东': PatternFill(start\_color="92D050", end\_color="92D050", fill\_type="solid"),
'拼多多': PatternFill(start\_color="00B0F0", end\_color="00B0F0", fill\_type="solid"),
'抖音': PatternFill(start\_color="ED7D31", end\_color="ED7D31", fill\_type="solid")
}
center\_align = Alignment(horizontal="center", vertical="center")
font\_12 = Font(size=12)
font\_11 = Font(size=11)
for col\_idx in range(1, 17):
ws.cell(row=1, column=col\_idx).font = font\_12
ws.cell(row=1, column=col\_idx).alignment = center\_align
for i, r in res\_df.iterrows():
row\_idx = i + 2
row\_data = \[
r\['日期'], r\['省份'], r\['区域'], r\['客户'], r\['餐饮配料'], r\['直销'],
r\['品种'], r\['规格'], r\['香型'], r\['数量'], r\['含税单价'],
f"=J{row\_idx}\*K{row\_idx}", f"=L{row\_idx}/1.13",
r\['备注'], r\['订单号'], r\['所属公司']
]
ws.append(row\_data)
row\_fill = fills.get(r\['备注'], None)
# 🚨 对整行(包含空白列)强制进行颜色填充与字号分级
for col\_idx in range(1, 17):
cell = ws.cell(row=row\_idx, column=col\_idx)
cell.alignment = center\_align
if row\_fill: cell.fill = row\_fill
cell.font = font\_11 if col\_idx in \[5, 6, 12, 13] else font\_12
if col\_idx == 13: cell.number\_format = '0.00'
wb.save(output\_path)
微信扫一扫