QTableWidget——单元格的复制、粘贴、还原

一、复制、粘贴的分类

QTableWidget单元格的内容:
主要实现单个单元格、整行、整列、多个单元格的复制粘贴
对于文本内容
主要实现内容与样式的复制粘贴
对于公式、日期、数字
实现内容递增、样式的复制粘贴

二、效果展示

1、文本内容单个单元格的复制粘贴

粘贴前
在这里插入图片描述

粘贴后
在这里插入图片描述

2、文本内容整行的复制粘贴

粘贴前
在这里插入图片描述
粘贴后
在这里插入图片描述

3、单列内容的复制粘贴

粘贴前
在这里插入图片描述
粘贴后
在这里插入图片描述

三、主要代码

1、文本内容单个单元格的复制粘贴

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "citemtypedialog.h"
#include <QMessageBox>
#include <QDebug>
#include<QKeyEvent>
using namespace std;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_table = new QTableWidget(this);
    m_table->setGeometry(10,10,800,450);
    m_table->setRowCount(5);
    m_table->setColumnCount(6);
    m_table->setContextMenuPolicy(Qt::CustomContextMenu);
    m_table->installEventFilter(this);
    m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
    init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::init()
{
    readTableData();
    createMenu();
    connect(m_table, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCellOperateMenu(QPoint)));
    connect(m_table,SIGNAL(itemDoubleClicked(QTableWidgetItem *)),this,SLOT(onItemDoubleClicked(QTableWidgetItem *)));
}

void MainWindow::createMenu()
{
    m_menu = new QMenu;
    m_menu->addAction(QString::fromLocal8Bit("合并单元格"), this, &MainWindow::onSpanCell);
    m_menu->addAction(QString::fromLocal8Bit("拆分单元格"), this, &MainWindow::onSplitCell);
    m_menu->addAction(QString::fromLocal8Bit("复制"), this, &MainWindow::onCopy);
    m_menu->addAction(QString::fromLocal8Bit("粘贴"), this, &MainWindow::onPaste);
    m_menu->addAction(QString::fromLocal8Bit("设置"), this, &MainWindow::onSet);
}

void MainWindow::createTable()
{
    int rowNum = m_table->rowCount();
    int colNum = m_table->columnCount();
    m_table->setRowCount(0);
    m_table->setColumnCount(0);

    m_table->setRowCount(rowNum);
    m_table->setColumnCount(colNum);

    for(auto& pRowInfro:m_tableInfor)
    {
        for(auto& pCol:pRowInfro.second)
        {
            if(pCol.second->rowSpan > 0||pCol.second->colSpan > 0)
            {
                m_table->setSpan(pCol.second->row, pCol.second->col, pCol.second->rowSpan , pCol.second->colSpan);
            }

            QTableWidgetItem * pItem = new QTableWidgetItem(pCol.second->data);
            QString str = QString::fromUtf8(pCol.second->style);
            QFont font;
            if (!(str.isEmpty()))
            {
               pItem->setText(pCol.second->data);

                // 设置单元格样式
                QStringList stylelist = str.split(",");
                font.setFamily(stylelist.at(0));
                font.setPointSize(stylelist.at(1).toInt());
                font.setBold(stylelist.at(2).toInt());
                pItem->setFont(font);
                QColor color(stylelist.at(3));
                pItem->setForeground(color);

                QColor bgdcolor(stylelist.at(4));
                QBrush Brush(bgdcolor);
                Brush.setStyle(Qt::SolidPattern);
                pItem->setBackground(Brush);
            }
            m_table->setItem(pCol.second->row, pCol.second->col,pItem);
        }
    }
}

void MainWindow::readTableData()
{
    int row;
    TableItemInfor* infor;
    for(row = 0;row< 5;row++)
    {
        std::map<int,TableItemInfor*> inforMap;
        for(int col = 0; col< 6;col++)
        {
            infor = new TableItemInfor;
            QString text = QString::number(col);
            infor->row = row;
            infor->col = col;
            infor->data = "";
            inforMap.insert(std::make_pair(col, infor));
        }
        m_tableInfor.insert(std::make_pair(row, inforMap));
    }
    createTable();
}

