5

親レコードが作成されていない場合、Excel から Access サブフォームにセルをコピー/貼り付けすると、予想どおりエラーが発生します。

問題は、このエラーが発生した後、アクセスがロックされ、入力された後続のすべてのデータが「トランザクションでサポートされていない操作」エラーになることです。テーブルを開くと、新しく追加されたデータがまだテーブルにないことがわかります。そのため、Access が実際に何らかのトランザクションを行っているように見えます。

私は 'Save' .. 'Refresh' .. を押して commitTrans() を強制するために AfterInsert イベントを追加しようとしましたが、運がありませんでした - そして Access は進行中のトランザクションがないと主張します

レコードが手動で入力されている場合、エラーはありません。この問題は、レコードを貼り付けるときにのみ発生するようです。Access が複数のレコード操作を処理するトランザクションを作成しており、エラーから適切に回復していないと推測しています。

「必須」フラグを削除すると機能しますが、孤立したレコードができます。After Insert Data Macro を使用して、デフォルトのバッチ名で新しいバッチを追加し、新しい BatchID を Items テーブルに自動入力できるのではないかと考えていました。ただし、それがどのように行われるかはわかりません。

「必須」フラグを削除し、Before Change Data マクロを使用してエラーをトラップしようとしましたが、エラーを削減しましたが、それでも同じOperation not supported in transactionsエラーが発生しました。

Microsoft Knowledgebase でエラーを調べましたが、私の状況に固有のものは見つかりませんでした。エラーメッセージをstackoverflowで検索しましたが、何も見つかりませんでした。

新しいデータベースを作成し、問題を再現できました。

複製する手順

データベースのセットアップ

  1. Access 2010 で新しい ACCDB データベースを作成する
  2. 次のフィールドを使用して、「バッチ」という名前のテーブルを作成します。
    • BatchID (オートナンバー) (主キー)
    • バッチ名 (テキスト)
  3. 次のフィールドを持つ「Items」というテーブルを作成します。
    • RecordID (オートナンバー) (主キー)
    • BatchID (長整数)
      • 必須属性を True に設定
    • データ - テキスト
  4. リレーションシップを作成し、Batches.BatchID を Items.BatchID にリンクします
    • バッチからのすべてのレコード、およびアイテムからの一致するレコードを含める
    • 参照整合性の強制
    • カスケード更新/削除
  5. 「フォーム」という名前のフォームを作成します
    • レコードソースをバッチに設定する
    • BatchID と Batch name テキスト ボックスを追加します。
    • サブフォーム/サブレポート コントロールに追加する
      • ソースオブジェクトを「Table.Items」に設定
      • リンクマスターフィールドを「BatchID」に設定
      • リンクの子フィールドを「BatchID」に設定します
      • 「空のマスターでフィルター」を設定 = はい
  6. サンプルデータの作成(フォームを使用)
    • バッチで新しいレコードを作成します。
      • BatchName = "Test" を設定
    • アイテムに新しいレコードを作成します。
      • バッチ レコードを参照します。
      • 設定データ = "テスト"

ご覧のとおり、これは手動でうまく機能します。

Excel からのデータのコピーと貼り付け

  1. エクセルで
    • A1 から A10 まで、セルごとに 1 つの文字を入力します: A、B、C、D、E、F、G、H、I、J
    • セル A1 ~ A10 を強調表示します
    • コピー (Control+C)
  2. Access では、フォームを使用して:
    • 新しいバッチ レコードを追加します。BatchID TextBox に "(New)" と表示されるはずです
    • バッチ名を入力しないでください
    • サブフォームで、新しいレコードのレコード セレクター (*) をクリックして、行全体を選択します。Control+V を入力して貼り付けます。
    • 「'Data.BatchID' フィールドに値を入力する必要があります。」エラー に対して [OK ] をクリックします。
      • このエラーが繰り返される場合があります。[OK] をクリックし続ける
      • 「これ以上エラー メッセージを表示しないようにしますか...」と尋ねられたら、「はい」と答えます。
    • 「Microsoft Access が貼り付けることができなかったレコードは、'貼り付けエラー' という名前の新しいテーブルに挿入されました」の [OK] をクリックします。通知
    • バッチ名のテキスト ボックスに「TestName」と入力します。
    • 優雅に回復してみてください。エスケープを押します。レコードを変更します。

この時点で、入力された BatchID、バッチ名、および新しいデータが表示されます。すべて期待どおりに機能しているようです。更新または別のバッチ レコードに移動しようとすると、Operation not supported in transactionsというエラーが表示されます。Access は、フォームを閉じて再度開くまで、このエラー メッセージを表示し続けます。貼り付けたデータは、データベースには作成されません。

通常、少し技術に精通している人は、何かがうまくいかないことに気づき、データベースを閉じて再び開きます...しかし、残念ながら、ポップアップボックスで「もぐらたたき」をしてから試してみるユーザーがいます続けます - だから私は物事を可能な限り防弾にしたいと思います.

望ましい解決策

この問題の回避策が必要です。最終的には、アクセスや値の重複などの他の癖につながることはありません。

私自身の経験では、VBA を使用してキーを「修正」することは信頼できません。データ マクロの方がはるかに信頼性が高いようですが、セットアップが難しい場合があります。まだあまり主流ではありません ( stackoverflowに ms-access-data-macrosタグがあるべきだと思いますが、ありません) 。まだ)

4

5 に答える 5

1

これが古い話であることは知っていますが、私もこれに苦労していました。私の解決策は、挿入されたレコードを保存するために、ユーザーがデータを受け取ったフォームを閉じるようにプロセスを再設計することでした。エレガントではありませんが効率的であり、発生する可能性のあるすべてのイベントを推測する必要がありませんでした。

