今回の記事では、サイボウズ社のグループウェア「ガルーン」のSOAP APIを利用して、VBScriptやVBAから「ファイルを添付したメッセージを送信」する処理のサンプルコードを紹介していきます。
ガルーンはオンプレ版を使用して検証していますが、クラウド版でもおそらく同様の実装で利用できると思います。
尚、当ブログでは、過去にVBAやVBScriptを使用した「メッセージ」を送信するサンプルプログラムを紹介しております。
ただ、その時の記事ではファイルの添付方法の解説まではしていなかったのですが、ファイル添付のやり方について当ブログに問い合わせをいただいたこともあり、新しく記事にしてみました。
以前に作成した「ガルーンのSOAP APIを使用してファイルを添付せずにメッセージを送信する方法」に関する記事のリンク先は以下です。
ファイルの添付が不要であれば、こちらの記事の方がシンプルでわかりやすいかと思います。
メッセージ送信APIの概要とファイル添付の仕組み
ガルーンで「メッセージ」を送信するSOAP APIの名称は「MessageCreateThreads」です。
当APIの詳しい解説は以下のサイボウズ社更新のデベロッパーサイトにてご確認ください。
サンプルプログラムの処理概要
今回紹介するサンプルプログラムは、VBA又はVBScriptで動作します。
尚、VBAとVBScriptは構文が似ており、VBScriptの方がVBAよりシンプルな言語仕様のため、VBScript用のコードであれば、そのコードを流用することで、VBAでもほぼ動作します。
よって、当記事では「VBScript」のコードで処理を解説していきます。
今回のサンプルプログラムの処理の流れは以下になります。
- 添付したいファイルをBase64形式でエンコードする
- メッセージ用xmlリクエストを作成してAPIにPOST
- API実行結果のレスポンスを受け取りxmlを解析
今回のポイントは、添付するファイルを「Base64」形式に変換する必要があるところです。
今回紹介するサンプルプログラムでは、このBase64形式への変換(エンコード)も実装しています。
次項で「Base64形式へのエンコード」について簡単に説明していきます。
【参考知識】「Base64」とは
当項では、記事の本題から少し外れますが、Base64へのエンコードを解説します。
まずはWikipediaから引用してみましょう。
Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式である。MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子メールにて広く利用されている。
Base64 -Wikipedia-
簡単に言えば、64進数で表現されるデータ形式です。
aからzとAからZ、0から9、+と/を使用してデータが構成されます(※さらにパディング用として = も使用)。
Wikipediaでは電子メールでファイルを添付する際に使用されると記載されておりますが、物理的なファイルをバイナリ形式の文字列に変換することで、あらゆるファイルをただのテキストデータとして通信データ内に組み込めるようになるため、電子メール以外にも広く利用されています。
今回の記事で紹介するようなWeb APIでは、xmlやjsonといったデータフォーマットがよく使われますが、それらのフォーマット内にBase64でエンコードしたバイナリ文字列を値に含めることは比較的容易であり、Web APIではファイル転送時のデータ変換処理として広く利用されています。
よって、ガルーンのAPIだけではなく、他社製のパッケージやクラウドサービスのWeb APIを利用する場合でもBase64を使用する機会は多いです。
これを機にBase64エンコードを習得しておくことをおススメします。
ファイルを添付してメッセージを送信するサンプルプログラム
当項では、ガルーンのSOAP APIとして提供されている「MessageCreateThreads」を使用して、ファイルを添付しつつメッセージを送信するサンプルプログラムを紹介していきます。
尚、冒頭でも説明しましたが、ファイル添付をしないメッセージの送信処理であれば、以下の記事で詳しく解説しているため、当記事では、ファイル添付をする際に必要な処理部分の解説と、全体のサンプルプログラムを紹介していきます。
ファイルをBase64形式にエンコードする処理
メッセージを送信する際には、Base64形式に変換したバイナリ文字列を、APIのリクエストに埋め込みます。
尚、Base64へエンコードするサンプルプログラムは、今回と同様に、SOAP APIを利用して、ガルーンの「ファイル管理」にファイルをアップロードするサンプルプログラムを紹介しており、その時に解説したサンプルプログラムと同一です。
ファイル管理へのアップロードの自動化に興味があれば、以下の記事も参考にしてください。

