【ガルーン活用】VBSやVBAからSOAP APIを実行してユーザー登録を自動化【前編】

ガルーン活用
スポンサーリンク

今回の記事では、ガルーンの「SOAP API」を利用して、ガルーンへのログインからユーザー登録の一連の流れをVBScriptやVBAで実装する際のサンプルコードを紹介します。

尚、APIの基礎やガルーンのSOAP APIの理解を深めていただくために、前編後編で分けて記事を作成していきます。

↓後編はこちらのリンクから

今回の前編では、APIやSOAP APIの説明とともに、ガルーンへのログインとログアウトまでのサンプルプログラムまでを紹介し、次回の後編で一通りの処理を実装していきます。

APIを利用することのメリット

今回紹介するサイボウズ社のグループウェア「ガルーン」でもそうですし、最近の様々なパッケージソフトやクラウドサービスでは「API」が提供されています。

当記事では、まず最初に、これまで「API」を活用されてこなかった方に対して、APIを活用するメリットを紹介していきます。

そもそも「API」ってなに?

API」とは「Application Programming Interface」の略称であり、今回紹介するガルーンや、その他の様々なパッケージソフトやクラウドサービスなどの機能を部分的に抜き出して、外部プログラムからそのパッケージソフトやクラウドサービスを操作するための「部品」として提供する仕組みのことを指します。

APIを利用してデータ登録する場合の通常のデータ登録イメージ

上記のイメージ図のように、通常は人がそのアプリケーションの入力画面を介してデータ登録を手作業で実施するのですが、APIを活用することで、例えば外部のデータベースからVBSやVBAなどのプログラムを利用して、関連するデータを抽出し、そのデータを元に対象のアプリケーションのAPIを実行してデータ登録の一連の作業を自動化することができます。

APIはデータを登録する処理だけではなく、データを検索したり、取得する処理も提供されています。

操作を外部のプログラムから行うための部品がAPIであり、多くの種類のAPIが提供されているパッケージソフトやクラウドサービスでは、様々な操作が自動化できることになります。

「SOAP API」と「REST API」について

今回のガルーンでは提供されているAPIの種類が大きく二つに分かれており、「SOAP API」と「REST API」の二種類があります。

このそれぞれのAPIはガルーンだけで提供されている仕組みではなく、ウェブの通信を使用したデータ交換やアプリケーション実行に関する共通規格や共通した設計思想であり、知識としても簡単にその違いを知っておくほうが、よりコーディング時の理解も深まると考えます。

よって、その違いについて紹介していきます。

SOAP API

SOAP APIの「SOAP」とは、「Simple Object Access Protocol」の略称であり、Microsoftが開発、規格化し、長らくウェブアプリケーションにおいて使われてきた、ウェブにおけるデータ送信やデータ形式に纏わる共通規格のことを指します。

SOAPでは、厳格に定められたフォーマットのXML形式のデータを使用します。

このXML形式のデータは拡張性が高い反面、記述は煩雑であり、且つ厳格である必要があるため、このXMLの生成及びその解析を規格の古いプログラミング言語で行う場合は、実装に手間が掛かります。

後述するREST APIと比べると、SOAPの名称にある「Simple」とはかけ離れた仕様だと言えます。

後、特徴として、SOAPではAPIを設置するURLは一つか、または最小限の分類分け程度にURLを用意し、機能単位でURLを分けることはしません。

APIに渡すXML内で実行するAPI名を指定します。
後述するREST APIでは、APIごとにURLを分けます。

よって、複雑な業務アプリケーションなどを開発する場合は、一つのURLで各APIを呼び出せるこの仕様の方が実装はしやすいと思います。

他にも色々と特徴はありますが、簡単にまとめると以下です。

規格が古く、呼び出し処理を実装する場合にコードが複雑化し易く、あまり今どきではない。

尚、ガルーンにおける「SOAP API」は「REST API」よりも先に実装されており、それが理由だとは思いますが、ガルーンのAPIの機能でもSOAP APIの方がREST APIよりも機能が多いため、今回の記事で実施する「ユーザーアカウント登録」といった機能はSOAP APIでしか提供されていません。

REST API

REST APIの「REST」とは「Representational State Transfer」の略称です。
前述したSOAP APIよりも後から生まれたウェブアプリケーションにおけるデータ交換の仕組みです。

SOAPは厳格な共通規格として存在しますが、RESTは規格ではなく「設計思想」です。
よって、その設計思想に準じた実装をしているREST APIを「RESTful API」と呼んだりします。

