SAS编程-宏:检查缺失或多余的文件

日常项目中,程序或Outputs一般会提前确定好,通过Excel Tracker或者文件管理系统进行管理。各个公司一般也有相关工具进行检查,以确保Tracker中的程序或Outputs都在输出文件夹中。

不过,本公司工具不会检查文件夹中多余的程序或Outputs。于是,写了个SAS宏程序用于实现这个功能。这个宏程序也可用于检查其它所需文件,例如xml

宏程序汇总在文章末尾,若参考引用,需要结合各自项目路径结构,以及Tracker信息,来更新程序。

宏程序的分为3个部分:

  1. 获取系统或Tracker中的文件名称
  2. 获取文件夹中已有的文件名称
  3. 通过比较以上两类名称,获取缺失或多余的文件

第一部分,可能通过公司的管理工具获取,也可以简单导入EXCEL Tracker。

options validvarname = v7;
proc import datafile = "/xxx/xxx/xxx.xlsx"
   out = tfls dbms = xlsx replace;
run;

第二部分,可以通过Dopen系列函数获取文件名称,具体可以参考文章SAS编程:如何获取某路径下文件的名称?,完整内容可以整合成一个宏程序。

%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 %index(%upcase(&type), SAS) %then %do;
        if strip(scan(filename, 2, "."))="sas" then output;
      %end;

      %if %index(%upcase(&type), RTF) %then %do;
        if strip(scan(filename, 2, "."))="rtf" then output;
      %end;

      %if %index(%upcase(&type), XLSX) %then %do;
        if strip(scan(filename, 2, "."))= "xlsx" then output;
      %end;

      end;
  end;

  keep filename filepath;

  proc sort;
    by filename;
  run;
%end;
%mend get_file;

%get_file(
  dirpath = &path_ana./tables
  ,outdt = source_pgm_tables
  ,type = sas 
);

第三部分,可以通过SQL简单的筛选呈现缺失或多余的文件。

%let out_type = tables;
%let type = T;

proc sql noprint;
  **in tracker not in folder;
  create table source_in_tracker_&out_type. as
    select output_number, base_output_name, program_name, programmer, tester
    from tfls
    where output_type = "&type." and program_name not in
    (
      select filename from source_pgm_&out_type.
    )
  ;

  **in folder not in tracker;
   create table source_in_folder_&out_type. as
      select *
      from source_pgm_&out_type.
      where filename not in
      (
        select program_name from tfls
      )
  ;
quit;

以上三部分,可以整合成一个完整的宏程序,用于检查同一个分析文件夹下的TFLs程序或Output缺失或多余的情况。

以我当前公司的数据结构为例,汇总程序如下。若读者想要引用,需结合项目文件结构以及Tracker信息进行更新。

***1. Get file names in tracker (Company internal tool);
%global path_ana pi_sas;

%let path_ana = /xxx/xxx;
%let pi_sas = pi_xxx_xxx.sas;

%include "&path_ana./docs/pi/&pi_sas.";

%pi_amg757_bla_iss_90d_2023(
  lib = work
  ,txtpath = &path_ana./docs/pi/
  ,outds = all
);


***2. Macro to get  file names in folder;
%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 %index(%upcase(&type), SAS) %then %do;
        if strip(scan(filename, 2, "."))="sas" then output;
      %end;

      %if %index(%upcase(&type), RTF) %then %do;
        if strip(scan(filename, 2, "."))="rtf" then output;
      %end;

      %if %index(%upcase(&type), XLSX) %then %do;
        if strip(scan(filename, 2, "."))= "xlsx" then output;
      %end;

      %if %index(%upcase(&type), XML) %then %do;
        if strip(scan(filename, 2, "."))= "xml" then output;
      %end;

      end;
  end;

  keep filename filepath;

  proc sort;
    by filename;
  run;
%end;
%mend get_file;


***3. Macro to check folder file;
%macro check_folder_file(out_type = tables);

%local type;
%if %upcase(&out_type) = TABLES %then %let type = T;
%else %if %upcase(&out_type) = LISTINGS %then %let type = L;
%else %if %upcase(&out_type) = FIGURES %then %let type = F;

**3.1 Source folder;
%get_file(
  dirpath = &path_ana./&out_type.
  ,outdt = source_pgm_&out_type.
);

proc sql noprint;
  **in tracker not in folder;
  create table source_in_tracker_&out_type. as
    select output_number, base_output_name, program_name, programmer, tester
    from tfls
    where output_type = "&type." and program_name not in
    (
      select filename from source_pgm_&out_type.
    )
  ;

  **in folder not in tracker;
   create table source_in_folder_&out_type. as
      select *
      from source_pgm_&out_type.
      where filename not in
      (
        select program_name from tfls
      )
  ;
quit;


**3.2 QC folder;
%get_file(
  dirpath = &path_ana./&out_type./validation
  ,outdt = qc_pgm_&out_type.
);

proc sql noprint;
  **in tracker not in folder;
  create table qc_in_tracker_&out_type. as
    select output_number, testing_program_name, tester
    from tfls
    where output_type = "&type." and testing_program_name not in
    (
      select filename from qc_pgm_&out_type.
    )
  ;

  **in folder not in tracker;
   create table qc_in_folder_&out_type. as
      select *
      from qc_pgm_&out_type.
      where filename not in
      (
        select testing_program_name from tfls
      )
  ;
quit;


**3.3 Output folder;
%get_file(
  dirpath = &path_ana./&out_type./output
  ,outdt = output_&out_type.
  ,type = rtf-xlsx
);

proc sql noprint;

  **in tracker not in folder;
  create table output_in_tracker_&out_type. as
    select *
    from tfls
    where output_type = "&type." and output_name not in
    (
      select filename from output_&out_type.
    )
  ;

  **in folder not in tracker;
   create table output_in_folder_&out_type. as
      select *
      from output_&out_type.
      where filename not in
      (
        select output_name from tfls
        where output_type = "&type."
      )
  ;

**3.4 xml template folder (internal use);
%get_file(
  dirpath = &path_ana./docs/templates
  ,outdt = tflgen_template
  ,type = xml
);

proc sql noprint;

  **in tracker not in folder;
  create table tflgen_template_in_tracker as
    select *
    from tfls
    where tflgen_allow_code_generation = "Yes" and strip(tflgen_template_name)||".xml" not in
    (
      select filename from tflgen_template
    )
  ;

  **in folder not in tracker;
   create table tflgen_template_in_folder  as
      select *
      from tflgen_template
      where filename not in
      (
        select strip(tflgen_template_name)||".xml" from tfls
        where tflgen_allow_code_generation = "Yes" 
      )
  ;

quit;


%mend check_folder_file;

%check_folder_file(out_type = tables);

%check_folder_file(out_type = listings);

%check_folder_file(out_type = figures);

感谢阅读, 欢迎关注:SAS茶谈!
若有疑问,欢迎评论交流!

梳理不易,转载请注明出处 (by Jihai / SAS茶谈)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容