于 2014-09-16T07:17:42.620 に答える
1

このエラーの原因が何であるかを最終的に理解するまで、私はこれに長い間苦労しました。詳細を説明するには、ブログの回答ではなく、かなり長い記事が必要です. 興味のある方は連絡方法を残していただければ、詳しくご説明いたします。ただし、これを理解したい人のために、問題の背後にあるアイデアを提供することで、多くの時間を節約できます。バインドされたサブフォームでデータ トランザクションを実行している場合、他のオブジェクトを参照することはできません。トランザクション プロセスの内部コードでは、これが許可されていません。たとえば、サブフォーム データ トランザクションの最中に別のフォームを開こうとするコードが Form_BeforeUpdate イベントにある場合、エラー 3246 が発生します。サブフォーム コントロールなどを参照しますが、別のオブジェクトに移動することはできません。これは考えてみれば当然のことです。ユーザーまたはコードが別のフォームまたはオブジェクトに入ると、ユーザーまたはコードが何をするかは誰にもわかりません。二度と戻らないか、トランザクションをハングさせたままにする他のエラーに巻き込まれる可能性があります。そのため、トランザクションを最初に完了する必要があります。これは、ユーザーがトランザクション中にサブフォームの外側の領域をクリックしようとしたときに発生するエラー 2115 をトラップして無視する必要があることを意味します。これは通常、ユーザーが入院したり、サブフォーム トランザクションの最中に別のレコードに進み始めたりする大規模なコピー アンド ペースト中に発生します。ユーザーまたはコードが別のフォームまたはオブジェクトに入ると、ユーザーまたはコードが何をするかは誰にもわかりません。二度と戻らないか、トランザクションをハングさせたままにする他のエラーに巻き込まれる可能性があります。そのため、トランザクションを最初に完了する必要があります。これは、ユーザーがトランザクション中にサブフォームの外側の領域をクリックしようとしたときに発生するエラー 2115 をトラップして無視する必要があることを意味します。これは通常、ユーザーが入院したり、サブフォーム トランザクションの最中に別のレコードに進み始めたりする大規模なコピー アンド ペースト中に発生します。ユーザーまたはコードが別のフォームまたはオブジェクトに入ると、ユーザーまたはコードが何をするかは誰にもわかりません。二度と戻らないか、トランザクションをハングさせたままにする他のエラーに巻き込まれる可能性があります。そのため、トランザクションを最初に完了する必要があります。これは、ユーザーがトランザクション中にサブフォームの外側の領域をクリックしようとしたときに発生するエラー 2115 をトラップして無視する必要があることを意味します。これは通常、ユーザーが入院したり、サブフォーム トランザクションの最中に別のレコードに進み始めたりする大規模なコピー アンド ペースト中に発生します。これは、ユーザーがトランザクション中にサブフォームの外側の領域をクリックしようとしたときに発生するエラー 2115 をトラップして無視する必要があることを意味します。これは通常、ユーザーが入院したり、サブフォーム トランザクションの最中に別のレコードに進み始めたりする大規模なコピー アンド ペースト中に発生します。これは、ユーザーがトランザクション中にサブフォームの外側の領域をクリックしようとしたときに発生するエラー 2115 をトラップして無視する必要があることを意味します。これは通常、ユーザーが入院したり、サブフォーム トランザクションの最中に別のレコードに進み始めたりする大規模なコピー アンド ペースト中に発生します。

于 2014-05-03T02:02:51.280 に答える
0

望ましくない内部トランザクションを回避するには、サブフォームのエラー イベントを次のようにコーディングするだけで十分です。

Private Sub Form_Error(DataErr As Integer, Response As Integer)

    Response = acDataErrContinue

End Sub

サブフォーム イベントを傍受するための一般的な方法は次のとおりです。

' parent form code
' ---------------------------------------------------
Private WithEvents subFormObj As [Form_Sottomaschera items]

Private Sub Form_Open(Cancel As Integer)

    Set subFormObj = Me.Sottomaschera_items.Form

End Subcode here

' asynchronous way
Private Sub subFormObj_isInserting()

    Me.batchName = vbNullString         ' this resolves the new ID issue

End Sub

' synchronous way
Public Sub subFormInserting()

    Me.batchName = vbNullString

End Sub

' sub-form code
' ---------------------------------------------------
Public Event isInserting()              ' for asynchronous way

Dim parentFormObj As Form_Maschera1     ' for synchronous way

Private Sub Form_BeforeInsert(Cancel As Integer)

    parentFormObj.subFormInserting
    RaiseEvent isInserting
'    Cancel = True

End Sub

Private Sub Form_Error(DataErr As Integer, Response As Integer)

    Response = acDataErrContinue

End Sub

Private Sub Form_Open(Cancel As Integer)

    Set parentFormObj = Me.Parent

End Sub

[Maschera1]メインフォームと[Sottomaschera items]サブフォームはどこにありますか。

残念ながら、貼り付けの問題は解決しません。

SetFocus問題を確実に解決するには、親レコードとトリックを同期または非同期で保存する必要があります。

Private Sub subFormObj_isInserting()

    Me.batchName = vbNullString
    DoCmd.RunCommand acCmdSaveRecord
'    DoEvents
    Me.batchName.SetFocus

End Sub

Public Sub subFormInserting()

    Me.batchName = vbNullString
    DoCmd.RunCommand acCmdSaveRecord
'   DoEvents
    Me.batchName.SetFocus

End Sub
于 2013-11-09T18:30:30.270 に答える