這裡的範例是用匯出的excel檔進行轉換動作
import pandas as pd
import json
import numpy as np
import re
import os
import tkinter as tk
from tkinter import filedialog
# **開啟 UI 讓使用者選擇 xls 檔案**
root = tk.Tk()
root.withdraw() # 隱藏主視窗
xls_file_path = filedialog.askopenfilename(title="選擇 XLS 檔案", filetypes=[("Excel 檔案", "*.xls;*.xlsx")])
if not xls_file_path:
print("❌ 未選擇檔案,程式結束")
exit()
# **取得檔案名稱與路徑**
file_dir, file_name = os.path.split(xls_file_path)
file_base_name, _ = os.path.splitext(file_name)
# **設定輸出檔案名稱**
json_output_path = os.path.join(file_dir, f"{file_base_name}.json")
excel_output_path = os.path.join(file_dir, f"{file_base_name}_output.xlsx")
# **讀取 XLS**
df = pd.read_excel(xls_file_path, dtype=str) # 讀取時強制為字串
# **讀取 plist.json(同目錄)**
plist_json_path = os.path.join(file_dir, "plist.json")
if os.path.exists(plist_json_path):
with open(plist_json_path, "r", encoding="utf-8") as f:
plist_data = json.load(f)
product_price_map = {str(item["產品編號"]): str(item.get("建議售價", "0")) for item in plist_data}
else:
print("⚠️ 找不到 plist.json,跳過商品價格填補")
product_price_map = {}
# **清理異常字元**
def clean_text(value):
if isinstance(value, str):
value = value.strip()
value = re.sub(r"[\x00-\x1F\x7F-\x9F]", "", value)
value = value.replace("\n", " ").replace("\r", " ")
value = value.replace('"', "'")
return str(value) # 確保返回字串
df = df.map(lambda x: clean_text(str(x)) if pd.notna(x) else "")
# **補充「商品結帳價」**
for index, row in df.iterrows():
if row["商品結帳價"] == "":
product_id = row["商品貨號"]
if product_id in product_price_map:
df.at[index, "商品結帳價"] = product_price_map[product_id]
# **建立 JSON**
order_dict = {}
for _, row in df.iterrows():
order_id = row["訂單號碼"]
# **如果該訂單號碼不存在,先存入第一列的所有欄位**
if order_id not in order_dict:
order_dict[order_id] = {
"order_info": row.to_dict(),
"products": [],
"order_total": 0
}
# **移除商品貨號為空的商品**
product_id = row["商品貨號"]
if product_id == "":
continue
quantity = int(row["數量"]) if row["數量"].isdigit() else 1
price = float(row["商品結帳價"]) if row["商品結帳價"].replace('.', '', 1).isdigit() else 0
total_price = price * quantity
product_info = {
"商品貨號": product_id,
"商品結帳價": str(price),
"商品名稱": row["商品名稱"] if row["商品名稱"] else row["選項"],
"數量": str(quantity)
}
order_dict[order_id]["products"].append(product_info)
order_dict[order_id]["order_total"] += total_price
# **加入 "折扣" 產品**
for order_id, data in order_dict.items():
payment_total = float(data["order_info"].get("付款總金額", "0") or "0")
discount_value = payment_total - data["order_total"]
discount_product = {
"商品貨號": "P00-000-00",
"商品結帳價": str(discount_value),
"商品名稱": "折扣",
"數量": "1"
}
data["products"].append(discount_product)
# **移除 order_total 欄位**
for order_id in order_dict:
del order_dict[order_id]["order_total"]
# **儲存 JSON**
with open(json_output_path, "w", encoding="utf-8") as f:
json.dump(order_dict, f, ensure_ascii=False, indent=4)
# **轉換為 Excel**
order_list = []
for order_id, data in order_dict.items():
order_info = data["order_info"]
for product in data["products"]:
combined_data = {**order_info, **product} # 先帶入 order_info,再覆蓋 products 內的欄位
order_list.append(combined_data)
# **轉換成 DataFrame**
order_df = pd.DataFrame(order_list)
# **儲存 Excel**
order_df.to_excel(excel_output_path, index=False)
print(f"✅ JSON 轉換完成,已儲存至 {json_output_path}")
print(f"✅ Excel 轉換完成,已儲存至 {excel_output_path}")
說明一下,P00-000-00是進銷中折扣的商品貨號
plist.json格式 (商品的資料庫)
[
{
"產品編號": "P01-001-01",
"品名規格": "商品1",
"(類別名稱)": "分類1",
"條碼編號": "55122124121",
"建議售價": "1300"
}
]
由於Shopline的組合商品,匯出的欄位會是
商品組合 SKU空值 總金額
商品1 SKU
商品2 SKU
(商品1和2伴隨者一堆空值)
因此我才用Python來解套
這裡的使用邏輯,就是如果商品的SKU沒有值,那麼就使用plist.json去撈金額
撈完商品金額後,在商品那裡會把 SKU空值的項目移掉
最後我會用訂單的總金額去扣除所有商品的售價x數量,生成一個折扣 P00-000-00
執行python後會自動存成json及xlsx兩種格式
大概的發想這是這樣,由於我們是用訂單總金額去扣,所以不用去管點數折扣及運費
更進階一點可以用api寫python去拉,會更省事