【入門編】フォームの「OpenArgs」をJSON形式で受け渡し、画面間の複雑なパラメータ制御を実現する – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。いつも業務アプリの開発や効率化、本当にお疲れ様です。

マクロの記録から一歩踏み出し、「VBAを使って、もっと複雑な画面遷移やデータ連携を作ってみたい!」と思い立ったその瞬間から、あなたは立派なアプリケーション開発者の道を歩み始めています。

今回は、Access開発において誰もが一度は頭を抱える「フォーム間で複数のデータをスマートに受け渡すにはどうすればいいの?」という疑問にお答えします。

「OpenArgs(オープン・アーギュメンツ)」という、Accessが標準で用意してくれている仕組みを使いながら、Web開発などでも主流の「JSON(ジェイソン)形式」を取り入れることで、驚くほどスッキリと、そしてバグの出にくい頑丈な画面連携を実現する方法を優しく解説します。

ここをクリアすれば、Access VBAの基本から実戦レベルへのステップアップはバッチリですよ。それでは、一緒に学んでいきましょう!

1. フォーム遷移の「壁」:なぜ標準のOpenArgsだけでは足りないのか?

Accessで新しいフォームを開くとき、私たちはよく `DoCmd.OpenForm` という命令を使います。この命令のいちばん最後に、`OpenArgs` という引数(パラメータ)を渡すことができます。

‘ 顧客ID「105」を渡して、詳細画面を開く
DoCmd.OpenForm “frmDetail”, , , , , , “105”

受け取り側のフォーム(`frmDetail`)では、`Me.OpenArgs` と書くだけで `”105″` という値を取り出すことができます。とても簡単ですね。

しかし、実戦の開発では、以下のように「複数の値」を同時に渡したくなることがよくあります。

  • 開く対象の「顧客ID(105)」
  • 画面を「編集モード」で開くのか、「閲覧モード」で開くのか
  • 呼び出し元の「親画面の名前」

標準の `OpenArgs` は、たった1つの文字列(テキスト)しか渡せないという制限があります。

従来の「イマイチな解決策」とそのリスク

この制限を乗り越えるために、昔からよく使われてきた方法が2つあります。しかし、これらには大きな弱点があります。

| 手法 | やり方 | 弱点・リスク |
| :— | :— | :— |
| カンマ区切り | `”105,Edit,frmMain”` のように繋げて、受け側で `Split` 関数で分解する。 | 値の中にカンマ(`,`)が含まれていると位置がズレてバグる。順番が変わると動かなくなる。 |
| グローバル変数 | 標準モジュールに `Public g_ID As Long` などを宣言して、そこに一時保存する。 | どこで値が書き換えられたか追跡しにくくなり、アプリが予期せぬ挙動(バグ)を起こしやすい。 |

そこで登場するのが、現代のプログラミングで最も愛されているデータの形、「JSON(ジェイソン)形式」です。

2. JSON(ジェイソン)形式とは?(図解イメージ)

JSONは、データを「キー(名前)」と「値(データ)」のペアで管理する、非常にシンプルなテキスト形式です。

例えば、先ほどの3つのデータをJSONで表現すると、次のようになります。

{
“CustomerID”: 105,
“Mode”: “Edit”,
“ParentForm”: “frmMain”
}

これを1本の文字列としてギュッと縮めると、以下のようになります。
`{“CustomerID”:105,”Mode”:”Edit”,”ParentForm”:”frmMain”}`

この文字列を `OpenArgs` に入れて次の画面に渡し、次の画面で「`CustomerID` の値はなに?」と指名して取り出します。

シリアライズ と デシリアライズ

この一連の流れを、専門用語で次のように呼びます。難しそうに見えますが、イメージは「お引っ越し」です。

【送信側フォーム】
複数のデータを1つの箱にパッキングする(文字にする)
=「シリアライズ(構造化)」

【OpenArgs(宅急便の段ボール)】で送信!

【受信側フォーム】
届いた箱を開けて、必要な荷物を取り出す
=「デシリアライズ(解析・復元)」

この方法なら、データの順番が変わっても、データの中にカンマが含まれていても、一切バグりません。非常に安全です!

3. 準備:Access VBAでJSONを扱う「プロの技」

