admin 管理员组

文章数量: 887021

一、描述

本文使用QT的QAxObject方式,处理word。其中包括创建、打开、保存、另存为、添加文字、添加段落、设置字体和格式、换行、选中、光标移动、设置标题、设置二级标题格式、设置文本格式、设置段落格式、创建表格、插入题注、创建题注、删除题注、设置光标在表格位置、设置表格格式、设置单元格内容、合并单元格、插入行、插入列、在表格中插入标签、设置word方向、插入空白页、设置标签处文字、设置标签处添加文字、删除标签、拷贝另一个word中内容到光标处、插入页眉、插入页脚、插入图片的接口。
参考文献:https://learn.microsoft/zh-cn/dotnet/api/microsoft.office.interop.word?view=word-pia

二、头文件内容如下

#pragma once

#include <QObject>
#include <QAxobject>
#include <QAxWidget>

class CWordOperation  : public QObject
{
	Q_OBJECT

public:
	CWordOperation(QObject *parent = Q_NULLPTR);
	~CWordOperation();

public:
	typedef enum _HALIIGNMENT_ {
		wdHorizontalLineAlignLeft = 0,
		wdHorizontalLineAlignCenter,
		wdHorizontalLineAlignRight,
	}HAlignment;

	typedef enum _VALIIGNMENT_ {
		wdCellAlignVerticalTop = 0,
		wdCellAlignVerticalCenter,
		wdCellAlignVerticalBottom = 3,
	}VAlignment;

	typedef enum _POSITION_ {
		UP = 0,
		DOWN,
		LEFT,
		RIGHT,
	}Postion;

	enum WdOrientation {
		wdOrientPortrait = 0,
		wdOrientLandscape,
	};
public:
	/*
	 * 描述:以模板方式打开word文档操作
	 * 注意:这里不打开一个已经存在文档 以创建新文件方式打开文件;调用此函数时,最后保存如果Save则会保存失败,会弹出另存为对话框
	 * strFilePath: 模板文件的路径,用于新文档的模板名。 如果省略该参数,则使用 Normal 模板
	 * bVisable: true 在可见窗口中打开该文档。 如果此值为 false,则 Microsoft Word 或者 WPS 打开文档
	 * Return: 打开文档成功返回true,否则返回false
	*/
	bool openAsCreateFileMethod(const QString &strFilePath = QString(), bool bVisable = false);

	/*
	 * 描述:打开指定文件,函数打开的文件,可以调用save保存,且不会弹出另存为的对话框
	 * strFilePath: 需要打开的文件路径
	 * bVisable: true 在可见窗口中打开该文档。 如果此值为 false,则 Microsoft Word 或者 WPS 打开文档
	 * Return: 打开文档成功返回true,否则返回false
	 */
	bool openFile(const QString &strFilePath, bool bVisable = false);

	/*
	 * 描述:关闭word文档操作
	 */
	void close();

	/*
	 * 描述:另存为
	 * strFilePath:保存文件的全路径,如果该路径错误或者不存在将会出现另存为弹框
	 */
	void saveAs(const QString &strFilePath);

	/*
	 * 描述:保存已被保存过的文件,如果未被保存过,则会弹出另存为对话框
	 */
	void save();

#pragma region 文字段落处理
	/*
	 * 描述:在光标所在位置插入文字
	 * strText:需要插入文字的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertText(const QString &strText);

	int insertParagraphsAndTable(const QString &filePath);
	bool testParagraph(const QString &strParagraphText);

	/*
	 * 描述:添加段落设置段落为首行缩进2个字符
	 * strParagraphText:需要插入段落的文字的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool addParagraph(const QString &strParagraphText);

	/*
	 * 描述:第一次添加段落信息
	 * strParagraphText:需要插入段落的文字的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool addFristParagraph(const QString &strParagraphText);

	/*
	 * 描述:非第一次添加段落信息
	 * strParagraphText:需要插入段落的文字的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool addOtherParagraph(const QString &strParagraphText);

	/*
	 * 描述:设置字体信息
	 * selection:当前光标位置,如果为null将会默认文档中光标所在位置
	 * strFontName:字体的名称
	 * nFontSize:表示字体大大小
	 * bBold:是否是粗体
	 * bItalic:是否是斜体
	 * strFontColor:颜色参数值参考:https://learn.microsoft/en-us/previous-versions/office/developer/office-2003/aa195614(v=office.11)
	 * strUnderline:下划线的值参考: https://learn.microsoft/en-us/previous-versions/office/developer/office-2003/aa224269(v=office.11)
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setFontFromSelect(QAxObject *selection, const QString &strFontName, int nFontSize, bool bBold = false, bool bItalic = false, const QString &strFontColor = u8"wdColorBlack", const QString &strUnderline = u8"wdUnderlineNone");

	/*
	 * 描述:将光标移至末尾,选中所有内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setSelectToEnd();

	/*
	 * 描述:将光标移动至末尾,非选中
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setFouseToEnd();

	/*
	 * 描述:在目前光标位置添加文字
	 * strText:文字的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool appendText(const QString &strText);

	/*
	 * 描述:设置标题
	 * strTitleText:标题的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setTitleText(const QString &strTitleText);

	/*
	 * 描述:插入回车
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool addEnter();

	/*
	 * 描述:设置正文格式
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setBodyFormat();

	/*
	 * 描述:设置2级标题格式
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setLevel2TileFormat();

	/*
	 * 描述:设置段落格式
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setFaragraphFormat();

#pragma endregion

#pragma region 表格操作
	/*
	 * 描述:创建rowCount * columnCount表格
	 * nRowCount:创建表格的行数必须大于0
	 * nColumnCount:创建表格的列数必须大于0
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool createTable(int nRowCount, int nColumnCount);

	/*
	 * 描述:在第nTableNumber个表上面插入题注
	 * strCaptionText:题注信息
	 * nTableNumber:第几个表,必须大于0
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertCaptionTable(const QString &strCaptionText, int nTableNumber);

	/*
	 * 描述:创建题注
	 * strCaptionName:需要创建的题注名字
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool createCaption(const QString &strCaptionName);

	/*
	 * 描述:删除题注
	 * strCaptionName:需要删除的题注名称
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool deleteCaption(const QString &strCaptionName);

	/*
	 * 描述:设置光标在表格中row和column
	 * nTableNo:第几个表格
	 * nRow:该表格第nRow行
	 * nColumn:该表格第nColumn行
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setFocusPos(int nTableNo, int nRow, int nColumn);

	/*
	 * 描述:设置当前光标所在单元格的格式
	 * HAlignment:文字在水平的格式
	 * VAlignment:文字在垂直的格式
	 * strFontName:字体的名称
	 * nFontSize:表示字体大大小
	 * bBold:是否是粗体
	 * bItalic:是否是斜体
	 * strFontColor:颜色参数值参考:https://learn.microsoft/en-us/previous-versions/office/developer/office-2003/aa195614(v=office.11)
	 * strUnderline:下划线的值参考: https://learn.microsoft/en-us/previous-versions/office/developer/office-2003/aa224269(v=office.11) 
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setTableFromat(HAlignment HAlignment, VAlignment VAlignment, const QString &strFontName, int nFontSize, bool bBold = false, bool bItalic = false, const QString &strFontColor = u8"wdColorBlack", const QString &strUnderline = u8"wdUnderlineNone");

	/*
	 * 描述:在指定表格的行列中插入文字
	 * nTableNumber:第几个表格
	 * nRow:该表格第nRow行
	 * nColumn:该表格第nColumn行
	 * strText:文字内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertTableText(int nTableNumber, int nRow, int nColumn, const QString &strText);

	/*
	 * 描述:检查该点是否在指定表区域内
	 * nTableNumber:第几个表格
	 * nRow:该表格第nRow行
	 * nColumn:该表格第nColumn行
	 * bResult:检查结果
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool checkPointWithinTable(int nTableNumber, int nRow, int nColumn, bool &bResult);

	/*
	 * 描述:合并单元格 注意合并单元格时:当前运行期间 某个单元格被合并后不能再次被合并
	 * nTableNumber:第几个表格
	 * nStartRow:开始的行数
	 * nStartColumn:开始列数
	 * nEndRow:结束的行数
	 * nEndColumn:结束的列数
	 * strText:合并后的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool mergeCells(int nTableNumber, int nStartRow, int nStartColumn, int nEndRow, int nEndColumn, const QString &strText);

	/*
	 * 描述:合并单元格 注意合并单元格时:当前运行期间 某个单元格被合并后不能再次被合并
	 * nTableNumber:第几个表格
	 * nStartRow:开始的行数
	 * nStartColumn:开始列数
	 * nEndRow:结束的行数
	 * nEndColumn:结束的列数
	 * strText:合并后的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool mergeCellsOther(int nTableNumber, int nStartRow, int nStartColumn, int nEndRow, int nEndColumn, const QString &strText);

	/*
	 * 描述:插入行
	 * nTableNumber:第几个表格
	 * nRow:表示第nRow行插入
	 * pos:插入行在选中行的方向
	 * nRowsNumber:插入的数量
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertRow(int nTableNumber, int nRow, Postion pos, int nRowsNumber);

	/*
	 * 描述:插入列
	 * nTableNumber:第几个表格
	 * nColumn:表示第nColumn列插入
	 * pos:插入行在选中行的方向
	 * nRowsNumber:插入的数量
	 * Return: 如果中间出现问题返回false, 否则返回true
	 * 注意:插入列时会导致超出页边距
	 */
	bool insertColumn(int nTableNumber, int nColumn, Postion pos, int nColumnsNumber);

