Qt读写Excel--QXlsx通过Document对象操作工作表3

本文详细介绍了如何通过Qt的QXlsx库读写Excel文件,包括获取工作表名称、创建、插入、重命名、复制和移动工作表,以及设置活动工作表。示例代码展示了如何在实际项目中应用这些功能并确保数据保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Qt读写Excel–QXlsx通过Document对象操作工作表3🌍

更多精彩内容
👉个人内容分类汇总 👈
👉Qt读写Excel–QXlsx基本使用1👈
👉Qt读写Excel–QXlsx编译为静态库2👈
👉Qt读写Excel–QXlsx通过Document对象操作工作表3👈

1、概述🧭

  • QXlsx是一个可以读写Excel文件的库。不依赖office以及wps组件,可以在Qt5支持的任何平台上使用;

  • 使用方式

    1. QXlsx可以编译为动态库使用(使用动态库不用每次的编译,也可以让项目代码量更少,不用一打开工程就几十个文件);
    2. 直接将QXlsx.pri加入代码中使用(我比较推荐直接使用源码,因为QXlsx的注释信息基本在cpp文件中,可以通过阅读源码和注释来学习QXlsx的功能,当然,如果你已经熟悉了QXlsx的使用方式那编译成库使用会更方便,可以使工程的代码量变少);
  • 本文中实现的功能:

    1. 查询打开的Excel中所有可用的工作表(Sheet)名称;
    2. 创建指定名称的工作表(Sheet),自动添加到最末尾,支持ST_WorkSheet、ST_ChartSheet两种类型;
    3. 在指定位置插入一个新的指定名称的工作表(Sheet),支持ST_WorkSheet、ST_ChartSheet两种类型;
    4. 将某个工作表(Sheet)设置为当前活动工作表,并写入数据(ST_WorkSheet类型);
    5. 将指定名称的工作表(Sheet)重命名为一个新的名称,不改变其它因素;
    6. 将指定名称的工作表(Sheet)拷贝为一个新的指定名称的工作表,两个工作表内容相同;
    7. 将指定名称的工作表(Sheet)移动到指定位置;
    8. 删除指定名称的工作表(Sheet)。

2、准备工作🌋

  • 👉👉👉👉👉👉👉看前几章内容。

3、函数说明🗻

