Roson的Qt之旅 #139 Qt读写Excel

news2024/11/20 11:32:16

1.使用QAxObject读写Excel

QAxObject类提供了一个包裹COM对象的QObject。
QAxObject可以被实例化为一个空的对象,用它应该包裹的COM对象的名字,或者用一个指向代表现有COM对象的IUnknown的指针。如果COM对象实现了IDispatch接口,该对象的属性、方法和事件就可以作为Qt属性、槽和信号使用。基类,QAxBase,提供了一个API,可以通过IUnknown指针直接访问COM对象。
QAxObject是一个QObject,并可以作为QObject使用,例如,它可以被组织在一个对象的层次结构中,接收事件并连接到信号和槽。
QAxObject也从QAxBase继承了大部分与ActiveX相关的功能,特别是dynamicCall()和querySubObject()。
警告。你可以对QAxObject进行子类化,但是你不能在子类中使用Q_OBJECT宏(生成的moc-file将不会被编译),所以你不能进一步添加信号、槽或属性。这个限制是由于在运行时生成的元对象信息造成的。为了解决这个问题,将QAxObject聚合为QObject子类的一个成员。
也请参见QAxBase、QAxWidget、QAxScript和ActiveQt Framework。

下面是示例代码:

excelopt.h 

#ifndef EXCELOPT_H
#define EXCELOPT_H

#include <QObject>
#include <QAxObject>
#include <Windows.h>

class ExcelOpt : public QObject
{
    Q_OBJECT
public:
    explicit ExcelOpt(QObject *parent = nullptr);
    ~ExcelOpt();

    bool open(const QString &fileName);
    bool save();
    bool saveAs(const QString &fileName);
    void close();

    QVariant read(int row, int column);
    bool write(int row, int column, const QVariant &value);

signals:

public slots:
    void slots_exception(int code, const QString &source, const QString &desc, const QString &help);

private:
    QAxObject *m_excel;
    QAxObject *m_workbooks;
    QAxObject *m_workbook;
    QAxObject *m_worksheets;
    QAxObject *m_worksheet;
};

#endif // EXCELOPT_H

excelopt.cpp 

#include "excelopt.h"
#include <QDebug>

ExcelOpt::ExcelOpt(QObject *parent) : QObject(parent)
{
    m_excel = NULL;
    m_workbooks = NULL;
    m_workbook = NULL;
    m_worksheets = NULL;
    m_worksheet = NULL;

    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    //HRESULT result = OleInitialize(nullptr);   //换成CoInitialize似乎也是一样的
    //if (result != S_OK && result != S_FALSE)
    //{
    //    qDebug()<<QString("Could not initialize OLE (error %x)").arg(static_cast<unsigned int>(result));
    //}

    // 创建一个新的Excel应用程序
    //m_excel = new QAxObject("Excel.Application");
    
    m_excel = new QAxObject(this);    //连接Excel控件
	if (m_excel->setControl("Excel.Application"))
	{

	}
	else
	{
        m_excel->setControl("ket.Application");  //连接Excel控件
	}

    m_excel->setProperty("Visible", false);  //不显示窗体
    
    
    connect(m_excel, SIGNAL(exception(int, const QString &, const QString &, const QString &)), this, SLOT(slots_exception(int, const QString &, const QString &, const QString &)));

    // 获取所有工作簿
    m_workbooks = m_excel->querySubObject("Workbooks");
}

ExcelOpt::~ExcelOpt()
{
    // 关闭所有工作簿
    m_workbooks->dynamicCall("Close()");

    // 关闭Excel应用程序
    m_excel->dynamicCall("Quit()");

    delete m_worksheet;
    delete m_worksheets;
    delete m_workbook;
    delete m_workbooks;
    delete m_excel;

    OleUninitialize();
}