RESTは以下の特徴があります。

  • データフォーマットはJSONが一般的
  • 機能ごと(APIごと)に呼び出し先のURLが異なる
  • 一度のAPIの実行で完結する(セッション管理をしない)

前述するSOAPと比較した場合は簡単にまとめると以下です。

より容易に利用できるようにし、API自体の機能も可能な限り単純化して、アプリケーションにおける機能の部品化をより推し進めたもの。

尚、ガルーンにおける「REST API」は前述したように後発で実装されており、まだ提供されている機能が少ないです。

特にデータを登録するとか更新するといった機能については、SOAPしか対応していないものが多いため、今後REST APIを充実させてもらえるのを期待しています。

サンプルプログラムの仕様について

当項では、今回の記事で紹介するサンプルプログラムの仕様について簡単に定義します。

  • パッケージ版ガルーンで検証済み(クラウド版も多分使える)
  • プログラミング言語はVBScript
  • 認証方式は「WS-Security」を使用
  • 「WSDL」の読み込みはしない(VBSやVBAではできない)
  • XMLはべた書き又は「MSXML2.DOMdocument」で生成
当記事で掲載するサンプルプログラムは「VBScript」で作成したものですが、VBAと言語仕様は共通であり、ほぼコピペで動作します。
上記の「WSDL」とは、「Web Services Description Language」の略称であり、ウェブサービスの仕様等を定義します。
C#などの別の言語ではこのWSDLをIDEで読み込ませることで、煩雑なXML文の作成処理を自前で実装する必要は無くなります。

今回の記事では前編でありログインとログオフの処理しか扱いませんが、後編の記事では以下の流れで実装した処理を紹介する予定です。

  1. データベースから登録及び更新データを取得
  2. APIでガルーンにログイン
  3. APIでガルーンのログイン名からユーザーIDを取得
  4. 取得したユーザーIDをもとにAPIでユーザーの登録又は更新を実施
  5. APIでガルーンからログオフ

尚、APIの呼び出しや仕様については、サイボウズ社のデベロッパーサイトをご確認ください。

ログイン用APIを実行するサンプルプログラム

まずは、SOAP APIを使用してガルーンにログインするサンプルプログラムを紹介します。

使用するAPI名は「UtilLogin」です。
詳細な仕様は以下のリンクからご確認ください。

上記のリンクを読めばわかりますが、「UtilLogin」では以下のようなxmlを作成してガルーンのAPIにPOSTするだけだということがわかります。

  <?xml version="1.0" encoding="UTF-8"?>
   <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
     <soap:Header>
       <Action>UtilLogin</Action>
       <Security></Security>
       <Timestamp>
         <Created>2010-08-12T14:45:00Z</Created>
         <Expires>2037-08-12T14:45:00Z</Expires>
       </Timestamp>
       <Locale>jp</Locale>
     </soap:Header>
     <soap:Body>
       <UtilLogin>
         <parameters>
           <login_name>xxxxxxxxxx</login_name>
           <password>xxxxxxx</password>
         </parameters>
       </UtilLogin>
     </soap:Body>
   </soap:Envelope>

尚、最も基本となる処理であり、SOAP APIの入門記事も兼ねているため、XMLをベタ書きした場合の処理と、MSXML2.DOMdocumentでXMLを生成する場合の処理の二通りを紹介します。

個人的には可読性を考慮すると、XMLをベタ書きするほうがまだ読みやすいと思います。

「MSXML2.DOMdocument」でxmlを作成するサンプルプログラム

Option Explicit

CONST BASE_URL = "http://192.168.0.1/scripts/cbgrn/grn.exe/"
CONST LOGIN_API_DIR = "util_api/util/api?"
CONST LOGIN_API_NAME = "UtilLogin"
CONST LOGIN_USERNAME = "Administrator"
CONST LOGIN_PASSWORD = "xxxxxxxxxx"

'ログイン処理を実行します。
If GaroonAPI_Login() Then
  msgbox "ログインに成功しました。"
Else
  msgbox "ログインに失敗しました。"
End If