void MainWindow::onSpanCell()
{
    QModelIndexList list = m_table->selectionModel()->selectedIndexes();
    if (list.size() < 2)
    {
        QMessageBox::warning(this, "单元格合并", "所选中单元格中为单个单元格,无法合并", "确定");
        return;
    }

    int minRow = 0;
    int maxRow = 0;
    int minCol = 0;
    int maxCol = 0;

    QList<QTableWidgetSelectionRange> vec = m_table->selectedRanges();

    if (vec.size() > 0)
    {
        minRow = vec[0].topRow();
        maxRow = vec[0].topRow();
        minCol = vec[0].leftColumn();
        maxCol = vec[0].rightColumn();
    }

    for (auto v : vec)
    {
        if (minRow > v.topRow())
        {
            minRow = v.topRow();
        }
        if (maxRow < v.bottomRow())
        {
            maxRow = v.bottomRow();
        }

        if (minCol > v.leftColumn())
        {
            minCol = v.leftColumn();
        }
        if (maxCol < v.rightColumn())
        {
            maxCol = v.rightColumn();
        }
    }

    int rowSpan = (maxRow - minRow) + 1;
    int colSpan = (maxCol - minCol) + 1;
    m_table->setSpan(minRow, minCol, rowSpan, colSpan);
    for(auto& pRowInfro:m_tableInfor)
    {
        if(pRowInfro.first==minRow)
        {
            for(auto& pColInfro:pRowInfro.second)
            {
                if(pColInfro.first==minCol)
                {
                    pColInfro.second->rowSpan = rowSpan;
                    pColInfro.second->colSpan = colSpan;
                }
            }
        }
    }
    //m_table->setCurrentCell(minRow, minCol,QItemSelectionModel::Deselect);
    m_table->setCurrentCell(minRow, minCol,QItemSelectionModel::Select);
}

void MainWindow::onSplitCell()
{
    qDebug()<< m_table->currentRow()<< m_table->currentColumn();
    QList<QTableWidgetSelectionRange> vec = m_table->selectedRanges();
    if (vec.size() < 2)
    {
        QMessageBox::warning(this, QString::fromLocal8Bit("拆分表格失败"), QString::fromLocal8Bit("单元格已是最小单元,不可再进行拆分"), QString::fromLocal8Bit("确定"));
        return;
    }
    int row,col;
    for (auto i : vec)
    {
        row = i.topRow();
        col = i.leftColumn();
        for(auto& pRowInfro:m_tableInfor)
        {
            if( pRowInfro.first == row )
            {
                for(auto& pColInfro:pRowInfro.second)
                {
                    if(pColInfro.first == col)
                    {
                        pColInfro.second->rowSpan = 0;
                        pColInfro.second->colSpan = 0;
                    }
                }
            }
        }
    }
    createTable();
}

void MainWindow::onCellOperateMenu(QPoint p)
{
    m_menu->exec(QCursor::pos());
}

void MainWindow::onCopy()
{
    m_cpyInfor.clear();
    //获取选中信息
    QList<QTableWidgetSelectionRange> tableList = m_table->selectedRanges();
    if(tableList.size() <= 0)
    {
        return;
    }

     int colNum;    //列号
     int rowNum;    //行号
    //判断选择的数量、行、列
    if(1 == tableList.size())
    {
        colNum = tableList.at(0).leftColumn();
        rowNum = tableList.at(0).topRow();

        //获取单元个内容
      TableItemInfor* infor = m_tableInfor[rowNum][colNum];
       if(!infor)
       {
           return;
       }
      m_cpyInfor.push_back(infor);
    }

    qDebug()<<"onCopy";
}

void MainWindow::onPaste()
{
    int curRow = m_table->currentRow();
    int curCol = m_table->currentColumn();

    if(m_cpyInfor.size() > 1)
    {
        //暂时只处理单个内容复制
        return;
    }
    //修改原有内容
    m_tableInfor[curRow][curCol]->data = m_cpyInfor[0]->data;

    memcpy(m_tableInfor[curRow][curCol]->style,m_cpyInfor[0]->style,sizeof(m_cpyInfor[0]->style));
    m_tableInfor[curRow][curCol]->colSpan = m_cpyInfor[0]->colSpan;
    m_tableInfor[curRow][curCol]->rowSpan = m_cpyInfor[0]->rowSpan;
    createTable();
    qDebug()<<"onPaste";
}

