Microsoft Access 掲示板

Error 3008に対する対処法

16 コメント
views
4 フォロー

お世話になっております。

あるフォーム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で開発しています)

nokonoko
作成: 2020/08/25 (火) 15:08:49
通報 ...
1

F_Displayおよびsbf_Displayがテーブル(またはクエリ)と連結しているフォームなら、フォームでデータを入力するという考えかたにすべきです。

VBAで新規レコードに移動して、そこでフィールドに代入するか、
フォームのRecorsetプロパティでレコードセットを取得してそれに対してAddNewするのが王道です。

2
nokonoko 2020/08/25 (火) 18:34:48 653a6@54883

ご回答ありがとうございます

テーブルと連結させる必要はありません。(簡単に表示させるために連結というスタイルをとりました)
sbf_Displayとテーブル(クエリ)の連結を取り、F_DisplayのLoadイベント時に
[Forms]![F_Display]![sbf_Display].Form.Recordsource = (SQL文)として表示させましたが、これも同じでした。
(この場合も連結になってしまうのでしょうか)

サブフォームに直接打ち込む方法でなく、インプットフォームを利用したいとする場合はどうするのでしょうか?

3

メイン/サブフォーム形式でサブフォームは帳票フォームかデータシートですよね。
だとしたら連結フォームにするしかないです。(非連結では1レコード分のデータしか表示できない。)

[Forms]![F_Display]![sbf_Display].Form.Recordsource = (SQL文)

これも連結フォームになります。レコードソースをデザインビューで設定するかVBAで設定するか、だけの違いですので。

とりあえず一部分のコードだけでは、全体像が把握できませんので、
インプット用のフォームを呼び出すイベントプロシージャ全体。
インプット用のフォームのコード全体を提示してもらえますか。

4
nokonoko 2020/08/26 (水) 10:38:33 653a6@54883

メイン/サブフォーム形式でサブフォームは帳票フォームかデータシートですよね。

帳票フォームです

インプット用のフォームを呼び出すイベントプロシージャ全体。

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と、閉じるボタンくらいです。

5

インプット用のフォームを呼び出すイベントプロシージャ全体。

Docmd.OpenForm "PF_Input1",,,,,acDialog

下記の1行を追加するとどうでしょうか。

Me.Refresh
Docmd.OpenForm "PF_Input1",,,,,acDialog
6

別案

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

    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

' フォームのレコードセットに直接データ入力

    With Forms!F_Display!sbf_Display.Form.RecordsetClone
        .AddNew
        !T_Time = Me.txtTzDate.Value
        !P_ID = Me.cmbPName.Column(0)
        !TID = Me.opgTzT
        !Qty = sngQty
        !Memo = Me.txtMemo
        .Update
    End With

    db.Execute strSQL

    MsgBox "Already Inputed"

    Call initilizeForm
Exit Sub

ErrHandler:
    MsgBox "Error #: " & Err.Number & vbNewLine & vbNewLine & _
        Err.Description, vbCritical, "Error"

End Sub
7
nokonoko 2020/08/26 (水) 11:51:34 653a6@54883

下記の1行を追加するとどうでしょうか。

だめでした(変化ありません)

別案

!T_Time = Me.txtTzDate.Value
のところで、Error3164 Field cannnot be updatedが出ました。

8
nokonoko 2020/08/26 (水) 11:59:37 653a6@54883

いままで
サブフォームsbf_DisplayのソースオブジェクトがF_Display_2(そのフォームのレコードソースがQ_Dislay)
となっていました。
(お伝えし忘れていました。すいません)

これを、
サブフォームsbf_DisplayのソースオブジェクトがQ_Display
にしたところ、エラーの発生が解消されました。

理由が全く分からないのですが、何が違うのでしょうか。

9

Q_Dislay クエリを直接開いたときにそのクエリで更新できますか。

更新できないなら、更新できるような設計にする必要があります。

10
nokonoko 2020/08/26 (水) 13:19:42 653a6@54883

Q_Dislay クエリを直接開いたときにそのクエリで更新できますか。

よくわかりません。
しかし、InputフォームのCall Initialize Formの後に

Forms!F_Display!sbf_Display.Requery

を挿入して更新させています。

11

エラー3008(T_Seihin_Torihikiが排他的に開かれている、云々)

どこかでT_Seihin_Torihikiを排他的に開いているということですので、コードのどこかで開いているとか、あるいはマルチユーザーで共有していて他のユーザーが開いているとか、・・・何か心当たりはないですか。

12
nokonoko 2020/08/27 (木) 13:16:48 653a6@54883

開発中で、完全にローカルサイトです。(データすら共用していません)
ほかのコードで開いていることもないような気がします。
昨日の報告通り、サブフォームをほかのフォームの埋め込みから、ソースオブジェクトをクエリに変更したところエラーの発生がなくなりましたので、(どういうことは私にはわかっておりませんが)、とりあえずこのやり方で構築していきます。

ありがとうございました。

13
hatena 2020/08/27 (木) 14:31:48 修正 >> 12

サブフォーム内のコードでレコードを更新するようなことをしていませんかね。
連結コントロールに値を代入するとか。

あるいは、フォームの「レコードロック」プロパティを「すべてのレコード」に設定しているとか。

ソースオブジェクトをクエリにすると、フォームで使えるいろいろな機能が使えなくなるので、将来、機能を拡張したいときに困るかもしれません。

14
nokonoko 2020/08/27 (木) 17:27:46 653a6@54883

 サブフォーム内のコードでレコードを更新するようなことをしていませんかね。
連結コントロールに値を代入するとか。

サブフォームにはイベントやコードがありませんでした

フォームの「レコードロック」プロパティを「すべてのレコード」に設定しているとか。

All Records(すべてのレコード)になっていました。
No LocksまたはEdited Recordに変更したら、Error3008が消えました。
つまり、解決しました。ありがとうございます。
そのプロパティをいじったことがなかったので、勉強します。

ソースオブジェクトをクエリにすると、フォームで使えるいろいろな機能が使えなくなる

そうなのですね。どういう弊害が出るのでしょうか。

15

弊害というかフォームで使える機能が使えないということです。
例えば、更新前に入力値をチェックするとか、いろいろ細かい制御がフォームならできます。

16
nokonoko 2020/08/28 (金) 11:34:11 653a6@54883

わかりました。ありがとうございました。