1.Qt操作Excel封装了很多功能,接口详细,注释丰富。
1.1.0.0更新到1.0.1,①更新读取单元格样式。②更新列数转换英文字母超过26累加字母
#ifndef EXCELTHREAD_H
#define EXCELTHREAD_H
#define VERSION "Excel Version V-1.0.1"
#include
#include
#include
#include
#include
#include
struct TableCellAttr {
int fillColor;//填充色/*无色 = -4142,自动 = -4105,黑色 = 1,褐色 = 53,橄榄 = 52,深绿 = 51,深青 = 49,深蓝 = 11,靛蓝 = 55,灰色80 = 56,深红 = 9,橙色 = 46,深黄 = 12,绿色 = 10,青色 = 14,蓝色 = 5,蓝灰 = 47,灰色50 = 16,红色 = 3,浅橙色 = 45,酸橙色 = 43,海绿 = 50,水绿色 = 42,浅蓝 = 41, 紫罗兰 = 13,灰色40 = 48,粉红 = 7,金色 = 44,黄色 = 6,鲜绿 = 4,青绿 = 8,天蓝 = 33,梅红 = 54,灰色25 = 15,玫瑰红 = 38,茶色 = 40,浅黄 = 36,浅绿 = 35,浅青绿 = 34,淡蓝 = 37,淡紫 = 39,白色 = 2*/
int border;//边框(=1 虚线;=2实线;=-4238 粗实线(一般粗);=4实线(很粗))
int fontColor;//字体颜色 = fillColor注释
int fontSize;//字体大小
QString fontStr;//字体
bool isItalic;//斜体
bool isBoldface;//粗体
bool isUnderline;//下划线
bool isWrapText;//自动换行
bool isAutoFitRow; //自适应行高
int cellFormat;//单元格格式 1文本 2日期 3数字 4货币 5百分比
TableCellAttr()
: fillColor(-1)
, border(-1)
, fontColor(-1)
, fontSize(-1)
, fontStr("")
, isItalic(false)
, isBoldface(false)
, isUnderline(false)
, isWrapText(false)
, isAutoFitRow(false)
, cellFormat(-1)
{}
};
class ExcelThread : public QObject
{
Q_OBJECT
public:
explicit ExcelThread(QObject *parent = nullptr);
~ExcelThread();
private slots:
void init();
public:
//打开excel
bool OpenExcel(const QString filePath);
/*----------工作表----------*/
//切换工作表
void switchSheet(const int sheetIndex);
bool switchSheet(const QString sheetName);
//获取当前工作表
int getCurrentSheetIndex();
QString getCurrentSheetName();
//获取所有工作表
QStringList getAllSheetName();
//增加工作表
void addSheet(const QString sheetName);
//删除工作表
bool delSheet(const QString sheetName);
void delSheet(const int sheetindex);
/*--------单元格数据--------*/
//获取行数列数
bool getRowAndColumn(int &row, int &column);
int getRow();
int getColumn();
//获取excel所有数据
bool getExcelAllContent(QList<QStringList>& allData);
bool getExcelAllContent(QList<QStringList>& allData, QList<QList<TableCellAttr>>& allDataStyle);
//插入数据
bool insertFileData(const int row, const int column, const QString data);
bool insertFileData(const int row, const int column, const QString data,
const TableCellAttr tableCellAttr); //row and column >=1
//一行行插入效率快
bool insertFileData(const int row, const int column, const QList<QVariant> dataList,
const TableCellAttr tableCellAttr = TableCellAttr());
//清除内容和样式
bool clearDataAndStyle(const int row, const int column);
//删除一行
void delRow(const int row);
//删除一列
void delColumn(const int column);
//单元格合并
bool cellMerge(const int beginRow, const int beginColumn, const int endRow,
const int endColumn, const bool isMergeCells = true);
//修改单元格行高和行宽
bool setHighAndWidth(const int row, const int column, const int high,
const int width, QAxObject* worksheet);
//修改列宽
void setColumnWidth(const int column, int width);
//修改行高
void setRowHeight(const int row, int height);
//操作完成保存
void writeFinishSave();
private:
//数据样式修改
void setCellStyle(const TableCellAttr tableCellAttr, QAxObject* cell);
TableCellAttr readCellStyle(QAxObject* cell);
//列数转换英文字母超过26累加字母
QString numberConvertCellStr(int size);
private:
QList<QStringList> m_DataList;
QString m_WriteFile;
QAxObject* m_Excel; //excel程序
QAxObject* m_WorkBooks; //excel所有工作薄
QAxObject* m_WorkBook; //excel文件对象
QAxObject* m_WorkSheets; //所有模板
int m_SheetIndex;
};
#endif // EXCELTHREAD_H
#include "excelthread.h"
#include "windows.h"
ExcelThread::ExcelThread( QObject *parent)
: QObject(parent)
, m_Excel(nullptr)
, m_SheetIndex(1)
{
qDebug() << VERSION;
init();
}
ExcelThread::~ExcelThread()
{
qDebug() << "excel quit";
if (m_Excel == nullptr) {
return;
}
delete m_Excel;
m_Excel = NULL;
}
void ExcelThread::init()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
m_Excel = new QAxObject("Excel.Application");
m_Excel->dynamicCall("SetVisible(bool Visible)", false);
m_Excel->setProperty("DisplayAlert", false);
}
bool ExcelThread::OpenExcel(const QString filePath)
{
if (!QFileInfo(filePath).exists()) {
qDebug() << filePath << "file no exists";
return false;
}
m_WorkBooks = m_Excel->querySubObject("WorkBooks");
m_WorkBook = m_WorkBooks->querySubObject("Open(const QString&)", filePath);
if (!m_WorkBook)
{
qDebug() << "m_WorkBook Error";
return false;
}
m_WorkSheets = m_WorkBook->querySubObject("Sheets");
return true;
}
void ExcelThread::switchSheet(const int sheetIndex)
{
m_SheetIndex = sheetIndex;
if (sheetIndex <= 0) {
m_SheetIndex = 1;
}
}
bool ExcelThread::switchSheet(const QString sheetName)
{
if (sheetName.isEmpty()) return false;
QStringList sheetNameList = getAllSheetName();
int index = sheetNameList.indexOf(sheetName);
if (index != -1) {
m_SheetIndex = index + 1;
}
return false;
}
int ExcelThread::getCurrentSheetIndex()
{
return m_SheetIndex;
}
QString ExcelThread::getCurrentSheetName()
{
QAxObject* sheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
return sheet->dynamicCall("Name").toString();
}
QStringList ExcelThread::getAllSheetName()
{
int count = m_WorkSheets->dynamicCall("Count").toInt();
QStringList sheetNameList;
for (int i = 1; i <= count; ++i) {
QAxObject* sheet = m_WorkSheets->querySubObject("Item(int)", i);
sheetNameList << sheet->dynamicCall("Name").toString();
}
return sheetNameList;
}
void ExcelThread::addSheet(const QString sheetName)
{
m_WorkSheets->querySubObject("Add()");
QAxObject* workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
workSheet->setProperty("Name", sheetName);
}
bool ExcelThread::delSheet(const QString sheetName)
{
if (sheetName.isEmpty()) return false;
QStringList sheetNameList = getAllSheetName();
int index = sheetNameList.indexOf(sheetName);
if (index != -1) {
QAxObject* sheet = m_WorkSheets->querySubObject("Item(int)", index);
sheet->dynamicCall("delete");
}
return false;
}
void ExcelThread::delSheet(const int sheetindex)
{
QAxObject* sheet = m_WorkSheets->querySubObject("Item(int)", sheetindex);
sheet->dynamicCall("delete");
}
bool ExcelThread::getRowAndColumn(int &row, int &column)
{
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* usedrange = workSheet->querySubObject("UsedRange");
if (!usedrange) {
qDebug() << "usedrange error";
return false;
}
QAxObject *rows, *columns;
rows = usedrange->querySubObject("Rows");
columns = usedrange->querySubObject("Columns");
row = rows->property("Count").toInt();
column = columns->property("Count").toInt();
return true;
}
int ExcelThread::getRow()
{
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* usedrange = workSheet->querySubObject("UsedRange");
if (!usedrange) {
qDebug() << "usedrange error";
return false;
}
QAxObject *rows;
rows = usedrange->querySubObject("Rows");
int row = rows->property("Count").toInt();
return row;
}
int ExcelThread::getColumn()
{
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* usedrange = workSheet->querySubObject("UsedRange");
if (!usedrange) {
qDebug() << "usedrange error";
return false;
}
QAxObject *columns;
columns = usedrange->querySubObject("Columns");
int column = columns->property("Count").toInt();
return column;
}
bool ExcelThread::getExcelAllContent(QList<QStringList> &allData)
{
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
int row, column;
if (getRowAndColumn(row, column)) {
for (int i = 1; i <= row; ++i) {
QStringList data;
for (int j = 1; j <= column; ++j) {
QAxObject* cell = workSheet->querySubObject("Cells(int, int)", i, j);
data << cell->dynamicCall("Value2()").toString();
}
allData << data;
}
}
else {
return false;
}
return true;
}
bool ExcelThread::getExcelAllContent(QList<QStringList> &allData, QList<QList<TableCellAttr> > &allDataStyle)
{
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
int row, column;
if (getRowAndColumn(row, column)) {
for (int i = 1; i <= row; ++i) {
QStringList data;
QList<TableCellAttr> dataStyle;
for (int j = 1; j <= column; ++j) {
QAxObject* cell = workSheet->querySubObject("Cells(int, int)", i, j);
data << cell->dynamicCall("Value2()").toString();
dataStyle << readCellStyle(cell);
}
allData << data;
allDataStyle << dataStyle;
}
}
else {
return false;
}
return true;
}
bool ExcelThread::insertFileData(const int row, const int column, const QString data)
{
int setRow = row;
int setColumn = column;
if (setRow == 0) setRow = 1;
if (setColumn == 0) setColumn = 1;
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Cells(int, int)", setRow, setColumn);
cell->dynamicCall("SetValue(conts QVariant&)", data);
return true;
}
bool ExcelThread::insertFileData(const int row, const int column, const QString data, const TableCellAttr tableCellAttr)
{
int setRow = row;
int setColumn = column;
if (setRow == 0) setRow = 1;
if (setColumn == 0) setColumn = 1;
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Cells(int, int)", setRow, setColumn);
setCellStyle(tableCellAttr, cell);
cell->dynamicCall("SetValue(conts QVariant&)", data);
return true;
}
bool ExcelThread::insertFileData(const int row, const int column, const QList<QVariant> dataList, const TableCellAttr tableCellAttr)
{
int setRow = row;
int setColumn = column;
if (setRow == 0) setRow = 1;
if (setColumn == 0) setColumn = 1;
QString cellStr;
cellStr.append(numberConvertCellStr(setColumn));
cellStr.append(QString::number(setRow));
cellStr.append(":");
cellStr.append(numberConvertCellStr(dataList.size() + setColumn - 1));
cellStr.append(QString::number(setRow));
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Range(QString)", cellStr);
setCellStyle(tableCellAttr, cell);
cell->dynamicCall("SetValue(conts QVariant&)", dataList);
return true;
}
void ExcelThread::setCellStyle(const TableCellAttr tableCellAttr, QAxObject *cell)
{
if (tableCellAttr.fillColor != -1) {
QAxObject* temp = cell->querySubObject("Interior");
temp->setProperty("ColorIndex", tableCellAttr.fillColor);
}
if (tableCellAttr.border != -1) {
QAxObject* temp = cell->querySubObject("Borders");
temp->setProperty("Weight", tableCellAttr.border);
}
if (tableCellAttr.fontColor != -1) {
QAxObject* temp = cell->querySubObject("Font");
temp->setProperty("ColorIndex", tableCellAttr.fontColor);
}
if (tableCellAttr.fontSize != -1) {
QAxObject* temp = cell->querySubObject("Font");
temp->setProperty("Size", tableCellAttr.fontSize);
}
if (tableCellAttr.fontStr != "") {
QAxObject* temp = cell->querySubObject("Font");
temp->setProperty("Name", tableCellAttr.fontStr);
}
if (tableCellAttr.isItalic) {
QAxObject* temp = cell->querySubObject("Font");
temp->setProperty("Italic", tableCellAttr.isItalic);
}
if (tableCellAttr.isBoldface) {
QAxObject* temp = cell->querySubObject("Font");
temp->setProperty("Bold", tableCellAttr.isBoldface);
}
if (tableCellAttr.isUnderline) {
QAxObject* temp = cell->querySubObject("Font");
temp->setProperty("UnderLine", tableCellAttr.isUnderline);
}
if (tableCellAttr.isWrapText) {
QAxObject* temp = cell;
temp->setProperty("WrapText", tableCellAttr.isWrapText);
}
if (tableCellAttr.isAutoFitRow) {
QAxObject* temp = cell;
temp->dynamicCall("AutoFit()");
}
if (tableCellAttr.cellFormat != -1) {
switch (tableCellAttr.cellFormat) {
case 1:
cell->setProperty("NumberFormatLocal", "@");
break;
case 2:
cell->setProperty("NumberFormatLocal", "yyyy/mm/dd");
break;
case 3:
cell->setProperty("NumberFormatLocal", "#,##0.00");
break;
case 4:
cell->setProperty("NumberFormatLocal", "#,##0.00");
break;
case 5:
cell->setProperty("NumberFormatLocal", "#0.00%");
break;
default:
cell->setProperty("NumberFormatLocal", "@");
break;
}
}
}
TableCellAttr ExcelThread::readCellStyle(QAxObject *cell)
{
if (cell->isNull()) return TableCellAttr();
TableCellAttr tableCellAttr;
QAxObject* temp = cell->querySubObject("Interior");
tableCellAttr.fillColor = temp->dynamicCall("ColorIndex").toInt();
temp = cell->querySubObject("Borders");;
tableCellAttr.border = temp->dynamicCall("Weight").toInt();
temp = cell->querySubObject("Font");;
tableCellAttr.fontColor = temp->dynamicCall("ColorIndex").toInt();
temp = cell->querySubObject("Font");;
tableCellAttr.fontSize = temp->dynamicCall("Size").toInt();
temp = cell->querySubObject("Font");;
tableCellAttr.fontStr = temp->dynamicCall("Name").toString();
temp = cell->querySubObject("Font");;
tableCellAttr.isItalic = temp->dynamicCall("Italic").toBool();
temp = cell->querySubObject("Font");;
tableCellAttr.isBoldface = temp->dynamicCall("Bold").toBool();
temp = cell->querySubObject("Font");;
tableCellAttr.isUnderline = temp->dynamicCall("UnderLine").toBool();
tableCellAttr.isWrapText = cell->dynamicCall("WrapText").toBool();
tableCellAttr.isAutoFitRow = cell->dynamicCall("AutoFit()").toBool();
QString cellFormat = cell->dynamicCall("NumberFormatLocal").toString();
if (cellFormat.contains("yyyy")) {
tableCellAttr.cellFormat = 2;
}
else if (cellFormat.contains("0.00_")) {
tableCellAttr.cellFormat = 3;
}
else if (cellFormat.contains("??#")) {
tableCellAttr.cellFormat = 4;
}
else if (cellFormat.contains("0.00%")) {
tableCellAttr.cellFormat = 5;
}
else {
tableCellAttr.cellFormat = 1;
}
return tableCellAttr;
}
QString ExcelThread::numberConvertCellStr(int size)
{
QString str;
if (size > 26 && size <= 255) {
int number1 = 0;
while (size % 26 != 0) {
size--;
number1++;
}
int number2 = size / 26;// 整数求商
str.append(QChar(number2 - 1 + 'A'));
str.append(QChar((number1 - 1) + 'A'));
return str;
}
else {
return QString(QChar(size -1 + 'A'));
}
}
bool ExcelThread::clearDataAndStyle(const int row, const int column)
{
int setRow = row;
int setColumn = column;
if (setRow == 0) setRow = 1;
if (setColumn == 0) setColumn = 1;
QAxObject *workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Cells(int, int)", setRow, setColumn);
cell->querySubObject("ClearContents");
return true;
}
void ExcelThread::delRow(const int row)
{
QAxObject* workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Rows(int)", row);
cell->querySubObject("Delete");
}
void ExcelThread::delColumn(const int column)
{
QAxObject* workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Columns(int)", column);
cell->querySubObject("Delete");
}
bool ExcelThread::cellMerge(const int beginRow, const int beginColumn, const int endRow, const int endColumn, const bool isMergeCells)
{
int setBeginRow = beginRow;
int setBeginColumn = beginColumn;
if (setBeginRow == 0) setBeginRow = 1;
if (setBeginColumn == 0) setBeginColumn = 1;
int setEndRow = endRow;
int setEndColumn = endColumn;
if (setEndRow == 0) setEndRow = 1;
if (setEndColumn == 0) setEndColumn = 1;
QString cellStr;
cellStr.append(numberConvertCellStr(setBeginColumn));
cellStr.append(QString::number(setBeginRow));
cellStr.append(":");
cellStr.append(numberConvertCellStr(setEndColumn));
cellStr.append(QString::number(setEndRow));
qDebug() << cellStr;
QAxObject* workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Range(QString)", cellStr);
cell->setProperty("VerticalAlignment", -4108);
cell->setProperty("MergeCells", isMergeCells);
return true;
}
bool ExcelThread::setHighAndWidth(const int row, const int column, const int high, const int width, QAxObject *worksheet)
{
}
void ExcelThread::setColumnWidth(const int column, int width)
{
QString cellStr;
cellStr.append(numberConvertCellStr(column));
cellStr.append(":");
cellStr.append(numberConvertCellStr(column));
QAxObject* workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Range(QString)", cellStr);
cell->setProperty("ColumnWidth", width);
}
void ExcelThread::setRowHeight(const int row, int height)
{
QString cellStr;
cellStr.append('A');
cellStr.append(QString::number(row));
QAxObject* workSheet = m_WorkSheets->querySubObject("Item(int)", m_SheetIndex);
QAxObject* cell = workSheet->querySubObject("Range(QString)", cellStr);
QAxObject* temp = cell->querySubObject("Rows");
temp->setProperty("RowHeight", height);
}
void ExcelThread::writeFinishSave()
{
m_WorkBook->dynamicCall("Save()");
m_Excel->dynamicCall("Quit(void)", false);
delete m_WorkSheets;
delete m_WorkBook;
delete m_WorkBooks;
m_WorkSheets = NULL;
m_WorkBook = NULL;
m_WorkBooks = NULL;
}
1.ExcelThread excelWrite;//建议全局,init比较慢
2.OpenExcel; //每次操作都打开
3.insertFileData; //插入数据
4.writeFinishSave();操作完成一定要保存,会清空所有open的WorkBook