2016年9月10日土曜日

RubyからExcelのマクロを実行する方法

rubyからwin32oleを使ってExcelを操作できることは良く知られていますが、それだけではrubyから操作するだけで、マクロを使用しなくては実行できない高度な処理を行う事はできません。

この記事は、rubyからexcelのマクロを呼び出して実行する処理をまとめたものです。
これにより、今までのマクロを使いまわしたり、いちいちマクロをrubyで書き直さなくても、excelでマクロを登録してあとはrubyから保存したマクロの名前から実行するだけで処理ができます。


今回の処理内容と実行するためのファイルを紹介します。
【処理内容】
1.txtファイルからデータを読み込む
2.excelにデータを転写
3.excelに予め保存しておいたFFTを行うマクロを実行  ←今回のキモ
4.excelを別名で保存

【ファイル】
data.txt ・・・ 読み込むデータファイル
excel.rb ・・・ 実行するルビーのファイル
excelMacro.vbs ・・・ エクセルでマクロを実行するためのファイル。これをrubyを通して動かす
FFTtemp.xlsm ・・・ FFTのマクロを記録してあるexcelファイル。


早速、プログラムを見ていきましょう。
(プログラムは以前、株価情報を周波数解析しようとした際のもの)

__ data.txt __
20150706 494 498 470 478 14,098,300 478
20150703 495 503 490 502 12,114,000 502
20150702 480 517 479 492 25,980,700 492

という内容が永遠と続きます
__ data.txt ここまで __



__ excel.rb __
#
# excelとrubyでFFT
#
require 'date' # Dateクラス読み込み
require 'win32ole' # Win32OLE(COM)の読み込み

# 文字コード指定
Encoding.default_external = 'UTF-8'

# 現在時刻を取得
d = DateTime.now

# データ格納用変数初期化
data = Array.new(4001).map{Array.new(25,0)} # 2次元配列を初期化
i = 0 # 配列管理用の変数を定義
j = 0 # 配列管理用の変数を定義

# データを変数に格納
File.open('data.txt') do |file|
file.each_line do |labmen|
labmen.split("\t").each do |dat|
data[i][j] = dat.chomp
j = j + 1
end
i = i + 1
j = 0
end
end
i = 0
j = 0

# Win32 ネイティブ版、Cygwin版の違いに関わらず絶対パスを取得する
def getAbsolutePath filename
  fso = WIN32OLE.new('Scripting.FileSystemObject')
  return fso.GetAbsolutePathName(filename)
end

excel = WIN32OLE.new('Excel.Application') # Excel.ApplicationのCOMオブジェクトを作成
excel.visible = true # windowの表示の有無

# ファイルを開く
workbook = excel.Workbooks.Open(getAbsolutePath("FFTtemp.xlsm"))

# Excelファイルに転写
for i in 0..127 do
if data[i][0].to_s == "0" then
break
end

workbook.sheets[1].rows[11 + i].columns[2] = data[i][0].to_s
workbook.sheets[1].rows[11 + i].columns[3] = data[i][1].to_s
workbook.sheets[1].rows[11 + i].columns[4] = data[i][2].to_s
workbook.sheets[1].rows[11 + i].columns[5] = data[i][3].to_s
workbook.sheets[1].rows[11 + i].columns[6] = data[i][4].to_s
workbook.sheets[1].rows[11 + i].columns[7] = data[i][5].to_s
workbook.sheets[1].rows[11 + i].columns[8] = data[i][6].to_s
end

# ファイル名を決定
filename = "FFT_" + d.strftime("%Y%m%d").to_s + "_" + d.strftime("%H%M%S").to_s + ".xlsm"

# 保存
workbook.saveAs(getAbsolutePath(filename))

# 終了処理
workbook.Close # ファイルを閉じる
excel.Quit # Excel.Applicationの終了

# コマンドラインからVBSを利用してアドインの読み込みとマクロの実行
puts `start ./excelMacro.vbs #{filename} FFTupdate128` # start ./FFTupdate128.vbs ファイル名 マクロ名
__ excel.rb ここまで __

重要なのは一番最後の行のexcelMacro.vbsを実行する部分のみです。



__ excelMacro.vbs __
'
' コマンドラインからの実行でExcelのマクロを実行・保存
'
' ※他のexcelファイルを開いているとエラーが発生する模様

