2009-10-30 7 views
3

후 꽉 잠겨있다 그러나 이것은 너무 많은 코드를 게시, expliaining 필요 데이터 입력이 필요한 메소드에서. transferText를 사용하여 파일을 두 개의 사양 (전역, 다른 하나는 특수 상황)으로 가져옵니다.양식 내 테이블도 텍스트 사람의 벽 죄송 docmd.close

나는이 레코드를 편집 할 수 있도록 AutoIncrement PK를 포함하는 중복 테이블을 만들기 위해 DAO를 사용하여 TableDefs의 모든 Field 개체를 순환하는 기능을 가지고 있습니다. 필자는 INSERT INTO를 사용하여 테이블에 데이터를 푸싱합니다.

훌륭한 작품입니다. 오류가 발견되면 사용자가 데이터 입력을 통해 수동으로 수정하여 400 자의 문자 행을 탐색하고 예상대로 모든 것을 재구성합니다. 위대한 작품!

문제 : : 데이터 입력이 변경되면 양식 외부의 모듈 내부에서 함수를 호출하는 커밋 버튼이 눌러집니다. 데이터 입력 폼을 닫고 원래 테이블에서 자동 증가 된 PK를 뺀 정보를 다시 푸시하고 ID가있는 복제 된 테이블을 DROP하도록 지원되며 오류를 다시 검색하여 새로운 테이블을 생성합니다 ...

푸시 원본으로 돌아 가면 ID 테이블을 삭제하지 않습니다. 항상이 테이블이 잠겨 있다는 메시지와 함께 나에게로 돌아온다. 필자는 모든 기능/서브가 종료 될 때까지 테이블이 indefiniatly 잠겨 있음을 알았다. 언제든지 코드를 단계별로 수동으로 삭제할 수 없으며 일단 실행이 완료되면 제거 할 수 있습니다.

나는 이것을 폼에서 명령으로 호출 했으므로 모든 코드가 끝날 때까지 잠금이 해제되지 않고 양식이 종료되고 그 일을 할 수 있다고 가정합니다. 이견있는 사람? 예, 이것은 매우 야만적이지만 잘 작동합니다. 업데이트 된 복사본을 다시 그릴 수 있도록 행성에서이 다른 테이블을 찢을 수 있어야합니다 ...

최악의 경우 사용자를 닫을 수 있습니다. 양식을 작성하고 기본 양식에있는 다른 버튼을 누르십시오. 그러나 이것은 사용자 compitence를 염두에두고 많이 고안되었습니다. 그러나 이것은 이제 내 모든 관심을 가지고 최선의 해결책이 아니더라도 적어도 해결책을 찾고 싶습니다.

-EDIT-

두 가지 형태가

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이 고정되고 나는 테이블을 떨어 뜨릴 수 없다. 폼에 대한 레코드 소스는 Problems_t의 ID에 대해 tempExtractID를 쿼리하여 키를 입력해야하는 항목 만 반환합니다.

양식이 완전히 종료 될 때까지 표를 삭제할 수 없습니다. 데이터 입력 폼의 버튼을 눌러 변경 내용을 커밋합니다. 잠금 오류가 발생하기 전에 코드 행만 실행됩니다.

*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" 

이 (테이블이 먼저 고정됩니다) 양식을 열 시간 사이에 실행 & 기능을 완료 한 모든 서브 때까지 잠금이 계속되는 유일한 코드입니다.

+0

