ラベル sashelp の投稿を表示しています。 すべての投稿を表示
ラベル sashelp の投稿を表示しています。 すべての投稿を表示

掲示板質問の回答例:現在使用中のFootnoteの最終番号を取得する方法

掲示板の方に、質問をいただきました。有難うございます!掲示板に返事書こうと思ったのですが、結構やってて面白い内容だったので記事にしました。
(掲示板:http://tumesas.progoo.com/bbs/tumesas_topic_pr_6.html)

ただ、本当にこの方法でいいのかわからないので、何かアイデアがあればコメントでも掲示板にでもメッセージください。

さて本題。質問は











なるほど、、。そういえば考えたことない、、。

検索しても、それっぽいのが出てこないので、自分の頭で考えてみました。
以下になります。


まず

data Q1;
X=1;
run;

title 'タイトル1';
footnote 'フットノート1';
footnote2 'フットノート2';
footnote3 'フットノート3';
proc print;
run;


を実行すると、当然















こうなるわけですね。
さて次のプロシジャ実行時に、すでにfootnote3まで使ったことを取得し、footnote4が展開されるようにしたいわけですね。仮にfootnote6まで使っていればfootnote7みたいな感じです。

さて、定義したタイトルやフットノートの情報はどこにいるでしょうか?











SASHELPライブラリの中には、SAS社が用意したサンプルデータセットと共に、SASの様々な定義情報がリアルタイムで更新されるビューが用意されてます。
(ちなみにSASHELPのサンプルデータセットを間違えて全部消したおバカさん(僕です)はSAS社のWebページから再ダウンロードできます)



この中のVTITLEを開けてみると










発見!

typeのTはタイトル、Fはフットノートです。

後は、もう簡単ですね

proc sql noprint;
 select max(number) into:fno
 from dictionary.TITLES
 where type='F' and text^='';
quit;

です。

sashelp.VTITLEはSQLの中ではdictionary.TITLESと書けます。そういうものなんです。

これでマクロ変数fnoには3が入ります。

そして以下

footnote%eval(&fno+1) 'プログラマー名:SASYAMA';

proc print;
run;


を実行すると














となって、確かに最後にプログラマー名がでてきます。

こんな感じです。

まあ、改善点としては、定義可能最大値が10なので、footnote10が既に定義されている場合や、全く定義されていない状態で実行した場合エラーにならないような分岐が必要ですが、そこまではやってません。

データセットラベルの話

知っている方からすると何を今さらなのですが、案外知られてないのではないかと思う話題です。

SASでラベルというと、labelステートメントで定義する変数ラベルのことが思い浮かぶと思うのですが、実は、変数だけではなくデータセットそのものにもラベルを付けることができます。

data Q1(label='20140831作成サンプルデータ');
 X=1;
run;

のように、データセットオプションの中にlabel=と指定することで、データセットにラベルがつきます。

このラベルは







のように、データセットをダブルクリックした際のウインドウ上部に表示されたり、
プロパティでみると





















「説明」の箇所に表示されます。

その他、プロシジャ出力の種類によっては、さりげなく出現します。

一度設定したデータセットラベルは

proc datasets nolist;
 modify Q1(label='20140831修正サンプルデータ');
run;
quit;

のようにして修正できます。


さて、それで一体、このデータセットラベルは何に使うかというと、
実際見たことがあるのが

data Q2(label='20130102作成');
run;

data Q3(label='20110302作成');
run;

data Q4(label='20130405作成');
run;

のように、永久データセットとして何かしらのデータを管理する場合、その説明として
作成日や作成者やバージョンや、その他説明を記載するという使い方です
(上記のコードは、サンプルなのでWORKにつくっていますが)

データステップのsashelp.vtable(SQLプロシジャで参照する場合はdictionary.table)
には、認識されている全てのデータセットの情報が入っているので

例えば後々、2013年に作成したデータセットの一覧が欲しいって際に

data LIST;
 set sashelp.vtable;
 where substr(memlabel,1,4)='2013';
 keep memname memlabel;
run;






みたいに、すぐに把握できたり、これとcall executeとかマクロを組み合わせて
特定のデータセット群を対象に一括処理をするみたいな発想が実現できます。

まあ、知っていて損はないデータセットラベルの話でした。






マクロ変数の削除

SASマクロ、あまり得意じゃないのですが、ユーザー定義のマクロ変数の削除についてです。

data A;
X=1;output;
X=2;output;
run;

proc sql noprint;
 select count(*) into:obs1
  from A;
quit;

今、値2の入ったマクロ変数obs1が作成されました。


%SYMDEL obs1;

消えました。

めでたしめでたしで終わりなのですが、

例えば、いっぱいマクロ変数を作成していて、それを一括で消したい場合
いちいち%SYMDELで指定するの面倒ですね、というかデータ内容に応じて可変的に
作成している場合、どれだけ作られるかわかりませんしね。

で、SAS社の古いヘルプだと

data symdel;
  set sashelp.vmacro;
  where scope = 'GLOBAL' ;
run;

data _null_;
  set symdel;
  call symdel(name);
run;

としているのです。
sashelp.には現在のSASセッションで最新の情報がテーブルビューとして格納されていて
SQLやデータステップで利用することで、存在する変数・ライブラリ・データセットなどなどの情報を
取得できるのですが
今回はvmacroというテーブルから、存在するマクロ変数の情報を取得します。
scopeという変数に、GLOBALまたはAUTOMATICといった値が入るのですが
GLOBALで絞ることで、自動マクロ変数以外を全部けしてやろうということですね
call symdelルーチンでマクロ変数を消せます。

ただ、いつのバージョンからか調べてないのですが
SQLを使うと
SYS_SQL_IP_ALL SYS_SQL_IP_STMTというマクロ変数が作成され、
カテゴリとしてはGLOBALなのに消そうとすると消せないのでエラーになってしまいます。

ので、

data symdel;
  set sashelp.vmacro;
  where scope = 'GLOBAL' and NAME not in ('SYS_SQL_IP_ALL','SYS_SQL_IP_STMT');
run;

data _null_;
  set symdel;
  call symdel(name);
run;

としてやればOKです。