注意:执行了操作要保存才生效。⛔

  • QStringList sheetNames() const
    • 功能说明: 查询Excel中所有的工作表(Sheet)名称;
    • 返回值: 所有工作表的名称列表;
  • bool addSheet(const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet)
    • 功能说明: 在末尾创建一个名称为name,类型为type的工作表;
    • 参数name: 创建的工作表的名称;
    • 参数type: 创建的工作表的类型,可省略;
      • ST_WorkSheet:表格工作表
      • ST_ChartSheet:图表工作表
      • ST_DialogSheet:还不支持
      • ST_MacroSheet:还不支持
    • 返回值: 创建成功则返回true,失败返回false;
      • 如果名称已存在则创建失败;
      • 如果是ST_DialogSheet、ST_MacroSheet也创建失败;(注意这种创建失败有bug,创建失败后输入的name会被保存,下次不能再创建这个名称的工作表,不过不影响使用, 修复方法:xlsxworkbook.cpp文件中的Q_ASSERT(false);下一行添加return sheet;即可)
  • bool insertSheet(int index, const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet)
    • 功能说明: 在指定位置插入工作表,可设置工作表名称和类型
    • 参数index: 插入工作表的位置,如果>=0则在开始位置插入工作表,如果0<index<sheet总数则在指定位置插入工作表;
    • 参数name: 工作表名称;
    • 参数type: 工作表类型;
    • 返回值: 插入成功返回true,失败返回false;
      • 失败原因与addSheet相同;
      • 如果插入工作表位置>工作表总数则插入失败;
  • bool selectSheet(const QString &name)
    • 功能说明: 将指定名称的工作表设置未活动工作表(可编辑);
    • 参数name: 工作表名称;
    • 返回值: 设置成功返回true,失败返回false;
      • 如果指定名称的工作表不存在则设置失败;
  • bool renameSheet(const QString &oldName, const QString &newName)
    • 功能说明: 将名为oldName的工作表重命名未newName;
    • 参数oldName: 已有工作表名称;
    • 参数newName: 重命名后的工作表名称;
    • 返回值: 重命名成功返回true,失败返回false;
      • 如果oldName不存在则重命名失败;
      • 如果newName已存在则重命名失败;
      • 如果oldName等于newName则重命名失败;
  • bool copySheet(const QString &srcName, const QString &distName = QString())
    • 功能说明: 将指定的srcName工作表拷贝为distName,两个工作表内容相同;
    • 参数srcName: 已有的需要拷贝的工作表名称;
    • 参数distName: 拷贝后的工作表名称;
    • 返回值: 拷贝成功返回true,失败返回false;
      • 如果srcName不存在则拷贝失败;
      • 如果distName已存在则拷贝失败;
      • 如果srcName等于distName则拷贝失败;
  • bool moveSheet(const QString &srcName, int distIndex)
    • 功能说明: 根据输入的工作表名称,将工作表移动到指定位置;
    • 参数srcName: 需要移动的工作表名称;
    • 参数distIndex: 需要将工作表移动到的位置,distIndex<=0则移动到开始位置,distIndex>=sheet总数则移动到最后位置,如果0< distIndex <sheet总数则移动到指定位置;
    • 返回值: 移动成功返回true,失败返回false;
      • 如果需要移动的工作表名称不存在则失败;
  • bool deleteSheet(const QString &name)
    • 功能说明: 删除指定名称的工作表;
    • 参数name: 需要参数的工作表名称;
    • 返回值: 删除成功返回true,失败返回false;
      • 如果指定名称的工作表不存在则返回失败。

4、示例代码⛲

4.1 .h文件🌄

#ifndef TEST2_H
#define TEST2_H

#include <QWidget>
#include "xlsxdocument.h"

namespace Ui {
class Test2;
}

class Test2 : public QWidget
{
    Q_OBJECT

public:
    explicit Test2(QWidget *parent = nullptr);
    ~Test2();

private slots:
    void on_but_open_clicked();

    void on_but_querySheet_clicked();

    void on_but_addSheet_clicked();

    void on_but_insert_clicked();

    void on_but_select_clicked();

    void on_but_rename_clicked();

    void on_but_close_clicked();

    void on_but_copy_clicked();

    void on_but_move_clicked();

    void on_but_delete_clicked();

private:
    Ui::Test2 *ui;

    QXlsx::Document* m_xlsx = nullptr;
};

#endif // TEST2_H

4.2 .cpp文件🌇

#include "test2.h"
#include "ui_test2.h"
#include <QDebug>
#include <QMetaEnum>
#include "xlsxabstractsheet.h"

QXLSX_USE_NAMESPACE            // 添加Xlsx命名空间
#define EXCEL_NAME "./1.xlsx"  // 本demo中用到的excel文件路径文件名

Test2::Test2(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Test2)
{
    ui->setupUi(this);

    this->setWindowTitle("QXlsx中通过Document对象操作工作表Demo");
}

Test2::~Test2()
{
    on_but_close_clicked();
    delete ui;
}

