문제

텍스트 녀석의 벽에 대해 죄송하지만이 하나는 설명해야합니다. 게시하기에는 너무 많은 코드가 필요합니다 ...

데이터 입력이 필요한 메소드에서 고정 너비 파일을 액세스로 가져오고 있습니다. TransferText를 사용하여 파일을 두 가지 사양 (글로벌, 다른 하나는 특별한 상황)으로 가져옵니다.

DAO를 사용하여 autoincrement PK를 포함한 중복 테이블을 구축하기 위해 DAO를 사용하여 이러한 레코드를 편집 할 수있는 기능이 있습니다. 삽입 된 상태에서 데이터를 해당 테이블에 밀어 넣습니다.

잘 작동합니다. 오류가 발견되고, 사용자는 400 개의 문자 라인을 통해 체로 치기를 비추고 예상되는 방식으로 모든 것을 재구성하는 데 수정하기 위해 데이터 입력으로 들어갑니다. 잘 작동합니다!

문제: 데이터 입력 변경이 이루어지면 커밋 버튼을 눌러 양식 외부 모듈 내부의 함수를 호출합니다. 데이터 입력 양식을 닫고 정보를 원래 테이블로 다시 눌러 자동화 된 PK를 뺀 다음 ID로 복제 된 테이블을 삭제하고 오류를 다시 검색하는 새 검색 테이블을 생성해야합니다.

원본으로 다시 밀려나하지만 ID 테이블을 떨어 뜨리지 않습니다. 이 테이블이 잠겨 있음을 나타내는 메시지와 함께 항상 나에게 반환합니다. Ive는 모든 기능/서브 종료 될 때까지 테이블이 무의식적으로 잠겨 있음을 알았습니다. 언제든지 코드를 통과 할 때는 수동으로 삭제할 수 없습니다. 실행이 완료되면 제거 할 수 있습니다.

나는 양식의 명령을 통해 이것을 호출했기 때문에 모든 코드가 끝날 때까지 잠금이 해제되지 않으며 양식이 종료 될 수 있다고 가정합니다. 이견있는 사람? 예, 이것은 매우 야만적이지만 아주 잘 작동합니다.이 다른 테이블을 지구에서 찢어서 업데이트 된 사본을 다시 찍을 수 있어야합니다 ...

최악의 경우 사용자가 양식을 닫고 기본 형식의 다른 버튼을 누르도록 할 수 있지만 사용자 컴퓨팅을 염두에두고 크게 설계되었습니다. 그러나 이것은 이제 나의 모든 관심을 가지고 있으며 최적의 솔루션이 아니더라도 최소한 솔루션을 찾고 싶습니다.

-편집하다-

이 문제에는 두 가지 형태가 사용됩니다

FormA (Role: Load in and search for problems)

Examine button is pressed that:

 - Uses TextTransfer based on predefined specs into tempExtract to
       import the file

 - DAO fires off on the Fields collection in tableDefs for
   tempExtract, creates new table tempExtractID

 - Performs searches through the file to find errors.  Errors are saved to
   a table Problem_t.  Table contains Problem_ID (Set from the ID field
   added to tempExtractID) and Description

 - Execution of these tasks is successfully requerying the initial
   form to showing a list of problems and number of occurances.  A button
   gains visibility, with onClick that opens the form DataEntry.            

 - At this point in the code after DAO execution, I can DROP the table
   tempExtractID.  DAO is NOT used again and was only used to build a new table.

formb- 데이터 입력 양식

이 양식을 열 자마자 테이블 tempextractid가 잠겨 테이블을 떨어 뜨릴 수 없습니다. Records는 recorses querys tempextractids indsuestion_t에 대해 querys tempextract에 대해 소송을 제기하여 키에 필요한 것만 반환합니다.

