スポンサーリンク

【pleasanter/VBA】エクスポート⑩汎用ツール完全版

プリザンター
スポンサーリンク
※当サイトは広告を含みます

エクセルVBAでプリザンターから情報取得、シリーズ。第10回です。今回でこのシリーズは終わりです。

前回、vbaでエクスポートの汎用ツールを作成しました。今回は、その増強版を作成してみました。
何が違うかというと、
・offset処理を追加(ページサイズ以上のデータも大丈夫)
・日付項目に限り、取得条件を設定できるようにした(1項目のみ設定可。省略も可)
・ワークシートへの書き出しのスピードアップのため配列を利用
・分類項目などのサフィックスがA~Z以外も対応可(試すことができないので、多分)

1.コード

いきなりですが、コードです。へなちょこテストサイトでしか試していないので、変なところあったらごめんなさいですが、責任はとれませんので、ご了承ください。。。
ご指摘ありましたら、コメントにて教えていただけたらと思います。
※のホスト名のところは環境に合わせて設定してください。
※jsonConverterを利用しています。詳しくはこちらの記事等を参照してください。
https://vba-labo.rs-techdev.com/archives/1401
※分類項目等はA~Zまでしか対応していません。
※Microsoft Scripting Runtime を参照設定しています。

'参照設定:Microsoft Scripting Runtime

Type columnname
    koumoku As String
    suffix As String
End Type

