在日常工作中,SDTM、ADaM以及TFL编程的程序、Output名称都会提前规定好,直接根据Spec、Tracker进行编程输出。但是,在一些非常紧急的项目中,SAP、TFLShell没有稳定,就不得不提前进行编程,这时候不可避免地发生Output、程序增删的情况,从而导致文件夹中有多余的SAS程序。
在输出Ouput、程序数目较多的情况下,人工检查多余程序显然不现实。于是,写了个简单的程序,用于移除文件夹中多余的程序。程序的主体内容主要有以下几部分:
- 读入用于保存程序输出列表的Tracker文档;
- 读入目标文件夹下所有SAS程序名称;
- SQL语句判断文件夹中缺少或多余的SAS程序;
- 对于多余的SAS程序,复制备份一版,然后删除;
- 对于缺少的SAS程序,提醒组员新建。
1. 读入EXCEL文档
简单import的语句读入Tracker中程序的信息。
***1. Get program names in SPEC;
%let excel = %str(/aaa/bbb/xxx.xlsx);
options validvarname = v7;
proc import datafile = "&excel." out = pgm dbms = xlsx replace;
run;
2. 读入文件夹下所有SAS程序名称
这个功能在之前文章中介绍过, SAS编程:如何获取某路径下文件的名称? 。
直接集合成一个宏程序,方便后续调用。
***2. Get file name;
%macro get_file(dirpath= , outdt=, type= sas);
%if "&dirpath." ne "" %then %do;
%local dirpath_tmp slash;
%let slash = %substr(%sysfunc(compress(&dirpath., : _ , a d)), 1, 1);
*Remove trailing slash;
%if "%substr(&dirpath.,%length(&dirpath.),1)" = "&slash." %then %let dirpath_tmp=%substr(&dirpath.,1,%length(&dirpath.)-1);
%else %let dirpath_tmp = &dirpath.;
**Dopen--Get filepath;
data &outdt.;
fileres = filename("dirpath", "&dirpath_tmp");
dirid = dopen("dirpath");
num = dnum(dirid);
length direct filename filepath $200;
if dirid > 0 and num >0 then do;
do i = 1 to num;
direct = "&dirpath_tmp.";
filename = dread(dirid, i);
filepath = catx("&slash.", direct, filename);
if strip(scan(filename, 2, "."))="&type." then output;
end;
end;
keep filename filepath;
proc sort;
by filename;
run;
%end;
%else %do;
%put Err-or: Path is missing.;
%end;
%mend;
%get_file(
dirpath = xxxx
,outdt = Source_pgm
);
宏程序输出数据集内容如下:
3. SQL语句判断缺少或多余的程序名称
在获取Tracker中程序列表以及当前文件夹中SAS程序程序名称后,使用SQL语句就进行筛选,就可以获取在Tracker中但不在文件夹中的程序,以及在文件夹中但不在Tracker中的程序。前者需要在文件夹中新建,后者需要从文件夹中移除。
这一部分程序中,会新建一个变量保存,复制粘贴的目标文件,其中宏变量&source_recy
是需要保存多余程序的目标文件夹。
***3. Check differernce between tracker and folder;
%let source_recy = %str(/ccc/ddd/);
proc sql noprint;
**in tracker not in folder;
create table source_inspec as
select program_name, program_programmer_1, program_programmer_2
from pgm
where program_name not in
(
select filename from source_pgm
)
;
**in folder not in tracker;
create table source_infolder as
select *, "&source_recy./"||strip(filename) as filepath_recy
from source_pgm
where filename not in
(
select program_name from pgm
)
;
quit;
程序运行结果如下,变量filepath
保存后续需要复制的文件,变量filepath_recy
复制后的文件地址。两个变量取值后续会使用filename
函数建立文件引用,用于文件的复制和删除。
4.复制多余的程序,并从原文件夹中删除
复制和删除使用的是fcopy
和fdetete
函数,这两个函数的参数都是文件引用,需要提前用filename
进行建立。
一般建立文件引用还可以使用filename
语句,但这个方法不方便调用数据集中的变量值,这个例子中使用filename
函数较为方便。
关于函数FCOPY
与FDELETE
的用法,读者可以直接参考SAS官方文档,这里就不再详细介绍。
***4. Copy and delete programs in folder but not in tracker;
data rst;
set source_infolder;
rc1 = filename("src"||strip(put(_n_, best.)), filepath);
rc2 = filename("dest"||strip(put(_n_, best.)), filepath_recy);
length msg $400;
rc = fcopy("src"||strip(put(_n_, best.)), "dest"||strip(put(_n_, best.)));
if rc = 0 then do;
put filename = " Copy Success";
rfd = fdelete("src"||strip(put(_n_, best.)));
msg = sysmsg();
put filename= rfd= msg=;
end;
else do;
msg = sysmsg();
put filename= rc= msg=;
end;
run;
5. 通知组员新建缺少的SAS程序
SQL语句筛选出在Tracker中但不在Folder中的程序时,可以保留Programmer的信息,这样方便定位到对应组员,方便通知更新。
总结
这篇文章介绍了如何使用SAS编程,移除文件夹中多余的SAS程序。移除的同时,也会备份对应的程序。这个过程涉及多个与文件处理相关的SAS函数,若不熟悉相关含义,读者可以参阅SAS文档。
感谢阅读, 欢迎关注:SAS茶谈!
若有疑问,欢迎评论交流!