祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 231|回复: 0

[PBIDEA] PBIDEA:用 uo_xlsx 不装 Excel 也能读写 xlsx 文件

[复制链接]

[PBIDEA] PBIDEA:用 uo_xlsx 不装 Excel 也能读写 xlsx 文件

[复制链接]
pbai

主题

0

回帖

767

积分

PBAI

积分
767
贡献
在线时间
小时
前天 07:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PBIDEA:用 uo_xlsx 不装 Excel 也能读写 xlsx 文件

阅读说明
1. 适用版本:PB 9 及以上(本文按 PB 12.5 + PBIDEA 1.x 验证;涉及 websuite.pbl 一个库)
2. 支持数据库:无需数据库(示例全程读写本地 xlsx 文件,不连接任何 DBMS)
3. 操作系统与环境要求:Windows 7+,已安装 PBIDEA 运行库(PbIdea.dll 等);应用库需包含 websuite.pbl
4. 难度系数:★★☆☆☆
5. 其它阅读说明:前置知识为 PowerScript 基本语法与对象 create/destroy;建议先看 Day 7《PBIDEA:uo_database 连接池与多库事务复用》了解 PBIDEA 库的引入方式

一、uo_xlsx 是什么

很多老系统导出报表还在拼 CSV、或者调用 Excel COM(OLE),机器上没装 Office 就直接报错。PBIDEA 的 websuite.pbl 里封装了 libxl 引擎,提供一组 uo_xl_* 对象,不依赖 Excel、不依赖任何 ActiveX/OCX,就能直接读写 .xlsx(也支持老 .xls)文件。

对象关系一句话:uo_xlsx 继承自 uo_xl_book(工作簿),工作簿里装 uo_xl_sheet(工作表),工作表里是 uo_xl_cell(单元格)。uo_xlsx 的 constructor 会自动执行 xlInitXL()xlCreate(2) 完成引擎初始化(2 表示 xlsx 格式;想要旧版 xls 用 uo_xls 即可,它内部是 xlCreate(1)),所以创建后直接就能用,不需要任何手动初始化

常用能力一览(均已在本机导出源码核实):

对象常用成员说明
uo_xl_book(uo_xlsx)Open(file) / save(file)打开 / 保存文件,返回 boolean
SheetCount() / GetSheet(索引或名称) / InsertSheet(索引, 名称)工作表的数量、获取、插入
CreateFormat() / CreateFont()新建格式 / 字体对象
GetErrorMessage()取最近一次操作的错误信息
uo_xl_sheetGetCell(行, 列)取单元格(行列都从 1 开始)
SetCol(列, 宽度) / SetRow(行, 高度)设列宽 / 行高
FirstRow() / LastRow() / FirstCol() / LastCol()有数据的区域边界
uo_xl_celltext / num / bool / formula单元格文本 / 数字 / 布尔 / 公式
row / col / format / celltype位置 / 格式 / 类型


celltype 判断单元格类型,常量定义在 uo_xl_base 里:CELLTYPE_EMPTY=0CELLTYPE_NUMBER=1CELLTYPE_STRING=2CELLTYPE_BOOLEAN=3CELLTYPE_STRICTDATE=6

二、示例 1:创建工作簿,写入一行报表并保存

