Qt-QAxObject类-导出为word文件

本文详细介绍了如何使用QAxObject类在C++中操作Word,创建并编辑成绩单样式的文档,包括初始化COM、创建表格、设置单元格样式、插入数据等步骤,并解决了QAxObject在子线程中连接失败、编译报错等问题。此外,还列举了一些常用的Word表格属性和操作方法。
摘要由CSDN通过智能技术生成

简介

  • 本文主要介绍QAxObject类导出为word文件操作。以实现导出一份成绩单为例,介绍可能会出现的问题,如何去解决。同时会将word中常用的一些属性枚举封装为函数进行介绍,方便读者理解。

代码实现

  • 代码分析详见注释
  • custome_output_file_service.h
#pragma once
#include <QObject>
#include <QAxObject>
#include <QTextCodec>
#include <QDateTime>
#include <QDebug>
#include "custome_output_file_global.h"

class CustomeOutputFileService
	:public ICustomeOutputFile
{
public:
	CustomeOutputFileService();
	~CustomeOutputFileService();

	virtual bool CreateRecordWord(CyCString _path);


	virtual bool SetRecordInformation(CyCString _name, int _count);


	virtual bool InsertRecordData(vector<std::string> _data);


	virtual bool Close();

private:
	QAxObject *		word_;
	QAxObject *		act_doc_;
	QString			file_path_;
	int				count_;
	QAxObject*		simulation_table_;
};
  • custome_output_file_service.cpp
#include "custome_output_file_service.h"
#include "qt_windows.h"

CustomeOutputFileService::CustomeOutputFileService()
	:count_(2)
{
}


CustomeOutputFileService::~CustomeOutputFileService()
{
}

bool CustomeOutputFileService::CreateRecordWord(CyCString _path)
{
	file_path_ = StdString2QString(_path);
	count_ = 2;
	//因为COM是在GUI线程初始化和销毁的,在新开的线程里面并没有初始化,所以得自己初始化。
	HRESULT r_com = OleInitialize(0);
	if (r_com != S_OK && r_com != S_FALSE)
	{
		qDebug("Qt: Could not initialize OLE (error %x)",(unsigned int)r_com);
	}
	//创建word文档
	//指向整个word应用程序
	word_ = new QAxObject();
	if (!word_->setControl("word.Application"))
		return false;
	word_->setProperty("Visible", false);
	QAxObject *documents = word_->querySubObject("Documents");
	if (!documents)
		return false;
	documents->dynamicCall("Add(void)");
	//获取当前激活的文档
	act_doc_ = word_->querySubObject("ActiveDocument");
	if (act_doc_ == nullptr)
		return false;
	QAxObject* selection = word_->querySubObject("Selection");
	selection->querySubObject("Font")->setProperty("Size", 11);
	selection->dynamicCall("TypeText(const QString&)", "");
	return true;
}