Sub pleasanter_export_hanyou2()
    On Error GoTo ErrHandler
    Dim msg As String
    Application.ScreenUpdating = False
    
    '++++++++++++++++++++++++++++++++++++++++++++
    '    基本情報設定
    '++++++++++++++++++++++++++++++++++++++++++++
    'プリザンター情報
    'ホスト名※
    Const serverName As String = "http://localhost/api/items/"
    
    'コマンドシート
    Dim wsCom As Worksheet
    Const RowStartKoumoku As Long = 6           '取得項目入力開始行
    Const ColKoumoku As Long = 2                '項目名の列
    Const ColSuffix As Long = 3                 'サフィックスの列
    Const StrRngDateKoumoku As String = "G6"    '日付条件項目名のセル位置
    Const StrRngDateSatrt As String = "G7"      '日付条件 開始日 のセル位置
    Const StrRngDateEnd As String = "G8"        '日付条件 終了日 のセル位置
    Set wsCom = Worksheets("コマンド")
    
    '出力シート
    Dim wsExport As Worksheet
    Const RowStartE As Long = 2         '出力開始行
    Set wsExport = Worksheets("出力")
    
    '++++++++++++++++++++++++++++++++++++++++++++
    '   コマンドシートから取得条件を取得
    '++++++++++++++++++++++++++++++++++++++++++++
    Dim myApikey As String, siteId As String
    With wsCom
        myApikey = Trim(.Range("C2").Value) 'APIキー
        siteId = Trim(.Range("C3").Value)   'サイトID
    End With
    
    '値のチェック
    If myApikey = "" Then
        msg = "APIキーを入力してください" & vbCrLf & "処理を中断します"
        GoTo ErrHandler
    ElseIf Not IsNumeric(siteId) Or siteId = "" Then
        msg = "サイトIDが正しくありません" & vbCrLf & "処理を中断します"
        GoTo ErrHandler
    End If
    
    '出力項目を配列colNamesに代入
    Dim colNames() As columnname     '項目名を入れる配列
    Dim i As Long, rowEnd As Long
    Dim idx As Long: idx = 1
    With wsCom
        rowEnd = .Cells(.Rows.Count, ColKoumoku).End(xlUp).Row
        If rowEnd < RowStartKoumoku Then
            msg = "出力項目を指定してください"
            GoTo ErrHandler
        End If
        For i = RowStartKoumoku To rowEnd
            If .Cells(i, ColKoumoku).Value <> "" Then
                ReDim Preserve colNames(1 To idx)
                colNames(idx).koumoku = .Cells(i, ColKoumoku).Value
                colNames(idx).suffix = .Cells(i, ColSuffix).Value
                idx = idx + 1
            End If
        Next i
    End With
    
    '日付条件作成
    Dim joukenDateKoumoku As String, strDate As String
    With wsCom
        '条件指定日付項目に項目名がセットされている場合のみ日付条件作成
        If .Range(StrRngDateKoumoku).Value <> "" Then
            '条件の日付項目
            joukenDateKoumoku = .Range(StrRngDateKoumoku).Value
            '日付条件文字列作成
            strDate = getDateJouken(.Range(StrRngDateSatrt).Value, .Range(StrRngDateEnd).Value)
        End If
    End With
    
    '++++++++++++++++++++++++++++++++++++++++++++
    '    前処理
    '++++++++++++++++++++++++++++++++++++++++++++
    '出力シートクリア,項目名出力
    wsExport.Cells.Clear
    With wsExport
        '項目名出力
        For idx = LBound(colNames) To UBound(colNames)
            .Cells(1, idx).Value = colNames(idx).koumoku & colNames(idx).suffix
        Next idx
    End With
    Dim printRow As Long: printRow = RowStartE

    '++++++++++++++++++++++++++++++++++++++++++++
    '   プリザンターから情報取得
    '++++++++++++++++++++++++++++++++++++++++++++
    Dim arrData() As Variant            '取得データ一時格納用配列
    
    Dim jsonRequest     As Dictionary
    Dim parseResponse   As Dictionary
    Dim httpRequest     As Object
    
    Dim offsetCnt As Long: offsetCnt = 0
    Dim endFlg As Boolean: endFlg = False
    
    Do Until endFlg = True
    
        Set jsonRequest = New Dictionary
        
        jsonRequest.Add "ApiVersion", "1.1"
        jsonRequest.Add "ApiKey", myApikey
        jsonRequest.Add "Offset", offsetCnt
        
        '日付条件がある場合のみフィルタ作成
        If strDate <> "" Then
            jsonRequest.Add "View", New Dictionary
            jsonRequest("View").Add "ColumnFilterHash", New Dictionary
            jsonRequest("View")("ColumnFilterHash").Add joukenDateKoumoku, strDate
        End If
        
        Set httpRequest = CreateObject("msxml2.xmlhttp")
        
        httpRequest.Open "POST", serverName & siteId & "/get"
        httpRequest.setRequestHeader "Content-Type", "application/json;charset=utf-8"
        
        httpRequest.send JsonConverter.ConvertToJson(jsonRequest)
        
        Do While httpRequest.readyState < 4
            DoEvents
        Loop
    
        Set parseResponse = JsonConverter.ParseJson(httpRequest.responseText)
        
        If parseResponse("Response")("Data").Count <= 0 Then
            MsgBox "出力データがありません" & vbCrLf & "処理を中断します"
            Exit Sub
        End If
        
        If offsetCnt + parseResponse("Response")("PageSize") >= parseResponse("Response")("TotalCount") Then
            endFlg = True
        Else
            offsetCnt = offsetCnt + parseResponse("Response")("PageSize")
        End If
        
        Dim responseData As Variant
        Dim idxRow As Long, idxCol As Long
        idxRow = 1
        
        'データ蓄積=>arrData
        ReDim arrData(1 To parseResponse("Response")("PageSize"), 1 To UBound(colNames))
        
        For Each responseData In parseResponse("Response")("Data")
            For idxCol = LBound(colNames) To UBound(colNames)
                
                With colNames(idxCol)
                    If .koumoku = "Class" Or .koumoku = "Num" Or .koumoku = "Check" Or .koumoku = "Description" Then
                        'クラス、数値等アルファベットが最後につく項目の処理
                        arrData(idxRow, idxCol) = responseData(.koumoku & "Hash")(.koumoku & .suffix)
                            
                    ElseIf .koumoku = "Date" Then
                        '日付の場合の処理。文字列日付をシリアル値に変換する
                        arrData(idxRow, idxCol) = strDateToDateTime(responseData("DateHash")("Date" & .suffix))
                        
                    ElseIf InStr(.koumoku, "Time") > 0 Then
                        'Date以外の日付の場合の処理。文字列日付をシリアル値に変換する
                        arrData(idxRow, idxCol) = strDateToDateTime(responseData(.koumoku & .suffix))
                        
                    Else
                        'クラス、数値等アルファベットが最後につく項目以外の処理
                        arrData(idxRow, idxCol) = responseData(.koumoku & .suffix)
                        
                    End If
                End With
            Next idxCol
            idxRow = idxRow + 1
        Next
        
        'シートに出力
        With wsExport
            .Cells(printRow, 1).Resize(UBound(arrData), UBound(arrData, 2)).Value = arrData
        End With
        printRow = printRow + parseResponse("Response")("PageSize")
        
        Set jsonRequest = Nothing
        Set httpRequest = Nothing
        Set parseResponse = Nothing
        
    Loop
    
    Application.ScreenUpdating = True
    MsgBox "出力完了"
    wsExport.Activate
    Exit Sub
ErrHandler:
    If msg <> "" Then
        MsgBox msg
    Else
        MsgBox "エラーが発生しました" & vbCrLf & "処理を中断します" & _
                "エラー№" & Err.Number & ":" & Err.Description
    End If
    Application.ScreenUpdating = True
