XScript 手册 · Chapter 51

SN 对象 — 序列号规则管理

脚本中以关键字 SN 访问。用于标签打印、MES 上报、可追溯性等场景的 固定区(Lot/Line)+ 可变区(序列) 序列号规则。可按规则名注册、生成、管理多套规则。

概念说明
规则(rule)以名称标识。同一项目可同时运行多套
格式[固定宽度:类型:对齐]&[字段::长度]|[可变区] 形式 — 例:`[12:0:Left]&[Lot::6]
上下文4 个键:LotNo · LineNo · WorkOrderNo · SubLot
排除字符默认 "1,0,D,I,O"(视觉易混字符)

一行总结SN.RegisterRule(...) 注册 → SN.SetContext(...) 填 Lot → SN.GenerateNext(...) 生成下一个。


1) 注册 / 更新规则

通过名称 + 完整格式字符串一行完成。

// 直接传完整格式
SN.RegisterRule("prodA", "[12:0:Left]&[Lot::6]|[SN:SequencialDecimal:0:6]");
 
// 验证是否注册成功
if( SN.GetRule("prodA") == null )
{
    LogError("rule register failed");
    return false;
}

如果存在同名规则,会覆盖 — 已有的序列计数器不会保留,会被重新初始化。


2) 填上下文

生成时合并到序列号中的外部值。

SN.SetContext("prodA", "LotNo",       "LOT2026");
SN.SetContext("prodA", "LineNo",      "L1");
SN.SetContext("prodA", "WorkOrderNo", "WO001");
SN.SetContext("prodA", "SubLot",      "S01");

有效键:"LotNo""SubLot""LineNo""WorkOrderNo"(其他键返回 false)。


3) 发放下一个序列号

string sn = SN.GenerateNext("prodA");
if( sn == "" )
{
    LogError("generate next failed");
    return false;
}
Log($"new SN : {sn}");
// 例: "12LOT2026000001"

GenerateNext 调用会 将序列计数器加 1 并返回新值。

不增加计数仅查看

string current = SN.Peek("prodA");   // 上一次发放的可变区值

计数器初始化

SN.ResetSequence("prodA");           // 规则定义保留,可变区重置

4) 预览 / 批量生成

Preview — 不改变状态

// 用于标签设计 / 检查画面的样本 5 个(实际计数器不会增加)
string[] samples = SN.Preview("prodA", 5);

GenerateBatch — 计数器增加 + 批量

// 一次性给打印机发 100 张
string[] batch;
if( SN.GenerateBatch("prodA", 100, batch) == false )
{
    LogError("batch failed");
    return false;
}
for(i, 0, batch.Length - 1)
{
    PRINTER.PrintLabel(batch[i]);
}

5) 排除字符(ExcludedChars)

可变区中不使用的字符,以逗号分隔。

// 默认值(未设置时):"1,0,D,I,O"
string current = SN.GetExcludedChars("prodA");
Log($"excluded : {current}");
 
// 修改
SN.SetExcludedChars("prodA", "1,0,O");
 
// 无排除
SN.SetExcludedChars("prodA", "");

排除与 0/1 易混的 I/O 等字符,可大幅降低打印 / OCR 误识别率。


6) 删除 / 列表

// 已注册的规则名数组
string[] names = SN.GetRuleNames();
for(i, 0, names.Length - 1) Log(names[i]);
 
// 单个删除
SN.RemoveRule("prodA");

7) 持久化 — 文件 · 项目保存 / 读取

规则定义以 JSON 序列化。可变区计数器不在持久化范围 — 仅在运行时保存于内存。

// 文件
SN.SaveToFile("D:/Backup/rules.json");
SN.LoadFromFile("D:/Backup/rules.json");
 
// 项目目录默认路径(SerialRules.XDF)
SN.SaveToProject();
SN.LoadFromProject();

LoadFromXxx 调用前会清空管理器再载入。如需保留同名规则,请提前导出。


常用模式

批次开始时 — 设置 Lot 后发放第一个序列号

FUNCTION OnLotStart(string lotNo, string subLot)
{
    SN.SetContext("prodA", "LotNo",  lotNo);
    SN.SetContext("prodA", "SubLot", subLot);
    SN.ResetSequence("prodA");      // 新 Lot 重新计数
 
    string firstSn = SN.GenerateNext("prodA");
    Data::CurrentSN = firstSn;
    return true;
}

新项目首次启动自动注册

FUNCTION OnInit()
{
    if( SN.LoadFromProject() == false )
    {
        // 文件还不存在 — 用代码注册默认规则并保存
        SN.RegisterRule("prodA", "[12:0:Left]&[Lot::6]|[SN:SequencialDecimal:0:6]");
        SN.SetExcludedChars("prodA", "1,0,D,I,O");
        SN.SaveToProject();
    }
    return true;
}

预览 → 用户确认 → 实发

string[] sample = SN.Preview("prodA", 3);
string msg = $"Sample: {sample[0]} / {sample[1]} / {sample[2]}\nProceed?";
if( ShowMessage(EB_YesNo, 0, msg) == ER_Yes )
{
    string real = SN.GenerateNext("prodA");
    // ... print or report
}

函数一览

分类函数
注册 / 查询RegisterRule(name, fullFormat) · GetRule(name) · GetRuleNames() · RemoveRule(name)
上下文SetContext(name, key, value)(LotNo/SubLot/LineNo/WorkOrderNo)
排除字符SetExcludedChars(name, chars) · GetExcludedChars(name)
发放GenerateNext(name) · Peek(name) · ResetSequence(name) · Preview(name, count) · GenerateBatch(name, count, ref array)
持久化SaveToFile(path) · LoadFromFile(path) · SaveToProject() · LoadFromProject()