Qt 5.12 上读取 .xlsx 文件(Windows 平台)

推荐最优方案:使用 QXlsx 库

QXlsx 是一个基于 Qt 的开源库,专门用于读写 .xlsx 文件,适用于 Qt 5.12,且无需依赖 Microsoft Excel 或 COM 对象。以下是其优势与实现步骤:

优势
  1. 跨平台:QXlsx 不依赖 Microsoft Excel,支持 Windows、Linux 和 macOS。
  2. 轻量高效:直接操作 .xlsx 文件(基于 XML 格式),避免 COM 对象的性能瓶颈。
  3. 易于集成:QXlsx 可以作为 Qt 项目的一部分直接嵌入,无需额外的动态链接库。
  4. MIT 许可证:开源且使用灵活,适合商业和非商业项目。
  5. 维护活跃:QXlsx 是 QtXlsxWriter 的后继者,社区维护较好。
安装与配置
  1. 下载 QXlsx
  2. 构建与集成
    • 将 QXlsx 源代码放入项目目录或单独编译为静态库。

    • 在 Qt 项目 .pro 文件中添加:

      复制代码
      include(path_to_QXlsx/QXlsx.pri)
    • 如果使用静态库,需先运行 qmake 和 make(Windows 上使用 mingw32-make)编译 QXlsx。

  3. 依赖
    • 确保 Qt 5.12 已安装,包含 QtCore 和 QtGui 模块。
    • 无需额外安装 Microsoft Office 或 ODBC 驱动。
示例代码

以下是一个简单的读取 .xlsx 文件的示例:

复制代码
#include <QCoreApplication>
#include <QDebug>
#include "xlsxdocument.h"

using namespace QXlsx;

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    // 加载 .xlsx 文件
    Document xlsxR("example.xlsx");
    if (!xlsxR.load()) {
        qDebug() << "Failed to load Excel file.";
        return -1;
    }

    // 读取特定单元格(例如 A1)
    QVariant value = xlsxR.read("A1");
    qDebug() << "Cell A1:" << value.toString();

    // 遍历整个工作表
    int maxRow = xlsxR.dimension().rowCount();
    int maxCol = xlsxR.dimension().columnCount();
    for (int row = 1; row <= maxRow; ++row) {
        for (int col = 1; col <= maxCol; ++col) {
            Cell* cell = xlsxR.cellAt(row, col);
            if (cell) {
                qDebug() << QString("Cell(%1,%2): %3").arg(row).arg(col).arg(cell->readValue().toString());
            }
        }
    }

    return app.exec();
}
性能注意事项
  • 小型文件:QXlsx 能快速处理小型 .xlsx 文件(几百行)。
  • 大型文件:对于大文件(例如上千行),QXlsx 可能因内存占用较高而变慢。建议分块读取或优化代码,避免一次性加载整个文件。
  • 调试:如遇到崩溃(例如处理大文件),使用调试器检查内存分配问题,避免手动删除 QXlsx::Document 管理的单元格指针。

其他方案对比

1. 使用 QODBC

通过 ODBC 驱动读取 .xlsx 文件,利用 Microsoft Access Database Engine。

优点

  • 简单,代码量少。
  • 支持 .xls 和 .xlsx 格式。
  • 适合快速查询特定范围的数据。

缺点

  • 依赖 Microsoft Access Database Engine(需单独安装)。
  • Windows 专用,无法跨平台。
  • 对复杂 .xlsx 文件的支持有限,可能因数据类型不一致导致丢失数据。
  • 存在已知的 ODBC 驱动 bug(例如 FirstRowHasNames 设置问题)。

示例代码

cpp 复制代码
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>

int main() {
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC", "xlsx_connection");
    db.setDatabaseName("DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:\\path\\to\\file.xlsx");
    if (db.open()) {
        QSqlQuery query("SELECT * FROM [Sheet1$]", db);
        while (query.next()) {
            qDebug() << query.value(0).toString();
        }
        db.close();
        QSqlDatabase::removeDatabase("xlsx_connection");
    } else {
        qDebug() << "Failed to open database.";
    }
    return 0;
}

适用场景:需要快速读取小型表格,且目标机器已安装 Excel 或 Access Database Engine。

2. 使用 ActiveX (QAxObject)

通过 ActiveX 访问 Microsoft Excel 的 COM 接口。

优点

  • 直接调用 Excel 的完整功能,适合复杂操作(如格式处理)。
  • 适合 Windows 平台,且 Excel 已安装。