	/*
	 * 描述:在表格中添加标签
	 * nTableNumber:第几个表格
	 * nRow:该表格第nRow行
	 * nColumn:该表格第nColumn行
	 * strLabelName:被插入的标签名字
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertLabelInTable(int nTableNumber, int nRow, int nColumn, const QString &strLabelName);

#pragma endregion

	/*
	 * 描述:设置word页面的方向
	 * nOrient:方向
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setPageOrient(WdOrientation nOrient);

	/*
	 * 描述:插入空白页(下一页分节符)
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertNewPage();

	/*
	 * 描述:插入空白页(分页符)该方法可能多一个空行
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertPage();

	/*
	 * 描述:在标签处添加指定文字(覆盖原有文字)
	 * strBookmark:标签名称
	 * strText:该标签处的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool setBookMarksText(const QString &strBookmark, const QString &strText);

	/*
	 * 描述:在标签处原有文字后面添加指定文字
	 * strBookmark:标签名字
	 * strText:标签处原来文字后面添加的内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool appendBookMarksText(const QString &strBookmark, const QString &strText);

	/*
	 * 描述:删除指定标签
	 * strBookmark:被删除的标签名
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool deletBookMark(const QString &strBookmark);

	/*
	 * 描述:在文件中插入另一个文件的内容
	 * strFilePath:另一个文件的路径
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertOtherFileContent(const QString &strFilePath);

	/*
	 * 描述:添加页眉
	 * strHeaderText:页眉内容
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertHeader(const QString &strHeaderText);

	/*
	 * 描述:添加页脚 wps能够插入成功,office会插到页眉处
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertFooter();

	/*
	 * 描述:插入图片
	 * strPicturePath:图片路径
	 * Return: 如果中间出现问题返回false, 否则返回true
	 */
	bool insertPicture(const QString &strPicturePath);

private:
	void clearValue();

private:
	QAxObject *m_pWord;			// 指向整个word应用程序
	QAxObject *m_pWordDoc;		// 激活的文档

	bool m_bOpen;				// 文档是否打开,true表示打开,false表示未打开

	bool m_bFristParagraph;		// 是否是第一次添加段落
};

三、源文件

#include "CWordOperation.h"

#include <QDebug>
#include <QDir>
#include <QFile>
#include <thread>

CWordOperation::CWordOperation(QObject *parent)
	: QObject(parent)
	, m_pWord(nullptr)
	, m_pWordDoc(nullptr)
	, m_bOpen(false)
	, m_bFristParagraph(true)
{
}

CWordOperation::~CWordOperation()
{
}

bool CWordOperation::openAsCreateFileMethod(const QString &strFilePath, bool bVisable)
{
	if (m_bOpen == true) {
		return true;
	}

	clearValue();

	m_pWord = new QAxObject();

	bool bFlag = m_pWord->setControl(u8"Word.Application");			// 连接office的word控件
	if (bFlag == false) {
		// 如果连接失败,则连接wps
		bFlag = m_pWord->setControl(u8"WPS.Application");			// 连接wps控件
		if (bFlag == false) {
			return false;											// 连接word控件操作失败
		}
	}

	// 设置word界面不现实
	m_pWord->setProperty("Visible", true);						// true表示显示word界面,false表示不现实word界面

	// 获取所有的工作文档
	QAxObject *document = m_pWord->querySubObject("Documents");
	if (document == nullptr) {
		return false;												// 获取工作文档失败
	}

	do {
		if (strFilePath.isEmpty() == false) {
			QFile file(strFilePath);
			if (file.exists()) {
				document->dynamicCall("Add(const QString&)", strFilePath);		// 以strFilePath为模板创建一个word文档
				break;
			}
		}

		document->dynamicCall("Add(void)");			// 创建一个空的word文档

	} while (0);

	// 获取当前激活的文档
	m_pWordDoc = m_pWord->querySubObject(u8"ActiveDocument");
	if (m_pWordDoc == nullptr) {
		m_bOpen = false;
	}
	else {
		m_bOpen = true;
	}

	return m_bOpen;
}

bool CWordOperation::openFile(const QString & strFilePath, bool bVisable)
{
	if (m_bOpen == true) {
		return true;
	}

	clearValue();

	m_pWord = new QAxObject();

	bool bFlag = m_pWord->setControl(u8"Word.Application");			// 连接office的word控件
	if (bFlag == false) {
		// 如果连接失败,则连接wps
		bFlag = m_pWord->setControl(u8"WPS.Application");			// 连接wps控件
		if (bFlag == false) {
			return false;											// 连接word控件操作失败
		}
	}

	// 设置word界面不现实
	m_pWord->setProperty("Visible", bVisable);						// true表示显示word界面,false表示不现实word界面

	// 获取所有的工作文档
	QAxObject *document = m_pWord->querySubObject("Documents");
	if (document == nullptr) {
		return false;												// 获取工作文档失败
	}

	QFile file(strFilePath);
	if (file.exists() == false) {
		clearValue();
		qDebug() << u8"openFile is error: the file is not exist";
		return false;
	}

	m_pWordDoc = document->querySubObject(u8"Open(QString)", strFilePath);
	if (m_pWordDoc == nullptr) {
		clearValue();
		qDebug() << u8"openFile is error: Word Doc is null";
		return false;
	}

	m_bOpen = true;
	return true;
}