bool ExcelOpt::open(const QString &fileName)
{
    // 如果工作簿已打开,则先关闭它
    if (m_workbook) {
        m_workbook->dynamicCall("Close()");
        delete m_worksheet;
        delete m_worksheets;
        delete m_workbook;
    }

    // 打开指定的工作簿
    m_workbook = m_workbooks->querySubObject("Open(const QString&)", fileName);
    if (!m_workbook)
        return false;

    // 获取所有工作表
    m_worksheets = m_workbook->querySubObject("Worksheets");
    if (!m_worksheets)
        return false;

    // 获取第一个工作表
    m_worksheet = m_worksheets->querySubObject("Item(int)", 1);
    if (!m_worksheet)
        return false;

    return true;
}

bool ExcelOpt::save()
{
    if (!m_workbook)
        return false;

    // 保存工作簿
    return m_workbook->dynamicCall("Save()").toBool();
}

bool ExcelOpt::saveAs(const QString &fileName)
{
    if (!m_workbook)
        return false;

    // 将工作簿另存为指定的文件
    return m_workbook->dynamicCall("SaveAs(const QString&)", fileName).toBool();
}

void ExcelOpt::close()
{
    if (m_workbook) {
        // 关闭工作簿
        m_workbook->dynamicCall("Close()");
        delete m_worksheet;
        delete m_worksheets;
        delete m_workbook;
        m_worksheet = nullptr;
        m_worksheets = nullptr;
        m_workbook = nullptr;
    }
}

QVariant ExcelOpt::read(int row, int column)
{
    if (!m_worksheet)
        return QVariant();

    // 读取指定单元格的值
    return m_worksheet->querySubObject("Cells(int,int)", row, column)->dynamicCall("Value()");
}

bool ExcelOpt::write(int row, int column, const QVariant &value)
{
    if (!m_worksheet)
        return false;

    // 写入指定单元格的值
    m_worksheet->querySubObject("Cells(int,int)", row, column)->setProperty("Value2", value);
    return true;
}

void ExcelOpt::slots_exception(int code, const QString &source, const QString &desc, const QString &help)
{

}

main.cpp 

#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>

#include "excelopt.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

	ExcelOpt objExcel;
	objExcel.open("C:\\Users\\roson\\Desktop\\test.xlsx");
	qDebug() << objExcel.read(1, 1).toString();
	objExcel.write(5, 2, QString("roson"));
	qDebug() << "write finish";
	objExcel.save();

    QtWidgetsApplication1 w;
    w.show();
    return a.exec();
}

1.1 注意事项(非常重要)

(1)

运行上面的代码的时候,很可能会出现运行异常,错误信息的格式如下:

QAxBase: Error calling IDispatch member SaveAs: Exception thrown by server

​ Code : -2146827284
​ Source : Microsoft Excel
​ Description: Microsoft Excel ???D://24ED7000?? ???:
​ Help : xlmain11.chm
 

其中“Code”的值会因为错误类型的不同而不同,可以去网上查阅这个错误代码所指代的含义。

上面这个错误代码“-2146827284”一般是因为Excel表格文件的路径不对造成的,我们在传参时,一定要用文件的绝对路径,这样就可以有效的避免上面的错误,切记!!!

(2)

如果在程序运行时,报错QAxBase: Error calling IDispatch member ActiveSheet: Unknown error,或者Excel表格突然弹出激活、许可协议等界面,则说明你的office没有激活,用激活工具激活office后就好了

(3)

有的人会出现读取Excel内容可以成功,但是在写入数据的时候遇到了问题,写进去的东西为空。经过排查是因为office和wps的原因,主要是property的Value值的问题。

office支持的是  

setProperty("Value", value)


然而要在装有wps中写入成功就需要把value属性改为Value2

setProperty("Value2", value)    

Value2 wps 和 office中都可以使用。
 

(4)

使用QtCreator时,我们要使用QAxObject,是需要在.pro文件中添加: QT += axcontainer,使用VS开发时,也需要添加这个模块,否则编译不过的。

2.Qt Xlsx插件