' コマンドライン引数(パラメータ)の取得
Set oParam = WScript.Arguments
cnsBook = oParam(0)
cnsMacro = oParam(1)


' 本スクリプトファイルのフォルダ名の取得
strPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
' Excelのオブジェクトの参照を取得
Set objExcelApp = CreateObject("Excel.Application")
' 自動起動マクロの抑止(イベント停止)
objExcelApp.EnableEvents = False
' Excelウィンドウを表示
objExcelApp.Visible = True
' 指定のワークブックを開く(同一フォルダ)
objExcelApp.Workbooks.Open(strPath & cnsBook)


' Shell関数を使ってATPVBAEN.XLAMを起動
' ※["""]~["""]で囲む
strPath2 = """C:\Program Files (x86)\Microsoft Office\Office14\Library\Analysis\ATPVBAEN.XLAM"""
Set objWShell = CreateObject("WScript.Shell")
objWShell.Run strPath2, 0, False

' 指定のマクロを実行
objExcelApp.Run "'" & strPath & cnsBook & "'!" & cnsMacro


' 各種の確認ダイアログを非表示
objExcelApp.DisplayAlerts = False
'ワークブックの保存
objExcelApp.Workbooks(1).Save


' イベント停止解除
objExcelApp.EnableEvents = True
' Excel終了
objExcelApp.Quit
Set objExcelApp = Nothing
__ excelMacro.vbs ここまで __

ここで重要なのは、真ん中あたりの

 ' Shell関数を使ってATPVBAEN.XLAMを起動
 ' ※["""]~["""]で囲む
 strPath2 = """C:\Program Files (x86)\Microsoft Office\Office14\Library\Analysis\ATPVBAEN.XLAM"""
 Set objWShell = CreateObject("WScript.Shell")
 objWShell.Run strPath2, 0, False

の部分です。

実はrubyからwin32oleを通してマクロを実行しようとしても上手く動かないのですが、その理由はマクロを実行するために必要なアドインである「ATPVBAEN.XLAM」がwin32oleを通してexcelを実行した際には起動されないからです。(バグ・・・なのかな?)
そこで、これを起動しておいてあげる事によってrubyからマクロを実行することが可能になるということです。



__ FFTtemp.xlsm __

__ FFTtemp.xlsm ここまで __



ここまできて、なぜ.vbsファイルが必要なのか、という疑問が出てくるかもしれませんが、たしか、rubyからでは何か不都合があったような気がしますが、実はこれを書いたのが1年前なのでわすれました。。。
とりあえず、このvbsファイルとその使い方である↓

# コマンドラインからVBSを利用してアドインの読み込みとマクロの実行
puts `start ./excelMacro.vbs #{filename} FFTupdate128` # start ./FFTupdate128.vbs ファイル名 マクロ名


だけ分かれば使えるはずです。

おすすめアニメ ランキング

アニメを見る時に某サイトで評価をチェックすることがありますが、なぜだかそのサイトにはランキング機能がありませんでした。
そこで今回は、スクレイピング(Ruby)とExcelを使用してアニメランキングを作成しました。

スクレイピングに関しては↓を参照。
http://vsanna.sakura.ne.jp/wp/2015/01/scraping_start_up/

説明は面倒なので、結果だけどうぞ↓


