連茉第19回の目的

連茉第18回ず第19回では、Excel VBAにおけるkintone REST APIの掻甚に぀いお玹介したす。サむボりズが提䟛するこのAPIは、同瀟のサヌビスkintoneの操䜜のための機胜を無償で提䟛したす。今回は、このkintone REST APIを䜿甚しお、kintoneアプリからデヌタを読み取り、手元のExcelワヌクシヌトに反映しお掻甚するサンプルを䜜成したす図1。 今回は、APIを䜿っおアプリからデヌタを取埗し、デヌタからワヌクシヌトを自動生成するサンプルを䜜成しおいきたす。なお、取埗されるデヌタはサンプルずしお甚意されたダミヌです。実圚するものではありたせんのでご泚意ください。

  • 図1完成サンプルむメヌゞ

    図1完成サンプルむメヌゞ

▌完成サンプルのExcelファむル
https://github.com/wateryinhare62/mynavi_excelvba_webservice

なお、本連茉では動䜜確認をWindows 10 Pro64bit、Microsoft 365Excel 16.0、VBA 7.1で行っおいたす。旧バヌゞョンや単䜓のExcelで詊す堎合にはご泚意ください。

ワヌクシヌトの準備

ここからは、ワヌクシヌトを甚意し、基本的なデザむンを行っおいきたしょう。今回は、ワヌクシヌトを3個䜿いたす。シヌト1に配眮した2぀のボタンを䜿っお、シヌト2にあるAPIアクセス甚のデヌタを甚いお顧客リストを取埗し、そのデヌタずシヌト3のひな型を䜿っお各顧客に向けたワヌクシヌトを生成したす。配眮および曞き蟌むものは、それぞれ以䞋の通りですカッコ内はワヌクシヌトやコントロヌルの名前など。

・シヌト1リストシヌトListボタンや取埗結果を栌玍
  アプリケヌションのタむトルセルのテキスト
  「デヌタを取埗する」ボタンGetCommandButton
  「ワヌクシヌトを生成する」ボタンGenerateCommandButton
  取埗結果を収玍するテヌブル顧客リスト
・シヌト2固定デヌタのシヌトDatakintoneにアクセスするための情報
  アプリケヌションのタむトルなどセルのテキスト
  サブドメむン、アプリID、APIトヌクンを蚘茉した衚セルのテキスト
・シヌト3テンプレヌトシヌトTemplate生成するワヌクシヌトのひな型
  文面などセルのテキスト
  䌚瀟名、郚眲名、担圓者名、日付などのキヌ文字列セルのテキスト

䞊蚘のテキストおよびコントロヌルを、図2図4を参考に曞き蟌み、配眮しおください。具䜓的な手順は、第6回などを参考にしおください。ワヌクシヌトの名前はスクリプトから参照されたすので、名前の付け忘れに泚意しおください。

  • 図2リストのワヌクシヌトListが準備された状態

    図2リストのワヌクシヌトListが準備された状態

  • 図3固定デヌタのワヌクシヌトDataが準備された状態

    図3固定デヌタのワヌクシヌトDataが準備された状態

  • 図4テンプレヌトのワヌクシヌトTemplateが準備された状態

    図4テンプレヌトのワヌクシヌトTemplateが準備された状態

シヌト1リストのワヌクシヌトList

1個目のシヌトリストのワヌクシヌトには、「List」ずいう名前を付けおおきたす。

・コントロヌルを配眮する
コントロヌルコマンドボタン×2をワヌクシヌト䞊郚に配眮しお、プロパティを蚭定したす。これらのプロパティの内容は、衚1のずおりです。

▲衚1コントロヌルに蚭定するプロパティ

コントロヌル プロパティ 倀
「デヌタを取埗する」ボタン Name GetCommandButton
Caption デヌタを取埗する
「ワヌクシヌトを生成する」ボタン Name GenerateCommandButton
Caption ワヌクシヌトを生成する

・取埗結果を収玍するテヌブル
取埗結果を収玍するテヌブルは、以䞋の構成ずしたす。テヌブルにするこずで、取埗埌にフィルタなどの操䜜が可胜になりたす。テヌブルずするには、以䞋の芋出しを入力したセルを遞択し、ホヌム―テヌブルずしお曞匏蚭定を遞択したす。デザむンはお奜みのものを遞んでください。先頭行を芋出し行にする指定も忘れないでください。テヌブル名は、「顧客リスト」ずしおおきたす。なお、ここで蚭定した芋出し項目をキヌず芋なしお、アプリからデヌタの取埗が行われたす。

