QT-功能--使用QAxObject和QAxBase将tableview或tablewidget数据导入导出为Excel

mac2024-05-25  57

此中解决方式是为了将tableview和tablewidget中的数据进行导出为Excel文件和将Excel文件导入为tableview和tablewidget中。故将其构建成了一个封装类。附一封装好了的类文件导入导出类封装

1,使用操作Excel文件的类

为了能调用系统中的Excel应用(以office2016为例)在项目工程文件中,添加如下

QT += axcontainer

2,构建一个名叫ExcelEngine的类。在其中写入对Excel文件的执行操作

excelengine.h

1)添加所需 头文件
#include <QObject> #include <QFile> #include <QString> #include <QStringList> #include <QVariant> #include <QAxBase> #include <QAxObject> #include <QTableWidget> #include <QTableView> #include <QTableWidgetItem> #include <QDebug>
2)头文件中函数声明与变量定义
public: ExcelEngine(); ExcelEngine(QString xlsFile); ~ExcelEngine(); public: bool Open(UINT nSheet = 1,bool visible = false); //打开xls文件 bool Open(QString xlsFile,UINT nSheet = 1,bool visible = false); void Save(); //保存xls报表 void Close(); //关闭xls报表 bool SaveDataFrTable(/*QTableWidget* tableWidget,*/QTableView *tableview,QString titile); //保存数据到xls bool ReadDataToTable(/*QTableWidget* tableWidget,*/QTableView *tableview); //从xls读取数据到ui QVariant GetCellData(UINT row,UINT column); //获取指定单元数据 bool SetCellData(UINT row,UINT column,QVariant data); //修改指定单元数据 UINT GetRowCount()const; //获取行数 UINT GetColumnCount()const; //获取列数 bool IsOpen(); //检验 bool IsValid(); //检验 protected: void Clear(); private: QAxObject *pExcel; //指向整个excel应用程序 QAxObject *pWorkbooks; //指向工作簿集,excel有很多工作簿 QAxObject *pWorkbook; //指向sXlsFile对应的工作簿 QAxObject *pWorksheet; //指向工作簿中的某个sheet表单 QString sXlsFile; //xls文件路径 UINT nCurrSheet; //当前打开的第几个sheet bool bIsVisible; //excel是否可见 int nRowCount; //行数 int nColumnCount; //列数 int nStartRow; //开始有数据的行下标值 int nStartColumn; //开始有数据的列下标值 bool bIsOpen; //是否已打开 bool bIsValid; //是否有效 bool bIsANewFile; //是否是一个新建xls文件,用来区分打开的excel是已存在文件还是有本类新建的 bool bIsSaveAlready;//防止重复保存
这里因为考虑到tablewidget和tableview的不同,所以将函数中注释了不同的参数,可以对比食用。

excelengine.cpp函数体

