2019年6月27日木曜日

「FMTERR」と「NOFMTERR」の機能と落とし穴




以下のようなログメッセージが出たことありませんか。

  • 「ERROR: 出力形式XXを変数XXにロードできません」
  • 「ERROR: 出力形式XXが見つからないか、またはロードできません。」



これは「存在しないフォーマットがデータセットに割り当てられている場合」に、現れるメッセージです。
このメッセージを制御しているのが「FMTERR」と「NOFMTERR」というシステムオプションです。




「Windows版SAS」では以下のシステムオプションがデフォルト設定となっています。

options fmterr;


「SAS Ondemand for Academics」では以下がデフォルト設定となっています。

options nofmterr;


それぞれがどんな動きか見ていきましょう。




FMTERR


以下は変数SEXに「$aaa」、変数BIRTHに「yymmdd10」というフォーマットを割り当てています。

options fmterr;

data test;
    format sex $aaa. birth yymmdd10.;
    sex = "FEMALE";
    birth = '26jun2019'd;
run;


--- Log ---------------------

しかし「$aaa」というフォーマットを事前に定義していなかったので、、「$aaaなんてフォーマット見つからんよ!!」とブチ切れられて処理がストップしちゃいました。



NOFMTERR


そこで「NOFMTERR」を指定してやると、

options nofmterr;

data test;
    format sex $aaa. birth yymmdd10.;
    sex = "FEMALE";
    birth = '26jun2019'd;
run;


--- Log ---------------------



--- Dataset ----------------


「フォーマット見つからないよ」と優しめに言われるものの、一応フォーマット$aaaが割り当てられて、処理を続けてくれます。

「NOFMTERR」が設定されてる間は、フォーマットが見つからなかった箇所を(通常は) 出力形式「w.」または「$w.」として扱ってくれます。





NOFMTERRの落とし穴


今度は以下のように「$aaa1.」というようにフォーマットに長さも指定した場合は、、

options nofmterr;

data test;
    format sex $aaa1. birth yymmdd10.;
    sex = "FEMALE";
    birth = '26jun2019'd;
run;



あれ、「FEMALE」の文字が「F」になってる。


実はフォーマットの長さの部分だけは見てくれるようです。つまり「$aaa1.」は「$1.」として扱われる。


あと例えば数値変数に対して「bbb8.2」みたいな感じで存在しないフォーマットを割り当てた場合も「8.2」として扱われる。


中途半端だな・・・




2019年6月25日火曜日

2019年6月21日金曜日

「ODS RTF」+「SGPLOT」だと、TITLEステートメントの設定値がグラフのタイトルになってしまう





以下の例をご覧ください。

title "HEIGHT AND WEIGHT";

ods rtf file="出力パス\test.rtf";

    proc sgplot data=sashelp.class;
        scatter x=height y=weight;
    run;

ods rtf close;


TITLEステートメントの設定値がSGPLOTのグラフ内のタイトルにあてられました。



いやいや、「RTFのヘッダーにあててほしいんだけど」って場合は「NOGTITLE」というオプションを指定します。

title "HEIGHT AND WEIGHT";

ods rtf file="出力パス\test.rtf" nogtitle;

    proc sgplot data=sashelp.class;
        scatter x=height y=weight;
    run;

ods rtf close;



同様にFOOTNOTEステートメントが設定されてると、SGPLOTのグラフ内のフットノートに当てられます。
これも「NOGFOOTNOTE」というオプションを指定することで、RTFのフッターにあてることができます。



ちなみに「ODS RTF」だけじゃなくて、「ODS EXCEL」「ODS PDF」とかも共通する話です。


2019年6月20日木曜日

スタイルテンプレートのソースを表示する




以下の構文でスタイルテンプレートのソースを表示することができます。



構文
proc template;
    source スタイル名;
run;




proc template;
   source styles.printer;
run;

Log



元からあるスタイルを継承して新たなスタイルを作成する場合とかに、継承元のスタイルの設定がどうなってるか確認する必要があるんで、この機能が必要になります。



2019年6月18日火曜日

ODS EXCEL入門: 表示倍率の設定




またまたODS EXCELの記事です。
ZOOMオプションで画面の表示倍率が設定できます。そんなことも出来るんですね~