'UtilLoginを使用しガルーンへログインを実施して、その実行結果を返します。
'引数1:無し
'戻り値:真偽 ※ログイン成功:True 失敗:False
Function GaroonAPI_Login()

  Dim objHTTP
  Dim Full_URL
  ReDim Para(1,1)
  Dim objXML
  Dim HeaderElement
  Dim RootElement
  Dim HeaderNode
  Dim BodyNode
  Dim childNode1,childNode2,childNode3,childNode4,childNode5
  Dim grandChildNode1,grandChildNode2,grandChildNode3
  Dim greatGrandchildNode1,greatGrandchildNode2
  Dim elm
  Dim rtnVal
  Dim ReqXML
  
    Full_URL = BASE_URL & LOGIN_API_DIR

    'ログインパラメーター
    Para(0,0) = "login_name"
    Para(0,1) = LOGIN_USERNAME
    Para(1,0) = "password"
    Para(1,1) = LOGIN_PASSWORD


    'XML作成処理開始
    Set ReqXML = CreateObject("MSXML2.DOMdocument")
    ReqXML.async = false

    'XML宣言を作成します。
    Set HeaderElement = ReqXML.createProcessingInstruction("xml","version='1.0' encoding='UTF-8'")
    'ルート要素を作成します。
    Set RootElement = ReqXML.createNode(1,"soap:Envelope","http://www.w3.org/2003/05/soap-envelope")

    ReqXML.appendChild(HeaderElement)
    ReqXML.appendChild(RootElement)

    'ルート直下のヘッダノードの作成します。
    Set HeaderNode = ReqXML.createElement("soap:Header")
    'ルート直下のボディノードを作成します。
    Set BodyNode = ReqXML.createElement("soap:Body")

    '子ノードを作成します。
    Set childNode1 = ReqXML.createElement("Action")
    Set childNode2 = ReqXML.createElement("Security")
    Set childNode3 = ReqXML.createElement("Timestamp")
    Set childNode4 = ReqXML.createElement("Locale")
    Set childNode5 = ReqXML.createElement(LOGIN_API_NAME)

    'ヘッダノードに子ノードを追加します。
    HeaderNode.appendChild(childNode1)
    HeaderNode.appendChild(childNode2)
    HeaderNode.appendChild(childNode3)
    HeaderNode.appendChild(childNode4)
    'ボディノードに子ノードを追加します。
    BodyNode.appendChild(childNode5)

    '子ノードに値を設定します。
    childNode1.appendChild(ReqXML.CreateTextNode(LOGIN_API_NAME))
    childNode2.appendChild(ReqXML.CreateTextNode(""))
    childNode4.appendChild(ReqXML.CreateTextNode("JP"))

    'ヘッダノード配下の孫ノードを作成します。
    Set grandChildNode1 = ReqXML.createElement("Created")
    Set grandChildNode2 = ReqXML.createElement("Expires")
    '孫ノードに値を設定します。
    grandChildNode1.appendChild(ReqXML.CreateTextNode("2010-08-12T14:45:00Z"))
    grandChildNode2.appendChild(ReqXML.CreateTextNode("2037-08-12T14:45:00Z"))

    'ボディノード配下の孫ノードを作成します。
    Set grandChildNode3 = ReqXML.createElement("parameters")

    'ヘッダノード配下の子ノードに孫ノードを追加します。
    childNode3.appendChild(grandChildNode1)
    childNode3.appendChild(grandChildNode2)
    'ボディノード配下の子ノードに孫ノードを追加します。
    childNode5.appendChild(grandChildNode3)

    'ボディノード配下のひ孫ノードを作成します。
    Set greatGrandchildNode1 = ReqXML.createElement(Para(0,0))
    Set greatGrandchildNode2 = ReqXML.createElement(Para(1,0))
    'ひ孫ノードの値を設定します。
    greatGrandchildNode1.appendChild(ReqXML.CreateTextNode(Para(0,1)))
    greatGrandchildNode2.appendChild(ReqXML.CreateTextNode(Para(1,1)))

    '孫ノードにひ孫ノードを追加します。
    grandChildNode3.appendChild(greatGrandchildNode1)
    grandChildNode3.appendChild(greatGrandchildNode2)

    'ドキュメントノードに追加します。
    ReqXML.documentElement.appendChild(HeaderNode)
    ReqXML.documentElement.appendChild(BodyNode)

    'XML作成処理終了

    '作成したリクエストをPOSTします。
    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
    objHTTP.Open "POST", Full_URL, False
    objHTTP.send ReqXML.xml
    
    If objHTTP.Status <> 200 Then
      GaroonAPI_Login = False
      Set objHTTP = Nothing
      Set ReqXML = Nothing
      Exit Function
    End If

    'XML解析用のオブジェクトを生成します。
    Set objXML = CreateObject("MSXML2.DOMdocument")
    'レスポンスをxmlで読み込みます。
    objXML.LoadXML(objHTTP.ResponseText)

    For Each elm In objXML.getElementsByTagName("returns")
      '目的の値を取得します。
      rtnVal = elm.getElementsByTagName("status")(0).text
    Next

    If rtnVal = "Login" Then
      GaroonAPI_Login = True
    Else
      GaroonAPI_Login = False
    End If

    Set objHTTP = Nothing
    Set ReqXML = Nothing
    Set objXML = Nothing
    