QtXlsx是一个可以读取和写入Excel文件的第三方库。它不需要Microsoft Excel,可以在Qt5支持的任何平台上使用。该库可以用来:
(1)创建一个新的.xlsx文件
(2)读取.xlsx文件内容
(3)往.xlsx文件写入内容

官网:http://qtxlsx.debao.me/

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

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

相关文章

【Python 身份证JSON数据读取】——身份证前六位地区码对照表文件(最全版-JSON文件)

点个赞留个关注吧&#xff01;&#xff01; 1、生成身份证前六位地区码对照表JSON文件 2、python 读取JSON文件 提取码【1234】 json文件下载 废话不多说&#xff0c;先上效果图 一、生成身份证json数据文件 先去百度搜索地区身份证号码前6位查询 ,然后进入网站控制台界面&…

经常会采坑的javascript原型应试题

一&#xff0e; 前言 原型和原型链在面试中历来备受重视&#xff0c;经常被提及。说难可能也不太难&#xff0c;但要真正完全理解&#xff0c;吃透它&#xff0c;还是要多下功夫的。 下面为大家简单阐述我对原型和原型链的理解&#xff0c;若是觉得有说的不对的地方&#xff…

必备技能,MySQL 查找并删除重复行

本文讲述如何查找数据库里重复的行。这是初学者十分普遍遇到的问题。方法也很简单。这个问题还可以有其他演变&#xff0c;例如&#xff0c;如何查找“两字段重复的行”&#xff08;#mysql IRC 频道问到的问题&#xff09; 如何查找重复行 第一步是定义什么样的行才是重复行。…

碳酸钾碱性溶液除钙镁软化树脂

碳酸钾是重要的基本无机化工、医药、轻工原料之一&#xff0c;主要用于光学玻璃、电焊条、电子管、电视显像管、灯泡、印染、染料、油墨、照相药品、泡花碱、聚酯、炸药、电镀、制革、陶瓷、建材、水晶、钾肥皂及药物的生产。用作气体吸附剂&#xff0c;干粉灭火剂&#xff0c;…

Spring Boot 整合 Groovy 脚本,实现动态编程

Groovy简介 Groovy 是增强 Java 平台的唯一的脚本语言。它提供了类似于 Java 的语法&#xff0c;内置映射&#xff08;Map&#xff09;、列表&#xff08;List&#xff09;、方法、类、闭包&#xff08;closure&#xff09;以及生成器。脚本语言不会替代系统编程语言&#xff…

「Redis数据结构」哈希对象(Hash)

「Redis数据结构」哈希对象&#xff08;Hash&#xff09; 文章目录「Redis数据结构」哈希对象&#xff08;Hash&#xff09;一、概述二、编码ZipListHashTable三、编码转换一、概述 Redis中hash对象是一个string类型的field和value的映射表&#xff0c;hash特别适合用于存储对…

RabbitMQ:消息模型

RabbitMQ 提供了 6 种消息模型&#xff0c;分别为&#xff1a;单生产单消费模型&#xff08;Hello World&#xff09;、消息分发模型&#xff08;Work queues&#xff09;、Fanout 消息订阅模式&#xff08;Publish/Subscribe&#xff09;、Direct 路由模式&#xff08;Routing…

基于JSP的手工艺品在线网站

摘 要 在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括手工艺品在线网站的网络应用&#xff0c;在外国手工艺品已经是很普遍的方式&#xff0c;不过国内的手工艺品可能还处于起步阶段。手工艺品在线网站具有在线下单功能。手…

详解vue中watch的用法

前言 说到 vue 中的 watch 方法&#xff0c;大家可能首先想到&#xff0c;它是用来监听数据的变化&#xff0c;一旦数据发生变化可以执行一些其他的操作。但是 watch 的操作可不止如此&#xff0c;本章就带大家一起深剖细析 vue 中的 watch 方法。 watch&#xff1f; 因为 vue…

DocuWare平台——用于文档管理和工作流程自动化的内容服务平台详细介绍(上)