構文

ODS EXCEL OPTIONS(  ZOOM = "表示倍率"  );






ods excel file="出力するパスを指定\test1.xlsx" options( zoom="50" );

    proc report data=sashelp.cars;
    run;

ods excel close;


2019年6月12日水曜日

データセット間で変数の順番を比較する方法




以下をご覧ください。




サンプルデータ

data A;
    X=1;
    Y=2;
    Z=3;
run;

data B;
    X=1;
    Z=3;
    Y=2;
run;


データセット A と B は、同じ変数 X, Y, Z を持っています。
しかし変数の順番が異なります(YとZの順番)


このように2つのデータセット間で変数の順番が異なっていないか、確認したいことがあります。

例えば、治験のCDISC対応を例にとると、SDTMやADaMのデータセットをダブルプログラミングで作ってPROC COMPAREして「一致したからOKね」で終わらせてしまいがちですが、変数の順番が一致してるかまではPROC COMPAREは見てくれません。


てことで、変数の順番を比較する方法を提案したいと思います。



PROC SORTでの解法例

%upcase(
   proc sort data=sashelp.vcolumn out=_null_ uniqueout=OUT1 nouniquekey sortseq=linguistic(strength=primary);
       by name varnum;
       where libname="WORK" and memname in ("A","B");
   run;
);

proc print data=OUT1 noobs label;
   var libname memname name varnum;
run;



結果がデータセットOUT1に出力されます。
「Y」と「Z」の順番が異なっていることが分かりますね。



やってること自体は、以下記事のテクニックの焼き直しなので、こちらもご参照下さい。
https://sas-boubi.blogspot.com/2019/02/blog-post_35.html

プログラム青文字部分にチェック対象のライブラリ名とデータセット名を指定します。


2019年6月6日木曜日

ODS EXCEL入門: セル内折り返しの設定





以前書いた以下の記事について、もうちょっと掘り下げたいと思います。
ODS EXCELで「セル内改行」されてしまうところを「セル内折り返し」に変える



まずは以下をご覧ください。

ods excel file="出力するパスを指定\test1.xlsx";

    proc report data=sashelp.cars;
    run;

ods excel close;


H1セルの値「Engine Size (L)」はパッと見「セル内折り返し」に見えて、実は「セル内改行」されてます。
こんな感じでODS EXCELでは横幅が足りない場合、セル内改行になってしまいます。



この「セル内改行」を「セル内折り返し」に変えるオプションが今回紹介する「FLOW=オプション」です。






構文

ODS EXCEL OPTIONS(  FLOW = "セル内折り返しにする場所"  );


  • SAS9.4M4からの新機能です。
  • FLOW=には設定値として「セル番地」「HEADER」「ROWHEADER」「DATA」「TABLE」「TEXT」が用意されています。



では各設定値がどのような動きをするのか、1つずつ見ていきましょう。





FLOW = "セル番地"


指定したセルだけ「セル内折り返し」に変えます。

ods excel file="出力するパスを指定\test1.xlsx"  options( flow="H1" );

    proc report data=sashelp.cars;
    run;

ods excel close;





FLOW = "HEADER"


表のヘッダー部分だけ「セル内折り返し」に変えます。

ods excel file="出力するパスを指定\test1.xlsx"  options( flow="header" );

    proc report data=sashelp.cars;
    run;

ods excel close;





FLOW = "DATA"


表のデータ部分だけ「セル内折り返し」に変えます。

ods excel file="出力するパスを指定\test1.xlsx"  options( flow="data" );

    proc report data=sashelp.cars;
    run;

ods excel close;



FLOW = "ROWHEADER"


行ヘッダーだけ「セル内折り返し」に変えます。
たとえば、以下のようにIDとして設定した変数MAKEとMODELが行ヘッダーとなり、A~B列が「セル内折り返し」になります。

ods excel file="出力するパスを指定\test1.xlsx"  options( flow="rowheader" );

    proc report data=sashelp.cars;
        define make / id;
        define model / id;
    run;

ods excel close;




FLOW = "TABLE"


こちらは「"HEADER"」「"ROWHEADER"」「"DATA"」をすべてカバーした機能を持っています。




FLOW = "TEXT"


これは大分説明が必要なんですが、以下をご覧ください。

