
本文介绍如何通过python结合串口通信与excel操作,实现电子秤实时数据的“点击触发式”记录——即仅在用户点击excel指定单元格时,才将当前称重值写入表格,避免持续写入干扰。
本文介绍如何通过python结合串口通信与excel操作,实现电子秤实时数据的“点击触发式”记录——即仅在用户点击excel指定单元格时,才将当前称重值写入表格,避免持续写入干扰。
要实现“点击Excel单元格才记录当前重量”的需求,关键在于解耦数据采集与数据写入:电子秤数据需持续读取并缓存,而Excel写入动作必须由用户交互(如点击)主动触发。原示例脚本采用轮询+自动写入方式,不符合“按需触发”要求。下面提供一个完整、可靠且可落地的解决方案。
✅ 核心设计思路
- 后台守护线程:持续监听串口,实时解析并缓存最新重量值(线程安全);
- Excel交互层:使用 openpyxl 无法响应鼠标点击,因此需借助 Excel COM 自动化(Windows) 或 外部轻量级GUI触发器(跨平台推荐);
- 推荐方案(跨平台 & 简洁可靠):用 Python 构建一个极简 Tkinter 按钮界面,点击即写入当前最新重量到 Excel —— 既满足“手动触发”语义,又规避了Excel自身宏/COM的复杂性和兼容性问题。
? 完整可运行代码(含串口监听 + 点击写入)
import serial
import openpyxl
import threading
import time
from tkinter import Tk, Button, Label, messagebox
from queue import Queue
# === 配置区(请按实际修改)===
SERIAL_PORT = 'COM3' # Windows 示例;macOS/Linux 为 '/dev/tty.usbserial-' 或 '/dev/ttyUSB0'
BAUD_RATE = 9600
EXCEL_FILE = 'weigh_data.xlsx'
# === 全局状态管理 ===
latest_weight = "N/A"
weight_lock = threading.Lock()
data_queue = Queue(maxsize=1) # 仅保留最新一条有效数据
# === 串口监听线程 ===
def read_scale():
global latest_weight
try:
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
print(f"✅ 已连接电子秤:{SERIAL_PORT} @ {BAUD_RATE}bps")
while True:
if ser.in_waiting > 0:
raw = ser.readline().strip()
try:
weight_str = raw.decode('utf-8')
# 简单校验:仅接受数字或带单位的数字(如 "12.34 kg" → 提取 12.34)
import re
match = re.search(r'[-+]?\d*\.?\d+', weight_str)
if match:
with weight_lock:
latest_weight = float(match.group())
# 仅保留最新值,丢弃旧值
if not data_queue.empty():
try:
data_queue.get_nowait()
except:
pass
data_queue.put(latest_weight)
except (UnicodeDecodeError, ValueError):
pass
time.sleep(0.2) # 减少CPU占用
except Exception as e:
print(f"❌ 串口错误:{e}")
messagebox.showerror("串口异常", f"无法连接电子秤:{e}")
# === 写入Excel函数(线程安全)===
def write_to_excel(weight_val):
try:
try:
wb = openpyxl.load_workbook(EXCEL_FILE)
except FileNotFoundError:
wb = openpyxl.Workbook()
wb.active.title = "WeighLog"
ws = wb.active
next_row = ws.max_row + 1
ws[f'A{next_row}'] = weight_val
ws[f'B{next_row}'] = time.strftime("%Y-%m-%d %H:%M:%S")
wb.save(EXCEL_FILE)
return True
except Exception as e:
messagebox.showerror("Excel错误", f"写入失败:{e}")
return False
# === GUI主界面 ===
def on_click_log():
with weight_lock:
w = latest_weight
if isinstance(w, (int, float)):
if write_to_excel(w):
label_status.config(text=f"✅ 已记录:{w:.3f} kg | {time.strftime('%H:%M:%S')}", fg="green")
else:
label_status.config(text="❌ 写入失败,请检查Excel是否被其他程序占用", fg="red")
else:
label_status.config(text="⚠️ 无有效重量数据,请检查秤连接与输出格式", fg="orange")
root = Tk()
root.title("电子秤数据记录器")
root.geometry("400x180")
root.resizable(False, False)
Label(root, text="实时电子秤数据记录系统", font=("Arial", 14, "bold")).pack(pady=10)
Button(root, text="? 点击记录当前重量", font=("Arial", 12), command=on_click_log, bg="#4CAF50", fg="white", width=25).pack(pady=10)
label_status = Label(root, text="等待连接...", font=("Arial", 10))
label_status.pack(pady=5)
# 启动串口监听线程
threading.Thread(target=read_scale, daemon=True).start()
print("?️ GUI已启动 —— 点击按钮即可记录当前重量")
root.mainloop()⚠️ 使用前注意事项
- 串口配置:务必确认电子秤的通信协议(通常为 RS232/USB转串口),使用设备管理器(Windows)或 ls /dev/tty*(macOS/Linux)确认端口号;常见波特率有 9600、19200、38400。
- 数据格式适配:不同秤输出格式不同(如 "12.34"、"W:12.34kg"、"STABLE 12.34")。代码中已内置正则提取,如不匹配,请调整 re.search(...) 模式。
- Excel占用问题:openpyxl 不能编辑已打开的 .xlsx 文件。请确保 Excel 程序关闭后再运行脚本,或改用 .csv(更轻量,支持实时追加)。
-
权限与依赖:
pip install pyserial openpyxl
- 进阶建议:如需真正嵌入Excel(如自定义右键菜单或单元格双击事件),需使用 VBA + Application.OnKey 或 Python win32com(仅限Windows),但开发复杂度与维护成本显著上升,不推荐初学者采用。
该方案兼顾稳定性、可读性与实用性,一次部署即可长期使用,是工业场景下轻量数据采集的理想实践。


















