2018年10月15日月曜日

マクロ内でCARDSが使えないので工夫してみる。




そろそろコタツみかんが出来る時期ですね。



さて、タイトルの通りマクロ内ではCARDSが使えません。
以下の例を見てみましょう。

%macro test;

data out1;
   infile mytemp lrecl=30000;
cards;
1 2 aaa
3 4 bbb
5 6 ccc
;

%mend;
%test

ログ
 ERROR: マクロTESTがCARDS(データ行)を生成しました。不当な結果の原因になるかもしれません。DATAステップとマクロの実行を中止します。
 ERROR: マクロTESTの実行を中止します。




原因はSAS社のFAQやデータステップ100万回でも言及されてますね。

https://www.sas.com/offices/asiapacific/japan/service/technical/faq/list/body/ba243.html
http://sas-tumesas.blogspot.com/2015/01/cards.html

マクロの仕様上、マクロソースは半角スペース(空白)が詰められてリフォーマットされる、
それによって改行位置がわからなくなってしまう、、
なので仕様上の制限として使用できないようにしている、、だそうです。


「それでも、マクロの中でCARDSのように読み込むテキストを指定したいんだ!」という質問を頂きます。
色々方法はありますが、今回2通りの解法を載せておきます。



SAS9.3以前の場合
%macro test;

filename mytemp temp;
data _null_;
   file mytemp;
   put "1 2 aaa";
   put "3 4 bbb";
   put "5 6 ccc";
run;

data out1;
   infile mytemp lrecl=3000;
   input x y z:$10.;
run;

%mend;
%test

プログラムの流れ
・filenameで一時的なファイル参照を作って、
・file/putでこのファイル参照に値を書き出して、
・infile/inputで書きだした値を読み込み



SAS9.4以降の場合
%macro test;

filename mytemp temp;
proc stream resetdelim="_reset" outfile=mytemp;
begin    _reset;
1 2 aaa  _reset newline;
3 4 bbb  _reset newline;
5 6 ccc  _reset;
;;;;

data out1;
   infile mytemp lrecl=3000;
   input x y z:$10.;
run;

%mend;
%test

プログラムの流れ
・filenameで一時的なファイル参照を作って、
・proc streamでこのファイル参照に値を書き出して、
・infile/inputで書きだした値を読み込み

リセットデリミタの設定がちょっとめんどくさいです。



0 件のコメント:

コメントを投稿