这一篇推文是针对上一篇推文,进行SAS程序与功能上的完善!点击此处将可跳转至上一篇推文:SAS-如何简单快捷的实现RTF合并。在上一篇推文推送后,有不少人都对RTF的合并感兴趣,并找到了小编。于是小编决定将RTF的合并完善一下,写成宏程序,以便有需要的朋友可以直接使用。
功能介绍
上一篇小编着重放在原理的介绍以及程序的实现上,太多细节由于小编太懒了没有好好优化。而这篇将是小编在程序上进行优化、功能上进行完善。在介绍功能之前,先来看看小编设置的宏参数。
下图为宏参数及简单说明
功能1:合并顺序的控制
解决办法:通过宏参数order进行控制。如果order=1,则判断待合并的RTF文件所在的路径下是否存在file_order.xls文件,如果不存在,则将RTF文件名输出到此文件中,并跳出当前宏程序的执行。待编辑完此文件后(人工编辑此Excel中的order列的值),再次执行宏,将会根据Excel中的order列的值进行排序(升序),来控制合并的先后顺序。如果order列的值为空,这样的RTF文件将不会被合并。
下图为编辑后的file_order.xls文件
功能2:页码错误的修正
解决办法:将观测中RTF标记符\pgnrestart清除即可实现页码的修正。
宏程序
嗯,还是早早的把程序贴出来凑字数。代码有点长,建议先转发到朋友圈进行收藏
再回来接着看。
下面是程序部分
%macro rtf_merge(inpath=,outfile=,order=,pageyn=1)
options ps=800 ls=256 nonotes nosource nosource2 ;
skip 5;
*获取指定路径下文件夹下RTF文件名称;
filename xcl_fil pipe "dir &inpath.\*.rtf /b/s";
data add_rtflist;
infile xcl_fil truncover;
input fname $char1000.;
order=.;
run;
*默认以文件名进行升序排别;
proc sort data=add_rtflist out=add_rtflist1 sortseq=linguistic(numeric_collation=on);by fname ;quit;
*判断是否需要人工排序;
*当order为1时则需要进行排序,同时根据step判断是否需要将文件名导出到外部Excel进行人工手动添加顺序;
%if &order. eq 1 %then %do;
*判断待合并RTF文件夹下有无file_order.xls文件(存放RTF文件合并先后的排序列表)
*如无,则生成此文件并退出宏的执行;
%if %sysfunc(fileexist(&inpath.\file_order.xls))=0 %then %do;
skip 2;
%put *宏参数order=1,但发现&inpath.\file_order.xls文件未存在,系统将自动生成此文件并退出当前程序的执行!;
%put *请在人工完成此文件的编辑后,再次执行此程序;
proc export data= add_rtflist1
outfile="&inpath.\file_order.xls"
dbms=excel replace label;
sheet="order";
newfile= no;
run;
%return;
%end;
*如文件存在,则将此文件导入;
%if %sysfunc(fileexist(&inpath.\file_order.xls)) %then %do;
proc import out = order1
datafile = "&inpath.\file_order.xls"
dbms = excel replace;
sheet = "order";
dbdsopts = "firstobs=1";
run;
data _null_ ;
set order1(where=(missing(order) ));
put "RTF文件(将不会参与RTF的合并):" fname;
run;
skip 3;
*如果数据集观测为0,1,则不进行合并,跳出循环;
%let dsid=%sysfunc(open(order1));
%let _checkobs=%sysfunc(attrn(&dsid,nobs));
%let rc= %sysfunc(close(&dsid));
%if &_checkobs. eq 0 or &_checkobs. eq 1 %then %return;
proc sort data=order1(where=(^missing(order) )) out=add_rtflist1 sortseq=linguistic(numeric_collation=on);by order fname;quit;
%end;
%end;
*定义filename定义路径便于合并;
data _null_;
set add_rtflist1 end=last;
rtffn=strip("filename rtffn")||strip(_N_)||right(' "')||strip(fname)||strip('" lrecl=5000 ;');
call execute(rtffn);
call symput('ard_rtf'||compress(put(_n_,best.)),strip(fname));
if last then call symput('maxn',vvalue(_n_));
run;
skip 3;
%do i=1 %to &maxn.;
/*将文件导入SAS中,变成SAS数据集*/
%put 即将完成对文件:&&ard_rtf&i. 的合并!;
data have&i. ;
infile rtffn&i. truncover;
informat line $5000.;format line $5000.;length line $5000.;input line $1-5000;
line=strip(line);
run;
/*实现三个处理过程:
1.除首个RTF外,其他RTF第一行的“{”要删除。
2.除最后一个RTF外,其他RTF最后一行的“}”要删除。
3.在每个俩个RTF编码间插入一行。这样一行放下面一串代码。
\sect\sectd\linex0\endnhere\pgwsxn15840\pghsxn12240\lndscpsxn\headery1440\footery1440\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440
*/
%if &i. eq 1 %then %do;
data want;
set have&i. end=last;
if last then line=substr(strip(line),1,length(strip(line))-1);
run;
%end;
%if &i. ne 1 %then %do;
proc sql;
insert into want(line) values ('\sect\sectd\linex0\endnhere\pgwsxn15840\pghsxn12240\lndscpsxn\headery1440\footery1440\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440');
quit;
data have&i.;
set have&i. end=last;
if last then line=substr(strip(line),1,length(strip(line))-1);
if _n_=1 then line=substr(line,2);
run;
data want;
set want have&i. ;
run;
%if &i. eq &maxn. %then %do;
data want;
set want end=last;
if last then line=strip(line)||strip("}");
%if &pageyn. eq 1 %then %do; /*删除 pgnrestart 即可解决页码错乱问题*/
if index(line,'\pgnrestart\') then line=compress(tranwrd(line,'\pgnrestart',' '));
%end;
run;
%end;
%end;
proc delete data= have&i.;quit;
%end;
%put 已完成所有文件的合并!;
/*文件输出成合并完成后的RTF*/
data _null_;
set want;
file "&outfile." lrecl=5000 ;
put line ;
run;
proc delete data=want;quit;
%mend;
注意事项
在写完代码后,一向自信的小编也难免不自信,为了测试宏的通用性,于是小编找了一位其他公司的朋友帮忙,跑了一下程序果真发现bug一大堆!!!辛亏小编有先见之明,没有直接发推送,不然就被啪啪啪的打脸。
为了不被打脸
上面的程序是在测试后,反复修改后诞生了,即便⁶₆⁶ 如小编,也有难以解决的bug~于是就有了这里的注意事项:.
目前已发现待解决的Bug就是,如果RTF内容为中文,并后期对RTF内容做了编辑(加颜色等等任何操作),合并的时候页眉页脚等处会发生乱码!如果内容是英文,那就可以尽情的放肆,随意修改编辑RTF的内容。程序也就简单的测试了一下,没有进行大规模的验证。欢迎留言指正,以及提出新的功能和需求。(如果小编感兴趣的话,会去完善的。)