今回やりたい事
以前の記事でPowerAppsで撮った画像をSharePointリストに保存し、それを他のPowerAppsのアプリで見るやり方を書きました。「【PowerApps】カメラで撮った画像をSharePointリストに保存し、他のアプリで見る。」
今回その画像をエクセルから開く案件がありましたが、Power Automateを使わないでやりたいという案件でした。悪戦苦闘をして出来たのでここに備忘録しておきます。
Base64をデコードするアプローチ
最初、偶然 Base64の文字列をChromeのURLボックスにコピペしたらその画像が出てくるのを発見しました。VBAやVBスクリプトでそれを再現出来ないか試しましたが出来なかったし、どうやらそれが出来るのはChromeブラウザーだけなのが分かってそのアプローチは止めました。
次に思いついたのがPowerAppsが画像ファイルをエンコードしてBase64に変換したのだからデコードすれば画像ファイルに戻るのではないかという事です。
エンコードとデコードについてはこのページが分かり易いです。
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
エクセルVBAでBase64をデコードする
早速、「vba base64 画像にデコード」と言うキーワードでググりました。そしてこちらのページのコードを参考に自分でコードを書いてみました。
ファイルをBase64エンコード・デコードするVBAマクロ | 初心者備忘録
Private Function DecodeBase64(ByVal Base64Str As String, ByVal FilePath As String) As Long
'Base64の文字列をデコード
Dim elm As Object
Dim ret As Long
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
ret = -1 '初期化
On Error Resume Next
Set elm = CreateObject("MSXML2.DOMDocument").createElement("base64")
elm.DataType = "bin.base64"
elm.Text = Base64Str
With CreateObject("ADODB.Stream")
.Type = adTypeBinary
.Open
.Write elm.nodeTypedValue
.SaveToFile FilePath, adSaveCreateOverWrite
.Close
End With
If Err.Number <> 0 Then ret = 0
On Error GoTo 0
DecodeBase64 = ret
End Function
参考にと言いながら上のコードは先ほどのページからのほとんんどコピペです。笑)感謝しかありません。ですので詳しい説明は割愛させて頂きます。要はMSXMLのBase64デコード機能を使用しています。上のコードは優れもので、参照設定無しで使えたので良かったです。
上のコードを標準モジュールに保存してBase64の文字列と保存先のURLを引数とするDecodeBase64関数を作った事になるのです。
最初の「Base64」までの文字を消すのがミソ
このDecodeBase64関数をメインのプロシジャーに入れて、引数の保存先を開ければ画像ファイルが開くのを期待したのですが上手く開きません。涙目)やっぱり無理かと諦めかけてたところヒントとなるページを見つけました。(すみません、この記事を執筆している時に見つからず、URLが分かりませんでした。)
PowerAppsのBase64でエンコードした文字列はいつも「data:image/jpeg;base64」から始まります。どうやらこれを含めずにデコードしたら良いらしいのです。
標準モジュールに下記のコードを入れました。
result = DecodeBase64(Mid(ImageURL, InStr(ImageURL, "base64,") + 7), SavePath2)
ImageURLがBase64の文字列が入った変数、SavePath2が保存したいファイル名のFullPathが入った変数です。これは関数なので結果をresultという変数に入れます。この二つの引数に問題があると「‐1」という結果が返ってきます。上手くいくと「0」が返ってきます。数式内のMid関数でBase64の文字列の最初の「Base64」までの文字を削除しています。
参考までに下記のコードで保存した画像ファイルをそのまま開けられます。
CreateObject("Shell.Application").Open (SavePath2)
これを達成するまでに数時間を要しました。なんか人生を無駄にしていますかね。