Do While loop hangs - database

The loop below hangs if the input fufills the Do...While condition.
This code is meant to first check if the entered product code in the combobox (Me!Combo_Product_number) exists in product code field of query Q_compliant_FCM_EU.
If it exists, it tests for compliance. The product is compliant if all its PURE_QP1 (which can be more than one for a particular product) is found in PURE_QP1 field of T_DOSSIER_FPL.
If at least one of them is not found, then it is not compliant.
Private Sub Command455_Click()
Dim db As DAO.Database
Dim rst As Recordset
Dim rst1 As Recordset
If Nz(Me!Combo_Product_number) <> "" Then
Set db = CurrentDb
Set rst = db.OpenRecordset("Q_compliant_FCM_EU", dbOpenDynaset)
Set rst1 = db.OpenRecordset("T_DOSSIER_FPL", dbOpenDynaset)
rst.FindFirst "[PRODUCT_CODE] = '" & Me!Combo_Product_number & "'"
If Not rst.NoMatch Then
Do While Not rst1.EOF
rst1.FindFirst "[PURE_QP1] = '" & rst.Fields("PURE_QP1") & "'"
If Not rst1.NoMatch Then
rst1.MoveNext
Else
MsgBox ("Product code is NOT compliant to FPL")
Exit Sub
End If
Loop
MsgBox ("Product code is compliant to FPL")
Else
MsgBox ("Product code is not available")
End If
End If
End Sub
What is wrong with the above code?