양식이 완전히 종료 될 때까지 테이블을 떨어 뜨릴 수 없습니다. 데이터 입력 양식의 버튼은 변경 사항을 커밋하도록 눌렀습니다. 5 잠금 오류가 발생하기 전에 해고되는 코드 줄.

*Xargs refers to the list of Field names pulled earlier through DAO.  As DAO loops through Field objects, the physical names are added to an Xargs String which is placed in this table.  Basically everything but the AutoNumber is being inserted back

    docmd.Close acForm, "frmDataEntry", acSaveNo
    call reInitializeExtract
         > docmd.RunSQL "DELETE FROM tempExtract"
         > docmd.RunSQL "INSERT INTO tempExtract SELECT (" & DLookup("Value", "CONFIG_t", "Item = 'Xargs'" & ") FROM tempExtractID"
    docmd.DeleteObject acTable, "tempExtractID"

이것은 양식이 열리는 시간 (테이블이 처음 고정 된 위치) 사이에 실행되는 유일한 코드이며 모든 서브 및 기능이 완료 될 때까지 계속 잠겨 있습니다.

도움이 되었습니까?

해결책

양식의 레코드 소스를 vbnullstring으로 설정 한 다음 테이블을 삭제하는 것이 좋습니다. 이 테이블에 콤보 박스 등이 없다면 이것은 작동해야합니다.

다른 팁

코드가 없으면 말하기는 어렵지만 DAO를 사용하는 경우 코드 객체를 정리해야합니다. 즉, 데이터베이스 개체를 아무것도 설정하지 않고 닫고 레코드 세트 객체를 닫고 설정하는 것을 의미합니다.

  Dim db As DAO.Database
  Dim rs As DAO.Recordset

  Set db = DBEngine.OpenDatabase("[path to database]")
  Set rs = db.OpenRecordset("[SELECT statement]")
  rs.Close
  Set rs = Nothing
  db.Execute("[DML or DDL statement]", dbFailOnError)
  db.Close
  Set db = Nothing

  Set db =CurrentDB
  Set rs = db.OpenRecordset("[SELECT statement]")
  rs.Close
  Set rs = Nothing
  Set db = Nothing  ' you don't close a db variable initialized with CurrentDB

VBA는 범위를 벗어날 때 이러한 객체를 정리해야하지만 100% 신뢰할 수있는 것은 아닙니다 (VBA 정리되었습니다).

열린 객체는 잠금의 가장 가능성이 높은 소스이므로 객체 변수를 완료 한 후에는 객체 변수를 정리해야합니다.

docmd.runsql을 사용하는 것을 본 후 편집 :

docmd.runsql을 사용하는 것이 문제의 원인 일 수 있습니다. 그것은 당신의 연결에 대한 프로그래밍 방식의 관리를 제거하는 것입니다. 대신 DAO를 사용하면 연결을 제어 할 수있을뿐만 아니라 DOCMD.RUNSQL의 실제 함정을 피할 수 있습니다. 이는 오류를 처리하지 않습니다. DML 또는 DDL 문을 완전히 완료 할 수없는 경우 모든 것이 실패해야합니다. 예를 들어, 100 개의 레코드를 추가하고 100 개의 레코드를 추가하고 주요 위반에 실패하는 경우 DocMd.Runsql은 90을 투명하게 추가하고 10 가지 실패를보고하지 않습니다. 업데이트 및 기타 DML/DDL 문과 동일합니다. docmd.runsql "유용하게"가능한 한 많은 업데이트를 조용히 완료하여 일부가 완료되지 않았다는 것을 알지 못합니다.

물론, 어떤 경우에는 PK 충돌이있을 수 있고 CPU 사이클을 외부 조인에 소비하고 싶지 않은 레코드를 부여하는 경우, 레코드 세트에서 복제물을 제거합니다. 당신은 추가 중입니다.

그러나 대부분의 경우에는 그렇지 않습니다.

위의 의견에서 말했듯이 Docmd.runsql을 투명하게 대체하도록 설계된 함수를 사용하고 DAO 실행 명령문 및 오류 처리를 사용합니다. 나는 그것을 두 번 게시했다 (여기 하나가 있습니다), 그리고 현재 가장 활발한 개발 프로젝트에서 제작에 사용 된 버전은 다음과 같습니다.

  Public Function SQLRun(strSQL As String, Optional db As Database, _
       Optional lngRecordsAffected As Long) As Long
  On Error GoTo errHandler
    Dim bolCleanup As Boolean

    If db Is Nothing Then
       Set db = CurrentDb
       bolCleanup = True
    End If
    'DBEngine.Workspaces(0).BeginTrans
    db.Execute strSQL, dbFailOnError
    lngRecordsAffected = db.RecordsAffected
    'DBEngine.Workspaces(0).CommitTrans

  exitRoutine:
    If bolCleanup Then
       Set db = Nothing
    End If
    SQLRun = lngRecordsAffected
    'Debug.Print strSQL
    Exit Function

  errHandler:
    MsgBox "There was an error executing your SQL string: " _
       & vbCrLf & vbCrLf & Err.Number & ": " & Err.Description, _
       vbExclamation, "Error in SQLRun()"
    Debug.Print "SQL Error: " & strSQL
    'DBEngine.Workspaces(0).Rollback
    Resume exitRoutine
  End Function

(거래는 문제를 해결할 시간이없는 문제를 일으키기 때문에 언급됩니다)

이 라인을 교체 할 수 있습니다.

  DoCmd.RunSQL "DELETE FROM tempExtract"
  DoCmd.RunSQL "INSERT INTO tempExtract SELECT (" _
    & DLookup("Value", "CONFIG_t", "Item = 'Xargs'" & ") FROM tempExtractID"

... 이것으로 :

  SQLRun "DELETE FROM tempExtract"
  SQLRun "INSERT INTO tempExtract SELECT (" _
    & DLookup("Value", "CONFIG_t", "Item = 'Xargs'" & ") FROM tempExtractID"

당신은 또한 이것을 할 수 있습니다 :

  Debug.Print SQLRun("DELETE FROM tempExtract") & " records deleted."
  Debug.Print SQLRun("INSERT INTO tempExtract SELECT (" _
    & DLookup("Value", "CONFIG_t", "Item = 'Xargs'" _
    & ") FROM tempExtractID") & " records inserted."

함수는 각 실행에 대해 .recordSaffrected를 반환하기 때문에 바로 즉시 창에 인쇄하거나 리턴 값을 변수에 할당하거나 기존 변수를 통과하여 해당 변수로 작업 할 수 있습니다.

  Dim lngRecordsAffected As Long
  ...
  Call SQLRun("DELETE FROM tempExtract", , lngRecordsAffected)
  Debug.Print lngRecordsAffected & " records deleted."
  Call SQLRun("INSERT INTO tempExtract SELECT (" _
    & DLookup("Value", "CONFIG_t", "Item = 'Xargs'" _
    & ") FROM tempExtractID", , lngRecordsAffected)
  Debug.Print lngRecordsAffected & " records inserted."

요점은 실행 명령문에 오류가 있으면 모든 것이 실패한다는 것입니다 (오류 메시지가 나타나면 오류가 있으면 오류가 있으면 -1 또는 일부를 팝업하는 대신에 반환 할 수 있습니다. msgbox).

사전 준비된 데이터베이스 변수를 전달 하여이 기능을 가장 자주 사용하므로 나중에 정리하고 싶지 않습니다. CurrentDB () 이외의 다른 데이터베이스를 사용하는 경우 실제로 외부 DB를 가리키는 데이터베이스 변수가 닫히고 아무것도 설정하지 않도록해야합니다. 그 없이는 잠금이 최상위 데이터베이스 개체에서 유지되며 LDB 파일은 열려 있고 활성화되어 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top