#if 0            // 使用到的函数
QStringList sheetNames() const;
bool addSheet(const QString &name = QString(),
              AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
bool insertSheet(int index, const QString &name = QString(),
                 AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet);
bool selectSheet(const QString &name);
bool renameSheet(const QString &oldName, const QString &newName);
bool copySheet(const QString &srcName, const QString &distName = QString());
bool moveSheet(const QString &srcName, int distIndex);
bool deleteSheet(const QString &name);
#endif

/**
 * @brief 打开Excel
 */
void Test2::on_but_open_clicked()
{
    if(!m_xlsx)
    {
        m_xlsx = new Document(EXCEL_NAME, this);        // 打开EXCEL_NAME文件,将所有数据读取到内存中,然后关闭excel文件
    }
    if(m_xlsx->load())  // 判断文件是否打开成功(也可以使用isLoadPackage)
    {
        qInfo() << "excel打开成功!";
        // 基于范围的for从容器中获取迭代器。但是因为容器不是const迭代器,所以迭代器将是非的const,这显然足以让容器分离
        const QList<QWidget*> objects =  this->findChildren<QWidget*>();
        for(auto object: objects)
        {
            object->setEnabled(true);
        }
    }
    else
    {
        qWarning() << "excel打开失败!";
    }
}

/**
 * @brief 释放Excel内存
 */
void Test2::on_but_close_clicked()
{
    if(m_xlsx)
    {
        delete m_xlsx;
        m_xlsx = nullptr;
        const QList<QWidget*> objects =  this->findChildren<QWidget*>();
        for(auto object: objects)
        {
            object->setEnabled(false);
        }
        ui->widget1->setEnabled(true);
        ui->but_open->setEnabled(true);
    }
}

/**
 * @brief 查询Excel中所有的工作表(Sheet)名称
 */
void Test2::on_but_querySheet_clicked()
{
    ui->com_sheets->clear();
    ui->com_sheets->addItems(m_xlsx->sheetNames());
}

/**
 * @brief 创建不同类型的工作表
 *        QXlsx 的SheetType定义了四种类型,但是目前只支持ST_WorkSheet, ST_ChartSheet两种;
 *        如果创建了不支持的两种在Debug模式下会报错(Q_ASSERT断言),在Release下会返回失败;
 *        注意:这里有一个小bug
 *        由于还不支持ST_DialogSheet和ST_MacroSheet;
 *        如果在Release模式下如果创建了ST_DialogSheet或者ST_MacroSheet将会失败,
 *        而Q_ASSERT在Release下如果失效则会导致sheetNames添加未创建的sheetName;
 *
 */
void Test2::on_but_addSheet_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    AbstractSheet::SheetType type = (AbstractSheet::SheetType)ui->com_sheetType->currentIndex();
    bool ret = m_xlsx->addSheet(strName, type);         // 创建一个新的工作表,参数二可以省略
    if(ret && m_xlsx->save())                           // 执行完操作后需要保存到原有Excel中,不保存则无效
    {
        qInfo() << QString("创建工作表:%1  %2 成功!").arg(strName).arg(type);
    }
    else
    {
        qWarning() << QString("创建工作表:%1  %2 失败!").arg(strName).arg(type);
    }
}

/**
 * @brief 在指定位置插入工作表,可设置工作表名称和类型
 */
void Test2::on_but_insert_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    AbstractSheet::SheetType type = (AbstractSheet::SheetType)ui->com_sheetType->currentIndex();
    int index = ui->spin_index->value();
    bool ret = m_xlsx->insertSheet(index, strName, type);
    if(ret && m_xlsx->save())
    {
        qInfo() << QString("在%1位置插入工作表:%2  %3 成功!").arg(index).arg(strName).arg(type);
    }
    else
    {
        qWarning() << QString("在%1位置插入工作表:%2  %3 失败!").arg(index).arg(strName).arg(type);
    }
}

/**
 * @brief 将输入名称的工作表设置为活动工作表,并写入数据,如果工作表不存在或者不是ST_WorkSheet类型则不写入
 */
void Test2::on_but_select_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    bool ret = m_xlsx->selectSheet(strName);          // 将strName设置为活动工作表
    if(ret)
    {
        qInfo() << QString("设置活动工作表%1成功!").arg(strName);
        AbstractSheet::SheetType type = m_xlsx->currentSheet()->sheetType();   // 获取当前工作表的类型
        if(type == AbstractSheet::ST_WorkSheet)
        {
            ret = m_xlsx->write(1, 1, "设置获取工作表!");
            if(ret && m_xlsx->save())
            {
                qInfo() << "将数据写入选择的工作表成功!";
            }
            else
            {
                qInfo() << "将数据写入选择的工作表失败!";
            }
        }
        else
        {
            qInfo() << "其它类型sheet,不写入数据";
        }
    }
    else
    {
        qWarning() << QString("设置活动工作表%1失败,可能不存在!").arg(strName);
    }
}

