首页 / 资讯中心 / 文章详情

VS2015下QtXlsxWriter编译与集成实战:从踩坑到生成Excel

VS2015下QtXlsxWriter编译与集成实战:从踩坑到生成Excel ★ FEATURED ARTICLE
1. 为什么一个菜鸟会卡在 QtXlsxWriter 的编译上如果你正在用 VS2015 做 Qt 相关的桌面开发突然接到一个需求把界面上的数据导出成 Excel 文件。你第一反应可能是——Qt 自带的 QTableWidget 数据导出成 CSV 挺简单但 CSV 打开后中文乱码、格式全丢、客户还嫌弃这不是真正的 Excel。于是你开始找能直接生成.xlsx文件的库搜来搜去QtXlsxWriter 几乎是绕不开的选择。问题来了。QtXlsxWriter 这个库官方文档写得比较工程师向默认你熟悉 qmake 的编译流程、知道怎么把第三方库塞进 Qt 工程、看得懂.pro文件里那些include()和link()的写法。但如果你是从 Visual Studio 那一套sln vcxproj的思维过来的或者平时写 Qt 主要靠 Qt Creator 点点点那第一次编译 QtXlsxWriter 大概率会卡住。我自己第一次搞这个库的时候在 VS2015 环境下折腾了差不多一个下午。报的错五花八门一会儿是nmake找不到一会儿是qmake不是内部命令一会儿编译过了但链接的时候一堆unresolved external symbol。最坑的是网上搜到的教程大多是 Qt Creator 的或者用的是 MinGW 版本的 Qt跟 VS2015 MSVC 这套组合拳对不上。所以这篇东西就是把我踩过的坑、绕过的弯按一个菜鸟也能跟着做的顺序重新捋一遍。核心目标只有一个在 VS2015 环境下把 QtXlsxWriter 编译成可用的库并且能在一个 Qt 工程里成功调用它生成 xlsx 文件。我会把每一步为什么这么做讲清楚而不是甩一堆命令让你复制粘贴。适合的人群很明确用 VS2015 写 Qt、对 qmake 和 nmake 不太熟、但需要导出 Excel 功能的开发者。2. 动手之前先把这几个概念和工具理清楚2.1 QtXlsxWriter 到底是个什么东西QtXlsxWriter 是一个基于 Qt 的第三方库专门用来读写 Excel 的.xlsx格式文件。注意它处理的是 Office 2007 之后的那种基于 XML 的 xlsx不是老的.xls二进制格式。它的工作方式不依赖 Office 组件也不需要装 Excel纯靠 Qt 自己的QIODevice、QXmlStreamWriter这些类把数据按 OOXML 规范写进压缩包里。这一点很关键——意味着你打包发布的程序客户机器上不装 Office 也能正常导出 Excel。它提供的能力大致包括创建工作表、写入单元格数据字符串、数字、日期、公式、设置单元格格式字体、颜色、边框、对齐、合并单元格、插入图片、设置列宽行高等等。对于绝大多数把表格数据导出成 Excel的需求这个库完全够用。2.2 为什么在 VS2015 下编译会跟网上教程不一样这里要讲一个很多人一开始没搞明白的事Qt 有两套编译器体系。一套是 MinGWWindows 上的 GCC一套是 MSVC微软的编译器。你用 Qt Creator 默认装的往往是 MinGW 版本而 VS2015 用的是 MSVC 2015也就是 MSVC 14.0。这两套编译出来的库二进制是不兼容的。网上大量 QtXlsxWriter 的编译教程默认你用的是 MinGW命令是mingw32-make。但你在 VS2015 环境下必须用nmake而且你的 Qt 必须是MSVC 版本的 Qt不能是 MinGW 版本的。如果你装的 Qt 是 MinGW 版那在 VS2015 里根本没法用得重新下载对应 MSVC 2015 的 Qt 版本。这是第一个大坑很多人卡在这里半天找不到原因。2.3 需要提前准备好的东西在正式开始之前确认下面这几样东西都到位了Visual Studio 2015安装时记得勾选 C 相关的组件确保nmake可用。Qt for Windows (MSVC 2015 版本)注意版本号要匹配比如 Qt 5.9.x 或 5.12.x 的 MSVC2015 32/64 位版本。装完之后qmake.exe和nmake都要能在命令行里调用。QtXlsxWriter 源码从代码托管平台拉一份下来解压到没有中文、没有空格的路径下比如D:\libs\QtXlsxWriter。一个命令行环境推荐用VS2015 开发人员命令提示符或者用 Qt 自带的命令行工具关键是环境变量要配好。提示路径里千万不要有中文和空格。我见过有人把源码放在我的文档\新建文件夹下面结果 qmake 生成 Makefile 的时候路径解析直接崩了报的错还特别隐晦查半天查不出来。3. 环境变量配置这一步错了后面全白搭3.1 把 qmake 和 nmake 都挂到 PATH 上编译 QtXlsxWriter 的核心命令就两条qmake生成 Makefilenmake执行编译。但前提是这两个命令在命令行里能直接找到。nmake来自 VS2015最省事的办法是直接用开始菜单里的VS2015 x64 本机工具命令提示符或者 x86 版本取决于你的 Qt 是 32 位还是 64 位。这个命令行窗口打开的时候VS 相关的环境变量已经自动配好了nmake直接可用。qmake来自 Qt 安装目录比如D:\Qt\Qt5.9.9\5.9.9\msvc2015_64\bin。你需要把这个bin目录加到系统 PATH 里或者临时在当前命令行里set PATH%PATH%;D:\Qt\Qt5.9.9\5.9.9\msvc2015_64\bin。验证一下在命令行里敲qmake -v如果输出了 Qt 的版本信息说明配好了。再敲nmake /?如果出来一堆帮助信息说明 nmake 也没问题。3.2 32 位还是 64 位必须跟 Qt 版本对齐这是个特别容易翻车的点。你的 Qt 是msvc2015_64那你就必须用x64 本机工具命令提示符编译出来的库才是 64 位的。如果你用 x86 的命令行去编译 64 位的 Qtqmake 阶段可能就报错了或者编译出来的库跟你的工程位数对不上链接的时候一堆符号找不到。判断方法很简单看你的 Qt 安装目录名带_64的就是 64 位不带的就是 32 位。然后选对应的命令行工具。我个人的习惯是在开始菜单里把VS2015 x64 本机工具命令提示符固定到任务栏省得每次找。3.3 一个容易被忽略的细节环境变量污染有时候你机器上装了多个版本的 Qt或者之前配过别的编译环境PATH 里可能混着好几个qmake。这时候qmake -v输出的版本可能不是你想要的。解决办法是在命令行里用绝对路径调用 qmake比如D:\Qt\Qt5.9.9\5.9.9\msvc2015_64\bin\qmake.exe -v这样能确保用的是你指定的那个版本。编译的时候也用绝对路径避免歧义。4. 编译 QtXlsxWriter 的完整操作链路4.1 进入源码目录先看一眼结构解压完 QtXlsxWriter 源码后进去看一眼目录结构。通常根目录下会有一个QtXlsxWriter.pro文件这是 qmake 的工程文件。还有一个src目录里面是库的源代码。有的版本还会带examples目录里面是示例工程。我们要编译的是库本身所以关注根目录的.pro文件就行。在命令行里cd到源码根目录cd /d D:\libs\QtXlsxWriter注意用/d参数因为要跨盘符切换。这一步没什么技术含量但路径一定要对。4.2 执行 qmake 生成 Makefile在源码根目录下执行qmake QtXlsxWriter.pro如果一切正常你会看到目录下多出来一个Makefile或者Makefile.Debug和Makefile.Release。这一步 qmake 做的事情是读取.pro文件里的配置结合当前 Qt 环境生成 nmake 能看懂的 Makefile。这一步常见的报错有几种qmake: command not foundPATH 没配好回去检查 3.1。Project ERROR: Unknown module(s) in QT: ....pro文件里引用了某个 Qt 模块但你的 Qt 安装里没有。QtXlsxWriter 一般只依赖core和gui如果报这个错可能是 Qt 装得不全。路径相关报错源码路径里有中文或空格换路径。4.3 执行 nmake 开始编译Makefile 生成之后直接nmake或者分开编译 debug 和 releasenmake debug nmake release编译过程会持续几分钟取决于机器性能。你会看到一堆.cpp文件被编译成.obj最后链接成.dll和.lib。这里有个经验第一次编译建议只编 release因为 debug 版本体积大、编译慢而且如果你只是要验证能不能用release 足够了。等确认流程跑通再补 debug 版本。4.4 编译产物在哪里怎么确认成功了编译完成后产物通常在源码目录下的lib文件夹里具体位置看.pro文件的配置。你会看到类似这样的文件文件类型文件名示例用途动态库QtXlsxWriter.dll运行时需要跟 exe 放一起或放系统路径导入库QtXlsxWriter.lib链接时需要告诉链接器 dll 里有哪些符号静态库如果配了QtXlsxWriter.lib (较大)静态链接时用如果lib目录下这几个文件都在而且大小正常dll 一般几百 KB 到 1MB 左右那基本就成功了。如果只有.obj没有.lib说明链接阶段出问题了往上翻编译日志找error。5. 把编译好的库塞进 VS2015 的 Qt 工程5.1 头文件、lib、dll 三件套怎么放编译出来只是第一步真正要用起来得让 VS2015 的工程能找到这三样东西头文件QtXlsxWriter 源码里的src目录下有一堆.h文件比如xlsxdocument.h、xlsxworksheet.h。你需要把src目录的路径告诉编译器。导入库.lib链接阶段需要告诉链接器去哪个 dll 里找符号。动态库.dll运行阶段需要程序启动时加载。我的习惯是在工程目录下建一个third_party文件夹里面分include、lib、bin三个子目录分别放头文件、lib、dll。这样工程自包含换台机器也能编译。5.2 在 VS2015 工程属性里配置包含目录和库目录右键工程 - 属性注意配置和平台要选对Debug/Release、x64/Win32C/C - 常规 - 附加包含目录加上third_party\include的路径。链接器 - 常规 - 附加库目录加上third_party\lib的路径。链接器 - 输入 - 附加依赖项加上QtXlsxWriter.lib。这三步做完编译和链接阶段就能找到库了。但运行时还需要 dll最简单的办法是把QtXlsxWriter.dll复制到你的 exe 输出目录下。5.3 一个真实的链接报错案例我第一次配的时候编译通过了但链接报了一堆unresolved external symbol全是QtXlsx::Document::...之类的。当时第一反应是库没链上检查了附加依赖项QtXlsxWriter.lib确实加了。后来发现问题出在位数不匹配。我的 Qt 是 64 位的但编译 QtXlsxWriter 的时候用的是 x86 的命令行编出来的是 32 位库。32 位的 lib 拿到 64 位工程里链接符号当然对不上。重新用 x64 命令行编译一遍问题解决。这个坑的教训是编译库的位数、Qt 的位数、VS 工程的位数三者必须完全一致。任何一个不一致都会在链接或运行阶段出问题。6. 写一段最小代码验证库能不能用6.1 一个最简单的导出示例库配好之后别急着往正式项目里塞先写个最小 demo 验证一下。下面这段代码创建一个 xlsx 文件往第一个单元格写点东西#include QCoreApplication #include xlsxdocument.h int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QXlsx::Document xlsx; xlsx.write(A1, Hello QtXlsxWriter); xlsx.write(A2, 12345); xlsx.write(A3, QDateTime::currentDateTime()); xlsx.saveAs(test_output.xlsx); return 0; }编译运行如果当前目录下生成了test_output.xlsx用 Excel 或 WPS 打开能看到内容说明整条链路通了。6.2 运行时报错找不到 QtXlsxWriter.dll怎么办这是最常见的问题。程序编译链接都过了一运行就弹窗说找不到 dll。原因很简单exe 运行时会在当前目录、系统目录、PATH 里找 dll你的QtXlsxWriter.dll不在这些地方。解决办法有三个按推荐程度排序把 dll 复制到 exe 所在目录最省事推荐。把 dll 所在目录加到系统 PATH不推荐污染环境。用 Qt 的windeployqt工具自动收集依赖适合发布时用。我一般用第一种在 VS 工程里配一个生成后事件自动把 dll 拷过去xcopy /y $(SolutionDir)third_party\bin\QtXlsxWriter.dll $(OutDir)这样每次编译完 dll 自动就位省得手动拷。6.3 中文乱码问题的排查如果你的导出内容里有中文打开 Excel 发现是乱码那多半是编码问题。QtXlsxWriter 内部用的是 UTF-8但你的源码文件如果是 GBK 编码字符串字面量传进去就可能出问题。解决办法确保源码文件保存为 UTF-8带 BOM 或不带都行VS2015 建议带 BOM或者在写字符串的时候显式转换xlsx.write(A1, QString::fromUtf8(中文内容));实测下来只要源码是 UTF-8直接写中文字面量一般没问题。如果还是乱码检查一下是不是用了const char*而不是QString。7. 踩坑复盘那些让我多花两小时的细节7.1 源码版本和 Qt 版本的兼容性QtXlsxWriter 的不同版本对 Qt 版本有要求。老版本的库可能用了 Qt 5.0 时代的 API在新版 Qt 上编译会报废弃警告甚至错误。反过来新版本的库可能用了 Qt 5.15 才有的特性在 Qt 5.9 上编译不过。我遇到过一次拉的最新源码在 Qt 5.9 上编译报错提示某个QStringView相关的 API 不存在。后来换了一个稍早的 tag 才编过。所以拉源码的时候留意一下 release 说明或者 commit 记录选一个跟你 Qt 版本匹配的。7.2 nmake 的并行编译参数nmake默认是单线程编译源码文件多的时候会比较慢。可以加/J参数开多核nmake /J不过要注意某些老版本的 nmake 对/J支持不好可能出现编译顺序问题。如果开了/J之后报奇怪的错去掉这个参数再试。7.3 清理重编的正确姿势编译过程中如果中断了或者改了配置想重来别直接删 Makefile 就完事。正确的清理命令是nmake clean nmake distcleanclean删掉编译产物distclean连 Makefile 一起删。然后再重新qmakenmake。直接手动删文件有时候会漏掉一些中间产物导致下次编译出现莫名其妙的错误。7.4 关于 debug 和 release 混用VS2015 工程默认有 Debug 和 Release 两种配置。如果你编译 QtXlsxWriter 只编了 release 版本那你的工程在 Debug 配置下链接就会失败因为找不到 debug 版的 lib。解决办法要么是补编 debug 版本要么是在工程里把 Debug 配置也指向 release 的 lib不推荐调试时可能出问题。最稳妥的是两个版本都编分别放到lib\debug和lib\release目录工程属性里按配置分别指向。8. 几个提升效率的实操建议8.1 把编译过程脚本化如果你经常需要在不同机器上配这个库建议把编译命令写成一个.bat脚本echo off call D:\Qt\Qt5.9.9\5.9.9\msvc2015_64\bin\qmake.exe QtXlsxWriter.pro nmake nmake clean注意第一行的call因为 qmake 本身也是个批处理不加call的话执行完 qmake 脚本就退出了后面的 nmake 不会执行。这个细节坑过我一次。8.2 用 .pri 文件简化工程配置QtXlsxWriter 源码里通常带一个.pri文件里面封装了头文件路径、库路径这些配置。如果你用的是 qmake 工程.pro可以直接include()这个 pri 文件省得手动配一堆路径。但 VS2015 的工程是.vcxproj用不了 pri还是得手动配属性。这也是为什么 VS 环境下配第三方库比 Qt Creator 麻烦的原因之一。8.3 关于静态链接的取舍QtXlsxWriter 也支持静态编译就是把库直接编进你的 exe不需要额外的 dll。好处是发布简单坏处是 exe 体积变大而且如果多个模块都用这个库可能产生符号冲突。我的建议是小项目、发布要求简单用静态大项目、模块多用动态。动态链接虽然多一个 dll但更新库的时候不用重新编译整个工程维护上更灵活。8.4 版本管理的一点心得第三方库的源码和编译产物建议纳入版本管理比如 Git。但注意编译产物.obj、.dll、.lib体积大且跟环境相关一般用.gitignore排除掉只保留源码和编译脚本。这样换机器的时候拉源码、跑脚本、重新编译流程清晰可控。9. 最后聊几句实际使用中的体会QtXlsxWriter 这个库功能上不算特别强大复杂的 Excel 操作比如图表、数据透视表它做不了。但对于把数据导出成带格式的 Excel这个最常见的需求它足够稳定而且不依赖 Office部署省心。我在实际项目里用它做过报表导出几千行数据、带单元格格式和合并生成速度很快打开也没问题。唯一需要注意的是写入大量数据时尽量用批量写入的方式比如先把数据组织成二维数组再循环写入比一个个单元格单独写要快不少。另外saveAs的时候如果目标文件被 Excel 占用会保存失败记得在代码里处理这个异常情况给用户一个友好的提示。编译这个库本身说难不难说简单也不简单。核心就是三件事环境变量配对、位数对齐、路径干净。这三样搞定了剩下的就是按部就班执行命令。第一次配可能会花点时间但配通一次之后后面再遇到就是十分钟的事。希望这篇东西能帮你少走点弯路把时间花在真正的业务逻辑上而不是跟编译环境较劲。
阅读完成 · 觉得有帮助?
咨询建站