ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Qt操作Excel表格

2022-02-23 10:02:43  阅读:152  来源: 互联网

标签:const Qt 表格 int void Excel cell range QString


简单介绍:

文章内使用的是Windows系统的ActiveX对象(QAxObject)操作Excel。

相关参考:

微软vba开发指南:https://docs.microsoft.com/zh-cn/office/vba/api/overview/
其他人的文章:https://blog.csdn.net/fcqwin/article/details/17885557

主要操作接口

主要流程先是querySubObject() 获取某一个子对象,然后可以对其设置属性setProperty()或读取属性property(),进一步可以调用dynamicCall()来实现对其进行操作。

querySubObject:获取对象的某个属性,示例代码如下

QAxObject* range = sheet->querySubObject("Cells(int,int)", row, column);

dynamicCall:调用对象的某个方法,示例代码如下

range->dynamicCall("SetValue(const QString&)", value);

setProperty:设置对象的属性值,示例代码如下

range->setProperty("VerticalAlignment", -4108);//xlCenter

相关代码

class QTCREATOR_UTILS_EXPORT QExcel : public QObject
{
	Q_OBJECT
public:
	QExcel(QString name = "");
	~QExcel();

	void writeTitle(const QString& module, const QStringList& titles);
	void writeLineTest(int row, QVariantList pValues, UNI_UINT32 valCnt);
	QVariant readLine(int row, int column);

	QAxObject* getWorkBooks();
	QAxObject* getWorkBook();
	QAxObject* getWorkSheets();
	QAxObject* getWorkSheet();

	/**************************************************************************/
	/* 工作表                                                                 */
	/**************************************************************************/
	void selectSheet(const QString& sheetName);
	//sheetIndex 起始于 1  
	void selectSheet(int sheetIndex);
	void deleteSheet(const QString& sheetName);
	void deleteSheet(int sheetIndex);
	void insertSheet(QString sheetName);
	int getSheetsCount();
	//在 selectSheet() 之后才可调用  
	QString getSheetName();
	QString getSheetName(int sheetIndex);
	//datas是二维数组,datas的值类型是QList<QVariant>
	bool readSheet(QString sheetName, QVariantList& datas);
	bool writeSheet(QString sheetName, int startRow, int startCol, QVariantList& datas);
	bool writeSheet(QString sheetName, const int& startRow, const int& startCol, const int& endRow, const int& endCol, const QVariant& datas);

	/**************************************************************************/
	/* 单元格                                                                 */
	/**************************************************************************/
	void setCellString(int row, int column, const QString& value);
	//cell 例如 "A7"  
	void setCellString(const QString& cell, const QString& value);
	//range 例如 "A5:C7"  
	void mergeCells(const QString& range);
	void mergeCells(int topLeftRow, int topLeftColumn, int bottomRightRow, int bottomRightColumn);
	QVariant getCellValue(int row, int column);
	void clearCell(int row, int column);
	void clearCell(const QString& cell);
	void setCellDropItems(int row, int col, const QString& items);

	/**************************************************************************/
	/* 布局格式                                                               */
	/**************************************************************************/
	void getUsedRange(int* topLeftRow, int* topLeftColumn, int* bottomRightRow, int* bottomRightColumn);
	void setColumnWidth(int column, int width);
	void setRowHeight(int row, int height);
	void setCellTextCenter(int row, int column);
	void setCellTextCenter(const QString& cell);
	void setCellTextWrap(int row, int column, bool isWrap);
	void setCellTextWrap(const QString& cell, bool isWrap);
	void setAutoFitRow(int row);
	void mergeSerialSameCellsInAColumn(int column, int topRow);
	int getUsedRowsCount();
	void setCellFontBold(int row, int column, bool isBold);
	void setCellFontBold(const QString& cell, bool isBold);
	void setCellFontSize(int row, int column, int size);
	void setCellFontSize(const QString& cell, int size);
	//复制指令区域的内容到目标区域,带格式
	void copyRangeToRange(QString resource, QString target);

	/**************************************************************************/
	/* 文件                                                                   */
	/**************************************************************************/
	void save();
	void saveAs(const QString& filePath);
	void close();


	/**************************************************************************/
	/* 自定义辅助方法								                                     */
	/**************************************************************************/
	QString getRangeString(int startRow, int startCol, int endRow, int endCol);

	static bool isFileUsed(const QString& fpath);
private:
	void freeSheet();
	QString columnIntToString(int col);
private:
	QAxObject* excel;
	QAxObject* workBooks;
	QAxObject* workBook;
	QAxObject* sheets;
	QAxObject* sheet;
};
``