/**
 * @brief 重命名sheet
 */
void Test2::on_but_rename_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    QString strNewName = ui->line_newSheetName->text();
    if(strNewName.isEmpty())
    {
        qWarning() << "新的工作表名称不能为空!";
        return;
    }
    bool ret = m_xlsx->renameSheet(strName, strNewName);
    if(ret && m_xlsx->save())
    {
        qInfo() << QString("将%1重命名为%2成功!").arg(strName, strNewName);
    }
    else
    {
        qWarning() << QString("将%1重命名为%2失败!").arg(strName, strNewName);
    }
}

/**
 * @brief 将指定的strName工作表拷贝为strNewName,如果strNewName已存在则拷贝失败
 */
void Test2::on_but_copy_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    QString strNewName = ui->line_newSheetName->text();
    if(strNewName.isEmpty())
    {
        qWarning() << "新的工作表名称不能为空!";
        return;
    }
    bool ret = m_xlsx->copySheet(strName, strNewName);       // 开始拷贝工作表
    if(ret && m_xlsx->save())
    {
        qInfo() << QString("将%1拷贝为%2成功!").arg(strName, strNewName);
    }
    else
    {
        qWarning() << QString("将%1拷贝为%2失败!").arg(strName, strNewName);
    }
}

/**
 * @brief 根据输入的工作表名称,将工作表移动到指定位置,如果工作表不存在或移动到当前位置则失败
 *        移动位置从0开始,如果大于sheet总数则移动到最后位置,如果小于0则移动到最开始位置
 */
void Test2::on_but_move_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    int index = ui->spin_index->value();
    bool ret = m_xlsx->moveSheet(strName, index);        // 开始移动工作表位置
    if(ret && m_xlsx->save())
    {
        qInfo() << QString("将%1移动到%2位置成功!").arg(strName).arg(index);
    }
    else
    {
        qWarning() << QString("将%1移动到%2位置失败!").arg(strName).arg(index);
    }
}

/**
 * @brief 删除指定名称的工作表,如果指定名称的工作表不存在则返回失败
 */
void Test2::on_but_delete_clicked()
{
    QString strName = ui->line_sheetName->text();
    if(strName.isEmpty())
    {
        qWarning() << "工作表名称不能为空!";
        return;
    }
    bool ret = m_xlsx->deleteSheet(strName);        // 开始删除
    if(ret && m_xlsx->save())
    {
        qInfo() << QString("删除工作表%1成功!").arg(strName);
    }
    else
    {
        qWarning() << QString("删除工作表%1失败!").arg(strName);
    }
}

5、实现效果🎡

  • 功能较多,没有一一演示

    在这里插入图片描述

6、源代码🏠

gitee
github

⛹🏋🚴🤸🤸‍♂️🤼🤾

