pskeens
asked on
Need Code Optimization - MS Access - VBA
I have a form and its one of the most complex forms that I have created. There is a lot going on however and its sluggish on certain items such as clearing record locks. I would ask you professionals to look at the code behind the one button giving me the most slowdown. Please provide any insight to better optimizing this code.
Private Sub btn_find_Click()
On Error GoTo Err_btn_find_Click
'--- Set form variables
Dim ctl As Control
Dim rs As Recordset
Dim strRecLock As String
Dim sParm As Variant
Dim Lockuser As String
'--- Set form parameters and set focus on ReqDate control
sParm = Me.txt_LoadID
strLockUser = Environ("username")
txt_reqDate.SetFocus
'--- Enable message to user "ESC to cancel search" and apply Green button color for search
lbl_cancelsrch.Visible = True
Me.BTN_FIND.BackColor = RGB(153, 204, 0)
'--- See what state FIND Button is in FIND or SEARCH. Check to see if form has data or not
'--- If form has data, prompt user to confirm clearing of form
If BTN_FIND.Caption = "FIND" Then
If Me.isdirty = True Then
If MsgBox("Form has been changed. Do you want to clear the form?", vbYesNo, "WARNING") = vbYes Then
'--- Clear all form controls upon confirmation
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
LBL_CANCELLED.Visible = False
lbl_ibshipper.Visible = False
btn_Details.Visible = False
txt_LoadID.Enabled = True
BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Go to RemoveLock to remove any record locks applied
GoTo RemoveLock
Else
Exit Sub
End If
'--- If form is not dirty with record then clear form without user confirmation
Else
'--- Clear all form controls
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
Me.LBL_CANCELLED.Visible = False
Me.lbl_ibshipper.Visible = False
Me.btn_Details.Visible = False
Me.txt_LoadID.Enabled = True
Me.BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Go to RemoveLock to remove any record locks applied
GoTo RemoveLock
RemoveLock:
'--- Remove Lock from current record
strLockUser = Environ("username")
'--- Check to see if any locks exist for current user in current form
If DCount("[LD_RECLOCK]", "TBL_LOAD_HED", "[LD_RECLOCK_USER] = '" & strLockUser & "'") >= 1 Then
'--- If locks are present clear locks
strLock = "select * from TBL_LOAD_HED where LD_RECLOCK_USER ='" & strLockUser & "'"
Set rs = CurrentDb.OpenRecordset(strLock, dbOpenDynaset, dbSeeChanges)
Do
rs.Edit
rs.Fields("LD_RECLOCK") = ""
rs.Fields("LD_RECLOCK_USER") = ""
rs.Update
rs.MoveNext
Loop Until rs.EOF
rs.Close
Set rs = Nothing
Else
'--- if no locks present then go to Delete Temp
GoTo DeleteTemp
End If
'--- Remove any records in DET TEMP Table for next record
DeleteTemp:
DoCmd.SetWarnings False
strSQLdel = "Delete * from TBL_LOAD_DET_TEMP"
DoCmd.RunSQL strSQLdel
DoCmd.SetWarnings True
Exit Sub
End If
'--- If FIND Button is in SEARCH state then
ElseIf Me.BTN_FIND.Caption = "SEARCH" Then
'--- See if search criteria has been entered. If no valid criteria then error message to user
If IsNull(txt_LoadID) = True Or txt_LoadID = "" Then
MsgBox "Nothing to search. Enter valid Load Number", vbOKOnly, "ERROR"
txt_LoadID.SetFocus
Exit Sub
Else
'--- check to see if record is locked before ruturning record to user. If locked LOCK notification
'--- to user, exit sub, set focus to LoadID control
If DLookup("[LD_RECLOCK]", "TBL_LOAD_HED", "[LD_NUM] = " & sParm) = "LOCKED" Then
Lockuser = DLookup("LD_RECLOCK_USER", "TBL_LOAD_HED", "[LD_NUM] =" & sParm)
MsgBox "User " & UCase(Lockuser) & " has record locked. Try again later"
Me.txt_LoadID.SetFocus
Exit Sub
Else
'--- If valid criteria and no locks found then return FIND button to FIND state and original color
'--- set form to dirty
Me.BTN_FIND.Caption = "FIND"
BTN_FIND.BackColor = RGB(47, 54, 153)
Me.isdirty = True
'--- Run query to populate form with record
strSQL = "Select * from TBL_LOAD_HED where LD_NUM =" & sParm
Set rs = CurrentDb.OpenRecordset(strSQL)
rs.MoveFirst
txt_carrier = rs.Fields("LD_CARRIER")
txt_reqDate = rs.Fields("LD_REQ_DATE")
txt_shipDate = rs.Fields("LD_SHIP_DATE")
cbo_custID = rs.Fields("LD_CUST_ID")
txt_CustName = rs.Fields("LD_CUST_NAME")
txt_CustCity = rs.Fields("LD_CUST_CITY")
txt_CustState = rs.Fields("LD_CUST_STATE")
txt_CustZip = rs.Fields("LD_CUST_ZIP")
txt_delCarrier = rs.Fields("LD_DEL_CARRIER")
txt_apptDate = rs.Fields("LD_APPT_DATE")
txt_apptTime = rs.Fields("LD_APPT_TIME")
cbo_shipToID = rs.Fields("LD_SHIPTO_ID")
txt_Instr = rs.Fields("LD_INSTRUCTIONS")
txt_delDate = rs.Fields("LD_DEL_DATE")
txt_bolNum = rs.Fields("LD_SHIP_NUM")
txt_bolLoc = rs.Fields("LD_SHIP_LOC")
cbo_inbShipperID = rs.Fields("LD_INB_SHIPPER")
txt_locName = rs.Fields("LD_LOC")
cbo_loc = rs.Fields("LD_LOC")
txt_createdBy = rs.Fields("LD_CREATED_BY")
txt_createdOn = rs.Fields("LD_CREATED_DATE")
txt_modifiedBy = rs.Fields("LD_MODIFIED_BY")
txt_modifiedOn = rs.Fields("LD_MODIFIED_DATE")
rs.Close
Set rs = Nothing
'--- Populate form controls with data that is not in recordset found in LD_HED table
txt_custPhone = DLookup("[CUST_PHONE]", "TBL_CUST_HED", "[CUST_ID] = " & [Forms]![frm_build_load]![cbo_custID])
txt_shipToName = DLookup("CUST_NAME", "TBL_CUST_HED", "[CUST_ID] = " & [Forms]![frm_build_load]![cbo_custID])
txt_shipToCity = DLookup("DET_CITY", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![cbo_shipToID] & "'")
txt_shipToState = DLookup("DET_STATE", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![cbo_shipToID] & "'")
txt_shipToZip = DLookup("DET_ZIP", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![cbo_shipToID] & "'")
txt_shipToPh = DLookup("DET_PHONE", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![cbo_shipToID] & "'")
'--- Append LOAD DET records to TEMP table and requery DET subform
DoCmd.SetWarnings False
DoCmd.OpenQuery "QRY_LOAD_DET_FIND", acViewNormal
DoCmd.SetWarnings True
Forms![frm_build_load].[FRM_LOAD_DET].Requery
'--- Hide message "ESC to cancel search"
Me.lbl_cancelsrch.Visible = False
'--- Apply record lock to selected record
strLock = "select * from TBL_LOAD_HED where LD_NUM =" & sParm
Set rs = CurrentDb.OpenRecordset(strLock, dbOpenDynaset, dbSeeChanges)
rs.Edit
rs.Fields("LD_RECLOCK") = "LOCKED"
rs.Fields("LD_RECLOCK_USER") = Environ("USERNAME")
rs.Update
rs.Close
Set rs = Nothing
End If
End If
End If
Exit_btn_find_Click:
Exit Sub
Err_btn_find_Click:
MsgBox Err.Description
Resume Exit_btn_find_Click
End Sub
Also, in the section following "'--- If locks are present clear locks" you will save some time by executing a single update such as
There are some more examples where you could do this too.
In the section titled "'--- Run query to populate form with record" you could extract all the data you need in one hit by adding some joins to the other relevant tables, eg:
There are probably more savings to be made, I will try to have a closer look.
strLock = "Update TBL_LOAD_HED set LD_RECLOCK='', LD_RECLOCK_USER= ''where LD_RECLOCK_USER ='" & strLockUser & "'"
currentdb.execute strLock
There are some more examples where you could do this too.
In the section titled "'--- Run query to populate form with record" you could extract all the data you need in one hit by adding some joins to the other relevant tables, eg:
strSQL = "Select t1.*, t2.CUST_PHONE, t2.CUST_NAME, t3.DET_CITY, t3.DET_STATE, t3.DET_ZIP, t3.DET_PHONE from TBL_LOAD_HED t1
left join TBL_CUST_HED t2 on t1.LD_CUST_ID = t2.CUST_ID
left join TBL_CUST_DET t3 on t1.LD_SHIPTO_ID = t3.DET_ID
where t1.LD_NUM =" & sParm
THis would save having to run all those Dlookups.There are probably more savings to be made, I will try to have a closer look.
ASKER
Thanks, will get to work on changing the code recommended. To answer your question this is an unbound form. This is the reason for a lot of the extra code. Almost all forms in my application are unbound just to have the control desired with searching, editing, and creating new records.
I was always told that using Goto is more effecient when having long code that you do not need to to through. In this case there is a whole section of code that gets jumped over by the "if" statement being true. In the code below when the IF statement is true then it skips over the italicized code:
If BTN_FIND.Caption = "FIND" Then
If Me.isdirty = True Then
If MsgBox("Form has been changed. Do you want to clear the form?", vbYesNo, "WARNING") = vbYes Then
'--- Clear all form controls upon confirmation
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
LBL_CANCELLED.Visible = False
lbl_ibshipper.Visible = False
btn_Details.Visible = False
txt_LoadID.Enabled = True
BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Go to RemoveLock to remove any record locks applied
>>>> GoTo RemoveLock
Else
Exit Sub
End If
'--- If form is not dirty with record then clear form without user confirmation
Else
'--- Clear all form controls
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
Me.LBL_CANCELLED.Visible = False
Me.lbl_ibshipper.Visible = False
Me.btn_Details.Visible = False
Me.txt_LoadID.Enabled = True
Me.BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Go to RemoveLock to remove any record locks applied
GoTo RemoveLock
>>>> RemoveLock:
I was always told that using Goto is more effecient when having long code that you do not need to to through. In this case there is a whole section of code that gets jumped over by the "if" statement being true. In the code below when the IF statement is true then it skips over the italicized code:
If BTN_FIND.Caption = "FIND" Then
If Me.isdirty = True Then
If MsgBox("Form has been changed. Do you want to clear the form?", vbYesNo, "WARNING") = vbYes Then
'--- Clear all form controls upon confirmation
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
LBL_CANCELLED.Visible = False
lbl_ibshipper.Visible = False
btn_Details.Visible = False
txt_LoadID.Enabled = True
BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Go to RemoveLock to remove any record locks applied
>>>> GoTo RemoveLock
Else
Exit Sub
End If
'--- If form is not dirty with record then clear form without user confirmation
Else
'--- Clear all form controls
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
Me.LBL_CANCELLED.Visible = False
Me.lbl_ibshipper.Visible = False
Me.btn_Details.Visible = False
Me.txt_LoadID.Enabled = True
Me.BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Go to RemoveLock to remove any record locks applied
GoTo RemoveLock
>>>> RemoveLock:
A golden rule of programming is "Never use goto (other than in on error goto statements)". It's not more efficient and can lead to terrible trouble debugging.
I'd remove the gotos if it was me. But I don't think it's affecting the performance of your form.
I'd remove the gotos if it was me. But I don't think it's affecting the performance of your form.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks Jim. To answer a couple of your questions:
The record lock happens at form level. Nobody else can call the record if "LOCKED" is present in current record within the table. They get a message telling them the record is locked by "username", try again later. No person can have the same record in a form at the same time, so therefore it cannot be edited by more than one person.
Thats correct. Reports do not look for this lock, so it will not prevent users from running any reports with locked records.
1. You have no error handling - depending on the number of users, your bound to get collisions when trying to place and clear locks. You must account for this.
The record lock happens at form level. Nobody else can call the record if "LOCKED" is present in current record within the table. They get a message telling them the record is locked by "username", try again later. No person can have the same record in a form at the same time, so therefore it cannot be edited by more than one person.
2. Your only handling exclusive locking, which you are going to find very restrictive, unless your point is to use this for editing only (i.e. what if someone runs a report against the table while someone else is editing; is that OK?, etc).
Thats correct. Reports do not look for this lock, so it will not prevent users from running any reports with locked records.
<<The record lock happens at form level. Nobody else can call the record if "LOCKED" is present in current record within the table. They get a message telling them the record is locked by "username", try again later. No person can have the same record in a form at the same time, so therefore it cannot be edited by more than one person.>>
Understood, but you missed the point. All the locks for each user are being placed against one table (TBL_LOAD_HED). In fact I didn't mention it, but this code will fail logically:
'--- Apply record lock to selected record
strLock = "select * from TBL_LOAD_HED where LD_NUM =" & sParm
Set rs = CurrentDb.OpenRecordset(st rLock, dbOpenDynaset, dbSeeChanges)
rs.Edit
rs.Fields("LD_RECLOCK") = "LOCKED"
rs.Fields("LD_RECLOCK_USER ") = Environ("USERNAME")
rs.Update
rs.Close
Set rs = Nothing
as you don't bother to lock the table while your placing the lock. If two users go after the same record at the same instant, they both may be granted a lock. You need to be locking TBL_LOAD_HED while you place the lock.
Also, a comment on this:
strLock = "select * from TBL_LOAD_HED where LD_NUM =" & sParm
Never return more fields then you need. And second, this is the actual data table; you don't want your lock flag in there. Why?
1. You need to lock the table while placing the lock.
2. If the power goes out/shoftware process is interuppted, you'll need to go through every record in the table to clear all the locks. Again read the article I posted the link to. A single lock table for all table locks is a much better approach.
Jim.
Understood, but you missed the point. All the locks for each user are being placed against one table (TBL_LOAD_HED). In fact I didn't mention it, but this code will fail logically:
'--- Apply record lock to selected record
strLock = "select * from TBL_LOAD_HED where LD_NUM =" & sParm
Set rs = CurrentDb.OpenRecordset(st
rs.Edit
rs.Fields("LD_RECLOCK") = "LOCKED"
rs.Fields("LD_RECLOCK_USER
rs.Update
rs.Close
Set rs = Nothing
as you don't bother to lock the table while your placing the lock. If two users go after the same record at the same instant, they both may be granted a lock. You need to be locking TBL_LOAD_HED while you place the lock.
Also, a comment on this:
strLock = "select * from TBL_LOAD_HED where LD_NUM =" & sParm
Never return more fields then you need. And second, this is the actual data table; you don't want your lock flag in there. Why?
1. You need to lock the table while placing the lock.
2. If the power goes out/shoftware process is interuppted, you'll need to go through every record in the table to clear all the locks. Again read the article I posted the link to. A single lock table for all table locks is a much better approach.
Jim.
ASKER
Jim, thanks again for your assistance. I am looking at changing the Lock routine to the article you posted. However I have a question. I am trying to modify it the the first instance without the flexible options that are not needed. I have the table set up as below. I am trying to create the functions but I am getting lost in removing the extra code. Any Insights to what I should/could remove?
I have changed the name of the table for my standard naming convention.
I have changed the name of the table for my standard naming convention.
ASKER
PLUMMET:
The query string with Joins is a tremendous idea, not sure why I never thought of it.........
Anyhow, I am getting this error when executing it.
strCustInfo = "Select t1.*, t2.CUST_PHONE, t2.CUST_NAME, t3.DET_CITY, t3.DET_STATE, t3.DET_ZIP, t3.DET_PHONE" & _
"from TBL_LOAD_HED t1" & _
"left join TBL_CUST_HED t2 on t1.LD_CUST_ID = t2.CUST_ID" & _
"left join TBL_CUST_DET t3 on t1.LD_SHIPTO_ID = t3.DET_ID" & _
"where t1.LD_NUM = " & sParm
Set rst = CurrentDb.OpenRecordset(st rCustInfo, dbOpenSnapshot) '<<<<<<<<<<<< BREAK HAPPENS HERE
strCustInfo-Error.PNG
The query string with Joins is a tremendous idea, not sure why I never thought of it.........
Anyhow, I am getting this error when executing it.
strCustInfo = "Select t1.*, t2.CUST_PHONE, t2.CUST_NAME, t3.DET_CITY, t3.DET_STATE, t3.DET_ZIP, t3.DET_PHONE" & _
"from TBL_LOAD_HED t1" & _
"left join TBL_CUST_HED t2 on t1.LD_CUST_ID = t2.CUST_ID" & _
"left join TBL_CUST_DET t3 on t1.LD_SHIPTO_ID = t3.DET_ID" & _
"where t1.LD_NUM = " & sParm
Set rst = CurrentDb.OpenRecordset(st
strCustInfo-Error.PNG
It looks like you need to add some spaces - in front of "from", "Left join" (two of these!) and "where"
Otherwise it looks ok I reckon. This will be better:
Cheers,
John
Otherwise it looks ok I reckon. This will be better:
strCustInfo = "Select t1.*, t2.CUST_PHONE, t2.CUST_NAME, t3.DET_CITY, t3.DET_STATE, t3.DET_ZIP, t3.DET_PHONE " & _
"from TBL_LOAD_HED t1" & _
" left join TBL_CUST_HED t2 on t1.LD_CUST_ID = t2.CUST_ID" & _
" left join TBL_CUST_DET t3 on t1.LD_SHIPTO_ID = t3.DET_ID" & _
" where t1.LD_NUM = " & sParm
Cheers,
John
<<Any Insights to what I should/could remove?>>
There is not much to remove outside of the lock level flag (Resource Tag is = LOC_TABLE_NAME and SubTag = LOC_REC_ID), but why would you want to? Just drop the code into a module and call it like this:
Dim varRet as Variant
varReturn = PlaceResourceLock("TBL_LOA D_HED", sParam, 3, True)
If varReturn = True then
' Ok to edit the record
Else
' Could not get a lock - message displayed by routine or an error occured - in either case, we do nothing here.
End If
and to clear:
varReturn = ClearResourceLock("TBL_LOA D_HED", sParam, WhoAmI(True), WhoAmI(False))
And your done!
Jim.
There is not much to remove outside of the lock level flag (Resource Tag is = LOC_TABLE_NAME and SubTag = LOC_REC_ID), but why would you want to? Just drop the code into a module and call it like this:
Dim varRet as Variant
varReturn = PlaceResourceLock("TBL_LOA
If varReturn = True then
' Ok to edit the record
Else
' Could not get a lock - message displayed by routine or an error occured - in either case, we do nothing here.
End If
and to clear:
varReturn = ClearResourceLock("TBL_LOA
And your done!
Jim.
ASKER
John, Query works great in SQL but cannot get it to work in access. I have messed with it for a long time and give up! lol.
I have tried changing it to Access SQL but still get an error. thoughts?
I have tried changing it to Access SQL but still get an error. thoughts?
ASKER
Wow I'm so stupid. Nevermind on that one John! I created a view in SQL and using that to populate the form. Wow, some of us are really slow! haha.
ASKER
Jim,
I have created the table:
tblResourceLock
LockID – Autonumber – Primary Key
ResourceTag – Text – Index 1A
ResourceSubTag – Text - Index 1B
UserID – Long – User ID that placed lock
DTPlaced – Date/Time
LockLevel – Integer
and created the two Functions for PlaceResourceLock and ClearResourceLock.
Now question is how do I call this in the form?
Thanks
I have created the table:
tblResourceLock
LockID – Autonumber – Primary Key
ResourceTag – Text – Index 1A
ResourceSubTag – Text - Index 1B
UserID – Long – User ID that placed lock
DTPlaced – Date/Time
LockLevel – Integer
and created the two Functions for PlaceResourceLock and ClearResourceLock.
Now question is how do I call this in the form?
Thanks
ASKER
Here is the latest code. I have removed all the Dlookup strings. Changed the Locking to another method. (Similar to Jim's, but still cannot get his to work)
Does this look better? Anything else I should look at changing?
Does this look better? Anything else I should look at changing?
Private Sub btn_find_Click()
On Error GoTo Err_btn_find_Click
'--- Set form variables
Dim Tblname As String
Dim LockUser As String
Dim LockDate As String
Dim strUserName As String
Dim ctl As Control
Dim rs As Recordset
Dim strRecLock As String
Dim sParm As Variant
'--- Set form parameters and set focus on ReqDate control
Tblname = "TBL_LOAD_HED"
LockUser = foSUserName()
LockDate = Now()
sParm = Me.txt_LoadID
txt_reqDate.SetFocus
'--- Enable message to user "ESC to cancel search" and apply Green button color for search
lbl_cancelsrch.Visible = True
Me.BTN_FIND.BackColor = RGB(153, 204, 0)
'--- See what state FIND Button is in FIND or SEARCH. Check to see if form has data or not
'--- If form has data, prompt user to confirm clearing of form
If BTN_FIND.Caption = "FIND" Then
If Me.isdirty = True Then
If MsgBox("Form has been changed. Do you want to clear the form?", vbYesNo, "WARNING") = vbYes Then
If DCount("*", "TBL_REC_LOCK", "[LOC_USER_ID] ='" & LockUser & "' And [LOC_TABLE_NAME] = '" & Tblname & "'") >= 1 Then
DoCmd.SetWarnings False
strSQL = "DELETE from [TBL_REC_LOCK] where [LOC_USER_ID] = '" & LockUser & "' and [LOC_TABLE_NAME] = '" & Tblname & "'"
DoCmd.RunSQL (strSQL)
DoCmd.SetWarnings True
End If
Else
Exit Sub
End If
'--- Clear all form controls upon confirmation
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
LBL_CANCELLED.Visible = False
lbl_ibshipper.Visible = False
btn_Details.Visible = False
txt_LoadID.Enabled = True
BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
Else
'--- If form is not dirty with record then clear form without user confirmation
If DCount("*", "TBL_REC_LOCK", "[LOC_USER_ID] ='" & LockUser & "' And [LOC_TABLE_NAME] = '" & Tblname & "'") >= 1 Then
DoCmd.SetWarnings False
strSQL = "DELETE from [TBL_REC_LOCK] where [LOC_USER_ID] = '" & LockUser & "' and [LOC_TABLE_NAME] = '" & Tblname & "'"
DoCmd.RunSQL (strSQL)
DoCmd.SetWarnings True
End If
'--- Clear all form controls
For Each ctl In Me.Controls
Select Case ctl.ControlType
Case acComboBox, acListBox, acOptionGroup, acTextBox, acCheckBox
ctl.Value = ctl.DefaultValue
End Select
'--- Ensure form is back to normal state, no labels showing. Change FIND button to SEARCH state
'--- enable LoadID control for search criteria and set focus here
Me.LBL_CANCELLED.Visible = False
Me.lbl_ibshipper.Visible = False
Me.btn_Details.Visible = False
Me.txt_LoadID.Enabled = True
Me.BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
Next
'--- Remove any records in DET TEMP Table for next record
DoCmd.SetWarnings False
strSQLdel = "Delete * from TBL_LOAD_DET_TEMP"
DoCmd.RunSQL strSQLdel
DoCmd.SetWarnings True
Exit Sub
End If
'--- If FIND Button is in SEARCH state then
ElseIf Me.BTN_FIND.Caption = "SEARCH" Then
Dim LockRecID As String
LockRecID = txt_LoadID
'--- See if search criteria has been entered. If no valid criteria then error message to user
If IsNull(txt_LoadID) = True Or txt_LoadID = "" Then
MsgBox "Nothing to search. Enter valid Load Number", vbOKOnly, "ERROR"
txt_LoadID.SetFocus
Exit Sub
ElseIf DCount("*", "TBL_LOAD_HED", "[LD_NUM]=" & sParm) = 0 Then
MsgBox "No records matching search criteria. Enter a valid Load Number", vbOKOnly, "ERROR"
txt_LoadID.SetFocus
Exit Sub
End If
'--- check to see if record is locked before ruturning record to user. If locked LOCK notification
'--- to user, exit sub, set focus to LoadID control
If DCount("*", "TBL_REC_LOCK", "[LOC_REC_ID] ='" & LockRecID & "' And [LOC_TABLE_NAME] = '" & Tblname & "'") >= 1 Then
MsgBox "Another User has this record locked. Try again later", vbOKOnly, "RECORD LOCKED"
txt_LoadID.SetFocus
Exit Sub
End If
'--- If valid criteria and no locks found then return FIND button to FIND state and original color
'--- set form to dirty
Me.BTN_FIND.Caption = "FIND"
BTN_FIND.BackColor = RGB(47, 54, 153)
Me.isdirty = True
'--- Run query to populate form with record
strSQL = "Select * from VW_LOAD_HED where LD_NUM =" & sParm
Set rs = CurrentDb.OpenRecordset(strSQL)
rs.MoveFirst
txt_carrier = rs.Fields("LD_CARRIER")
txt_reqDate = rs.Fields("LD_REQ_DATE")
txt_shipDate = rs.Fields("LD_SHIP_DATE")
cbo_custID = rs.Fields("LD_CUST_ID")
txt_CustName = rs.Fields("LD_CUST_NAME")
txt_CustCity = rs.Fields("LD_CUST_CITY")
txt_CustState = rs.Fields("LD_CUST_STATE")
txt_CustZip = rs.Fields("LD_CUST_ZIP")
txt_custPhone = rs.Fields("CUST_PHONE")
txt_delCarrier = rs.Fields("LD_DEL_CARRIER")
txt_apptDate = rs.Fields("LD_APPT_DATE")
txt_apptTime = rs.Fields("LD_APPT_TIME")
cbo_shipToID = rs.Fields("LD_SHIPTO_ID")
txt_shipToName = rs.Fields("DET_NAME")
txt_shipToCity = rs.Fields("DET_CITY")
txt_shipToState = rs.Fields("DET_STATE")
txt_shipToZip = rs.Fields("DET_ZIP")
txt_shipToPh = rs.Fields("DET_PHONE")
txt_Instr = rs.Fields("LD_INSTRUCTIONS")
txt_delDate = rs.Fields("LD_DEL_DATE")
txt_bolNum = rs.Fields("LD_SHIP_NUM")
txt_bolLoc = rs.Fields("LD_SHIP_LOC")
cbo_inbShipperID = rs.Fields("LD_INB_SHIPPER")
txt_locName = rs.Fields("LD_LOC")
cbo_loc = rs.Fields("LD_LOC")
txt_createdBy = rs.Fields("LD_CREATED_BY")
txt_createdOn = rs.Fields("LD_CREATED_DATE")
txt_modifiedBy = rs.Fields("LD_MODIFIED_BY")
txt_modifiedOn = rs.Fields("LD_MODIFIED_DATE")
rs.Close
Set rs = Nothing
'--- Append LOAD DET records to TEMP table and requery DET subform
DoCmd.SetWarnings False
DoCmd.OpenQuery "QRY_LOAD_DET_FIND", acViewNormal
DoCmd.SetWarnings True
Forms![frm_build_load].[FRM_LOAD_DET].Requery
'--- Hide message "ESC to cancel search"
Me.lbl_cancelsrch.Visible = False
'--- Apply record lock to selected record
DoCmd.SetWarnings False
strSQL = "INSERT INTO TBL_REC_LOCK ([LOC_TABLE_NAME],[LOC_REC_ID],[LOC_USER_ID],[LOC_DT_PLACED])" & _
"VALUES ('" & Tblname & "', '" & LockRecID & "', '" & LockUser & "', '" & LockDate & "')"
DoCmd.RunSQL (strSQL)
DoCmd.SetWarnings True
End If
Exit_btn_find_Click:
Exit Sub
Err_btn_find_Click:
MsgBox Err.Description
Resume Exit_btn_find_Click
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Changing "DoCmd.RunSQL (strSQL) " to "CurrentDB.Execute strSQL" did the trick for performance!
Thanks guys for your assistance on this! You have been a tremendous help!
I am splitting the points to both since you both gave valuable solutions on this optimization!
Thanks guys for your assistance on this! You have been a tremendous help!
I am splitting the points to both since you both gave valuable solutions on this optimization!
ASKER
The answers to this question have been a tremendous help! Thanks to everyone who helped out. Wish I had more points to allocate!
I'm surprised that you didn't also select my first comment, especially since you did select comment #36486853, which said exactly the same thing (i.e. move the code our of your loops, and use Currentdb.Execute instead of DoCmd.RunSQL).
ASKER
Sorry LSM!!! Its very hard to award points in this system with so many great people helping! I did overlook you this time.
Sorry AGAIN!
Sorry AGAIN!
No troubles, just wanted to make the point that the comment suggested had been offered previously. It's really up to the Experts to insure they do not duplicate posts. As the question thread gets longer, however, that becomes a bit more difficult of course, but taking the time to review previous comments is just part of the deal (at least in my opinion).
Scott
Scott
Why are you looping through your controls and setting them to Default values? If this is a bound form, and you're just moving to a different record, then Access will "clear" the form for you. If it's not bound, then just set the form to an empty string, or to 0, or whatever make sense. With complex forms moving through the control collection can take some time, so often you're better off explicitly clearing controls:
Me.Textbox1=""
Me.Combo2= ""
Move this out of your loop:
LBL_CANCELLED.Visible = False
lbl_ibshipper.Visible = False
btn_Details.Visible = False
txt_LoadID.Enabled = True
BTN_FIND.Caption = "SEARCH"
txt_LoadID.SetFocus
There's no need to call this for each control
replace ths block:
DoCmd.SetWarnings False
strSQLdel = "Delete * from TBL_LOAD_DET_TEMP"
DoCmd.RunSQL strSQLdel
DoCmd.SetWarnings True
With this line:
currentdb.execute "DELETE * FROM tbl_load_det_temp"
Use a Recordset instead of a string of DLookups:
txt_custPhone = DLookup("[CUST_PHONE]", "TBL_CUST_HED", "[CUST_ID] = " & [Forms]![frm_build_load]![
txt_shipToName = DLookup("CUST_NAME", "TBL_CUST_HED", "[CUST_ID] = " & [Forms]![frm_build_load]![
txt_shipToCity = DLookup("DET_CITY", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![
txt_shipToState = DLookup("DET_STATE", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![
txt_shipToZip = DLookup("DET_ZIP", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![
txt_shipToPh = DLookup("DET_PHONE", "TBL_CUST_DET", "[DET_ID] = '" & [Forms]![frm_build_load]![
should be written as
Dim rst = Currentdb.OpenRecordset("S
txt_shiptoname = rst("Cust_Name")
Same for the filter on ShipToID