void CWordOperation::close()
{
	if (m_pWord != nullptr) {
		m_pWord->setProperty("DisplayAlerts", 0);			// 不显示警告或者错误
	}

	if (m_pWordDoc != nullptr) {
		m_pWordDoc->dynamicCall("Close(bool)", true);		// 关闭文档窗口
		delete m_pWordDoc;
		m_pWordDoc = nullptr;
	}

	if (m_pWord != nullptr) {
		m_pWord->dynamicCall("Quit()");
		delete m_pWord;
		m_pWord = nullptr;
	}

	m_bOpen = false;
}

void CWordOperation::saveAs(const QString & strFilePath)
{
	m_pWordDoc->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(strFilePath));
}

void CWordOperation::save()
{
	m_pWordDoc->dynamicCall("Save()", true);		// 这里最好使用true,会有提示框。否则Visible设置为false时不会弹出保存位置,就会导致卡顿。
}

bool CWordOperation::insertText(const QString & strText)
{
	// 获取光标所在位置
	QAxObject *selection = m_pWord->querySubObject("Selection");
	if (selection == false) {
		return false;
	}

	selection->dynamicCall("TypeText(const QString&)", strText);

	return true;
}

int CWordOperation::insertParagraphsAndTable(const QString & filePath)
{
	// 创建Word应用程序实例
	QAxObject* word = new QAxObject("Word.Application");
	if (!word) {
		qDebug() << "无法创建Word应用程序实例";
		return -1;
	}

	// 添加一个新文档
	QAxObject* documents = word->querySubObject("Documents");
	QAxObject* document = documents->querySubObject("Add()");
	if (!document) {
		qDebug() << "无法添加新文档";
		return -1;
	}

	// 获取文档的末尾 Range 对象
	QAxObject* range = document->querySubObject("Range()");
	if (!range) {
		qDebug() << "无法获取文档的末尾 Range 对象";
		return -1;
	}

	// 插入一个新段落并设置首行缩进
	QAxObject* paragraphFormat = range->querySubObject("ParagraphFormat");
	if (paragraphFormat) {
		paragraphFormat->dynamicCall("SetFirstLineIndent(double)", 21);
	}

	// 在新段落中插入文本
	range->dynamicCall("InsertAfter(const QString&)", u8"这是新段落的文本");

	QAxObject* paragraphs = document->querySubObject("Paragraphs");
	if (!paragraphs) {
		qDebug() << "无法获取文档的段落集合";
		return -1;
	}

	// 现在再次插入一个新的段落并设置格式
	QAxObject* newParagraph = paragraphs->querySubObject("Add()");
	if (newParagraph) {
		QAxObject* newParagraphFormat = newParagraph->querySubObject("Format");
		if (newParagraphFormat) {
			newParagraphFormat->dynamicCall("SetFirstLineIndent(double)", 21);
		}

		QAxObject* newRange = newParagraph->querySubObject("Range");
		if (newRange) {
			newRange->dynamicCall("InsertAfter(const QString&)", u8"这是第1个段落"); // 插入文本并添加回车
		}

		delete newParagraphFormat;
		delete newRange;
	}

	QAxObject* paragraphs2 = document->querySubObject("Paragraphs");
	if (!paragraphs2) {
		qDebug() << "无法获取文档的段落集合";
		return -1;
	}
	// 现在再次插入一个新的段落并设置格式
	QAxObject* newParagraph2 = paragraphs2->querySubObject("Add()");
	if (newParagraph2) {
		QAxObject* newParagraphFormat = newParagraph->querySubObject("Format");
		if (newParagraphFormat) {
			newParagraphFormat->dynamicCall("SetFirstLineIndent(double)", 21);
		}

		QAxObject* newRange = newParagraph->querySubObject("Range");
		if (newRange) {
			newRange->dynamicCall("InsertAfter(const QString&)", u8"这是第2个段落"); // 插入文本并添加回车
		}

		delete newParagraphFormat;
		delete newRange;
	}


	// 保存并关闭文档
	document->dynamicCall("SaveAs2(const QString&)", "path/to/your/document.docx");
	document->dynamicCall("Close()");

	// 退出Word应用程序
	word->dynamicCall("Quit()");

	// 清理资源
	delete document;
	delete documents;
	delete word;

	return 0;
}

bool CWordOperation::testParagraph(const QString & strParagraphText)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"testParagraph error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"testParagraph error: selection is nullptr";
		return false;
	}

	// 获取Range
	auto range = selection->querySubObject(u8"Range");
	if (range == nullptr) {
		qDebug() << u8"testParagraph error: range is nullptr";
		return false;
	}

	// 移动 Range 到前一个字符
	range->dynamicCall("MoveStart(enum WdUnits, int)", 1, -1);

	// 获取前一个字符的文本
	QString text = range->property("Text").toString();

	// 重置 Range 到原来的位置
	range->dynamicCall("MoveEnd(enum WdUnits, int)", 1, 1);

	// 判断文本是否包含换行符
	if (!(text.contains(u8"\n") || text.contains(u8"\r"))) {
		addEnter();
	}

	setFontFromSelect(selection, u8"宋体", 20, true, true, u8"wdColorBlue", u8"wdUnderlineDouble");

	selection->dynamicCall(u8"TypeText(const QString&)", strParagraphText);

	return true;
}

bool CWordOperation::addParagraph(const QString & strParagraphText)
{
	// 获取段落数量
	QAxObject *paragraphs = m_pWordDoc->querySubObject("Paragraphs");
	if (paragraphs == nullptr) {
		return false;
	}

	int count = paragraphs->property("Count").toInt();

	if (count == 0) {
		addFristParagraph(strParagraphText);
	}
	else {
		addOtherParagraph(strParagraphText);
	}

	return false;
}

bool CWordOperation::addFristParagraph(const QString & strParagraphText)
{
	// 获取文档的末尾 Range 对象
	QAxObject* range = m_pWordDoc->querySubObject("Range()");
	if (!range) {
		qDebug() << "无法获取文档的末尾 Range 对象";
		return false;
	}

	// 插入一个新段落并设置首行缩进
	QAxObject* paragraphFormat = range->querySubObject("ParagraphFormat");
	if (paragraphFormat) {
		paragraphFormat->setProperty("CharacterUnitFirstLineIndent", 2);
	}

	// 在新段落中插入文本
	range->dynamicCall("InsertAfter(const QString&)", strParagraphText);

	return true;
}

bool CWordOperation::addOtherParagraph(const QString & strParagraphText)
{
	QAxObject* paragraphs = m_pWordDoc->querySubObject("Paragraphs");
	if (!paragraphs) {
		qDebug() << "无法获取文档的段落集合";
		return false;
	}

	// 现在再次插入一个新的段落并设置格式
	QAxObject* newParagraph = paragraphs->querySubObject("Add()");
	if (newParagraph) {
		QAxObject* newParagraphFormat = newParagraph->querySubObject("Format");
		if (newParagraphFormat) {
			newParagraphFormat->setProperty("CharacterUnitFirstLineIndent", 2);
		}

		QAxObject* newRange = newParagraph->querySubObject("Range");
		if (newRange) {
			newRange->dynamicCall("InsertAfter(const QString&)", strParagraphText); // 插入文本并添加回车
		}

		delete newParagraphFormat;
		delete newRange;
	}

	return true;
}