<think>好的,我现在要帮用户解决关于QXlsx分页的问题。用户提到想了解QXlsx分页的实现方法和示例。首先,我需要确认QXlsx这个库是否支持分页功能。根据之前的知识,QXlsx是一个用于处理Excel文件的Qt库,但它的文档可能不是很详细,所以需要查证。 首先,我会回忆一下QXlsx的基本功能。QXlsx主要用于读写Excel文件,支持单元格操作、样式设置、公式等。分页功能通常指的是在打印时设置分页符,或者在Excel中显示分页预览。在Excel中,分页符可以通过页面布局中的分页符设置来实现,那么在QXlsx中是否有对应的API呢? 接下来,我需要查找QXlsx的相关文档或示例。可能的关键词是“QXlsx分页符”或“QXlsx page break”。假设在文档中找到了QXlsx::PageBreak类,或者相关的方法,比如添加水平或垂直分页符。例如,addHorizontalPageBreak和addVerticalPageBreak方法,这些可能在Worksheet类中。 然后,考虑如何编写示例代码。用户可能需要一个简单的例子,演示如何在特定的行或列添加分页符。比如,在第10行后添加水平分页符,或者在第5列后添加垂直分页符。代码的结构可能包括创建QXlsx::Document对象,获取Worksheet指针,然后调用添加分页符的方法。 另外,需要注意分页符的位置是否正确。例如,Excel中的行和列是从1开始的,还是从0开始?QXlsx的API是否遵循同样的索引方式?这可能会影响示例代码的正确性,需要确认。 还要考虑保存文件后的验证步骤。用户生成Excel文件后,需要打开它查看分页符是否生效,可能在页面布局视图下检查。这部分可能需要提醒用户在Excel中手动查看,或者使用QXlsx的其他功能来验证。 如果发现QXlsx的文档不明确,可能需要参考其GitHub仓库的issue或示例代码。例如,是否有其他用户提到过分页符的使用,或者官方示例中有没有相关代码。假设在某个示例中找到使用addPageBreak的方法,那么就可以基于此编写代码。 最后,整理步骤:创建文档,获取工作表,添加分页符,保存文件。并给出示例代码,同时说明如何验证分页是否成功。可能还需要提到注意事项,比如行号和列号的起始索引,以及不同Excel版本的支持情况。 现在,检查是否遗漏了用户可能的其他需求,比如动态分页,根据内容自动分页。但用户当前的问题可能更基础,所以先提供手动添加分页符的方法。如果有进一步的优化或高级功能,可以在相关问题中提及。 总结回答的结构:先介绍分页符的概念,在QXlsx中的实现方法,给出代码示例,注意事项,以及验证步骤。最后生成相关问题,帮助用户深入了解更多内容。</think>QXlsx是一个用于操作Excel文件的Qt库,支持创建、修改和读取.xlsx文件。关于分页功能的实现,主要通过设置分页符(Page Break)控制打印或预览时的分页效果。以下是具体实现方法和示例: --- ### **分页实现方法** 1. **手动添加分页符** 使用`QXlsx::Worksheet`类的`addPageBreak`方法,在指定行或列插入分页符: ```cpp QXlsx::Document xlsx; QXlsx::Worksheet *sheet = xlsx.currentWorksheet(); // 在第10行后添加水平分页符 sheet->addPageBreak(QXlsx::PageBreak::Horizontal, 10); // 在第5列后添加垂直分页符 sheet->addPageBreak(QXlsx::PageBreak::Vertical, 5); ``` 2. **自动分页设置** 通过页面布局参数(如纸张方向、边距)间接影响分页效果: ```cpp sheet->setPageOrientation(QPageLayout::Landscape); // 横向纸张 sheet->setPageMargins(QMarginsF(1.5, 1.5, 1.5, 1.5)); // 边距(英寸) ``` --- ### **完整示例代码** ```cpp #include <QCoreApplication> #include <QXlsx> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QXlsx::Document xlsx; QXlsx::Worksheet *sheet = xlsx.currentWorksheet(); // 填充测试数据(1~20行) for (int row = 1; row <= 20; ++row) { sheet->write(row, 1, "Row " + QString::number(row)); } // 在第10行后添加水平分页符 sheet->addPageBreak(QXlsx::PageBreak::Horizontal, 10); // 保存文件 xlsx.saveAs("output.xlsx"); return a.exec(); } ``` --- ### **验证分页效果** 1. 用Excel打开生成的`output.xlsx`文件。 2. 进入「视图」→「分页预览」,观察第10行下方是否显示分页符虚线。 --- ### **注意事项** - 分页符位置基于行号或列号的索引(从1开始)。 - Excel的渲染效果可能因版本差异略有不同[^1]。 ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mahuifa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值