【VB6|第18期】基于libxl导出Excel之导出失败的解决方案

news2024/11/23 22:32:02

日期:2023年6月12日
作者:Commas
签名:(ง •_•)ง 积跬步以致千里,积小流以成江海……
注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^
1.01365 = 37.7834;0.99365 = 0.0255
1.02365 = 1377.4083;0.98365 = 0.0006


在这里插入图片描述


文章目录

  • 一、前言
  • 二、排查错误
  • 三、解决问题
    • (3-1)调用问题的解决方案
    • (3-2)自身问题的解决方案


历史回顾:

《VB6使用libxl读写Excel浅谈(一)》


一、前言

基于libxl开发导出xlsx格式的Excel文件的功能,遇到一些奇奇怪怪的问题,导致提示“导出失败”,其实归根结底应该还是栈溢出导致的,但是问题隐藏的比较深,也是通过大量数据排查出来的,没有直接结论,而是带领大家一起分析一遍再解决问题,主要还是想分享这种分析的思想,且听我慢慢道来吧……

知识加油站:
xls格式:xls是Excel 97-2003版本中使用的文件格式。它是一种二进制文件格式,以二进制形式存储电子表格数据。xls格式的文件通常较大,并且在功能和兼容性方面存在一些限制。在Excel 2007及更高版本中,可以继续打开和编辑xls格式的文件,但在保存时会转换为xlsx格式。
xlsx格式:xlsx是Excel 2007及之后版本中引入的文件格式。它是基于XML(可扩展标记语言)的开放文件格式,以压缩形式存储电子表格数据。相比于xls格式,xlsx文件通常更小,并且支持更多的功能和选项。它提供了更好的数据恢复能力、更高的兼容性,并且支持使用新的功能,如条件格式、表格样式和更多的行列限制。

二、排查错误

一般情况下,在导出255个以内的sheet不会有问题,导出超过255个就可能会出现“导出失败”的情况,这个情况在xls格式的Excel文件确实是一个棘手的问题,在xlsx格式的Excel文件应该已经轻松解决了。于是我将问题锁定在了libxl库本身以及调用libxl上。至于为什么会怀疑libxl库本身,说多了那都是不愿回首的曾经啊,话不多说,还是回到正题上接着聊下去。功夫不负有心人,找到了几点错误,如下:

  • 【调用问题】:单元格样式的问题;
  • 【自身问题】:工作表表名sheetname超过15个中文字符或31个西文字符的问题;

三、解决问题

(3-1)调用问题的解决方案

当不设置单元格样式,不管数据多少都可以正常导出,这波操作直接把我整蒙了,难道要我导出没有样式的Excel文件给客户,这显然是不合乎常理的。冷静思考片刻,貌似这个库给我们的感觉就是,一直在创建指针,那会不会是指针创建太多了,栈被撑爆了。

接口函数:

'创建格式
Declare Function xlBookAddFormat Lib "lib4xl.dll" Alias "xlBookAddFormatA" (ByVal bookHandle As Long, ByVal formatHandle As Long) As Long
'创建字体
Declare Function xlBookAddFont Lib "lib4xl.dll" Alias "xlBookAddFontA" (ByVal bookHandle As Long, ByVal fontHandle As Long) As Long

每个单元格创建一个 formatHandlefontHandle 指针 ,如下:

'(1)创建格式与字体的指针
formatHandle = xlBookAddFormat(lngbook, 0)
fontHandle = xlBookAddFont(lngbook, 0)

'(2)给对应指针赋值(以下仅写几个样式作为示例而已)
'(2-1)单元格右边边框线
Call xlFormatSetBorderRight(formatHandle, 1)
'(2-2)字体格式
Call xlFontSetBold(fontHandle, 1)               '字体加粗
Call xlFontSetSize(fontHandle, FontSizs)        '字体大小
Call xlFormatSetFont(formatHandle, fontHandle)  '字体格式赋值到单元格格式

'(3)将指针样式赋值给单元格
'lngsheet:当前Excel中某个sheet的指针
'lngRow:单元格行数
'lngCol:单元格列数
'sFormula:单元格Excel公式
Call xlSheetWriteFormula(lngsheet, lngRow, lngCol, sFormula, formatHandle)

顺着这个思路,做了第一次尝试。
只创建一个 formatHandlefontHandle 指针,然后每个单元格重置指针的赋值,也就是上述代码的步骤(2),测试数据都可以正常导出了,欣喜之余,看了看导出的内容,发现所有单元格样式全部被设置为最后一次赋值的样式了,看来此法行不通;

大体方向对了,格式却变样了,所以又做了第二次尝试。
每种样式只创建一个 formatHandlefontHandle 指针,将创建好的 formatHandle 指针存于一个字典 dicFmtHdl 中,这样就极大减少了创建的指针的数量,同时又保证了每个单元格的样式。这次终于成功了,样本数据均通过测试;

