合并Word文档

该博客介绍了在Word 2010中实现特定功能的操作。将类型设为一级标题,先把文档前三行初始化为正文,再将第一行设为标题2,最后形成目录。还提及调用了progressbar.h、progressbar.cpp等多个文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Word版本:2010

实现功能:将类型设置为一级标题,将文档前三行先初始化为正文,再将第一行设置为标题2,然后形成目录的形式

调用:

	WordMerger *m_pWordMerger = new WordMerger;

	QString strSavePath = "D:/test/merger.doc";

	QList<QVariant> listWord;
	TestWord tag1;
	tag1.m_strTypeName = "测试1";
	tag1.m_strlstTestWordPath << "D:/test/word1.docx" << "D:/test/word2.docx" << "D:/test/word3.docx";

	TestWord tag2;
	tag2.m_strTypeName = "测试2";
	tag2.m_strlstTestWordPath << "D:/test/word4.docx" << "D:/test/word5.docx" << "D:/test/word6.docx";

	listWord.push_back(QVariant::fromValue(tag1));
	listWord.push_back(QVariant::fromValue(tag2));

	m_pWordMerger->setSavePath(strSavePath);
	m_pWordMerger->mergeTestReports(listWord);
	m_pWordMerger->startMerge();

progressbar.h

#ifndef PROGRESSBAR_H
#define PROGRESSBAR_H

#include <QDialog>
#include <QLabel>
#include <QProgressBar>

class ProgressBar : public QDialog
{
	Q_OBJECT

public:
	ProgressBar(QWidget *parent = 0);
	~ProgressBar();

	void initUI();
public slots:
	void setProgressBarValue(double nValue);
	void closeProgressBar();
private:
	QLabel *m_pTipLabel;
	QProgressBar *m_pProgressBar;
};

#endif // PROGRESSBAR_H

progressbar.cpp

#include "progressbar.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSpacerItem>

ProgressBar::ProgressBar(QWidget *parent)
	: QDialog(parent)
{
	initUI();

	setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
	m_pProgressBar->setRange(0,100);
}

ProgressBar::~ProgressBar()
{

}

void ProgressBar::initUI()
{
	this->resize(427,55);
	QVBoxLayout *pVlayout = new QVBoxLayout;
	QHBoxLayout *pHlayout = new QHBoxLayout;
	m_pTipLabel = new QLabel("正在合并word文档,请稍等...");
	m_pProgressBar = new QProgressBar;
	pHlayout->addStretch();
	pHlayout->addWidget(m_pTipLabel);
	pHlayout->addStretch();

	pVlayout->addLayout(pHlayout);
	pVlayout->addWidget(m_pProgressBar);
	this->setLayout(pVlayout);
}

void ProgressBar::setProgressBarValue( double nValue )
{
	m_pProgressBar->setValue(qRound(nValue*100));
	if (nValue == 1)
	{
		m_pTipLabel->setText("word文档合并完成!");
	}
}

void ProgressBar::closeProgressBar()
{
	close();
}

WordMerger.h

#ifndef WORDMERGER_H
#define WORDMERGER_H

#include <QObject>
#include <QVariant>
#include <QAxObject>
#include <QThread>
#include "WordOperator.h"
#include "ProgressBar.h"


struct TestWord {
	QString m_strTypeName; 
	QStringList m_strlstTestWordPath; 
};
Q_DECLARE_METATYPE(TestWord);

class WordMerger : public QObject
{
	Q_OBJECT

public:
	WordMerger();
	~WordMerger();

	void setSavePath(const QString &strSavePath);
	void mergeTestReports(const QList<QVariant> &qListReports);
	//查看测试报告是否生成成功,true:生成成功  false:没有生成
	bool wordMergeSate();
	//判断保存路径的文件夹是否存在,不存在则创建
	bool judgeSaveDirIsExist(QString &strSaveDir);

	void startMerge();
signals:
	void sendProgressToBar(double);
	void wordCloseFinish();

private:
	QString m_strMergeSavePath;
	QList<QVariant> m_qListWords;
	//word总数,总共有几篇word
	int m_nTotalWords;
	//当前处理到哪篇word
	int m_nCurrentWord;
	ProgressBar *m_pProgressBar;
};
#endif //WORDMERGER_H

