DAO Recordset vs Numerous Dlookups - database

I created an access DB for a small business. In this DB I frequently auto fill some text boxes based on a key field via VBA using:
me.textboxvalue0.value = Nz(DLookup("VALUE0", "tblsomething", "lookedfield = '" & Me.keyfield.Value & "'"), "")
me.textboxvalue1.value = Nz(DLookup("VALUE1", "tblsomething", "lookedfield = '" & Me.keyfield.Value & "'"), "")
me.textboxvalue2.value = Nz(DLookup("VALUE2", "tblsomething", "lookedfield = '" & Me.keyfield.Value & "'"), "")
This piece of code repeats for all of my auto fillable textboxes ranging from 2 to 15 txtboxes.
My question is:
Is it faster to open a DAO recordset and find that particular row with all of its fields, or is it faster (execution time) to keep using multiple Dlookups to pull field by field of that row.

You can use the OnCurrent event of the form:
Dim rst As DAO.Recordset
Dim SQL As String
SQL = "Select * From tblSomething Where lookedfield = '" & Me!keyfield.Value & "'")
Set rst = CurrentDb.OpenRecordset(SQL)
If rst.RecordCount > 0 Then
Me!textboxvalue0.Value = rst!VALUE0.Value
Me!textboxvalue1.Value = rst!VALUE1.Value
Me!textboxvalue2.Value = rst!VALUE2.Value
Else
Me!textboxvalue0.Value = Null
Me!textboxvalue1.Value = Null
Me!textboxvalue2.Value = Null
End If
rst.Close
Set rst = Nothing

Related

Excel VBA Runtime 3704 Operation is not allowed when object is closed