順位 タイトル 合計点
100 THE IDOLM@STER - アイドルマスター - 5170
98 プラネテス 5190
98 School Days - スクールデイズ - 5190
97 にゃんこい! 5210
95 夏目友人帳 5220
95 BTOOOM! -ブトゥーム- 5220
94 這いよれ! ニャル子さん 5250
93 みなみけ 5260
92 黄昏乙女×アムネジア 5300
91 さんかれあ 5310
90 true tears - トゥルー ティアーズ - 5320
89 GOSICK -ゴシック- 5360
87 オオカミさんと七人の仲間たち 5440
87 まよチキ! 5440
86 君に届け 5510
85 新世紀エヴァンゲリオン 5570
84 坂道のアポロン 5610
82 ベン・トー 5660
82 人類は衰退しました 5660
81 AIR 5670
80 あの夏で待ってる 5740
79 SHIROBAKO 5760
78 TIGER&BUNNY - タイガー&バニー - 5770
77 翠星のガルガンティア 5810
75 いちばんうしろの大魔王 5860
75 新世界より 5860
74 となりの怪物くん 5880
72 じょしらく 5920
72 四月は君の嘘 5920
71 アマガミSS 5950
70 ef - a tale of memories 5960
69 交響詩篇エウレカセブン 6000
68 日常 6080
66 らき☆すた 6150
66 緋弾のアリア 6150
65 灼眼のシャナ 6160
63 僕は友達が少ないNEXT 6210
63 凪のあすから 6210
62 とある科学の超電磁砲S 6220
61 これはゾンビですか? 6240
60 WORKING’!! 6320
59 銀魂 ~  銀魂'延長戦 6350
58 神のみぞ知るセカイ 6470
57 TARI TARI 6530
56 咲-Saki- 6650
55 東のエデン 6700
54 ヨルムンガンド 6710
53 はたらく魔王さま! 6760
52 ゆるゆり 6940
51 狼と香辛料 7010
50 学園黙示録 HIGHSCHOOL OF THE DEAD 7150
49 やはり俺の青春ラブコメはまちがっている。 7350
48 電波女と青春男 7380
47 ひぐらしのなく頃に 7400
46 アクセル・ワールド 7430
45 パパのいうことを聞きなさい! 7510
44 ちはやふる 7560
43 とある魔術の禁書目録II 7680
42 生徒会役員共 7700
41 デュラララ!! 7840
40 エルフェンリート 7870
39 ハイスクールDxD 8240
38 未来日記 8270
37 進撃の巨人 8320
36 喰霊-零- 8380
35 荒川アンダーザブリッジ 8400
34 妖狐×僕SS 8430
33 バカとテストと召喚獣 8640
32 さくら荘のペットな彼女 8700
31 PSYCHO-PASS -サイコパス- 8880
30 うさぎドロップ 8890
29 IS <インフィニット・ストラトス> 8930
27 中二病でも恋がしたい! 9190
27 ココロコネクト 9190
25 コードギアス 反逆のルルーシュ 9440
25 僕は友達が少ない 9440
24 男子高校生の日常 9590
23 コードギアス 反逆のルルーシュR2 9750
22 花咲くいろは 9770
21 氷菓 9920
20 涼宮ハルヒの憂鬱 10320
19 WORKING!! 10810
18 偽物語 11570
17 けいおん! 11650
16 けいおん!! 12060
15 俺の妹がこんなに可愛いわけがない 12140
14 Fate/Zero -フェイト ゼロ- 12280
13 魔法少女まどかマギカ 13170
12 ギルティクラウン 13400
11 Another 13560
10 とある魔術の禁書目録 13860
9 CLANNAD 13870
8 とある科学の超電磁砲 14440
7 CLANNAD AFTER STORY 15020
6 ソードアート・オンライン 15760
5 Steins;Gate -シュタインズ・ゲート- 15810
4 化物語 18030
3 とらドラ! 19320
2 あの日見た花の名前を僕達はまだ知らない。 20530
1 Angel Beats! 22740


いかがでしたか? 合計点をざっくりと計算しただけなので、色々無理のあるところはあると思いますが、注目度や話題性も込みの評価だと考えるとこんなものかなと思います。



※某サイトの仕様変更のため、データは201507のものを使用。

2016年9月9日金曜日

Excel オートフィル(連続データ)のショートカット

続けざまに新しい記事を。

Excelを使う際に、式を入力した後にセルの右下をダブルクリックしてオートフィル(連続データ)によって下のセルへ内容をコピーすることがあると思います。
以前よりショートカットが無いか気になっていたのですが、この度、見つかりましたので忘れないように。


コピー元のセルを含めてコピーしたい範囲を選択した状態で「Ctrl+D」


のショートカットで実現できます。Ctrl+Dは元々、上にあるセルをコピーするショートカットですが、範囲指定をすることで一気にコピーできる様です。

Excel ダブルクリックせずにセルを編集

些細な事ですが、excelのショートカットを理解し切れていなかったようなので更新。

excelで中身のあるセルを編集する際に、いつもダブルクリックをしていましたが、調べたところ、簡単なショートカットがありました。

「F2」

です。フォルダ名の変更の際によく使うショートカットですが、実はセルの中身を編集する際にも使えるようです。
お試しあれ。