void MainWindow::onRestore()
{
    qDebug()<<"onRestore";
}

void MainWindow::onSet()
{
    int row = m_table->currentRow();
    int col = m_table->currentColumn();
    TableItemInfor* pItemInfo = m_tableInfor.at(row).at(col);
    CItemTypeDialog dlg;
    QFont font;
    dlg.setType(pItemInfo);
    if (QDialog::Accepted == dlg.exec())
    {
        QString str = QString::fromUtf8(pItemInfo->style);
        if (!(str.isEmpty()))
        {
           QTableWidgetItem *pTableWidgetItem = m_table->currentItem();
           pTableWidgetItem->setText(pItemInfo->data);
            // 设置单元格样式
            QStringList stylelist = str.split(",");
            font.setFamily(stylelist.at(0));
            font.setPointSize(stylelist.at(1).toInt());
            font.setBold(stylelist.at(2).toInt());
            pTableWidgetItem->setFont(font);
            QColor color(stylelist.at(3));
            pTableWidgetItem->setForeground(color);

            QColor bgdcolor(stylelist.at(4));
            QBrush Brush(bgdcolor);
            Brush.setStyle(Qt::SolidPattern);
            pTableWidgetItem->setBackground(Brush);
            QString style = font.styleName() ;
        }
    }
}

void MainWindow::onItemDoubleClicked(QTableWidgetItem *item)
{

     onSet();
}

bool MainWindow::eventFilter(QObject *pObj, QEvent *pEvent)
{
    if (pObj == m_table)
    {
        if (pEvent->type() == QEvent::KeyPress)
        {
            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(pEvent);

            if (keyEvent->modifiers() == Qt::ControlModifier)
            {
                if (keyEvent->key() == Qt::Key_C)
                {
                    onCopy();
                    return true;
                }
                else if (keyEvent->key() == Qt::Key_V)
                {
                    onPaste();
                    return true;
                }
                else if (keyEvent->key() == Qt::Key_Z)
                {
                    onRestore();
                    return true;
                }

            }
        }
    }
    return QObject::eventFilter(pObj, pEvent);;
}

2、文本内容整行内容的复制粘贴(一行)

void MainWindow::onCopy()
{
    m_cpyInfor.clear();
    //获取选中信息
    QList<QTableWidgetSelectionRange> tableList = m_table->selectedRanges();
    if(tableList.size() <= 0)
    {
        return;
    }

     int colNum;    //列号
     int rowNum;    //行号
     int rowCount,colCount,currentRow;
     QList <TableItemInfor*> itemInfor;

    //判断选择的数量、行、列
    if(1 == tableList.size())
    {
        //判断单个单元格和一整行
        if(1 == tableList.at(0).rowCount() && tableList.at(0).columnCount() > 1)
        {
            m_cpyType = 0;
            rowCount = tableList.at(0).rowCount();

            //计算选中的总列数
            colCount = tableList.at(0).columnCount();
            currentRow = tableList.at(0).topRow();

            //获取相应的项数据
            for (int i = 0; i < colCount; i++)
            {
                TableItemInfor* infor;
                infor = m_tableInfor[currentRow][i];

                //合并列处理
                if (((i + 1) + infor->colSpan) >= colCount)
                {

                   itemInfor.push_back(infor);
                    break;
                }
               itemInfor.push_back(infor);
            }
             m_cpyInfor.insert(make_pair(m_cpyType,itemInfor));
        }
        else
        {
            m_cpyType = 2;
            colNum = tableList.at(0).leftColumn();
            rowNum = tableList.at(0).topRow();

            //获取单元个内容
            TableItemInfor* infor = m_tableInfor[rowNum][colNum];
            if(!infor)
            {
                return;
            }
            itemInfor.push_back(infor);
            m_cpyInfor.insert(make_pair(m_cpyType,itemInfor));
        }
    }

    qDebug()<<"onCopy";
}