DocuWare平台——用于文档管理和工作流程自动化的内容服务平台 成功实现办公自动化所需的一切 DocuWare 是一个先进的平台&#xff0c;可让您集中、快速、有效地管理、处理和利用业务信息。 我们的文档管理和工作流程解决方案的各项功能可以集成到任何 IT 系统中&#xff0c;…

源码解析:从 kubelet、容器运行时看 CNI 的使用

这是 Kubernetes 网络学习的第三篇笔记。 深入探索 Kubernetes 网络模型和网络通信认识一下容器网络接口 CNI&#xff08;本篇&#xff09;源码分析&#xff1a;从 kubelet、容器运行时看 CNI 的使用从 Flannel 学习 Kubernetes VXLAN 网络Cilium CNI 与 eBPF... 在上一篇中&…

web前端期末大作业 基于HTML+CSS+JavaScript程序员个人博客模板(web学生作业源码)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

翻译: ChatGPT 的激发敬畏、恐惧、特技和试图绕过其护栏的尝试

来自 OpenAI 的新聊天机器人正在激发敬畏、恐惧、特技和试图绕过其护栏的尝试。 以下是 DALL-E 2 在给出提示时生成的内容&#xff0c;“采用 AI 聊天机器人形式的分布式语言超级大脑。” “A distributed linguistic superbrain that takes the form of an A.I. chatbot.” 信…

WPS文件转Excel文件怎么转?建议看看这些方法

小伙伴们平时在接收文件的时候&#xff0c;有没有发现有些文件是以WPS格式进行保存的。这种格式的文件&#xff0c;如果没有使用相关的软件是没办法直接打开的。这种时候&#xff0c;其实我们可以将WPS转成其它office格式就可以打开它&#xff0c;进行编辑了。那你们知道WPS转E…

面试官:你说说Springboot的启动过程吧(5万字分析启动过程)

文章目录前言一、Springboot是什么二、启动流程2.1 构建Spring Boot项目2.2 启动的日志2.3 启动流程分析说明2.3.1 第一部分&#xff1a;SpringApplication的构造函数A、webApplicationType&#xff08;web应用类型&#xff09;B、引导注册初始化器C、设置初始化器D、设置监听器…

嵌入式开发-STM32硬件SPI驱动TFT屏

嵌入式开发-STM32硬件SPI驱动TFT屏这次用到的TFT屏CubeMX设置代码编写增加的内容需要注意问题代码下载这次用到的TFT屏 现在的TFT屏幕已经很便宜了&#xff0c;65536色屏幕&#xff0c;2.8英寸&#xff0c;分辨率320X240的液晶屏才20元&#xff0c;我为了图省事&#xff0c;多配…

[附源码]Nodejs计算机毕业设计基于JAVA快递配送平台Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

SpringBoot整合GitLab-CI实现持续集成

写在前面 &#x1f341;个人主页&#xff1a;微枫Micromaple ✨本期专栏&#xff1a;《0到1项目搭建》欢迎订阅学习~ &#x1f4cc;源码获取&#xff1a;GitCode、GitHub、码云Gitee 持续更新中&#xff0c;别忘了 star 喔~ 在企业开发过程中&#xff0c;我们开发的功能或者是修…

python之筛选图像中是否存在黑白背景

python之筛选图像中是否存在黑白背景 紧接上篇文章的需求&#xff0c;需要进行功能增加 某些图片存在背景丢失问题&#xff0c;出现黑白背景现象&#xff0c;这种需要排查&#xff0c;同样交给了自动化处理。 这次不比上次了&#xff0c;我搜罗了一堆资料&#xff0c;全是什么…

【实时数仓】DWD层需求分析及实现思路、idea环境搭建、实现DWD层处理用户行为日志的功能

文章目录一 DWD层需求分析及实现思路1 分层需求分析2 每层的职能3 DWD层职能详细介绍&#xff08;1&#xff09;用户行为日志数据&#xff08;2&#xff09;业务数据4 DWD层数据准备实现思路二 环境搭建1 创建maven工程2 修改配置文件&#xff08;1&#xff09;添加依赖&#x…