ods excel file="出力するパスを指定\test1.xlsx" ;

ods excel text="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    proc report data=sashelp.cars;
        column type origin;
    run;

ods excel close;


「ODS EXCEL TEXT="出力するテキスト"」でExcelにテキストを出力することが出来るんですが、上の例でA1セルに出力されたテキストがずらーーーーっとD1セルの領域にまで侵入していますね。


そこで、FLOW="TEXT"を指定すると、、

ods excel file="出力するパスを指定\test1.xlsx"  options( flow="text" );

ods excel text="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    proc report data=sashelp.cars;
        column type origin;
    run;

ods excel close;

このテキストに対して「セル結合」&「セル内折り返し」が設定されます。





ちなみに


以下のような感じで折り返し範囲をカンマで区切って設定することも可能です。

ods excel file="出力するパスを指定\test1.xlsx"  options( flow="table,text" );




2019年6月4日火曜日

ODS EXCELで「ヘッダー・フッター」の書式を設定する




以前、ODS EXCELでヘッダーとフッターを設定する方法を紹介しました。



上の記事の番外編でちょっとしたテクニックを紹介したいと思います。



これはSASではなくExcel側の機能なんですが、以下の「VBAコード」や「書式コード」と呼ばれるものを用いて、ヘッダー・フッターに書式を設定することが出来ます。

  書式コード    機能    
 &L 文字を左側に表示する 
 &C 文字を中央部に表示する
 &R 文字を右側に表示する
 &B 文字を太文字にする
 &I 文字を斜体にする
 &U 文字を下線付きにする
 &"フォント名" 指定したフォントにする(ダブルクォーテーションで囲って指定)
 &Kカラー 指定したカラーにする(16進カラーコードを指定)
 &nn 指定したフォントサイズにする(nnには2桁の数値を指定)
  VBAコード    機能    
 &D 現在の日付を表示
 &T  現在の時刻を表示
 &Z ファイルパスを表示
 &F   ファイル名を表示
 &A シート名を表示
 &P   ページ番号を表示
 &N  総ページ数を表示
 ...等々





title '&Lあいうえお&Rかきくけこ';
footnote '&"Arial"&P/&"Arial"&N';

ods excel file="出力するパスを指定\test.xlsx";

    proc report data=sashelp.class;
    run;

ods excel close;



1つ気をつけなきゃいけないのが、TITLE・FOOTNOTEステートメント中の文字をダブルクォーテーションで囲むと「&L」などのコードがマクロ変数と認識されちゃいます。

title "&Lあいうえお&Rかきくけこ";

なので、シングルクォーテーションで囲んでマクロ変数として見られないようにしときましょう。




落とし穴


「TITLEステートメント」または「FOOTNOTEステートメント」を使ってヘッダー・フッターを設定する場合は先ほどの方法でOKでしたが、、


今度は以下のように「PRINT_HEADER」または「PRINT_FOOTER」を使ってヘッダー・フッターを設定した場合は、、

title;
footnote;

ods excel file="出力するパスを指定\test.xlsx" options(
    print_header = '&Lあいうえお'
    print_footer = '&Rかきくけこ' );

    proc report data=sashelp.class;
    run;

ods excel close;


生成されたExcelを開こうとすると、上のようなメッセージが出てしまいます。なんかぶっ壊れたらしい。


SASのバージョンにもよるのかもしれません。もし上のようにぶっ壊れてしまったら、以下のように「&」を「&」に置き換えるとうまくいきます。

title;
footnote;
ods excel file="出力するパスを指定\test.xlsx" options(
    print_header = '&Lあいうえお'
    print_footer = '&Rかきくけこ' );

    proc report data=sashelp.class;
    run;

ods excel close;




2019年6月3日月曜日

ODS EXCEL入門: 出力位置の指定





最近、ODS EXCELの記事書きすぎ。。
それは置いといて、ODS EXCELでプロシジャの出力位置を指定する方法を紹介します。



構文
ODS EXCEL OPTIONS( START_AT = "出力列, 出力行" );



例1
ods excel file="出力するパスを指定\test1.xlsx"  options( start_at="2,3" );

proc report data=sashelp.class;
run;

ods excel close;

2列3行目から出力しています。