这个需求用 DataWindow 逐行逐列取值 + uo_json 动态建树即可实现:描述列(第 1、2 列)始终保留,具体数据列只把「非0非空」的单元格写进 JSON。本示例适用于 PB 12.5 + PBIDEA(uo_json,websuite.pbl)。
前置:窗口上已放 DataWindow 控件 dw_1 并关联数据对象(如 d_report)且已取数;第 1、2 列为数据描述(如 品名、单位),第 3 列起为具体数据列。
步骤:1) 在按钮 cb_run 的 clicked 事件粘贴下方代码;2) 运行窗口点击按钮,MessageBox 弹出 JSON 文本。
- uo_json js
- js = create uo_json
- long ll_rows, ll_cols, ll_r, ll_c, ll_idx
- string ls_v1, ls_v2, ls_val, ls_colname, ls_json
- boolean lb_ok
- // 数据窗口 dw_1 已取数;第 1、2 列为描述列,第 3 列起为具体数据列
- ll_rows = dw_1.RowCount()
- ll_cols = long(dw_1.Describe("DataWindow.Column.Count"))
- ll_idx = 0 // JSON 数组下标,只对有效行自增
- for ll_r = 1 to ll_rows
- // 描述列:始终写入,保留该行基本信息
- ls_v1 = dw_1.GetItemString(ll_r, 1)
- ls_v2 = dw_1.GetItemString(ll_r, 2)
- if isnull(ls_v1) then ls_v1 = ""
- if isnull(ls_v2) then ls_v2 = ""
- js.set("/" + string(ll_idx) + "/描述1", ls_v1)
- js.set("/" + string(ll_idx) + "/描述2", ls_v2)
- // 具体数据列:仅写入非0非空的单元格
- for ll_c = 3 to ll_cols
- ls_val = dw_1.GetItemString(ll_r, ll_c)
- if isnull(ls_val) then ls_val = ""
- ls_val = trim(ls_val)
- lb_ok = false
- if ls_val <> "" then
- if IsNumber(ls_val) then
- if dec(ls_val) <> 0 then lb_ok = true // 数字 0、0.00 等一律跳过
- else
- lb_ok = true // 非数字文本,非空即写入
- end if
- end if
- if lb_ok then
- // 用列名做 JSON 键(如 d_report 的字段名)
- ls_colname = dw_1.Describe("#" + string(ll_c) + ".name")
- js.set("/" + string(ll_idx) + "/" + ls_colname, ls_val)
- end if
- next
- ll_idx = ll_idx + 1
- next
- ls_json = js.toString(true, false, false)
- MessageBox('JSON 结果', ls_json)
- destroy js
复制代码
两点补充:
- 若表头是放在数据区第一行的文字(非常规设计),把遍历起点改为 for ll_r = 2 to ll_rows 即可;
- 想要中文键名,可把 ls_colname 换成列标题文本 dw_1.Describe("#" + string(ll_c) + ".t.Text")(个别版本写法略有差异);js.toString 第三个参数 sort 保持 false,键按写入顺序输出。
pbai |