SAS編程:如何將數(shù)據(jù)集批量輸出到Excel屡谐?

有時(shí)為了解項(xiàng)目數(shù)據(jù)結(jié)構(gòu)述么,需要查看不少原始數(shù)據(jù)。簡(jiǎn)單的記錄篩選愕掏,SAS操作起來不復(fù)雜度秘,但是對(duì)于大批量數(shù)據(jù)記錄的查看,SAS篩選就顯得繁瑣亭珍。這種情況下敷钾,將數(shù)據(jù)集批量輸出到Excel中進(jìn)行查看,不失為一個(gè)很好的方法肄梨。

數(shù)據(jù)集批量輸出的要達(dá)到什么效果呢?出于篩選方便的考慮挠锥,所有數(shù)據(jù)集保存在一個(gè)Excel文件中众羡,數(shù)據(jù)集名稱作為對(duì)應(yīng)的Sheet名稱,每個(gè)表單凍結(jié)首行蓖租,并且直接設(shè)置首行篩選粱侣。

這樣打開Excel文件,就可以不需要額外設(shè)置蓖宦,可以直接瀏覽齐婴、篩選數(shù)據(jù)。

在SAS編程中稠茂,常見的批量處理的方法有兩種柠偶,一是宏程序中的宏循環(huán),二是call execute語句睬关。

下面介紹整個(gè)輸出的實(shí)現(xiàn)過程诱担,先從單個(gè)數(shù)據(jù)集輸出開始。

1. 單個(gè)數(shù)據(jù)集的輸出

SAS程序參考之前的文章SAS編程:輸出SAS數(shù)據(jù)集(Listing)到EXCEL电爹。通常蔫仙,使用export過程步,進(jìn)行簡(jiǎn)單的輸出丐箩;使用ods excel語句以及report過程步摇邦,進(jìn)行復(fù)雜的輸出設(shè)置恤煞,例如,凍結(jié)標(biāo)題施籍、首行自動(dòng)篩選等

ods excel file = "E:\999_test.xlsx" 
     options(sheet_name="Class"  frozen_headers="Yes" autofilter = "Yes");

proc report data = sashelp.class;
 column _all_;
run;

ods excel close;

輸出結(jié)果如下:

單個(gè)數(shù)據(jù)集實(shí)現(xiàn)了對(duì)應(yīng)格式的輸出阱州。

2. 兩個(gè)數(shù)據(jù)集的輸出

還是參考之前的文章,第二個(gè)ods excel語句輸出不添加file=語句法梯,這樣兩個(gè)數(shù)據(jù)集就輸出到同一個(gè)Excel文件的不同sheet中苔货。

ods excel file = "E:\999_test\test.xlsx" 
     options(sheet_name="Class"  frozen_headers="Yes" autofilter = "Yes");

proc report data = sashelp.class;
run;

ods excel 
     options(sheet_name="Cars" frozen_headers = "Yes" autofilter="Yes");

proc report data = sashelp.cars;
 column _all_;
run;

ods excel close;

3個(gè)及以上數(shù)據(jù)集的輸出,與此類似立哑。

3. 邏輯庫內(nèi)所有數(shù)據(jù)集的輸出

顯然夜惭,如果照著上面舉例手動(dòng)添加數(shù)據(jù)集的輸出程序,輸出邏輯庫中的所有數(shù)據(jù)集的過程就太過繁瑣铛绰,所以需要批量處理诈茧。

常見的批量處理的方法有兩種,一是宏循環(huán)捂掰,二是call execute語句敢会。下面來介紹這兩種方法的實(shí)現(xiàn)。

不管哪種方法这嚣,首先需要獲取邏輯庫中的數(shù)據(jù)集名稱鸥昏,以方便引用。這里姐帚,以SASHelp邏輯庫中前10個(gè)數(shù)據(jù)集進(jìn)行舉例吏垮。