bool CustomeOutputFileService::SetRecordInformation(CyCString _name, int _count)
{
	//当前日期
	QDateTime cur_data_time = QDateTime::currentDateTime();
	QString data_time = cur_data_time.toString("yyyy-MM-dd hh:mm:ss");

    //设置标题风格及内容
	QAxObject* selection = word_->querySubObject("Selection");
	selection->querySubObject("Font")->setProperty("Size", 14);
	selection->querySubObject("Font")->setProperty("Bold", true);
	selection->querySubObject("ParagraphFormat")->setProperty("Alignment", "wdAlignParagraphCenter");
	selection->dynamicCall("TypeText(const QString&)", QStringLiteral("成绩单\n"));

    //设置成绩单信息风格及内容
	selection->querySubObject("Font")->setProperty("Size", 11);
	selection->querySubObject("Font")->setProperty("Bold", false);
	selection->querySubObject("ParagraphFormat")->setProperty("Alignment", "wdAlignParagraphLeft");
	selection->dynamicCall("TypeText(const QString&)", QStringLiteral("教师:%1 日期:%2\n").arg(StdString2QString(_name)).arg(data_time));

    //设置数据内容格式
	QAxObject* tables = act_doc_->querySubObject("Tables");
	QAxObject* range = selection->querySubObject("Range");
	simulation_table_ = tables->querySubObject("Add(QAxObject*, int, int)", range->asVariant(), _count + 1, 6);
	QAxObject* border_line1 = simulation_table_->querySubObject("Borders(1)");
	border_line1->dynamicCall("SetLineStyle(int)", 1);
	QAxObject* border_line2 = simulation_table_->querySubObject("Borders(2)");
	border_line2->dynamicCall("SetLineStyle(int)", 1);
	QAxObject* border_line3 = simulation_table_->querySubObject("Borders(3)");
	border_line3->dynamicCall("SetLineStyle(int)", 1);
	QAxObject* border_line4 = simulation_table_->querySubObject("Borders(4)");
	border_line4->dynamicCall("SetLineStyle(int)", 1);
	QAxObject* border_line5 = simulation_table_->querySubObject("Borders(5)");
	border_line5->dynamicCall("SetLineStyle(int)", 1);
	QAxObject* border_line6 = simulation_table_->querySubObject("Borders(6)");
	border_line6->dynamicCall("SetLineStyle(int)", 1);
	QAxObject* trange = simulation_table_->querySubObject("Range");
	trange->querySubObject("ParagraphFormat")->setProperty("Alignment", "wdAlignParagraphCenter");
	trange->querySubObject("Cells")->setProperty("VerticalAlignment", "wdCellAlignVerticalCenter");
	selection->querySubObject("Font")->setProperty("Bold", true);
	simulation_table_->querySubObject("Cell(int, int)", 1, 1)->querySubObject("Range")->dynamicCall("SetText(QString)", QStringLiteral("姓名"));
	simulation_table_->querySubObject("Cell(int, int)", 1, 2)->querySubObject("Range")->dynamicCall("SetText(QString)", QStringLiteral("学号"));
	simulation_table_->querySubObject("Cell(int, int)", 1, 3)->querySubObject("Range")->dynamicCall("SetText(QString)", QStringLiteral("班级"));
	simulation_table_->querySubObject("Cell(int, int)", 1, 4)->querySubObject("Range")->dynamicCall("SetText(QString)", QStringLiteral("实验场次"));
	simulation_table_->querySubObject("Cell(int, int)", 1, 5)->querySubObject("Range")->dynamicCall("SetText(QString)", QStringLiteral("成绩"));
	simulation_table_->querySubObject("Cell(int, int)", 1, 6)->querySubObject("Range")->dynamicCall("SetText(QString)", QStringLiteral("评语"));
	return true;
}

//插入数据
bool CustomeOutputFileService::InsertRecordData(vector<std::string> _data)
{
	if (_data.size() == 0)
	{
		return false;
	}
	for (int i = 0; i < _data.size(); ++i)
	{
		simulation_table_->dynamicCall("AutoFitBehavior(int)", 6);
		simulation_table_->querySubObject("Rows(int)", count_)->setProperty("Height", 20);
		simulation_table_->querySubObject("Cell(int, int)", count_, i + 1)->querySubObject("Range")->dynamicCall("SetText(QString)", StdString2QString(_data.at(i)));
	}
	count_++;
	return true;
}

//关闭连接
bool CustomeOutputFileService::Close()
{
	act_doc_->dynamicCall("SaveAs (const QString&)", file_path_);
	act_doc_->dynamicCall("Close(bool)", true);
	word_->dynamicCall("Quit()");
    //关闭COM
	OleUninitialize();
	return true;
}

常见问题解决

1、QAxObject对象在子线程中连接失败

 word_->setControl("word.Application")
  1. 连接对象为QAxWidget类对象,GUI相关对象不能在子线程中进行操作,所以应该修改为QAxObject类对象。
  2. 如果对象为QAxObject类对象还是连接失败,则查看COM是否在子线程初始化,如果没有添加如下代码
//因为COM是在GUI线程初始化和销毁的,在新开的线程里面并没有初始化,所以得自己初始化。
	HRESULT r_com = OleInitialize(0);
	if (r_com != S_OK && r_com != S_FALSE)
	{
		qDebug("Qt: Could not initialize OLE (error %x)",(unsigned int)r_com);
	}

2、添加QAxObject头文件后编译报错:“无法打开源文件”

  • 原因在于当前工程中并没有包含相应的模块,需要到项目属性设置中添加相应模块,并添加相应附加包含目录和附加依赖项。如下图所示:
    在这里插入图片描述

