LoginSignup
15
10

More than 1 year has passed since last update.

【MATLAB】Excel 内での計算結果を更新させる方法

Last updated at Posted at 2020-11-03

はじめに

Excel シートに MATLAB から何らかの値を出力して、Excel を開くことなくその値に対して Excel 内で何らかの計算処理を同時にさせたい。そんな時には 'UseExcel' オプションを使うといいよというお話。

Twitter で豆腐さんど (@tohu_sand) とのやり取りをしたので、Qiita にも備忘録としてまとめておくことにします。

'UseExcel' オプションは R2019b からはデフォルトで 'false' ですが、それまでは Excel が使える環境であれば 'true' であったという点には要注意。リリースノートへのはこちら: UseExcel。なので R2019a 以前を使っている場合は、特に意識する必要はないと思います。

この記事の Livescript 版(MATLAB)は GitHub: ActiveX-Excel-MATLAB1 に置いてあります。

使用環境

  • MATLAB R2020b

やりたいこと

例えばこんな感じ。

Code
data = rand(5,5);
writematrix(data,'example.xlsx','Range','A2:E6');

image_0.png

MATLAB から入力値を出力し、総和は Excel で計算する。(これくらいの計算であれば MATLAB でやってしまえ・・という話もありますがあくまで例です。)

Excel への出力の仕方によっては、改めて Excel ファイルを開かないと A9 の総和が更新されない。

値が更新されないとは?

A2:E6 の範囲にあたらしい値を MATLAB から出力しても、そのままでは Excel 側の A9 の値が変わらない現象です。

例えば新しいデータを書き出したあと Excel 内での処理結果(A9)を確認すると

Code
data = rand(5,5);
writematrix(data,'example.xlsx','Range','A2:E6');
readmatrix('example.xlsx','Range','A9:A9')
Output
ans = 12.6398
Code
sum(data,'all')
Output
ans = 12.0239

と値が異なるというか、A9 の値が更新されないという落とし穴。

もちろん Excel ファイルを開けば結果は更新されるんですが、いちいち開くのも面倒くさい場合もあると思います。

なんで更新されない?

最近は xlsread 関数xlswrite 関数は非推奨となっている(なんで xlswrite が非推奨?)いて、代わりに writematrix 関数writetable 関数 などの使用が薦められています。

ちなみに xlswrite 関数を使うとちゃんと更新されます。

Code
data = rand(5,5);
xlswrite('example.xlsx',data,'A2:E6');
readmatrix('example.xlsx','Range','A9:A9')
Output
ans = 11.9684
Code
sum(data,'all')
Output
ans = 11.9684

大丈夫ですね。

これは xlswrite 関数は(Excel がインストールされている環境であれば)実行時に Excel を起動するから。Excel が起動すると Excel 内の計算を実行することになります。xlswrite 関数が非推奨な大きな理由はこの Excel を起動する処理に時間がかかるためと見ています。writematrix 関数などの比較的新しい関数は(R2019b 以降のデフォルトの設定では) Excel アプリを介することなくデータを出力します。

参考:ちなみに自動計算を停止させるよう設定も可能 See. Anyway to turn off Excel automatic calculation by a MatLab command for faster export ?

ではどうするか

Excel を起動してしまえばよいのかなと。他にも良い方法があればコメントください。

方法1

writematrix 関数には 'UseExcel' というオプションがあり何も指定しなければ 'false'、すなわち Excel を使用しません。ここを 'true' に変更することで解決します。

Code
data = rand(5,5);
writematrix(data,'example.xlsx','Range','A2:E6','UseExcel',true);
readmatrix('example.xlsx','Range','A9:A9')
Output
ans = 13.7890
Code
sum(data,'all')
Output
ans = 13.7890

大丈夫ですね。総和(A9)もしっかり更新されています。

方法2

上で既にみた方法ですが xlswrite 関数も非推奨ではありますが必要があれば使ってもいいでしょう(個人的見解)。xlswrite 関数を使うことで Excel が起動され、計算結果も更新されます。

ここでは処理時間を比較してみます。

Code
tic
writematrix(data,'example.xlsx','Range','A2:E6','UseExcel',true);
toc
Output
経過時間は 0.390221 秒です。
Code
tic
xlswrite('example.xlsx',data,'A2:E6');
toc
Output
経過時間は 0.185799 秒です。

5x5 の行列であれば xlswrite 関数の方が速いみたいですね。

結果は載せていませんがデータ量が大きくなれば writematrix 関数の方が有利でした。同然の事ながら 'UseExcel' = false (既定の設定) の方がもちろん速いです。

Code
tic
writematrix(data,'example.xlsx','Range','A2:E6','UseExcel',false);
toc
Output
経過時間は 0.017237 秒です。

方法3

もう十分かと思いますが、他の選択肢も一応ご紹介します。ActiveX 経由で Excel を一度起動させてしまう・・。

Code
data = rand(5,5);
writematrix(data,'example.xlsx','Range','A2:E6');

tic
ExcelApp = actxserver('Excel.Application'); 
ExcelFile = ExcelApp.Workbooks.Open(fullfile(pwd,'\example.xlsx')); 
ExcelFile.Save; 
ExcelFile.Close; 
ExcelApp.Quit;
toc
Output
経過時間は 2.573898 秒です。
Code
readmatrix('example.xlsx','Range','A9:A9')
Output
ans = 11.5360
Code
sum(data,'all')
Output
ans = 11.5360

欲しい結果になっていますが、これは時間がかかるので NG ですね。

まとめ

データの出力には write* 系の関数がよさそうです。

MATLAB からファイルに出力する関数としては最近は

などが推奨されています。同様に csvwrite 関数も R2019a 以降「非推奨」の文字が出るようになりましたね。

  1. Livescript から markdown への変換は livescript2markdown​: MATLAB's live scripts to markdown を使っています。

15
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
10