#!/usr/bin/env ruby
require 'win32ole'
wso = WIN32OLE.new('WScript.Shell')
["USERPROFILE", "HOMEDRIVE", "HOMEPATH"].each{|k|wso.Environment("Process").setproperty("item", k, (["Process", "Volatile", "User", "System"].map{|t|wso.Environment(t).Item(k)} << ENV[k]).bsearch{|x|x!=""})}
fso = WIN32OLE.new('Scripting.FileSystemObject')
xl = WIN32OLE.new('Excel.Application')
xl.Visible = true
unless 0 < ARGV.count
wb = xl.Workbooks.Add() # 新規ワークブック
else
wb = xl.Workbooks.Open(fso.GetAbsolutePathName(ARGV[0])) # 既存のワークブック
end
p wb
4行目で WSH の
WshEnvironment へ 3 つの環境変数(USERPROFILE, HOMEDRIVE, HOMEPATH)を上書きしているが、これを行わない場合、自分の環境では Workbook を開く際に以下のようなエラーが発生してしまう。
2013-09-09 現在以下の環境で行った結果
- Windows 7 Ultimate SP1
- Microsoft Office Professional 2010
- cygwin/x86
- rbenv / Ruby 2.0.0p0
ローカルフォルダ
$ ./win32ole_excel.rb
./win32ole_excel.rb:10:in `method_missing': (in OLE method `Add': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
メモリまたはディスクの空き容量が不足しているため、ドキュメントを開いたり、保存したりできません。
? 不要なブックやプログラムを終了して、メモリの空き容量を増やしてください。
? ディスクに保存されている不要なファイルを削除して、ディスクの空き容量を増やしてください。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:10:in `<main>'
$ ./win32ole_excel.rb hoge.tsv
./win32ole_excel.rb:12:in `method_missing': (in OLE method `Open': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
メモリまたはディスクの空き容量が不足しているため、ドキュメントを開いたり、保存したりできません。
? 不要なブックやプログラムを終了して、メモリの空き容量を増やしてください。
? ディスクに保存されている不要なファイルを削除して、ディスクの空き容量を増やしてください。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:12:in `<main>'
$ ./win32ole_excel.rb hoge.csv
./win32ole_excel.rb:12:in `method_missing': (in OLE method `Open': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
メモリまたはディスクの空き容量が不足しているため、ドキュメントを開いたり、保存したりできません。
? 不要なブックやプログラムを終了して、メモリの空き容量を増やしてください。
? ディスクに保存されている不要なファイルを削除して、ディスクの空き容量を増やしてください。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:12:in `<main>'
$ ./win32ole_excel.rb hoge.xlsx
#<WIN32OLE:0x80148db0>
リモート(ネットワークドライブ)
$ ./win32ole_excel.rb
./win32ole_excel.rb:10:in `method_missing': (in OLE method `Add': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
メモリまたはディスクの空き容量が不足しているため、ドキュメントを開いたり、保存したりできません。
? 不要なブックやプログラムを終了して、メモリの空き容量を増やしてください。
? ディスクに保存されている不要なファイルを削除して、ディスクの空き容量を増やしてください。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:10:in `<main>'
$ ./win32ole_excel.rb hoge.tsv
./win32ole_excel.rb:12:in `method_missing': (in OLE method `Open': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
ファイル '... \hoge.tsv' にアクセスできません。次のいずれかの理由が考えられます。
? ファイル名またはパスが存在しません。
? ファイルが他のプログラムによって使用されています。
? 保存しようとしているブックと同じ名前のブックが現在開かれています。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:12:in `<main>'
$ ./win32ole_excel.rb hoge.csv
./win32ole_excel.rb:12:in `method_missing': (in OLE method `Open': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
ファイル '... \hoge.csv' にアクセスできません。次のいずれかの理由が考えられます。
? ファイル名またはパスが存在しません。
? ファイルが他のプログラムによって使用されています。
? 保存しようとしているブックと同じ名前のブックが現在開かれています。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:12:in `<main>'
$ ./win32ole_excel.rb hoge.xlsx
./win32ole_excel.rb:12:in `method_missing': (in OLE method `Open': ) (WIN32OLERuntimeError)
OLE error code:800A03EC in Microsoft Excel
ファイル '... \hoge.xlsx' にアクセスできません。次のいずれかの理由が考えられます。
? ファイル名またはパスが存在しません。
? ファイルが他のプログラムによって使用されています。
? 保存しようとしているブックと同じ名前のブックが現在開かれています。
HRESULT error code:0x80020009
Exception occurred.
from ./win32ole_excel.rb:12:in `<main>'
上記の結果を見ての通り、
ローカルだと xlsx は開けるものの、.Add() や csv, tsv の .Open() が失敗してしまい、
リモートだと .Add(), .Open() がすべて失敗してしまうという状況。
ファイルの置き場所がローカルかリモートかで失敗したとされる原因が微妙に異なっているのも気持ち悪いのだが、
ディスクもメモリもたっぷり余っているし、当該のファイルも開いてない状態なので原因がさっぱりわからない。
とりあえず、参考にしたページから、環境変数に問題がありそうだと当りが付いたので、以下のような感じで調べた。
envcheck.js
var wso = WScript.CreateObject("WScript.Shell");
var types = ["SYSTEM", "USER", "VOLATILE", "PROCESS"];
var keys = ["TEMP", "USERPROFILE", "HOMEDRIVE", "HOMEPATH"]
var t,k;
for (t = 0; t < types.length; t++) {
for (k = 0; k < keys.length; k++) {
WScript.echo("Environment("+types[t]+").Item("+keys[k]+")="+(wso.Environment(types[t]).Item(keys[k])));
}
}
実行結果
>cscript /nologo envcheck.js
Environment(SYSTEM).Item(TEMP)=%SystemRoot%\TEMP
Environment(SYSTEM).Item(USERPROFILE)=
Environment(SYSTEM).Item(HOMEDRIVE)=
Environment(SYSTEM).Item(HOMEPATH)=
Environment(USER).Item(TEMP)=%USERPROFILE%\AppData\Local\Temp
Environment(USER).Item(USERPROFILE)=
Environment(USER).Item(HOMEDRIVE)=
Environment(USER).Item(HOMEPATH)=
Environment(VOLATILE).Item(TEMP)=
Environment(VOLATILE).Item(USERPROFILE)=C:\Users\kou
Environment(VOLATILE).Item(HOMEDRIVE)=C:
Environment(VOLATILE).Item(HOMEPATH)=\Users\kou
Environment(PROCESS).Item(TEMP)=C:\Users\kou\AppData\Local\Temp
Environment(PROCESS).Item(USERPROFILE)=C:\Users\kou
Environment(PROCESS).Item(HOMEDRIVE)=C:
Environment(PROCESS).Item(HOMEPATH)=\Users\kou
envcheck.rb
#!/usr/bin/env ruby
require 'win32ole'
wso = WIN32OLE.new('WScript.Shell')
keys = ["TEMP", "USERPROFILE", "HOMEDRIVE", "HOMEPATH"]
types = ["SYSTEM", "USER", "VOLATILE", "PROCESS"]
types.each{|t|
keys.each{|k| puts '%-43s = "%s"' % ['Environment("%s").Item("%s")' % [t, k], wso.Environment(t).Item(k)]}
}
keys.each{|k| puts '%-43s = "%s"' % ['ENV["%s"]' % k, ENV[k]]}
keys.each{|k|
wso.Environment("Process").setproperty("item", k,
(["Process", "Volatile", "User", "System"].map{|t|wso.Environment(t).Item(k)} << ENV[k]).bsearch{|x|x!=""}
)
}
["PROCESS"].each{|t|
keys.each{|k| puts '%-43s = "%s"' % ['Environment("%s").Item("%s")' % [t, k], wso.Environment(t).Item(k)]}
}
実行結果
$ ./envcheck.rb
Environment("SYSTEM").Item("TEMP") = "%SystemRoot%\TEMP"
Environment("SYSTEM").Item("USERPROFILE") = ""
Environment("SYSTEM").Item("HOMEDRIVE") = ""
Environment("SYSTEM").Item("HOMEPATH") = ""
Environment("USER").Item("TEMP") = "%USERPROFILE%\AppData\Local\Temp"
Environment("USER").Item("USERPROFILE") = ""
Environment("USER").Item("HOMEDRIVE") = ""
Environment("USER").Item("HOMEPATH") = ""
Environment("VOLATILE").Item("TEMP") = ""
Environment("VOLATILE").Item("USERPROFILE") = "C:\Users\kou"
Environment("VOLATILE").Item("HOMEDRIVE") = "C:"
Environment("VOLATILE").Item("HOMEPATH") = "\Users\kou"
Environment("PROCESS").Item("TEMP") = ""
Environment("PROCESS").Item("USERPROFILE") = ""
Environment("PROCESS").Item("HOMEDRIVE") = ""
Environment("PROCESS").Item("HOMEPATH") = ""
ENV["TEMP"] = "/tmp"
ENV["USERPROFILE"] = "C:\Users\kou"
ENV["HOMEDRIVE"] = "C:"
ENV["HOMEPATH"] = "\Users\kou"
Environment("PROCESS").Item("TEMP") = "%USERPROFILE%\AppData\Local\Temp"
Environment("PROCESS").Item("USERPROFILE") = "C:\Users\kou"
Environment("PROCESS").Item("HOMEDRIVE") = "C:"
Environment("PROCESS").Item("HOMEPATH") = "\Users\kou"
あとは、動作に必要な最低限の環境変数がどれか絞り込むという地味な作業。
以下、参考にしたページでは、環境変数 TEMP の設定が原因になっている場合もあるようなので、
TEMP もコピーしておいた方が良いのかもしれないが、うちの環境では TEMP は放置しておいても特に問題なく動いている模様。
参考:
コメントをかく