Use DLookup for such simple tasks, like:
Dim PURE_QP1 As Variant
If Nz(Me!Combo_Product_number) <> "" Then
PURE_QP1 = DLookup("[PURE_QP1]", "[Q_compliant_FCM_EU]", "[PRODUCT_CODE] = '" & Me!Combo_Product_number & "'")
If IsNull(PURE_QP1) Then
MsgBox ("Product code is not available")
Else
If IsNull(DLookup("[ID field of T_DOSSIER_FPL]", "[T_DOSSIER_FPL]", "[PURE_QP1] = '" & PURE_QP1 & "'")
MsgBox ("Product code is NOT compliant to FPL")
End If
End If
End If

Related

How do I capture a specific SQL Server Error In Access VBA That Is Missing the Access Error Code?

I have a login form in Access that sends the username and pwd to an ODBC connection string to connect to a SQL Server (Express) onsite. If they type the credentials in wrong I'd like a custom msgbox to come up rather than these 4 window messages from SQL Server and Access freaking out telling the user they didn't type something in correctly. Since there isn't an Access error message in the first two I'm not sure how to intercept them and put something there in it's place.
Here is the error handling I have, which normally works for me with everything, but not for SQL Server:
Private Sub cmdLogin_Click()
'Stop
On Error GoTo Err_Login
Dim varUserName As String
Dim varPassword As String
Dim vardim As String
Dim varCreds As String
varUserName = Me.txtUserName
varPassword = Nz(Me.txtPassword, vbNullString)
varCreds = "UID=" & varUserName & ";PWD=" & varPassword
strConnection = "ODBC;Driver=SQL Server;Server=serverip\database;" & varCreds & ";APP=2007 Microsoft Office system;DATABASE=database"
Dim dbCurrent As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set dbCurrent = DBEngine(0)(0)
Set qdf = dbCurrent.CreateQueryDef("")
Dim td As TableDef
strsql = "SELECT * FROM ActiveTablesToLink WHERE LinkFlag = -1 And DatabaseName = 'database'"
Set recLocal = CurrentDb.OpenRecordset(strsql)
recLocal.MoveLast
recLocal.MoveFirst
strRecCount = recLocal.RecordCount
If strRecCount > 0 Then
Do While Not recLocal.EOF
stLocalTableName = recLocal!LocalTableName
stRemoteTableName = recLocal!SSTableName
Set td = CurrentDb.CreateTableDef(stLocalTableName, dbAttachSavePWD, stRemoteTableName, strConnection)
CurrentDb.TableDefs.Append td
recLocal.MoveNext
Loop
Else
End If 'Empty recordset
recLocal.Close
Application.RefreshDatabaseWindow
DoCmd.Close acForm, "Login"
Exit_cmdLogin: ' Label to resume after error.
Exit Sub
Err_Login:
MsgBox Err.Number & ": " & Err.Description
Call LogError(Err.Number, Err.Description, "SelectAll()")
Resume Exit_cmdLogin
End Sub
Here are the 4 messages that popup with bad credentials in the order they appear:
Any help is greatly appreciated.
To test User/Password, use a QueryDef beforehand to test the connection.
Don't try to create the linked table before that.
' Create a simple Pass-Through query
Set qdf = dbCurrent.CreateQueryDef("")
With qdf
.Connect = strConnection
.ReturnsRecords = True
.Sql = "SELECT GETDATE() AS Test"
' Try to connect, this will raise a trappable ODBC error if User/Password are wrong
On Error Resume Next
Set rst = .OpenRecordset(dbOpenSnapshot)
If Err.Number <> 0 Then
MsgBox "Wrong User/Password."
' etc.
End If
End With
On Error GoTo ErrHandler
This is the kind of error handling i would use to try and capture both applications errors
If DBEngine.Errors.Count > 1 Then
'ODBC Error
For Each errany In DBEngine.Errors
msgbox "ODBCExecute: Err# " & errany.Number & " raised by " _
& errany.Source & ": " & errany.Description, _
vbCritical, "cmdExecuteAttached()"
Next errany
Else 'Access Error
msgbox "ODBCExecute: Err# " & ERR.Number & " raised by " _
& ERR.Source & ": " & ERR.Description, _
vbCritical, "cmdExecuteAttached()"
End If
GoTo Exit_Sub
Resume

Doing stuff for each record in a recordset

I'm working on some code that checks a database for a specific value and returns a string under certain conditions.
I cannot get this code to iterate to the next row in my database results. It appears that my code only checks the first record of the recordset and then continues.
Sometimes my recordset may only have one row, but sometimes it may have many rows. If any of the rows of this recordset have a certain value I want to throw a MsgBox. Not just the first or last record.
Here's my code:
'Database Connection Strings.
strServerName = "string"
strDatabase = "string"
strUserName = "string"
strPassword = "string"
'Connection string for SQL Server.
strConn = "Driver={SQL Server};Server=" & strServerName & ";Database=" & strDatabase & ";Uid=" & strUsername & ";Pwd=" & strPassword & ";"
'Create required objects for the session.
Set WShell = CreateObject("WScript.Shell")
Set db = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
'Create the array of reciever lines and count them.
Set arrayLine = LINES.Value
intNumOfLines = arrayLine.Count
intLineNum = Cint(intNumOfLines)-1
cleanPN2 = array()
skipArray = array("-", " ", "PLATE", "HEAT-TREAT", "PAINT", "MACHINE", "WELD", "MPI")
result = MsgBox ("Scan PO for cert requirements?", vbYesNo, "PO Requirement Scanner")
Select Case result
Case vbYes
'Iterate through the reciever lines and look for part numbers.
For intLineNum = 0 To intNumOfLines
If intLineNum = intNumOfLines Then
Exit For
End If
Set arrayLine = LINES(intLineNum).Value
strPN = arrayLine("VENDOR_PART_ID")
cleanPN = split(strPN, " ")
For Each iteration in cleanPN
iteration = LTrim(RTrim(iteration))
ReDim Preserve cleanPN2(UBound(cleanPN2) + 1)
cleanPN2(UBound(cleanPN2)) = iteration
Next
Next
'Take any part numbers that were found and search the WO Master for operations that require certs.
For Each cleanPN3 In cleanPN2
strSQL = "SELECT USER_3 FROM OPERATION WHERE WORKORDER_BASE_ID = " & "'" & cleanPN3 & "';"
db.Open strConn, db
rs.Open strSQL, db
If Not rs.EOF And Not rs.BOF Then
strUSER3 = rs("USER_3")
Do While rs("USER_3") = Null
strUSER3 = rs("USER_3").MoveNext
Loop
If (strUSER3 <> Null) Or (strUSER3 <> "") Then
MsgBox "Certifications are required for part number " & cleanPN3 & "!", vbOKOnly
End If
End If
rs.Close
db.Close
Next
MsgBox "PO Scan Complete!"
Case vbNo
MsgBox("PO Scan Cancelled!")
End Select
Assuming everything else is working as you wish
rs.Open strSQL, db
If Not rs.BOF Then
rs.MoveFirst
Do While Not rs.EOF
If Len(Trim(Cstr(rs.fields("USER_3").value)) > 0 Then
MsgBox "Certifications are required for part number " & cleanPN3 & "!", vbOKOnly
End If
rs.MoveNext
Loop
End If
rs.Close

Update or CancelUpdate without AddNew or Edit - Access error

I have built a database that I get an occasional error in.
I have a bound form in split form/datasheet view. Occasionally when updating records, I get the "Update or CancelUpdate without AddNew or Edit" error when moving to a new record. This will happen in either the single record form, or on the datasheet.
It does not happen every time the record is saved. Maybe 1 out of 20 or 30 times.
I do have an AuditTrail built in, which is my only guess as to what may be causing the problem.
The VBA on the form:
Private Sub Form_AfterDelConfirm(Status As Integer)
If Status = acDeleteOK Then Call AuditChanges("ApptID", "DELETED PRIOR RECORD")
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
If Me.NewRecord Then
Call AuditChanges("ApptID", "NEW")
Else
Call AuditChanges("ApptID", "EDIT")
End If
End Sub
Private Sub Form_Delete(Cancel As Integer)
If Status = acDeleteOK Then Call AuditChanges("ApptID", "DELETE BUTTON HIT")
End Sub
The AuditTrail code is:
Sub AuditChanges(IDField As String, UserAction As String)
On Error GoTo AuditChanges_Err
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim ctl As Control
Dim datTimeCheck As Date
Dim strUserID As String
Set cnn = CurrentProject.Connection
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM AuditTrail", cnn, adOpenDynamic, adLockOptimistic
datTimeCheck = Now()
strUserID = Environ("USERNAME")
Select Case UserAction
Case "EDIT"
For Each ctl In Screen.ActiveControl.Parent.Controls
If ctl.Tag = "Audit" Then
If Nz(ctl.Value) <> Nz(ctl.OldValue) Then
With rst
.AddNew
![DateTime] = datTimeCheck
![UserName] = strUserID
![FormName] = Screen.ActiveControl.Parent.Name
![Action] = UserAction
![RecordID] = Screen.ActiveControl.Parent.Controls(IDField).Value
![FieldName] = ctl.ControlSource
![OldValue] = ctl.OldValue
![NewValue] = ctl.Value
.Update
End With
End If
End If
Next ctl
Case Else
With rst
.AddNew
![DateTime] = datTimeCheck
![UserName] = strUserID
![FormName] = Screen.ActiveControl.Parent.Name
![Action] = UserAction
![RecordID] = Screen.ActiveControl.Parent.Controls(IDField).Value
.Update
End With
End Select
AuditChanges_Exit:
On Error Resume Next
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
Exit Sub
AuditChanges_Err:
MsgBox Err.Description, vbCritical, "ERROR!"
Resume AuditChanges_Exit
End Sub
If the error doesn't involve the VBA code, I have no idea what the problem could be.
I concur with dbmitch; adding some extra info to your error message would be a great help.
In addition, if that doesn't get you exactly what you want, you can also implement the little-known ERL function. Most people don't even know that Access can trap at the line level if they add line numbers (are you old enough to remember Basic?) to their code.
So, something like:
Sub AuditChanges(IDField As String, UserAction As String)
10 On Error GoTo AuditChanges_Err
20 Dim cnn As ADODB.Connection
30 Dim rst As ADODB.Recordset
40 Dim ctl As Control
50 Dim datTimeCheck As Date
60 Dim strUserID As String
70 Set cnn = CurrentProject.Connection
80 Set rst = New ADODB.Recordset
etc...
And then you could change your error handler to be something like:
400 MsgBox "UserAction: " & UserAction & vbCrLf & _
"IDField: " & IDField & vbCrLf & _
"Error Line: " & Erl & vbCrLf & _
"Error: (" & Err.Number & ") " & Err.Description, vbCritical, "ERROR!"
Turns out that the problem didn't seem to have any issues with the AuditTrail code.
There is a combobox that was getting hung up occasionally when moving to a new record.
I added the code below to the 'On Exit' event for the field, and I haven't seen the error come up since.
If Me.Dirty Then
Me. Dirty = False
End If

Convert Access Attachment data type to file system files

I have a lot of files stored as attached files in an Access db. I am going to move data to an SQL server and for that purpose I need to extract the attached files and turn them into file system files.
This snippet works fine for images and pdf files but not for Office documents like Word or Excel. I assume it has something to do with encoding, but I have no clues. Any ideas?
Dim dbs As Database
Dim rs As Recordset
Set dbs = CurrentDb
Set rs = dbs.OpenRecordset("table1")
With rs
Do While Not .EOF
Set rsRec = rs.Fields("AttFiles").Value
While Not rsRec.EOF
NameOfFile = "C:\temp\" & rsFil.Fields("FileName")
Open NameOfFile For Binary Access Write As #1
Put #1, , rsRec.Fields("FileData").Value
Close #1
rsRec.MoveNext
Wend
.MoveNext
Loop
End With
rs.Close
dbs.Close
If the File is actually an attachment type, then you might as well use the Recordset2 of the Microsoft Access Object Library. Something like,
Public Sub exportDocument(tableName As String, fieldName As String, uniqueID As Long)
On Error GoTo Err_SaveImage
Dim rsParent As DAO.Recordset2
Dim rsChild As DAO.Recordset2
Dim saveAsName As String
Set rsParent = CurrentDb.OpenRecordset("SELECT " & tableName & ".* " & _
"FROM " & tableName & " WHERE " & tableName & "." & fieldName & " = " & uniqueID)
Set rsChild = rsParent.Fields("fileData").Value
If rsChild.RecordCount <> 0 Then
If Dir(Environ("userprofile") & "\My Documents\tmp\", vbDirectory) <> "." Then MkDir Environ("userprofile") & "\My Documents\tmp\"
saveAsName = Environ("userprofile") & "\My Documents\tmp\" & rsChild.Fields("FileName")
rsChild.Fields("fileData").SaveToFile saveAsName
FollowHyperlink saveAsName
End If
Exit_SaveImage:
Set rsChild = Nothing
Set rsParent = Nothing
Exit Sub
Err_SaveImage:
If Err = 3839 Then
Resume Next
Else
MsgBox "Some Other Error occured!" & vbCrLf & vbCrLf & Err.Number & " - " & Err.Description, vbCritical
Resume Exit_SaveImage
End If
End Sub
The above code will save the files to a location specified in saveAsName. I have specific unique ID in the WHERE condition. If you want to export all documents, you can alter the code accordingly, but might have to loop through the recordset. I hope this helps !

Update a linked table(In access 2003) through Excel VBA

I have some data in Excel that needs to be updated into a linked table in MS access. The link table connects to a sharepoint site. The code I have so far only works with regular table. rs.Open returns unspecified error in this case.
Sub Button1_Click()
On Error GoTo ExceptionHandle
Dim cn As ADODB.Connection, rs As ADODB.Recordset
' connect to the Access database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source=D:\.....\db1.mdb;"
' open a recordset
Set rs = New ADODB.Recordset
'ERROR
rs.Open "LinkedTableName", cn, adOpenKeyset, adLockOptimistic, adCmdTable
Range("B2").Activate ' row 1 contains column headings
Do While Not IsEmpty(ActiveCell)
s_title = ActiveCell.Offset.Value
s_start_time = ActiveCell.Offset(0, 1).Value
s_end_time = ActiveCell.Offset(0, 2).Value
rs.Filter = "Title ='" & s_title & "'"
If rs.EOF Then
Debug.Print "No existing record - adding new..."
rs.Filter = ""
rs.AddNew
Else
Debug.Print "Existing record found..."
End If
rs("Title").Value = s_title
rs("Start Time").Value = s_start_time
rs("End Time").Value = s_end_time
rs.Update
Debug.Print "...record update complete."
ActiveCell.Offset(1, 0).Activate ' next cell down
Loop
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
ExitProcedure:
MsgBox "Update success"
Exit Sub
ExceptionHandle:
MsgBox "Error:" & Err.Number & ": " & Err.Description
Exit Sub
End Sub

Resources