2017-10-12 180 views
0

對於我粘貼功能後,馬上編輯記錄,我需要能夠創造一個紀錄,之後立即進行編輯。這是因爲我需要知道爲AutoNumber字段生成的值。 我得到的錯誤是「Update或CancelUpdate without AddNew or Edit」。我標記了在我的代碼示例中彈出此錯誤的位置。在某些情況下創建它

我的情況下,它可能有助於粘貼我整個粘貼功能。雖然我不確定如何正確執行的代碼位於最後4位(***以下的所有內容)。

如果你想知道什麼,我試圖做隨意閱讀後的休息,雖然它應該是沒有足夠的。

本質上講,我試圖做的是在我的剪貼板中的每條記錄,我想讓它的一個副本 - 複製所有字段的值。但也有例外。感興趣的是AutoNumber字段,「ESDNodeID」和「ParentID」,它是記錄繼承的記錄的ESDNodeID。

已存在的正在複製的節點的剪貼板(其中包含ESDNodeID和ParentID)將進行排序,以便如果子記錄具有父記錄,則其父項是列表中的下一個記錄。所以我的想法是我可以使用爲記錄的id生成的AutoNumber值來找出它的父id(它應該是它的id + 1,因爲它是for循環中的下一個)。

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

也不要關閉rstInsert裏面For,它會在下一行失敗。

幾件事。

可能是我沒趕上的整體思路,但是如果你編輯它以剛讀ESDNodeID.AddNew後產生前移到最後一行,則不需要使用.Update.MoveLast,你可以閱讀新的Id在.AddNew之後,它是可用的。

預測自動編號字段的值是壞主意,尤其是在多用戶環境。

數據庫的完整性非常重要,所以ParentID應該在ESDNodeID上有外鍵約束,在這種情況下數據庫不允許插入不存在的ESDNodeID。試着回顧一下這個過程的邏輯。

+0

感謝您的回覆,特別是關於數據庫完整性的一點。我不知道外鍵約束是可能的。我改變了我的算法很多,選擇一個更優雅的遞歸解決方案,並且不會猜測ParentID。 –

相關問題