bool CWordOperation::setFontFromSelect(QAxObject *selection, const QString &strFontName, int nFontSize, bool bBold, bool bItalic, const QString & strFontColor, const QString &strUnderline)
{
	if (selection == nullptr) {
		selection = m_pWord->querySubObject(u8"Selection");
		if (selection == nullptr) {
			qDebug() << "setFontFromSelect error: selection is nullptr";
			return false;
		}
	}

	auto font = selection->querySubObject(u8"Font");
	if (font == nullptr) {
		qDebug() << "setFontFromSelect error: Font is nullptr";
		return false;
	}

	font->setProperty(u8"Name", strFontName.isEmpty() ? u8"微软雅黑" : strFontName);
	font->setProperty(u8"Size", nFontSize);
	if (bBold == true) {
		font->setProperty(u8"Bold", -1);
		font->setProperty(u8"BoldBi", 0);
	}
	else {
		font->setProperty(u8"Bold", 0);
		font->setProperty(u8"BoldBi", -1);
	}

	if (bItalic == true) {
		font->setProperty(u8"Italic", -1);
		font->setProperty(u8"ItalicBi", 0);
	}
	else {
		font->setProperty(u8"Italic", 0);
		font->setProperty(u8"ItalicBi", 1);
	}

	font->setProperty(u8"Color", strFontColor);			// 设置字体颜色
	font->setProperty(u8"Underline", strUnderline);		// 设置划线

	return true;
}

bool CWordOperation::setSelectToEnd()
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"setSelectToEnd error: document is nullptr";
		return false;
	}

	auto content = m_pWordDoc->querySubObject(u8"Content");
	if (content == nullptr) {
		return true;
	}

	content->dynamicCall(u8"Select()");

	return true;
}

bool CWordOperation::setFouseToEnd()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setSelectToEnd error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setSelectToEnd error: selection is nullptr";
		return false;
	}

	QVariantList params;
	params.append(6);		// 设置WdUnits wdStory
	params.append(0);		// 设置WdMovementType wdMove
	selection->dynamicCall("EndOf(QVariant&, QVariant&)", params);	// 建议使用EndOf,因为WdUnits可操作性更多

	return true;
}

bool CWordOperation::appendText(const QString & strText)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"appendText error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"appendText error: selection is nullptr";
		return false;
	}

	selection->dynamicCall(u8"TypeText(const QString&)", strText);		// 写文字

	return true;
}

bool CWordOperation::setTitleText(const QString & strTitleText)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setTitleText error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setTitleText error: selection is nullptr";
		return false;
	}

	auto paragraphFormat = selection->querySubObject(u8"ParagraphFormat");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setTitleText error: paragraphFormat is nullptr";
		return false;
	}

	paragraphFormat->setProperty(u8"Alignment", u8"wdAlignParagraphCenter");		// 居中
	paragraphFormat->setProperty(u8"OutlineLevel", u8"wdOutlineLevel2");			// 二级标题
	paragraphFormat->setProperty(u8"LineSpacingRule", u8"wdLineSpace1pt5");			// 行间距1.5
	paragraphFormat->setProperty(u8"CharacterUnitFirstLineIndent", 0);				// 设置无首行缩进

	auto font = selection->querySubObject(u8"Font");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setTitleText error: font is nullptr";
		return false;
	}

	font->setProperty(u8"NameFarEast", u8"宋体");
	font->setProperty(u8"Size", 15);
	font->setProperty(u8"Bold", true);					// true表示加粗
	font->setProperty(u8"Italic", true);				// true表示斜体

	selection->dynamicCall(u8"TypeText(const QString&)", strTitleText);

	return true;
}

bool CWordOperation::addEnter()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setTitleText error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setTitleText error: selection is nullptr";
		return false;
	}

	selection->dynamicCall(u8"TypeParagraph(void)");

	return true;
}

bool CWordOperation::setBodyFormat()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setBodyFormat error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setBodyFormat error: selection is nullptr";
		return false;
	}

	auto paragraphFormat = selection->querySubObject(u8"ParagraphFormat");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setBodyFormat error: paragraphFormat is nullptr";
		return false;
	}

	paragraphFormat->setProperty(u8"Alignment", u8"wdAlignParagraphLeft");			// 左对齐
	paragraphFormat->setProperty(u8"OutlineLevel", u8"wdOutlineLevelBodyText");		// 设置正文
	paragraphFormat->setProperty(u8"LineSpacingRule", u8"wdLineSpaceDouble");		// 行间距2倍
	paragraphFormat->setProperty(u8"CharacterUnitFirstLineIndent", 0);				// 设置无首行缩进
	paragraphFormat->setProperty(u8"WidowControl", -1);

	auto font = selection->querySubObject(u8"Font");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setBodyFormat error: font is nullptr";
		return false;
	}

	font->setProperty(u8"Name", u8"宋体");
	font->setProperty(u8"Size", 12);
	font->setProperty(u8"SizeBi", 12);
	font->setProperty(u8"Bold", false);					// 取消加粗
	font->setProperty(u8"BoldBi", -1);
	font->setProperty(u8"Italic", false);				// 取消斜体
	font->setProperty(u8"ItalicBi", -1);
	font->setProperty(u8"Color", u8"wdColorBlack");		// 设置字体颜色为黑色
	font->setProperty(u8"Underline", u8"wdUnderlineNone");	// 设置无下划线

	return true;
}

bool CWordOperation::setLevel2TileFormat()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setTitleText error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setTitleText error: selection is nullptr";
		return false;
	}

	auto paragraphFormat = selection->querySubObject(u8"ParagraphFormat");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setTitleText error: paragraphFormat is nullptr";
		return false;
	}

	paragraphFormat->setProperty(u8"Alignment", u8"wdAlignParagraphCenter");		// 居中
	paragraphFormat->setProperty(u8"OutlineLevel", u8"wdOutlineLevel2");			// 二级标题
	paragraphFormat->setProperty(u8"LineSpacingRule", u8"wdLineSpace1pt5");			// 行间距1.5
	paragraphFormat->setProperty(u8"CharacterUnitFirstLineIndent", 0);				// 设置无首行缩进

	auto font = selection->querySubObject(u8"Font");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setTitleText error: font is nullptr";
		return false;
	}

	font->setProperty(u8"NameFarEast", u8"宋体");
	font->setProperty(u8"Size", 15);				// 小三
	font->setProperty(u8"SizeBi", 15);				// 小三

	font->setProperty(u8"Bold", -1);				// 加粗
	font->setProperty(u8"BoldBi", 0);


	return true;
}

bool CWordOperation::setFaragraphFormat()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setBodyFormat error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setBodyFormat error: selection is nullptr";
		return false;
	}

	auto paragraphFormat = selection->querySubObject(u8"ParagraphFormat");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setBodyFormat error: paragraphFormat is nullptr";
		return false;
	}

	paragraphFormat->setProperty(u8"Alignment", u8"wdAlignParagraphLeft");			// 左对齐
	paragraphFormat->setProperty(u8"OutlineLevel", u8"wdOutlineLevelBodyText");		// 设置正文
	paragraphFormat->setProperty(u8"LineSpacingRule", u8"wdLineSpaceDouble");		// 行间距2倍
	paragraphFormat->setProperty(u8"CharacterUnitFirstLineIndent", 2);				// 设置首行缩进2字符
	paragraphFormat->setProperty(u8"WidowControl", -1);

	auto font = selection->querySubObject(u8"Font");
	if (paragraphFormat == nullptr) {
		qDebug() << u8"setBodyFormat error: font is nullptr";
		return false;
	}

	font->setProperty(u8"Name", u8"宋体");
	font->setProperty(u8"Size", 12);
	font->setProperty(u8"SizeBi", 12);
	font->setProperty(u8"Bold", false);					// 取消加粗
	font->setProperty(u8"BoldBi", -1);
	font->setProperty(u8"Italic", false);				// 取消斜体
	font->setProperty(u8"ItalicBi", -1);
	font->setProperty(u8"Color", u8"wdColorBlack");		// 设置字体颜色为黑色
	font->setProperty(u8"Underline", u8"wdUnderlineNone");	// 设置无下划线

	return true;
}

