以下に掲げるrubyスクリプトのサンプルは、Excel操縦用ライブラリ exlap.rb 最新版: exlap_latest.zipに同梱のものを利用するとの前提で書かれています。
目次
#! ruby -Ks # display the Excel addin list, and report especially on the Solver file. require "win32ole" app = WIN32OLE.new("Excel.Application") ary = [] solver_file = nil app.AddIns.each do |target| ary << [target.Name, target.FullName] if target.Name =~ /^solver\.x/i solver_file = target.FullName end end app.Quit unless solver_file puts 'can not find the solver addin file' else puts "the solver file: #{solver_file}" end printf("\n") puts 'Excel addin list' ary.each do |row| puts row.join("\t") enddownload addin.rb
#! ruby -Ks # ソルバーを使って2の平方根を求める require "exlap" solver_file = 'C:\Program Files\Microsoft Office' + '\Office12\Library\SOLVER\SOLVER.XLAM' # for Excel2007 unless test(?e, solver_file) # SOLVER.XLAMが存在しない STDERR.puts "変数solver_fileの値が不適当です." exit end prefix = "'#{solver_file}'!" filename = "slv01.xls" Exlap.new(filename) do |wb| app = wb.app.obj # Excel Application app.Run "#{prefix}Auto_Open" if app.Version.to_f < 12.0 ss = wb.fes # 空のワークシートを選択 ss.Activate ss.Range("A1").Formula = "=B1*B1" val = 2 # 2の平方根を求める app.Run("#{prefix}SolverOk", "A1", 3, val, "B1") # 目標条件の設定 app.Run("#{prefix}SolverSolve", true) # ソルバーの実行 app.Run("#{prefix}SolverFinish", 1) # 実行結果をセルに書き込む wb.save enddownload slv01.rb
#! ruby -Ks # ソルバーを使って2〜10の平方根を求める # solver.xla | solver.xlam の所在を検索する仕組みを内包 require "exlap" filename = "slv02.xls" Exlap.new(filename) do |wb| app = wb.app.obj # Excel Application # SOLVER.XLA | SOLVER.XLAM のフルパスを探索 solver_file = nil app.AddIns.each do |target| if target.Name =~ /^solver\.x/i solver_file = target.FullName break end end ## prefix = "'#{solver_file}'!" app.Run "#{prefix}Auto_Open" if app.Version.to_f < 12.0 ss = wb.fes # 空のワークシートを選択 ss.Activate # 2〜10の平方根を求める作業 y = 0 for val in 2..10 y += 1 # 行番号 ss.cell(y,1).Formula = "=RC[1]*RC[1]" # 「RC[1]」は右隣のセル app.Run("#{prefix}SolverOk", ss.cell(y,1), 3, val, ss.cell(y,2)) app.Run("#{prefix}SolverSolve", true) app.Run("#{prefix}SolverFinish", 1) end wb.save enddownload slv02.rb
#! ruby -Ks # ExlSolverクラス利用による平方根の計算 require "exlap" filename = "slv03.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.fes # 空のワークシートを選択 ss.Activate # 2〜10の平方根を求める作業 y = 0 for val in 2..10 y += 1 # 行番号 ss.cell(y,1).Formula = "=RC[1]*RC[1]" # 「RC[1]」は右隣のセル slv.ok(ss.cell(y,1), 'val', val, ss.cell(y,2)) slv.settle end wb.save enddownload slv03.rb
#! ruby -Ks # 連立方程式「x*200+y*300=2600」 「x+y=11」を解く require "exlap" filename = "slv04.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.fes ss.Activate ss.Range("A1:B1").Value = [[1, 1]] # 初期値の設定(ダミー) ss.Range("C1").Formula = "=A1*200+B1*300" ss.Range("D1").Formula = "=A1+B1" slv.ok("C1", 'val', 2600, "A1:B1") # x*200+y*300=2600の目標条件 slv.add("A1", 'int') # A1が整数であるとの制約条件 slv.add("B1", 'int') # B1が整数であるとの制約条件 slv.add("D1", '=', 11) # x+y=11の制約条件 slv.settle # ソルバーの実行と結果のセルへの書き込み wb.save enddownload slv04.rb
#! ruby -Ks # x+y=11, x>=1, y>=1 の時に x*200+y*300 の最大値を求める require "exlap" filename = "slv04max.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.fes ss.Activate ss.Range("A1:B1").Value = [[1, 1]] # 初期値の設定(ダミー) ss.Range("C1").Formula = "=A1*200+B1*300" ss.Range("D1").Formula = "=A1+B1" slv.ok("C1", 'max', nil, "A1:B1") # 最大値を求めたい slv.add("A1", 'int') # A1が整数であるとの制約条件 slv.add("B1", 'int') # B1が整数であるとの制約条件 slv.add("A1", '>=', 1) slv.add("B1", '>=', 1) slv.add("D1", '=', 11) # x+y=11の制約条件 slv.settle # ソルバーの実行と結果のセルへの書き込み wb.save enddownload slv04max.rb
#! ruby -Ks # x+y=11, x>=1, y>=1 の時に x*200+y*300 の最小値を求める require "exlap" filename = "slv04min.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.fes ss.Activate ss.Range("A1:B1").Value = [[1, 1]] # 初期値の設定(ダミー) ss.Range("C1").Formula = "=A1*200+B1*300" ss.Range("D1").Formula = "=A1+B1" slv.ok("C1", 'min', nil, "A1:B1") # 最小値を求めたい slv.add("A1", 'int') # A1が整数であるとの制約条件 slv.add("B1", 'int') # B1が整数であるとの制約条件 slv.add("A1", '>=', 1) slv.add("B1", '>=', 1) slv.add("D1", '=', 11) # x+y=11の制約条件 slv.settle # ソルバーの実行と結果のセルへの書き込み wb.save enddownload slv04min.rb
#! ruby -Ks # 放物線の分析: なるべく遠くまで投げるための角度、その時の最高位置を求める require "exlap" filename = "slv05.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.fes # 空のワークシートを選択 ss.Activate vel = "C1" # 初速度が書かれているセル番地 g = 9.8 # 重力加速度 9.8メートル毎秒毎秒 ss.Range("A1:D1").Value = [["放物線の分析", "(初速度", 28, "m/s)"]] ss.Range("B2:E2").Value = [%w(角度(度) 時間(秒) 横の距離x 高さy)] # 見出し ss.Range("A3:A4").Value = [["x最大値"], ["↑y最大値"]] # 縦の見出し for rn in 3..4 # rnは行番号 a = "B#{rn}" # 角度の番地 t = "C#{rn}" # 時間の番地 x = "D#{rn}" # 横の距離xの番地 y = "E#{rn}" # 高さyの番地 ss.Range(a).Value = (rn==3) ? 10 : "=R[-1]C" ss.Range(t).Value = 0.1 # 時間・秒数の初期値(ダミー) ss.Range(x).Formula = "=(#{vel}*COS(RADIANS(#{a})))*#{t}" ss.Range(y).Formula = "=(#{vel}*SIN(RADIANS(#{a})))*#{t}-#{g}*#{t}^2/2" slv.reset # 念のためソルバー諸設定のリセット case rn when 3 # xの最大値を求める slv.ok(x, 'max', nil, "#{a}:#{t}") slv.add(a, '>=', 10) slv.add(t, '>=', 0.1) slv.add(y, '>=', 0.0) when 4 # xが最大値の時のyの最大値を求める slv.ok(y, 'max', nil, t) slv.add(t, '>=', 0.1) end slv.settle end wb.save enddownload slv05.rb
#! ruby -Ks # 放物線の分析: なるべく遠くまで投げるための角度、その時の最高位置を求める # 第1ワークシートでsave、第2ワークシートでloadを行うサンプル require "exlap" filename = "slv06.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.ss(1) # 第1ワークシートを選択 ss.Name = "velocity28" # ワークシート名を設定 ss.UsedRange.Clear # 念のためシート全体の内容を消去 ss.Activate vel = "C1" # 初速度が書かれているセル番地 g = 9.8 # 重力加速度 9.8メートル毎秒毎秒 ss.Range("A1:D1").Value = [["放物線の分析", "(初速度", 28, "m/s)"]] ss.Range("B2:E2").Value = [%w(角度(度) 時間(秒) 横の距離x 高さy)] # 見出し ss.Range("A3:A4").Value = [["x最大値"], ["↑y最大値"]] # 縦の見出し for rn in 3..4 # rnは行番号 a = "B#{rn}" # 角度の番地 t = "C#{rn}" # 時間の番地 x = "D#{rn}" # 横の距離xの番地 y = "E#{rn}" # 高さyの番地 ss.Range(a).Value = (rn==3) ? 10 : "=R[-1]C" ss.Range(t).Value = 0.1 # 時間・秒数の初期値(ダミー) ss.Range(x).Formula = "=(#{vel}*COS(RADIANS(#{a})))*#{t}" ss.Range(y).Formula = "=(#{vel}*SIN(RADIANS(#{a})))*#{t}-#{g}*#{t}^2/2" slv.reset # 念のためソルバー諸設定のリセット case rn when 3 # xの最大値を求める slv.ok(x, 'max', nil, "#{a}:#{t}") slv.add(a, '>=', 10) slv.add(t, '>=', 0.1) slv.add(y, '>=', 0.0) when 4 # xが最大値の時のyの最大値を求める slv.ok(y, 'max', nil, t) slv.add(t, '>=', 0.1) end slv.settle save_cell = (rn==3) ? "A10" : "C10" slv.save(save_cell) end # saveした結果を標準出力に出力 puts "SolverSaveされた情報" for cn in [1,3] # A列、C列 rn = 10 while true val = ss.cell(rn,cn).Value.to_s fml = ss.cell(rn,cn).Formula.to_s break if val == '' and fml == '' printf("%s\t%s\t%s\n", Exl::a1(ss.cell(rn,cn)), val, fml) rn += 1 end printf("\n") end wb.save end # 2回目のExcel起動 Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.ss(1) # 先ほど作成した第1ワークシート sname = ss.Name # => "velocity28" rng = ss.Range("A1").CurrentRegion # 放物線分析結果領域 addr1 = Exl::ab(ss.Range("A10").CurrentRegion) # => "$A$10:$A$15" addr2 = Exl::ab(ss.Range("C10").CurrentRegion) # => "$C$10:$C$13" ss = wb.fes # 空のシートを選択 rng.Copy(ss.Range("A1")) # 第1シートの分析結果領域をA1以降にコピー ss.Range("C1").Value = 42 # 初速度を42m/sにする ss.Range("B3").Value = 10 # 角度の初期値 ss.Range("C3:C4").Value = [[0.1], [0.1]] # 時間の初期値 ss.Activate slv.load("#{sname}!#{addr1}") # "velocity28!$A$10:$A$15" slv.settle slv.reset slv.load("#{sname}!#{addr2}") # "velocity28!$C$10:$C$13" slv.settle wb.save enddownload slv06.rb
#! ruby -Ks # ソルバーの各オプションの値を確認・設定する require "exlap" filename = "dummy.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) hs = slv.get_options puts "現在のオプションの値の一覧" slv.options_key.each do |key| printf("%s\t", key) p hs[key] end printf("\n") puts "MaxTime, IntToleranceの値を変更." slv.options({'MaxTime'=>1000, 'IntTolerance'=>2.5}) hs = slv.get_options printf("現在のMaxTimeの値:") p hs['MaxTime'] printf("現在のIntToleranceの値:") p hs['IntTolerance'] enddownload slv07.rb
#! ruby -Ks # 放物線の分析: なるべく遠くまで投げるための角度、その時の最高位置を求める # FinishDialog利用の例 require "exlap" filename = "slv08.xls" Exlap.new(filename) do |wb| slv = ExlSolver.new(wb.app.obj) ss = wb.fes # 空のワークシートを選択 ss.Activate vel = "C1" # 初速度が書かれているセル番地 g = 9.8 # 重力加速度 9.8メートル毎秒毎秒 ss.Range("A1:D1").Value = [["放物線の分析", "(初速度", 28, "m/s)"]] ss.Range("B2:E2").Value = [%w(角度(度) 時間(秒) 横の距離x 高さy)] # 見出し ss.Range("A3:A4").Value = [["x最大値"], ["↑y最大値"]] # 縦の見出し for rn in 3..4 # rnは行番号 a = "B#{rn}" # 角度の番地 t = "C#{rn}" # 時間の番地 x = "D#{rn}" # 横の距離xの番地 y = "E#{rn}" # 高さyの番地 ss.Range(a).Value = (rn==3) ? 10 : "=R[-1]C" ss.Range(t).Value = 0.1 # 時間・秒数の初期値(ダミー) ss.Range(x).Formula = "=(#{vel}*COS(RADIANS(#{a})))*#{t}" ss.Range(y).Formula = "=(#{vel}*SIN(RADIANS(#{a})))*#{t}-#{g}*#{t}^2/2" slv.reset # 念のためソルバー諸設定のリセット case rn when 3 # xの最大値を求める slv.ok(x, 'max', nil, "#{a}:#{t}") slv.add(a, '>=', 10) slv.add(t, '>=', 0.1) slv.add(y, '>=', 0.0) when 4 # xが最大値の時のyの最大値を求める slv.ok(y, 'max', nil, t) slv.add(t, '>=', 0.1) end slv.solve(true) slv.FinishDialog end wb.save enddownload slv08.rb