SAS-RTF的合并【完善篇】

2019-10-20 14:33:02 浏览数 (1)

这一篇推文是针对上一篇推文,进行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清除即可实现页码的修正。

宏程序

嗯,还是早早的把程序贴出来凑字数。代码有点长,建议先转发到朋友圈进行收藏

再回来接着看。

下面是程序部分

代码语言:javascript复制
%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编码间插入一行。这样一行放下面一串代码。
    sectsectdlinex0endnherepgwsxn15840pghsxn12240lndscpsxnheadery1440footery1440marglsxn1440margrsxn1440margtsxn1440margbsxn1440
*/
  %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 ('sectsectdlinex0endnherepgwsxn15840pghsxn12240lndscpsxnheadery1440footery1440marglsxn1440margrsxn1440margtsxn1440margbsxn1440');
    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的内容。程序也就简单的测试了一下,没有进行大规模的验证。欢迎留言指正,以及提出新的功能和需求。(如果小编感兴趣的话,会去完善的。)

0 人点赞