お世話になっております。
あるフォームF_Displayが、サブフォームsbf_Displayを持っています。
sbf_DisplayはレコードソースがクエリQ_Dislayです。
Q_DispayはテーブルT_Seihin_Torihiki,MT_Torihiki,MT_seihinの三つからなら選択クエリです。
これにより、F_Displayで、取引状況を表示させようとしています。
このフォームから、Docmd.OpenForm "PF_Input1",,,,,acDialogで、インプット用のフォームをポップアップ表示させます。
インプットフォームでデータを入力したあと、
Dim strSQL as string
Dim db AS DAO.Database
strSQL = "INDERT INTO T_Seihin_Torihiki (中略) VALUES (中略);"
Set db = CurrentDb
db.Execute strSQL
のようなコードでテーブルに入力させようとすると、最後の行でエラー3008(T_Seihin_Torihikiが排他的に開かれている、云々)が出ました。
たぶん、F_Displayおよびsbf_Displayが開いているため、そのソースであるテーブルにデータを格納できないのだと思います。
質問は、この考え方であっているかということと、どういう方針で回避すればよいかです。
よろしくお願いいたします
(当方、英語版のaccessで開発しています)
F_Displayおよびsbf_Displayがテーブル(またはクエリ)と連結しているフォームなら、フォームでデータを入力するという考えかたにすべきです。
VBAで新規レコードに移動して、そこでフィールドに代入するか、
フォームのRecorsetプロパティでレコードセットを取得してそれに対してAddNewするのが王道です。
ご回答ありがとうございます
テーブルと連結させる必要はありません。(簡単に表示させるために連結というスタイルをとりました)
sbf_Displayとテーブル(クエリ)の連結を取り、F_DisplayのLoadイベント時に
[Forms]![F_Display]![sbf_Display].Form.Recordsource = (SQL文)として表示させましたが、これも同じでした。
(この場合も連結になってしまうのでしょうか)
サブフォームに直接打ち込む方法でなく、インプットフォームを利用したいとする場合はどうするのでしょうか?
メイン/サブフォーム形式でサブフォームは帳票フォームかデータシートですよね。
だとしたら連結フォームにするしかないです。(非連結では1レコード分のデータしか表示できない。)
これも連結フォームになります。レコードソースをデザインビューで設定するかVBAで設定するか、だけの違いですので。
とりあえず一部分のコードだけでは、全体像が把握できませんので、
インプット用のフォームを呼び出すイベントプロシージャ全体。
インプット用のフォームのコード全体を提示してもらえますか。
帳票フォームです
Docmd.OpenForm "PF_Input1",,,,,acDialog
Private Sub btnInput_Click()
On Error GoTo ErrHandler
If Nz(Me.cmbP_Name, "") = "" Or Nz(Me.txtQty, "") = "" Then
MsgBox "Fill P_Name and transaction Quantitiy", vbExclamation, "Caution"
Exit Sub
End If
Dim sngQty As Single
Dim strSQL As String
If Nz(Me.opgTzT, "") = "" Then
MsgBox "Choice transaction type", vbExclamation, "Caution"
Exit Sub
ElseIf Me.opgTzT = 21 Or 22 Then
sngQty = Me.txtQty
Else
sngQty = Me.txtQty * -1
End If
' SQLによる、データ入力
strSQL = _
"INSERT INTO T_SeihinTorihiki (T_Time, P_ID, TID, Qty, Memo) " &
"VALUES(" &
"#" & Me.txtTzDate & "#, " &
"'" & Me.cmbPName.Column(0) & "', " &
Me.opgTzT & ", " &
sngQty & ", " &
"'" & Me.txtMemo & "' );"
Dim db As DAO.Database
Set db = CurrentDb
db.Execute strSQL
MsgBox "Already Inputed"
Call initilizeForm
GoTo Finally
ErrHandler:
MsgBox "Error #: " & Err.Number & vbNewLine & vbNewLine & _
Err.Description, vbCritical, "Error"
Finally:
If Not db Is Nothing Then
db.Close
Set db = Nothing
End If
End Sub
以上です。
インプットフォームはほかにこれといったコードがありません。初期化のためのInitialize Formと、閉じるボタンくらいです。
下記の1行を追加するとどうでしょうか。
別案
だめでした(変化ありません)
!T_Time = Me.txtTzDate.Value
のところで、Error3164 Field cannnot be updatedが出ました。
いままで
サブフォームsbf_DisplayのソースオブジェクトがF_Display_2(そのフォームのレコードソースがQ_Dislay)
となっていました。
(お伝えし忘れていました。すいません)
これを、
サブフォームsbf_DisplayのソースオブジェクトがQ_Display
にしたところ、エラーの発生が解消されました。
理由が全く分からないのですが、何が違うのでしょうか。
Q_Dislay クエリを直接開いたときにそのクエリで更新できますか。
更新できないなら、更新できるような設計にする必要があります。
よくわかりません。
しかし、InputフォームのCall Initialize Formの後に
Forms!F_Display!sbf_Display.Requery
を挿入して更新させています。
どこかでT_Seihin_Torihikiを排他的に開いているということですので、コードのどこかで開いているとか、あるいはマルチユーザーで共有していて他のユーザーが開いているとか、・・・何か心当たりはないですか。
開発中で、完全にローカルサイトです。(データすら共用していません)
ほかのコードで開いていることもないような気がします。
昨日の報告通り、サブフォームをほかのフォームの埋め込みから、ソースオブジェクトをクエリに変更したところエラーの発生がなくなりましたので、(どういうことは私にはわかっておりませんが)、とりあえずこのやり方で構築していきます。
ありがとうございました。
サブフォーム内のコードでレコードを更新するようなことをしていませんかね。
連結コントロールに値を代入するとか。
あるいは、フォームの「レコードロック」プロパティを「すべてのレコード」に設定しているとか。
ソースオブジェクトをクエリにすると、フォームで使えるいろいろな機能が使えなくなるので、将来、機能を拡張したいときに困るかもしれません。
サブフォームにはイベントやコードがありませんでした
All Records(すべてのレコード)になっていました。
No LocksまたはEdited Recordに変更したら、Error3008が消えました。
つまり、解決しました。ありがとうございます。
そのプロパティをいじったことがなかったので、勉強します。
そうなのですね。どういう弊害が出るのでしょうか。
弊害というかフォームで使える機能が使えないということです。
例えば、更新前に入力値をチェックするとか、いろいろ細かい制御がフォームならできます。
わかりました。ありがとうございました。