# Add to your Claude Code skills
git clone https://github.com/yohoten/PB-devPB-dev is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by yohoten. PowerBuilder 开发辅助 Skill. It has 0 GitHub stars.
PB-dev's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/yohoten/PB-dev" and add it to your Claude Code skills directory (see the Installation section above). PB-dev ships a SKILL.md manifest, so compatible agents can discover and load it automatically.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh PB-dev against similar tools.
No comments yet. Be the first to share your thoughts!
Unlocks once the catalog security scan passes (runs nightly).
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
你是 PowerBuilder 10 (Unicode) / 25 开发专家。你理解 PowerScript 语法、DataWindow 定义格式、ORCA API 工作流、匈牙利命名法、嵌入式 SQL、动态 SQL、游标操作、窗口事件管理,并能操作 SQL Anywhere 数据库。
PBL 库文件 ──(ORCA 导出)──> .sr* 文本源文件 ──(VSCode/编辑器修改)──> .sr* 源文件 ──(ORCA 导入编译)──> PBL 库文件
源文件是 纯文本,可直接创建、编辑、搜索替换、版本控制。
重要编码说明:当前项目使用 PB10 Unicode:
PBORCA_UTF8=1 转为 UTF-8 源文件PBORCA_ANSI_DBCS=3 转为系统 ANSI/GBK(中文 Windows 上的备选)写 PB 代码时遵循以下规范(详见 references/pb-coding-conventions.md):
<范围><类型>_<含义>string gs_orgcode // 全局变量(g_=global, s_=string)
string ls_name // 局部变量(l_=local, s_=string)
integer li_age // 局部变量(l_=local, i_=integer)
decimal ldec_salary // 局部变量(l_=local, dec_=decimal)
long ll_rowcount // 局部变量(l_=local, l_=long)
变量全部用小写,注释标明含义。一个变量一行。声明在脚本最前面完成。
| 对象类型 | 命名规则 | 示例 |
|---|---|---|
| 窗口 | w_<含义> |
w_main, w_report_sheet |
| 数据窗口控件 | dw_<含义> |
dw_notice, dw_user_info |
| 数据窗口对象 | d_<含义> / dddw_<含义> |
d_goods, dddw_sex |
| 全局函数 | gf_<含义> |
gf_getOrgInfo |
| 窗口函数 | wf_<含义> |
wf_getUserInfo |
| 用户对象 | uo_<含义> |
uo_common_settle |
| CommandButton | cb_<含义> |
cb_exit |
| SingleLineEdit | sle_<含义> |
sle_name |
| DropDownListBox | ddlb_<含义> |
ddlb_type |
| DataWindow控件 | dw_<含义> |
dw_user_info |
完整控件缩写表见 references/pb-coding-conventions.md。
+ &sqlca.sqlcode| 扩展名 | 对象类型 | PBORCA_TYPE | 说明 |
|---|---|---|---|
.sra |
Application | 0 | 应用入口对象 |
.srd |
DataWindow | 1 | 数据窗口定义 |
.srf |
Function | 2 | 全局函数 |
.srm |
Menu | 3 | 菜单(PB10 导入限制:经常失败,建议在 PB IDE 中创建) |
.srq |
Query | 4 | 查询对象 |
.srs |
Structure | 5 | 结构体 |
.sru |
UserObject | 6 | 自定义用户对象 |
.srw |
Window | 7 | 窗口及其控件、脚本 |
.srp |
Pipeline | 8 | 数据管道 |
.srj |
Project | 9 | 项目对象 |
$PBExportHeader$w_mywindow.srw
$PBExportComments$我的窗口
forward // 前置声明区
global type w_mywindow from window // 窗口类型定义
int x=200, int y=150, string title="标题" // 窗口属性
end type
type cb_ok from commandbutton within w_mywindow // 控件类型定义
int x=100, int y=200, string text="确定" // 控件属性
end type
type cb_ok from commandbutton within w_mywindow // 控件实例声明(与类型同名)
cb_ok cb_ok
end type
on w_mywindow.create // 窗口事件
// PowerScript code here
end on
event open;
// PowerScript code
end event
type cb_ok from commandbutton within w_mywindow
event clicked;
// PowerScript code
end event
关键规则:
forward 行是 ORCA 导出的头部标记event <事件名>; 开始,end event 结束type <控件名> from ... within <窗口名> 内详细的 PowerScript 语法、控件属性映射、事件名列表见 references/powerscript-syntax.md。
release 10;
datawindow(units=0 processing=1 ...)
header(height=80 color="536870912")
summary(height=0 color="536870912")
footer(height=0 color="536870912")
detail(height=92 color="536870912")
table(
column=(type=char(10) update=yes key=yes name=col1 dbname="table.col1")
column=(type=decimal update=yes name=col2 dbname="table.col2")
retrieve="PBSELECT(...)" update="table_name" ...
)
text(band=header alignment="2" text="标题" x="9" y="8" height="60" width="352" name=col1_t ...)
column(band=detail id=1 alignment="2" x="9" y="8" height="76" width="352" name=col1 ...)
compute(band=detail expression="sum(col1)" name=calc_total ...)
DataWindow 画板、12 种显示样式、5 种数据源、PB SELECT 语法、控件属性、颜色值表等见 references/datawindow-syntax.md。
.srf (Function): 函数签名 + PowerScript 代码体.srm (Menu): 菜单项树形结构 + clicked 事件.sru (UserObject): 类似 Window 但基类是 userobject.srs (Structure): 成员变量列表.sra (Application): 应用属性 + open 事件详细语法见 references/powerscript-syntax.md。
// 单行查询
select max(pzh) into :r_pzh from zw_pz_zb
where zth=:g_zth and nkjqj=:g_nkjqj and ykjqj=:g_ykjqj;
// 变量前加冒号 :, into 子句用于单行查询
// 检查 isnull() 和 sqlca.sqlcode
// 更新
update table set col1=:val1 where id=:id_var;
if sqlca.sqlcode <> 0 then
messagebox('错误', sqlca.sqlerrtext)
rollback;
return
end if
commit;
// 插入行
long r_row = dw_1.insertrow(0) // 0=末尾插入
dw_1.setitem(r_row, 'col1', value)
// 获取数据
string r_val = dw_1.getitemstring(1, 'col1')
decimal r_dec = dw_1.getitemdecimal(1, 'col2')
// 更新
dw_1.accepttext()
if dw_1.update() = 1 then commit; else rollback;
// 行操作
dw_1.rowcount() // 总行数
dw_1.getrow() // 当前行
dw_1.deleterow(row) // 删除行
dw_1.reset() // 清空
dw_1.setfilter("col1 = '" + r_val + "'")
dw_1.filter()
dw_1.setsort("col1 A")
dw_1.sort()
dw_1.scrolltorow(row)
模式 1:无参数 — EXECUTE IMMEDIATE
EXECUTE IMMEDIATE "drop table emp" USING SQLCA;
模式 2:带参数 — PREPARE + EXECUTE
PREPARE SQLSA FROM "DELETE FROM emp WHERE empno=?" ;
EXECUTE SQLSA USING :li_empno ;
模式 3:游标(do while 最常用)
string ls_empno, ls_ename
Declare cur_emp Cursor For
select empno, ename from emp where deptno = :ls_dept;
Open cur_emp;
Fetch cur_emp Into :ls_empno, :ls_ename;
Do While SQLCA.SqlCode = 0
// 处理数据...
Fetch cur_emp Into :ls_empno, :ls_ename;
Loop
Close cur_emp;
完整动态 SQL、存储过程调用、游标模式见 references/pb-advanced-patterns.md。
事件触发顺序: Open → Activate → CloseQuery → Close → Deactivate
open — 初始化(设置事务对象、检索数据、禁用按钮) closequery — 检查未保存修改,通过 Return 0/1 决定是否关闭 resize — 按比例自适应调整所有控件位置大小
// closequery 防止数据丢失
If dw_1.ModifiedCount() <= 0 And dw_1.DeletedCount() <= 0 Then Return 0
Int li_flag = MessageBox("提示", "数据已修改,是否保存?", Question!, YesNoCancel!, 1)
Choose Case li_flag
Case 1: If dw_1.Update() = 1 Then Commit; Return 0
Case 2: Rollback; Return 0
Case 3: Return 1 // 取消关闭
End Choose
详细窗口类型、事件、控件、自适应布局见 references/pb-advanced-patterns.md。
// 字符串
Len(s), Mid(s, start, n), Pos(s1, s2), Trim(s), Upper(s), Lower(s)
Fill('0', n) + string(num) // 左侧补零
// 日期
Today(), Now(), Year(d), Month(d), Day(d)
RelativeDate(d, n), DaysAfter(d1, d2)
String(date_val, 'yyyy-mm-dd')
// 类型检查/转换
IsNull(v), IsNumber(s), IsDate(s)
string(num), integer(s), long(s), dec(s)
// 消息框
MessageBox('标题', '内容', Question!, YesNoCancel!, 2)
完整函数速查表见 references/pb-common-functions.md。
MyApp.pbw ← 工作空间(Workspace),可包含多个 Target
MyApp.pbt ← 应用目标(Target),定义 PBL 列表和应用入口
MyApp.pbl ← 库文件(Library),存放实际对象
public.pbl ← 公共 PBL(全局函数、结构体)
report.pbl ← 按功能拆分的 PBL
File → New → Workspace → 保存 .pbwFile → New → Target → Application → 生成 .pbt + .pblFile → New → PB Object → Window → 设计界面Run → Run 或点击工具栏"奔跑的小人"File → New → Project → Application Wizard.pbr 文件pbvm100.dll, pbdwe100.dll, pbodb100.dll 等详细步骤、.pbw/.pbt 文件格式、PBR 资源、打包清单见 references/pb-project-setup.md。
| 表名 | 说明 | 关键字段 |
|---|---|---|
| jxc_d_goods | 商品字典 | code, name, sort, unit, price |
| jxc_d_operator | 操作员 | oper_code, oper_name |
| jxc_sheet_buy | 采购单 | zth, sheetid, code, amount, price, money, sheetdate |
| jxc_sheet_sale | 销售单 | zth, sheetid, code, amount, price, money, sheetdate |
| jxc_table_amount | 商品库存 | zth, code, amount |
| jxc_report_amount | 月度报表 | zth, code, dat_min, amount_ini/buy/sale/end |
-- 1. 金额 ≠ 数量 × 单价
SELECT * FROM jxc_sheet_buy WHERE money <> amount * price AND zth = '34';
-- 2. 商品编码不存在
SELECT * FROM jxc_sheet_sale WHERE code NOT IN (SELECT code FROM jxc_d_goods);
-- 3. 编码/日期/制单人为空
SELECT * FROM jxc_sheet_sale WHERE TRIM(code) = '' OR code IS NULL;
-- 4. 数量异常(空或≤0)
SELECT * FROM jxc_sheet_sale WHERE amount IS NULL OR amount <= 0;
-- 5. 日期逻辑错误(开始>结束)
SELECT * FROM jxc_report_amount WHERE dat_min > date_max;
-- 6. 库存与实际不符
-- 库存应 = SUM(采购) - SUM(销售)
期末库存 = 期初库存 + 采购总量 - 销售总量
// PB 中使用游标遍历库存差异
declare cur_stock cursor for
select t1.code, t1.采购 - coalesce(t2.销售, 0) as 库存
from (select code, sum(amount) as 采购 from jxc_sheet_buy group by code) t1
left join (select code, sum(amount) as 销售 from jxc_sheet_sale group by code) t2
on t1.code = t2.code;
完整表结构、审计 SQL、库存计算流程、月度报表 SQL 见 references/pb-sql-patterns.md。
从头编写 .srd 文件时,遵循以下模板:
release 10;datawindow(...) 属性块table(...) 数据列和 SQLtext 控件(标签)column 控件当需要跨多个文件做相同修改时(如替换表名、调整列宽、重命名列):
常见批量场景:
dbname="old" → dbname="new"x= y= width= height=retrieve= 段方式一:通过 .srd 文件反推表结构(优先)
table(...) 段包含完整的列定义和 SQL方式二:直接读取 SQL Anywhere .db 文件
references/read-db-files.md工具路径:F:\(8)Desktop\Files\Script_plugin\pb-dev-helper
main.py (64-bit GUI) ──JSON-RPC──> orca_worker.py (32-bit) ──ctypes──> pborc100.dll (PB10 ORCA)
pborc100.dll,PB25 使用 pborc.dll{
"pb_ide_path": "PB IDE 目录(含 pborc100.dll)",
"pb_runtime_path": "PB Runtime 目录",
"pb_version": "10",
"export_encoding": 1,
"export_headers": true,
"export_include_binary": false
}
cd pb-dev-helper && python main.pyF:\(8)Desktop\sr 中的现有源文件将模板项目批量改造为新学号项目(如 ZW → 0457)的完整工作流,详见 references/pb-project-renaming.md。
PB IDE 导出原始 PBL → Python 批量重命名 → 依赖排序 → PB IDE 按序导入
在类型前缀后插入学号:w_zw_cover → w_0457_zw_cover,dw_zw_c_bb_d → dw_0457_zw_c_bb_d。
内部 global type 声明和 dataobject = "..." 引用必须同步更新。
PB 导入 .sr* 必须按依赖序,否则报错:
window 系统类型依赖解析:global type X from Y(继承)+ dataobject = "dw_xxx"(引用)。
pbkiller 常导出冗余文件(内嵌 DW 的 _d/_i 后缀、grid+freeform 双版本)。PB IDE 直接导出更干净。
用 grep -rn "name" sr_new/ 验证冗余文件是否被引用,无引用即可删除。
本项目 pb_tools/ 目录提供了完整工具:
pb_project_renamer.py — 批量重命名+内容替换+依赖分析pb_source_validator.py — 语法检查+自动修复pb_dependency_analyzer.py — 依赖图+导入顺序+DOT可视化pb_rename_gui.py — Tkinter GUI(双击即用)当需要在 PB 中实现以下功能时,优先考虑使用 Pbidea.dll:
项目地址:https://github.com/lxb320124/pbidea
F:\(8)Desktop\share\ZW\)F:\(8)Desktop\srzw.pbw + zw.pbt + zw.pbl(1.9 MB)zw.db(1.9 MB)PBORCA_UTF8=1 从 PBL Unicode 转为 UTF-8 导出)| 前缀 | 含义 | 示例 |
|---|---|---|
zw_ |
账务系统前缀 | 所有表 |
_c_ |
字典/代码表 | zw_c_kmlb(科目类别) |
_d_ |
基础数据表 | zw_d_ztxxb(账套信息) |
_pz_ |
凭证表 | zw_pz_zb(凭证主表), zw_pz_mxb(凭证明细) |
_zb_ |
账簿表 | zw_zb_kmyeb(科目余额表), zw_zb_mxzb(明细账) |
_yb_ |
月报表 | zw_yb_zcfzb(资产负债表), zw_yb_lrb(利润表) |
_zb 后缀 |
主表 | zw_pz_zb |
_mxb 后缀 |
明细表 | zw_pz_mxb |
| 模块 | 表 | 窗口命名前缀 |
|---|---|---|
| 系统管理 | zw_d_ztxxb, zw_d_czy, zw_d_kjkmbmb | w_sys_* |
| 凭证输入 | zw_pz_zb, zw_pz_mxb | w_pz_* |
| 凭证审核 | zw_pz_zb (shbj, shr) | w_pz_sh_* |
| 凭证记账 | zw_pz_zb (jzbj, jzr) | w_pz_jz_* |
| 科目余额 | zw_zb_kmyeb | w_km_ye_* |
| 明细账 | zw_zb_mxzb | w_mxz_* |
| 资产负债表 | zw_yb_zcfzb | w_bb_zcfz_* |
| 利润表 | zw_yb_lrb | w_bb_lr_* |
| 财务指标 | zw_yb_cwzbtjb + zw_c_cwzbmb | w_cwzb_* |
| 杜邦分析 | zw_yb_dbfxb | w_db_* |
string g_zth // 当前账套号(从 zw_d_ztxxb 选择)
string g_nkjqj // 年会计期间(如 "2025")
string g_ykjqj // 月会计期间(如 "01"~"12")
string g_czy // 当前操作员
| 字段 | 含义 | PB 变量命名 |
|---|---|---|
| zth | 账套号 | g_zth |
| nkjqj | 年会计期间 | g_nkjqj |
| ykjqj | 月会计期间 | g_ykjqj |
| pzh | 凭证号 | ls_pzh, r_pzh |
| rq | 日期 | ld_rq |
| fdjs | 附单据数 | li_fdjs |
| zdr | 制单人 | ls_zdr |
| shr | 审核人 | ls_shr |
| shbj | 审核标记 | ls_shbj |
| jzr | 记账人 | ls_jzr |
| jzbj | 记账标记 | ls_jzbj |
| km_code | 科目编码 | ls_km_code |
| zy | 摘要 | ls_zy |
| jfje | 借方金额 | ldec_jfje |
| dfje | 贷方金额 | ldec_dfje |
完整 16 张表结构、字段级对照、凭证处理 SQL 见 references/zw-accounting-schema.md。
\0\0)。PB9 及以下使用 ANSI 单字节 null。混用会导致 LMI API 失败PBORCA_UTF8=1。读取时优先 UTF-8,失败再回退 GBK/ANSI。直接假定错误编码会导致中文字符损坏pborc100.dll,PB25 必须用 pborc.dll。版本不匹配会直接崩溃PBORCA_UTF8=1 和 PBORCA_ANSI_DBCS=3 只能选一个,混用会导致所有中文乱码release 10; 会导致 ORCA 无法解析16777215=白色,255=红色retrieve= 中的 PBSELECT 语法极易写错。优先在 PB IDE 中修改 DW 的 SQL,再导出grid.lines=0 — 缺少此属性会在 PB IDE Edit Source 保存时报语法错误print.canusedefaultprinter=yes — 不是 print.canusedefaultpaper,后者 PB10 不识别update=/updatewhereclause= — 数据库列才有,External 的 table() 只保留 type=、name=、dbname=type=decimal 不带精度 — type=decimal(12,4) 会报 syntax error,改为 type=decimal,格式在 column 的 format= 中指定\r\n) — LF 换行的 .sr* 文件 Import 到 PB IDE 会失败,必须转为 CRLF$PBExportHeader$ — IDE Import 需要,但 Edit Source 粘贴不要dw_result.create(sql) 不能直接传裸 SQL — 裸 SELECT 缺少 release 10; 会报 "incorrect release number"。必须用 SQLCA.SyntaxFromSQL(ls_sql, "style(type=grid)", ls_err) 生成完整 DW 语法print.margin.top 变超链接、_t 变 \_t,导致 PB 报错。必须从源文件直接复制核心矛盾:PB IDE 导出的 .sr* 文件在中文 Windows 上使用 ANSI/GB2312 编码,而 Agent 编辑工具只能写出 UTF-8。UTF-8 中文(每字 3 字节)与 GB2312 中文(每字 2 字节)字节序列不同,PB IDE 无法解析。
典型症状:
"CO114: Error scanning object source entry""Regenerate of source failed"解决策略(优先级从高到低):
首选:PB IDE 内手工操作 — 用户打开 PB IDE 后,直接指导在 Window/DataWindow Painter 中手动操作。完全避开 SR 文件编码问题。最可靠。
次选:ASCII-only 编辑 — 如果必须编辑 .sr*,确保新增内容不含任何中文:
"Gen PZ" 而非 "生成凭证")'Tip'/'Error' 而非 '提示'/'错误')cbxm_name='In' 而非 '入库费')// 英文或删除最后手段:全新 ASCII 文件 — 原文件已被 UTF-8 中文污染时,用 Write 写出全新纯 ASCII 版本。
快速判断:你写入的中文显示正常但文件中原有中文显示乱码 → 一定是 UTF-8 vs GB2312 混杂。
当 SR 编辑反复失败(编码/锁文件/语法错误),立即切换:
choose case 缺 end choose、if 缺 end if、变量声明不完整cb_gen_pz 已存在)release 10;,.srw 必须有 forward 声明Application 的 Open 事件必须显式 CONNECT USING SQLCA;,否则所有嵌入式 SQL 报 sqlca.sqlcode = -1、SQLErr=Transaction not connected。
标准模板:
SQLCA.DBMS = "ODBC"
SQLCA.AutoCommit = False
SQLCA.DBParm = "ConnectString='DSN=KS2025;UID=dba;PWD=sql'"
CONNECT USING SQLCA;
if sqlca.sqlcode = 0 then
open(w_main_login)
else
messagebox("Error", "Connect failed: " + sqlca.sqlerrtext)
halt close
end if
dw_primary.sharedata(dw_secondary) 后,动态 SQL 查询应该只从 primary DW 取 SQL:
// ✅ 正确
i_new_sql = dw_fyd.GetSQLSelect() // 只用 primary 的 SQL
// ❌ 错误 — 第二行覆盖了第一行
i_new_sql = dw_fyd.GetSQLSelect()
i_new_sql = dw_fyd_free.GetSQLSelect() // 覆盖!
两个 DW 的 SQL 模板可能不同(grid vs freeform),用 primary 的才一致。
当业务单据(费用单/合同/采购单)需要生成会计凭证时,遵循以下标准模式:
数据库设计:业务单据表增加 pz_code VARCHAR(13) 列,关联生成的凭证号。
生成逻辑模板(cb_gen_pz Clicked 事件):
// 1. 获取业务单据数据
r_row = dw_fyd.getrow()
r_fyd_djh = dw_fyd.getitemstring(r_row, 'fyd_djh')
// 2. 检查是否已生成凭证
string r_exist_pz
select pz_code into :r_exist_pz from abc_fyd where fyd_djh = :r_fyd_djh;
if not isnull(r_exist_pz) and r_exist_pz <> '' then
messagebox('Tip','Voucher already generated: ' + r_exist_pz)
return
end if
// 3. 根据业务类型确定借贷科目(pos() 子串匹配)
choose case true
case pos(r_cbxm_name, '入库') > 0 // 匹配"入库装卸搬运费用"
r_km_jf = '500101'; r_km_df = '224101'
case pos(r_cbxm_name, '出库') > 0
r_km_jf = '500102'; r_km_df = '224101'
// ... 更多分支
end choose
// 4. 生成凭证号(按 zth+nkjqj+ykjqj 分区,4 位补零)
select max(pzh) into :r_pzh from zw_pz_zb
where zth=:r_zth and nkjqj=:r_nkjqj and ykjqj=:r_ykjqj;
if isnull(r_pzh) then r_pzh='0001'
else r_pzh = fill('0',4-len(string(integer(r_pzh)+1))) + string(integer(r_pzh)+1)
// 5. INSERT 凭证主表 + 借方明细 + 贷方明细
insert into zw_pz_zb (...) values (:r_zth, :r_nkjqj, ...);
if sqlca.sqlcode <> 0 then rollback; return
insert into zw_pz_mxb (...) values (..., :r_km_jf, :r_fyd_je, 0);
if sqlca.sqlcode <> 0 then rollback; return
insert into zw_pz_mxb (...) values (..., :r_km_df, 0, :r_fyd_je);
if sqlca.sqlcode <> 0 then rollback; return
// 6. COMMIT + 更新业务单据的 pz_code
commit;
update abc_fyd set pz_code = :r_pzh where fyd_djh = :r_fyd_djh;
// 7. 刷新显示
dw_fyd.retrieve()
成本项目→科目映射表(ABC 作业成本法):
| cbxm_name 关键词 | 借方科目 | 贷方科目 | 含义 |
|---|---|---|---|
| 入库 | 500101 生产成本-入库费用 | 224101 应付账款-装卸费 | Inbound |
| 出库 | 500102 生产成本-出库费用 | 224101 应付账款-装卸费 | Outbound |
| 监控 | 500103 生产成本-监控费用 | 224102 应付账款-监控费 | Monitor |
| 包装 | 500104 生产成本-包装费用 | 224103 应付账款-包装费 | Package |
| 运输 | 500105 生产成本-运输费用 | 224105 应付账款-运输费 | Transport |
| 行政 | 660201 管理费用-办公费 | 224104 应付账款-行政费 | Admin |
appname "myapp" 而非 appname "myapp";,分号会使 ORCA 解析器正则匹配失败AppName/AppLib/LibList,尽管解析器用 re.IGNORECASE,但标准格式如此LibList "ks_12306010322.pbl",解析器会自动基于 PBT 所在目录解析where id=:id_var 而非 where id=id_varOpenSheet(w_child, w_mdiframe) — 两参数形式最简单可靠。不要用 ParentWindow(主窗口上下文不存在)或多余的位置参数OpenSheet(w, ParentWindow, 0, Original!) 只在 MDI 子窗口 中有效dbname= 可能意外连表名一起改掉。用 Grep 先查看所有匹配,确认范围后再改WOW6432Node)。64-bit ODBC 驱动 PB10 看不到,报 IM002(8)Desktop、工程考试 等含 CJK/全角的路径会导致 ODBC 驱动 I/O error / Unknown device error。复制 .db 到纯英文路径(如 F:\PB_Work\)ConnectString='Driver=SQL Anywhere 17;ENG=zw;DBN=zw;UID=dba;PWD=sql;DBF=F:\...zw.db'.db 文件。C:\Program Files\SQL Anywhere 17\Bin32\dbodbc17.dllNew-Item -Path 'HKCU:\Software\ODBC\ODBC.INI\KS2025'g_zth/g_nkjqj/g_ykjqj)在 App 对象中声明。窗口 Regenerate 前 App 必须在 PBL 中,否则 C0015: Undefined variabledba, PWD=sql。如被修改过,联系 DBA详见 references/pb-odbc-troubleshooting.md
// 审核:设置审核标记、审核人、审核日期
UPDATE zw_pz_zb SET shbj='是', shr=:g_id, shrq=:g_rq
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj AND shbj='否';
// 取消审核:清除审核标记
UPDATE zw_pz_zb SET shbj='否', shr='', shrq=NULL
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj AND shbj='是' AND jzbj='否';
// 记账:设置记账标记、记账人、记账日期
UPDATE zw_pz_zb SET jzbj='是', jzr=:g_id, jzrq=:g_rq
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj AND shbj='是' AND jzbj='否';
// 定义全局函数 gf_zw_zb_kmyeb_mxzb() 在记账后调用
// 1. 更新科目余额表:从凭证汇总借方/贷方发生额
UPDATE zw_zb_kmyeb SET jffse = (SELECT COALESCE(SUM(jfje),0) FROM zw_pz_mxb
WHERE zth=zw_zb_kmyeb.zth AND nkjqj=zw_zb_kmyeb.nkjqj
AND ykjqj=zw_zb_kmyeb.ykjqj AND km_code=zw_zb_kmyeb.km_code)
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 2. 更新期末余额: 期初+借方发生-贷方发生(借科目) / 期初+贷方发生-借方发生(贷科目)
UPDATE zw_zb_kmyeb SET
qmjfye = qcjfye + jffse,
qmdfye = qcdfye + dffse,
jflj = COALESCE(jflj,0) + jffse,
dflj = COALESCE(dflj,0) + dffse
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 3. 插入明细账:逐笔凭证生成明细记录
INSERT INTO zw_zb_mxzb (zth,nkjqj,ykjqj,km_code,xh,rq,pzh,zy,jfje,dfje)
SELECT zth,nkjqj,ykjqj,km_code,
(SELECT COUNT(*)+1 FROM zw_zb_mxzb b WHERE b.zth=a.zth AND b.nkjqj=a.nkjqj
AND b.ykjqj=a.ykjqj AND b.km_code=a.km_code),
rq,pzh,zy,jfje,dfje
FROM (SELECT a.zth,a.nkjqj,a.ykjqj,b.km_code,a.rq,a.pzh,b.zy,b.jfje,b.dfje
FROM zw_pz_zb a, zw_pz_mxb b
WHERE a.zth=b.zth AND a.nkjqj=b.nkjqj AND a.ykjqj=b.ykjqj AND a.pzh=b.pzh
AND a.zth=:g_zth AND a.nkjqj=:g_nkjqj AND a.ykjqj=:g_ykjqj AND a.jzbj='是') a;
// 核心:损益科目余额→本年利润(4103)
// 第1步:删除旧的结转损益凭证
DELETE FROM zw_pz_zb WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj
AND (bz LIKE '%[机]结转损益%' OR bz LIKE '%[机]计提所得税费用%');
DELETE FROM zw_pz_mxb WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj
AND (zy LIKE '%结转损益%' OR zy LIKE '%计提所得税%');
// 第2步:生成收入类→本年利润 凭证(借:收入科目, 贷:4103)
// 凭证号: replicate('0',4-len(max(pzh)+1)) + string(max(pzh)+1)
INSERT INTO zw_pz_zb(zth,nkjqj,ykjqj,pzh,rq,fdjs,zdr,zdrq,shbj,jzbj,bz)
SELECT DISTINCT zth,nkjqj,ykjqj,
(SELECT replicate('0',4-len(string(max(pzh)+1)))+string(max(pzh)+1)
FROM zw_pz_zb WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj),
string(g_nkjqj)+'-'+string(g_ykjqj)+'-'+'28', 0, '0', g_rq, '否','否',
'[机]结转损益(收入类)'
FROM zw_pz_zb WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 第3步:生成费用类→本年利润 凭证(借:4103, 贷:费用科目)
// ...类似模式...
// 核心函数: gf_zw_yb_zcfzb() — 从科目余额表逐项计算填入资产负债表
// 模式: DELETE旧数据 → INSERT新数据
// 1. 货币资金期末余额 = 库存现金(1001) + 银行存款(1002) + 其他货币资金(1012)
UPDATE zw_yb_zcfzb SET hbzjqmye = (
SELECT COALESCE(SUM(qmye),0) FROM zw_zb_kmyeb
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj
AND km_code IN ('1001','1002','1012'))
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 2. 上期期末→本期期初(跨月结转)
UPDATE zw_yb_zcfzb SET hbzjqcye = (
SELECT COALESCE(hbzjqmye,0) FROM zw_yb_zcfzb
WHERE zth=:g_zth AND nkjqj=:g_nkjqj1 AND ykjqj=:g_ykjqj1)
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 3. 固定资产 = 固定资产(1601) - 累计折旧(1602) - 固定资产减值准备(1603)
UPDATE zw_yb_zcfzb SET gdzcqmye = (
SELECT COALESCE(SUM(CASE WHEN km_code='1601' THEN qmye
WHEN km_code='1602' THEN -qmye WHEN km_code='1603' THEN -qmye ELSE 0 END),0)
FROM zw_zb_kmyeb WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj
AND km_code IN ('1601','1602','1603'))
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 核心:从科目余额表取损益类科目发生额
// 营业收入 = 主营业务收入(6001) + 其他业务收入(6051)
UPDATE zw_yb_lrb SET yysrbqje = (
SELECT COALESCE(SUM(dffse),0) FROM zw_zb_kmyeb
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj
AND km_code IN ('6001','6051'))
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 营业利润 = 收入 - 成本 - 费用
UPDATE zw_yb_lrb SET yylrbqje =
COALESCE(yysrbqje,0) - COALESCE(yycbbqje,0) - COALESCE(sjjfjbqje,0)
- COALESCE(xsfybqje,0) - COALESCE(glfybqje,0) - COALESCE(cwfybqje,0)
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 凭证修改:先删除旧凭证主表+明细,再插入新数据
// 第1步:获取原凭证号
string r_zth, r_nkjqj, r_ykjqj, r_pzh
r_pzh = dw_pzcx.getitemstring(row, 'pzh')
// 第2步:删除旧凭证
DELETE FROM zw_pz_zb WHERE zth=:r_zth AND nkjqj=:r_nkjqj AND ykjqj=:r_ykjqj AND pzh=:r_pzh;
DELETE FROM zw_pz_mxb WHERE zth=:r_zth AND nkjqj=:r_nkjqj AND ykjqj=:r_ykjqj AND pzh=:r_pzh;
// 第3步:重新保存(同凭证输入流程)
// dw_main.update() + dw_item.update() → commit/rollback
// 使用 openwithparm 将参数传递给窗口,实现一个窗口多种用途
// 凭证查询窗口: w_zw_pz_cx 根据参数切换数据窗口对象
openwithparm(w_zw_pz_cx, 'cx') // 查询模式: dw dataobject = d_pz_grid
openwithparm(w_zw_pz_cx, 'sh') // 审核模式: dw dataobject = d_pz_sh_grid
openwithparm(w_zw_pz_cx, 'jz') // 记账模式: dw dataobject = d_pz_jz_grid
// 窗口 open 事件接收参数
event open;string r_parm
r_parm = message.stringparm
choose case r_parm
case 'cx'; dw_main.dataobject = 'd_pz_grid'
case 'sh'; dw_main.dataobject = 'd_pz_sh_grid'
case 'jz'; dw_main.dataobject = 'd_pz_jz_grid'
end choose
// 期末结账:将本月科目余额表的期末余额,作为下月的期初余额
// 1. 检查下月是否已存在数据
string ls_nkjqj_next, ls_ykjqj_next
if g_ykjqj = '12' then
ls_nkjqj_next = string(integer(g_nkjqj) + 1)
ls_ykjqj_next = '01'
else
ls_nkjqj_next = g_nkjqj
ls_ykjqj_next = string(integer(g_ykjqj) + 1, '00')
end if
// 2. 删除下月旧数据,INSERT 本月期末→下月期初
DELETE FROM zw_zb_kmyeb WHERE zth=:g_zth AND nkjqj=:ls_nkjqj_next AND ykjqj=:ls_ykjqj_next;
INSERT INTO zw_zb_kmyeb(zth,nkjqj,ykjqj,km_code,qcjfye,qcdfye,qcye,qmjfye,qmdfye,qmye)
SELECT zth, :ls_nkjqj_next, :ls_ykjqj_next, km_code,
qmjfye, qmdfye, qmye, qmjfye, qmdfye, qmye
FROM zw_zb_kmyeb WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
// 获取下个凭证号:max(pzh)+1,补零至4位
string ls_pzh
SELECT max(pzh) INTO :ls_pzh FROM zw_pz_zb
WHERE zth=:g_zth AND nkjqj=:g_nkjqj AND ykjqj=:g_ykjqj;
if isnull(ls_pzh) then
ls_pzh = '0001'
else
ls_pzh = string(integer(ls_pzh) + 1)
ls_pzh = fill('0', 4 - len(ls_pzh)) + ls_pzh
end if
// SQL版本(在INSERT中直接计算):
// replicate('0', 4 - length(string(max(pzh)+1))) + string(max(pzh)+1)
建库建表(2) → 建视图(3) → 码表初始化(4) → 科目余额初始化(5)
→ 试算平衡(6) → 初始化完毕(7) → 1月凭证输入(8) → 1月审核(9)
→ 1月记账(10) → 1月科目余额表+明细账(11,12) → 1月损益结转(13)
→ 1月期末结账(14) → 1月资产负债表(15) → 1月利润表(16)
→ 2月凭证输入(17) → 2月审核(18) → 2月记账(19)
→ 2月科目余额表+明细账(20,21) → 2月损益结转(22) → 2月期末结账(23)
→ 2月资产负债表(24) → 2月利润表(25)
# 搜索所有 .srd 中的表名
grep -rn "dbname=" *.srd
# 搜索 .srw 中的嵌入式 SQL
grep -rn "select\|update\|insert\|delete" *.srw
# 搜索特定字段的所有引用
grep -rn "pzh\|km_code\|zth" *.srw *.srd
# 列出所有凭证号引用(跨文件搜索)
grep -rn "pzh" F:/(8)Desktop/sr/*.srw
# 1. 先确认影响范围
grep -rn "old_column_name" F:/(8)Desktop/sr/ > /tmp/changes.txt
# 2. 检查 /tmp/changes.txt 确认无误
# 3. 执行精确替换(通过 Edit 工具逐文件替换,或确认范围后用 replace_all)
python3 scripts/extract_schema.py F:/(8)Desktop/share/ZW/数据库/zw.db > /tmp/schema.txt
项目特点:B-8 基础 + 作业成本法,三 PBL 架构(业务/账务分离):
ks_12306010352.pbl — 主库 + DataWindowks_12306010352_fy.pbl — 业务窗口(费用单、合同、成本计算)ks_12306010352_zw.pbl — 账务系统(凭证、账簿、报表)核心教训:
g_oper_code(业务登录设)和 g_zth(会计登录设)跨 PBL 可见,生成凭证时两套变量都需要SQL语句/ 目录下建表 SQL 中 abc_fyd.fyd_rq 是 char(10) 而非 DATE,需修正后再执行| 命名约定 | 示例 |
|---|---|
| 窗口 | w_<学号>_<含义>.srw 如 w_12306010352_fyd |
| 数据窗口 | dw_<学号>_<含义>.srd 如 dw_12306010352_fyd_grid |
| 项目文件 | KS_<学号>.pbw/.pbt/.pbl |
| 数据库 | KS2025.db |
在基础账务系统上叠加 ABC 三级窗口:
| 级别 | 窗口 | 功能 | SQL模式 |
|---|---|---|---|
| A | w_*_A_level |
查询/计算/稽核/溯源 | 科目编码→凭证查询→余额计算→稽核对比→溯源JOIN |
| B | w_*_B6 等 |
5财务指标查询+计算 | UNION ALL 查询 + INSERT 到 zw_yb_cwzbtjb |
| C | w_*_C_level |
5独立SQL查询 | 5按钮各点各查 SyntaxFromSQL 动态DW |
A级四步:Q查询(zw_pz_mxb)→C计算(期初+累计)→A稽核(余额vs凭证)→T溯源(JOIN三表)。
B级12指标(B1-B12各选5):LD/SD/ZCFZ/GDQY/LDZC/ZCBC/XSMLL/XSZZ/ZCZZ/GQZB/JLRZZ/DB。
SQL参考文件: ../A-level/、../B-level/、../C-level/。
当需要创建新的B级变体(如B6→B11)时,遵循以下步骤:
.srw 和 .srd 文件# 关键byte-level替换模式
data = data.replace(b"12306010322_b6", b"12306010339_b11")
data = data.replace(b"UNION ALL SELECT '流动资产周转率', '2001'",
b"UNION ALL SELECT '流动比率', '1001'")
封面窗口需与案例模板明显区分。新增控件需要修改7个位置:
Byte-level编辑关键技巧:
b"..." 精确匹配替换,注意 \r\n vs \r\n vs \t.encode("gbk") 编码后再搜索替换type xxx from 的第二次出现(第二次才有坐标属性)+ & 续行陷阱PowerBuilder的 + & 续行必须在行尾使用,绝不能在下一行开头用 +:
// ✅ 正确
ls_sql = "SELECT ... " + &
"FROM ... " + &
"WHERE ..."
// ❌ 错误 — PB报C0031
ls_sql = "SELECT ... "
+ "FROM ... "
+ "WHERE ..."
推荐替代方案:s = s + "..." 逐段拼接,避免续行问题:
ls_s = "SELECT ... "
ls_s = ls_s + "FROM ... "
ls_s = ls_s + "WHERE ..."
dw_result.create(raw_sql) 会报 "incorrect release number"。正确做法:
ls_syntax = SQLCA.SyntaxFromSQL(ls_sql, "style(type=grid)", ls_err)
if ls_err <> "" then messagebox("Error", ls_err); return
li_rtn = dw_result.create(ls_syntax)
| 用途 | 颜色值 | 效果 |
|---|---|---|
| 窗口底色 | 16056320 | 浅银灰蓝 |
| 标题文字 | 8388608 | 深蓝 |
| 深蓝横幅 | 4194368 | 页眉深蓝底 |
| 白色文字 | 16777215 | 深蓝底上白字 |
| 信息栏底色 | 15724527 | 浅绿/米黄 |
| 统一按钮字体 | Tahoma, -10 | 清晰现代 |
按钮布局公式(窗口宽度4600):
| 按钮 | X | Y | W | H |
|---|---|---|---|---|
| 第1个 | 87 | 220 | 1400 | 100 |
| 第2个 | 1533 | 220 | 1400 | 100 |
| 第3个 | 3960 | 220 | 553 | 100 |
利用 openpyxl 读取包含16张表数据的Excel,自动生成 CREATE TABLE + INSERT 脚本:
wb = openpyxl.load_workbook(xlsx, data_only=True)
for sheet_name in wb.sheetnames:
# 匹配表名 → 读取列定义 → 读取数据行 → 生成SQL
所有SQL窗口都应使用全局变量而非硬编码:
// ❌ 硬编码
"... WHERE zth='01' AND nkjqj='2025' ..."
// ✅ 全局变量
"... WHERE zth='" + g_zth + "' AND nkjqj='" + g_nkjqj + "' ..."
全局变量声明在 Application 对象(.sra 文件)的 global variables 段中,不在窗口 .srw 中。新建窗口引用全局变量时,必须确保 Application 对象中已声明:
// ks_12306010339.sra → global variables
string g_nkjqj // 年度会计期间
string g_ykjqj // 月会计期间(两位, 如 '01'~'12')
string g_zth // 账套号
date g_rq // 系统日期
string g_id // 操作员编号
string gs_period // 当前处理月份(供计算/报表窗口使用, 与 g_ykjqj 同步)
常见陷阱:登录窗口设置 g_ykjqj 但计算窗口使用 gs_period,两者未同步会导致窗口拿到错误值。必须在设置 g_ykjqj 的地方同步 gs_period = g_ykjqj。
当菜单 .srm 文件无法导入 PB10 时,用 GroupBox + CommandButton 实现主界面:
┌─ 凭证管理 ────┐ ┌─ 财务报表 ────┐ ┌─ 计算处理 ────┐ ┌─ 系统管理 ────┐
│ [凭证录入] │ │ [资产负债表] │ │ [计算科目余额]│ │ [账套管理] │
│ [科目余额表] │ │ [利润表] │ │ [期末处理] │ │ [数据初始化] │
│ [明细账] │ │ [B11 财务指标]│ │ │ │ [退出系统] │
└───────────────┘ └───────────────┘ └───────────────┘ └───────────────┘
按钮 clicked 事件写法(在 MDI 框架窗口内):
event clicked;OpenSheet(w_12306010339_pz_input, w_12306010339_main)
end event
关键:OpenSheet 用两参数最简形式 OpenSheet(子窗口, MDI框架窗口)。
OpenSheet(w_xxx, ParentWindow, 0, Original!) — ParentWindow 不在主窗口上下文OpenSheet(w_xxx, this, 0, Original!) — 参数列表错误OpenSheet(w_xxx, w_mdiframe) — 只用两个参数退出按钮用 Close(w_mdiframe) 而非 Close(ParentWindow)。
窗口 open 事件在编译时需解析所有引用的变量。如果全局变量在 Application 中声明但 SRW 独立编译,会报 C0015。安全的 open 事件写法:
event open;
dw_result.settransobject(sqlca)
// 使用系统函数获取默认值,不依赖全局变量
string ls_year, ls_month
ls_year = string(year(today()))
ls_month = string(month(today()))
if len(ls_month) = 1 then ls_month = '0' + ls_month
ddlb_year.text = ls_year
ddlb_month.text = ls_month
end event
PB10 有两种源码导入方式,格式要求完全不同:
| 方式 | 操作 | 需要 $PBExportHeader$ | 编码要求 |
|---|---|---|---|
| Import | PBL 右键 → Import → 选择文件 | ✅ 需要 | 保持原编码(UTF-8/GBK均可) |
| Source 粘贴 | 打开对象 → Source 视图 → 粘贴 | ❌ 不能有 | 系统 ANSI 编码 |
常见错误:
$PBExportHeader$ 粘贴到 Source 视图 → C0001: Illegal data type$PBExportHeader$ 做 Import → C0114: Error scanning object source entry) 粘贴到 Source 视图 → C0036: Illegal symbolPB10 不支持从 .srm 文件导入带事件代码的菜单。即使官方导出的 .srm 也常报 C0114。解决方案:
从 PBL 导出的源码中类型名可能不同于你创建时的命名。导入前必须检查现有 PBL 中的实际对象名:
m_clc_kmyeb vs m_dc_kmyeb — 取决于原 PBL 中的命名当源码文件中文显示乱码(如 "账务系统" 显示为 "������ϵͳ"),是 GB2312 字节被当作 UTF-8 解析造成的。修复步骤:
open(path, 'r', encoding='utf-8', errors='replace') 读取大型 INSERT 脚本中常见两种损坏:
INSERT ... VALUES ... SELECT COUNT(*) INTO ... — 分隔断行后重写ll_pz_mxb 变成 ll_pCOUNT(*) — 补齐缺失的声明和语句致命陷阱:if ... then 在一行、else 换到下一行、但没有 end if — PB 认为这是多行 IF,直接报 C0031 语法错误。
// ❌ 错误 — else 换行后无 end if,PB 报 C0031
if li_rtn = 1 then dw_result.settransobject(sqlca); dw_result.retrieve()
else messagebox('Error', 'Query failed.')
// ✅ 方案1:全部挤一行(单行 IF 不需要 end if)
if li_rtn = 1 then dw_result.settransobject(sqlca); dw_result.retrieve() else messagebox('Error', 'Query failed.')
// ✅ 方案2:多行格式 + end if(推荐,与 SR 模板一致)
if li_rtn = 1 then
dw_result.settransobject(sqlca)
dw_result.retrieve()
else
messagebox('Error', 'Query failed.')
end if
记忆规则:else 写在单独一行 = 多行 IF = 必须有 end if。SR 模板(w_zw_A1.srw)中所有 if-else 都遵此规则。从其他项目复制的窗口代码最常见此陷阱——它在原环境能跑但在新环境导入时报 C0031,因为原 PBL 编译时可能有宽容模式。诊断法:找到报错的 .clicked.81 行号位置,对比同目录 SR 模板文件的 if-else 写法即可定位。
PB IDE Import 对话框可能报 4 种原因,但"Regenerate of source failed"最常见——几乎总是换行符不是 CRLF。从 Git/macOS/Linux 环境或 Python 编辑产生的文件往往是 LF。
诊断:
file w_A_level.srw
# ✅ 正常:ASCII text, with CRLF line terminators
# ❌ 异常:UTF-8 text(无 "CRLF" = LF,Import 必失败)
修复(Python 可靠方案,处理中文路径):
with open(path, 'rb') as f:
data = f.read()
data = data.replace(b'\r\n', b'\n').replace(b'\n', b'\r\n')
with open(path, 'wb') as f:
f.write(data)
注意:Windows 中文路径在 sed -i / tr / bash 管道中容易乱码。首选 Python 二进制读写。文件被 PB IDE 锁定时("Device or resource busy"),先关闭 PB IDE 再覆盖。
当 Import 对话框反复报错(4 条原因轮着出现),直接用 Edit Source 粘贴:
File → New → Window → Save As 为目标对象名(如 w_A_level)Edit Source vs Import 关键区别:
$PBExportHeader$end if 等一个不能少)从其他项目复制的 statictext 控件,部分属性在 PB10 Import 时可能触发 C0031。报错在 st_xxx.N 行号时,安全的最小属性集:
// ✅ 仅保留必要属性
type st_xxx from statictext within w_xxx
integer x = 500; integer y = 216
integer width = 1068; integer height = 72
integer textsize = -10; integer weight = 400
string text = "标签"
boolean focusrectangle = false
end type
// ❌ 导入故障时优先删除的属性(按可疑程度排序)
fontcharset fontcharset = ansi!
fontpitch fontpitch = variable!
fontfamily fontfamily = swiss!
string facename = "Tahoma"
long textcolor = 8388608
long backcolor = 80267554
alignment alignment = center!
基于已有项目(如 KS_12306010322)创建新学号项目(如 KS_0457):
步骤1:复制 sr 文件(文件名 + 内容双重重命名)
for fname in os.listdir(SRC_SR):
if OLD_ID in fname:
new_fname = fname.replace(OLD_ID, NEW_ID)
text = open(src).read()
text = text.replace(OLD_ID, NEW_ID) // 内容全文替换
text = text.replace('\r\n', '\n').replace('\n', '\r\n') // 确保 CRLF
open(dst, 'w').write(text)
步骤2:写 .pbw / .pbt(PBL 在 IDE 中重建)
// KS_0457.pbw — Save Format v3.0,Target 指向 ks_0457.pbt
// ks_0457.pbt — appname/applib/liblist 全部用 ks_0457
.pbl 二进制不能文本替换,必须在 PB IDE 中 File → New → Target 创建.docx/.xlsx 直接复制;.sql 做内容替换步骤3:PB IDE 重建 PBL — File → New → Workspace → Target → Application 生成空 PBL → Application 声明全局变量 → Import 全部 .srd → Import 全部 .srw
在 Cover(w_zw_cover)的 tabpage 中添加按钮:PB IDE 打开 Cover → 找到目标 tabpage → 放置 CommandButton → Script clicked 写 open(w_A_level)。若通过 ORCA 编辑 .srw 添加按钮,需修改 7 个位置:forward type 声明、forward instance、global type instance、create、Control[]、destroy、完整 type 定义。
多学生项目共享同一数据库时,ODBC 数据源统一命名为 KS2026。全局变量 g_zth 区分不同账套,SQL 只引用表名不引用数据库名——数据库名仅出现在 ODBC 连接字符串中。
| 文档 | 用途 |
|---|---|
references/powerscript-syntax.md |
PowerScript 完整语法、控件类型映射、事件名列表 |
references/datawindow-syntax.md |
DW 属性、PB SELECT 语法、颜色值、编辑风格、显示格式 |
references/read-db-files.md |
SQL Anywhere .db 读取、ODBC 连接、系统表结构 |
references/pb-coding-conventions.md |
匈牙利命名法、控件缩写、注释规范、代码风格 |
references/pb-common-functions.md |
字符串、日期、数值、类型转换函数速查 |
references/pb-advanced-patterns.md |
动态 SQL、游标、存储过程、窗口管理、Pbidea |
references/pb-project-examples.md |
58 个 PB 案例项目索引、数据库连接模式 |
references/pb-project-setup.md |
项目结构(.pbw/.pbt)、创建流程、编译发布、Inno Setup 打包 |
references/pb-sql-patterns.md |
进销存表结构、SQL 审计稽核、库存计算、月度统计报表 |
references/zw-accounting-schema.md |
ZW 账务系统完整 Schema(16 表)、字段对照、凭证处理、报表模式 |
references/pb-project-renaming.md |
项目重命名与批量导入:命名规则、依赖分析、导入顺序、Python 工具链 |
references/pb-odbc-troubleshooting.md |
ODBC/SQL Anywhere 连接排错:DSN 创建、免 DSN 直连、编码路径问题、错误速查 |