I have been using this code for some time and it works. As a matter of fact it works with a basic query. It just does not work with my new Stored Procedure. I can run the stored procedure manually. in SSMS and get my results. I thought that the error was when I was not getting data back so I added the . . . If myRS1.EOF Then . . . still getting the 3704 runtime error.
Here is my Excel (2013) Code
Private Sub cmdOK_Click()
Dim myStartDate, myEndDate
Dim myInsuranceCode
Dim objAD, objUser
Dim myDisplayName, myLastRow
Dim myMessage, myStyle, myTitle, myResult
Dim mySQL As String
Dim myConn
Dim myCmd
Dim myRS1
Dim myRange, myNamedRange, myCheckRange As Range
Dim X, Y, z
Dim myPercent, myLowEnd, myHighEnd
Dim myValue1, myValue2, myValue3, myValue4, myValue5, myValue6, myValue7, myValue8
Dim myCheckValue
Dim myHeaderRow, myDataRow, myLastColumn
'SET THESE ACCORDING TO THE REPORT. THE FIRST TWO MIGHT NOT NEED ANY CHANGES
myHeaderRow = 2
myDataRow = 3
myLastColumn = 22
'SETUP DATABASE OBJECTS
Set myConn = New ADODB.Connection
Set myCmd = New ADODB.Command
Set myRS1 = New ADODB.Recordset
Application.StatusBar = True
Application.StatusBar = "Connecting to SQL Server"
'GET DATES FROM TEH FORM AND SET SQL STATEMENT
myStartDate = frmMain.txtStartDate
myEndDate = frmMain.txtEndDate
'RUN INSURANCE STORE PROCEDURE
'SEPERATE THE INSURANCE CODE WITH A |
myInsuranceCode = "S19|S22"
mySQL = "dbo.BMH_rpt_PATIENTS_INSURANCE_LISTING '" & myStartDate & "', '" & myEndDate & "', '" & myInsuranceCode & "'"
'mySQL = "SELECT * FROM dbo.BETHESDA_ADMIT_SOURCE"
'HIDE THE FORM
frmMain.Hide
'GET THE USER THAT IS SIGNED IN
Set objAD = CreateObject("ADSystemInfo")
Set objUser = GetObject("LDAP://" & objAD.UserName)
myDisplayName = objUser.DisplayName
'OPEN CONNECTIONS TO THE DATABASE
myConn.ConnectionString = "Provider=SQLOLEDB;Data Source=mySQLServer;Initial Catalog=myDatabaseName;User ID=user;Password=xxxxxxxx;Connection Timeout=300;"
myConn.Open
'SET AND EXECUTE SQL COMMAND
Set myCmd.ActiveConnection = myConn
myCmd.CommandText = mySQL
myCmd.CommandType = adCmdText
Application.StatusBar = "Running Stored Procedure " & mySQL
myCmd.CommandTimeout = 3000
'OPEN RECORDSET
Set myRS1.Source = myCmd
myRS1.Open
'CHECK TO MAKE SURE WE ARE NOT AT THE BOTTOM OF THE SHEET COULD MEAN THERE WAS NOT DATA LAST TIME.
'THIS SAME CODE WILL REPEAT FOR THE DATA TAB
'*********** DATA *************
'CHECK TO MAKE SURE THERE IS DATA
If myRS1.EOF Then <---- THIS IS THE LINE I AM GETTING THE ERROR
Cells(myDataRow, 1).Value = "No Data Qualifies"
myMessage = "No data qualifing for your request " & mySQL
myTitle = "No Data"
myStyle = vbCritical + vbOKOnly
myResult = MsgBox(myMessage, myStyle, myTitle)
Exit Sub
End If
'SELECT THE SHEET TO CLEAR OUT THE OLD data on DATA
'IF THIS IS NOT SET ON THE SEEHET IT WILL FAIL
Set myTable = Sheets("DATA").ListObjects("DATA")
If Cells(myDataRow, 1).Value <> "" Then
myTable.DataBodyRange.Rows.Delete
End If
'COPY THE DATA TO EXCEL
Application.StatusBar = "Copying the new data."
Sheets("DATA").Cells(myDataRow, 1).CopyFromRecordset myRS1
Cells(1048576, 1).Select
Selection.End(xlUp).Select
myLastRow = ActiveCell.Row
'Application.StatusBar = "Naming the new DATA range"
'ActiveWorkbook.Names.Add Name:=myNamedRange, RefersTo:=Range(Cells(myHeaderRow, 1), Cells(myLastRow, myLastColumn))
myTable.Resize Range(Cells(myHeaderRow, 1), Cells(myLastRow, myLastColumn))
End Sub
*** This is all the VBA Code now. It is failing on the myRS1.EOF line so none of the other code even runs.
As you can see I have two mySQL statements. The first one is not working, but the second one works no issue.
If I run the SP from SSMS or even take the mySQL that is generated it runs fine in SSMS.
Here is the SP
--EXAMPLE
-- dbo.BMH_rpt_PATIENTS_INSURANCE_LISTING '11/01/2020', '11/30/2020', 'S19|S22'
ALTER PROCEDURE [dbo].[BMH_rpt_PATIENTS_INSURANCE_LISTING]
#StartDate AS DATETIME,
#EndDate AS DATETIME,
#Insurance AS VARCHAR(MAX)
AS
/** GET THE INSURANCE CODES **/
SELECT VALUE
INTO #INSURANCE
FROM STRING_SPLIT(#Insurance, '|')
/** GET THE PATIENTS FOR THE LIST **/
SELECT vv.pt_id AS 'Patient Account',
vv.alt_med_rec_no AS 'MRN'
FROM smsdss.vst_v AS vv
WHERE vv.pyr_cd IN (SELECT * FROM #INSURANCE)
AND vv.start_full_date BETWEEN #StartDate AND #EndDate
AND vv.tot_bal_amt <> 0

Speeding up an Access Database

I have an Access database to report on event statistics gathered from a mainframe system. The mainframe scheduler (ZEKE) doesn't have robust reporting features, so I export daily event data to report on.
A master listing from a separate source (a static list that will not change on a regular basis) lists the individual applications, including the application code (which is the naming standard for production runs) and the name of the programmer, coordinator, manager, business unit, etc. for that application.
The user can search by any field, application code, programmer, coordinator, etc.
Choose the production center to search in (there are 5) or default to all, and choose all dates, a single date, or a date range.
The query takes the search parameters and starting with either the application code, or the person, searches the table for applications and copies records to a temp table for reporting.
For example, to see how many failures the application coordinator John Doe had for the past week for all of the applications he is responsible for, the query would move all application records listing John Doe as the coordinator to the temp table.
From there, it moves through the temp table for each application and searches the event data for events under that application code which meet the criteria entered for date, production center and event type (success, failure or both).
This is moved to a temp table for the final report.
The table for event data is currently 2.5 million lines (this is 15 days worth of data) and is growing daily.
I put the back end onto a newly created NAS drive on our network.
A report that took two minutes when the back end and front end were on the same machine now takes 29 minutes.
Any suggestions to streamline the queries over a network?
Code which is run from the report criteria selection form and runs the report.
'this macro will generate a report based on multiple input criteria.
'this report allows the user to slect:
' date range, single date or all dates
' type of events: Abends, Successes or both
' centers to pull data from: OCC,QCC,BCC,ITS,DAIN, or ALL centers
' The type of data to report on: App code, App Coordinator, Custodian, L3, L4 or L5
'Once the user has selected all of the required data and fields, the report will be generated
'based on the selection criteria.
'we begin by defining the active database as the currently open database
Dim db As DAO.Database
Set db = DBEngine(0)(0)
On Error GoTo ErrorHandler
'Now we designate the variables which will be used in this macro
Dim strSQ1 As String
Dim strSQ2 As String
Dim strSQ3 As String
Dim strSQ4 As String
Dim appl As String
Dim evstatus As String
Dim appletype As String
Dim fullapp As String
Dim length As Long
Dim iipmname As String
Dim iipmcoor As String
Dim fullappnm As String
Dim fullappcoor As String
Dim kinddate As String
Dim coor As String
Dim cust As String
Dim appL3 As String
Dim appL4 As String
Dim appL5 As String
Dim ctrOCC As String
Dim ctrMTL As String
Dim ctrBCC As String
Dim ctrITS As String
Dim ctrDAIN As String
'We will start by setting some default values
'We will ste the default values for center selection.
'We start by searching for terms we know are not there, then change them to
'valid search terms if the center is selected.
ctrOCC = "notOCC"
ctrMTL = "notMTL"
ctrBCC = "notBCC"
ctrITS = "notITS"
ctrDAIN = "notUSWM"
fullapp = "*"
'First we determine which event types the user wants to look for
state = Me![opt-status].Value
If state = 1 Then
evstatus = " [ev-status] = 'AEOJ'"
ElseIf state = 2 Then
evstatus = " [ev-status] = 'EOJ'"
ElseIf state = 3 Then
evstatus = " ([ev-status] = 'EOJ' OR [ev-status] = 'AEOJ')"
End If
'MsgBox "Event status pulled is:.. " & evstatus & "."
' Next up we will configure the date parameters based on the user input
If [grp-datesel] = 1 Then
Sdte = "1"
Edte = "9999999"
kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " "
End If
If [grp-datesel] = 2 Then
'error handling
If IsNull(Me.[sel-onedate]) Then
MsgBox "You have not entered a date to search....please try again."
Me.[sel-onedate] = Null
Me.[sel-onedate].SetFocus
Exit Sub
End If
'end of error handling
Dim currdte As Date
currdte = Me![sel-onedate].Value
currjul = Format(currdte, "yyyyy")
daycurr = CDbl(currjul)
Sdte = daycurr
Edte = daycurr
kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " "
End If
If [grp-datesel] = 3 Then
'error handling
If IsNull(Me.[sel-Sdate]) Or IsNull(Me.[sel-Edate]) Then
MsgBox "You Must enter a start and end date for the search....please try again."
Me.[sel-Sdate] = Null
Me.[sel-Edate] = Null
Me.[sel-Sdate].SetFocus
Exit Sub
End If
'end of error handling
Dim startdte As Date
Dim enddte As Date
startdte = Me.[sel-Sdate].Value
enddte = Me.[sel-Edate].Value
startjul = Format(startdte, "yyyyy")
endjul = Format(enddte, "yyyyy")
Sday = CDbl(startjul)
Eday = CDbl(endjul)
Sdte = Sday
Edte = Eday
'MsgBox "start date is " & Sdte & " and end date is " & Edte & "."
'check that dates are in proper chronological order
If Sdte > Edte Then
MsgBox "The start Date you entered is after the end date....please try again."
Me.[sel-Sdate] = Null
Me.[sel-Edate] = Null
Me.[sel-Sdate].SetFocus
Exit Sub
End If
'keep going if it's all good
kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " "
End If
MsgBox "Date used is:.. " & kinddate & "."
'Now lets look at center selection
If [chk-allctr].Value = True Then
ctrOCC = "OCC"
ctrMTL = "MTL"
ctrBCC = "BCC"
ctrITS = "ITS"
ctrDAIN = "USWM"
End If
If [chk-OCC].Value = True Then
ctrOCC = "OCC"
End If
If [chk-MTL].Value = True Then
ctrMTL = "MTL"
End If
If [chk-BCC].Value = True Then
ctrBCC = "BCC"
End If
If [chk-RTF].Value = True Then
ctrITS = "ITS"
End If
If [chk-DAIN].Value = True Then
ctrDAIN = "DAIN"
End If
'Error handling if no center is selected
If [chk-OCC].Value = Flase Then
If [chk-MTL].Value = Flase Then
If [chk-BCC].Value = Flase Then
If [chk-RTF].Value = Flase Then
If [chk-DAIN].Value = Flase Then
MsgBox "You have not selected a center to search search....please try again."
Me.[chk-allctr].SetFocus
Exit Sub
End If
End If
End If
End If
End If
'end of error handling
'MsgBox "centers used are: Chr(10) " & ctrOCC & " Chr(10) " & ctrBCC & " Chr(10) " & ctrMTL & " Chr(10) " & ctrITS & " Chr(10) " & ctrDAIN & " For this run"
'All good so far, now we will parse the application code if an
'application code report is selected
appl = "*"
If [opt-criteria].Value = 1 Then
'error handling
If IsNull(Me.[sel-appcode]) Then
MsgBox "You have not entered an application code to search....please try again."
Me.[sel-appcode] = Null
Me.[sel-appcode].SetFocus
Exit Sub
End If
'end of error handling
End If
If [opt-criteria].Value = 1 Then
appl = Me![sel-appcode].Value
End If
'trust = "no"
'If Mid(appl, 3, 2) = "RT" Then trust = "yes"
'length = Len(appl)
'If length = 2 Then appltype = "short"
'If length = 3 Then appltype = "long"
'If appltype = "short" Then fullapp = "" & appl & "00"
'If appltype = "long" Then fullapp = "" & appl & "0"
'If trust = "yes" Then fullapp = appl
'End If
fullapp = appl
'MsgBox "App to use is: " & appl & " fullapp code is " & fullapp & "."
'Now we set values if names are used
coor = "*"
cust = "*"
appL3 = "*"
appL4 = "*"
appL5 = "*"
If [opt-criteria].Value = 2 Then
'error handling
If IsNull(Me.[sel-coor]) Then
MsgBox "You have not entered a Coordinator to search....please try again."
Me.[sel-coor] = Null
Me.[sel-coor].SetFocus
Exit Sub
End If
'end of error handling
coor = Me![sel-coor].Value
'MsgBox "Coordinator report selected for: " & coor & "."
End If
If [opt-criteria].Value = 3 Then
'error handling
If IsNull(Me.[sel-custodian]) Then
MsgBox "You have not entered a Custodian to search....please try again."
Me.[sel-custodian] = Null
Me.[sel-custodian].SetFocus
Exit Sub
End If
'end of error handling
cust = Me![sel-custodian].Value
'MsgBox "Custodian report selected for: " & cust & "."
End If
If [opt-criteria].Value = 4 Then
'error handling
If IsNull(Me.[sel-L3]) Then
MsgBox "You have not entered an L3 to search....please try again."
Me.[sel-L3] = Null
Me.[sel-L3].SetFocus
Exit Sub
End If
'end of error handling
appL3 = Me![sel-L3].Value
'MsgBox "L3 report selected for: " & appL3 & "."
End If
If [opt-criteria].Value = 5 Then
'error handling
If IsNull(Me.[sel-L4]) Then
MsgBox "You have not entered an L4 to search....please try again."
Me.[sel-L4] = Null
Me.[sel-L4].SetFocus
Exit Sub
End If
'end of error handling
appL4 = Me![sel-L4].Value
'MsgBox "L4 report selected for: " & appL4 & "."
End If
If [opt-criteria].Value = 6 Then
'error handling
If IsNull(Me.[sel-L5]) Then
MsgBox "You have not entered an L5 to search....please try again."
Me.[sel-L5] = Null
Me.[sel-L5].SetFocus
Exit Sub
End If
'end of error handling
appL5 = Me![sel-L5].Value
'MsgBox "L5 report selected for: " & appL5 & "."
End If
'Most of these reports take a while to build with this macro, so to make sure the user
'knows that the macro is still working, we didsplay a splash screen. It's cute and has
'hamsters, cause everyone loves hamsters.
DoCmd.OpenForm "PlsWaitFrm", acWindowNormal
[Forms]![PlsWaitFrm].Repaint
'All of out criteria values are now selected. We can move on to pulling data from the tables.
'We start by populating the IIPM table with the information that we require for applications.
strSQ1 = "DELETE * from [tbl-RPT-IIPM] "
db.Execute strSQ1
strSQ2 = "INSERT INTO [tbl-RPT-IIPM] " & _
"SELECT * FROM [tbl-IIPM] " & _
"WHERE (([AppCode] like '" & fullapp & "')" & _
"AND ([AppCoordinator] like '" & coor & "') " & _
"AND ([AppCustodian] like '" & cust & "') " & _
"AND ([L3] like '" & appL3 & "') " & _
"AND ([L4] like '" & appL4 & "') " & _
"AND ([L5] like '" & appL5 & "')) "
db.Execute strSQ2
'MsgBox "made it past the populate of rpt-iipm"
'Now we have populated the IIPM report table, it's time to populate the event report table.
'We will loop through all fields in the IIPM report table and pull information for each
'application code.
strSQ3 = "DELETE * from [tbl-EVENTREPORT] "
db.Execute strSQ3
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tbl-RPT-IIPM") 'this opens the IIPM report table just populated
'populate the table
rs.MoveLast
rs.MoveFirst
Do While Not rs.EOF
'we will execute these action against the selected record.
'first step - parse the application code to display the full application code
appl = rs![AppCode].Value
length = Len(appl)
If length = 1 Then appl = "" & appl & "00"
rptdelin = Mid(appl, 3, 1)
rptcode = Mid(appl, 1, 3)
If rptdelin = "0" Then rptcode = Mid(appl, 1, 2)
If rptdelin = "R" Then rptcode = "RT" & Mid(appl, 1, 2) & ""
'MsgBox "searching for: " & rptcode & "."
applist = applist & "," & appl
strSQ4 = "INSERT INTO [tbl-EVENTREPORT] " & _
"SELECT * FROM [tbl-EVENT DATA] " & _
"WHERE (([ev-jobname] LIKE '?" & rptcode & "*') " & _
"AND (([ev-ctr] = '" & ctrOCC & "')" & _
"OR ([ev-ctr] = '" & ctrMTL & "')" & _
"OR ([ev-ctr] = '" & ctrBCC & "')" & _
"OR ([ev-ctr] = '" & ctrITS & "')" & _
"OR ([ev-ctr] = '" & ctrDAIN & "'))" & _
"AND (" & kinddate & ") " & _
"AND " & evstatus & ")"
db.Execute strSQ4
'now we're done with this report, we move on to the next
rs.MoveNext 'press Ctrl+G to see debuG window beneath
Loop
'END OF LOOPING CODE
'MsgBox "made it past the looping"
'Now we have completed populating the table that the report will be based on.
'Next step is to gather master statistics to produce abend and success percentages.
totfail = DCount("[ev-status]", "tbl-EVENTREPORT", "[ev-status] = 'AEOJ'")
totsucc = DCount("[ev-status]", "tbl-EVENTREPORT", "[ev-status] = 'EOJ'")
Dim allabend As Long
Dim allsucc As Long
allabend = DCount("[ev-status]", "[tbl-EVENT DATA]", "[ev-status] = 'AEOJ' AND ([ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & ")")
allsucc = DCount("[ev-status]", "[tbl-EVENT DATA]", "[ev-status] = 'EOJ' AND ([ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & ")")
Dim pctabend As Long
Dim pctsucc As Long
pctabend = (totfail / allabend) * 100
pctsucc = (totsucc / allsucc) * 100
'Now we will generate the reports for display based on what type of report was selected
'by the user in the initial form.
'Before we open the report, we will close the splash screen
DoCmd.Close acForm, "PlsWaitFrm", acSaveNo
'Now we open the report
If [opt-criteria].Value = 1 Then
fullappnm = DLookup("AppName", "tbl-RPT-IIPM", "AppCode = '" & fullapp & "' ")
fullappcoor = DLookup("AppCoordinator", "tbl-RPT-IIPM", "AppCode = '" & fullapp & "' ")
DoCmd.OpenReport "rpt-APPLREPORT", acViewReport
[Reports]![rpt-APPLREPORT]![rpt-appcode].Value = fullapp
[Reports]![rpt-APPLREPORT]![rpt-appname].Value = fullappnm
[Reports]![rpt-APPLREPORT]![rpt-appcoor].Value = fullappcoor
[Reports]![rpt-APPLREPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-APPLREPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-APPLREPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-APPLREPORT]![rpt-succpct].Value = pctsucc
End If
If [opt-criteria].Value = 2 Then
DoCmd.OpenReport "rpt-COORREPORT", acViewReport
[Reports]![rpt-COORREPORT]![rpt-appcode].Value = applist
[Reports]![rpt-COORREPORT]![rpt-appcoor].Value = coor
[Reports]![rpt-COORREPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-COORREPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-COORREPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-COORREPORT]![rpt-succpct].Value = pctsucc
End If
If [opt-criteria].Value = 3 Then
DoCmd.OpenReport "rpt-CUSTREPORT", acViewReport
[Reports]![rpt-CUSTREPORT]![rpt-appcode].Value = applist
[Reports]![rpt-CUSTREPORT]![rpt-appcoor].Value = cust
[Reports]![rpt-CUSTREPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-CUSTREPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-CUSTREPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-CUSTREPORT]![rpt-succpct].Value = pctsucc
End If
If [opt-criteria].Value = 4 Then
DoCmd.OpenReport "rpt-L3REPORT", acViewReport
[Reports]![rpt-L3REPORT]![rpt-appcode].Value = applist
[Reports]![rpt-L3REPORT]![rpt-appcoor].Value = appL3
[Reports]![rpt-L3REPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-L3REPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-L3REPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-L3REPORT]![rpt-succpct].Value = pctsucc
End If
If [opt-criteria].Value = 5 Then
DoCmd.OpenReport "rpt-L4REPORT", acViewReport
[Reports]![rpt-L4REPORT]![rpt-appcode].Value = applist
[Reports]![rpt-L4REPORT]![rpt-appcoor].Value = appL4
[Reports]![rpt-L4REPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-L4REPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-L4REPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-L4REPORT]![rpt-succpct].Value = pctsucc
End If
If [opt-criteria].Value = 6 Then
DoCmd.OpenReport "rpt-L5REPORT", acViewReport
[Reports]![rpt-L5REPORT]![rpt-appcode].Value = applist
[Reports]![rpt-L5REPORT]![rpt-appcoor].Value = appL5
[Reports]![rpt-L5REPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-L5REPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-L5REPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-L5REPORT]![rpt-succpct].Value = pctsucc
End If
ErrorHandler:
If Err.Number = 7874 Then
Resume Next 'Tried to delete a non-existing table, resume
End If
End Sub
'''
Firstly, you need to work out where the bottlenecks are, so I would suggest putting some Debug.Print Now statements throughout the code to give you an idea of what is causing the issue.
I would guess that two of the processes that take most of the time are the DELETE/INSERT statements that you are doing.
I would suggest that rather than doing this, you look at normalizing your database, and then creating a query that provides the information that you need.
Also, by running the report directly from a query rather than a temporary table means that you don't have to worry about the deletes/inserts creating database bloat.
If you really insist on keeping this process, then consider deleting the table [tbl-RPT-IIPM] and then recreating it, rather than deleting the records. And consider removing the indexes before the insert, and then adding them back afterwards, as indexes splow down inserts, but obviously speed up searches and joins.
Also, when you are inserting data into [tbl-RPT-IIPM], you are using ([L3] like '" & appL3 & "'), which is the same as ([L3]='" & appL3 & "'), but slower.
When you are inserting data into [tbl-EVENTREPORT], you are doing it when looping through a recordset - it may be faster to use an INSERT SQL statement.
Regards,
OK, with some more information, some more answers that may (or may not!!) help. Again, you will need to run timing tests to see which works best for you.
Try adding a "Yes/No" field to the table [tbl-EVENT DATA]. You can then use an UPDATE statement to indicate which fields to include in the report, rather than using the slow INSERT query.
Another thing to try would be to replace the INSERT statement with several, each using a different value for [ev-ctr]. Or else rather than using OR try using IN:
strSQ4 = "INSERT INTO [tbl-EVENTREPORT] " & _
"SELECT * FROM [tbl-EVENT DATA] " & _
"WHERE [ev-jobname] LIKE '?" & rptcode & "*' " & _
"AND [ev-ctr] IN('" & ctrOCC & "','" & ctrMTL & "','" & ctrBCC & "','" & ctrITS & "','" & ctrDAIN & "')" & _
"AND " & kinddate & _
"AND " & evstatus
Also, I notice that kinddate is set to effectively include all dates in one instance, and that evstatus is set to include both "EOJ" and "AEOJ" in one instance. Rather than including these fields as criteria in these cases, you may wish to not include them at all:
If state = 1 Then
evstatus = " AND [ev-status] = 'AEOJ'"
ElseIf state = 2 Then
evstatus = " AND [ev-status] = 'EOJ'"
ElseIf state = 3 Then
evstatus = " "
End If
And then you would rewrite " AND " & evstatus to & evstatus in the SQL statement.
A final thing to look at is to actually run the INSERT directly in the backend, rather than operating on linked tables in the frontend, as Access will be dragging vast amounts of data across the network and then sending it back. As a basic guide, something like this:
Sub sUpdateQuery()
Dim objAccess As New Access.Application
objAccess.OpenCurrentDatabase "J:\downloads\test.accdb"
objAccess.DoCmd.RunSQL "UPDATE test2 SET Field1=UCASE(Field1);"
objAccess.CloseCurrentDatabase
Set objAccess = Nothing
End Sub
Regards,
Applecore, Firstly, let me thank you for your insights. Unfortunately due to the nature of the way the data is processed, some of them I'm not sure I can implement. I have used debug.print statements to get a better idea of the timing.
You are correct, the INSERT statement is causing me the most problems, and only the second one. The deletes fly through almost instantly, no issues there. It's the second insert from the event data that is slowing it down.
I have been thinking about this since inception of how to nromalize more efficiently and create better relationships, but I'm stymied. My issue is, the data between the event table and the event table are related "in the world" but in no clear way in terms of data. There is no way to determine the relationship without a complex calculation. For example, the unique part of the application data is the application code. They are always unique. A single Application coordinator can have dozens of codes assigned to them, as can custodians, L3,L4, etc. Each event is related to an application, however, there is no specific field that is exported that tells the application code, it is obtained by parsing the event name (And yes, that is as archaic as it sounds). The event naming standards are standard mainframe 8 character names: .
For example PGRD1234 - Production job, GRD application, 1234 as the designator. So to determine what application the job is related to, I take the application code, and select LIKE with wildcards. It's not 100% accurate I am well aware, but to use wildcards, I seem to be stuck using LIKE. I haven't been able to make '=' work with wildcards. Can you?
You also mentioned "When you are inserting data into [tbl-EVENTREPORT], you are doing it when looping through a recordset - it may be faster to use an INSERT SQL statement." which I'm not sure what you are saying.. My apologies. I don't think I am understanding it. I think that is what I am doing now. I use the IIPM table to obtain the listing of the application codes I need to pull, then loop through that recordset to pull all of the event data for only those applications. As there is no direct correlation between the data, I Can't think of another way to do it.

Row data into string conversion vb.net 2010

How can I convert a row data into string or text and display it into a label? My problem is when I click on my login button which contains the SQL code that gains a row data into alabel, the result in my label is false. not the text. How can I convert it into string?
Here's my code:
Private Sub cmdLog_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLog.Click
Dim connection As New SqlClient.SqlConnection
Dim command As New SqlClient.SqlCommand
Dim adaptor As New SqlClient.SqlDataAdapter
Dim dataset As New DataSet
Dim reader As MySqlDataReader = Nothing
Dim sapi
sapi = CreateObject("sapi.spvoice")
connection.ConnectionString = ("Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Calupad\Desktop\HTF feat Yiyet\HTF feat Yiyet\Database1.mdf;Integrated Security=True;User Instance=True")
command.CommandText = "SELECT * FROM [Users] WHERE Username='" & txtUser.Text & "' AND Password ='" & txtPass.Text & "';"
txtWel.Text = "Welcome Back, " + txtUser.Text + "!....."
connection.Open()
command.Connection = connection
adaptor.SelectCommand = command
adaptor.Fill(dataset, "0")
txtStat.text = command.CommandText = "SELECT Status FROM [Users] WHERE Username = '" & txtUser.Text & "' ".ToString
txtStat.Text = stat
Dim count = dataset.Tables(0).Rows.Count
If count > 0 Then
MsgBox("Login Successful!" & vbNewLine & txtStat.Text, MsgBoxStyle.Information, "Access Granted")
sapi.speak(txtWel.Text)
Me.Hide()
Form1.Show()
frmMenu.Show()
txtUser.Clear()
txtPass.Clear()
tries = 3
Else
ctr = tries - 1
tries = ctr
sapi.speak(txtUser.Text + txtNot.Text)
MsgBox("Invalid Account!" + vbNewLine + "Attempts Remaining: " & tries, vbCritical, "Access Denied")
txtUser.Clear()
txtPass.Clear()
If tries = 0 Then
MsgBox("You've reached the maximum attempts!" + vbNewLine + "The program will be terminated.", vbCritical, "Terminated!")
Me.Close()
End If
End If
End Sub
First of all, the way you check for username and password is weak and is most certainly volnurable to SQL injections. You are checking if the 'count' of rows is greater than zero then the user has logged in successfully, where as you should only compare count to 1. and instead of counting the rows, try to compare the row values to what the user has input in the username and passoword fields and what is returned from the database rows.
The "hacker" can simply type this and he will be allowed to log in according to the logic of your code:
You just need to retrieve the data stored into dataset variable that you filled using the adapter.
Assuming your database table contains fields like First_Name and 'Last_Name', here is how you can display them on any label control on your form:
adaptor.Fill(dataset, "0")
myFirstName.Text = dataset.Tables(0).Rows(0).Item("First_Name").ToString()
myLastName.Text = dataset.Tables(0).Rows(0).Item("First_Name").ToString()
You can also retrieve the column without having to know its name like this
myLabel.text = = dataset.Tables(0).Rows(0).Item(3).ToString()
'This will retrieve the 4th column from the table (zero based array)
You can also clean up your code by declaring a variable to hold the retrieved table
adaptor.Fill(dataset, "0")
Dim myTable as DataTable = dataset.Tables(0)
myFirstName.Text = myTable.Rows(0).Item(0).ToString()
Hope this helps

How to display more data from the database (access) in VBA?

What's the matter. After selecting a name from a ComboBox in ListBox have to display all the employees of the chosen company. And now my problem, always in a ListBox displays only 2 employees of the chosen company. The following piece of code responsible for displaying. For the record, I'm new in VBA. And of course, my question is why only two employees?
Procedure-click on the selected company from ComboBox:
Dim RecordSt As Recordset
Dim db As Database
Dim query As String
Dim strKombi30 As String
Dim i As Integer
strKombi30 = Me.Kombi30.Value ''combobox
query = "SELECT [Employees].[First name], [Employees].[Name] FROM" & _
"[Employees] WHERE [Employees].[Company] = '" & Me.Kombi30
Set db = CurrentDb()
Set RecordSt = db.OpenRecordset(query)
RecordSt.MoveFirst
For i = 0 To RecordSt.RecordCount
listContacts.AddItem (RecordSt.Fields("First name").Value & " " & RecordSt.Fields("Name").Value)
RecordSt.MoveNext
Next i
strKombi30 = Me.Kombi30.Value ''combobox
query = "SELECT [Employees].[First name], [Employees].[Name] FROM" & _
"[Employees] WHERE [Employees].[Company] = '" & strKombi30 & "'"

find the duplicate and write it in log file

I have craeted code which reads the acc no, rtn, name and amt from text file and stores in recordset. After that i created sql that stores recordset data into sql server 2005 table.
The problem is In that accno column is primary key. but i have some duplicate accno in my text file. While adding recordset to database, if it finds duplicate accno it is stopping there and not inserting any rows after that duplicate column.
Now i what i want to do is if there is any duplicate column, i want to store that column into log file and skip that column and insert remaining columns into databse. I dont know how to do it. Can anybody help me. like how to check the duplicate column and skip that and insert remaining.
' Write records to Database
frmDNELoad.lblStatus.Caption = "Loading data into database......"
Dim lngRecCount As Long
lngRecCount = 0
rcdDNE.MoveFirst
With cmdCommand
.ActiveConnection = objConn
.CommandText = "insert into t_DATA_DneFrc (RTN, AccountNbr, FirstName, MiddleName, LastName, Amount) values ('" & rcdDNE("RTN") & "', '" & rcdDNE("AccountNbr") & "', '" & rcdDNE("FirstName") & "', '" & rcdDNE("MiddleName") & "', '" & rcdDNE("LastName") & "', '" & rcdDNE("Amount") & "')"
.CommandType = adCmdText
End With
Set rcddnefrc = New ADODB.Recordset
With rcddnefrc
.ActiveConnection = objConn
.Source = "SELECT * FROM T_DATA_DNEFRC"
.CursorType = adOpenDynamic
.CursorLocation = adUseClient
.LockType = adLockOptimistic
.Open
End With
Do Until rcdDNE.EOF
lngRecCount = lngRecCount + 1
frmDNELoad.lblStatus.Caption = "Adding record " & lngRecCount & " of " & rcdDNE.RecordCount & " to database."
frmDNELoad.Refresh
DoEvents
Call CommitNew
rcdDNE.MoveNext
Loop
frmDNELoad.lblStatus.Caption = "DNE Processing Complete."
frmDNELoad.Refresh
End Function
Sub CommitNew()
' Add records to DneFrc table
With rcddnefrc
.Requery
.AddNew
.Fields![RTN] = rcdDNE.Fields![RTN]
.Fields![AccountNbr] = rcdDNE.Fields![AccountNbr]
.Fields![FirstName] = rcdDNE.Fields![FirstName]
.Fields![MiddleName] = rcdDNE.Fields![MiddleName]
.Fields![LastName] = rcdDNE.Fields![LastName]
.Fields![Amount] = rcdDNE.Fields![Amount]
.Update
End With
End Sub
More of a strategy then a specific answer but ...
When importing data from external sources we'll often insert the data into staging tables that do not have the same keys/contraints placed on them and then sanitize the data prior to insertion.
What is done during "sanitation" depends on your requirements (for example, when you have two of the same account numbers are the records the same or are the data fields different, if the fields are different, how do you choose which data to use?). And then insert/move it into the production table once sanitization is complete.
I ran into this problem and what I did is to make a collection that I stored the object and the key into the Key. If I try to add a duplicated key I get an error.
This is the easyest way I found to do this in vb6. in c# is dictionary.
My suggestion would be to add error handling to CommitNew to see if the row inserted would create a primary key violation, and if so then perform other handling.
Example:
Sub CommitNew()
''#Add records to DneFrc table
On Error GoTo CommitNew_Error
With rcddnefrc
.Requery
.AddNew
.Fields![RTN] = rcdDNE.Fields![RTN]
.Fields![AccountNbr] = rcdDNE.Fields![AccountNbr]
.Fields![FirstName] = rcdDNE.Fields![FirstName]
.Fields![MiddleName] = rcdDNE.Fields![MiddleName]
.Fields![LastName] = rcdDNE.Fields![LastName]
.Fields![Amount] = rcdDNE.Fields![Amount]
.Update
End With
Exit Sub ''# If no error, exit routine.
CommitNew_Error:
If Err.Number = -2147217873 Then
''# code here will only execute if the constraint violation occurs
Call WriteDuplicateAccountToFile()
Err.Clear() ''# This clears the error, since you handled it
Else
''# Do stuff with other errors.
''# If you're not sure, at least display what error its giving, like so
MsgBox "The following error was encountered when new record was saved:" & _
vbNewLine & CStr(Err.Number) & " - " & Err.Description & vbNewLine & _
"New record not saved.", vbOkOnly + vbCritical, "Error"
End If
End Sub

Resources