End Sub

Private Function strDateToDateTime(ByVal str As String) As Variant
    '日付時刻
    If Val(Left(str, 4)) < 1900 Then
        strDateToDateTime = ""
    Else
        strDateToDateTime = CDate(Replace(str, "T", " "))
    End If
End Function

Private Function getDateJouken(ByVal date1 As Variant, ByVal date2 As Variant) As String
    
    Dim dateStart As String, dateEnd As String
    Dim dateStartflg As Boolean, dateEndflg As Boolean
    
    '開始日
    If date1 <> "" and IsDate(date1) Then
        dateStart = Format(date1, "yyyy/mm/dd")
        dateStartflg = True
    End If
    '終了日
    If date2 <> "" and IsDate(date2) Then
        dateEnd = Format(date2, "yyyy/mm/dd")
        dateEndflg = True
    End If
    
    '日付条件文字列作成
    Dim strDate As String
    If dateStartflg = True And dateEndflg = True Then
        strDate = "[""" & dateStart & " 00:00:00," & dateEnd & " 23:59:59""]"
    ElseIf dateStartflg = True Then
        strDate = "[""" & dateStart & " 00:00:00,""]"
    ElseIf dateEndflg = True Then
        strDate = "[""," & dateEnd & " 23:59:59""]"
    End If
    
    getDateJouken = strDate
    
End Function

2.エクセルの仕様

Excelのコマンドシートのイメージです。

「出力項目」「サフィックス」「条件指定日付項目」は入力規則でリストから選択するようにしています。別シートにリストの内容を用意しています。

※2023.9.16追記。出力項目リストにOwnerが3行目と8行目でダブっています。どちらか一つだけで大丈夫です。ごめんなさい。

最近覚えたのですが、リストの参照範囲にしたいセル範囲に名前を定義しておいて、入力規則で定義した名前を使用して参照範囲を設定する方法は便利ですね。

ちなみにサフィックスの部分は非表示にしているD列にClass,Num,Date,Description,Checkの場合「サフィックス」と表示させ、INDIREDT関数と組み合わせてClass,Num,Date,Description,Checkが入力された場合のみ、A~Zのプルダウンを表示するようにしています。
そこまでしなくても Title A 等と指定しても、サフィックスは無視される仕様なのでそんなことしなくてもいいのですが。

はい、本題からそれましたね。

なお、日付条件の指定の個所は、日付が入力されるように入力規則で制限しています。
開始日だけを指定したいときは終了日は空欄で開始日のみ入力、終了日だけを指定したいときは開始日は空欄で終了日のみ入力すればOKです。
日付条件を設定しない場合は、すべて空欄でOKです。

3.最後に

前回のコードから改善していますが、わかりやすくしようとして、わかりにくくしている私の悪い癖がさく裂している感があります。解説もなく、すみません。

タイトルで完全版と大ぶろしきを広げてしまいましたが、何をもって完全版と言い切るか?と言われると微妙ですね。ごめんなさい。

4.参考とさせていただいた記事

【EXCEL VBA】VBAでJSONを利用したい
https://vba-labo.rs-techdev.com/archives/1401

PleasanterとExcelを接続してみた-応用編
https://qiita.com/m-isik/items/0abfd51a22587bed2e47

ありがとうございます!大変勉強になりました。

5.プリザンザンターVBAエクスポートシリーズ リンク

プリザンザンターVBAエクスポートシリーズ
【pleasanter/VBA】エクセルからプリザンターのデータを取得する
【pleasanter/VBA】エクセルからプリザンターのデータを取得する②絞り込み条件の指定
【pleasanter/VBA】エクセルからプリザンターのデータを取得する③変数で絞り込み条件を指定する
【pleasanter/VBA】エクスポート④絞り込み条件で〇〇を含むを指定する
【pleasanter/VBA】エクスポート⑤並べ替え
【pleasanter/VBA】エクスポート⑥表示名を出したい
【pleasanter/VBA】エクスポート⑦データがちょん切れる時の対応 Offset
【pleasanter/VBA】エクスポート⑧出力される日付を文字列ではなく日付時刻型で出したい
【pleasanter/VBA】エクスポート⑨汎用ツールを作ってみた
【pleasanter/VBA】エクスポート⑩汎用ツール完全版(今回)

VBAでインポート
【pleasanter/VBA】エクセルからプリザンターへデータを追加、更新する~import~

プリザンターPowerQuery連携シリーズ
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する①
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する②取得条件の指定方法
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する③上限値以上のレコードを連続で取得する
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する④ユーザーテーブルとマージ

コメント

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