
ゴルフ練習場を見ている柴犬は「俺にはクラブが持てないからゴルフは分からない。ボールは追いかけるものだ」と思っているのでしょう。
今回の概要
開いた最初のフォーム画面です。

これは、ボタン「編集フォーム」をクリックした画面です。

一番上の新規レコードのレコードセレクタ(左端の黒い四角部分)をクリックしました。
すると、入力フォームが開きます。
また、「新規」が分かるように、IDの表示が「新規」となるようにしています。

次に、上から2つ目のレコードセレクタをクリックします。
すると、選択したレコードの内容がフォームに表示されます。

次に、例として新規に追加してみます。
新規レコードのレコードセレクタをクリックしてフォームを開きます。
名前以下必要事項を入力します。
そして、終了したらボタン「更新」をクリックします。

新しいレコードが追加されました。

確認のため、ボタン「選択フォーム」をクリックします。
期待通りに、新規レコードが確認できます。

フォーム「 入力 」
フォームの構成
フォーム1 のコントロールの配置は次のとおりです。
そして、コントロール名は「テーブル1」のフィールド名と一致するようにします。
すなわち、ID を「ID」、名前を「名前」、郵便番号を「郵便番号」、住所を「住所」とします。
テキストボックスの「コントロールソース」を全部削除して非連結にします。
テキストボックス「 ID 」の編集は想定しないので、編集ロックを「はい」にします。

フォームのプロパティは大体次のように設定しました。
「レコードソース」に「テーブル1」をセットしているのは、「既存のフィールドの追加」でドラッグアンドペーストでフォームにコントロールをセットするためです。
最終には、これを削除します。

コード
OpenArgs に呼び出したフォーム名(親フォーム名)がセットしてあるので、これを取得します。
続いて、親フォームのプロパティ「Data」からデータを取得して描画します。
コードは次のとおりです。
Option Compare Database
Option Explicit
Private myParent As String
Private memData As Dictionary
'---------------------------------------
'このプロパティは主にアクティブが親フォームに戻った後、
'親フォームが参照します。
Public Property Set Data(ByRef myDict As Object)
Set memData = myDict
End Property
Public Property Get Data() As Object
Set Data = memData
End Property
'---------------------------------------
'
Private Sub Form_Open(Cancel As Integer)
'親フォーム名を取得します。
myParent = Me.OpenArgs
End Sub
'---------------------------------------
'
Private Sub Form_Load()
Dim Ctrl As Object
Dim UF As Object
Dim myDict As Dictionary
'------親フォームを探査します。
For Each UF In Forms
If UF.Name = myParent Then
'------親フォームから呼び出したレコードのデータを取得します。
Set myDict = UF.Data
'------フォームのコントロールを探査します。
For Each Ctrl In Me.Controls
'------テキストボックスのみを対象にします。
If TypeName(Ctrl) = "TextBox" Then
'------コントロール名とキーを照合します。
If myDict.Exists(Ctrl.Name) Then
'------照合できたら値をコントールにセットします。
Ctrl.Value = myDict(Ctrl.Name)
End If
End If
Next Ctrl
End If
Next UF
End Sub
'---------------------------------------
'
Private Sub bu更新_Click()
Dim Ctrl As Object
'------フォーム2が参照するデータをセットします。
Set memData = New Dictionary
With Data
For Each Ctrl In Me.Controls
If TypeName(Ctrl) = "TextBox" Then
.Add Ctrl.Name, Ctrl.Value
End If
Next Ctrl
End With
'------アクティブをフォーム2に移します。
Me.Visible = False
End Sub
'---------------------------------------
'
Private Sub bu閉じる_Click()
DoCmd.Close acForm, Me.Name
End Sub
フォーム「 フォーム2 」
フォームの構成
作成したいフォームの最終形です。

テキストボックス「 BC 」「 名前 」「 住所 」「 郵便番号 」「 ID 」「 selected 」、ラベル「 Protect 」などを配置しています。
「 BC 」は黄色の帯を描画します。
「 Protect 」は「 名前 」などの蓋の役割をさせています。


つぎの式の意味は「selected」の文字列の中に「ID」がある場合、ggggggggggがセットされ、ない場合は空がセットされます。
=IIf(InStr([selected].[Value] & ",","," & [ID].[Value] & ",")>0,"gggggggggg","")
ここで、フォント「 Webdings 」は図形表現のようなもので、「 g 」は文字範囲を隙間なく「■」で表現します。
したがって、gは■なので■■■■■■■■■■が隙間なく黄色で表示されます。
ということは、レコード全体が黄色になります。
使い方によっては、この「■」1つを1つのピクセルのようにして、画像表現もできます。
しかし、文字と文字の境界が白く表現されますので、境界が目立たないように薄い黄色にしています。