小结一下,每个单元格都创建一个指针的话,那么指针数量是巨大的,同种类型的使用同一个指针是最佳的方式。只要指针数量控制在一定范围内,那么就可以正常导出Excel。libxl 的作者没有处理栈空间不足的问题,可能觉得指针就该发挥指针最大的用途吧。但是对于没有指针,或者弱指针类型的语言开发者来说可能会有些不太友好,毕竟开发思路会有些许差异的,适应适应就好,一切都是为了效率嘛。

(3-2)自身问题的解决方案

众所周知,工作表表名sheetname被定义不得超过31个字符,并无字节的限制。这么说来,那么超过31个字符就导出失败,极有可能是libxl库的问题,测试结果如下:

  • 字母+数字<=31
  • 中文<16(可以感受出来,1个中文等于2个“位置”)

以上条件是可以导出的,中文最大只能是15个字符,这极度不合理呀,这样我们只能另辟蹊径了,除了新建sheet可以命名之外,我们还可以对sheet进行重命名。

新建sheet

Declare Function xlBookAddSheet Lib "lib4xl.dll" Alias "xlBookAddSheetA" (ByVal bookHandle As Long, ByVal name As String, ByVal sheetHandle As Long) As Long

sheetname重命名

Declare Sub xlSheetSetName Lib "lib4xl.dll" Alias "xlSheetSetNameA" (ByVal sheetHandle As Long, ByVal name As String)

于是,新建的时候采用“sheet+数字”,让其不大于31字符,然后再重命名成自己想要的中文名称,如下所示:

'(1)新建sheet,让其以“字母+数字”命名sheetname,并控制其不得大于31个字符
lngsheet = xlBookAddSheet(lngbook, h, 0)

'(2)对sheet一堆操作
'此处省略一万行代码

'(3)将其命名成中文,最大可以达到31个中文字符,或者中文+字母+数字总共不得超过31个字符;
Call xlSheetSetName(lngsheet, "自己想要的中文名称")

正所谓关上一扇门的同时也打开一扇窗,虽然接口函数 xlBookAddSheet 有点小问题,不过重命名函数 xlSheetSetName 还是可以扛住,样本数据测试通过,完美手工^ - ^


版权声明:本文为博主原创文章,如需转载,请给出:
原文链接:https://blog.csdn.net/qq_35844043/article/details/130915267

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/635866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

康耐视Visionpro-插入脚本的标准流程 _ 简单方式

机器视觉海康Visionmaster-字符缺失缺陷检测 支持脚本添加的工具如下&#xff1a;添加的脚本只针对当前工具容器有效 Step - 1 &#xff1a; 制作ToolBlock&#xff0c;添加输入/输出等 Step - 2 &#xff1a; 新建Script Step - 3 &#xff1a; 检查界面终端 Step - 4 &am…

【黑马程序员 C++教程从0到1入门编程】【笔记4-2】C++核心编程(类和对象——运算符重载)(左操作数、右操作数)(仿函数)

文章目录 4 类和对象&#xff08;类属性【成员属性】&#xff0c;类函数【成员函数】&#xff09;4.5 运算符重载&#xff08;对已有的运算符重新进行定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型&#xff09;4.5.0.1 可重载运算符和不可重载运算符4.5.0…

案例:创建一个学生管理系统(PXSCJ1)的数据库(SQL)

1、新建数据库&#xff1a;PXSCJ1 --创建数据库CREATE DATABASE PXSCJ1 --创建并确认属性&#xff1a;XSB、KCB、CJB&#xff08;以下代码用于2、3、4、5题&#xff09; use PXSCJ1 create table XSB (学号 char(6) primary key check(学号 like [0][8][1][12][0-9][0-9])…

SM3_Robotics,轴组函数调用

1轴组状态&#xff1a; AXIS_GROUP_REF_SM3 (FB) 2使能&#xff1a; MC_GroupEnable &#xff08;使能&#xff09; 默认在&#xff1a; MC_GroupDisable &#xff08;轴组关闭&#xff09;位置 1&#xff1a;用 MC_GroupEnable &#xff08;使能&#xff09;进入 Gro…

chatgpt赋能python:Python怎么定义主函数:完整指南

Python怎么定义主函数&#xff1a;完整指南 Python是当今最流行的编程语言之一&#xff0c;因为它提供了简单易学、高效率、高度可读性和可维护性的代码编写方式。在Python中定义主函数是一个重要的编程技能&#xff0c;使您能够将Python程序变成可执行的Python应用程序。在本…

chatgpt赋能python:Python多次输入——如何自动化处理数据输入

Python多次输入——如何自动化处理数据输入 作为一名有10年Python编程经验的工程师&#xff0c;我曾遇到过很多需要重复输入数据的情况。这不仅浪费时间&#xff0c;而且容易出错&#xff0c;影响我们的工作效率和准确性。作为程序员&#xff0c;我们需要借助Python的自动化技…

openGauss5 企业版之SQL语法和数据结构

文章目录 1.openGauss SQL 语法2. 数据类型2.1数值类型2.2 布尔类型2.3 字符类型2.4 二进制类型2.5日期/时间类型2.6 几何类型2.7 网络地址类型2.8 位串类型2.9 文本搜索类型2.10 UUID数据类型2.11 JSON/JSONB类型2.11 HLL数据类型2.12 范围类型2.13 索引2.14 对象标识符类型2.…

