此中解决方式是为了将tableview和tablewidget中的数据进行导出为Excel文件和将Excel文件导入为tableview和tablewidget中。故将其构建成了一个封装类。附一封装好了的类文件导入导出类封装
1,使用操作Excel文件的类
为了能调用系统中的Excel应用(以office2016为例)在项目工程文件中,添加如下
QT += axcontainer
2,构建一个名叫ExcelEngine的类。在其中写入对Excel文件的执行操作
excelengine.h
1)添加所需 头文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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;ihorizontalHeaderItem(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;iitem(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;iquerySubObject("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;imodel()->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;nremoveColumn(0);
tableview->model()->removeColumn(0);
}
int rowcnt = nStartRow + nRowCount;
int columncnt = nStartColumn + nColumnCount;
//获取excel中的第一行数据作为表头
QStringList headerList;
for(int n = nStartColumn;nquerySubObject("Cells(int,int)",nStartRow, n);
if(cell)
{
headerList<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;iinsertRow(r); //插入新行
model->insertRow(r);
for(int j=nStartColumn,c=0;jquerySubObject("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文件,容易使杀毒软件检测出"有程序正在修改文件"之类的提示项,建议允许或者将杀毒软件关闭,即可成功导出文件。