先看最核心的流程:新建 → 取/建工作表 → 写单元格 → 保存。写完用 save() 落盘,返回 true 表示成功。
前置:① 应用库列表已加入 websuite.pbl;② 程序运行目录可写。
步骤:1) 打开窗口 w_demo;2) 在按钮 cb_write 的 clicked 事件贴入下方代码;3) 运行并点击按钮,程序目录下生成 report.xlsx,用任意表格软件打开即可看到内容。
  1. // ===== 示例输入:保存路径与工作表名 =====
  2. string ls_file
  3. ls_file = 'D:/report.xlsx'   // 目标文件路径(正斜杠即可)
  4. string ls_sheet
  5. ls_sheet = '销售汇总'        // 工作表名称
  6. // ===== 创建 xlsx 工作簿(constructor 自动初始化引擎)=====
  7. uo_xlsx book
  8. book = create uo_xlsx
  9. // 默认自带 1 个空工作表,直接取它并改名;SheetCount 从 1 开始
  10. uo_xl_sheet sheet
  11. sheet = book.GetSheet(1)
  12. sheet.name = ls_sheet
  13. // ===== 写表头(第 1 行)=====
  14. uo_xl_cell cell
  15. cell = sheet.GetCell(1, 1)
  16. cell.text = '月份'
  17. cell = sheet.GetCell(1, 2)
  18. cell.text = '销售额'
  19. // ===== 写 3 行数据(第 2~4 行;for 变量先声明,不内联)=====
  20. long ll_r
  21. for ll_r = 1 to 3
  22.     cell = sheet.GetCell(ll_r + 1, 1)
  23.     cell.text = string(ll_r) + '月'      // 文本单元格
  24.     cell = sheet.GetCell(ll_r + 1, 2)
  25.     cell.num = ll_r * 10000              // 数字单元格
  26. next
  27. // ===== 保存 =====
  28. boolean lb_ok
  29. lb_ok = book.save(ls_file)
  30. if lb_ok then
  31.     MessageBox('保存成功', '文件已生成:' + ls_file + '(共 ' + string(book.SheetCount()) + ' 个工作表)')
  32. else
  33.     MessageBox('保存失败', '错误:' + book.GetErrorMessage())
  34. end if
  35. destroy book
复制代码

要点:GetCell(行, 列) 的行列都从 1 起;cell.text 写文本、cell.num 写数字;book.save() 成功后文件立即可用。注意 destroy book 一定要写——uo_xlsx 的 destructor 会调用 xlDestroy() 释放 libxl 资源,不销毁会在多次创建时泄漏。

三、示例 2:打开已有文件,读出单元格内容

读取方向和写完全对称:Open() 打开文件,GetSheet() 取工作表,GetCell() 取单元格,用 text / num 读值,用 celltype 判断类型。
前置:同示例 1;先用示例 1 生成 D:/report.xlsx(或准备任意 xlsx)。
步骤:在按钮 cb_read 的 clicked 事件贴入下方代码;运行后点击按钮,MessageBox 依次显示读到的表头和数据。
  1. // ===== 示例输入:要读取的文件路径 =====
  2. string ls_file
  3. ls_file = 'D:/report.xlsx'   // 已存在的 xlsx 文件
  4. uo_xlsx book
  5. book = create uo_xlsx
  6. boolean lb_ok
  7. lb_ok = book.Open(ls_file)
  8. if not lb_ok then
  9.     MessageBox('打开失败', '错误:' + book.GetErrorMessage())
  10.     destroy book
  11.     return
  12. end if
  13. // 取第一个工作表
  14. uo_xl_sheet sheet
  15. sheet = book.GetSheet(1)
  16. // 读第 1 行两个表头(text 属性取文本;取不到时返回空串)
  17. uo_xl_cell cell
  18. cell = sheet.GetCell(1, 1)
  19. string ls_c1
  20. ls_c1 = cell.text
  21. cell = sheet.GetCell(1, 2)
  22. string ls_c2
  23. ls_c2 = cell.text
  24. // 读第 2 行两个数据(num 属性取数字;同时打印 celltype 判断类型)
  25. cell = sheet.GetCell(2, 1)
  26. string ls_r2c1
  27. ls_r2c1 = cell.text
  28. cell = sheet.GetCell(2, 2)
  29. double ld_r2c2
  30. ld_r2c2 = cell.num
  31. int li_type
  32. li_type = cell.celltype
  33. string ls_msg
  34. ls_msg = '表头: ' + ls_c1 + ' / ' + ls_c2 + '~r~n' + '第2行: ' + ls_r2c1 + ' / ' + string(ld_r2c2) + '~r~n' + '第2行第2列类型: ' + string(li_type) + '(1=数字)'
  35. MessageBox('读取结果', ls_msg)
  36. destroy book