3、修改单元格属性后未生效

  1. 查看设置单元格为全局还是特定单元格。
  2. 是否设置属性后再插入数据。
  3. 属性字段是否正确。
  4. 单元格对象是否添加。

常见属性

  • 以下是一些word中表格常用的一些属性( QAxObject* selection_ = m_pWord->querySubObject(“Selection”);)
/*
 * 排版方式
 * 纵行、横行
*/
    selection_->querySubObject("PageSetup")->setProperty("Orientation","wdOrientLandscape");    //纵
    selection_->querySubObject("PageSetup")->setProperty("Orientation","wdOrientPortrait");     //横
/*
 * 获取页宽
*/
    int width_;
    width_ = selection_->querySubObject("PageSetup")->property("PageWidth").toInt();;
/*
 *设置字号
*/
    selection_->querySubObject("Font")->setProperty("Size",14);
/*
  *设置对齐方式
*/
    selection_->querySubObject("ParagraphFormat")->setProperty("Alignment","wdAlignParagraphCenter");    //居中对齐
    selection_->querySubObject("ParagraphFormat")->setProperty("Alignment","wdAlignParagraphJustify");   //分散对齐
    selection_->querySubObject("ParagraphFormat")->setProperty("Alignment","wdAlignParagraphRight");     //右对齐
    selection_->querySubObject("ParagraphFormat")->setProperty("Alignment","wdAlignParagraphLeft");      //左对齐
/*
  *插入文字
*/
selection_->dynamicCall("TypeText(const QString&)","hello world!");
/*
   *插入图片
*/
    QString filename = file;
    filename.replace("/","\\");     //转义字符替换
    QAxObject *Inlineshapes = selection_->querySubObject("InlineShapes");
    Inlineshapes->dynamicCall("AddPicture(const QString&)",filename);
    delete Inlineshapes;
/*
   *插入回车
*/
selection_->dynamicCall("TypeParagraph(void)");
/*
 * 光标移到末尾,跳出单元格
*/

    QVariantList params;
    params.append(6);
    params.append(0);
    selection->dynamicCall("EndOf(QVariant&, QVariant&)", params).toInt();
/*
   创建表格
   QStringList headList 添加表头
*/

QAxObject* MainWindow::createTable(int row, int column, QStringList head_list)
{
    QAxObject* selection  = m_pWord->querySubObject("Selection");
    if(!selection)
    {
        return false;
    }
    selection->dynamicCall("InsertAfter(QString&)", "\r\n");

    QAxObject *range = selection->querySubObject("Range");
    QAxObject *tables = m_pWorkDocument->querySubObject("Tables");
    QAxObject *table = tables->querySubObject("Add(QVariant,int,int)",range->asVariant(),row,column);

    table->setProperty("Style","网格型");
    //表格自动拉伸列 0固定  1根据内容调整  2 根据窗口调整
    table->dynamicCall("AutoFitBehavior(WdAutoFitBehavior)", 2);

    //设置表头
    for(int i=0;i<headList.size();i++)
    {
        table->querySubObject("Cell(int,int)",1,i+1)->querySubObject("Range")->dynamicCall("SetText(QString)", head_list.at(i));
        //加粗
        table->querySubObject("Cell(int,int)",1,i+1)->querySubObject("Range")->dynamicCall("SetBold(int)", true);
    }
    return table;
}

/*
   填充表格
*/

void MainWindow::setCellText(QAxObject *table, int row, int column, QString text)
{
    QAxObject* range = table->querySubObject("Cell(int, int)",row+1,column+1)->querySubObject("Range");
    if( range)
        return;
    range->dynamicCall("SetText(QString)", text);
}

/*
  表格插入图片
*/
void MainWindow::setAddPicture(QAxObject *table, int row, int column, QString picPath)
{
    QAxObject* range = table->querySubObject("Cell(int, int)",row+1,column+1)->querySubObject("Range");
    if(!range)
        return;
    range->querySubObject("InlineShapes")->dynamicCall("AddPicture(const QString&)",picPath);
}

/*
   *光标跳转,类似表格中的tab
*/
    selection->dynamicCall("MoveRight(int)",1);

以上是对QAxObject导出word文档表格的一些简单操作,新人第一次发博客,如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。
原创文章,转载请标明本文出处。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦醒梦起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值