関連ページ  
力任せの WEB アプリ (3) -- IFRAME 内の Excel VBA

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 アプリとしては現実的ではありません
( 管理する内容も増えますし )

しかし、この方法も力任せなので、きちんとした運用ルールとメンテする側での仕様を
明確にドキュメント化していなければ、これもまた現実的では無くなってしまいます。