2017年1月26日木曜日

webサーバ上のExcelファイルなどを開く

WScript.ShellオブジェクトのRunメソッドなどに「http://~~/sample.xlsx」などのアドレスを普通に渡すと、まずブラウザが起動して「ファイルを開く?保存する?」の問いかけメッセージが表示されます。


「開く」を選択するとファイルが開き、その前に開かれた空白のページは自動で閉じてくれるけど、、

ちょっとしたことだけど、煩わしいです。
まず問いかけを無くしたい。
そもそもブラウザを起動してほしくない。

……という要求を満たすアイデアを見つけました。


選択肢はいくつかあります。

A.ファイルに対して適切なコマンドでRunする。
例えばExcelファイルなら shell.run('excel http://~~/sample.xlsx') のようにすればOK。
しかしこれではコマンドが不明な拡張子などには対応できません。

B.assocコマンドとftypeコマンドを使って拡張子に対応する規定のコマンドを調べて、Runする。
これでどんな拡張子だろうと対応するコマンドで開ける!と思いきや、試しにやってみるとftypeの返り値は以下のようになります。

コマンドの形式がバラバラで、開きたいファイルのURLと組み合わせるのも難しいです。
そもそもコマンドが取得できない拡張子もあるようですし。。

C.一時フォルダにダウンロードして開く。
Runメソッドに渡すアドレスが「http://」から始まる文字列だからブラウザが起動してしまうのです。
ローカルエリア内のアドレスを渡せばファイルをダブルクリックして開く時と同じリアクションをしてくれます。


というわけでダウンロードして開くスクリプトは以下
<html>
<title>拡張子に対応するコマンド</title>
<body>
<input id=inp style="width:100%;">
<button id=btn0>普通にrun</button>
<button id=btn1>規定コマンドを調べる</button>
<button id=btn2>一時フォルダにコピーして開く</button>
<div id=div></div>
</body>
<script>
btn0.onclick=function(){
shell.run(inp.value)
}
btn1.onclick=function(){
var str=inp.value, 拡張子=str.split('.').pop()
var assoc=execCMD('assoc .'+拡張子)
if(assoc.StdErr){ return alert(assoc.StdErr) }
var ftype=execCMD('ftype '+assoc.StdOut.split('=')[1])
if(ftype.StdErr){ return alert(ftype.StdErr) }
var cmd=ftype.StdOut.split('=')
cmd.shift()
cmd = cmd.join('=')
var reg=/%1/, path=必要ならpathをDQで囲む(inp.value)
if(cmd.match(reg)){ cmd = cmd.replace(reg,path) }else{ cmd += ' '+path }
div.innerText = 'assoc = ['+assoc.StdOut+']\n\nftype = ['+ftype.StdOut+']\n\ncmd = ['+cmd+']'
}
btn2.onclick=function(){
var URL=inp.value, path=必要ならpathをDQで囲む(fs.GetSpecialFolder(2)+'\\'+fs.GetFileName(URL))
switch(1){
case 0:
// bitsadminというものを使う方法もあるらしいが、実行してみたら
// 「現在のユーザーのジョブ数がユーザー1人あたりのジョブ数の制限を超えています。」というエラーが出た。
execCMD('bitsadmin.exe /TRANSFER hoge '+URL+' '+path)
case 1:
// PowerShellを利用するのでWin7以降限定になるが、以下は動作した。
if(0){
// 以下は一応動作するが、なぜかcmd.exeの画面を手動でとじなければいけない。
execCMD('@powershell -NoProfile -ExecutionPolicy Bypass -Command "$d=new-object System.Net.WebClient;$d.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials;$d.DownloadFile(\''+URL+'\','+path+')')
}
shell.run('powershell -Command "$d=new-object System.Net.WebClient;$d.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials;$d.DownloadFile(\''+URL+"','"+fs.GetSpecialFolder(2)+'\\'+fs.GetFileName(URL)+"')", 1, true)
}
shell.run(path, 1, true)
fs.DeleteFile(path)
}
execCMD=function(コマンド){
var obj=shell.exec('cmd /C '+コマンド)
return {StdOut:obj.StdOut.ReadAll(), StdErr:obj.StdErr.ReadAll() }
}
AXO=function(name){return new ActiveXObject(name)}
shell = AXO('WScript.Shell')
fs = AXO('Scripting.FileSystemObject')
必要ならpathをDQで囲む=function(path){return 0<path.indexOf(' ') ? ('"'+path+'"') : path}
resizeTo(400,400)
</script>
</html>

用が済んだら後始末もしてくれます。

0 件のコメント:

コメントを投稿