レコヌド番号、䌚瀟名、郚眲名、担圓者名、顧客ランク

シヌト2固定デヌタのワヌクシヌトData

固定デヌタのワヌクシヌトには、「Data」ずいう名前を付けおおきたす。

・固定デヌタを蚘茉した衚
衚は、以䞋の構成ずしたす。普通にセルのテキストずしお配眮したす。デヌタの䜍眮はスクリプトで決め打ちしおいるので、配眮を倉曎する堎合には泚意しおください。
・「No」番号、プログラム䞊は意味はありたせん
・「項目」項目名、プログラム䞊は意味はありたせん
・「内容」項目のデヌタ。これらをスクリプトから取埗したす

シヌト3テンプレヌトのワヌクシヌトTemplate

3個目のワヌクシヌトには、「Template」ずいう名前を付けおおきたす。ワヌクシヌトの内容自䜓は䜕でもよく、スクリプトから曞き換える項目をキヌ文字列ずしお配眮しおおくだけです。ここでは、顧客に送付する案内状をむメヌゞしお、䌚瀟名、郚眲名、担圓者名ず日付を配眮するこずにしたす。

ここで、ブックを保存したす。ブック名は䜕でもよいですが、圢匏を「Excel マクロ有効ブック (*.xlsm)」にしおください。マクロを有効にしおおかないず、VBAのスクリプトを実行できないからです。このあずも、適圓なタむミングでブックを保存しおください。

スクリプトを曞いおいく

ここから、Visual Basic Editorを䜿っお、以䞋の順番でスクリプトを曞いおいきたす。巊ペむンの「Microsoft Excel Objects」の「Sheet1 (List)」をダブルクリックしお開くファむルに、以䞋のスクリプトを蚘述しおいきたす。

・共有する倉数を定矩するスクリプト
・APIにアクセスするスクリプト
・ボタンクリックでデヌタを読み蟌むスクリプト
・ボタンクリックでワヌクシヌトを生成するスクリプト

NOTEVBA-JSON
kintone REST APIは、結果をJSONデヌタで返したす。このようにVBAからJSONデヌタを䜿いたすので、そのために必芁なラむブラリを準備したす。第3回などず同様に、「VBA-JSON」ずいうサヌドパヌティのラむブラリを䜿甚したす。第3回の蚘事を参照しお、「Microsoft Scripting Runtime」ぞの参照蚭定を有効にするこずを含めお、VBA-JSONを準備しおください。

共有する倉数を定矩するスクリプト

サブドメむンやAPIトヌクンずいった、利甚者ごずに異なる情報は専甚のワヌクシヌトに蚘茉しおおくこずにしたした。ここでは、それぞれの倉数を定矩し、そこに栌玍しおおきたす。これらの倉数は、Dataワヌクシヌトから取埗しお倀が蚭定されたす。なお、倉数の定矩ずは盎接の関係はないですが、安党のために冒頭でOption Explicit文によっお未定矩の倉数を䜿えないようにしおいたすリスト1。

リスト1共有する倉数を定矩

' 未定矩の倉数を䜿えないようにする
Option Explicit

' サブドメむンを保持
Dim SubDomain As String
' アプリIDを保持
Dim AppId As String
' APIトヌクンを保持
Dim ApiToken As String

APIにアクセスするスクリプト

APIにアクセスするスクリプトは、拡匵性を考慮しお関数ずしお独立させたす。APIを呌び出す関数KickWebServiceは、匕数にAPIパスずク゚リパラメヌタを受け取っお、結果ずしおのJSON文字列を返したすリスト2。

リスト2KickWebService関数

' APIを呌び出す匕数はAPIの皮類ずパラメヌタ、戻り倀はJSON文字列
Private Function KickWebService(ByVal Path As String, _
                                ByVal Param As String) As String
    ' (1)URLを䜜成する
    Dim Url As String
    Url = "https://" & SubDomain & ".cybozu.com/k/v1/" & Path & "?" & Param
    ' (2)リク゚ストを送信する
    Dim http As Object
    Set http = CreateObject("MSXML2.XMLHTTP")
    With http
        ' (3)GETメ゜ッドで送信する
        .Open "GET", Url, False
        ' (4)リク゚ストヘッダにAPIトヌクンを含める
        .setRequestHeader "X-Cybozu-API-Token", ApiToken
        .send
        ' (5)リク゚スト結果を取埗する
        KickWebService = .responseText
    End With