**Get datasets' names;
data tables;
  set sashelp.vtable;
  where libname = "SASHELP";

  if _n_ <= 10;
  keep libname memname;
run;

輸出結(jié)果如下:

Tables
3.1 宏循環(huán)批量輸出數(shù)據(jù)集

SAS宏可以理解成是“代碼生成器”,宏程序的批量處理是通過宏循環(huán)實(shí)現(xiàn)罐旗。

參考兩個(gè)數(shù)據(jù)集輸出的代碼膳汪,對(duì)于不同數(shù)據(jù)集,sheet_name=data=選項(xiàng)值是變化的九秀∫潘裕考慮到SAS數(shù)據(jù)集名稱是不區(qū)分大小寫,這兩個(gè)選項(xiàng)值可以看作是相同的鼓蜒。

宏循環(huán)的思路是痹换,將數(shù)據(jù)集的名稱保存到各個(gè)宏變量中,這些宏變量名稱的前綴相同友酱,后綴以序號(hào)結(jié)尾晴音。這里我將其稱為,宏變量序列缔杉。獲取宏變量序列后锤躁,利用循環(huán)變量,從而實(shí)現(xiàn)“代碼生成”的效果或详。

3.1.1 宏變量序列的生成

宏變量序列的生成常用也有2種方法:

  1. Proc SQL 中的into :語句
  2. Data步中的call symputx語句
3.1.1.1 Proc SQL生成宏變量序列

into :語句之前介紹過系羞,可以參考SAS編程:Proc SQL生成宏變量時(shí)INTO子句的使用 郭计。使用這個(gè)方法,需要獲取數(shù)據(jù)集的記錄數(shù)椒振,這里就不介紹如何獲取數(shù)據(jù)集的記錄數(shù)了昭伸,直接手動(dòng)賦值為10。

**Save tables' names in macro vars by sql;
proc sql noprint;
 select memname
   into :memname1- :memname10
   from tables;
quit;

%put memname1 = &memname1.;
%put memname10 = &memname10.;

輸出結(jié)果如下:

3.1.1.2 Data 步中生成宏變量序列

與SQL中依靠后綴序列進(jìn)行計(jì)數(shù)不同澎迎,Data步中數(shù)據(jù)集自帶的自動(dòng)變量_n_可以實(shí)現(xiàn)計(jì)數(shù)的功能庐杨。

**Save tables' names in macro vars by data step;
data _null_;
   set tables;
    call symputx("name"||strip(put(_n_, best.)), strip(memname));
run;

%put memname1 = &name1.;
%put memname10 = &name10.;

輸出結(jié)果與SQL結(jié)果一致,可以看出Data步方法實(shí)現(xiàn)可以省去獲取數(shù)據(jù)集記錄數(shù)的步驟夹供,整體上代碼比較簡(jiǎn)潔灵份。

3.1.2 宏循環(huán)批量輸出數(shù)據(jù)集

宏循環(huán)需要處理,第一個(gè)數(shù)據(jù)集與其他數(shù)據(jù)集輸出的不同(后續(xù)數(shù)據(jù)集不需要file=選項(xiàng))哮洽,用判斷語句進(jìn)行區(qū)分填渠。

如果想要查看宏程序具體的運(yùn)行代碼,可以參考文章SAS編程:檢查宏程序issue思路介紹鸟辅,里面有對(duì)mprint選項(xiàng)的介紹氛什。

調(diào)試程序的時(shí)候,發(fā)現(xiàn)SASHelp.BIRTHWGT這個(gè)數(shù)據(jù)集居然有10萬條記錄匪凉,ods excel語句輸出會(huì)出現(xiàn)內(nèi)存不足等問題枪眉,于是使用ods tagsets.excelxp進(jìn)行輸出

**Export datasets to Excel file using macro loop;
%macro loop;
 