コントロールの上で右クリックするとメニューが開きます。
そして、メニューの中ほどにある「位置」をクリックすると「最前面」「最背面」が選択できます。
「 BC 」は「最背面」に、「 Protect 」は「最前面」にします。
以上のように、セットして「 フォーム2 」を開くと次のようになります。

コード
Option Compare Database
Option Explicit
Private TargetList As String
Private memData As Dictionary
'---------------------------------------
'
Public Property Set Data(ByRef myDcit As Object)
Set memData = myDict
End Property
Public Property Get Data() As Object
Set Data = memData
End Property
'---------------------------------------
'
Private Sub Form_Open(Cancel As Integer)
Dim mySQL As String
'------ユニオンSQLで空レコードをセットして表示します。
mySQL = mySQL & "SELECT B.* FROM"
mySQL = mySQL & " (SELECT"
mySQL = mySQL & " A.ID"
mySQL = mySQL & ", A.名前"
mySQL = mySQL & ", A.住所"
mySQL = mySQL & ", A.郵便番号"
mySQL = mySQL & " FROM テーブル1 AS A"
mySQL = mySQL & " UNION"
'------空レコード
mySQL = mySQL & " SELECT TOP 1"
mySQL = mySQL & " '新規' AS ID"
mySQL = mySQL & ", '' AS 名前"
mySQL = mySQL & ", '' AS 住所"
mySQL = mySQL & ", '' AS 郵便番号"
mySQL = mySQL & " FROM テーブル1) AS B"
mySQL = mySQL & " ORDER BY B.名前;"
Me.RecordSource = mySQL
End Sub
'---------------------------------------
'
Private Sub Form_Click()
Dim Ctrl As Control
Dim UF As Object
Dim myData As Dictionary
Dim mySQL As String
Dim RES As String
'------レコードセレクタをクリックしました。
If Me.SelHeight > 0 Then
'------レコードを黄色に塗ります。
Me.selected.Value = "," & Me.ID.Value
Me.Recalc
'------レコードのデータを値、コントロール名をキーにした
' ハッシュテーブルを作成します。
Set memData = New Dictionary
With Data
For Each Ctrl In Me.Controls
If TypeName(Ctrl) = "TextBox" Then
.Add Ctrl.Name, Ctrl.Value
End If
Next Ctrl
End With
'------入力フォームを開きます。
DoCmd.OpenForm "入力", acNormal, WindowMode:=acDialog, OpenArgs:=Me.Name
'------入力フォームからアクティブが戻り開いているか確認します。
For Each UF In Forms
'------開いている。
If UF.Name = "入力" Then
'------入力フォームから入力状況を取得します。
Set myData = UF.Data
'------新規レコードの場合追加します。
If myData("ID") = "新規" Then
Call InsertRun(myData, RES)
If RES = "" Then
Me.selected.Value = "," & DMax("ID", "テーブル1")
End If
'------更新の場合修正します。
Else
Call UpdateRun(myData, RES)
End If
'------エラーがなければ再クエリーします。
If RES = "" Then
Me.Requery
'------エラーメッセージを表示します。
Else
MsgBox RES
End If
'------非表示のフォームを閉じます。
DoCmd.Close acForm, "入力", acSaveNo
End If
Next UF
End If
End Sub
'---------------------------------------
'
Private Sub InsertRun(ByRef myData As Dictionary, _
ByRef RES As String)
Dim DB As DAO.Database
Dim WSP As Workspace
Dim mySQL As String
'------追加SQL文
mySQL = "INSERT INTO テーブル1 ("
mySQL = mySQL & "名前"
mySQL = mySQL & ", 住所"
mySQL = mySQL & ", 郵便番号)"
mySQL = mySQL & " VALUES("
mySQL = mySQL & "'" & myData("名前") & "'"
mySQL = mySQL & ", '" & myData("住所") & "'"
mySQL = mySQL & ", '" & myData("郵便番号") & "');"
Call RunSQL(mySQL, RES)
End Sub
'---------------------------------------
'
Private Sub UpdateRun(ByRef myData As Dictionary, _
ByRef RES As String)
Dim DB As DAO.Database
Dim WSP As Workspace
Dim Keys As Variant
Dim BUF As String
Dim mySQL As String
'------更新SQL文
mySQL = "UPDATE テーブル1 AS A"
mySQL = mySQL & " SET"
mySQL = mySQL & "【VALUES】"
mySQL = mySQL & " WHERE A.ID = " & myData("ID") & ";"
For Each Keys In memData
If myData.Exists(Keys) Then
'------元データと比較して異なっていれば更新します。
If memData(Keys) <> myData(Keys) Then
If BUF = "" Then
BUF = Keys & " = '" & myData(Keys) & "'"
Else
BUF = BUF & ", " & Keys & " = '" & myData(Keys) & "'"
End If
End If
End If
Next Keys
'------更新がなければmySQLを空にします。
If BUF <> "" Then
BUF = " " & BUF
mySQL = Replace(mySQL, "【VALUES】", BUF)
Else
mySQL = ""
End If
If mySQL <> "" Then
Call RunSQL(mySQL, RES)
Else
RES = "変更はありません。"
End If
End Sub
'---------------------------------------
'
Private Sub RunSQL(ByVal mySQL As String, _
ByRef RES As String)
Dim DB As DAO.Database
Dim WSP As Workspace
On Error GoTo Err_order
Set WSP = DBEngine.Workspaces(0)
Set DB = CurrentDb
'------トランザクション処理開始
WSP.BeginTrans
DB.Execute mySQL
If DB.RecordsAffected = 0 Then
'------ロールバック処理
WSP.Rollback
Else
'------トランザクション処理終了
WSP.CommitTrans
End If
Exit_order:
'------WSP.Close は不要
Set DB = Nothing
Set WSP = Nothing
Exit Sub
Err_order:
RES = Err.Description
'------トランザクション処理終了(処理をなかったことにする)
WSP.Rollback
Resume Exit_order
End Sub
フォーム「 ベース 」
ここでは、ボタン「編集フォーム」を新しく追加します。
そして、コントロール名は「bu3」とします。