```cpp

QExcel::QExcel(QString name) :
	excel(nullptr),
	workBooks(nullptr),
	workBook(nullptr),
	sheets(nullptr),
	sheet(nullptr)
{
	CoInitializeEx(NULL, COINIT_MULTITHREADED);
	excel = new QAxObject(this);
	excel->setControl("Excel.Application");
	excel->dynamicCall("SetVisible (bool Visible)", "false");
	excel->setProperty("DisplayAlerts", false);
	workBooks = excel->querySubObject("Workbooks");	
	if(!name.isEmpty())
		workBooks->dynamicCall("Open(const QString&)", name);
	else
		workBooks->dynamicCall("Add");
	workBook = excel->querySubObject("ActiveWorkBook");
	sheets = workBook->querySubObject("WorkSheets");
}

QExcel::~QExcel()
{
	close();
}

void QExcel::writeTitle(const QString& module, const QStringList& titles)
{
	freeSheet();

	sheets->querySubObject("Add()");
	sheet = sheets->querySubObject("Item(int)", 1);
	sheet->setProperty("Name", module);

	for (int column =0; column < titles.size(); ++column)
	{
		QAxObject* cell = sheet->querySubObject("Cells(int,int)", 1, column + 1);
		cell->dynamicCall("SetValue(const QString&)", titles.at(column));
		delete cell;
		cell = nullptr;
	}
}

void QExcel::writeLineTest(int row, QVariantList pValues, UNI_UINT32 valCnt)
{
	for (UNI_UINT32 column = 0; column < valCnt; ++column)
	{
		QAxObject* cell = sheet->querySubObject("Cells(int,int)", row, column + 1);
		cell->dynamicCall("SetValue(const QString&)", pValues[column]);
		delete cell;
		cell = nullptr;
	}
}

QVariant QExcel::readLine(int row, int column)
{
	QVariant data;
	QAxObject* range = sheet->querySubObject("Cells(int,int)", row, column);
	//        return range->property("value");
	if (range)
	{
		data = range->dynamicCall("Value2()");
	}
	return data;
}

void QExcel::close()
{
	//关闭excel
	excel->dynamicCall("Quit()");

	delete sheet;
	delete sheets;
	delete workBook;
	delete workBooks;
	delete excel;

	excel = nullptr;
	workBooks = nullptr;
	workBook = nullptr;
	sheets = nullptr;
	sheet = nullptr;

	CoUninitialize();
}

QAxObject* QExcel::getWorkBooks()
{
	return workBooks;
}

QAxObject* QExcel::getWorkBook()
{
	return workBook;
}

QAxObject* QExcel::getWorkSheets()
{
	return sheets;
}

QAxObject* QExcel::getWorkSheet()
{
	return sheet;
}

void QExcel::selectSheet(const QString& sheetName)
{
	sheet = sheets->querySubObject("Item(const QString&)", sheetName);
}

void QExcel::deleteSheet(const QString& sheetName)
{
	QAxObject* a = sheets->querySubObject("Item(const QString&)", sheetName);
	a->dynamicCall("delete");
}

void QExcel::deleteSheet(int sheetIndex)
{
	QAxObject* a = sheets->querySubObject("Item(int)", sheetIndex);
	a->dynamicCall("delete");
}

void QExcel::selectSheet(int sheetIndex)
{
	sheet = sheets->querySubObject("Item(int)", sheetIndex);
}

void QExcel::setCellString(int row, int column, const QString& value)
{
	QAxObject* range = sheet->querySubObject("Cells(int,int)", row, column);
	range->dynamicCall("SetValue(const QString&)", value);
}

void QExcel::setCellFontBold(int row, int column, bool isBold)
{
	QString cell;
	cell.append(QChar(column - 1 + 'A'));
	cell.append(QString::number(row));

	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range = range->querySubObject("Font");
	range->setProperty("Bold", isBold);
}

void QExcel::setCellFontSize(int row, int column, int size)
{
	QString cell;
	cell.append(QChar(column - 1 + 'A'));
	cell.append(QString::number(row));

	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range = range->querySubObject("Font");
	range->setProperty("Size", size);
}

void QExcel::copyRangeToRange(QString resource, QString target)
{
	if (sheet)
	{
		QAxObject* resRange = sheet->querySubObject("Range(const QString&)", resource);
		resRange->dynamicCall("Copy");//复制指令区域内容到剪贴板
		
		QAxObject* tarRange = sheet->querySubObject("Range(const QString&)", target);//选中目标区域
		tarRange->dynamicCall("PasteSpecial");
	}
}

void QExcel::mergeCells(const QString& cell)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->setProperty("VerticalAlignment", -4108);//xlCenter  
	range->setProperty("WrapText", true);
	range->setProperty("MergeCells", true);
}

void QExcel::mergeCells(int topLeftRow, int topLeftColumn, int bottomRightRow, int bottomRightColumn)
{
	QString cell;
	cell.append(QChar(topLeftColumn - 1 + 'A'));
	cell.append(QString::number(topLeftRow));
	cell.append(":");
	cell.append(QChar(bottomRightColumn - 1 + 'A'));
	cell.append(QString::number(bottomRightRow));

	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->setProperty("VerticalAlignment", -4108);//xlCenter  
	range->setProperty("WrapText", true);
	range->setProperty("MergeCells", true);
}

QVariant QExcel::getCellValue(int row, int column)
{
	QAxObject* range = sheet->querySubObject("Cells(int,int)", row, column);
	return range->property("Value");
}

void QExcel::save()
{
	workBook->dynamicCall("Save()");
}

void QExcel::saveAs(const QString& filePath)
{
	//QDateTime current_date_time = QDateTime::currentDateTime();
	//QString current_date = current_date_time.toString("yyyy_MM_dd_hh_mm_ss");
	//if (isFileUsed(filePath))
	//{
	//	filePath == "C:\\Users\\" + current_date + ".xlsx";
	//}
	workBook->dynamicCall("SaveAs(const QString &)", QDir::toNativeSeparators(filePath));
	workBook->dynamicCall("Close(Boolean)", true);
}

int QExcel::getSheetsCount()
{
	return sheets->property("Count").toInt();
}

QString QExcel::getSheetName()
{
	return sheet->property("Name").toString();
}

QString QExcel::getSheetName(int sheetIndex)
{
	QAxObject* a = sheets->querySubObject("Item(int)", sheetIndex);
	return a->property("Name").toString();
}

bool QExcel::readSheet(QString sheetName, QVariantList& datas)
{
	selectSheet(sheetName);
	if (sheet == nullptr)
		return false;
	if (QAxObject* usedRange = sheet->querySubObject("UsedRange"))
	{
		QVariantList varRows = usedRange->dynamicCall("Value").toList();
		datas = varRows;
	}
	return true;
}

bool QExcel::writeSheet(QString sheetName, int startRow, int startCol, QVariantList& datas)
{
	selectSheet(sheetName);
	if (sheet == nullptr)
		return false;
	
	for (auto iter : datas)
	{
		QList<QVariant> rowDatas = iter.toList();
		int curCol = startCol;
		for (auto value : rowDatas)
		{
			setCellString(startRow, curCol, value.toString());
			++curCol;
		}
		++startRow;
	}
	//QString rangeCells = getRangeString(startRow, startCol, startRow + datas.size(), startCol + colCnt);
	//QAxObject* range = sheet->querySubObject("Range(const QString&)", rangeCells);
	//range->dynamicCall("SetValue(const QString&)", datas);

	return true;
}

bool QExcel::writeSheet(QString sheetName, const int& startRow, const int& startCol, const int& endRow, const int& endCol,
	const QVariant& datas)
{
	selectSheet(sheetName);
	if (sheet == nullptr)
		return false;
	QString rangeStr = getRangeString(startRow, startCol, endRow, endCol);
	QAxObject* range = sheet->querySubObject("Range(const QString&)", rangeStr);
	if (range)
	{
		bool res = range->setProperty("Value", datas);
		return res;
	}
	return true;
}

void QExcel::getUsedRange(int* topLeftRow, int* topLeftColumn, int* bottomRightRow, int* bottomRightColumn)
{
	QAxObject* usedRange = sheet->querySubObject("UsedRange");
	*topLeftRow = usedRange->property("Row").toInt();
	*topLeftColumn = usedRange->property("Column").toInt();

	QAxObject* rows = usedRange->querySubObject("Rows");
	*bottomRightRow = *topLeftRow + rows->property("Count").toInt() - 1;

	QAxObject* columns = usedRange->querySubObject("Columns");
	*bottomRightColumn = *topLeftColumn + columns->property("Count").toInt() - 1;
}

void QExcel::setColumnWidth(int column, int width)
{
	QString columnName;
	columnName.append(QChar(column - 1 + 'A'));
	columnName.append(":");
	columnName.append(QChar(column - 1 + 'A'));

	QAxObject* col = sheet->querySubObject("Columns(const QString&)", columnName);
	col->setProperty("ColumnWidth", width);
}

void QExcel::setCellTextCenter(int row, int column)
{
	QString cell;
	cell.append(QChar(column - 1 + 'A'));
	cell.append(QString::number(row));

	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->setProperty("HorizontalAlignment", -4108);//xlCenter  
}

void QExcel::setCellTextWrap(int row, int column, bool isWrap)
{
	QString cell;
	cell.append(QChar(column - 1 + 'A'));
	cell.append(QString::number(row));

	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->setProperty("WrapText", isWrap);
}

void QExcel::setAutoFitRow(int row)
{
	QString rowsName;
	rowsName.append(QString::number(row));
	rowsName.append(":");
	rowsName.append(QString::number(row));

	QAxObject* rows = sheet->querySubObject("Rows(const QString &)", rowsName);
	rows->dynamicCall("AutoFit()");
}

void QExcel::insertSheet(QString sheetName)
{
	sheets->querySubObject("Add()");
	QAxObject* a = sheets->querySubObject("Item(int)", 1);
	a->setProperty("Name", sheetName);
}

void QExcel::mergeSerialSameCellsInAColumn(int column, int topRow)
{
	int a, b, c, rowsCount;
	getUsedRange(&a, &b, &rowsCount, &c);

	int aMergeStart = topRow, aMergeEnd = topRow + 1;

	QString value;
	while (aMergeEnd <= rowsCount)
	{
		value = getCellValue(aMergeStart, column).toString();
		while (value == getCellValue(aMergeEnd, column).toString())
		{
			clearCell(aMergeEnd, column);
			aMergeEnd++;
		}
		aMergeEnd--;
		mergeCells(aMergeStart, column, aMergeEnd, column);

		aMergeStart = aMergeEnd + 1;
		aMergeEnd = aMergeStart + 1;
	}
}

void QExcel::clearCell(int row, int column)
{
	QString cell;
	cell.append(QChar(column - 1 + 'A'));
	cell.append(QString::number(row));

	clearCell(cell);
}

void QExcel::clearCell(const QString& cell)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->dynamicCall("ClearContents()");
}

void QExcel::setCellDropItems(int row, int col, const QString& items)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", getRangeString(row, col, row, col));
	QAxObject* validTion = range->querySubObject("Validation");
	//validTion->dynamicCall("Add(Type,AlertStyle,Operator,Formula1)", "xlValidateList", "xlValidAlertStop", "xlBetween", items);
	validTion->dynamicCall("Modify(int,int,int,QVariant)", 3, 1, 1, items);
	validTion->setProperty("IgnoreBlank", true);
	validTion->setProperty("InCellDropdown", true);
	validTion->setProperty("InputTitle", "test");
	//validTion->setProperty("Formula1", items);
}

int QExcel::getUsedRowsCount()
{
	QAxObject* usedRange = sheet->querySubObject("UsedRange");
	int topRow = usedRange->property("Row").toInt();
	QAxObject* rows = usedRange->querySubObject("Rows");
	int bottomRow = topRow + rows->property("Count").toInt() - 1;
	return bottomRow;
}

void QExcel::setCellString(const QString& cell, const QString& value)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->dynamicCall("SetValue(const QString&)", value);
}

void QExcel::setCellFontSize(const QString& cell, int size)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range = range->querySubObject("Font");
	range->setProperty("Size", size);
}

void QExcel::setCellTextCenter(const QString& cell)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->setProperty("HorizontalAlignment", -4108);//xlCenter  
}

void QExcel::setCellFontBold(const QString& cell, bool isBold)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range = range->querySubObject("Font");
	range->setProperty("Bold", isBold);
}

void QExcel::setCellTextWrap(const QString& cell, bool isWrap)
{
	QAxObject* range = sheet->querySubObject("Range(const QString&)", cell);
	range->setProperty("WrapText", isWrap);
}

void QExcel::setRowHeight(int row, int height)
{
	QString rowsName;
	rowsName.append(QString::number(row));
	rowsName.append(":");
	rowsName.append(QString::number(row));

	QAxObject* r = sheet->querySubObject("Rows(const QString &)", rowsName);
	r->setProperty("RowHeight", height);
}

QString QExcel::getRangeString(int startRow, int startCol, int endRow, int endCol)
{
	QString res = QString("%1%2:%3%4").arg(columnIntToString(startCol)).arg(startRow).arg(columnIntToString(endCol)).arg(endRow);
	if (startRow = endRow && startCol == endCol)
	{
		res = QString("%1%2").arg(columnIntToString(startCol)).arg(startRow);
	}
	return	res;
}

bool QExcel::isFileUsed(const QString& fpath)
{
	bool isUsed = false;

	QString fpathx = fpath + "x";

	QFile file(fpath);
	if (file.exists())
	{
		bool isCanRename = file.rename(fpath, fpathx);
		if (isCanRename == false)
		{
			isUsed = true;
		}
		else
		{
			file.rename(fpathx, fpath);
		}
	}
	file.close();

	return isUsed;
}

void QExcel::freeSheet()
{
	if (sheet)
	{
		delete sheet;
		sheet = nullptr;
	}	
}

QString QExcel::columnIntToString(int col)
{
	QString res;
	if (col / 26 > 0)
	{
		res += columnIntToString(col - 26);
	}
	else
	{
		res = QString("%1").arg(QString(col - 1 + 'A'));
	}
	return res;
}

标签:const,Qt,表格,int,void,Excel,cell,range,QString
来源: https://blog.csdn.net/qq_41806386/article/details/123082871

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有