缺点

  • 依赖 Microsoft Excel,需安装 Office。
  • Windows 专用,无法跨平台。
  • 性能较慢,尤其是处理大量数据时(例如上千行可能需要数秒)。
  • 可能产生"僵尸进程"问题,需确保正确关闭 Excel 实例。

示例代码

cpp 复制代码
#include <QAxObject>
#include <QDebug>

int main() {
    QAxObject* excel = new QAxObject("Excel.Application");
    QAxObject* workbooks = excel->querySubObject("Workbooks");
    QAxObject* workbook = workbooks->querySubObject("Open(const QString&)", "C:\\path\\to\\file.xlsx");
    QAxObject* sheets = workbook->querySubObject("Worksheets");
    QAxObject* sheet = sheets->querySubObject("Item(int)", 1);

    QAxObject* usedRange = sheet->querySubObject("UsedRange");
    int rows = usedRange->querySubObject("Rows")->property("Count").toInt();
    int cols = usedRange->querySubObject("Columns")->property("Count").toInt();

    for (int row = 1; row <= rows; ++row) {
        for (int col = 1; col <= cols; ++col) {
            QAxObject* cell = sheet->querySubObject("Cells(int,int)", row, col);
            qDebug() << cell->dynamicCall("Value()").toString();
        }
    }

    workbook->dynamicCall("Close()");
    excel->dynamicCall("Quit()");
    delete excel;
    return 0;
}


​

适用场景:需要调用 Excel 的高级功能(如宏或复杂格式),且目标机器已安装 Excel。

3. 使用第三方库(xlnt 或 libxlsxwriter)
  • xlnt:跨平台的 C++ 库,QXlsx 内部使用 xlnt 作为后端。
  • libxlsxwriter:专注于写 .xlsx 文件,但读支持有限。

优点

  • 跨平台,适合多平台开发。
  • 不依赖 Excel。

缺点

  • 集成到 Qt 需要额外配置(例如 Qxlnt 辅助项目)。
  • 相比 QXlsx,直接使用 xlnt 的 API 较复杂,学习曲线陡峭。

适用场景:需要高度定制化的 .xlsx 文件处理,且不希望依赖 QXlsx。

4. 使用 Qt 的 XML 处理

.xlsx 文件本质上是 ZIP 压缩的 XML 文件,可以用 Qt 的 QXmlStreamReader 解析。

优点

  • 无需第三方库,完全依赖 Qt。
  • 适合简单的数据提取。

缺点

  • 需要手动解析 XML 结构,代码复杂且易出错。
  • 不适合复杂 .xlsx 文件(例如包含公式或格式)。

适用场景:文件结构简单,且仅需提取少量数据。


为什么推荐 QXlsx?

  • 跨平台性:无需依赖 Excel 或 ODBC,适合多平台部署。

  • 易用性 :API 简单,集成方便,文档和示例丰富。

  • 性能:对于中小型文件(<1000 行),性能良好;大型文件需优化读取逻辑。

  • 维护性:QXlsx 是 QtXlsxWriter 的活跃分支,社区支持较好。

注意事项

  1. 环境配置
    • 确保 Qt 5.12 安装正确,包含 qmake 和 mingw32-make(Windows)。
    • 如果使用 MinGW 编译器,可能需安装 Perl(如 Active Perl)以构建 QXlsx。
  2. 大文件优化
    • 对大文件,建议分块读取(如逐行或指定范围)。
    • 避免频繁创建/销毁 QXlsx::Document 对象。
  3. 调试
    • 如果遇到崩溃,使用调试器检查内存分配或文件路径问题。
    • 确保 .xlsx 文件格式正确,避免损坏文件导致加载失败。

总结

在 Qt 5.12 上读取 .xlsx 文件,QXlsx 是最优选择,因其跨平台、易用性和无需外部依赖的特性。相比 QODBC 和 ActiveX,QXlsx 避免了 Windows 专属依赖和性能瓶颈,适合大多数场景。如果需要处理复杂文件或高级功能,可考虑 ActiveX,但需权衡性能和依赖问题。

如果您有特定需求(例如文件大小、是否只读、跨平台要求),可以进一步提供细节,我可以为您调整方案!

相关推荐
TrisighT8 小时前
Electron 跑鸿蒙 PC 上,这 4 个 API 的行为跟 Windows 完全不一样——但文档一行都没写
windows·electron·harmonyos
用户805533698035 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner5 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz10 天前
QML Hello World 入门示例
qt
xcyxiner13 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner14 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner14 天前
DicomViewer (添加模型类)3
qt
xcyxiner15 天前
DicomViewer (目录调整) 2
qt
xcyxiner15 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00617 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言