目次
1.サンプルデータ
サンプルとして、以下2つのSASデータセットをExcelファイルとして出力してみます。
data hojin_list;
infile datalines dlm="," dsd missover;
input no hojin_name:$200.;
label no="No." hojin_name="法人名";
datalines;
1,日本郵船株式会社
2,株式会社Mizkan J plus Holdings
3,公益社団法人福岡医療団
4,社団医療法人 啓愛会
5,一般社団法人 北陸地区信用金庫協会
6,兵庫県弁護士協同組合
7,学校法人 藤田学園
8,一般財団法人東北電気保安協会
9,社会医療法人蘇西厚生会
10,公益社団法人福岡医療団
;
run;
data kojin_list;
infile datalines dlm="," dsd missover;
input
first_name :$20.
last_name :$20.
sex
age
;
datalines;
Kaori,Ito,2,22
Hideki,Tanaka,1,35
Taro,Yamada,1,30
Hiroki,Sato,1,25
Mizue,Ishii,2,54
Yuko,Koyama,2,30
Ichiro,Suzuki,1,.
Shinji,Suda,1,27
Reiko,Yamauchi,2,42
Mituru,Adachi,3,45
;
run;
2.展開例
以下は展開例で、引数delの値について、1段目がYで、2段目をNにしています。
%export_excel(indata=hojin_list, outfile=C:\Blog\SAS\export_excel\リスト.xlsx, sheet=法人, del=Y);
%export_excel(indata=kojin_list, outfile=C:\Blog\SAS\export_excel\リスト.xlsx, sheet=個人, del=N);
1段目をdel=Yにしているのは、同一ファイルが存在している場合に、事前に削除しておくためです。
2段目をdel=Nにしているのは、「リスト.xlsx」を削除せずに、シート「個人」を追加するためです。
以下のように、2シート「法人」と「個人」が存在する「リスト.xlsx」が作成されました。
3.REPLACEオプションが効かない?
PROC EXPORTプロシジャのオプションに、同一ファイルが存在する場合に置換するためのREPLACEオプションがあるのですが、これを指定しても意図した置換にならないんですよね・・・。
同一ファイルが存在している状態で、REPLACEオプションで置換を試みると、ファイルが破損し、開くときに以下のようなコメントが表示されます。
以下のように、不要なシート「回復済み_Sheet1」が生成され、意図通りの置換にならないです。
それ故、引数delを設けており、事前に削除できるようにしている、というわけです。
(以前は正しく置換できていたような・・・)
4.参考プログラム
以下は、参考プログラムになります。
右上のコピーボタンを押せば、プログラム全体をコピーできます。
%macro export_excel(indata=, outfile=, sheet=, label=N, del=N, fit=N);
%put --------------------------------------------------;
%put export_excel; /*SASデータセットをExcelファイルとして出力する*/
%put &=indata; /*データセット名を指定*/
%put &=outfile; /*出力ファイルをフルパス指定*/
%put &=sheet; /*任意のシート名を指定(Excelの仕様で31バイト以上は出力不可)*/
%put &=label; /*変数名ではなくラベルを出力する場合はYを指定(既定値=N)*/
%put &=del; /*事前に同一ファイルを削除する場合はYを指定(既定値=N)*/
%put &=fit; /*列幅を自動調整する場合はYを指定(既定値=N)*/
%put --------------------------------------------------;
/*同一ファイルが存在する場合に削除する*/
%if %upcase(&del.) = Y %then %do;
data _null_;
rc=filename("oldfile","%superq(outfile)");
rc=fdelete("oldfile");
run;
%end;
%if %sysfunc(lengthn(%superq(sheet))) > 31 %then %do;
%put WARNING: シート名は31バイト以内としてください。正しく出力されない可能性があります。&=sheet;
%end;
proc export data=&indata.
outfile="%superq(outfile)"
dbms=xlsx
%if %upcase(&label.) = Y %then %do; label %end;
replace
;
sheet="&sheet."n;
run;
/*.bakファイルが存在する場合は削除*/
data _null_;
rc=filename("bakfile","%superq(outfile).bak");
rc=fdelete("bakfile");
run;
/*列幅の自動調整(エクセルファイルが破損、PW設定などされている場合、エラーとなるため注意)*/
%if %upcase(&fit.)=Y %then %do;
%let path=%substr(%superq(outfile), 1, %length(%superq(outfile))-%length(%scan(%superq(outfile), -1, '\'))-1);
%if %substr(%superq(path), %length(%superq(path))) = \ %then %do;
%put ERROR: outfileのバックスラッシュの入力が不正です。&=outfile;
%abort;
%end;
option noxwait xsync;
filename outpath "%superq(path)";
data _null_;
call symputx("outpath",pathname("outpath"));
text="'"||tranwrd(strip(pathname("outpath")),'','" "')||'\エクセル設定用.vbs'||"'";
call symputx("xcommand",text);
run;
filename vbs "%superq(path)\エクセル設定用.vbs" encoding="sjis";
proc stream outfile=vbs resetdelim="br"; begin
Set ex=CreateObject("Excel.Application") br newline;
ex.Visible=True br newline;
ex.Workbooks.Open("%superq(outfile)") br newline;
ex.DisplayAlerts=False br newline;
ex.ActiveWorkbook.Sheets("%superq(sheet)").Columns.AutoFit br newline;
ex.ActiveWorkbook.SaveAs "%superq(outfile)" br newline;
ex.Quit
;;;;
filename vbs clear;
data _null_;
call system(&xcommand.);
rc=filename("vbs","%superq(path)\エクセル設定用.vbs");
rc=fdelete("vbs");
run;
filename outpath clear;
option noxsync;
%end;
%mend export_excel;