void MainWindow::onPaste()
{
    int curRow = m_table->currentRow();
    int curCol = m_table->currentColumn();

    if(m_cpyInfor.size() > 1)
    {
        //暂时只处理单个内容复制
        return;
    }

    for(auto& it:m_cpyInfor)
    {
        if( 0 == it.first)
        {
            for(auto& pItem:it.second)
            {
                curCol = pItem->col;
                m_tableInfor[curRow][curCol]->data = pItem->data;
                memcpy(m_tableInfor[curRow][curCol]->style,pItem->style,sizeof(pItem->style));
                m_tableInfor[curRow][curCol]->colSpan = pItem->colSpan;
                m_tableInfor[curRow][curCol]->rowSpan = pItem->rowSpan;
            }
        }
        else if(1 == it.first)
        {
            return;
        }
        else if(2 == it.first)
        {
            m_tableInfor[curRow][curCol]->data = it.second.at(0)->data;
            memcpy(m_tableInfor[curRow][curCol]->style,it.second.at(0)->style,sizeof(it.second.at(0)->style));
            m_tableInfor[curRow][curCol]->colSpan = it.second.at(0)->colSpan;
            m_tableInfor[curRow][curCol]->rowSpan = it.second.at(0)->rowSpan;
        }
    }

    createTable();
    qDebug()<<"onPaste";
}

3、文本内容整行内容的复制粘贴(多行)

 else if(ONEROW < tableList.at(0).rowCount() && tableList.at(0).columnCount() > 1)
        {
            m_cpyType = 0;
            rowCount = tableList.at(0).rowCount();

            //计算选中的总列数
            colCount = tableList.at(0).columnCount();
            currentRow = tableList.at(0).topRow();

            //获取相应的项数据
            for(int r = 0;r < rowCount;r++)
            {
                itemInfor.clear();
                for (int i = 0; i < colCount; i++)
                {

                    TableItemInfor* infor;
                    infor = m_tableInfor[currentRow + r][i];

                    //合并列处理
                    if (((i + 1) + infor->colSpan) >= colCount)
                    {

                        itemInfor.push_back(infor);
                        cpyInfor.insert(make_pair(r,itemInfor));
                        break;
                    }
                    itemInfor.push_back(infor);
                }
                cpyInfor.insert(make_pair(r,itemInfor));
            }
            m_cpyInfor.insert(make_pair(MOREROW,cpyInfor));
        }
 
 void MainWindow::onPaste()
{
   // m_restoreInfor.clear();
    int curRow = m_table->currentRow();
    int curCol = m_table->currentColumn();
    //m_restoreInfor
    QList<TableItemInfor> reInforList;
    TableItemInfor itemInfor;
    for(auto& it:m_cpyInfor)
    {
        if( ONEROW == it.first)
        {
            for (auto& [_, pItem] : it.second)
            {
                for(int i = 0;i < pItem.size();i++)
                {
                    curCol = pItem[i]->col;
                    itemInfor = *m_tableInfor[curRow][curCol];
                    reInforList.push_front(itemInfor);
                    m_tableInfor[curRow][curCol]->data = pItem[i]->data;
                    memcpy(m_tableInfor[curRow][curCol]->style,pItem[i]->style,sizeof(pItem[i]->style));
                    m_tableInfor[curRow][curCol]->colSpan = pItem[i]->colSpan;
                    m_tableInfor[curRow][curCol]->rowSpan = pItem[i]->rowSpan;
                }
            }
        }
        else if(ONECOL == it.first)
        {
            for (auto& [row, pItem] : it.second)
            {
                for(int i = 0;i < pItem.size();i++)
                {
                    //curCol = pItem[i]->col;
                    itemInfor = *m_tableInfor[row][curCol];
                    reInforList.push_front(itemInfor);
                    m_tableInfor[row][curCol]->data = pItem[i]->data;
                    memcpy(m_tableInfor[row][curCol]->style,pItem[i]->style,sizeof(pItem[i]->style));
                    m_tableInfor[row][curCol]->colSpan = pItem[i]->colSpan;
                    m_tableInfor[row][curCol]->rowSpan = pItem[i]->rowSpan;
                }
            }
        }
        else if(MOREROW == it.first)
        {
            if(curRow == m_table->rowCount()||m_table->rowCount()- curRow < 1)
            {
                return;
            }

            int row = 0;
           //   如果使用QT的编译环境 .pro文件需要设置CONFIG += c++17
            for (auto& [_, pItem] : it.second)
            {
                if(curRow + row > m_table->rowCount())
                {
                    break;
                }
                curCol = 0;
                for(int i = 0;i < pItem.size();i++)
                {
                    itemInfor = *m_tableInfor[curRow + row][curCol];
                    reInforList.push_front(itemInfor);
                    // reInfor.push_front( m_tableInfor[curRow + row][curCol]);
                    m_tableInfor[curRow + row][curCol]->data = pItem[i]->data;
                    memcpy(m_tableInfor[curRow + row][curCol]->style,pItem[i]->style,sizeof(pItem[i]->style));
                    m_tableInfor[curRow + row][curCol]->colSpan = pItem[i]->colSpan;
                    m_tableInfor[curRow + row][curCol]->rowSpan = pItem[i]->rowSpan;
                    curCol++;
                }
                row++;
            }
        }
        else if(SINGLE == it.first)
        {
            for (auto& [_, pItem] : it.second)
            {
                for(int i = 0;i < pItem.size();i++)
                {
                    itemInfor = *m_tableInfor[curRow][curCol];
                    reInforList.push_front(itemInfor);
                    //reInfor.push_front( m_tableInfor[curRow][curCol]);
                    //curCol = pItem[i]->col;
                    m_tableInfor[curRow][curCol]->data = pItem[i]->data;
                    memcpy(m_tableInfor[curRow][curCol]->style,pItem[i]->style,sizeof(pItem[i]->style));
                    m_tableInfor[curRow][curCol]->colSpan = pItem[i]->colSpan;
                    m_tableInfor[curRow][curCol]->rowSpan = pItem[i]->rowSpan;
                }
            }

        }
    }

    createTable();
    m_restoreInfor.push_front(reInforList);
}

