はじめに
Excelに入力した内容をリアルタイムでWebアプリに反映させたかったので、Excelファイルにマクロを仕込んでサーバにPOST⇒DBを更新してみました。
サーバ側はC#で実装しました。
また、サーバ側のExcel操作はOpenXmlを使用しました。
サンプルコード
Excel側で「Excel_Post()」を実行すれば、自身が「http://hoge.com/sample/excel_post/」にPOSTされる。
Excel側
vba
Sub Excel_Post()
Dim fileName As String
Dim retCd As Integer
Dim fso As Object
Dim objHTTP As Object
Dim objStream As Object
On Error GoTo ErrorHandler
'-----自身をPOST出来ない為、別名で保存する-----
Set fso = CreateObject("Scripting.FileSystemObject")
'Tempファイル名を生成
fileName = fso.GetSpecialFolder(2) & "\" & fso.GetBaseName(fso.GetTempName) & ".xlsx"
'保存時のダイアログを表示しなくする
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'新規ブックにシートをコピーして保存⇒閉じる
ThisWorkbook.Worksheets().Copy
ActiveWorkbook.SaveAs fileName
ActiveWorkbook.Close
'ダイアログ非表示の設定を戻す
Application.DisplayAlerts = True
Application.ScreenUpdating = True
'-----
'-----Streamに変換する-----
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = 1
objStream.Open
objStream.LoadFromFile fileName
'-----
'-----WebAPIにPOSTする-----
Set objHTTP = CreateObject("msxml2.xmlhttp")
objHTTP.Open "POST", "http://hoge.com/sample/excel_post/", False
objHTTP.setRequestHeader "Content-Length", objStream.Size
objHTTP.send objStream.Read(objStream.Size)
'-----
'送信したらStreamを閉じる&Tempファイルを削除する
objStream.Close
fso.DeleteFile fileName, True
'readyStateが4で読み込み完了⇒先の処理に進む
Do While objHTTP.readyState < 4
DoEvents
Loop
retCd = objHTTP.Status
If retCd = 200 Then
'戻り値を使った処理
'objHTTP.responseTextでレスポンスが取得できる
Else
Call MsgBox("error:" & retCd)
End If
GoTo Finally
ErrorHandler:
Call MsgBox("error:" & Err.Description)
Resume Finally
Finally:
Set objHTTP = Nothing
Set objStream = Nothing
Set fso = Nothing
End Sub
サーバー側
C#
using OfficeOpenXml;
byte[] ret;
using (ExcelPackage package = new ExcelPackage(Request.InputStream))
{
ret = package.GetAsByteArray();
}
補足
自身を読み込もうとすると「objStream.LoadFromFile fileName」で「3002:ファイルを開けませんでした。」になる。
その対策として、Tempファイルを作成している。
一時ファイルの保存先
fso.GetSpecialFolder(0) ⇒ C:\Windows
fso.GetSpecialFolder(1) ⇒ C:\Windows\System32
fso.GetSpecialFolder(2) ⇒ C:\Users\xxxx\AppData\Local\Temp
となる。
ランダムなファイル名を取得
fso.GetTempName ⇒ ランダムなファイル名(例「rad7704F.tmp」)
ファイル拡張子を除去
fso.GetBaseName([ファイル名]) ⇒ ファイル名(拡張子あり)を引数に、ファイル名(拡張子なし)を返却