WordMerger.cpp

#include "WordMerger.h"
#include <QFileInfo>
#include <QApplication>
#include <QDebug>
#include <Ole2.h>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include <QProcess>
#include <QDir>
#include <QCoreApplication>

WordMerger::WordMerger()
	: m_strMergeSavePath("")
	, m_nTotalWords(0)
	, m_nCurrentWord(0)
	, m_pProgressBar(NULL)
{
	m_qListWords.clear();

	m_pProgressBar = new ProgressBar;
	m_pProgressBar->show();
	connect(this,SIGNAL(sendProgressToBar(double)),m_pProgressBar,SLOT(setProgressBarValue(double)));
	connect(this,SIGNAL(wordCloseFinish()),m_pProgressBar,SLOT(closeProgressBar()));
}

WordMerger::~WordMerger()
{
	
}

void WordMerger::setSavePath( const QString &strSavePath )
{
	m_strMergeSavePath = strSavePath;
}

void WordMerger::mergeTestReports(const QList<QVariant> &qListReports)
{
	m_qListWords = qListReports;
	for (int i=0; i<m_qListWords.size(); ++i)
	{
		const QVariant &var = m_qListWords.at(i);
		const TestWord &tag = var.value<TestWord>();
		m_nTotalWords += tag.m_strlstTestWordPath.size();
	}
}

