VC输出word——读取xml模板并存储为多页(加入分页符)

Posted jingnianq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC输出word——读取xml模板并存储为多页(加入分页符)相关的知识,希望对你有一定的参考价值。

项目中遇到一个新需求,要输出一些数据到word表格,而数据量不确定,超过一页的话需要分割输出多页word。师弟对此表示摇头,没办法,我只好抽时间亲自上阵。

OK,首先要搞明白xml里面word是如何进行分页的。

我在word里面新建了两个文档,一个只有一页,另一个有两页,中间有一个分页符和一个换行符(作用后面再说),像下面两张图一样:

技术分享图片技术分享图片

 

然后将两张图另存为XML模板,这里我导出的是03版本的,其中第一个文档,找到其<body>到</body>之间的字符:

技术分享图片
<w:body>
<wx:sect>
////////////////////////////////////////1(该行是注释)
<w:p wsp:rsidR="00AA0B17" wsp:rsidRPr="00CB3957" wsp:rsidRDefault="0053415C">
<w:pPr>
<w:rPr>
<w:sz w:val="240"/><w:sz-cs w:val="84"/>
</w:rPr>
</w:pPr>
<w:r wsp:rsidRPr="00CB3957">
<w:rPr>
<w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/><w:sz w:val="240"/><w:sz-cs w:val="84"/>
</w:rPr>
<w:t>第一页</w:t>
</w:r>
</w:p>
////////////////////////////////////////2(该行是注释)
<w:sectPr wsp:rsidR="00AA0B17" wsp:rsidRPr="00CB3957">
<w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992" w:gutter="0"/><w:cols w:space="425"/><w:docGrid w:type="lines" w:line-pitch="312"/>
</w:sectPr>
</wx:sect>
</w:body>
View Code

然后对比第二个文档的XML

技术分享图片
 1 <w:body>
 2 <wx:sect>
 3 //////////////////////////////////3
 4 <w:p wsp:rsidR="00704431" wsp:rsidRPr="0024060F" wsp:rsidRDefault="00704431" wsp:rsidP="00704431">
 5 <w:pPr>
 6 <w:rPr>
 7 <w:sz w:val="144"/><w:sz-cs w:val="84"/>
 8 </w:rPr>
 9 </w:pPr>
10 <w:r wsp:rsidRPr="0024060F">
11 <w:rPr>
12 <w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/>
13 <w:sz w:val="96"/><w:sz-cs w:val="84"/>
14 </w:rPr>
15 <w:t>第一页</w:t>
16 </w:r>
17 </w:p>
18 /////////////////////////////////////4
19 <w:p wsp:rsidR="007B1B30" wsp:rsidRDefault="00704431" wsp:rsidP="0024060F">
20 <w:pPr>
21 <w:widowControl/><w:jc w:val="left"/>
22 <w:rPr>
23 <w:rFonts w:hint="fareast"/><w:sz w:val="96"/><w:sz-cs w:val="84"/>
24 </w:rPr>
25 </w:pPr>
26 <w:r wsp:rsidRPr="0024060F">
27 <w:rPr>
28 <w:sz w:val="96"/><w:sz-cs w:val="84"/>
29 </w:rPr>
30 <w:br w:type="page"/>
31 </w:r>
32 </w:p>
33 ////////////////////////////////////5
34 <w:p wsp:rsidR="0080147A" wsp:rsidRPr="0024060F" wsp:rsidRDefault="00704431" wsp:rsidP="0024060F">
35 <w:pPr>
36 <w:widowControl/><w:jc w:val="left"/>
37 <w:rPr>
38 <w:sz w:val="96"/><w:sz-cs w:val="84"/>
39 </w:rPr>
40 </w:pPr>
41 <w:r wsp:rsidRPr="0024060F">
42 <w:rPr>
43 <w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/><w:sz w:val="96"/><w:sz-cs w:val="84"/>
44 </w:rPr>
45 <w:t>第二页</w:t>
46 </w:r>
47 </w:p>
48 //////////////////////////////////////6
49 <w:sectPr wsp:rsidR="0080147A" wsp:rsidRPr="0024060F" wsp:rsidSect="00CE1B00">
50 <w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992" w:gutter="0"/><w:cols w:space="425"/><w:docGrid w:type="lines" w:line-pitch="312"/>
51 </w:sectPr>
52 </wx:sect>
53 </w:body>
View Code