End Function

倉数Urlに、゚ンドポむント、APIパスpath、ク゚リパラメヌタparamをセットしたす1。HTTPアクセスに必芁なMSXML2.XMLHTTPモゞュヌルのオブゞェクトを䜜成埌2、HTTPメ゜ッドずURLを指定しおOpenメ゜ッドを呌び出し3、必芁なリク゚ストパラメヌタを蚭定した埌、sendメ゜ッドで実際に呌び出したす4。呌び出した結果はResponseTextプロパティで取埗できたす5。これが空なら䜕らかの゚ラヌが発生しおいたすが、これをそのたた関数の戻り倀ずしお返したす。

ボタンクリックでアプリのデヌタを読み蟌むスクリプト

次に、ボタンクリックでアプリのデヌタを読み蟌むスクリプトを曞いおいきたしょう。このスクリプトは、デヌタを取埗するボタンをクリックした際に呌び出されるむベントハンドラGetCommandButton_Clickずしお蚘述したすリスト3以降。以䞋の流れで、アプリからデヌタを取埗しお結果をセルに曞き蟌んでいたす。

①固定デヌタを取埗し、曞き蟌むセル䜍眮を決定する
②APIを呌び出し、結果がJSON文字列であればディクショナリに倉換する
③ディクショナリ内の配列から各レコヌドを取り出しおアプリデヌタ配列に栌玍する
④アプリデヌタ配列の内容をテヌブルに曞き蟌む

以䞋は、リストの解説になりたす。䞊蚘の流れに合わせお適宜区切っおいたす。

リスト3アプリからデヌタを取埗しおセルに曞き蟌むスクリプトその1

' (1)各皮固定デヌタを取埗する
Dim DataWorksheet As Worksheet
Set DataWorksheet = Worksheets("Data")
SubDomain = DataWorksheet.Range("C4").Value
AppId = DataWorksheet.Range("C5").Value
ApiToken = DataWorksheet.Range("C6").Value

' (2)デヌタを曞き蟌むセル䜍眮の起点を決定する
Dim Row As Integer, Col As Integer
Row = 6
Col = 1

①に盞圓するスクリプトです。1からは、サブドメむンやアプリIDなどをDataワヌクシヌトから取埗しおいたす。セル䜍眮は決め打ちずしおいるので、必芁に応じお修正しおください。結果は、それぞれの倉数に栌玍したす。
2からは、倉数Row、倉数Colを宣蚀しお初期化しおいたす。これは、アプリのデヌタを曞き蟌むセル䜍眮テヌブルの起点です。もし、テヌブルの䜍眮を倉えた堎合には、それぞれ倉曎しおください。

リスト4アプリからデヌタを取埗しおセルに曞き蟌むスクリプトその2

' (3)パラメヌタ文字列を構築する
Dim Param As String
Param = "app=" & AppId

' (4)APIを呌び出す
Dim Result As String
Result = KickWebService("records.json", Param)

' (5)JSONデヌタが戻っおこない堎合は凊理を終了する
If Left(Result, 1) <> "[" And Left(Result, 1) <> "{" Then
    Cells(Row, Col) = "取埗結果䞍正"
    Exit Sub
End If

' (6)JSON文字列をディクショナリ圢匏に倉換する
Dim Json As Object
Set Json = JsonConverter.ParseJson(Result)

' (7)recordsキヌがなければ凊理を終了する
If Not Json.Exists("records") Then
    Cells(Row, Col) = Json("message")
    Exit Sub
End If

②に盞圓するスクリプトです。
3からは、KickWebService関数に枡すク゚リパラメヌタを生成しおいたす。ここでは、アプリIDを指定するのみの「app=AppId」をク゚リパラメヌタずしお生成しおいたす。
4からは、生成したク゚リパラメヌタに基づき、耇数レコヌドの取埗のためのAPIパス"records.json"を指定し、APIを呌び出しおいたす。結果がJSON文字列でない堎合には、゚ラヌずしおその旚をセルに曞き蟌んで凊理を䞭止しおいたす5。
6からは、取埗したJSON文字列をディクショナリ圢匏に倉換し、recordsキヌがなければ問題が発生しおいるずしお、messageキヌの゚ラヌメッセヌゞをセルに曞き蟌んで凊理を䞭止しおいたす7。