コード
Private Sub Form_Load() の修正
2カ所修正します。
'------ボタンのキャプションリスト
CmdBL = Array("一覧プレ", "タックシールプレ", "選択フォーム", "編集フォーム")
'------ボタンのキャプション名とレポート名・フォーム名の
' ハッシュテーブル
Set CapRepo = New Dictionary
With CapRepo
.Add CmdBL(0), "R:レポート1"
.Add CmdBL(1), "R:レポート2"
.Add CmdBL(2), "F:フォーム1"
.Add CmdBL(3), "F:フォーム2"
End With
Private Sub bu3_Click() の追加
ボタン「編集フォーム」をクリックしたときのアクションを記述しています。
'---------------------------------------
'
Private Sub bu3_Click()
Call ChangeObj(CapRepo(Me.bu3.Caption))
End Sub
Private Sub Form_Load()
Dim Ret As Variant
Dim SetValue As Long
Dim OpenObj As Variant
Dim I As Long
On Error Resume Next
'------Win32API関数を使ってアクセスを最小化します
CloseWindow Application.hWndAccessApp
'------現在の設定値を取得
SetValue = GetWindowLong(Me.hWnd, GWL_STYLE)
'------最小化ボタンを無効
SetValue = SetValue And Not WS_MINIMIZEBOX
'------設定値をセット
SetWindowLong Me.hWnd, GWL_STYLE, SetValue
'------単位変換の変換率の計算
TP = TwipPixel
'------ボタンのキャプションリスト
CmdBL = Array("一覧プレ", "タックシールプレ", "選択フォーム", "編集フォーム")
'------ボタンのキャプションをセット
For I = 0 To UBound(CmdBL)
Me("bu" & I).Caption = CmdBL(I)
Next I
'------ボタンのキャプション名とレポート名・フォーム名の
' ハッシュテーブル
Set CapRepo = New Dictionary
With CapRepo
.Add CmdBL(0), "R:レポート1"
.Add CmdBL(1), "R:レポート2"
.Add CmdBL(2), "F:フォーム1"
.Add CmdBL(3), "F:フォーム2"
End With
'------初期値
curReportName = ""
curFormName = ""
TargetList = ""
AllList = ""
'------子フォームの原点
X = 0
Y = Me.bu閉じる.Height + Me.bu閉じる.Top * 2
'------子フォームの大きさ
Call ChildFormSize
'------フォームの OpenArgs プロパティを使用します
If IsNull(Me.OpenArgs) Then
Call ChangeObj(CapRepo("選択フォーム"))
Else
Call ChangeObj(Me.OpenArgs)
End If
End Sub
'---------------------------------------
'
Private Sub bu3_Click()
Call ChangeObj(CapRepo(Me.bu3.Caption))
End Sub