Access VBAには、標準でJSONを解析する機能がありません。インターネットで調べると「外部のライブラリ(JsonConverter.basなど)を導入しましょう」と書かれていることが多いですが、初心者にとっては少しハードルが高いですよね。

また、昔よく使われていた `ScriptControl` という機能は、現在の主流である 64bit版のOffice(Access)では動かない という致命的な罠があります。

そこで今回は、「外部ライブラリ不要」「32bit/64bit両対応」「コピペするだけでそのまま動く」、正規表現(RegExp)を使ったスマートな簡易JSON解析関数を用意しました。

まずは、以下のコードをAccessの「標準モジュール」に貼り付けてください。

標準モジュールに貼り付けるコード(`modJSONHelper`)

Accessのメニューから `挿入` > `標準モジュール` を選択し、名前を `modJSONHelper` として保存して、以下のコードをそのまま貼り付けます。

Option Compare Database
Option Explicit

‘ =================================================================
‘ 簡易JSON作成・解析モジュール (32bit/64bit 両対応)
‘ =================================================================

‘ — 送信用:キーと値のペアから、JSON文字列を作成する —
Public Function CreateJson(ParamArray KeyValuePairs() As Variant) As String
Dim i As Long
Dim result As String
result = “{”

For i = LBound(KeyValuePairs) To UBound(KeyValuePairs) Step 2
If i > LBound(KeyValuePairs) Then result = result & “,”

‘ キーの追加
result = result & “””” & KeyValuePairs(i) & “””:”

‘ 値の型に応じて適切にエスケープして追加
If IsNumeric(KeyValuePairs(i + 1)) Then
result = result & KeyValuePairs(i + 1)
ElseIf VarType(KeyValuePairs(i + 1)) = vbBoolean Then
result = result & IIf(KeyValuePairs(i + 1), “true”, “false”)
Else
‘ 文字列の場合はダブルクォーテーションで囲む
result = result & “””” & Replace(KeyValuePairs(i + 1), “”””, “\”””) & “”””
End If
Next i

result = result & “}”
CreateJson = result
End Function

‘ — 受信用:JSON文字列から、指定したキーの値を取り出す —
Public Function GetJsonValue(ByVal jsonString As String, ByVal key As String) As String
On Error GoTo ErrorHandler

‘ 正規表現エンジンをレイトバインディングで生成(参照設定不要、64bit対応)
Dim regEx As Object
Set regEx = CreateObject(“VBScript.RegExp”)

‘ JSONから特定のキーの値(文字列または数値)を抽出するパターン
regEx.Pattern = “””” & key & “””\s:\s””?([^””,}]+)””?”
regEx.IgnoreCase = True

Dim matches As Object
Set matches = regEx.Execute(jsonString)

If matches.Count > 0 Then
‘ マッチしたグループ(括弧の中身)を返す
GetJsonValue = matches(0).SubMatches(0)
Else
GetJsonValue = “”
End If

Set regEx = Nothing
Exit Function

ErrorHandler:
GetJsonValue = “”
Set regEx = Nothing
End Function

このモジュールを用意しておくだけで、複雑なJSONの生成と解析がいつでも数行で書けるようになります。

4. 実践:画面遷移の実装コード

それでは、実際に「送信側フォーム(`frmMain`)」から「受信側フォーム(`frmDetail`)」へデータを渡すコードを書いてみましょう。

① 送信側フォーム(`frmMain`)のボタンクリックイベント

メイン画面にボタン(例:`btnOpenDetail`)を配置し、そのクリック時イベントに以下のコードを記述します。

Private Sub btnOpenDetail_Click()
On Error GoTo ErrorHandler

Dim jsonParams As String

‘ 1. 送信したい複数のパラメータをJSONにパックする(シリアライズ)
‘ ※「キー」と「値」を交互に指定します
jsonParams = CreateJson( _
“CustomerID”, 105, _
“Mode”, “Edit”, _
“ParentForm”, Me.Name _
)

‘ デバッグウィンドウに生成されたJSONを表示(確認用)
Debug.Print “送信するJSON: ” & jsonParams

‘ 2. OpenArgsにJSON文字列を乗せて、詳細画面を開く
DoCmd.OpenForm “frmDetail”, acNormal, , , , acWindowNormal, jsonParams

Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “システムエラー”
End Sub

② 受信側フォーム(`frmDetail`)の読み込みイベント

