2017-10-12 5 views
0

私のペースト機能では、レコードを作成してすぐに後で編集できるようにする必要があります。これは、オートナンバー型フィールドに生成される値を知る必要があるためです。 私が得るエラーは、「AddNewまたはEditなしのUpdateまたはCancelUpdate」です。このエラーがコードサンプルでポップアップする場所をマークしました。レコードを作成した直後に編集する

貼り付け機能全体が貼り付けられている場合があります。私が正しく実行する方法がわからないコードは、最下位4位(***より下のすべて)です。

私がしようとしていることを正確に知りたいのであれば、それが十分でなければならないが、投稿の残りの部分を自由に読むことができます。

私がしようとしていることは、クリップボードの各レコードに対して、すべてのフィールドの値をコピーすることです。しかし、例外があります。対象となるのは、レコードが継承するレコードのESDNodeIDである、「ESDNodeID」および「ParentID」のオートナンバー型フィールドです。

コピー中の既存のノードのクリップボードはソートされているため、子レコードに親レコードがある場合、その親はリスト内の次の子レコードになります。ですから、私の考えは、レコードのidに対して生成されるAutoNumber値を、親ID(forループの次のものであるid + 1でなければなりません)のために見つけることができるということです。

Public Function Paste(nodeID As Long) 
    Dim currScenarioID As Long 
    Dim i As Long 
    Dim saveParentIDs As Collection 
    Set saveParentIDs = New Collection 
    currScenarioID = Forms("Main")!Scenarios!ScenarioID 

    Dim rstSource As DAO.Recordset 
    Dim rstInsert As DAO.Recordset 
    Dim fld   As DAO.Field 

    'We want to insert records into the ESDNodes table 
    Set rstInsert = CurrentDb.OpenRecordset("ESDNodes") 

    'We want to insert a record for each element in the clipboard 
    For i = 0 To UBound(clipboard) 
    'rstSource represents the record that we want to copy. Should only be 1 as ESDNodeID is unique. 
    Set rstSource = CurrentDb.OpenRecordset("SELECT * FROM ESDNodes WHERE ESDNodeID = " & clipboard(i)(0)) 
    rstSource.MoveFirst 
     With rstInsert 
      'create a new record 
      .AddNew 
       'Want to copy all the fields 
       For Each fld In rstSource.Fields 
       With fld 
        If .Name = "ESDNodeID" Then 
         'Skip Autonumber field 
        'If the field is the ParentID 
        ElseIf .Name = "ParentID" Then 
         'If the clipboard has a NULL value that means the node selected is the Parent 
         If IsNull(clipboard(i)(1)) Then 
          rstInsert.Fields(.Name).value = nodeID 
         'If the parent ID has already been created for another node, we want to grab that ID 

         ElseIf Contains(saveParentIDs, CStr(clipboard(i)(1))) Then 
          rstInsert.Fields(.Name).value = saveParentIDs(CStr(clipboard(i)(1))) 
         'If neither of these conditions pass, the parentID is handled after the for loop 
         End If 
        'We want the active scenario id 
        ElseIf .Name = "ScenarioID" Then 
         rstInsert.Fields(.Name).value = currScenarioID 
        'Copy all other fields direcly from record 
        Else 
         rstInsert.Fields(.Name).value = .value 
        End If 
       End With 
       Next 
       'If the parent ID was not set above, that means we have not yet created the record corresponding to its parentID 
       'But because of how our clipboard is sorted, it will be the next one in the loop. Meaning that we can create this new record 
       'with an empty parentID, and then predict the id of its parent by simply adding 1 to its id 

       '***************** 
       .Update 
       .MoveLast 
       If Not IsNull(clipboard(i)(1)) Then 
       If Not Contains(saveParentIDs, CStr(clipboard(i)(1))) Then 
        !parentID = !ESDNodeID + 1 'ERROR HERE 
        saveParentIDs.Add !parentID, CStr(clipboard(i)(1)) 
        .Update 
       End If 
       End If 
       .Close 
     End With 
    Next i 
    loadESDTreeView 
End Function 

答えて

1

既存のレコードセットフィールドを変更する前に、メソッド.Editを使用する必要があります。

またrstInsertForに閉じないと、次の行で失敗します。

さらに多くのものがあります。

は、私は全体的なアイデアをキャッチしていないが、あなたは.AddNew後に生成された、ちょうどESDNodeIDを読み取るために、それを編集する前に、最後の行に移動した場合、あなたは.MoveLast.Updateを使用する必要はありません、あなたが読むことができるかもしれませ新しいIDは.AddNewの直後にあります。

自動番号フィールド値の予測は、特にマルチユーザー環境では悪い考えです。

ParentIDは外部キー制約がESDNodeIDである必要があります。この場合、データベースにはまだ存在しないものを挿入することはできませんESDNodeID。この手順のロジックを見直してみてください。

+0

ご回答いただきありがとうございます。特に、データベースの完全性についてお聞かせください。私は外来キーの制約が可能であることを知らなかった。アルゴリズムをかなり変更して、はるかにエレガントでParentIDを推測しない再帰的なソリューションを選択しました。 –

関連する問題