bool CWordOperation::createTable(int nRowCount, int nColumnCount)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"createTable error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"createTable error: selection is nullptr";
		return false;
	}

	auto range = selection->querySubObject(u8"Range");
	if (range == nullptr) {
		qDebug() << u8"createTable error: range is nullptr";
		return false;
	}

	auto tables = range->querySubObject(u8"Tables");
	if (tables == false) {
		qDebug() << u8"createTable error: tables is nullptr";
		return false;
	}

	auto tableInfo = tables->querySubObject(u8"Add(QVariant,int,int,int,int)", range->asVariant(), nRowCount, nColumnCount,1,0);

	tableInfo->setProperty("Style", u8"网络型");
	// tableInfo->dynamicCall(u8"AutoFitBehavior(WdAutoFitBehavior)", u8"wdAutoFitWindow");

	return true;
}

bool CWordOperation::insertCaptionTable(const QString &strCaptionText, int nTableNumber)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"insertCaptionTable error: widget is nullptr";
		return false;
	}

	// 得到题注的集合
	auto captionLabels = m_pWord->querySubObject(u8"CaptionLabels");
	if (captionLabels == nullptr) {
		qDebug() << u8"insertCaptionTable error: captionLabels is nullptr";
		return false;
	}

	// 得到表的题注
	auto item = captionLabels->querySubObject(u8"Item(QVariant)", u8"表");
	if (item == nullptr) {	// 这里如果题注不是表可能不存在,所以应该使用Add方法先建立题注
		//qDebug() << u8"insertCaptionTable error: item is nullptr";
		//return false;
		if (createCaption(u8"表") == false) {
			return false;
		}

		return insertCaptionTable(strCaptionText, nTableNumber);
	}

	// 设置题注自动
	qDebug() << item->setProperty(u8"NumberStyle", u8"wdCaptionNumberStyleArabic");
	qDebug() << item->setProperty(u8"IncludeChapterNumber", 0);

	// 获取所有的表格
	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"insertCaptionTable error: tables is nullptr";
		return false;
	}

	if (tables->property(u8"Count").toInt() <= 0) {
		return true;	// 没有表格不能添加题注
	}

	auto table = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (table == nullptr) {
		qDebug() << u8"insertCaptionTable error: table is nullptr";
		return false;
	}

	QAxObject* range = table->querySubObject("Range");
	if (range == nullptr) {
		qDebug() << u8"insertCaptionTable error: range is nullptr";
		return false;
	}

	// 选中整个表格
	range->dynamicCall("Select()");

	// 得到光标
	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"insertCaptionTable error: selection is nullptr";
		return false;
	}

	// 插入表 题注
	QVariantList list;
	list.append(u8"表");
	list.append(strCaptionText);
	list.append(u8"");
	list.append(0);				// wdCaptionPositionAbove
	list.append(false);
	qDebug() << selection->dynamicCall("InsertCaption(QVariant,QVariant,QVariant,QVariant,QVariant)", list);

	// 将题注文字居中
	auto paragraphFotmat = range->querySubObject(u8"ParagraphFormat");
	if (paragraphFotmat == nullptr) {
		qDebug() << u8"insertCaptionTable error: paragraphFotmat is nullptr";
		return false;
	}

	paragraphFotmat->dynamicCall(u8"Alignment", HAlignment::wdHorizontalLineAlignCenter);

	// 将光标移至最后 作用防止插入数据时插入在题注上面
	setFouseToEnd();

	return true;
}

bool CWordOperation::createCaption(const QString & strCaptionName)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"createCaption error: widget is nullptr";
		return false;
	}

	// 得到题注的集合
	auto captionLabels = m_pWord->querySubObject(u8"CaptionLabels");
	if (captionLabels == nullptr) {
		qDebug() << u8"createCaption error: captionLabels is nullptr";
		return false;
	}

	auto item = captionLabels->querySubObject(u8"Item(QVariant)", strCaptionName);
	if (item != nullptr) {	// 这里如果题注存在,则返回不需要创建
		qDebug() << u8"createCaption error: item is not null";
		return true;
	}

	auto captionLabel = captionLabels->querySubObject(u8"Add(const QString&)", strCaptionName);
	if (captionLabel == nullptr) {
		return false;
	}

	/* // 测试用
	int nCount = captionLabels->property(u8"Count").toInt();

	for (int i = 1; i <= nCount; ++i) {
		auto item = captionLabels->querySubObject(u8"Item(int)", i);
		qDebug() << item->property(u8"Name").toString();
	}
	*/
	return true;
}

bool CWordOperation::deleteCaption(const QString & strCaptionName)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"createCaption error: widget is nullptr";
		return false;
	}

	// 得到题注的集合
	auto captionLabels = m_pWord->querySubObject(u8"CaptionLabels");
	if (captionLabels == nullptr) {
		qDebug() << u8"createCaption error: captionLabels is nullptr";
		return false;
	}

	auto item = captionLabels->querySubObject(u8"Item(QVariant)", strCaptionName);
	if (item == nullptr) {	// 这里如果题注不存在,则返回不需要删除
		qDebug() << u8"createCaption error: item is null";
		return true;
	}

	item->dynamicCall(u8"Delete()");

	/* // 测试用
	captionLabels = m_pWord->querySubObject(u8"CaptionLabels");

	int nCount = captionLabels->property(u8"Count").toInt();

	for (int i = 1; i <= nCount; ++i) {
		auto item = captionLabels->querySubObject(u8"Item(int)", i);
		qDebug() << item->property(u8"Name").toString();
	}
	*/
	return true;
}

bool CWordOperation::setFocusPos(int nTableNo, int nRow, int nColumn)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"setFocusPos error: m_pWordDoc is nullptr";
		return false;
	}

	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"setFocusPos error: tables is nullptr";
		return false;
	}

	int nCount = tables->property(u8"Count").toInt();
	if (nTableNo > nCount || nTableNo <= 0) {
		qDebug() << u8"setFocusPos error: The table number is invalid";
		return false;
	}

	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNo);
	if (tableInfo == nullptr) {
		qDebug() << u8"setFocusPos error: table is nullptr";
		return false;
	}

	auto rowsObject = tableInfo->querySubObject(u8"Rows");
	if (rowsObject == nullptr) {
		qDebug() << u8"setFocusPos error: rowsObject is nullptr";
		return false;
	}

	auto columnsObject = tableInfo->querySubObject(u8"Columns");
	if (columnsObject == nullptr) {
		qDebug() << u8"setFocusPos error: columnsObject is nullptr";
		return false;
	}

	int nRowCount = rowsObject->dynamicCall(u8"Count").toInt();
	int nColumnCount = columnsObject->dynamicCall(u8"Count").toInt();

	if (nRow > nRowCount) {
		qDebug() << u8"setFocusPos error: The nRow is invalid";
		return false;
	}

	if (nColumn > nColumnCount) {
		qDebug() << u8"setFocusPos error: The nColumn is invalid";
		return false;
	}

	auto tableUnit = tableInfo->querySubObject(u8"Cell(int,int)", nRow, nColumn);
	if (tableUnit == nullptr) {
		qDebug() << u8"setFocusPos error: tableUnit is nullptr";
		return false;
	}

	tableUnit->dynamicCall(u8"Select()");

	return true;
}

