公告

[公告]
2014/01/17
由於已經是faculty的關係,不太有足夠時間寫部落格。因此更新的速度會相當緩慢。再加上近幾年來SAS GLOBAL FORUM沒有出現讓我覺得驚艷的技術文件,所以能分享的文章相對也減少許多。若有人推薦值得分享的SAS技術文件,請利用『問題討論區』告知。

2013/07/19
臉書留言板的功能因為有不明原因故障,因此特此移除。而intensedebate的留言板因管理不易,也一併移除。目前已經開啟內建的 G+ 留言系統,所以請有需要留言的朋友,可直接至『問題討論區』裡面留言。


2007年3月29日 星期四

Switch Data Source and Output Destination without Changing Programs

原文載點:http://www2.sas.com/proceedings/sugi29/049-29.pdf

有些人寫程式時,習慣將資料、程式、輸出報表或 log 檔分別存在不同的檔案夾內。當計畫越接越多後,難免會用不同的檔案夾來放這些檔案。但每次一換檔案夾,所有程式內部的路徑都要更著修改,還挺麻煩的。 David Shen 和 Zaizei Lu 於 2003 年的 SUGI 29 上發表了一個 macro,可以很輕易的轉換資料來源和輸出報表的目的檔案夾。重點是,不需要更改原始程式。

這個 macro 可以進行三項動作:
(一)在不變動原始程式的情況下,修改資料來源、更改輸出報表的檔名、還有在 ODS 內的設定路徑。
(二)修改輸出報表存檔的路徑。
(三)可以批次執行不同的程式。

程式如下所示:

%MACRO RUNNER(_sasloc=, _lstloc=, _logloc=, datapath=, csvfile=, csvonly=);

options noxwait;

%if &_lstloc eq %then %do;
%let _lstloc=&_sasloc;
%end;

%if &_logloc eq %then %do;
%let _logloc=&_lstloc;
%end;

%let Progn=;

data saslst (keep=sasprog);
rc=filename('prog', "&_sasloc");
dsid=dopen('prog');
if dsid then do;
n=dnum(dsid);
do i=1 to n ;

sasprog=dread(dsid, i);

sasprog=upcase(trim(left(sasprog)));
if scan(sasprog, 2, '.')='SAS' then output;
end;
end;
else do; *if dir not exist;
put / "*-SAS Program Location Does not Exist.-* ";
end;
rc=dclose(dsid); *close dir;
run;

data saslst;
length sasprog $100;
set saslst;
outfile=' ';
run;

proc sort data=saslst;
by sasprog;
run;

%if &csvfile ne %then %do;
proc import datafile="&csvfile"
out=sascsv dbms=csv replace;
getnames=yes; *get column name;
datarow=2; *data from 2nd row;
run;

data sascsv;
length sasprog $100;
set sascsv;
sasprog=upcase(trim(left(sasprog)));
run;

proc sort data=sascsv;
by sasprog;
run;

data saslst;
length outfile $500;
merge saslst (in=in_lst)

sascsv (in=in_csv);
by sasprog;
%if %upcase(&csvonly)=YES %then %do;
if in_lst and in_csv;
%end;
%else %do;
if in_lst;
%end;
run;
%end;

data _null_; *program names to macro vars;
set saslst end=last;
call symput ('_Prog'||left(_N_), sasprog);
call symput ('_outf'||left(_N_), outfile);
if last then call symput('Progn', trim(left(_N_)));
run;

%if &progn ne %then %do;
data _null_; *check lst dir;
rc=filename('lst', "&_lstloc");
dsid=dopen('lst');
if not dsid then do;
call system("mkdir &_lstloc");
put "*-New LST Dir &_lstloc Has been Created.";
end;
rc=dclose(dsid);
rc=filename('log', "&_logloc"); *check log dir;
dsid=dopen('log');
if not dsid then do;
call system("mkdir &_logloc");
put "*-New LOG Dir &_logloc Has been Created.";
end;
rc=dclose(dsid);
run;

%do Runner=1 %to &progn;
%put *==============================================*;
%put *== RUNNER=&runner PROGRAM=&&_prog&runner;
%put *==============================================*;
%let loglst=%scan(&&_prog&runner, 1, '.');
filename logname "&_logloc\&loglst..log";
filename lstname "&_lstloc\&loglst..lst";

%let filepath=&&_outf&runner;
%if &filepath ne %then %do;
%let path=%substr(&filepath, 1, %length(&filepath)- %length(%scan(&filepath, -1, '\'))-1 );
%put ---Path To Save File=&path ---;
filename path "&path";

%if %sysfunc(fileref(path))=0 %then %do;
%put ---Output File Location Existed---;
%end;
%else %do;
%sysexec "mkdir &path";
%put ---New &path Created To Save File---;
%end;
filename filepath "&filepath";
%end;

%if &datapath ne %then %do;
libname datapath "&datapath";
%end;

%let sasprog=&_sasloc\&&_prog&runner;

proc printto log=logname new;
proc printto print=lstname new;

options nosymbolgen nomacrogen nomprint nomlogic;

%inc "&sasprog";
run;
proc printto log=log; run;
proc printto print=print;
run;
proc datasets lib=work kill nowarn nolist;
quit;

libname datapath clear;
filename filepath clear;
%end;
%end;

%else %do;
%put *------------------------------------*;
%put *--No SAS Program Found in &_SASLOC--*;
%put *------------------------------------*;
%end;

%mend;


在執行 %Runner 之前,記得在每個程式開頭的 libname 和 filename 周圍加上額外的程式碼(以下藍色的部分):

%macro SetInOut;
%let rc=%sysfunc(libref(datapath));
%if &rc %then %do;
libname datapath 's:\study\test\data';
%end;

%let rc=%sysfunc(fileref(filepath));
%if &rc>0 %then %do;
filename filepath 's:\study\test\draft.rtf';
%end;
%mend;

%SetInOut;


換句話說,程式碼中紅色的部分是你本來就寫在程式裡面的部分,但要在周圍加上藍色部分的程式碼。由於在最後面加上一個 %SetInOut; 的程式碼,所以當原始程式執行時,這個 macro 也會一併執行。

最後,再執行 %Runner 即可。簡單範例如下:

%Runner (_sasloc =s:\study\prod\sas,
_lstloc =,
_logloc =,
datapath = s:\study\prod\data,
csvfile = s:\stusy\prod\SasOut.csv,
csvonly =);



CONTACT INFORMATION

Zaizai Lu
AstraZeneca Pharmaceutical
Wilmington, Delaware
Zz_lu@hotmail.com

David Shen
ClinForce Consulting
Philadelphia, PA
Shenda168@hotmail.com

沒有留言:

張貼留言

要問問題的人請在文章下方的intensedebate欄位留言,請勿使用blogger預設的意見表單。今後用blogger意見表單留言的人我就不回應了。

CODE { display: block; /* fixes a strange ie margin bug */ font-family: Courier New; font-size: 8pt; overflow:auto; background: #f0f0f0 url(http://klcintw.images.googlepages.com/Code_BG.gif) left top repeat-y; border: 1px solid #ccc; padding: 10px 10px 10px 21px; max-height:200px; height:200px; // for IE6 line-height: 1.2em; }