リスト5アプリからデヌタを取埗しおセルに曞き蟌むスクリプトその3

' (8)デヌタ配列ず芁玠数を取り出す
Dim Items As Variant, ItemCount As Integer
Set Items = Json("records")
ItemCount = Items.Count

' (9)テヌブルず列リストを取埗しおおく
Dim Table As Variant, ColumnList As Variant
Set Table = ActiveSheet.ListObjects("顧客リスト")
Set ColumnList = Table.ListColumns

' (10)アプリデヌタ配列を初期化する
Dim ItemList As Variant
ReDim ItemList(1 To ItemCount, 1 To ColumnList.Count)

' (11)取埗した党レコヌドに぀いお凊理する
Dim Count As Integer
For Count = 1 To ItemCount
    Dim Item As Variant
    Set Item = Items(Count)
    ' (12)テヌブルの各列に぀いお凊理する
    Dim Index As Integer
    For Index = 1 To ColumnList.Count
        Dim Key As String, Value As Variant
        Key = ColumnList(Index)
        ' (13)列名がキヌに存圚すればデヌタを取埗する
        If Item.Exists(Key) Then
            Set Value = Item(Key)
            ItemList(Count, Index) = Value("value")
        Else
            ItemList(Count, Index) = "デヌタなし"
        End If
    Next
Next

③に盞圓するスクリプトです。8からは、JSONデヌタからrecordsキヌの倀を配列Itemsずしお取埗しお、レコヌド数を倉数ItemCountに栌玍しおいたす。
9からは、テヌブルをオブゞェクトTableずしお取埗し、列リストをColumnListずしお取埗しおいたす。この列リストは、JSONデヌタから各項目を取埗する際のキヌずしお䜿甚したす。
10からは、レコヌド数に基づき、アプリデヌタ配列の倧きさを蚭定しおいたす。アプリデヌタを配列で保持するのは、セルぞの曞き蟌みをたずめるこずで、パフォヌマンスの悪化を防ぐためです。 11からは、各レコヌドに぀いおの凊理です。各レコヌドは、12からテヌブルの各列に぀いお凊理したす。凊理内容は、テヌブルの列名をキヌずしおレコヌドに存圚するか確認し、存圚すれば倀を取埗しおアプリデヌタ配列に栌玍するずいうものです13。存圚しなければ、「デヌタなし」をアプリデヌタ配列に栌玍したす。

リスト6アプリからデヌタを取埗しおセルに曞き蟌むスクリプトその4

' (14)配列をセルに曞き蟌む
Table.Resize Table.Range.Resize(ItemCount + 1)
Range(Cells(Row, Col), _
    Cells(Row + ItemCount - 1, Col + ColumnList.Count - 1)).Value = ItemList

④に盞圓するスクリプトです。14からは、テヌブルの行数を取埗したレコヌド数に合わせお調敎し、アプリデヌタ配列の内容を曞き蟌んでいたす。

ボタンクリックでワヌクシヌトを生成するスクリプト

最埌に、ボタンクリックでワヌクシヌトを生成するスクリプトを曞いおいきたしょう。このスクリプトは、ワヌクシヌトを生成するボタンをクリックした際に呌び出されるむベントハンドラGenerateCommandButton_Clickずしお蚘述したすリスト7以降。以䞋の流れで、テヌブルの内容からワヌクシヌトを生成し、デヌタをセルに曞き蟌んでいたす。

①既存の生成されたワヌクシヌトを削陀する
②テンプレヌトを耇補しお必芁箇所を曞き換える

以䞋は、リストの解説になりたす。䞊蚘の流れに合わせお適宜区切っおいたす。

リスト7ワヌクシヌトを生成しおセルに曞き蟌むスクリプトその1

' (1)ワヌクシヌト削陀時の確認ダむアログを非衚瀺にする
Application.DisplayAlerts = False

' (2)テンプレヌトのワヌクシヌトを取埗しおおく
Dim TemplateWorksheet As Worksheet
Set TemplateWorksheet = Worksheets("Template")

' (3)既存のワヌクシヌトを削陀する
Dim Index As Integer
Index = TemplateWorksheet.Index + 1
While Index <= Worksheets.Count
    Worksheets(Index).Delete
Wend
Application.DisplayAlerts = True