bool CWordOperation::setTableFromat(HAlignment HAlignment, VAlignment VAlignment, const QString & strFontName, int nFontSize, bool bBold, bool bItalic, const QString & strFontColor, const QString & strUnderline)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setTableFromat error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setTableFromat error: selection is nullptr";
		return false;
	}

	auto range = selection->querySubObject("Range");
	if (range == nullptr) {
		qDebug() << u8"setTableFromat error: range is nullptr";
		return false;
	}

	auto paragraphFotmat = range->querySubObject(u8"ParagraphFormat");
	if (paragraphFotmat == nullptr) {
		qDebug() << u8"setTableFromat error: paragraphFotmat is nullptr";
		return false;
	}

	paragraphFotmat->dynamicCall(u8"Alignment", HAlignment);

	auto cells = range->querySubObject(u8"Cells");
	if (cells == nullptr) {
		qDebug() << u8"setTableFromat error: cells is nullptr";
		return false;
	}

	cells->dynamicCall(u8"VerticalAlignment", VAlignment);

	// 设置字体风格
	setFontFromSelect(selection, strFontName, nFontSize, bBold, bItalic, strFontColor, strUnderline);

	return true;
}

bool CWordOperation::insertTableText(int nTableNumber, int nRow, int nColumn, const QString & strText)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"insertTableText error: m_pWordDoc is nullptr";
		return false;
	}

	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"insertTableText error: tables is nullptr";
		return false;
	}

	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"insertTableText error: table is nullptr";
		return false;
	}

	// 此处需要判断一下列和行的数量,否则插入超过的列时会默认最后一列,行同理
	auto rowsObject = tableInfo->querySubObject(u8"Rows");
	if (rowsObject == nullptr) {
		qDebug() << u8"insertTableText error: rowsObject is nullptr";
		return false;
	}

	auto columnsObject = tableInfo->querySubObject(u8"Columns");
	if (columnsObject == nullptr) {
		qDebug() << u8"insertTableText error: columnsObject is nullptr";
		return false;
	}

	int nRowCount = rowsObject->dynamicCall(u8"Count").toInt();
	int nColumnCount = columnsObject->dynamicCall(u8"Count").toInt();

	if (nRow > nRowCount) {
		qDebug() << u8"insertTableText error: The nRow is invalid";
		return false;
	}

	if (nColumn > nColumnCount) {
		qDebug() << u8"insertTableText error: The nColumn is invalid";
		return false;
	}

	auto tableUnit = tableInfo->querySubObject(u8"Cell(int,int)", nRow, nColumn);
	if (tableUnit == nullptr) {
		qDebug() << u8"insertTableText error: The tableUnit is invalid";
		return false;
	}

	tableUnit->querySubObject(u8"Range")->dynamicCall(u8"SetText(QString)", strText);

	return true;
}

bool CWordOperation::checkPointWithinTable(int nTableNumber, int nRow, int nColumn, bool & bResult)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"checkPointWithinTable error: m_pWordDoc is nullptr";
		return false;
	}

	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"checkPointWithinTable error: tables is nullptr";
		return false;
	}

	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"checkPointWithinTable: the table does not exist";
		bResult = false;
		return true;
	}

	// 此处需要判断一下列和行的数量,否则插入超过的列时会默认最后一列,行同理
	auto rowsObject = tableInfo->querySubObject(u8"Rows");
	if (rowsObject == nullptr) {
		qDebug() << u8"checkPointWithinTable error: rowsObject is nullptr";
		return false;
	}

	auto columnsObject = tableInfo->querySubObject(u8"Columns");
	if (columnsObject == nullptr) {
		qDebug() << u8"checkPointWithinTable error: columnsObject is nullptr";
		return false;
	}

	int nRowCount = rowsObject->dynamicCall(u8"Count").toInt();
	int nColumnCount = columnsObject->dynamicCall(u8"Count").toInt();

	if (nRow > nRowCount) {
		bResult = false;
		return true;
	}

	if (nColumn > nColumnCount) {
		bResult = false;
		return true;
	}

	bResult = true;
	return true;
}

bool CWordOperation::mergeCells(int nTableNumber, int nStartRow, int nStartColumn, int nEndRow, int nEndColumn, const QString & strText)
{
	bool bResult = false;
	if (checkPointWithinTable(nTableNumber, nStartRow, nStartColumn, bResult) == false) {
		return false;
	}

	if (bResult == false) {
		qDebug() << QString(u8"mergeCells error: table: %1 does not exist or row: %2 and column: %3 are not within table").arg(nTableNumber, nStartRow, nStartColumn);
		return false;
	}

	if (checkPointWithinTable(nTableNumber, nEndRow, nEndColumn, bResult) == false) {
		return false;
	}

	if (bResult == false) {
		qDebug() << QString(u8"mergeCells error: table: %1 does not exist or row: %2 and column: %3 are not within table").arg(nTableNumber).arg(nEndRow).arg(nEndColumn);
		return false;
	}

	// 获取表集合
	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"mergeCells error: tables is nullptr";
		return false;
	}

	// 获取指定表
	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"mergeCells: the table does not exist";
		return true;
	}

	auto startCell = tableInfo->querySubObject(u8"Cell(int,int)", nStartRow, nStartColumn);
	if (startCell == nullptr) {
		qDebug() << u8"mergeCells error: startCell is null";
		return false;
	}

	auto endCell = tableInfo->querySubObject(u8"Cell(int,int)", nEndRow, nEndColumn);
	if (endCell == nullptr) {
		qDebug() << u8"mergeCells error: endCell is null";
		return false;
	}

	startCell->dynamicCall("Merge(QVariant)", endCell->asVariant());

	int nRow = nStartRow > nEndRow ? nEndRow : nStartRow;
	int nColumn = nStartColumn > nEndColumn ? nEndColumn : nStartColumn;

	auto cellUnit = tableInfo->querySubObject(u8"Cell(int,int)", nRow, nColumn);
	if (cellUnit == nullptr) {
		qDebug() << u8"mergeCells error: cellUnit is null";
		return false;
	}

	cellUnit->querySubObject(u8"Range")->dynamicCall(u8"SetText(QString)", strText);

	return true;
}

bool CWordOperation::mergeCellsOther(int nTableNumber, int nStartRow, int nStartColumn, int nEndRow, int nEndColumn, const QString & strText)
{
	bool bResult = false;
	if (checkPointWithinTable(nTableNumber, nStartRow, nStartColumn, bResult) == false) {
		return false;
	}

	if (bResult == false) {
		qDebug() << QString(u8"mergeCells error: table: %1 does not exist or row: %2 and column: %3 are not within table").arg(nTableNumber, nStartRow, nStartColumn);
		return false;
	}

	if (checkPointWithinTable(nTableNumber, nEndRow, nEndColumn, bResult) == false) {
		return false;
	}

	if (bResult == false) {
		qDebug() << QString(u8"mergeCells error: table: %1 does not exist or row: %2 and column: %3 are not within table").arg(nTableNumber).arg(nEndRow).arg(nEndColumn);
		return false;
	}

	// 获取表集合
	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"mergeCells error: tables is nullptr";
		return false;
	}

	// 获取指定表
	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"mergeCells: the table does not exist";
		return true;
	}

	auto startCell = tableInfo->querySubObject(u8"Cell(int,int)", nStartRow < nEndRow ? nStartRow : nEndRow, nStartColumn < nEndColumn ? nStartColumn : nEndColumn);
	if (startCell == nullptr) {
		qDebug() << u8"mergeCells error: startCell is null";
		return false;
	}

	auto endCell = tableInfo->querySubObject("Cell(int,int)", nStartRow > nEndRow ? nStartRow : nEndRow, nStartColumn > nEndColumn ? nStartColumn : nEndColumn);
	if (endCell == nullptr) {
		qDebug() << u8"mergeCells error: endCell is null";
		return false;
	}

	if (startCell && endCell) {
		// 获取起始单元格的范围
		QAxObject* startRange = startCell->querySubObject("Range");

		// 获取结束单元格的范围
		QAxObject* endRange = endCell->querySubObject("Range");

		auto selection = m_pWord->querySubObject(u8"Selection");
		if (selection == nullptr) {
			qDebug() << u8"createTable error: selection is nullptr";
			return false;
		}
		selection->dynamicCall("SetRange(QVariant, QVariant)", startRange->property("Start"), endRange->property("End"));

		qDebug() << selection->querySubObject(u8"Cells")->dynamicCall(u8"Merge()");

		selection->querySubObject(u8"Range")->dynamicCall(u8"SetText(QString)", strText);
	}

	return true;
}

