IFRAME 内の Excel との直接アクセスはできないので、クリップボードを使用します。
重要なのは、Excel 側で VBA マクロを使用する必要があるので、IFRAME に Excel
をロードした時に、警告ダイアログを出さないようにする方法です
レジストリの書き換え
既に、「信頼するサイト」として実行している URL をIE に登録済みなので、
レジストリを直接書き換える事ができます。
Excel のマクロのセキュリティレベルは単純で、ログインユーザ毎に
1 <= 低、3<= 高 というふうにデータを書き換えると即座に有効になり、
ロードした後で元に戻しても制限対象にはならないので、以下のコード
で対処します
<HTML>
<HEAD>
<script language="VBScript">
Dim flg,flgLoad,ExcelSheet,MyBook
flg = False
flgLoad = False
Call window.setInterval("Call set_cellloc()", 500)
</script>
</HEAD>
<BODY>
<IFRAME
id="xls"
frameborder="no"
scrolling="no"
width="600"
height="400"
onLoad="Call update_cell()"
></IFRAME>
<br>
<INPUT type="button" value="この値をセルにセット" onClick="flg=True:Call reload()">
<INPUT type="text" id="cell">
<br>このフィールドにセル位置をセット=><INPUT type="text" id="cellloc">
<script language="VBScript">
' **********************************************************
' レジストリを変更する為のオブジェクト
' **********************************************************
Set WshShell = CreateObject("WScript.Shell")
' **********************************************************
' Excel のセキュリティレベルを低にして、マクロを実行可能にする
' **********************************************************
WshShell.RegWrite "HKCU\Software\Microsoft\Office\11.0\Excel\Security\Level", 1, "REG_DWORD"
' **********************************************************
' マクロを含んだ Excel ブック
' **********************************************************
document.getElementById("xls").contentWindow.location = "webexcel.xls"
' **********************************************************
' いったんロードすると、必要無いので再びセキュリティを変更
' ( 但し1秒後 )
' **********************************************************
Call window.setTimeout("Call reset_reg()", 1000)
' **********************************************************
' Excel のセキュリティレベルを高にして通常セキュリティにする
' **********************************************************
function reset_reg()
WshShell.RegWrite "HKCU\Software\Microsoft\Office\11.0\Excel\Security\Level", 3, "REG_DWORD"
flgLoad = True
end function
' **********************************************************
' Excel を更新した後の処理
' 再ロードの為のセキュリティレベルの変更処理もあり
' **********************************************************
function update_cell()
if flg then
Set ExcelApp = CreateObject("Excel.Application")
Set MyBook = ExcelApp.Workbooks.Open("c:\\tmp\\001\\app\\webexcel.xls")
MyBook.Sheets("Sheet1").Cells(1, 1) = document.getElementById("cell").value
MyBook.Save()
ExcelApp.Quit()
Set ExcelApp = Nothing
WshShell.RegWrite "HKCU\Software\Microsoft\Office\11.0\Excel\Security\Level", 1, "REG_DWORD"
document.getElementById("xls").contentWindow.location = "webexcel.xls"
Call window.setTimeout("Call reset_reg()", 1000)
end if
end function
' **********************************************************
' IE 上の Excel をアンロードする為の処理
' **********************************************************
function reload()
if flg then
document.getElementById("xls").contentWindow.location = "about:blank"
end if
end function
' **********************************************************
' Excel のマクロから受け渡されたクリップボード上の
' データをフィールドにセット
' **********************************************************
function set_cellloc()
Dim str
if flgLoad then
str = window.clipboardData.getData("Text")
if Left( str, 3 ) = "***" then
document.getElementById("cellloc").value = Replace(str,"***","")
end if
end if
end function
</script>
</body>
</html>
書き換えた後のローディングは問題無いのですが、ローディングそのものが
非同期である為、Excel の処理を書いた後に即レジストリを戻せません。
そこで、window.setTimeout で、1秒後に戻しています
( 1秒という数字に根拠はありませんので、問題があれば増やします )
また、Excel 側からセットされたクリップボードデータを監視する為に、
window.setInterval を使って、0.5 秒毎にフォーマットをチェックして
取得しています( ここでは頭3文字が "***" )
Excel 側は VB Editor で以下のようなイベントをシート毎に書きます
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim CB As New DataObject
With CB
.SetText "***" & Target.Column & "|" & Target.Row
.PutInClipboard ''DataObjectのデータをクリップボードに格納する
End With
End Sub
VBA は詳しく無いので、クリップボードに関する手法は、インターネットの情報
をそのまま利用しています。そこでは、上記参照をする事が前提のコードと書いてありました。
ここでは実装していませんが、ページのアンロード時にクリップボードに "***" を送る
事で、次回の連続使用の対応になります( アプリの仕様によっては必要無いかもですが )
マクロの対応として、デジタル署名を利用する手もありますが、Office のツールでは、
PC 一台ごとに Excel を作成する必要があるので、WEB アプリとしては現実的ではありません
( 管理する内容も増えますし )
しかし、この方法も力任せなので、きちんとした運用ルールとメンテする側での仕様を
明確にドキュメント化していなければ、これもまた現実的では無くなってしまいます。
|
|