4、文本内容整列内容的复制粘贴(一列)

 else if (ONEROW < tableList.at(0).rowCount() && tableList.at(0).columnCount() == 1) //一整列
        {
            m_cpyType = 0;
            rowCount = m_table->rowCount();

            //计算选中的总列数
            rowCount = tableList.at(0).rowCount();
            currentCol = m_table->currentColumn();

            //获取相应的项数据
            for(int r = 0;r < rowCount;r++)
            {
                TableItemInfor* infor;
                itemInfor.clear();
                infor = m_tableInfor[ r][currentCol];

                //合并行处理
                if (((r + 1) + infor->rowSpan) >= rowCount)
                {

                    itemInfor.push_back(infor);
                    cpyInfor.insert(make_pair(r,itemInfor));
                    break;
                }
                itemInfor.push_back(infor);
                cpyInfor.insert(make_pair(r,itemInfor));
            }


            m_cpyInfor.insert(make_pair(ONECOL,cpyInfor));
        }

5、文本内容粘贴内容还原

void MainWindow::onRestore()
{
    if(m_restoreInfor.size() > 0)
    {
        for(auto& it:m_restoreInfor)
        {
            for(int i = 0 ;i< it.size();i++)
            {
                int row = it.at(i).row;
                int col = it.at(i).col;
                m_tableInfor[row][col]->data = it.at(i).data;
                memcpy(m_tableInfor[row][col]->style,it.at(i).style,sizeof(it.at(i).style));
                m_tableInfor[row][col]->colSpan = it.at(i).colSpan;
                m_tableInfor[row][col]->rowSpan = it.at(i).rowSpan;
            }
            it.clear();
            m_restoreInfor.pop_front();
            createTable();
            return;
            qDebug()<<"onRestore";
        }
    }
}

四、视频效果展示

视频1 基本复制粘贴

文本内容效果展示


视频2 多行、单列内容的粘贴复制,粘贴撤回

多行粘贴复制

五、补充

创建表格行数过多时,在操作底部单元格,在操作完成后,滑块会默认移动到顶部。
通过QTableWidget 的QScrollBar对象进行操作后保持原来位置。

/**通过下面的方法实现操作后保持原有的位置**/
 //移动滑块
 m_table->verticalScrollBar()->setValue(m_pos);
 //获取滑块位置
 m_pos = m_table->verticalScrollBar()->value(); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Liu Zz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值