【ガルーン活用】VBSやVBAからSOAP APIを実行しファイル管理のファイルを更新しよう
今回の記事では、ガルーンのSOAP APIをVBAやVBScriptから実行して、ガルーンの「ファイル管理」内に登録済み...
'引数で渡されたパスのファイルをBase64エンコードした値を返します。
'引数1:エンコード対象のファイルパス
'戻り値:Base64のバイナリ値
Function base64_encode(TargetFilePath)
Const adTypeBinary = 1
Dim objStream
Dim xmlDoc
Dim objElement
Set objStream = CreateObject("ADODB.Stream")
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
'ストリームを開きます。
objStream.Open
'ストリームのタイプを1:バイナリで指定します。
objStream.Type = adTypeBinary
objStream.Position = 0
'ストリームにファイルを読み込みます。
objStream.LoadFromFile TargetFilePath
Set objElement = xmlDoc.CreateElement("dummy")
objElement.DataType = "bin.base64"
objElement.NodeTypedValue = objStream.Read
base64_encode = objElement.Text
Set xmlDoc = Nothing
Set objStream = Nothing
End Function
メッセージ送信APIのリクエスト(ボディ部)作成処理
SOAP APIの「MessageCreateThreads」に渡すXMLリクエストを作成して実行し、その実行結果を受け取ります。
尚、当サンプルでは、ファイルを添付する際に必要なパラメーターの「ファイル名」、「MIMEタイプ(こちらは任意)」は定数で予め定義するものとし、「ファイルデータ」は前述したFunctionプロシージャ「base64_encode」を使用して動的に取得する実装です。
ガルーンの「MessageCreateThreads」でメッセージを送る際に、
本文に改行を入れるやり方がわからないと当ブログに問い合わせをいただきました。
以下のサンプルでも実装しておりますが、「
」を入れると改行として扱われます。
'ガルーンのAPI(MessageCreateThreads)を実行し、メッセージを登録します。
'引数1:無し
'戻り値:登録時のIDを返します。※失敗した場合は0
Function ExeAPI_MessageCreateThreads()
Dim objHTTP
Dim Full_URL
Dim sEnv
Dim ReqXML
Dim objXML
Dim elm
Dim rtnVal
Dim attr
sEnv = sEnv & "<soap:Body> "
sEnv = sEnv & " <MessageCreateThreads> "
sEnv = sEnv & " <parameters> "
sEnv = sEnv & " <create_thread> "
sEnv = sEnv & " <thread id=""dummy"" version=""dummy"" subject=""APIテストメッセージ"" confirm=""false""> "
sEnv = sEnv & " <addressee user_id=""1"" name=""dummy"" deleted=""false""></addressee> "
sEnv = sEnv & " <content body=""テストメッセージ 改行テスト""> "
sEnv = sEnv & " <file id=""dummy"" name=""" & TARGET_FILE_NAME & """ mime_type=""" & TARGET_MIME_TYPE & """></file> "
sEnv = sEnv & " </content> "
sEnv = sEnv & " <folder id=""dummy""></folder> "
sEnv = sEnv & " </thread> "
sEnv = sEnv & " <file xmlns="""" id=""dummy""> "
sEnv = sEnv & " <content xmlns="""">""" & base64_encode(TARGET_FILE_PATH) & """</content>"
sEnv = sEnv & " </file> "
sEnv = sEnv & " </create_thread>"
sEnv = sEnv & " </parameters> "
sEnv = sEnv & " </MessageCreateThreads> "
sEnv = sEnv & "</soap:Body> "
sEnv = sEnv & "</soap:Envelope> "
Full_URL = BASE_URL & ACTION_API_DIR1
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.Open "POST", Full_URL, False
ReqXML = Get_CreateXML_Header("MessageCreateThreads") & vbcrlf & sEnv
'パラメーターを渡します。
objHTTP.send ReqXML
If objHTTP.Status <> 200 Then
'httpレスポンスコードが異常な場合は戻り値に0を返します。
ExeAPI_MessageCreateThreads = 0
Set objHTTP = Nothing
Exit Function
End If
'XML解析用のオブジェクトを生成します。
Set objXML = CreateObject("MSXML2.DOMdocument")
'レスポンスをxmlで読み込みます。
objXML.LoadXML(objHTTP.ResponseText)
rtnVal = 0
'レスポンスxmlの要素thread内の属性idの値を取得して戻り値にセットします。
For Each elm In objXML.getElementsByTagName("thread")
For Each attr In elm.attributes
If attr.name = "id" Then
rtnVal = attr.text
End If
Next
Next
ExeAPI_MessageCreateThreads = rtnVal
Set objHTTP = Nothing
Set objXML = Nothing
End Function
尚、上記サンプルプログラムでは、リクエストパラメーターの user_id に 1 を指定しています。
<addressee user_id=""1"" name=""dummy"" deleted=""false""></addressee> "
この user_idは、ガルーンの登録ユーザーごとに振られているID番号です。
1は通常、デフォルトのユーザーとして存在しているAdministratorです。
このサンプルでは、Administratorに対してメッセージを送信します。
こちらも必要によって、適切なユーザーIDを調べたうえで変更してください。
尚、このユーザーごとのIDはガルーンの内部的に振られている番号であり、ガルーンの管理画面等から確認することはできません。
「ログイン名」から「ユーザーID」を取得するには、別のWeb APIである「AdminGetUserIdByLoginName」を使用します。
必要によってこのAPIも使用してください。
サンプルプログラム全体(VBScript、VBA共通)
前項に紹介したFunctionプロシージャを使用しつつ、プログラム全体のサンプルを紹介します。
プログラムの冒頭の定数で、処理で必要になる値を設定しています。
使用する環境に合わせて変更する定数は以下です。
定数「LOGIN_USERNAME」で指定するログインユーザー名は、Web APIへのアクセス権が設定されている必要があります。
尚、当項では、VBScript版のプログラムを紹介しますが、VBAで動かす場合は、新しく標準モジュールを作成し、そのモジュール内に以下のプログラムをコピペしてください。
後、13行目の「Call GaroonAPI_Executor」を削除してください。
Option Explicit
CONST BASE_URL = "http://example.com/scripts/cbgrn/grn.exe/"
CONST LOGIN_USERNAME = "99999"
CONST LOGIN_PASSWORD = "xxxxxx"
CONST ACTION_API_DIR = "sysapi/admin/api?"
CONST ACTION_API_DIR1 = "cbpapi/message/api?"
CONST TARGET_FILE_PATH = "C:\test\test_data.pdf"
CONST TARGET_FILE_NAME = "test_data.pdf"
CONST TARGET_MIME_TYPE = "application/pdf"
'VBAで実行する場合は、以下の1行を削除してください。
Call GaroonAPI_Executor
Sub GaroonAPI_Executor()
Dim rtnCode
'メッセージ作成用のFunctionプロシージャを実行します。
rtnCode = ExeAPI_MessageCreateThreads()
If rtnCode = 0 Then
Msgbox "メッセージの登録に失敗しました。"
Else
Msgbox "メッセージの登録に成功しました。"
End If
End Sub
'引数で渡されたパスのファイルをBase64エンコードした値を返します。
'引数1:エンコード対象のファイルパス
'戻り値:Base64のバイナリ値
Function base64_encode(TargetFilePath)
Const adTypeBinary = 1
Dim objStream
Dim xmlDoc
Dim objElement
Set objStream = CreateObject("ADODB.Stream")
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
'ストリームを開きます。
objStream.Open
'ストリームのタイプを1:バイナリで指定します。
objStream.Type = adTypeBinary
objStream.Position = 0
'ストリームにファイルを読み込みます。
objStream.LoadFromFile TargetFilePath
Set objElement = xmlDoc.CreateElement("dummy")
objElement.DataType = "bin.base64"
objElement.NodeTypedValue = objStream.Read
base64_encode = objElement.Text
Set xmlDoc = Nothing
Set objStream = Nothing
End Function
'ガルーンのAPI(MessageCreateThreads)を実行し、メッセージを登録します。
'引数1:無し
'戻り値:登録時のIDを返します。※失敗した場合は0
Function ExeAPI_MessageCreateThreads()
Dim objHTTP
Dim Full_URL
Dim sEnv
Dim ReqXML
Dim objXML
Dim elm
Dim rtnVal
Dim attr
sEnv = sEnv & "<soap:Body> "
sEnv = sEnv & " <MessageCreateThreads> "
sEnv = sEnv & " <parameters> "
sEnv = sEnv & " <create_thread> "
sEnv = sEnv & " <thread id=""dummy"" version=""dummy"" subject=""APIテストメッセージ"" confirm=""false""> "
sEnv = sEnv & " <addressee user_id=""1"" name=""dummy"" deleted=""false""></addressee> "
sEnv = sEnv & " <content body=""テストメッセージ 改行テスト""> "
sEnv = sEnv & " <file id=""dummy"" name=""" & TARGET_FILE_NAME & """ mime_type=""" & TARGET_MIME_TYPE & """></file> "
sEnv = sEnv & " </content> "
sEnv = sEnv & " <folder id=""dummy""></folder> "
sEnv = sEnv & " </thread> "
sEnv = sEnv & " <file xmlns="""" id=""dummy""> "
sEnv = sEnv & " <content xmlns="""">""" & base64_encode(TARGET_FILE_PATH) & """</content>"
sEnv = sEnv & " </file> "
sEnv = sEnv & " </create_thread>"
sEnv = sEnv & " </parameters> "
sEnv = sEnv & " </MessageCreateThreads> "
sEnv = sEnv & "</soap:Body> "
sEnv = sEnv & "</soap:Envelope> "
Full_URL = BASE_URL & ACTION_API_DIR1
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.Open "POST", Full_URL, False
ReqXML = Get_CreateXML_Header("MessageCreateThreads") & vbcrlf & sEnv
'パラメーターを渡します。
objHTTP.send ReqXML
If objHTTP.Status <> 200 Then
'httpレスポンスコードが異常な場合は戻り値に0を返します。
ExeAPI_MessageCreateThreads = 0
Set objHTTP = Nothing
Exit Function
End If
'XML解析用のオブジェクトを生成します。
Set objXML = CreateObject("MSXML2.DOMdocument")
'レスポンスをxmlで読み込みます。
objXML.LoadXML(objHTTP.ResponseText)
rtnVal = 0
'レスポンスxmlの要素thread内の属性idの値を取得して戻り値にセットします。
For Each elm In objXML.getElementsByTagName("thread")
For Each attr In elm.attributes
If attr.name = "id" Then
rtnVal = attr.text
End If
Next
Next
ExeAPI_MessageCreateThreads = rtnVal
Set objHTTP = Nothing
Set objXML = Nothing
End Function
'リクエストで使用するXMLヘッダーの文字列を生成して返します。
Function Get_CreateXML_Header(API_Name)
Dim sEnv
sEnv = "<?xml version=""1.0"" encoding=""UTF-8""?>"
sEnv = sEnv & "<soap:Envelope xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"">"
sEnv = sEnv & " <soap:Header>"
sEnv = sEnv & " <Action>" & API_Name & "</Action>"
sEnv = sEnv & " <Security>"
sEnv = sEnv & " <UsernameToken>"
sEnv = sEnv & " <Username>" & LOGIN_USERNAME & "</Username>"
sEnv = sEnv & " <Password>" & LOGIN_PASSWORD & "</Password>"
sEnv = sEnv & " </UsernameToken>"
sEnv = sEnv & " </Security>"
sEnv = sEnv & " <Timestamp>"
sEnv = sEnv & " <Created>" & Get_forTimestampDate(0) & "</Created>"
sEnv = sEnv & " <Expires>" & Get_forTimestampDate(15) & "</Expires>"
sEnv = sEnv & " </Timestamp>"
sEnv = sEnv & " <Locale>jp</Locale>"
sEnv = sEnv & " </soap:Header>"
Get_CreateXML_Header = sEnv
End Function
'リクエストに含めるタイムスタンプを所定の書式で作成して返します。
'引数1:現在の日時から加算する分数
'戻り値:タイムスタンプ書式の日時
Function Get_forTimestampDate(add_Minutes)
Dim wkNow
'yyyy-mm-ddThh:mm:ssZの書式に変換します。
wkNow = Year(Dateadd("n",add_Minutes,Now()))
wkNow = wkNow & "-" & Right("0" & Month(Dateadd("n",add_Minutes,Now())) , 2)
wkNow = wkNow & "-" & Right("0" & Day(Dateadd("n",add_Minutes,Now())) , 2)
wkNow = wkNow & "T" & Right("0" & Hour(Dateadd("n",add_Minutes,Now())) , 2)
wkNow = wkNow & ":" & Right("0" & Minute(Dateadd("n",add_Minutes,Now())) , 2)
wkNow = wkNow & ":" & Right("0" & Second(Dateadd("n",add_Minutes,Now())) , 2)
wkNow = wkNow & "Z"
Get_forTimestampDate = wkNow
End Function
【おまけ】ファイルを複数添付する場合のパラメーターの渡し方
当記事ではファイルを一つ添付してメッセージを送る場合の実装方法を紹介してきましたが、複数のファイルを添付してメッセージを送る実装方法についても問い合わせをいただいたため、追加で解説します。
言葉で説明するより、生成するxmlを見ていただく方が早いかと思うので、複数のファイルを添付する場合のxml例を以下に記載します。
<create_thread>
<thread id="dummy" version="dummy" subject="APIテストメッセージ" confirm="false">
<addressee user_id="1" name="dummy" deleted="false"></addressee>
<content body="テストメッセージ 改行テスト">
<file id="1" name="ファイル名A" mime_type="application/pdf"></file>
<file id="2" name="ファイル名B" mime_type="application/pdf"></file>
</content>
<folder id="dummy"></folder>
</thread>
<file xmlns="" id="1">
<content xmlns="">"ファイル名AのBase64の値"</content>
</file>
<file xmlns="" id="2">
<content xmlns="">"ファイル名BのBase64の値"</content>
</file>
</create_thread>
ポイントはfile要素のidです。
ファイルを一つだけ添付する場合は、idは使用しない為、”dummy”をセットしていました。
複数ファイルを一つのメッセージに添付する場合は、リクエストで渡すパラメーターの要素「thread」配下の要素「file」のidと、要素「create_thread」の直下の要素「file」内のidとを紐付けることが必要になります。
その紐づけ方法として、それぞれのidに対して任意の番号を指定します。
上記のxml例では、fileのidに対して1と2をそれぞれ指定しています。
こうすることで、一つのメッセージで複数のファイルを添付することが可能です。
最後に
今回の記事では、ガルーンのSOAP APIを使用して、ファイルを添付したメッセージを送信するプログラムを紹介しました。
尚、今回の記事で紹介したBase64エンコード処理は、ガルーンでファイルをアップロードする別の処理でも使用しますし、ガルーンに限らず、Web APIを利用してファイル転送を行う場合に広く使用されている手法です。
よって、是非覚えておいてください。
今回も読んでいただきありがとうございました。
それでは皆さま、ごきげんよう!