我輩はブロガーではない。ネタもまだない

SASとかDelphiあたりの人様の役に立たないネタを提供します

SASからExcelにDDEコマンドを投げる(1)

SASからExcelへのDDE接続でハマったのでまとめておきます。

もともと、マクロが埋め込まれたxlsファイルにデータを出力して、データが
ある場所だけVBAで罫線を引いたり、シート名を変更する、ということを
していたのですが、最終的にこのファイルを顧客に渡す際、(大したものじゃ
ないですが)vbaのソースを削除するため、xlsxに手動で変換していました。

ただ、この手動変換が手間なので、生成ファイルをxlsxに変更しようと思った
のですが、ここでちょっとハマりました。

テンプレートファイルの形式をxls→xlsmに変更することについてはSASプロ
グラム中のファイル名を変更するだけで良かったのですが、xlsm→xlsxへの
保存で確認ダイアログが表示されてしまうため、自動化となりません。

<次の機能はマクロなしのブックに保存できません>
f:id:japelin:20181018090151p:plain


もともとのコードはこんな感じでした

options noxwait noxsync;
%sysexec "C:\temp\test.xls";
data _null_;
  rc=sleep(2);
run;
filename cmds dde 'excel|system';
filename xls dde "excel|[C:\temp\test.xls]Sheet1!R1C1:R1C1" notab;

data _null_;
  file cmds;
  put '[select("R1C1:R1C1")]';
  put '[error(false)]';
  put '[save()]';
  put '[error(true)]';
run;

これを

  put '[save.as("C:\temp\test.xlsx",51)]';

とすしても、先程と同じダイアログが表示されてしまいます。

あれ?DisplayAlertsをfalseに設定してるのに?


xlsx→xlsxならrenameだけでいいのですが、xlsm→xlsxなのでExcelによる保存処理が必要、
ということで、テンプレートのマクロに以下のコードを追加しました。

Sub SaveXLSX()
  Application.DisplayAlerts = False
  ThisWorkbook.SaveAs ActiveWorkbook.Path & "\" & Replace(ActiveWorkbook.Name, "xlsm", "xlsx"), FileFormat:=xlOpenXMLWorkbook
End Sub

んでもって、SASからは

  put '[run("SaveXLSX")]';

で実行し、その後、

filename xdel "c:\temp\test.xlsm";
data _null_;
  rc=fdelete('xdel');
run;

でrename前のファイルを削除して完了です。

なぜDisplayAlertsが効かなくなったかについてはまた別の記事にします。


注:本記事の稼働環境は以下の通りです。

  • Windows10 Pro 64bit
  • Excel2016 64bit
  • SAS9.4 TS1M5 64bit