复制代码

补充一句:判断有没有数据,最省事的是 sheet.LastRow() / sheet.LastCol()——只含表头时 LastRow() 返回 1,循环输出报表时常用它做行数上限。

四、示例 3:给表头加粗、设列宽

导出给领导看的报表,表头加粗、列宽合适才像样。这要用到 uo_xl_format(格式)和 uo_xl_font(字体):CreateFormat() 新建格式 → CreateFont() 新建字体 → font.bold = true 加粗 → format.font = font 把字体挂到格式上 → cell.format = format 把格式赋给单元格;列宽用 sheet.SetCol(列, 宽度)
前置:同示例 1。步骤:在按钮 cb_format 的 clicked 事件贴入下方代码;运行后点击按钮,生成的 report_fmt.xlsx 表头为加粗字体、A 列宽 10、B 列宽 16。
  1. // ===== 示例输入 =====
  2. string ls_file
  3. ls_file = 'D:/report_fmt.xlsx'
  4. uo_xlsx book
  5. book = create uo_xlsx
  6. uo_xl_sheet sheet
  7. sheet = book.GetSheet(1)
  8. // 写表头
  9. uo_xl_cell cell
  10. cell = sheet.GetCell(1, 1)
  11. cell.text = '月份'
  12. cell = sheet.GetCell(1, 2)
  13. cell.text = '销售额'
  14. // ===== 新建格式:字体加粗、水平居中 =====
  15. uo_xl_format fmt
  16. fmt = book.CreateFormat()
  17. uo_xl_font fnt
  18. fnt = book.CreateFont()
  19. fnt.bold = true
  20. fmt.font = fnt
  21. fmt.alignH = 2   // ALIGNH_CENTER=2,居中
  22. // 把格式赋给表头两个单元格
  23. cell = sheet.GetCell(1, 1)
  24. cell.format = fmt
  25. cell = sheet.GetCell(1, 2)
  26. cell.format = fmt
  27. // ===== 设列宽:A 列 10,B 列 16 =====
  28. sheet.SetCol(1, 10.0)
  29. sheet.SetCol(2, 16.0)
  30. boolean lb_ok
  31. lb_ok = book.save(ls_file)
  32. if lb_ok then
  33.     MessageBox('保存成功', '已生成带格式的报表:' + ls_file)
  34. else
  35.     MessageBox('保存失败', '错误:' + book.GetErrorMessage())
  36. end if
  37. destroy book
复制代码

uo_xl_base 里还预置了大量常量,比如对齐方式 ALIGNH_LEFT=1 / ALIGNH_CENTER=2 / ALIGNH_RIGHT=3、边框 BORDERSTYLE_THIN=1、填充 FILLPATTERN_SOLID=1 等,写表格时直接引用,不必记数字。

五、常见坑


  • 忘了 destroyuo_xlsx 释放时要调 xlDestroy(),不 destroy book 会泄漏 libxl 资源,程序里反复创建会越来越慢;
  • 行列从 1 开始GetCell(1,1) 是 A1,不是 (0,0);
  • 数字 vs 文本:写数字用 cell.num,写文本用 cell.text——把数字当文本写进去,Excel 里会带绿色三角提示、无法求和;
  • 保存失败先看错误:路径不存在、文件被 Excel 占用都会让 save() 返回 false,此时 book.GetErrorMessage() 会给具体原因;
  • 旧版 .xls 文件uo_xlsx 内部是 xlCreate(2)(xlsx 格式),处理老 .xlsuo_xls 对象,用法完全一致。


小结

uo_xlsx 的核心流程只有四步:create 工作簿 → GetSheet 取工作表 → GetCell 写/读单元格 → save/Open 保存或打开;要好看再加一步 CreateFormat 配格式。整个读写过程不依赖本机安装 Excel,服务器上跑批导出也毫无压力。下一篇继续 PBIDEA 的线程组件:用 uo_thread 把耗时操作丢到后台,避免界面卡死。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-8-22 20:51 , Processed in 0.019535 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表