End Function

 

上記が「MSXML2.DOMdocument」を使用してリクエストで使用するxmlを生成する例です。
ご覧の通り、可読性は低いです。

次に、リクエスト用のxmlをべた書きした場合のサンプルプログラムも紹介します。

リクエスト用のxmlを文字列としてべた書きして作成するサンプルプログラム

Option Explicit

CONST BASE_URL = "http://192.168.0.1/scripts/cbgrn/grn.exe/"
CONST LOGIN_API_DIR = "util_api/util/api?"
CONST LOGIN_API_NAME = "UtilLogin"
CONST LOGIN_USERNAME = "Administrator"
CONST LOGIN_PASSWORD = "xxxxxxxxxx"


If GaroonAPI_Login Then
  msgbox "ログインに成功しました。"
Else
  msgbox "ログインに失敗しました。"
End If


'UtilLoginを使用しガルーンへログインを実施して、その実行結果を返します。
'引数1:無し
'戻り値:真偽 ※ログイン成功:True 失敗:False
Function GaroonAPI_Login()

  Dim objHTTP
  Dim Full_URL
  ReDim Para(1,1)
  Dim objXML
  Dim sEnv
  Dim elm
  Dim rtnVal

    Full_URL = BASE_URL & LOGIN_API_DIR

    'ログインパラメーター
    Para(0,0) = "login_name"
    Para(0,1) = LOGIN_USERNAME
    Para(1,0) = "password"
    Para(1,1) = LOGIN_PASSWORD

    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")

    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>" & LOGIN_API_NAME & "</Action>"
    sEnv = sEnv & "    <Security></Security>"
    sEnv = sEnv & "    <Timestamp>"
    sEnv = sEnv & "      <Created>2010-08-12T14:45:00Z</Created>"
    sEnv = sEnv & "      <Expires>2037-08-12T14:45:00Z</Expires>"
    sEnv = sEnv & "    </Timestamp>"
    sEnv = sEnv & "    <Locale>jp</Locale>"
    sEnv = sEnv & "  </soap:Header>"
    sEnv = sEnv & "  <soap:Body>"
    sEnv = sEnv & "    <" & LOGIN_API_NAME & ">"
    sEnv = sEnv & "      <parameters>"
    sEnv = sEnv & "        <" & Para(0,0) & ">" & Para(0,1) & "</" & Para(0,0) & ">"
    sEnv = sEnv & "        <" & Para(1,0) & ">" & Para(1,1) & "</" & Para(1,0) & ">"
    sEnv = sEnv & "      </parameters>"
    sEnv = sEnv & "    </" & LOGIN_API_NAME & ">"
    sEnv = sEnv & "  </soap:Body>"
    sEnv = sEnv & "</soap:Envelope>"

    '作成したリクエストをPOSTします。
    objHTTP.Open "POST", Full_URL, False
    objHTTP.send sEnv
    
    If objHTTP.Status <> 200 Then
      GaroonAPI_Login = False
      Set objHTTP = Nothing
      Set ReqXML = Nothing
      Exit Function
    End If

    'XML解析用のオブジェクトを生成します。
    Set objXML = CreateObject("MSXML2.DOMdocument")
    'レスポンスをxmlで読み込みます。
    objXML.LoadXML(objHTTP.ResponseText)

    For Each elm In objXML.getElementsByTagName("returns")
      '目的の値を取得します。
      rtnVal = elm.getElementsByTagName("status")(0).text
    Next

    If rtnVal = "Login" Then
      GaroonAPI_Login = True
    Else
      GaroonAPI_Login = False
    End If

    Set objHTTP = Nothing
    Set objXML = Nothing
    
End Function

如何でしょうか?
上記のコードは洗練とは程遠い泥くさい書き方ではありますが、このようにXMLをべた書きするほうが可読性は高いと思います。

念のため、上記のXMLべた書き側のコードを部分的に補足説明いたします。