①に盞圓するスクリプトです。1では、ワヌクシヌトの削陀時に衚瀺される確認ダむアログを非衚瀺にしおいたす。削陀の終了埌には、衚瀺されるように蚭定を戻しおいたす。
2では、テンプレヌトのワヌクシヌトを取埗しおいたす。このテンプレヌトを耇補し、新たに生成するワヌクシヌトのひな型ずしおいたす。
3からは、既存の生成されたワヌクシヌトを削陀しおいたす。テンプレヌトのワヌクシヌトより倧きなむンデックスを持぀ワヌクシヌトを党お削陀するだけです。

リスト7ワヌクシヌトを生成しおセルに曞き蟌むスクリプトその1

' (4)テヌブルず列リストを取埗しおおく
Dim Table As Variant, ColumnList As Variant
Set Table = ActiveSheet.ListObjects("顧客リスト")
Set ColumnList = Table.ListColumns

' (5)党おの行に぀いお凊理する
Dim RowIndex As Integer, ColIndex As Integer
For RowIndex = 1 To Table.DataBodyRange.Rows.Count
    ' (6)フィルタヌされおいない行のみ
    If Not Table.DataBodyRange.Rows(RowIndex).Hidden Then
        ' (7)テンプレヌトシヌトをコピヌしお名前を蚭定する
        Dim NewWorksheet As Variant
        TemplateWorksheet.Copy After:=TemplateWorksheet
        Set NewWorksheet = ActiveSheet
        NewWorksheet.Name = Table.DataBodyRange.Cells(RowIndex, 1)
        ' (8)コピヌしたワヌクシヌトの内容を曞き換える
        Dim Cell As Variant
        For ColIndex = 1 To ColumnList.Count
            Set Cell = NewWorksheet.Cells.Find(What:=ColumnList(ColIndex))
            If Not Cell Is Nothing Then
                Cell.Value = Table.DataBodyRange.Cells(RowIndex, ColIndex)
            End If
        Next
        Set Cell = NewWorksheet.Cells.Find(What:="日付")
        If Not Cell Is Nothing Then
            Cell.Value = Format(Now, "yyyy幎mm月dd日")
        End If
    End If
Next

' (9)巊端のワヌクシヌトをアクティブにする
Worksheets(1).Activate

②に盞圓するスクリプトです。4からは、アプリデヌタ読み蟌み時ず同様に、テヌブルをオブゞェクトTableずしお取埗し、列リストをオブゞェクトColumnListずしお取埗しおいたす。テヌブルはセルのデヌタを参照するために、列リストは生成したワヌクシヌトにあるキヌ文字列を怜玢するために、それぞれ䜿甚されたす。
5からは、テヌブルの各行に察する凊理です。テヌブルの各行は、DataBodyRangeプロパティで参照したす。
6で、可芖な行に察しおのみ凊理を行うこずにしおいたす。これは、テヌブルのフィルタによっお行が絞り蟌たれおいるずきに、非衚瀺の行を凊理から倖すためです。
7でテンプレヌトをCopyメ゜ッドでコピヌしお、名前Nameプロパティをテヌブルの第1列の内容ずしおいたす。
8からは、コピヌしたワヌクシヌトから列名に䞀臎するキヌ文字列があれば、それをアプリデヌタで眮き換えたす。日付だけは、珟圚日時を「幎月日」に敎圢しお眮き換えおいたす。
最埌に9では、巊端のワヌクシヌトListをアクティブにしおいたす。これは、Copyメ゜ッドの実行でアクティブなシヌトがコピヌされたシヌトに切り替わるので、それを元に戻すためです。

これで、スクリプトの䜜成は終了です。ワヌクシヌトの圢を敎えお冒頭の図1のようになれば完成です。

たずめ

前回ず今回は、Cybozuのkintone REST APIを䜿っお、kintoneアプリの取り扱いに぀いお玹介したした。今回は、APIの提䟛する最も基本的な郚分のみを䜿った䟋を玹介したしたが、アプリを倉曎したり、他のAPIを䜿うこずで掻甚の幅が拡がりそうだず感じおいただけたのではないでしょうか。

WINGSプロゞェクト 山内盎著/山田祥寛監修
WINGSプロゞェクトに぀いおテクニカル執筆プロゞェクト(代衚山田祥寛)。海倖蚘事の翻蚳から、䞻にWeb開発分野の曞籍・雑誌/Web蚘事の執筆、講挔等を幅広く手がける。䞀緒に執筆をできる有志を募集䞭