bool CWordOperation::insertRow(int nTableNumber, int nRow, Postion pos, int nRowsNumber)
{
	bool bResult = false;
	if (checkPointWithinTable(nTableNumber, nRow, 1, bResult) == false || pos < 0 || pos > 1) {
		return false;
	}

	// 获取表集合
	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"insertRow error: tables is nullptr";
		return false;
	}

	// 获取指定表
	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"insertRow: the table does not exist";
		return true;
	}

	auto cell = tableInfo->querySubObject(u8"Cell(int,int)", nRow, 1);
	if (cell == nullptr) {
		qDebug() << u8"insertRow error: cell is null";
		return false;
	}

	cell->dynamicCall("Select()");

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"createTable error: selection is nullptr";
		return false;
	}

	if (pos == Postion::UP) {
		selection->dynamicCall("InsertRowsAbove(int)", nRowsNumber);
	} else if (pos == Postion::DOWN) {
		selection->dynamicCall("InsertRowsBelow(int)", nRowsNumber);
	}

	return true;
}

bool CWordOperation::insertColumn(int nTableNumber, int nColumn, Postion pos, int nColumnsNumber)
{
	bool bResult = false;
	if (checkPointWithinTable(nTableNumber, 1, nColumn, bResult) == false || checkPointWithinTable(nTableNumber, 1, nColumn - nColumnsNumber + 1, bResult) == false || pos < 2 || pos > 3) {
		return false;
	}

	// 获取表集合
	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"insertRow error: tables is nullptr";
		return false;
	}

	// 获取指定表
	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"insertRow: the table does not exist";
		return true;
	}

	auto startCell = tableInfo->querySubObject(u8"Cell(int,int)", 1, nColumn - nColumnsNumber + 1);
	if (startCell == nullptr) {
		qDebug() << u8"insertRow error: startCell is null";
		return false;
	}

	auto endCell = tableInfo->querySubObject(u8"Cell(int,int)", 1, nColumn);
	if (endCell == nullptr) {
		qDebug() << u8"insertRow error: endCell is null";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"createTable error: selection is nullptr";
		return false;
	}

	selection->dynamicCall("SetRange(QVariant, QVariant)", startCell->querySubObject("Range")->property("Start"), endCell->querySubObject("Range")->property("End"));

	if (pos == Postion::RIGHT) {
		selection->dynamicCall("InsertColumnsRight()");
	}
	else if (pos == Postion::LEFT) {
		selection->dynamicCall("InsertColumns()");
	}

	return true;
}

bool CWordOperation::insertLabelInTable(int nTableNumber, int nRow, int nColumn, const QString & strLabelName)
{
	bool bResult = false;
	if (checkPointWithinTable(nTableNumber, nRow, nColumn, bResult) == false) {
		return false;
	}

	// 获取表集合
	auto tables = m_pWordDoc->querySubObject(u8"Tables");
	if (tables == nullptr) {
		qDebug() << u8"insertLabelInTable error: tables is nullptr";
		return false;
	}

	// 获取指定表
	auto tableInfo = tables->querySubObject(u8"Item(int)", nTableNumber);
	if (tableInfo == nullptr) {
		qDebug() << u8"insertLabelInTable: the table does not exist";
		return true;
	}

	auto cell = tableInfo->querySubObject(u8"Cell(int,int)", nRow, nColumn);
	if (cell == nullptr) {
		qDebug() << u8"insertLabelInTable error: cell is null";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"createTable error: selection is nullptr";
		return false;
	}

	selection->dynamicCall("SetRange(QVariant, QVariant)", cell->querySubObject("Range")->property("Start"), cell->querySubObject("Range")->property("End"));

	m_pWordDoc->querySubObject(u8"Bookmarks")->dynamicCall("Add(QVariant,QVariant)", strLabelName, selection->querySubObject(u8"Range")->asVariant());

	return true;
}

bool CWordOperation::setPageOrient(WdOrientation nOrient)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"setPageOrient error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"setPageOrient error: selection is nullptr";
		return false;
	}

	auto pageSetup = selection->querySubObject(u8"PageSetup");
	if (pageSetup == nullptr) {
		qDebug() << u8"setPageOrient error: pageSetup is nullptr";
		return false;
	}

	pageSetup->setProperty(u8"Orientation", nOrient);

	return pageSetup->setProperty(u8"Orientation", nOrient);
}

bool CWordOperation::insertNewPage()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"insertNewPage error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"insertNewPage error: selection is nullptr";
		return false;
	}

	selection->dynamicCall("EndOf(QVariant&,QVariant&)", 6, 0);

	selection->dynamicCall(u8"InsertBreak(QVariant)", 2);
	
	return true;
}

bool CWordOperation::insertPage()
{
	if (m_pWord == nullptr) {
		qDebug() << u8"insertNewPage error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"insertNewPage error: selection is nullptr";
		return false;
	}

	selection->dynamicCall("EndOf(QVariant&,QVariant&)", 6, 0);

	selection->dynamicCall(u8"InsertNewPage()");

	return true;
}

bool CWordOperation::setBookMarksText(const QString & strBookmark, const QString & strText)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"setBookMarksText error: Word Doc is nullptr";
		return false;
	}

	auto bookMark = m_pWordDoc->querySubObject(u8"Bookmarks(QVariant)", strBookmark);
	if (bookMark == nullptr) {
		qDebug() << u8"setBookMarksText error: bookMark is not exist";
		return false;
	}

	// 获取书签的区域
	auto range = bookMark->querySubObject(u8"Range");
	if (range == nullptr) {
		qDebug() << u8"setBookMarksText error: range is null";
		return false;
	}

	// 设置在书签位置内容
	range->setProperty(u8"Text", strText);

	return true;
}

bool CWordOperation::appendBookMarksText(const QString & strBookmark, const QString & strText)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"appendBookMarksText error: Word Doc is nullptr";
		return false;
	}

	auto bookMark = m_pWordDoc->querySubObject(u8"Bookmarks(QVariant)", strBookmark);
	if (bookMark == nullptr) {
		qDebug() << u8"appendBookMarksText error: bookMark is not exist";
		return false;
	}

	// 获取书签的区域
	auto range = bookMark->querySubObject(u8"Range");
	if (range == nullptr) {
		qDebug() << u8"appendBookMarksText error: range is null";
		return false;
	}

	QString strOldText = range->property("Text").toString();

	range->setProperty(u8"Text", strOldText + strText);

	return true;
}