%do a = 1 %to 10;
  %if &a. = 1 %then %do;
    ods tagsets.excelxp file = "E:\999_test\test.xlsx" 
      options(sheet_name="&name1."  frozen_headers="Yes" autofilter = "Yes");

    proc report data = sashelp.&name1.;
     column _all_;
    run;
  %end;
  
  %else %do;
    ods tagsets.excelxp options(sheet_name="&&name&a." frozen_headers = "Yes" autofilter="Yes");

    proc report data = sashelp.&&name&a.;
     column _all_;
    run;
  %end;

%end;

ods tagsets.excelxp close;

%mend;

%loop;

問題處理

但使用ods tagsets.excelxp有會(huì)出現(xiàn)一個(gè)問題洒缀,輸出文件用Excel打開的話瑰谜,會(huì)顯示如下內(nèi)容,無法打開文件:

image.png

WPS可以正常打開輸出文件树绩,10個(gè)數(shù)據(jù)集完整的輸出到Excel文件中。

也可以使用.xls作為輸出文件的后綴隐轩,這時(shí)文件可以用Excel打開饺饭,不過會(huì)有Warning提示。

ods tagsets.excelxp file = "E:\999_test\test.xls" 

ods tagsets.excelxp close;

還有一個(gè)退而求其次的方法职车,舍棄Excel的設(shè)置瘫俊,使用export過程步,進(jìn)行簡(jiǎn)單的輸出悴灵,不進(jìn)行Excel的屬性設(shè)置扛芽,后續(xù)再使用VBA對(duì)各個(gè)Sheet進(jìn)行批量屬性設(shè)置。

%macro loop;
  %do a = 1 %to 10;

    proc export data=sashelp.&&name&a.
        outfile='E:\999_test\test.xlsx'
        dbms=xlsx replace;
        sheet = "&&name&a.";
    run;

  %end;
%mend;

%loop;
3.2 call execute()批量輸出數(shù)據(jù)集
3.2.1 call execute()的簡(jiǎn)單介紹

官方文檔是這樣积瞒,介紹call execute()語句的:

Resolves the argument, and issues the resolved valuefor execution at the next step boundary.
(解析參數(shù)川尖,并發(fā)出已解析的值以便在下一步邊界執(zhí)行。)

call execute()是為了在Data步中執(zhí)行其他完整的SAS代碼茫孔,括號(hào)里面的內(nèi)容是一段完整的字符串叮喳,舉個(gè)簡(jiǎn)單的例子被芳。

data _null_;
  call execute(
  '
  data class;
    set sashelp.class;
  run;
  '
 );
run;

以上的代碼就是直接引號(hào)中的程序。這里讀者可能會(huì)有疑問馍悟,直接寫一遍引號(hào)中的代碼再運(yùn)行畔濒,不是更方便嗎?

單從直接調(diào)用簡(jiǎn)單的SAS程序來講锣咒,這確實(shí)是多此一舉侵状。但是,call execute()是可以直接調(diào)用數(shù)據(jù)集中的記錄值毅整,進(jìn)行運(yùn)行趣兄。再舉個(gè)例子:

data tmp;
   a = "class";
run;

data _null_;
  set tmp;
  call execute(
  '
  data class;
    set sashelp.'||strip(a)||';
  run;
  '
 );
run;

以上程序運(yùn)行的結(jié)果,是解析數(shù)據(jù)集Tmp中變量a的值毛嫉,帶入引號(hào)中的程序诽俯。可以這樣理解承粤,括號(hào)中的內(nèi)容依舊是一個(gè)待運(yùn)行的字符串暴区,只不過這個(gè)字符串拼接了Tmp數(shù)據(jù)集中變量a的值

讀者看到這里可能又會(huì)有疑問辛臊,如果數(shù)據(jù)集中有多條數(shù)據(jù)仙粱,call execute()將如何處理呢?

如果數(shù)據(jù)集中有多條數(shù)據(jù)彻舰,call execute()就會(huì)運(yùn)行多次程序伐割,按數(shù)據(jù)集記錄的行數(shù)進(jìn)行迭代,每一次運(yùn)行的程序會(huì)更新"變量a"的值刃唤。

