SASマクロ データの入出力

【SAS】テキストファイル(カンマ区切りCSV、タブ区切りTSV)の出力

1.サンプルデータ

以下のサンプルデータを使用して、展開例を示します。

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,公益社団法人福岡医療団
11,田中貴金属労働組合
12,医療法人社団 友愛病院会
13,東京海上日動調査サービス共済組合
14,社会医療法人財団白十字会
15,オカムラグループ健康保険組合
16,日本ヒューレット・パッカード合同会社
17,社団医療法人 啓愛会
;
run;

hojin_list
 

2.展開例

・カンマ区切りで出力

カンマ区切りで出力する場合は、2つの引数を指定するだけで出力できます。

%output_text(
	indata	=hojin_list, 
	outfile	=C:\Blog\SAS\output_text\法人リスト.csv
);

output_text_csv
 

・タブ区切りで出力

タブ区切りで出力する場合は、引数tab=Yを指定します。

%output_text(
	indata	=hojin_list, 
	outfile	=C:\Blog\SAS\output_text\法人リスト.txt,
	tab		=Y
);

output_text_tab
 

・ヘッダーをラベルで出力

ヘッダー部分を変数名ではなくラベルで出力する場合は、引数label=Yを指定します。

%output_text(
	indata	=hojin_list, 
	outfile	=C:\Blog\SAS\output_text\法人リスト_ラベル出力.txt,
	tab		=Y,
	label	=Y
);

以下のように、変数名ではなく、ラベルが出力されています。
output_text_tab_label
 

・ヘッダー無しで出力

ヘッダー部分を出力しない場合は、引数header=N(Y以外であればOK)を指定します。

%output_text(
	indata	=hojin_list, 
	outfile	=C:\Blog\SAS\output_text\法人リスト_ヘッダー無し.txt,
	tab		=Y,
	header	=N
);

以下のように、ヘッダーが出力されておらず、1行目からデータ部分が出力されています。
output_text_tab_noheader
 

・UTF-8で出力

文字コードをUTF-8で出力する場合は、引数encoding=utf8を指定します。

%output_text(
	indata	=hojin_list, 
	outfile	=C:\Blog\SAS\output_text\法人リスト_UTF-8.txt,
	tab		=Y,
	encoding=utf8
);

以下のように、文字コードがUTF-8(BOM付き)で出力されています。
output_text_tab_utf8
 

・UTF-8、BOMなしで出力

BOMなしで出力する場合は、引数encoding=utf8、bom=N(Y以外であればOK)を指定します。

%output_text(
	indata	=hojin_list, 
	outfile	=C:\Blog\SAS\output_text\法人リスト_UTF-8_BOMなし.txt,
	tab		=Y,
	encoding=utf8,
	bom		=N
);

先ほどとは違って、BOMなしに変わりました。
output_text_tab_utf8_nobom
 

3.PROC EXPORTで出力しない理由

PROC EXPORTプロシジャのみで出力すると、以下のように、ラベルにダブルクォテーション「""」が必ず付いてしまいます。
proc_export
ダブルクォテーション「""」が問題ない方は、PROC EXPORTプロシジャのみで出力しても問題ありません。
 

4. 参考プログラム

以下は、参考プログラムになります。
右上のコピーボタンを押せば、プログラム全体をコピーできます。

%macro output_text(indata=, where=, var=, outfile=, tab=N, header=Y, label=N, encoding=sjis, bom=Y, temp_fol=c:);
%put --------------------------------------------------;
%put output_text;	/*テキストファイル(カンマ区切りcsv、タブ区切りtsv)の出力*/
%put &=indata;		/*入力データセットを指定(データセットオプションの指定可)*/
%put &=where;		/*絞り条件を指定(省略した場合は全レコード出力)*/
%put &=var;			/*出力変数名を指定(指定した順番で出力される、省略した場合は全変数出力)*/
%put &=outfile;		/*出力ファイル名を指定*/
%put &=tab;			/*Yを指定した場合はタブ区切り、それ以外はカンマ区切り(既定値=N)*/
%put &=header;		/*Yを指定した場合はヘッダーを出力し、それ以外は出力しない(既定値=Y)*/
%put &=label;		/*変数ラベルを出力する場合はY(既定値=N)*/
%put &=encoding;	/*文字コードを指定(既定値=sjis、それ以外にutf8(utf-8)など)*/
%put &=bom;			/*encoding=utf8を指定した場合のみ機能するパラメータ(既定値=Y、BOMあり)*/
%put &=temp_fol;	/*一時ファイルの出力フォルダの指定(既定値=c:)*/
%put --------------------------------------------------;

	/*区切り文字の設定*/
	%if %upcase( &tab. ) = Y %then %let dlm='09'x ;
	%else                          %let dlm=',';
	
	/*BOMの設定*/
	%if %upcase(&bom.)=Y %then %let _bom=bom;
	%else %let _bom=nobom;

	/*出力データの絞り込み*/
	data _output_text_temp;

		%if %length(&var.) > 0 %then %do;
			format &var.;
			keep &var.;
		%end;

		set &indata.;
		where %superq(where);
	run;
	
	/*一時ファイルへの出力*/
	filename xxxxxxxx "%superq(temp_fol)\output_text" lrecl=1000000;
	proc export data = _output_text_temp outfile=xxxxxxxx dbms=dlm replace;
		delimiter = &dlm.;
	run;

	/*変数情報の取得*/
	proc contents data = _output_text_temp out = _output_text_vlab noprint;
	run;
	proc sort data = _output_text_vlab;
		by varnum;
	run;

	/*ヘッダー(変数名またはラベル)の出力*/
	data _null_;
		set _output_text_vlab;
		file "%superq(outfile)" dsd dlm=&dlm. encoding="&encoding." &_bom. lrecl=1000000;
		%if %upcase(&label.) = Y %then %do;
			if not missing(label) then	put label @;
			else						put name @;
		%end;
		%else %do;
			put name @;
		%end;
	run;

	/*データ部分の出力*/
	data _null_;
		infile xxxxxxxx lrecl=1000000;
		input;
		if _n_ ne 1;
		file "%superq(outfile)" encoding="&encoding." &_bom. lrecl=1000000 %if %upcase(&header.) = Y %then mod;;
		put _infile_;
	run;

	/*一時ファイルoutput_textを削除*/
	data _null_;
		rc = fdelete('xxxxxxxx');
		if rc ne 0 then put 'WARNING:%output_textが作成した一時ファイル「' "&temp_fol.\output_text" '」が正常に削除されませんでした';
	run;
	filename xxxxxxxx clear;
	
	/*不要データの削除*/
	proc datasets lib=work nolist;
		delete _output_text_:;
	quit;
	
%mend output_text;