bool CWordOperation::deletBookMark(const QString & strBookmark)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"deletBookMark error: Word Doc is nullptr";
		return false;
	}

	auto bookMark = m_pWordDoc->querySubObject(u8"Bookmarks(QVariant)", strBookmark);
	if (bookMark == nullptr) {
		qDebug() << u8"deletBookMark error: bookMark is not exist";
		return true;
	}

	bookMark->dynamicCall(u8"Delete()");

	return true;
}

bool CWordOperation::insertOtherFileContent(const QString & strFilePath)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"insertOtherFileContent error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"insertOtherFileContent error: selection is nullptr";
		return false;
	}
	
	QVariantList list;
	list << strFilePath << u8"" << false << false << false;
	selection->dynamicCall(u8"InsertFile(QString,QVariant,QVariant,QVariant,QVariant)", list);

	return true;
}

bool CWordOperation::insertHeader(const QString & strHeaderText)
{
	if (m_pWordDoc == nullptr) {
		qDebug() << u8"insertHeader error: Word Doc is nullptr";
		return false;
	}

	auto activeWindow = m_pWordDoc->querySubObject(u8"ActiveWindow");
	if (activeWindow == nullptr) {
		qDebug() << u8"insertHeader error: active Window is null";
		return false;
	}

	auto activePane = activeWindow->querySubObject(u8"ActivePane");
	if (activePane == nullptr) {
		qDebug() << u8"insertHeader error: active pane is null";
		return false;
	}

	auto view = activePane->querySubObject(u8"View");
	if (view == nullptr) {
		qDebug() << u8"insertHeader error: view is null";
		return false;
	}

	view->setProperty(u8"SeekView", u8"wdSeekCurrentPageHeader");

	auto sections = m_pWordDoc->querySubObject(u8"Sections");
	if (sections == nullptr) {
		qDebug() << u8"insertHeader error: sections is null";
		return false;
	}

	auto section = sections->querySubObject(u8"First()");
	if (section == nullptr) {
		qDebug() << u8"insertHeader error: section is null";
		return false;
	}

	auto header = section->querySubObject("Headers")->querySubObject("Item(QAxEnum::WordHeaderFooterIndex)", QVariant(1));
	if (header == nullptr) {
		qDebug() << u8"insertHeader error: header is null";
		return false;
	}

	auto headerRange = header->querySubObject(u8"Range");
	headerRange->dynamicCall(u8"Select()");

	if (m_pWord == nullptr) {
		qDebug() << u8"insertHeader error: widget is nullptr";
		return false;
	}

	auto selection = m_pWord->querySubObject(u8"Selection");
	if (selection == nullptr) {
		qDebug() << u8"insertHeader error: selection is nullptr";
		return false;
	}

	// 设置页眉内容
	selection->dynamicCall(u8"TypeText(QString)", strHeaderText);

	// 设置页眉居中对齐
	selection->querySubObject(u8"ParagraphFormat")->setProperty(u8"Alignment", "wdAlignParagraphCenter");

	view->setProperty(u8"SeekView", 0);

	return true;
}

bool CWordOperation::insertFooter()
{
	// 设置编辑页脚
	m_pWord->querySubObject("ActiveWindow")->querySubObject(u8"ActivePane")->querySubObject(u8"View")->setProperty("SeekView", "wdSeekCurrentPageFooter");

	// 得到footer
	auto footer = m_pWordDoc->querySubObject("Sections")->querySubObject("Item(int)", 1)->querySubObject("Footers")->querySubObject("Item(wdHeaderFooterPrimary)");
	
	// 添加一个shape,并得到该shape
	auto shape = footer->querySubObject("Shapes")->querySubObject("AddTextbox(QVariant,QVariant,QVariant,QVariant,QVariant,QVariant)", 1, 10, 10, 144, 144,
		footer->querySubObject("Range")->asVariant());
	
	if (shape == nullptr) {
		return false;
	}

	shape->querySubObject("Fill")->dynamicCall("setVisible(QVariant)", 0);
	shape->querySubObject("Line")->dynamicCall("setVisible(QVariant)", 0);

	auto textFrame = shape->querySubObject("TextFrame");
	textFrame->setProperty("AutoSize", 1);
	textFrame->setProperty("WordWrap", 0);
	textFrame->setProperty("MarginLeft", 0);
	textFrame->setProperty("MarginRight", 0);
	textFrame->setProperty("MarginTop", 0);
	textFrame->setProperty("MarginBottom", 0);
	textFrame->dynamicCall("setOrientation(int)", 1);

	shape->setProperty("RelativeHorizontalPosition", "wdRelativeHorizontalPositionMargin");
	shape->setProperty("Left", -999995);
	shape->setProperty("RelativeVerticalPosition", "wdRelativeVerticalPositionParagraph");
	shape->setProperty("Top", 0);
	shape->querySubObject("WrapFormat")->setProperty("Type", "wdWrapNone");
	
	auto textRange = shape->querySubObject("TextFrame")->querySubObject("TextRange");
	textRange->dynamicCall("setText(QString)", u8"X");

	auto field = textRange->querySubObject("Fields")->querySubObject("Add(QVariant,QVariant,QVariant,QVariant)",
		textRange->asVariant(), 33, "", true);			// 这里必须使用33不能使用"wdFieldPage"

	if (field == nullptr) {
		return false;
	}

	auto PageNumbers = footer->querySubObject("PageNumbers");
	PageNumbers->setProperty("NumberStyle", "wdPageNumberStyleNumberInDash");
	PageNumbers->setProperty("RestartNumberingAtSection", false);
	PageNumbers->setProperty("StartingNumber", 1);
	PageNumbers->setProperty("IncludeChapterNumber", false);

	auto PageNumbers2 = m_pWordDoc->querySubObject("Sections")->querySubObject("Item(int)", 2)->querySubObject("Footers")->querySubObject("Item(WdHeaderFooterIndex)", "wdHeaderFooterPrimary")->querySubObject("PageNumbers");
	PageNumbers2->setProperty("NumberStyle", "wdPageNumberStyleNumberInDash");
	PageNumbers2->setProperty("RestartNumberingAtSection", false);
	PageNumbers2->setProperty("StartingNumber", 1);
	PageNumbers2->setProperty("IncludeChapterNumber", false);

	m_pWord->querySubObject("Selection")->querySubObject("Range")->querySubObject("PageSetup")->setProperty("DifferentFirstPageHeaderFooter", 0);
	m_pWord->querySubObject("ActiveWindow")->querySubObject("ActivePane")->setProperty("VerticalPercentScrolled", 31);
	m_pWord->querySubObject("ActiveWindow")->querySubObject("View")->setProperty("SeekView", "wdSeekMainDocument");

	return true;
}

bool CWordOperation::insertPicture(const QString & strPicturePath)
{
	if (m_pWord == nullptr) {
		qDebug() << u8"insertPicture is error: word is null";
		return false;
	}

	auto selection = m_pWord->querySubObject("Selection");
	if (selection == nullptr) {
		qDebug() << u8"insertPicture is error: selection is null";
		return false;
	}

	selection->querySubObject("InlineShapes")->dynamicCall("AddPicture(QStrng,int,int)", strPicturePath, 0, 1);

	return true;
}

void CWordOperation::clearValue()
{
	if (m_pWord != nullptr) {
		delete m_pWord;
		m_pWord = nullptr;
	}

	if (m_pWordDoc != nullptr) {
		delete m_pWordDoc;
		m_pWordDoc = nullptr;
	}
}

四、 工程下载链接

https://download.csdn/download/qq_22606043/89122474

本文标签: QT Word