这里将最重要的导入导出函数进行实现
1)导出为excel文件
bool ExcelEngine::SaveDataFrTable(/*QTableWidget *tableWidget,*/QTableView *tableview,QString title) { // /*第一种方法,暂时在tablewidget中可以实现*/ // QString fileName = QFileDialog::getSaveFileName(tableview, "保存",QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),"Excel 文件(*.xls *.xlsx)"); // if(fileName != NULL); // { // QStandardItemModel *model = new QStandardItemModel(); // tableview->setModel(model); // if(NULL == tableview) // { // return false; // } // if(!bIsOpen) // { // return false; // } // // int tableR = tableWidget->rowCount(); // // int tableC = tableWidget->columnCount(); // int tableR = model->rowCount(); // int tableC = model->columnCount(); // //获取表头写做第一行 // for(int i=0;i<tableC;i++) // { // //if(tableWidget->horizontalHeaderItem(i) != NULL) // if(model->horizontalHeaderItem(i) != NULL) // { // //this->SetCellData(1,i+1,tableWidget->horizontalHeaderItem(i)->text()); // this->SetCellData(1,i+1,model->horizontalHeaderItem(i)->text()); // } // } // //写数据 // for(int i=0;i<tableR;i++) // { // for(int j=0;j<tableC;j++) // { // //if(tableWidget->item(i,j) != NULL) // if(model->item(i,j) != NULL) // { // //this->SetCellData(i+2,j+1,tableWidget->item(i,j)->text()); // this->SetCellData(i+2,j+1,model->item(i,j)->text()); // } // } // } // //保存 // Save(); // return true; // } /*第二种方法,针对于tableview*/ QString fileName = QFileDialog::getSaveFileName(tableview, "保存",QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),"Excel 文件(*.xls *.xlsx)"); if (fileName!="") { QAxObject *excel = new QAxObject; if (excel->setControl("Excel.Application")) //连接Excel控件 { excel->dynamicCall("SetVisible (bool Visible)","false");//不显示窗体 excel->setProperty("DisplayAlerts", false);//不显示任何警告信息。如果为true那么在关闭是会出现类似“文件已修改,是否保存”的提示 QAxObject *workbooks = excel->querySubObject("WorkBooks");//获取工作簿集合 workbooks->dynamicCall("Add"); //新建一个工作簿 QAxObject *workbook = excel->querySubObject("ActiveWorkBook");//获取当前工作簿 QAxObject *worksheet = workbook->querySubObject("Worksheets(int)", 1); int i,j; //QTableView 获取列数 int colcount=tableview->model()->columnCount(); int rowcount = tableview->model()->rowCount(); QAxObject *cell,*col; //标题行 cell=worksheet->querySubObject("Cells(int,int)", 1, 1); cell->dynamicCall("SetValue(const QString&)", title); cell->querySubObject("Font")->setProperty("Size", 18); //调整行高 worksheet->querySubObject("Range(const QString&)", "1:1")->setProperty("RowHeight", 30); //合并标题行 QString cellTitle; cellTitle.append("A1:"); cellTitle.append(QChar(colcount - 1 + 'A')); cellTitle.append(QString::number(1)); QAxObject *range = worksheet->querySubObject("Range(const QString&)", cellTitle); range->setProperty("WrapText", true); range->setProperty("MergeCells", true); range->setProperty("HorizontalAlignment", -4108);//xlCenter range->setProperty("VerticalAlignment", -4108);//xlCenter //列标题 for(i=0;i<colcount;i++) { QString columnName; columnName.append(QChar(i + 'A')); columnName.append(":"); columnName.append(QChar(i + 'A')); col = worksheet->querySubObject("Columns(const QString&)", columnName); col->setProperty("ColumnWidth", tableview->columnWidth(i)/6); cell=worksheet->querySubObject("Cells(int,int)", 2, i+1); columnName=tableview->model()->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString(); cell->dynamicCall("SetValue(const QString&)", columnName); cell->querySubObject("Font")->setProperty("Bold", true); cell->querySubObject("Interior")->setProperty("Color",QColor(191, 191, 191)); cell->setProperty("HorizontalAlignment", -4108);//xlCenter cell->setProperty("VerticalAlignment", -4108);//xlCenter } //QTableView 获取表格数据部分 for(i=0;i<rowcount;i++) //行数 { for (j=0;j<colcount;j++) //列数 { QModelIndex index = tableview->model()->index(i, j); QString strdata=tableview->model()->data(index).toString(); worksheet->querySubObject("Cells(int,int)", i+3, j+1)->dynamicCall("SetValue(const QString&)", strdata); } } //画框线 QString lrange; lrange.append("A2:"); lrange.append(colcount - 1 + 'A'); //lrange.append(QString::number(table->rowCount() + 2)); lrange.append(QString::number(tableview->model()->columnCount() + 2)); range = worksheet->querySubObject("Range(const QString&)", lrange); range->querySubObject("Borders")->setProperty("LineStyle", QString::number(1)); range->querySubObject("Borders")->setProperty("Color", QColor(0, 0, 0)); //调整数据区行高 QString rowsName; rowsName.append("2:"); rowsName.append(QString::number(tableview->model()->rowCount() + 2)); range = worksheet->querySubObject("Range(const QString&)", rowsName); range->setProperty("RowHeight", 20); workbook->dynamicCall("SaveAs(const QString&)",QDir::toNativeSeparators(fileName));//保存至fileName workbook->dynamicCall("Close()");//关闭工作簿 excel->dynamicCall("Quit()");//关闭excel delete excel; excel=NULL; if (QMessageBox::question(NULL,"完成","文件已经导出,是否现在打开?",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes) { QDesktopServices::openUrl(QUrl("file:///" + QDir::toNativeSeparators(fileName))); } } else { QMessageBox::warning(NULL,"错误","未能创建 Excel 对象,请安装 Microsoft Excel。",QMessageBox::Apply); } } }
这里采用了两种不同的方式对表格文件中的数据进行在excel文件的的边框绘制和导出,方法一经检验可以在tablewidget中更好的绘制出数据,而方法二效果更显著。
2)导入Excel文件到tableview中
bool ExcelEngine::ReadDataToTable(/*QTableWidget *tableWidget,*/QTableView *tableview) { QStandardItemModel *model = new QStandardItemModel(); tableview->setModel(model); //model->setho //tableview->horizontalHeader()->setResizeMode(0,QHeaderView::Fixed); if(NULL == tableview) { return false; } //先把table的内容清空 // int tableColumn = tableWidget->columnCount(); int tablecol = tableview->model()->columnCount(); //tableWidget->clear(); tableview->clearSpans(); for(int n=0;n<tablecol;n++) { //tableWidget->removeColumn(0); tableview->model()->removeColumn(0); } int rowcnt = nStartRow + nRowCount; int columncnt = nStartColumn + nColumnCount; //获取excel中的第一行数据作为表头 QStringList headerList; for(int n = nStartColumn;n<columncnt;n++) { QAxObject* cell = pWorksheet->querySubObject("Cells(int,int)",nStartRow, n); if(cell) { headerList<<cell->dynamicCall("Value2()").toString(); } } //重新创建表头 // tableWidget->setColumnCount(nColumnCount); // tableWidget->setHorizontalHeaderLabels(headerList); model->setColumnCount(nColumnCount); model->setHeaderData(0,Qt::Horizontal,headerList); //插入新数据 for(int i=nStartRow+1,r=0;i<rowcnt;i++,r++)//行 { //tableWidget->insertRow(r); //插入新行 model->insertRow(r); for(int j=nStartColumn,c=0;j<columncnt;j++,c++)//列 { QAxObject * cell = pWorksheet->querySubObject("Cells(int,int)",i,j);//获取单元格 if(cell) { //tableWidget->setItem(r,c,new QTableWidgetItem(cell->dynamicCall("Value2()").toString())); model->setItem(r,c, new QStandardItem(cell->dynamicCall("Value2()").toString())); } } } return true; }
将导入导出功能设置为bool函数,故成功与否只有true和false
3)类调用实例
//导入 void mywidget::on_button_import_clicked() { QString fileName = QFileDialog::getOpenFileName(this,"打开",QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),"Excel 文件(*.xls *.xlsx)"); ExcelEngine excel(fileName); excel.Open(); excel.ReadDataToTable(ui->tableView); //导入到widget中 excel.Close(); } //导出 void mywidget::on_button_export_clicked() { //第二种方法成功对tableview保存 QString fileName = " "; ExcelEngine excel(fileName); excel.SaveDataFrTable(ui->tableView,"简单测试"); //导出到widget中 //第一种方法试验对tableview保存出现bug // QString filename = QFileDialog::getSaveFileName(this, "保存",QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),"Excel 文件(*.xls *.xlsx)"); // ExcelEngine excel(filename); // excel.SaveDataFrTable(ui->tableView," "); // //excel.Close(); }
如果想成功运行的话只需要忽略注释即可,由于篇幅问题,导入功能中的open和close函数这里没有给出,有兴趣的可以自己按照这个方式激发灵感写一下,或者可以去康康鄙人上传至csdn上的封装好了类封装类。

3.效果展示

这个界面由两个button和一个tableview显示区域构成,这里主要以tableview为例做主要展示,tablewidget只需要改变一下就行了。

1)导入展示

我这里有一个excel文件。直接将其导入进去

2)导出展示

4,注意

用此种方式操作的excel文件,容易使杀毒软件检测出"有程序正在修改文件"之类的提示项,建议允许或者将杀毒软件关闭,即可成功导出文件。

最新回复(0)