EAN-13(European Article Number,現改稱為 International Article Number)是目前全球最廣泛使用的商品條碼標準。它主要用於零售商品的結帳與庫存管理,您在超市看到的大多數商品背後都是這種條碼。
以下是 EAN-13 標準的詳細組成與規範:
1. 條碼結構 (共 13 位數字)
EAN-13 的數字由四個部分組成,每個部分都有特定意義:
前綴碼 (GS1 Prefix): 前 2 到 3 位數字。代表商品註冊的國家或地區(例如:471 為台灣,690-699 為中國,45-49 為日本)。
廠商代碼 (Manufacturer Code): 緊接在後的 5 到 7 位數字。由各國的 GS1 機構核發給申請企業。
商品項目代碼 (Product Item Code): 由廠商自行編號,代表特定的商品(例如:不同口味、不同容量的飲料會有不同的編號)。
檢查碼 (Check Digit): 最後 1 位數字。用於掃描時驗證前 12 位數字是否讀取正確。
2. 檢查碼的計算公式 (加權模數 10)
EAN-13 使用一套數學公式來確保條碼的正確性,步驟如下:
從右向左,將第 2、4、6、8、10、12 位(偶數位)的數字相加,結果乘以 3。
將其餘第 3, 5, 7, 9, 11 位(奇數位)的數字相加,再加上第 1 位。
將上述兩個結果相加。
取這個總和的個位數,用 10 減去該個位數,所得的結果即為檢查碼(若結果為 10,則檢查碼為 0)。
3. 編碼邏輯 (二進位圖形)
EAN-13 不僅僅是數字,其黑白線條的寬度也有嚴格定義:
起始碼/結束碼 (Guard Bars): 條碼左右兩側較長的兩條細線(101 模式)。
中間分隔碼 (Center Guard Bar): 位於中間較長的兩條細線(01010 模式),將條碼分為左、右兩半。
左側與右側編碼: 條碼的左半部與右半部使用了不同的二進位模式(左側採用 A 或 B 組,右側固定採用 C 組),這讓掃描器可以辨識條碼是正著掃還是倒著掃。
4. 物理尺寸規範
為了確保掃描器能穩定讀取,EAN-13 有其標準尺寸(稱為 100% 放大率):
標準寬度: 37.29 mm
標準高度: 25.93 mm
靜區 (Quiet Zone): 條碼左右兩側必須留出足夠的空白(左側 3.63mm,右側 2.31mm),否則掃描器會無法辨識邊界。
總結
EAN-13 的核心價值在於其唯一性,確保全世界任何一件零售商品在系統中都不會發生衝突。
import tkinter as tk
from tkinter import Label, Button
import barcode
from barcode.writer import ImageWriter
from PIL import Image, ImageTk
import random
import io
class BarcodeGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("EAN-13 條碼自動產生器")
self.root.geometry("400x480")
self.root.resizable(False, False)
# 標題
self.title_label = Label(self.root, text="EAN-13 Barcode Generator", font=("Arial", 16, "bold"))
self.title_label.pack(pady=15)
# 顯示條碼圖片的區域
self.label_image = Label(self.root, bg="white", relief="sunken")
self.label_image.pack(pady=10, padx=20, fill="both", expand=True)
# 顯示條碼數字的標籤
self.label_text = Label(self.root, text="按下按鈕產生條碼", font=("Consolas", 14), fg="blue")
self.label_text.pack(pady=10)
# 操作按鈕
self.btn_generate = Button(
self.root,
text="產生隨機新條碼",
command=self.generate_ean,
font=("Microsoft JhengHei", 12),
bg="#4CAF50",
fg="white",
padx=20,
pady=10
)
self.btn_generate.pack(pady=20)
# 程式啟動時先產生一個
self.generate_ean()
def generate_ean(self):
try:
# 1. 隨機產生 12 位數字 (EAN-13 的前 12 位)
# 例如:471 代表台灣
prefix = "471"
rest = "".join([str(random.randint(0, 9)) for _ in range(9)])
data_string = prefix + rest
# 2. 使用 python-barcode 產生 EAN-13 物件
# ImageWriter 會處理繪製邏輯
ean = barcode.get('ean13', data_string, writer=ImageWriter())
# 3. 將條碼渲染到記憶體緩衝區 (BytesIO)
buffer = io.BytesIO()
ean.write(buffer)
buffer.seek(0)
# 4. 使用 PIL 開啟圖片並縮放到適合視窗的大小
pil_image = Image.open(buffer)
# 原始條碼通常較大,這裡縮放為寬 320 像素
w, h = pil_image.size
new_h = int(h * (320 / w))
pil_image = pil_image.resize((320, new_h), Image.Resampling.LANCZOS)
# 轉為 Tkinter 用的 PhotoImage
tk_image = ImageTk.PhotoImage(pil_image)
# 5. 更新 UI 內容
self.label_image.config(image=tk_image)
self.label_image.image = tk_image # 重要:保留引用防止圖片被回收
full_code = ean.get_fullcode()
self.label_text.config(text=f"條碼內容: {full_code}")
except Exception as e:
self.label_text.config(text=f"發生錯誤: {e}", fg="red")
if __name__ == "__main__":
root = tk.Tk()
app = BarcodeGeneratorApp(root)
root.mainloop()
在 EAN-13 標準中,台灣的國家代碼(Country Code)是 471。
我已經將程式碼進行了微調,確保每次生成的隨機條碼都以 471 開頭。同時,我也加入了一個**「儲存圖片」**的按鈕,方便您將產生的條碼存成實體檔案(如用於列印或測試)。
修正後的完整程式碼
import tkinter as tk
from tkinter import Label, Button, messagebox, filedialog
import barcode
from barcode.writer import ImageWriter
from PIL import Image, ImageTk
import random
import io
class BarcodeGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("EAN-13 台灣條碼產生器 (471)")
self.root.geometry("450x550")
self.root.resizable(False, False)
# 標題
self.title_label = Label(self.root, text="台灣 EAN-13 條碼產生器", font=("Arial", 16, "bold"))
self.title_label.pack(pady=15)
# 說明文字
self.info_label = Label(self.root, text="國家代碼已固定為: 471 (台灣)", fg="gray")
self.info_label.pack()
# 顯示條碼圖片的區域
self.label_image = Label(self.root, bg="white", relief="sunken", bd=2)
self.label_image.pack(pady=10, padx=20, fill="both", expand=True)
# 顯示條碼數字的標籤
self.label_text = Label(self.root, text="", font=("Consolas", 16, "bold"), fg="blue")
self.label_text.pack(pady=10)
# 按鈕容器
self.btn_frame = tk.Frame(self.root)
self.btn_frame.pack(pady=20)
# 產生按鈕
self.btn_generate = Button(
self.btn_frame, text="產生新條碼", command=self.generate_ean,
font=("Microsoft JhengHei", 10), bg="#4CAF50", fg="white", width=12
)
self.btn_generate.grid(row=0, column=0, padx=10)
# 儲存按鈕
self.btn_save = Button(
self.btn_frame, text="儲存條碼圖片", command=self.save_barcode,
font=("Microsoft JhengHei", 10), bg="#2196F3", fg="white", width=12
)
self.btn_save.grid(row=0, column=1, padx=10)
self.current_ean_img = None
self.current_code = ""
# 啟動時先產生一個
self.generate_ean()
def generate_ean(self):
try:
# 1. 固定台灣代碼 471,後面隨機產生 9 位數 (總共 12 位)
prefix = "471"
random_part = "".join([str(random.randint(0, 9)) for _ in range(9)])
data_string = prefix + random_part
# 2. 產生條碼 (自動計算第 13 位檢查碼)
ean = barcode.get('ean13', data_string, writer=ImageWriter())
# 3. 渲染到記憶體
buffer = io.BytesIO()
ean.write(buffer)
buffer.seek(0)
# 4. 處理顯示用的圖片 (縮放)
full_pil_img = Image.open(buffer)
self.current_ean_img = full_pil_img # 保存原始圖供儲存使用
# 縮放預覽圖
display_img = full_pil_img.copy()
w, h = display_img.size
new_w = 350
new_h = int(h * (new_w / w))
display_img = display_img.resize((new_w, new_h), Image.Resampling.LANCZOS)
tk_image = ImageTk.PhotoImage(display_img)
self.label_image.config(image=tk_image)
self.label_image.image = tk_image
self.current_code = ean.get_fullcode()
self.label_text.config(text=self.current_code)
except Exception as e:
messagebox.showerror("錯誤", f"產生條碼失敗: {e}")
def save_barcode(self):
if self.current_ean_img:
file_path = filedialog.asksaveasfilename(
defaultextension=".png",
filetypes=[("PNG files", "*.png")],
initialfile=f"barcode_{self.current_code}.png"
)
if file_path:
self.current_ean_img.save(file_path)
messagebox.showinfo("成功", "條碼已成功儲存!")
if __name__ == "__main__":
root = tk.Tk()
app = BarcodeGeneratorApp(root)
root.mainloop()
EAN-13 結構解析 (以台灣為例)
國家代碼 (Prefix): 前三位
471代表此條碼由台灣的 GS1 組織發放。廠商代碼: 接下來的 4 到 6 位數。
商品項目代碼: 由廠商自行定義的剩餘位數。
檢查碼 (Check Digit): 最後一位,程式會根據前 12 位透過公式
import tkinter as tk
from tkinter import Label, Button, messagebox, filedialog
import barcode
from barcode.writer import ImageWriter
from PIL import Image, ImageTk
import random
import io
class BarcodeGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("EAN-13 台灣條碼產生器 (471)")
self.root.geometry("450x550")
self.root.resizable(False, False)
# 標題
self.title_label = Label(self.root, text="台灣 EAN-13 條碼產生器", font=("Arial", 16, "bold"))
self.title_label.pack(pady=15)
# 說明文字
self.info_label = Label(self.root, text="國家代碼已固定為: 471 (台灣)", fg="gray")
self.info_label.pack()
# 顯示條碼圖片的區域
self.label_image = Label(self.root, bg="white", relief="sunken", bd=2)
self.label_image.pack(pady=10, padx=20, fill="both", expand=True)
# 顯示條碼數字的標籤
self.label_text = Label(self.root, text="", font=("Consolas", 16, "bold"), fg="blue")
self.label_text.pack(pady=10)
# 按鈕容器
self.btn_frame = tk.Frame(self.root)
self.btn_frame.pack(pady=20)
# 產生按鈕
self.btn_generate = Button(
self.btn_frame, text="產生新條碼", command=self.generate_ean,
font=("Microsoft JhengHei", 10), bg="#4CAF50", fg="white", width=12
)
self.btn_generate.grid(row=0, column=0, padx=10)
# 儲存按鈕
self.btn_save = Button(
self.btn_frame, text="儲存條碼圖片", command=self.save_barcode,
font=("Microsoft JhengHei", 10), bg="#2196F3", fg="white", width=12
)
self.btn_save.grid(row=0, column=1, padx=10)
self.current_ean_img = None
self.current_code = ""
# 啟動時先產生一個
self.generate_ean()
def generate_ean(self):
try:
# 1. 固定台灣代碼 471,後面隨機產生 9 位數 (總共 12 位)
prefix = "471"
random_part = "".join([str(random.randint(0, 9)) for _ in range(9)])
data_string = prefix + random_part
# 2. 產生條碼 (自動計算第 13 位檢查碼)
ean = barcode.get('ean13', data_string, writer=ImageWriter())
# 3. 渲染到記憶體
buffer = io.BytesIO()
ean.write(buffer)
buffer.seek(0)
# 4. 處理顯示用的圖片 (縮放)
full_pil_img = Image.open(buffer)
self.current_ean_img = full_pil_img # 保存原始圖供儲存使用
# 縮放預覽圖
display_img = full_pil_img.copy()
w, h = display_img.size
new_w = 350
new_h = int(h * (new_w / w))
display_img = display_img.resize((new_w, new_h), Image.Resampling.LANCZOS)
tk_image = ImageTk.PhotoImage(display_img)
self.label_image.config(image=tk_image)
self.label_image.image = tk_image
self.current_code = ean.get_fullcode()
self.label_text.config(text=self.current_code)
except Exception as e:
messagebox.showerror("錯誤", f"產生條碼失敗: {e}")
def save_barcode(self):
if self.current_ean_img:
file_path = filedialog.asksaveasfilename(
defaultextension=".png",
filetypes=[("PNG files", "*.png")],
initialfile=f"barcode_{self.current_code}.png"
)
if file_path:
self.current_ean_img.save(file_path)
messagebox.showinfo("成功", "條碼已成功儲存!")
if __name__ == "__main__":
root = tk.Tk()
app = BarcodeGeneratorApp(root)
root.mainloop()
在台灣,所有的 EAN-13 條碼(國家代碼為 471)都是由 GS1 Taiwan(財團法人編碼策進會) 統一核發與管理的。
廠商代碼的長度通常為 5 到 7 位數,這取決於該廠商申請時預估的產品種類數量。以下是台灣一些知名品牌的廠商代碼範例,您可以在之前的程式中輸入這些數字進行測試:
1. 台灣常見知名廠商代碼範例
| 品牌名稱 | 國家代碼 | 廠商代碼 (可輸入至程式) | 商品類別範例 |
| 統一企業 | 471 | 0088 (或 0010) | 泡麵、飲料、麵包 |
| 黑松 | 471 | 0123 | 沙士、碳酸飲料 |
| 義美食品 | 471 | 0120 | 餅乾、牛奶、冰棒 |
| 光泉牧場 | 471 | 0131 | 鮮乳、豆漿 |
| 味全食品 | 471 | 0150 | 調味乳、罐頭 |
| 維他露 | 471 | 0430 | 舒跑、御茶園 |
| 金車 | 471 | 0105 | 伯朗咖啡、波爾天然水 |
| 旺旺 | 471 | 0203 | 仙貝、雪餅 |
2. 廠商代碼的長度邏輯
GS1 根據廠商的需求,會分配不同長度的代碼:
7 位廠商代碼:最常見,適合一般中小企業,剩下的位數可編 5 位數商品(00000-99999)。
5 或 6 位廠商代碼:核發給產品品項極多的超大型企業(如統一、義美),讓他們有更多位數可以編排成千上萬種不同的單品。
3. 如何查詢特定的台灣廠商代碼?
如果您手邊有一個商品,想知道它的廠商是誰,或者想確認某個廠商的正式代碼,可以使用以下官方工具:
GS1 Taiwan 官網查詢:前往
。GS1 Taiwan 條碼資訊查詢服務 手機 APP:下載「標竿條碼掃描」App,掃描後會直接顯示該 471 條碼所屬的台灣公司名稱。
如何在您的程式中使用?
在您執行之前的程式時,直接在「廠商代碼」輸入框中輸入上述表格內的 「廠商代碼」欄位數字(例如輸入 0123),程式就會自動生成一個:
471 (台灣) + 0123 (黑松) + XXXXX (隨機商品碼) + X (自動計算檢查碼) 的合法條碼。
import tkinter as tk
from tkinter import Label, Button, Entry, messagebox, filedialog
import barcode
from barcode.writer import ImageWriter
from PIL import Image, ImageTk
import random
import io
class BarcodeGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("EAN-13 台灣條碼自定義產生器")
self.root.geometry("450x620")
self.root.resizable(False, False)
# 標題
Label(self.root, text="台灣 EAN-13 條碼工具", font=("Arial", 16, "bold")).pack(pady=10)
# 輸入區域容器
input_frame = tk.LabelFrame(self.root, text=" 設定廠商資訊 ", padx=10, pady=10)
input_frame.pack(pady=10, padx=20, fill="x")
# 固定國碼顯示
Label(input_frame, text="國家代碼: 471 (台灣)").grid(row=0, column=0, sticky="w", pady=5)
# 廠商代碼輸入
Label(input_frame, text="手動輸入廠商代碼 (5-7位):").grid(row=1, column=0, sticky="w")
self.entry_mfg = Entry(input_frame, font=("Arial", 12))
self.entry_mfg.insert(0, "123456") # 預設值
self.entry_mfg.grid(row=1, column=1, padx=5, pady=5)
# 提示文字
self.hint_label = Label(self.root, text="註:商品代碼與檢查碼將由系統自動計算", fg="gray", font=("Arial", 9))
self.hint_label.pack()
# 顯示條碼圖片的區域
self.label_image = Label(self.root, bg="white", relief="sunken", bd=2)
self.label_image.pack(pady=10, padx=20, fill="both", expand=True)
# 顯示完整條碼數字
self.label_text = Label(self.root, text="", font=("Consolas", 18, "bold"), fg="blue")
self.label_text.pack(pady=10)
# 按鈕容器
btn_frame = tk.Frame(self.root)
btn_frame.pack(pady=15)
Button(btn_frame, text="產生條碼", command=self.generate_ean,
font=("Microsoft JhengHei", 10), bg="#4CAF50", fg="white", width=12).grid(row=0, column=0, padx=10)
Button(btn_frame, text="儲存圖片", command=self.save_barcode,
font=("Microsoft JhengHei", 10), bg="#2196F3", fg="white", width=12).grid(row=0, column=1, padx=10)
self.current_ean_img = None
self.current_code = ""
# 初始產生一個
self.generate_ean()
def generate_ean(self):
mfg_code = self.entry_mfg.get().strip()
# 驗證輸入內容是否為數字
if not mfg_code.isdigit():
messagebox.showwarning("輸入錯誤", "廠商代碼必須全部為數字!")
return
# 驗證長度 (471 + 廠商代碼 + 商品代碼 = 12位)
# 通常廠商代碼為 5-7 位
if not (5 <= len(mfg_code) <= 7):
messagebox.showwarning("長度錯誤", "廠商代碼建議為 5 到 7 位數!")
return
try:
# 1. 組合:國碼(471) + 廠商代碼
prefix = "471"
base_string = prefix + mfg_code
# 2. 自動補齊剩餘位數至 12 位
remaining_len = 12 - len(base_string)
product_part = "".join([str(random.randint(0, 9)) for _ in range(remaining_len)])
final_12_digits = base_string + product_part
# 3. 產生條碼 (自動計算第 13 位檢查碼)
ean = barcode.get('ean13', final_12_digits, writer=ImageWriter())
# 4. 渲染圖片
buffer = io.BytesIO()
ean.write(buffer)
buffer.seek(0)
full_pil_img = Image.open(buffer)
self.current_ean_img = full_pil_img
# 縮放預覽圖
w, h = full_pil_img.size
display_img = full_pil_img.resize((350, int(h * (350 / w))), Image.Resampling.LANCZOS)
tk_img = ImageTk.PhotoImage(display_img)
self.label_image.config(image=tk_img)
self.label_image.image = tk_img
self.current_code = ean.get_fullcode()
self.label_text.config(text=self.current_code)
except Exception as e:
messagebox.showerror("錯誤", f"無法產生條碼: {e}")
def save_barcode(self):
if self.current_ean_img:
file_path = filedialog.asksaveasfilename(
defaultextension=".png",
filetypes=[("PNG files", "*.png")],
initialfile=f"EAN13_{self.current_code}.png"
)
if file_path:
self.current_ean_img.save(file_path)
messagebox.showinfo("成功", f"條碼 {self.current_code} 已儲存")
if __name__ == "__main__":
root = tk.Tk()
app = BarcodeGeneratorApp(root)
root.mainloop()
功能說明:
廠商速查下拉選單 (Combobox):
預設內建了幾家台灣龍頭企業的代碼。
選擇「統一企業」後,代碼輸入框會自動填入
0088。若選「自定義輸入」,則可自行手動填寫。
批量處理機制:
在「產生數量」輸入想要產生的個數(例如 10)。
點擊「批量產生」後,程式會瞬間跑完隨機生成、檢查碼計算。
中間的列表(Treeview)會列出所有產生的 13 位完整碼。
即時互動預覽:
滑鼠點擊列表中的任何一組數字,右側視窗會即時顯示該條碼的圖形。
一鍵批次儲存:
點擊「全部儲存」,選擇一個資料夾,程式會自動將清單中所有的條碼存成
EAN13_471xxxx.png。






沒有留言:
張貼留言