【MySQL】SQL的高阶用法

文章目录 函数聚合函数Count()Max()Min()Sum()Avg() 其他常用函数时间函数字符串函数数学函数 条件查询使用关系运算符查询使用IN关键字查询使用BETWEEN AND关键字查询使用空值查询使用AND关键字查询使用OR关键字查询使用LIKE关键字查询(模糊查询)使用LIMIT限制查询结果的数量使…

用ChatGPT生成测试数据

大家好&#xff0c;欢迎来到 Crossin的编程教室 &#xff01; 在之前的文章 用ChatGPT写一个数据采集程序 中&#xff0c;我们演示了如何用 ChatGPT 辅助编写代码。 除了直接让ChatGPT写代码&#xff0c;我们也可以让它生成一些开发中使用的测试数据。 比如在开发和测试时&…

Alloy Tutorial(3)Traces Modelling —— Cache Memory

文章目录 Cache Memory完整代码 Cache Memory //Addresses and data sig Addr {} sig Data {}//A cache system consists of main memory and cached memory, but mapping addresses to data one sig CacheSystem {var main, cache: Addr -> lone Data }//Initially there …

yolov5——从未见过注释比代码还多的源码解析You Only Look Once And You get it——训练部分

目录 一&#xff1a;前言 二&#xff1a;先介绍v5源码中必须知道的一些文件&#xff08;了解的可直接加入第三代码部分&#xff09; ​编辑 三&#xff1a;训练 参数配置 模式选择 搭建网络 加载预训练和自定义模型的参数 是否需要冻结层数 定义累计梯度的次数 设置…

零基础小白如何自学 Unity 游戏开发?(送 Unity 教程)

如何自学 Unity&#xff1f;初级阶段&#xff1a;学习编程语言初级阶段&#xff1a;编程实践中级阶段&#xff1a;继续学习编程语言 Unity 教程赠书活动内容简介作者简介赠书方式 如何自学 Unity&#xff1f; 有很多同学对 游戏开发 很感兴趣&#xff0c;但都不知道从何学起&a…

PostgreSQL如何查看事务所占有的锁?

表级锁命令LOCK TABLE 在PG中&#xff0c;显式地在表上加锁的命令为“LOCK TABLE”&#xff0c;此命令的语法如下&#xff1a; LOCK [TABLE] [ONLY] name [,...][IN lockmode MODE] [NOWAIT]语法中各项参数说明如下&#xff1a; name&#xff1a;表名lockmode&#xff1a;表…

GPT1,2,3

GPT1 transformer解码器因为有掩码所以不看后面的东西 gpt就是transformer的解码器&#xff0c;bert 是transformer的编码器 gpt核心卖点&#xff1a;不管输入如何&#xff0c;transformer模型不会变 半监督&#xff1a;先在没有标号上进行训练&#xff0c;再到有标号上进行微…

配置Nexus私服

私服是一种特殊的远程仓库&#xff0c;它代理广域网上的远程仓库&#xff0c;供局域网下的maven用户使用。 目前Nexus3的官方下载地址为 https://help.sonatype.com/repomanager3/product-information/download &#xff0c;由于下载较慢&#xff08;真的很慢&#xff09;&…

【MySQL】库和表的增删查改

目录 一、库的操作 1、创建数据库 2、数据库所使用的编码 2.1查询编码集和校验集 2.2查看数据库的字符集和校验集 2.3创建数据库指定字符集和校验集 2.4不同的校验集所筛选的数据结果不一样 3、查看数据库 4、修改数据库 5、删除数据库 6、数据库的备份和恢复 6.1备…

数字图像处理期末复习习题 SCUEC part2

1.连续图像在空间位置上的离散化称为采样&#xff1b;图像空间分辨率由灰度级决定。 2.坐标的离散化叫采样&#xff0c;幅值的离散化叫量化。 3. 4.图像分割方法多种多样&#xff0c;一般可以根据像素灰度取值的特性将分割方法分为两类&#xff08;阈值分割&#xff0c;区域分割…

软件工程开发文档写作教程(15)—概要设计书的编写

本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;电子工业出版社《软件文档写作教程》 马平&#xff0c;黄冬梅编著 概要设计书的编写 按照国家《概要设计说明书GB8567—88&#xff09;所定义的标准&#xff0…

算法刷题-链表-链表相交

链表相交 面试题 02.07. 链表相交思路其他语言版本JavaPythonGojavaScript 面试题 02.07. 链表相交 同&#xff1a;160.链表相交 力扣题目链接 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0…

chatgpt赋能python:Python如何填充空值

Python如何填充空值 在数据处理过程中&#xff0c;经常会遇到数据集中存在空值的情况。这些空值&#xff08;或缺失值&#xff09;可能会影响数据分析的准确性&#xff0c;因此我们需要对这些空值进行填充。Python作为一种流行的编程语言&#xff0c;提供了许多有效的方法来处…