可以看出,第一页和第二页不同的部分在于多了4-5和5-6中间的部分,而5-6部分与第一页其实是类似的,因此换行符就是4-5中间部分代码:

技术分享图片
 1 <w:p wsp:rsidR="007B1B30" wsp:rsidRDefault="00704431" wsp:rsidP="0024060F">
 2  <w:pPr>
 3   <w:widowControl/><w:jc w:val="left"/>
 4   <w:rPr>
 5    <w:rFonts w:hint="fareast"/><w:sz w:val="96"/><w:sz-cs w:val="84"/>
 6    </w:rPr>
 7  </w:pPr>
 8  <w:r wsp:rsidRPr="0024060F">
 9   <w:rPr>
10    <w:sz w:val="96"/><w:sz-cs w:val="84"/>
11   </w:rPr>
12   <w:br w:type="page"/>
13  </w:r>
14 </w:p>
View Code

剩下的事情就简单了,聪明的你肯定知道该怎么从一页的模板生成多页文档了!

我是这么做的:

1.读取xml字符串以后,从主体部分找到并分离该页文档所有内容(1-2):

//找到第一页内容strOnePage,从<wx:sect>后一位到<w:sectPr第一位之间的<w:p到</w:p>的内容(1-2)
//tStr[2]是读取的xml从<w:wordDocument到</w:wordDocument>的所有内容
CString strOnePage(tStr[2]);
int iBegin = strOnePage.Find("<w:sectPr");
strOnePage = strOnePage.Left(iBegin);
int iEnd = strOnePage.Find("<wx:sect>");
iEnd += 8;
strOnePage = strOnePage.Right(strOnePage.GetLength() - iEnd - 1);

2.之后循环所有数据判断该分的页数,找到该内容之后的一个位置作为插入位置(2),然后在第二次循环开始的每次循环中为主体部分在插入位置追加一个分页符字符串(4-5)和一个(1-2),同时替换字符串(1-2)中应该被替换的部分

 1 #define RowInPage 18
 2 //set pages number by iMaxNum, each page can save 18 records
 3 for (int i = 0; i < iMaxNum / RowInPage + 1; i++) {
 4     iBegin = i * RowInPage;
 5     if (iBegin >= iMaxNum) break;
 6     if (0 == i){ 
ReplaceTemplate(tStr[2],outputDatas,iBegin,RowInPage); 7 }else { 8 //find insert position 9 int iInsertPos = tStr[2].Find("<w:sectPr"); 10 //insert a new page 11 //换页符(strSeperator) 12 CString strSeperator("<w:p wsp:rsidR=\\"007B1B30\\" wsp:rsidRDefault=\\"00704431\\"><w:pPr><w:widowControl/><w:jc w:val=\\"left\\"/></w:pPr><w:r><w:br w:type=\\"page\\"/></w:r></w:p>"); 13 //页面内容(strNextPage) 14 CString strNextPage(strOnePage); 15 //替换每一页模板字符串中的内容,根据自己的需求编写 16 ReplaceTemplate(strNextPage,outputDatas,iBegin,RowInPage); 17 //拼接:换页符(strSeperator)+页面内容(strNextPage) 18 strSeperator += strNextPage; 19 tStr[2].Insert(iInsertPos,strSeperator); 20 } 21 }

至此你就可以实现自己的多页文档了,上一下我实现的效果图:

技术分享图片

本次内容结束,胖友再见!


以上是关于VC输出word——读取xml模板并存储为多页(加入分页符)的主要内容,如果未能解决你的问题,请参考以下文章

ImageMagick或GhostScript:将多页TIFF转换为多页PDF

java如何实现读取word文件并按指定word样式格式输出

如何在stimulsoft中为多页报告创建目录?

ImageMagick:在不使用外部文本文件的情况下将选择性图像转换为多页 PDF?

springboot系列(二十五):如何实现单word模板分多页导出?这你得会|超级详细,建议收藏

springboot系列(二十五):如何实现单word模板分多页导出?这你得会|超级详细,建议收藏