値を受け取る側の詳細画面(`frmDetail`)を開くとき、届いたJSONを解析して、画面をコントロールします。
ここでは、`Form_Load`(読み込み時)イベントに記述するのが最も安全で確実です。

Private Sub Form_Load()
On Error GoTo ErrorHandler

‘ 1. OpenArgs(届いた段ボール)が空っぽでないか確認する
If IsNull(Me.OpenArgs) Or Me.OpenArgs = “” Then
Exit Sub ‘ パラメータがない場合は何もしない(または既定の動作)
End If

Dim receivedJson As String
receivedJson = Me.OpenArgs

‘ デバッグウィンドウに受け取ったJSONを表示(確認用)
Debug.Print “受信したJSON: ” & receivedJson

‘ 2. JSONから必要なキーの値を個別に取り出す(デシリアライズ)
Dim custID As String
Dim openMode As String
Dim parentName As String

custID = GetJsonValue(receivedJson, “CustomerID”)
openMode = GetJsonValue(receivedJson, “Mode”)
parentName = GetJsonValue(receivedJson, “ParentForm”)

‘ 3. 取り出した値を使って、画面の挙動をコントロールする
‘ 例:顧客IDをもとに、データを検索して表示する
If custID <> “” Then
‘ フォームに特定のレコードを表示させる処理(一例)
Me.Filter = “顧客ID = ” & custID
Me.FilterOn = True
End If

‘ 例:編集モードに応じて、編集許可を切り替える
If openMode = “Edit” Then
Me.AllowEdits = True
Me.Caption = “顧客詳細 [編集モード] – 元画面: ” & parentName
Else
Me.AllowEdits = False
Me.Caption = “顧客詳細 [読み取り専用]”
End If

Exit Sub

ErrorHandler:
MsgBox “パラメータの読み込み中にエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub

5. 陥りやすいエラーと回避策(チーフアーキテクトの眼)

この実装方法を現場で使う際、プロのエンジニアが必ず気をつける「落とし穴」と、その回避策を解説します。

① OpenArgsが「Null(空)」のときの考慮

受信側のフォームは、必ずしも「他の画面からパラメータ付きで開かれる」とは限りません。開発中にそのフォーム単体で開いてテストすることもありますよね。
その場合、`Me.OpenArgs` は `Null` になります。
`Null` の状態のまま `GetJsonValue` に渡すと、VBAは「型が違います」というエラーを吐いてしまいます。

  • 対策: 必ず `Form_Load` の冒頭で `IsNull(Me.OpenArgs)` をチェックし、空っぽの場合は安全に処理を抜ける(またはデフォルト値を入れる)ガードコードを書きましょう。

② なぜ Form_Open ではなく Form_Load に書くのか?

Accessフォームの起動イベントには `Form_Open`(開くとき)と `Form_Load`(読み込み時)があります。

  • `Form_Open`:フォームのレコードソースが読み込まれる前に発生します。ここでは、画面のテキストボックスなどに値を代入しようとすると、タイミングが早すぎてエラーになることがあります。
  • `Form_Load`:画面要素がすべて準備万端になった後に発生します。そのため、受け取ったパラメータをテキストボックスに代入したり、レコードをフィルタリングしたりする処理は `Form_Load` に書くのがベストプラクティスです。

まとめ:この技術を手に入れたあなたの未来

お疲れ様でした!
一見難しそうに見える「JSONを使ったパラメータ制御」ですが、仕組みを紐解いてみれば、「データをきれいに1箱に詰めて送り、受け取り側で優しく取り出す」という、現実のお引っ越しと同じとてもシンプルなルールで動いています。

この方法を一度マスターしてしまえば、以下のような素晴らしいメリットが手に入ります。

1. 画面が増えても、コードが散らからない。
2. 仕様変更(「やっぱり渡すデータをもう1つ増やしたい!」)があっても、引数の順番を気にせず簡単に追加できる。
3. グローバル変数に頼らないため、メモリが原因の奇妙なバグに悩まされなくなる。

Access VBAの基本を一つひとつ丁寧に紐解いていけば、どんなに複雑なシステムも自由自在にコントロールできるようになります。あなたの開発が、もっと楽しく、もっとスマートなものになりますように。

「ここをクリアすれば、Access VBAの基本はバッチリですよ!」
また分からないことがあれば、いつでも聞きに来てくださいね。応援しています!

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