使用c++批量生成docx文档

目录

一、需求说明

二、实验准备

1、准备数据:

2、准备模板:

3、准备vs环境:

三、代码实现

1、建立数据结构

2、读数据并保存

3、批量向标签增添内容

4、新建表格(新)

5、修改字体格式(新)

四、实验结果


一、需求说明

能够根据模板批量生成docx文档。具体而言,使用c++读取数据(笔者为了简单,使用的是存储在txt中的数据),然后根据模板批量生成docx文档

二、实验准备

1、准备数据:

3
张三
班级 一班
语文 80
数学 70
英语 60
李四
班级 二班
语文 50
数学 10
英语 20
王五
班级 二班
语文 90
数学 100
英语 95

将数据保存为data.txt

2、准备模板:

在指定位置添加书签:

笔者在建立书签时,在两个地方使用相同的书签时在第一个得分无法显示书签,目前还不知道具体原因,所以使用两个不同的书签(name和name1)

将数据保存为template.doc

3、准备vs环境:

使用的是vs2017社区版

使用MFC生成docx文档参考:https://www.jianshu.com/p/a5063628a65a

先安装MFC环境:

打开vs,新建项目:

导入word类库:项目-》类向导-》添加类(下拉框中“类型库中的MFC类”)-》选择“从文件中添加类”,然后从office的安装目录(office的默认路径如下)中找到MSWORD.OLB

然后选择接口:

_Application, _Document, Bookmark, Bookmarks, Cell, Cells, Column, Columns, Documents, Range, Row, Rows, Selection, Table, Tables

对每个接口类,修改一下生成文件位置

然后点击“完成”

在生成的头文件.h中将导入的MSWORD.OLB注释掉:

然后在pch.h文件中添加头文件:

初始化:在自己的MFC项目的.cpp文件中找到XXXApp::InitInstance()中添加以下代码:

然后在MFC项目中添加“生成”按钮,双击按钮,在按钮的点击事件中添加响应事件代码

三、代码实现

1、建立数据结构

写具体的实现代码之前,在ReadWordDlg.h中引入需要使用的头文件,特别注意这个引入头文件的位置,否则会出现交叉引用从而报类似”int类型...“这样的错

首先建立保存数据的结构体:

typedef struct{
	char name[20];
	char clas[20];
	int language;
	int math;
	int english;
}Stu;
Stu stu[10];

2、读数据并保存

从data.txt中读取数据存入结构体数组:

int readdata(string path)
{
	ifstream file(path, ios::in);
	if (!file) {//打开文件失败
		AfxMessageBox(_T("打开文件失败!"));
		return 0;
	}
	int n;
	file >> n;
	for (int i = 0; i < n; i++) {
		file >> stu[i].name;
		char str[20] = "";
		file >> str >> stu[i].clas;
		file >> str >> stu[i].language;
		file >> str >> stu[i].math;
		file >> str >> stu[i].english;
	}
	file.close();
	return n;
}

3、批量向标签增添内容

void CReadWordDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	COleVariant covzZero((short)0),
		covTrue((short)TRUE),
		covFalse((short)FALSE),
		covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR),
		covDocxType((short)0),
		start_line, end_line,
		dot(_T("D:\\code\\c\\ReadWord\\template.dot"));

	int n = readdata("D:\\code\\c\\ReadWord\\data.txt");
	for (int i = 0; i < n; i++) {
		CApplication wordApp;
		CDocuments docs;
		CDocument0 docx;
		CBookmarks bookmarks;
		CBookmark0 bookmark;
		CRange range;
		CCell cell;
		if (!wordApp.CreateDispatch(_T("Word.Application")))
		{
			AfxMessageBox(_T("本机没有安装word产品!"));
			return;
		}

		//locale::global(locale(""));

		wordApp.put_Visible(FALSE);
		CString wordVersion = wordApp.get_Version();
		docs = wordApp.get_Documents();
		docx = docs.Add(dot, covOptional, covOptional, covOptional);
		bookmarks = docx.get_Bookmarks();

		bookmark = bookmarks.Item(&_variant_t(_T("name1")));
		range = bookmark.get_Range();
		range.put_Text(convert(stu[i].name));

		bookmark = bookmarks.Item(&_variant_t(_T("class")));
		range = bookmark.get_Range();
		range.put_Text(convert(stu[i].clas));

		bookmark = bookmarks.Item(&_variant_t(_T("name")));
		range = bookmark.get_Range();
		range.put_Text(convert(stu[i].name));

		bookmark = bookmarks.Item(&_variant_t(_T("language")));
		range = bookmark.get_Range();
		CString str_lan;
		str_lan.Format(_T("%d"), stu[i].language);
		range.put_Text(str_lan);

		bookmark = bookmarks.Item(&_variant_t(_T("math")));
		range = bookmark.get_Range();
		CString str_math;
		str_math.Format(_T("%d"), stu[i].math);
		range.put_Text(str_math);

		bookmark = bookmarks.Item(&_variant_t(_T("English")));
		range = bookmark.get_Range();
		CString str_en;
		str_en.Format(_T("%d"), stu[i].english);
		range.put_Text(str_en);

		CString strSavePath = _T("D:\\code\\c\\ReadWord\\");
		strSavePath += convert(stu[i].name);
		strSavePath += _T("的成绩单.docx");
		docx.SaveAs(COleVariant(strSavePath), covOptional, covOptional, covOptional, covOptional,
			covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional,
			covOptional, covOptional, covOptional, covOptional);

		//退出word应用
		docx.Close(covFalse, covOptional, covOptional);
		wordApp.Quit(covOptional, covOptional, covOptional);
		range.ReleaseDispatch();
		bookmarks.ReleaseDispatch();
		wordApp.ReleaseDispatch();
	}

	AfxMessageBox(_T("文档生成成功!"));
}