4行目

ガルーンのSOAP APIでは、APIの機能の分類によって配置されているURLが異なります。
ログインやログアウトなどのAPIはこのURLを指定して呼び出します。

33行目~36行目

パラメーターを配列に入れていますが、このログインのAPI実行だけで言えば、わざわざ配列化する必要性は無いです。
必要によって普通の変数に書き変えてください。

46行目~47行目

ここはこのAPIを呼び出す際のタイムスタンプを指定します。
上記のコードではガルーンのデベロッパーサイトのリクエスト例と同じ値を指定していますが、本来は適切な値を指定するべきです。
「Created」ではこのAPIを呼び出す際のシステム日時、「Expires」では、有効期限を指定するので、なるべく短い未来の時間を指定したほうが良いです。

82行目

APIがレスポンスとして返してくるXMLを解析し、要素名「status」に”Login”が入っていたらログイン成功としています。

ログアウト用APIを実行するサンプルプログラム

当項では、ガルーンをログアウトするAPIを実行するサンプルプログラムを紹介します。

尚、以降のサンプルプログラムでは、可読性の観点から、XMLベタ書きのコードで進めていきます。

XMLをベタ書きするにあたって、XMLの生成処理を一部関数化します。
特にXMLのヘッダー部分はガルーンの別のSOAP APIでも共通なので、以降のXML生成処理では常に呼び出すようにしていきます。

'リクエストで使用する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>2010-08-12T14:45:00Z</Created>"
    sEnv = sEnv & "      <Expires>2037-08-12T14:45:00Z</Expires>"
    sEnv = sEnv & "    </Timestamp>"
    sEnv = sEnv & "    <Locale>jp</Locale>"
    sEnv = sEnv & "  </soap:Header>"

    Get_CreateXML_Header = sEnv

End Function


'UtilLogoutを使用してガルーンをログアウトしてその実行結果を返します。
'引数1:無し
'戻り値:真偽 ※ログアウト成功:True 失敗:False
Function GaroonAPI_Logout()

  Dim objHTTP
  Dim Full_URL
  Dim sEnv
  Dim ReqXML
  Dim objXML
  Dim retCd
  Dim elm
  Dim rtnVal

    GaroonAPI_Logout = False

    Full_URL = BASE_URL & LOGIN_API_DIR
    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")

    'リクエスト用xml文字列を生成します。※パラメーター無し
    sEnv = sEnv & "  <soap:Body>"
    sEnv = sEnv & "    <UtilLogout>"
    sEnv = sEnv & "    </UtilLogout>"
    sEnv = sEnv & "  </soap:Body>"
    sEnv = sEnv & "</soap:Envelope>"

    ReqXML = Get_CreateXML_Header("UtilLogout") & vbcrlf & sEnv
    'リクエストをPOSTします。
    objHTTP.Open "POST", Full_URL, False
    objHTTP.send ReqXML

    retCd = objHTTP.Status

    If retCd <> 200 Then
      'httpレスポンスコードが異常な場合はFalseを返します。
      Set objHTTP = Nothing
      Set ReqXML = Nothing
      Exit Function
    End If

    'XML解析用のオブジェクトを生成します。
    Set objXML = CreateObject("MSXML2.DOMdocument")
    'レスポンスをxmlで読み込みます。
    objXML.LoadXML(objHTTP.ResponseText)

    For Each elm In objXML.getElementsByTagName("returns")
      '目的の値を取得します。
      rtnVal = elm.getElementsByTagName("status")(0).text
    Next

    If rtnVal = "Logout" Then
      GaroonAPI_Logout = True
    End If

    Set objHTTP = Nothing
    Set ReqXML = Nothing

End Function

 

上記のコードはFunctionプロシージャとして独立しているので、VBSやVBAから適当に呼び出してもらえばそのまま動くと思います。

後編について

今回の記事では、ガルーンのSOAP APIをVBScriptで呼び出す際のサンプルプログラムの紹介と、APIを今後使いこなせるように、基礎的なAPIの知識を紹介しました。

これで、ガルーンに対してウェブの通信を使用したログインとログアウトはできるようになったはずです。

次回の記事では、今回の紹介した処理を応用して、ユーザーアカウントの登録処理に関するサンプルプログラムを紹介していこうと思います。

↓後編はこちらのリンクから

今回も長々と読んでいただきましてありがとうございました。
また次回もよろしくお願いいたします。

タイトルとURLをコピーしました