void WordMerger::startMerge()
{
	if (m_qListWords.isEmpty())
	{
		emit wordCloseFinish();
		QMessageBox::information(NULL,"提示","测试报告列表为空!");
		return;
	}

	QString strSaveDir = "";
	if (!judgeSaveDirIsExist(strSaveDir))
	{
		emit wordCloseFinish();
		QMessageBox::information(NULL,"提示",QString("文件夹%1不存在,创建也失败!").arg(strSaveDir));
		return;
	}

	HRESULT result = OleInitialize(0);
	//WordOperator创建和其函数使用必须在一个线程中   注:不可在主线程中创建,子线程中使用
	WordOperator *m_pWordApp = new WordOperator;

	if (!m_pWordApp->init()) //打开Word APP
	{
		emit wordCloseFinish();
		OleUninitialize();
		QMessageBox::information(NULL,"提示","Word初始化失败!");
		return;
	}

	if (!m_pWordApp->createDocFromTemplate("")) //创建空白主文档
	{
		emit wordCloseFinish();
		m_pWordApp->close();
		OleUninitialize();
		QMessageBox::information(NULL,"提示","创建主文档失败!");
		return;
	}

	for (int i=0; i<m_qListWords.size(); ++i)
	{
		const TestWord &tag = m_qListWords.at(i).value<TestWord>();

		//判断文件路径是否存在
		foreach (const QString &strFileName, tag.m_strlstTestWordPath) {
			if (!QFile::exists(strFileName))
			{
				QMessageBox::critical(NULL,"错误",QString("步骤报告<%1>不存在!").arg(strFileName));
				m_pWordApp->close();
				emit wordCloseFinish();
				OleUninitialize();
				return;
			}
		}

		QString strMainTitle = QString("%1.%2").arg(i+1).arg(tag.m_strTypeName);
		//例:SAC101,SAC102...为一级标题
		m_pWordApp->insertTextToCurrentParagraph(strMainTitle,FIRST_LEVEL_TITLE);

		for (int j=0; j<tag.m_strlstTestWordPath.size(); ++j)
		{
			const QString &strTestStepReportPath = tag.m_strlstTestWordPath.at(j);
			QString strSubTitle = QString("%1.%2.").arg(i+1).arg(j+1);
			m_pWordApp->copySubDocToMainDoc(strTestStepReportPath,strSubTitle);
			++m_nCurrentWord;
			emit sendProgressToBar((double)m_nCurrentWord/(double)m_nTotalWords);
		}
	}
	m_pWordApp->save(m_strMergeSavePath);
	m_pWordApp->close();
	emit wordCloseFinish();

	if (wordMergeSate())
	{
		if(QMessageBox::question(NULL, "提示", "生成报告成功。是否打开报告所在路径文件夹?", QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok)
		{
			//打开生成文件路径,并选中文件
			QProcess process;
			// 路径包含空格需要特殊处理
			QString strTmpPath = QDir::toNativeSeparators(m_strMergeSavePath).replace(" ", "\" \"");
			QString cmd = QString("explorer.exe /select,\"%1\"").arg(strTmpPath);
			process.startDetached(cmd);
		}
	}
	else
	{
		QMessageBox::information(NULL,"提示","测试报告生成失败!");
	}
	OleUninitialize();
}

bool WordMerger::wordMergeSate()
{
	QFile file;
	int nIndex = m_strMergeSavePath.lastIndexOf ("."); //从后面查找"."位置
	if (nIndex == -1)
	{
		m_strMergeSavePath += ".docx";
	}

	if (file.exists(m_strMergeSavePath))
	{
		return true;
	}
	return false;
}

bool WordMerger::judgeSaveDirIsExist(QString &strSaveDir)
{
	strSaveDir = QFileInfo(m_strMergeSavePath).absolutePath();
	QDir dir;
	if (!dir.exists(strSaveDir))
	{
		return dir.mkdir(strSaveDir);
	}
	return true;
}

WordOperator.h

#ifndef WORDOPERATOR__H
#define WORDOPERATOR__H

#include <QStringList>
#include <QMetaType>
#include <QObject>
#include "progressbar.h"

//一级标题
#define FIRST_LEVEL_TITLE -2 
//二级标题
#define SECOND_LEVEL_TITLE -3 
//正文
#define MAIN_BODY -67


class QAxObject;
class WordOperator :public QObject
{
	Q_OBJECT
public:
	WordOperator();
	~WordOperator();
	bool init();
	bool createDocFromTemplate( const QString &file, bool visible = true );
	void save(const QString &savePath);
	void close();

	//合并word函数 start...
	//复制子文档到主文档
	void copySubDocToMainDoc(const QString &strSubDocPath,const QString &strOrder);
	void mergeTestReports(const QList<QVariant> &qListReports, const QString &strSavePath);
	QAxObject *updateDocumentRange(); //更新主文档当前段落Range
	void startMergeTestReports(const QList<QVariant> &qListReports, const QString &strSavePath);
	void insertTextToCurrentParagraph(QString strText, int nLevel); //插入文本到当前段落
	//合并word函数 end...

protected:
	QAxObject * m_wordAxObj;
	QAxObject * m_documentsAxObj;
	QAxObject * m_documentAxObj;
	QAxObject * m_documentRangeObj;
	ProgressBar *m_ProgressBar;

	QString m_strMergeSavePath; //合并word保存路径
};

#endif //WORDOPERATOR__H

WordOperator.cpp

#include <Ole2.h>
#include <QAxObject>
#include "WordOperator.h"
#include <QFileInfo>
#include <QClipboard>
#include <QApplication>
#include <QDebug>
#include <QThread>
#include <Windows.h>

static QAxObject * getItemFromArray(QAxObject * arrayObj, int index);

WordOperator::WordOperator()
	:m_wordAxObj(0), m_documentsAxObj(0), m_documentAxObj(0)
	,m_documentRangeObj(0),m_ProgressBar(0),m_strMergeSavePath("")
{
}

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

bool WordOperator::init()
{
	m_wordAxObj = new QAxObject("Word.Application");
	if(!m_wordAxObj)
	{
		return false;
	}

	m_wordAxObj->setProperty("Visible", false);
	m_documentsAxObj = m_wordAxObj->querySubObject("Documents");

	if (!m_documentsAxObj)
	{
		return false;
	}
	return true;
}

bool WordOperator::createDocFromTemplate(const QString &file, bool visible)
{
	if (m_wordAxObj == 0 || m_documentsAxObj == 0)
	{
		return false;
	}

	m_documentsAxObj->dynamicCall("Add(QString)", file);
	m_documentAxObj = m_wordAxObj->querySubObject("ActiveDocument");
	return m_documentAxObj != 0;
}

void WordOperator::save(const QString &savePath)
{
	if (0 == m_documentAxObj)
	{
		return;
	}

	m_documentAxObj->dynamicCall("SaveAs2(const QString&)", savePath);
}

void WordOperator::close()
{
	if (m_documentAxObj)
	{
		m_documentAxObj->dynamicCall("Close(bool)", false);
		delete m_documentAxObj;
		m_documentAxObj = nullptr;
	}
	if (m_wordAxObj)
	{
		m_wordAxObj->setProperty("DispalyAlerts", true);
		QAxObject* axobjNormalTemplate = m_wordAxObj->querySubObject("NormalTemplate");
		if(axobjNormalTemplate != nullptr)
		{
			axobjNormalTemplate->setProperty("Saved", true);
		}
		m_wordAxObj->dynamicCall("Quit()");
		delete m_wordAxObj;
		m_wordAxObj = nullptr;
	}
}

void WordOperator:: mergeTestReports(const QList<QVariant> &qListReports, const QString &strSavePath)
{
	m_ProgressBar = new ProgressBar(NULL);
	connect(this,SIGNAL(sendProgressToBar(int)),m_ProgressBar,SLOT(setProgressBarValue(int)));
	m_ProgressBar->show();
}

void WordOperator::startMergeTestReports( const QList<QVariant> &qListReports, const QString &strSavePath )
{

	save(strSavePath);
}

QAxObject * WordOperator::updateDocumentRange()
{
	if (!m_wordAxObj || !m_documentAxObj)
	{
		return NULL;
	}

	QAxObject *paragraphs = m_documentAxObj->querySubObject("Paragraphs");
	int nParaCount = paragraphs->property("Count").toInt();
	if (nParaCount <= 0)
	{
		return NULL;
	}

	QAxObject *paragraph = paragraphs->querySubObject("Item(int)",nParaCount);
	if (!paragraph)
	{
		return NULL;
	}

	return paragraph->querySubObject("Range()");
}

void WordOperator::insertTextToCurrentParagraph(QString strText, int nLevel)
{
	if (strText.isEmpty())
	{
		return;
	}

	m_documentRangeObj = updateDocumentRange();
	if (!m_documentRangeObj)
	{
		return;
	}

	m_documentRangeObj->setProperty("Text",strText);
	m_documentRangeObj->setProperty("Style",nLevel);
	m_documentRangeObj->dynamicCall("InsertParagraphAfter()");
}

void WordOperator::copySubDocToMainDoc( const QString &strSubDocPath,const QString &strOrder)
{
	m_documentsAxObj->dynamicCall("Add(QString)",strSubDocPath); //打开strDoc
	QAxObject *pDocument = m_wordAxObj->querySubObject("ActiveDocument"); //获取当前激活文档
	if (!pDocument)
	{
		return;
	}
	QAxObject *pRange = pDocument->querySubObject("Range()"); //获取strDoc文档中的所有内容,文档的Range代表该文档的所有内容
	if (!pRange)
	{
		return;
	}
	QAxObject *pParagraphs = pRange->querySubObject("Paragraphs"); //获取到所有段落
	if (!pParagraphs)
	{
		return;
	}
	int nParaCount = pParagraphs->property("Count").toInt();
	if (nParaCount <= 0)
	{
		return;
	}
	//将前3段落设置为正文
	for (int i=1; i<=2; ++i)
	{
		QAxObject *paragraph = pParagraphs->querySubObject("Item(int)",i);
		if (!paragraph) 
		{
			continue;
		}
		paragraph->setProperty("Style",MAIN_BODY);
	}
	QAxObject *paragraph = pParagraphs->querySubObject("Item(int)",1);
	QAxObject *pParaRange = paragraph->querySubObject("Range()");
	pParaRange->dynamicCall("InsertBefore(QString)",strOrder);
	paragraph->setProperty("Style",SECOND_LEVEL_TITLE); //将第1段落设置为标题2
	pRange->dynamicCall("Copy()"); //这里的复制是复制到剪贴板上的,所以复制和粘贴的对象可以不同
	m_documentRangeObj = updateDocumentRange();
	if (!m_documentRangeObj)
	{
		pDocument->dynamicCall("Close(boolean)",false); 
		return;
	}
	m_documentRangeObj->dynamicCall("Paste()"); //这里的复制是复制到剪贴板上的,所以复制和粘贴的对象可以不同
	pDocument->dynamicCall("Close(int)",0); //0:不保存更改
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值