如果Tmp數(shù)據(jù)集中有2條記錄隔心,class, cars,那么最后執(zhí)行的代碼如下:

 data class;
    set sashelp.class;
 run;

 data class;
    set sashelp.cars;
 run;
3.2.2 call execute()批量輸出數(shù)據(jù)集到EXCEL

有了上面的介紹尚胞,直接看批量輸出數(shù)據(jù)集的代碼:

data _null_;
  set tables end = eof;
  if _n_ = 1 then call execute(
  '
  ods tagsets.excelxp file = "E:\999_test\test.xlsx" 
    options(sheet_name="'||strip(memname)||'"  frozen_headers="Yes" autofilter = "Yes");

  proc report data = sashelp.'||strip(memname)||';
    column _all_;
  run;
  '
  );

  else call execute(
  '
  ods tagsets.excelxp 
    options(sheet_name="'||strip(memname)||'"  frozen_headers="Yes" autofilter = "Yes");

  proc report data = sashelp.'||strip(memname)||';
    column _all_;
  run;
  '
  );

  if eof then call execute(
  '
  ods tagsets.excelxp close;
  '
  );
run;

程序中硬霍,通過_n_這個(gè)自動(dòng)變量進(jìn)行區(qū)分是否是第一條記錄,然后進(jìn)行對(duì)應(yīng)的設(shè)置笼裳;end = eof選項(xiàng)唯卖,新建eof變量用于判斷記錄是否到達(dá)尾行,尾行需要將輸出進(jìn)行關(guān)閉躬柬。

輸出結(jié)果與前面SQL一致:

總結(jié)

文章介紹了2種將數(shù)據(jù)集批量輸出到Excel中的方法拜轨,宏循環(huán)和call execute()語句。宏循環(huán)允青,是先將所有數(shù)據(jù)集名稱保存到宏變量序列中橄碾,然后通過宏循環(huán)進(jìn)行調(diào)用。call execute()語句,是通過獲取數(shù)據(jù)集變量值構(gòu)建完整的運(yùn)行程序堪嫂。

本質(zhì)上偎箫,宏循環(huán)和call execute()語句作用是相同的,都是“代碼生成器”皆串。

在介紹宏循環(huán)實(shí)現(xiàn)的過程中淹办,還介紹了2種生成宏變量序列的方法。

感謝閱讀恶复, 歡迎關(guān)注:SAS茶談怜森!
若有疑問,歡迎評(píng)論交流谤牡!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末副硅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子翅萤,更是在濱河造成了極大的恐慌恐疲,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件套么,死亡現(xiàn)場(chǎng)離奇詭異培己,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胚泌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門省咨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人玷室,你說我怎么就攤上這事零蓉。” “怎么了穷缤?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵敌蜂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我津肛,道長(zhǎng)紊册,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任快耿,我火速辦了婚禮,結(jié)果婚禮上芳绩,老公的妹妹穿的比我還像新娘掀亥。我一直安慰自己,他們只是感情好妥色,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布搪花。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撮竿。 梳的紋絲不亂的頭發(fā)上吮便,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音幢踏,去河邊找鬼髓需。 笑死,一個(gè)胖子當(dāng)著我的面吹牛房蝉,可吹牛的內(nèi)容都是我干的僚匆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼搭幻,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼咧擂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起檀蹋,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤松申,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后俯逾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贸桶,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年纱昧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刨啸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡识脆,死狀恐怖设联,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灼捂,我是刑警寧澤离例,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站悉稠,受9級(jí)特大地震影響宫蛆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜的猛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一耀盗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卦尊,春花似錦叛拷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裙椭。三九已至,卻和暖如春署浩,著一層夾襖步出監(jiān)牢的瞬間揉燃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工筋栋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炊汤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓二汛,卻偏偏與公主長(zhǎng)得像婿崭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肴颊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容