Q1 :이 문제는 일관 적이거나 간헐적입니까? 간헐적으로 ldb 파일의 대기 시간이 발생할 수 있습니다. 질문 2 : 왜 트랜잭션 처리 *** expression.RunSQL (SQLStatement, UseTransaction) ***? 아마도 이것은 롤백을 용이하게 할 수 있습니다. 또한 ** [docmd의 제한 사항] (http://support.microsoft.com/kb/89587) ** Access97 또는 이전 버전을 사용하는 경우 – heferav

+0

문제가 일관되고 이러한 파일의 특성으로 인해 조합이 기본 키로 설정되었을 수 있으므로 고유 한 식별자가 없기 때문에 양식을 통해 데이터를 변경할 수 없으므로 이러한 레코드를 이동해야했습니다. Access 2000 및 docmd.runsql drop table과 DBEngine을 사용하여 테이블을 지우는 것은 물론 테이블을 수동으로 이동하고 양식이 올라가고 코드가 빠져 나가는 동안 삭제하려고 시도했습니다 요새 knox보다 : ( – Mohgeroth

+0

) DoCmd.RunSQL 사용을 중단하십시오 - 오류를 무시하기 때문에 신뢰할 수없는 결과를 생성합니다. 사용하기 쉬운 대안은 내 SQLRun() 함수입니다 : http://stackoverflow.com/questions/343396/how -a-get-a-value-from-the-update-query-prompt-in-access-vba/348453 # 348453 - 기능이 마음에 든다면, 원래 버전은 그것이 투표에 부쳐졌고 그때 투표자가 돌아 오지 않고 수정에 응답하지 않았다. –

답변

5

폼의 recordsource를 vbNullString으로 설정 한 다음 테이블을 삭제하는 것이 좋습니다. 이 테이블에 콤보 박스 등이 바인딩되어 있지 않으면이 작업이 가능합니다.

+0

내가 오늘 들어갈 때 나는 그 기회를 줄 것이다 – Mohgeroth

+0

해결 된 주 전, 받아 들여진 대답을 게시하는 것을 깜박했다. , 이것은 트릭 감사를 했어! – Mohgeroth

4

코드가 없으면 DAO를 사용하는 경우 코드 개체를 정리해야합니다. 즉, 데이터베이스 개체를 Nothing으로 설정하고 닫고 Nothing으로 설정하는 것은 모든 레코드 집합 개체를 의미합니다. VBA는 개체가 해제 할 수 있는지 여부를 추적하기 위해 참조 카운팅을 사용하고 있기 때문에 VBA 그들이 범위 밖으로 갈 때 이러한 개체를 정리하도록되어 있지만

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 

, 그것은 100 % 신뢰할 수 없습니다입니다 (그렇지 않습니다 모든 참조가 언제 지워 졌는지 항상 알 수 있습니다).

열려있는 객체가 잠금의 가장 일반적인 원인이므로 객체 변수를 모두 마친 후에는 객체 변수를 정리해야합니다. 당신이 DoCmd.RunSQL을 사용하고 있는지보고 후

편집 : DoCmd.RunSQL를 사용

가능성이 문제의 원인입니다. 그것은 확실히 당신의 연결에 대한 프로그래밍 방식의 관리를 제거하는 것입니다. 대신 DAO를 사용하면 연결을 제어 할 수있을뿐만 아니라 DoCmd.RunSQL의 실제 함정을 피할 수 있습니다. 즉, 오류를 처리하지 않습니다. DML 또는 DDL 문을 성공적으로 완료 할 수 없으면 모든 작업이 실패합니다. 예를 들어, 100 개의 레코드를 추가하는 중 10 개가 키 위반에 실패하면 DoCmd.RunSQL은 90을 추가하고 10 개의 FAILURES를보고하지 않습니다. 업데이트 및 다른 DML/DDL 문과 동일합니다. DoCmd.RunSQL은 "유용하게"가능한 많은 업데이트를 자동으로 완료하므로 일부를 완료하지 못했다는 것을 알지 못합니다.

허용되는 경우가 있습니다. 예를 들어 PK 충돌이있는 것으로 알고있는 레코드를 추가하고 외부 조인에서 중복을 제거하는 CPU 사이클을 사용하지 않으려는 경우 추가하는 레코드 세트.

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

내가 위에서 언급 한 것처럼 DoCmd.RunSQL을 투명하게 바꾸기 위해 설계된 함수를 사용하고 DAO Execute 문과 오류 처리를 사용합니다. 그들은 문제가 발생했기 때문에

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 

가 (트랜잭션이 주석 처리되어 : 내 현재 가장 적극적인 개발 프로젝트에서 생산 사용에 내가 가지고있는 버전이 SO (here's one)에 몇 번 게시하고, 여기있다 이와 함께 ...

DoCmd.RunSQL "DELETE FROM tempExtract" 
    DoCmd.RunSQL "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." 

를 함수가 각 사용자가 직접 실행 창에 인쇄 할 수 있습니다, 또는 당신은 변수에 반환 값을 할당하거나 전달할 수, 실행에 대한 .RecordsAffected을 반환한다 - 당신에게 할 수 있습니다

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를 가리키는 데이터베이스 변수가 닫혀 있는지 확인하고 Nothing으로 설정해야합니다. 이 기능이 없으면 최상위 데이터베이스 개체에서 잠금이 유지되고 LDB 파일은 열린 상태로 유지됩니다.