期间遇到中文字符的处理问题,参考https://blog.csdn.net/weixin_43794736/article/details/116589122

4、新建表格(新)

导入接口类:

Border, Borders, Cells, Tables, Paragraph, Paragraphs

然后按照步骤三修改头文件,记得在新添加的头文件中将导入的MSWORD.OLB注释掉:

代码实现:

//生成表格
		CCells            cells;
		CTable0           table;
		CTables0          tables;
		CBorder           border;
		CBorders          borders;
		CParagraph		  paragraph;
		CParagraphs		  paragraphs;

		//以当前段落最后一行为表起始位置
		paragraphs = docx.get_Paragraphs();
		paragraph = paragraphs.get_Last();
		range = paragraph.get_Range();
		//添加新制作表格:(n+1)*5
		tables = docx.get_Tables();
		table = tables.Add(range, n + 2, 5, covOptional, covOptional);
		borders = table.get_Borders();
		borders.put_Enable(1);//显示表框

		range = table.get_Range();
		cells = range.get_Cells();
		cells.put_VerticalAlignment(1);//文字居中

		cells.SetWidth(60, 1);

		//第一行(表格标题)
		//合并第一行的单元格
		cell = table.Cell(1, 1);
		cell.Merge(table.Cell(1, 5));
		range = cell.get_Range();
		
		range.put_Bold(1);//字体加粗
		range.put_Text(_T("学生成绩表"));//在单元格中输入信息

		//第二行(表头信息:姓名,班级,语文,数学,英语)
		cell = table.Cell(2, 1);
		range = cell.get_Range();
		range.put_Bold(1);
		range.put_Text(_T("姓名"));

		cell = table.Cell(2, 2);
		range = cell.get_Range();
		range.put_Bold(1);
		range.put_Text(_T("班级"));

		cell = table.Cell(2, 3);
		range = cell.get_Range();
		range.put_Bold(1);
		range.put_Text(_T("语文"));

		cell = table.Cell(2, 4);
		range = cell.get_Range();
		range.put_Bold(1);
		range.put_Text(_T("数学"));

		cell = table.Cell(2, 5);
		range = cell.get_Range();
		range.put_Bold(1);
		range.put_Text(_T("英语"));

		//循环生成3-5行学生成绩信息
		for (int j = 0; j < n; j++) {
			cell = table.Cell(3 + j, 1);
			range = cell.get_Range();
			range.put_Bold(0);
			range.put_Text(convert(stu[j].name));

			cell = table.Cell(3 + j, 2);
			range = cell.get_Range();
			range.put_Bold(0);
			range.put_Text(convert(stu[j].clas));

			cell = table.Cell(3 + j, 3);
			range = cell.get_Range();
			range.put_Bold(0);
			str_score.Format(_T("%d"), stu[i].language);
			range.put_Text(str_score);

			cell = table.Cell(3 + j, 4);
			range = cell.get_Range();
			range.put_Bold(0);
			str_score.Format(_T("%d"), stu[i].math);
			range.put_Text(str_score);

			cell = table.Cell(3 + j, 5);
			range = cell.get_Range();
			range.put_Bold(0);
			str_score.Format(_T("%d"), stu[i].english);
			range.put_Text(str_score);
		}

5、修改字体格式(新)

导入接口类:

_Font

然后按照步骤三修改头文件,记得在新添加的头文件中将导入的MSWORD.OLB注释掉:

代码实现:


//修改字体
CFont0 oWordFont;
oWordFont = range.get_Font();
oWordFont.put_Size(16.0f);
oWordFont.put_Name(_T("宋体"));

四、实验结果

文件夹中:

样例文档:

修改字体后:

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值