※おことわり
2024年2月時点の情報です。プリザンターのバージョンは 1.3.50.2 です。Google Chrome でやっています。
javascript,html,cssともに初心者です。調べながら、やってみながら、きっとこうすればいいんだ!という感じで書いていますので、間違っている場合、効率的な書き方ではない可能性が大いにあります。間違ってるよ!とか、こうしたほうがいいよ!ということがありましたら、コメント等で教えていただけると大変ありがたいです。
以前、vbaでプリザンターからデータを取得してエクセルに出力する、というのをシリーズものにしてしつこくやりました。
今回は、vbaでエクセルからプリザンターへデータを追加する、更新する、つまりインポートの動きをやってみたいと思います。
おもに、こちらのサイトで勉強させていただきました。ありがとうございました。
https://qiita.com/m-isik/items/0abfd51a22587bed2e47
1.エクセルVBA to プリザンター エクスポート、インポートの相違点とポイント
HTTPリクエストを送る部分(※)
IXMLHTTPRequestオブジェクト.Open メソッド, URL
ここの違いを押さえればあとはだいたい同じ。
(サーバー名は実際の環境のサーバー名を入れる。サイトID、レコードIDは実際のIDを入れる)
エクスポート
IXMLHTTPRequestオブジェクト.Open “POST”, “http://サーバー名/api/items/サイトID/get“
インポート(新規レコード追加)
IXMLHTTPRequestオブジェクト.Open “POST”, “http://サーバー名/api/items/サイトID/create“
インポート(既存レコード更新)
IXMLHTTPRequestオブジェクト.Open “POST”, “http://サーバー名/api/items/レコードID/update“
おしりがgetかcreateかupdateかの違い。エクスポートと追加はサイトID、既存レコードの更新はレコードIDを指定する。
※本当に送るのはSendの部分だけど送るといったほうがわかりやすいので、とりあえず「送る」で。HTTPリクエストについてはこちらのサイトで勉強させていただきました。わかりやすいです。
https://tonari-it.com/excel-vba-http-request/
公式サイトのapiの記載をみてみると、これを利用しているのかと、おぼろげながらわかってきました。
開発者向け機能:API:テーブル操作:複数レコード取得
開発者向け機能:API:テーブル操作:レコード作成
開発者向け機能:API:テーブル操作:レコード更新
2.VBAの前提条件
①VBAJSONをインポートしておく。
https://github.com/VBA-tools/VBA-JSON
②Microsoft Scripting Runtime を参照設定しておく
3.インポート:レコード作成(追加)
(1)エクセルシート
下図のエクセルシート(シート名import)から値を取得してプリザンターへ送信します。
(2)VBAコード
Sub importToPleasanter()
Dim ws As Worksheet
Set ws = Worksheets("import")
'更新情報(実際の環境に合わせてください)
Const saver As String = "localhost"
Dim apikey As String, siteId As String
With ws
apikey = .Range("B2").Value
siteId = .Range("B3").Value
End With
'リクエストデータ作成
Dim jsonRequest As Object
Set jsonRequest = New Dictionary
jsonRequest.Add "ApiVersion", "1.1"
jsonRequest.Add "ApiKey", apikey
jsonRequest.Add "View", New Dictionary
'タイトル
jsonRequest.Add "Title", ws.Range("A6").Value
'内容
jsonRequest.Add "Body", ws.Range("B6").Value
'状況
jsonRequest.Add "Status", ws.Range("C6").Value
'分類、数値、日付、説明、チェック等はXXXHashのディクショナリを作成して
' そこへディクショナリの入れ子で入れていく
'分類項目
jsonRequest.Add "ClassHash", New Dictionary
jsonRequest("ClassHash").Add "ClassA", ws.Range("D6").Value
jsonRequest("ClassHash").Add "ClassB", ws.Range("E6").Value
'数値項目
jsonRequest.Add "NumHash", New Dictionary
jsonRequest("NumHash").Add "NumA", ws.Range("F6").Value
'日付項目
'※セル値が空白の場合、作成しない
'※文字列にして渡す
jsonRequest.Add "DateHash", New Dictionary
If ws.Range("G6").Value <> "" Then
jsonRequest("DateHash").Add "DateA", Format(ws.Range("G6").Value, "yyyy/mm/dd hh:nn:ss")
End If
'説明項目
jsonRequest.Add "DescriptionHash", New Dictionary
jsonRequest("DescriptionHash").Add "DescriptionA", ws.Range("H6").Value
'チェック項目
jsonRequest.Add "CheckHash", New Dictionary
jsonRequest("CheckHash").Add "CheckA", ws.Range("I6").Value
'イミディエイトウィンドウに作成したリクエストのディクショナリをjson形式で出力してみる
'Whitespace:=4 は4スペース分のインデント
Debug.Print JsonConverter.ConvertToJson(jsonRequest, Whitespace:=4)
'プリザンターへ送信
Dim httpRequest As Object
Set httpRequest = CreateObject("msxml2.xmlhttp")
'URL文字列作成
Dim strUrl As String
strUrl = "http://" & saver & "/api/items/" & siteId & "/create"
httpRequest.Open "POST", strUrl, False
httpRequest.setRequestHeader "Content-Type", "application/json"
httpRequest.send JsonConverter.ConvertToJson(jsonRequest)
'成功したら200
Debug.Print httpRequest.Status
End Sub
(3)プリザンター
プリザンターのサイト132を見てみます。
結果が反映されてない?という場合はブラウザの更新ボタンを押してみてください。
テーブルにレコードが追加されました!ぱちぱち
(4)注意事項
詳しい解説はここではしませんが、注意事項としては
・日付項目はそのまま日付時刻値で突っ込むと9時間ずれるので、format関数で文字列に変換して登録しています。vbajsonの中で変換されるときにマイナス9時間になるみたい?GMT標準時間とやらとの時差が9時間だそうなので、なんとなく納得。
https://time.artjoey.com/jp/japan.htm
format関数で文字列にするとよい、というのはこちらで勉強させていただきました。
https://asbepartners.com/convjson/#google_vignette
・日付項目はセル値が空欄の場合、エラーになってしまうので、セル値が空欄の場合はディクショナリに値をセットしないようにif文を入れています。
・状況や分類項目など選択肢を設定している項目は表示名ではなく値をインポート値とする
・チェック項目は true,false または 1,0 で登録が可能です。
(5)参考:作成したjsonの内容
イミディエイトウインドウに出力したjsonの内容。
日本語は16進数になるとか。。。
{
"ApiVersion": "1.1",
"ApiKey": "****",
"View": {
},
"Title": "\u30C6\u30B9\u30C8\uFF11",
"Body": "\u30C6\u30B9\u30C8\u3067\u3059\u3088",
"Status": 200,
"ClassHash": {
"ClassA": "\u5C0F\u9EA6\u7C89",
"ClassB": 100
},
"NumHash": {
"NumA": 1234
},
"DateHash": {
"DateA": "2024-02-18T11:54:44.000Z"
},
"DescriptionHash": {
"DescriptionA": "\u8AAC\u660E\u3059\u308B\u3068\u9577\u304F\u306A\u308B"
},
"CheckHash": {
"CheckA": true
}
}
4.インポート:レコード更新
(1)エクセル
今度はサイトIDは不要でレコードIDが必要になります。
先ほどインポートして作成したレコード139を修正します。
タイトルを「テスト1」→「テスト1の修正」と書き換えます。
内容を「テストですよ」→「修正しました」と書き換えます。
ここからはちょっと実験で、分類A「小麦粉」、説明A「説明すると長くなる」を空欄に書き換えたいと思いました。
どちらも空白セルに見えますが、分類Aに「=””」と入力してあります。説明Aは空欄でなにも入力していません。この違いがどう出るか、ちょっと実験です。
(2)VBAコード
Sub updateToPleasanter()
Dim ws As Worksheet
Set ws = Worksheets("import更新")
'更新情報(実際の環境に合わせてください)
Const saver As String = "localhost"
Dim apikey As String, recordId As String
With ws
apikey = .Range("B2").Value
recordId = .Range("A6").Value
End With
'リクエストデータ作成
Dim jsonRequest As Object
Set jsonRequest = New Dictionary
jsonRequest.Add "ApiVersion", "1.1"
jsonRequest.Add "ApiKey", apikey
jsonRequest.Add "View", New Dictionary
'タイトル
jsonRequest.Add "Title", ws.Range("B6").Value
'内容
jsonRequest.Add "Body", ws.Range("C6").Value
'分類、数値、日付、説明、チェック等はXXXHashのディクショナリを作成して
' そこへディクショナリの入れ子で入れていく
'分類項目
jsonRequest.Add "ClassHash", New Dictionary
jsonRequest("ClassHash").Add "ClassA", ws.Range("D6").Value
'説明項目
jsonRequest.Add "DescriptionHash", New Dictionary
jsonRequest("DescriptionHash").Add "DescriptionA", ws.Range("E6").Value
'イミディエイトウィンドウに作成したリクエストのディクショナリをjson形式で出力してみる
'Whitespace:=4 は4スペース分のインデント
Debug.Print JsonConverter.ConvertToJson(jsonRequest, Whitespace:=4)
'プリザンターへ送信
Dim httpRequest As Object
Set httpRequest = CreateObject("msxml2.xmlhttp")
'URL文字列作成
Dim strUrl As String
strUrl = "http://" & saver & "/api/items/" & recordId & "/update"
httpRequest.Open "POST", strUrl, False
httpRequest.setRequestHeader "Content-Type", "application/json"
httpRequest.send JsonConverter.ConvertToJson(jsonRequest)
'成功したら200
If httpRequest.Status = 200 Then
MsgBox "更新しました"
Else
MsgBox "更新に失敗しました"
End If
End Sub
(3)結果
分類Aは空欄に更新されています。セル値が空欄だった説明Aは内容がもとのままで書き換えられていません。
イミディエイトウインドウに出力されたjsonの内容を見てみましょう。
ClassHashのClassAには “” がセットされています。
DiscriptionHashはなにも入っていないですね。Dictionaryの値がEmptyの場合、jsonとして作成されないようです。
説明Aも空欄に書き換えたい場合は、セルに「=””」と入力しておきます。
逆に、空欄であれば、プリザンターは更新されないということもわかりましたね。
{
"ApiVersion": "1.1",
"ApiKey": "3921d01096dd1fd8f7cb958e53bc512980e49ac1963e73d538f819e3ab29f08cc56f22a188534f1f2256dbb6a0d7a0d9a98292b0fda73ea82b8c12e3ef45ecbc",
"View": {
},
"Title": "\u30C6\u30B9\u30C81\u306E\u4FEE\u6B63",
"Body": "\u4FEE\u6B63\u3057\u307E\u3057\u305F",
"ClassHash": {
"ClassA": ""
},
"DescriptionHash": {
}
}
5.複数レコードの追加
複数レコードでやってみます。
(1)エクセル
3行分のデータを登録します。
(2)VBAコード
結果的に単一読み込みの時とあまり変わりません。。。
エラー処理などは入れていません。
なお、登録するデータが大量の場合、ワークシートからの直接読み込みではなく、配列にいったん代入してから処理する方法のほうがおすすめです。
Sub importToPleasanter2()
Dim ws As Worksheet
Set ws = Worksheets("import")
'更新情報(実際の環境に合わせてください)
Const saver As String = "localhost"
Dim apikey As String, siteId As String
With ws
apikey = .Range("B2").Value
siteId = .Range("B3").Value
End With
Dim jsonRequest As Object
Dim httpRequest As Object
Dim strUrl As String
Dim successCnt As Long
Dim errorCnt As Long
Dim i As Long: i = 6 '読取開始行
Do Until ws.Cells(i, 1).Value = ""
'リクエストデータ作成
Set jsonRequest = New Dictionary
jsonRequest.Add "ApiVersion", "1.1"
jsonRequest.Add "ApiKey", apikey
jsonRequest.Add "View", New Dictionary
'タイトル
jsonRequest.Add "Title", ws.Cells(i, 1).Value
'内容
jsonRequest.Add "Body", ws.Cells(i, 2).Value
'状況
jsonRequest.Add "Status", ws.Cells(i, 3).Value
'分類、数値、日付、説明、チェック等はXXXHashのディクショナリを作成して
' そこへディクショナリの入れ子で入れていく
jsonRequest.Add "ClassHash", New Dictionary
jsonRequest.Add "NumHash", New Dictionary
jsonRequest.Add "DateHash", New Dictionary
jsonRequest.Add "DescriptionHash", New Dictionary
jsonRequest.Add "CheckHash", New Dictionary
jsonRequest("ClassHash").Add "ClassA", ws.Cells(i, 4).Value '分類A
jsonRequest("ClassHash").Add "ClassB", ws.Cells(i, 5).Value '分類B
jsonRequest("NumHash").Add "NumA", ws.Cells(i, 6).Value '数値A
'日付A※文字列に変換
jsonRequest("DateHash").Add "DateA", Format(ws.Cells(i, 7).Value, "yyyy/mm/dd hh:nn:ss")
jsonRequest("DescriptionHash").Add "DescriptionA", ws.Cells(i, 8).Value '説明A
jsonRequest("CheckHash").Add "CheckA", ws.Cells(i, 9).Value 'チェックA
'*** プリザンターへ送信 ***
Set httpRequest = CreateObject("msxml2.xmlhttp")
'URL文字列作成
strUrl = "http://" & saver & "/api/items/" & siteId & "/create"
'初期化
httpRequest.Open "POST", strUrl, False
httpRequest.setRequestHeader "Content-Type", "application/json"
'送信
httpRequest.send JsonConverter.ConvertToJson(jsonRequest)
'成功したら200
If httpRequest.Status = 200 Then
successCnt = successCnt + 1
Else
errorCnt = errorCnt + 1
End If
Set jsonRequest = Nothing
Set httpRequest = Nothing
'行番号プラス1
i = i + 1
Loop
MsgBox "処理終了" & vbCrLf & _
"登録成功" & successCnt & "件" & vbCrLf & _
"登録失敗" & errorCnt & "件"
End Sub
(3)結果
6.複数レコード更新
(1)エクセル
更新しない項目は空白にしています。チェックAはtrue、falseではなく1,0としてみました。(1がチェックオン(true)、0がチェックオフ(false))
レコードID147の説明Aはには改行を入れてあります。はたして反映されるでしょうか。
(2)VBAコード
今度は配列に入れてループしてみました。そのほか特にあんまり変わりはないですね。
Sub updateToPleasanter2()
Dim ws As Worksheet
Set ws = Worksheets("import更新")
'更新情報(実際の環境に合わせてください)
Const saver As String = "localhost"
Dim apikey As String
Dim recordId As String
Dim jsonRequest As Object
Dim httpRequest As Object
Dim strUrl As String
Dim successCnt As Long
Dim errorCnt As Long
Dim arrData As Variant
Dim i As Long
'ワークシートからデータ
With ws
apikey = .Range("B2").Value
With .Range("A5").CurrentRegion
arrData = .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Value
End With
End With
For i = LBound(arrData) To UBound(arrData)
'リクエストデータ作成
Set jsonRequest = New Dictionary
jsonRequest.Add "ApiVersion", "1.1"
jsonRequest.Add "ApiKey", apikey
jsonRequest.Add "View", New Dictionary
'レコードID
recordId = arrData(i, 1)
'内容
jsonRequest.Add "Body", arrData(i, 2)
'状況
jsonRequest.Add "Status", arrData(i, 3)
'分類、数値、日付、説明、チェック等はXXXHashのディクショナリを作成して
' そこへディクショナリの入れ子で入れていく
jsonRequest.Add "ClassHash", New Dictionary
jsonRequest.Add "NumHash", New Dictionary
jsonRequest.Add "DateHash", New Dictionary
jsonRequest.Add "DescriptionHash", New Dictionary
jsonRequest.Add "CheckHash", New Dictionary
jsonRequest("ClassHash").Add "ClassA", arrData(i, 4) '分類A
jsonRequest("ClassHash").Add "ClassB", arrData(i, 5) '分類B
jsonRequest("NumHash").Add "NumA", arrData(i, 6) '数値A
If arrData(i, 7) <> "" Then
jsonRequest("DateHash").Add "DateA", Format(arrData(i, 7), "yyyy/mm/dd hh:nn:ss") '日付A
End If
jsonRequest("DescriptionHash").Add "DescriptionA", arrData(i, 8) '説明A
jsonRequest("CheckHash").Add "CheckA", arrData(i, 9) 'チェックA
'*** プリザンターへ送信 ***
Set httpRequest = CreateObject("msxml2.xmlhttp")
'URL文字列作成
strUrl = "http://" & saver & "/api/items/" & recordId & "/update"
'初期化
httpRequest.Open "POST", strUrl, False
httpRequest.setRequestHeader "Content-Type", "application/json"
'送信
httpRequest.send JsonConverter.ConvertToJson(jsonRequest)
'成功したら200
If httpRequest.Status = 200 Then
successCnt = successCnt + 1
Else
errorCnt = errorCnt + 1
End If
Set jsonRequest = Nothing
Set httpRequest = Nothing
Next i
MsgBox "処理終了" & vbCrLf & _
"登録成功" & successCnt & "件" & vbCrLf & _
"登録失敗" & errorCnt & "件"
End Sub
(3)結果
意図したとおりになっていますね。セル値が空欄の個所は変更されず、セル値が入っているところだけ変更されています。
ID149の説明Aはちゃんと改行されていますね。
7.おわりに
恐れていたより簡単にできた!
複数データを突っ込むときもあまり省略できるところがなかったので(できるのかもしれないけど)、インポート部分を更新値を引数にしたファンクションにしてもよさそうですね。
解説は少なめですが、vbaエクスポートの時にしつこくごちゃごちゃ書いているので、よろしければそちらもご参照ください。
お読みいただきありがとうございました。
※更新をfunctionにしてみた例を挙げておきます。
Sub test1()
Dim ws As Worksheet: Set ws = Worksheets("import更新")
'サーバー名(環境に合わせて設定)
Const saver As String = "localhost"
'ワークシートからapiley
Dim apikey As String
With ws
apikey = .Range("B2").Value
End With
Dim successCnt As Long
Dim errorCnt As Long
Dim tmp As Variant
Dim rtn As Boolean
Dim i As Long: i = 6
With ws
Do Until .Cells(i, 1).Value = ""
tmp = .Range("A" & i & ":J" & i).Value '2次元配列にIN
tmp = WorksheetFunction.Index(tmp, 1, 0) '3次元配列を1次元配列に変換
'更新実行
rtn = exe_updateToPleasanter(saver, apikey, tmp)
'戻り値によって成功カウント、失敗カウントを更新
If rtn = True Then
successCnt = successCnt + 1
Else
errorCnt = errorCnt + 1
End If
'次の行へ
i = i + 1
Loop
End With
MsgBox "処理終了" & vbCrLf & _
"登録成功" & successCnt & "件" & vbCrLf & _
"登録失敗" & errorCnt & "件"
End Sub
Function exe_updateToPleasanter(ByVal saver As String, ByVal apikey As String, arrDataRow) As Boolean
Dim jsonRequest As Object
Dim httpRequest As Object
Dim strUrl As String
Dim recordId As String
'リクエストデータ作成
Set jsonRequest = New Dictionary
jsonRequest.Add "ApiVersion", "1.1"
jsonRequest.Add "ApiKey", apikey
jsonRequest.Add "View", New Dictionary
'レコードID
recordId = arrDataRow(1)
'タイトル
jsonRequest.Add "Title", arrDataRow(2)
'内容
jsonRequest.Add "Body", arrDataRow(3)
'状況
jsonRequest.Add "Status", arrDataRow(4)
'分類、数値、日付、説明、チェック等はXXXHashのディクショナリを作成して
' そこへディクショナリの入れ子で入れていく
jsonRequest.Add "ClassHash", New Dictionary
jsonRequest.Add "NumHash", New Dictionary
jsonRequest.Add "DateHash", New Dictionary
jsonRequest.Add "DescriptionHash", New Dictionary
jsonRequest.Add "CheckHash", New Dictionary
jsonRequest("ClassHash").Add "ClassA", arrDataRow(5) '分類A
jsonRequest("ClassHash").Add "ClassB", arrDataRow(6) '分類B
jsonRequest("NumHash").Add "NumA", arrDataRow(7) '数値A
If arrDataRow(8) <> "" Then
jsonRequest("DateHash").Add "DateA", Format(arrDataRow(8), "yyyy/mm/dd hh:nn") '日付A
End If
jsonRequest("DescriptionHash").Add "DescriptionA", arrDataRow(9) '説明A
If arrDataRow(10) <> "" Then
jsonRequest("CheckHash").Add "CheckA", arrDataRow(10) 'チェックA
End If
Debug.Print JsonConverter.ConvertToJson(jsonRequest, Whitespace:=4)
'*** プリザンターへ送信 ***
Set httpRequest = CreateObject("msxml2.xmlhttp")
'URL文字列作成
strUrl = "http://" & saver & "/api/items/" & recordId & "/update"
'初期化
httpRequest.Open "POST", strUrl, False
httpRequest.setRequestHeader "Content-Type", "application/json"
'送信
httpRequest.send JsonConverter.ConvertToJson(jsonRequest)
'成功したらTrueを返す
If httpRequest.Status = 200 Then
exe_updateToPleasanter = True
Else
exe_updateToPleasanter = False
End If
Set jsonRequest = Nothing
Set httpRequest = Nothing
End Function
8.参考文献、記事
■プリザンター公式サイトより
FAQ:サンプルコード:ExcelからPleasanterへアクセスしたい
■参考とさせていただいた記事
PleasanterとExcelを接続してみた-応用編
m-ishikawa1980/ExcelToPleasanter
エクセルVBAでHTTPリクエストをする最も簡単なプログラム
【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)3 HTTPリクエスト
内部リンク
プリザンザンターVBAエクスポートシリーズ
【pleasanter/VBA】エクセルからプリザンターのデータを取得する
【pleasanter/VBA】エクセルからプリザンターのデータを取得する②絞り込み条件の指定
【pleasanter/VBA】エクセルからプリザンターのデータを取得する③変数で絞り込み条件を指定する
【pleasanter/VBA】エクスポート④絞り込み条件で〇〇を含むを指定する
【pleasanter/VBA】エクスポート⑤並べ替え
【pleasanter/VBA】エクスポート⑥表示名を出したい
【pleasanter/VBA】エクスポート⑦データがちょん切れる時の対応 Offset
【pleasanter/VBA】エクスポート⑧出力される日付を文字列ではなく日付時刻型で出したい
【pleasanter/VBA】エクスポート⑨汎用ツールを作ってみた
【pleasanter/VBA】エクスポート⑩汎用ツール増強版
プリザンターPowerQuery連携シリーズ
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する①
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する②取得条件の指定方法
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する③上限値以上のレコードを連続で取得する
【pleasanter/PowerQuery】プリザンターの情報をパワークエリで取得する④ユーザーテーブルとマージ
コメント