DAO.QueryDef shows incorrect result in MS Access 2010 - vba

I have the following stored query in MS Access
SELECT
tblRegistration.ID,
tblRegistration.TypeCode,
CDate([tblRegistration].[RegStart]) AS Reg1,
CDate([tblRegistration].[RegStop]) AS Reg2
FROM
tblRegistration
WHERE
(
(tblRegistration.TypeCode = "T" Or tblRegistration.TypeCode = "S" Or tblRegistration.TypeCode = "F")
AND
(CDate([tblRegistration].[RegStart]) Between CDate([Forms]![frmRegBilling]![RegStart]) And CDate([Forms]![frmRegBilling]![RegStop]))
)
OR
(
(tblRegistration.TypeCode = "T" Or tblRegistration.TypeCode = "S" Or tblRegistration.TypeCode = "F")
AND
(CDate([tblRegistration].[RegStop]) Between CDate([Forms]![frmRegBilling]![RegStart]) And CDate([Forms]![frmRegBilling]![RegStop]))
);
The query, when stand alone executed as query (when the frmRegBilling is loaded with the parameters used by the query) shows the proper result (8 records).
But when the query is executed in VBA, only 2 records are shown. In this case, only the first parameter is validated.
Dim qdf As DAO.QueryDef, rst As Recordset, varData As Variant
Dim intFields As Integer, intRecords As Integer, j As Integer, k As Integer
Dim rec As String, fld_type As Integer
Set qdf = CurrentDb.QueryDefs("Query1")
qdf.Parameters(0).Value = Eval(qdf.Parameters(0).Name)
qdf.Parameters(1).Value = Eval(qdf.Parameters(1).Name)
Set rst = qdf.OpenRecordset()
j = rst.RecordCount - 1
k = rst.Fields.Count - 1
Switching the lines Parameter(0) or (1) doesn't help (if of influence for any reason). Why aren't both parameters validated in the query when executed in VBA?

If you are using VBA, why not create this as a Run time Query?
Dim strSQL As String, rst As Recordset, varData As Variant
Dim intFields As Integer, intRecords As Integer, j As Integer, k As Integer
Dim rec As String, fld_type As Integer
strSQL = "SELECT tblRegistration.ID, tblRegistration.TypeCode, CDate([tblRegistration].[RegStart]) AS Reg1, " & _
"CDate([tblRegistration].[RegStop]) AS Reg2 FROM tblRegistration WHERE " & _
"((tblRegistration.TypeCode = 'T' Or tblRegistration.TypeCode = 'S' Or tblRegistration.TypeCode = 'F') AND " & _
"(CDate([tblRegistration].[RegStart]) Between " & Format([Forms]![frmRegBilling]![RegStart], "\#mm\/dd\/yyyy\#") & _
" And " & Format([Forms]![frmRegBilling]![RegStop], "\#mm\/dd\/yyyy\#") & ")) OR " & _
"((tblRegistration.TypeCode = 'T' Or tblRegistration.TypeCode = 'S' Or tblRegistration.TypeCode = 'F') " & _
"AND (CDate([tblRegistration].[RegStop]) Between " & Format([Forms]![frmRegBilling]![RegStart], "\#mm\/dd\/yyyy\#") & _
" And " & Format([Forms]![frmRegBilling]![RegStop], "\#mm\/dd\/yyyy\#") & "));"
Set rst = CurrentDb.OpenRecordset(strSQL)

Related

How to bring a recordset into a table in Access

an access newbie here. I am trying to write a VBA code to query from an SQL database, and append the values into an access table. For this, i wrote below code but so far, i could only write a query and create a connection to the server. But i don't know how to bring it into the access table. Can you help me with this?
Sub getInv()
Dim RowCount As Long, ColCount As Long
Dim cnn As Object
Dim RS As Object
Set cnn = CreateObject("ADODB.Connection")
Set RS = CreateObject("ADODB.Recordset")
Dim SQLQuery As String
SQLQuery = _
"SELECT " & _
"PSDDD.SDDPP, PSDDD.SPPRD " & _
"WHERE " & _
"PSDDD.SDDPP = '2244556'" & _
"ORDER BY " & _
"PSDDD.SDDPP ASC, PSDDD.SPPRD DESC "
ConnectString = _
"DRIVER={Client Access ODBC Driver (32-bit)};" & _
"UID=abbsx;PWD=password;" & _
"SYSTEM=ABCSQT;DBQ=SSTNCHP22DB;"
cnn.Open (ConnectString)
RS.Open SQLQuery, cnn
' I believe i should put the code for writing into access table here.
'Close the Recordset and Connection
RS.Close
cnn.Close
Set RS = Nothing
Set cnn = Nothing
Exit Sub
erden. I hope this code gives you inspiration to solve your problem.
Public Function appendSelectedStudentsIntoPoolTable(Interest As String) As Long
Dim rSQL As String, rParams As String
Dim aSQL As String, aParams As String
Dim sourceTable As String, targetTable As String
sourceTable = "tStudents"
targetTable = "tStudentsPool"
'Note for targetTable: ID column not set to autonumber because to preserve
'original data as in the source table. But you can use it as PK as long no
'duplication on IDs.
rParams = "PARAMETERS [par_interest] Text(50); "
rSQL = rParams & "SELECT ID, Email, FirstName " & _
"FROM " & sourceTable & _
" WHERE Interest = par_interest;"
aParams = "PARAMETERS [par_ID] Long, [par_Email] Text(255), " & _
"[par_FirstName] Text(50); "
aSQL = aParams & "INSERT INTO " & targetTable & _
" (ID, Email, FirstName) " & _
"VALUES (par_ID, par_Email, par_FirstName);"
Dim db As DAO.Database
Dim rQDf As DAO.QueryDef
Dim aQdf As DAO.QueryDef
Dim rs As DAO.Recordset
Dim rec As Variant
Dim rsCount As Long 'change data type as needed
Dim appendedCount As Long 'same as rsCount data type
Dim i As Long 'same as rsCount data type
'On Error GoTo commit_failed
Set db = CurrentDb
Set rQDf = db.CreateQueryDef("", rSQL)
rQDf.Parameters("par_interest") = Interest
Set rs = rQDf.OpenRecordset()
With rs
On Error Resume Next: .MoveLast
On Error Resume Next: .MoveFirst
If .RecordCount > 0 Then
Do While Not rs.EOF
Set aQdf = db.CreateQueryDef("", aSQL)
aQdf.Parameters("par_ID") = !ID
'add routine(s) to check existing ID on pool table here
'before record append to pool table
'to prevent duplicate ID. For now, i skip it.
aQdf.Parameters("par_Email") = !Email
aQdf.Parameters("par_FirstName") = !FirstName
aQdf.Execute dbFailOnError
aQdf.Close
appendedCount = appendedCount + 1
.MoveNext
Loop
.Close
rQDf.Close
End If
End With
appendSelectedStudentsIntoPoolTable = appendedCount: Exit Function
commit_failed:
appendSelectedStudentsIntoPoolTable = 0
'You can put error handler here
End Function

Microsoft Access VBA Run Time Syntax Error for SQL Query

Here is my updated code per #Parfait suggestion. It still isn't working, getting the following error:
Run-time error '3421'
Data type conversion error
On the following line: Set rec = qdef.OpenRecordset(strQry)
Option Compare Database
Private Sub Command0_Click()
Dim db As DAO.Database
Dim qdef As DAO.QueryDef
Dim rec As DAO.Recordset
Dim olApp As Object
Dim olItem As Variant
Dim strQry As String
Dim aHead(1 To 4) As String
Dim aRow(1 To 4) As String
Dim aBody() As String
Dim lCnt As Long
'Prepared Statement No Data
strQry = "PARAMETERS cboParam TEXT(255);" _
& " SELECT [Loan ID], [Prior Loan ID], [SRP Rate], [SRP Amount] " _
& " FROM emailtable " _
& " WHERE [Seller Name:Refer to As] = [cboParam]"
Set db = CurrentDb
Set qdef = db.CreateQueryDef("", strQry)
' BIND PARAMETER
qdef!cboParam = Me.Combo296
' OPEN RECORDSET
Set rec = qdef.OpenRecordset(strQry)
'Create the header row
aHead(1) = "Loan ID"
aHead(2) = "Prior Loan ID"
aHead(3) = "SRP Rate"
aHead(4) = "SRP Amount"
lCnt = 1
ReDim aBody(1 To lCnt)
aBody(lCnt) = "<HTML><body><table border='2'><tr><th>" & Join(aHead, "</th><th>") & "</th></tr>"
If Not (rec.BOF And rec.EOF) Then
Do While Not rec.EOF
lCnt = lCnt + 1
ReDim Preserve aBody(1 To lCnt)
aRow(1) = rec("[Loan ID]")
aRow(2) = rec("[Prior Loan ID]")
aRow(3) = rec("[SRP Rate]")
aRow(4) = rec("[SRP Amount]")
aBody(lCnt) = "<tr><td>" & Join(aRow, "</td><td>") & "</td></tr>"
rec.MoveNext
Loop
End If
aBody(lCnt) = aBody(lCnt) & "</table></body></html>"
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
With objMail
.Display 'To display message
.To = Me.Combo88
.cc = Me.Combo282
.Subject = "*SECURE* " & Me.Combo296 & " Refund Request (" & Me.Combo212 & " " & Me.Combo284 & ")"
.HTMLBody = "<p><font face=""calibri"" style=""font-size:11pt;"">Greetings,</p>" _
& "<p>We recently acquired loans from " & Me.Combo296 & ", some of which have paid in full and meet the criteria for early prepayment defined in the governing documents. We are requesting a refund of the SRP amount detailed on the attached list.</p>" _
& "<p>Please wire funds to the following instructions:</p>" _
& "<ul>Bank Name: My Bank</ul>" _
& "<ul>ABA: 1111111</ul>" _
& "<ul>Credit To: ABC Mortgage</ul>" _
& "<ul>Acct: 11111111111</ul>" _
& "<ul>Description: " & Combo296 & " EPO SRP Refund</ul>" _
& "<p>Thank you for the opportunity to service loans from " & Me.Combo296 & "! We appreciate your partnership.</p>" _
& "<p>If you have any questions, please contact your Relationship Manager, " & Me.Combo336 & " (Cc'd).</p>" _
& "<p><br>Sincerely,</br>" _
& "<br>Acquisitions</br>" _
& "<br>acquisitions#us.com</br></p>"
End With
rec.Close
Set rec = Nothing: Set qdef = Nothing: Set db = Nothing
End Sub
Any help would be greatly appreciated.
Avoid concatenating VBA data to SQL even HTML strings. Instead, consider the industry standard of SQL parameterization.
Dim db DAO.Database, qdef As DAO.QueryDef, rec AS DAO.Recordset
' PREPARED STATEMENT (NO DATA)
strQry = "PARAMETERS cboParam TEXT(255);" _
& " SELECT [Loan ID], [Prior Loan ID], [SRP Rate], [SRP Amount] " _
& " FROM emailtable " _
& " WHERE [Seller Name:Refer to As] = [cboParam]"
Set db = CurrentDb
Set qdef = db.CreateQueryDef("", strQry)
' BIND PARAMETER
qdef!cboParam = Me.Combo296
' OPEN RECORDSET
Set rec = qdef.OpenRecordset()
... ' REST OF CODE USING rec
rec.Close
Set rec = Nothing: Set qdef = Nothing: Set db = Nothing
Also, consider saving the email message HTML markup as a text in the table or as text box on form with placeholders to be replaced with combo box values:
.HTMLBody = Replace(Replace(Me.EmailMessage, "placeholder1", Me.Combo296),
"placeholder2", Me.Combo336)
I'm guessing (from your photo) that the data type of your [Seller Name:Refer to as] column is supposed to be string? In which case, your query is missing quotes to denote the string value in your comparison:
'Create each body row
strQry = "Select * from emailtable where [Seller Name:Refer to As] = """ & Me.Combo296 & """"
Set db = CurrentDb
Set rec = CurrentDb.OpenRecordset(strQry)

Microsoft Visual Basic - Run-time error '3075: Syntax error (missing operator) in query expression "1st", 'A', 1-Jan-15', '1')'

I'm trying to add 50,000 records to my Tournament_Result table in Microsoft Access but I have encountered this error: Run-time error '3075: Syntax error (missing operator) in query expression "1st", 'A', 1-Jan-15', '1')'.
Option Compare Database
Option Explicit
Sub arrayData()
Dim TournamentResult() As Variant
Dim DivisionEntered() As Variant
Dim DateOfTournament() As Variant
Dim num As Long, TournamentResultNo As Long, MembershipNo As Long, dbs As Database, InsertRecord As String
Dim num1 As Long 'we need to declare num1 as an Integer to create a loop
Dim TournamentResultDescription As String, DivisionEnteredDescription As String, DateOfTournamentDescription As String
Set dbs = CurrentDb()
TournamentResultNo = 0
MembershipNo = 0
TournamentResultNo = TournamentResultNo + 1
TournamentResult = Array("1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th")
DivisionEntered = Array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J")
DateOfTournament = Array("1-Jan-15", "2-Feb-15", "3-Mar-15", "4-Apr-15", "5-May-15", "6-Jun-15", "7-July-15", "8-Aug-15", "9-Sep-15", "10-Oct-15", "11-Nov-15", "12-Dec-15")
MembershipNo = MembershipNo + 1
For num1 = 0 To 50000
num = Int((50000 - 0 + 1) * Rnd + 0)
TournamentResultDescription = TournamentResult(num)
DivisionEnteredDescription = DivisionEntered(num)
DateOfTournamentDescription = DateOfTournament(num)
InsertRecord = "insert into TOURNAMENT_RESULT(TournamentResultNo, TournamentResult, DivisionEntered, DateOfTournament, MembershipNo) values (" & "'" & TournamentResultNo & "'" & "," & "'" & TournamentResultDescription & "'" & "'" & "," & "'" & DivisionEnteredDescription & "'" & "," & "'" & DateOfTournamentDescription & "'" & "," & "'" & MembershipNo & "'" & ")"
dbs.Execute InsertRecord
Debug.Print TournamentResultNo; TournamentResultDescription; DivisionEnteredDescription; DateOfTournamentDescription; MembershipNo
Next
End Sub
EDIT: dbs.Execute InsertRecord is highlighted as the problem
Commenters are correct in their suggestions.
These types of dynamic statements can be difficult to debug because of the concatenated strings - and you're making it doubly worse by doing extra concatenation of delimiters and commas.
To me it looks like you just had an extra single quote ("'") in your SQL.
Try:
InsertRecord = _
"insert into TOURNAMENT_RESULT(TournamentResultNo, TournamentResult, DivisionEntered, DateOfTournament, MembershipNo) values ('" & _
TournamentResultNo & "','" & TournamentResultDescription & "','" & _
DivisionEnteredDescription & "','" & DateOfTournamentDescription & _
"','" & MembershipNo & "')"
This is probably what you are after:
Public Function InsertRange()
Const Results As Long = 50000
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim Num101 As Integer
Dim Num102 As Integer
Dim Num12 As Integer
Dim ResultNo As Long
Set dbs = CurrentDb()
Set rst = dbs.OpenRecordset("Select Top 1 * From TOURNAMENT_RESULT")
Randomize
For ResultNo = 1 To Results
Num101 = 1 + Int(10 * Rnd)
Num102 = 1 + Int(10 * Rnd)
Num12 = 1 + Int(12 * Rnd)
rst.AddNew
rst!TournamentResultNo.Value = ResultNo
rst!TournamentResult.Value = CStr(Num101) & "st"
rst!DivisionEntered.Value = Chr(64 + Num102)
rst!DateOfTournament.Value = DateSerial(2015, Num12, Num12)
rst!MembershipNo.Value = ResultNo
rst.Update
Next
rst.Close
Set rst = Nothing
Set dbs = Nothing
End Function

UDF function in Excel running ACE SQL query, JOIN two tables does not work

I am trying to figure out what wrong may be with a function in Excel that tries to join two tables. I presume the error is somewhere in SQL string.
The function works well without a join, returning correctly a table to an array - range of cells. ie when strSQL is only "SELECT * FROM [" & currAddress & "] "
It does not work when the string contains a join, ie strSQL = "SELECT * FROM [" & currAddress & "] " & _
"LEFT JOIN [" & currAddress2 & "] ON [Indeks].[" & currAddress & "] = [Indeks2].[" & currAddress2 & "];"
Here is my code, thank you for help:
Function SQL(dataRange As Range, dataRange2 As Range) As Variant
Application.Volatile
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim currAddress, currAddress2 As String
Dim varHdr, varDat, contentOut As Variant
Dim nc, nr, i, j As Long
SQL = Null
currAddress = ActiveSheet.Name & "$" & dataRange.Address(False, False)
Debug.Print currAddress
currAddress2 = ActiveSheet.Name & "$" & dataRange2.Address(False, False)
Debug.Print currAddress2
strFile = ThisWorkbook.FullName
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _
& ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=0"";"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseClient ' required to return the number of rows correctly
cn.Open strCon
strSQL = "SELECT * FROM [" & currAddress & "] " & _
"LEFT JOIN [" & currAddress2 & "] ON [Indeks].[" & currAddress & "] = [Indeks2].[" & currAddress2 & "];"
Debug.Print strSQL
rs.Open strSQL, cn
'Check if recordset is empty
If rs.EOF Then
MsgBox "Function does not return any values"
SQL = ""
Exit Function
End If
' Process Column Headings
nc = rs.Fields.Count
ReDim varHdr(nc - 1, 0)
For i = 0 To rs.Fields.Count - 1
varHdr(i, 0) = rs.Fields(i).Name
Next
' Get Rows from the Recordset
nr = rs.RecordCount
varDat = rs.GetRows
' Combing Header and Data and Transpose
ReDim contentOut(0 To nr, 0 To nc - 1)
For i = 0 To nc - 1
contentOut(0, i) = varHdr(i, 0)
Next
For i = 1 To nr
For j = 0 To nc - 1
contentOut(i, j) = varDat(j, i - 1)
Next
Next
' Optional solution: Write Output Array to Sheet2
' With Sheet2
' .Cells.Clear
' .Range("A1").Resize(nr, nc) = contentOut
' End With
'Figure out size of calling range which will receive the output array
Dim nRow As Long: nRow = Application.Caller.Rows.Count
Dim nCol As Long: nCol = Application.Caller.Columns.Count
'Error if calling range too small
If nRow < UBound(contentOut, 1) Or nCol < UBound(contentOut, 2) Then
'Popup message
'MsgBox "your range is too small."
' or return #VALUE! error
SQL = "Too small range" 'CVErr(xlValue)
' or both or whatever else you want there to happen
Exit Function
End If
'Initialise output array to match size of calling range
Dim varOut As Variant
ReDim varOut(1 To nRow, 1 To nCol)
'And fill it with some background value
Dim iRow As Long
Dim iCol As Long
For iRow = 1 To nRow
For iCol = 1 To nCol
varOut(iRow, iCol) = "" ' or "funny bear", or whatever
Next
Next
'Put content in output array and return
For iRow = 0 To UBound(contentOut, 1)
For iCol = 0 To UBound(contentOut, 2)
varOut(iRow + 1, iCol + 1) = contentOut(iRow, iCol)
Next
Next
SQL = varOut
'Cleanup
Erase contentOut
Erase varHdr
Erase varDat
rs.Close
Set rs = Nothing
Set cn = Nothing
End Function
It looks like you are not specifying the fields/columns in the join. Both currAddress and curAddress2 look like tables. The SQL should be something like:
strSQL = "SELECT * FROM [Table1] " & _
"LEFT JOIN [Table2] ON [Table1].[Field] = [Table2].[Field];"
Are Indeks and Indeks2 your field names? If so, you need to place the field name after the table name:
strSQL = "SELECT * FROM [" & currAddress & "] " & _
"LEFT JOIN [" & currAddress2 & "] ON [" & currAddress & "].[Indeks] = [" & currAddress2 & "].[Indeks2];"
I believe 'Indeks' is your common field in the two tables, then strSQL should be this:
strSQL = "SELECT * FROM [" & currAddress & "] " & _
"LEFT JOIN [" & currAddress2 & "] ON [" & currAddress & "].[Indeks] = [" & currAddress2 & "].[Indeks]"

Microsoft Query in Excel SQL Criteria Variant Type causes OLE error

Public Sub SQLSelect(connection As String, range1 As Excel.range, _
range2 As Excel.range, Optional range1name As String, Optional range2name As String,_
Optional varparameter As Variant, Optional varcriteria As Variant, _
Optional varnot As Variant, Optional sdestination As String,_
Optional srangename As String, Optional sqlrange As String)
Dim sselect As String
Dim cn As ADODB.connection
Dim rs As ADODB.Recordset
Dim cm As ADODB.Command
Dim pm As ADODB.Parameter
Dim iiterator As Integer
Dim varcriteriterator As Variant
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.recordset")
Set cm = New ADODB.Command
sselect = "SELECT " & range1name & ".ENTITYREF, SUM(" & range1name & ".AMT), SUM(" & range2name & ".AMT) FROM " & range1name & " " & range1name & " INNER JOIN " & range2name & " " & range2name & " ON " & range1name & ".ENTITYREF" & " = " & range2name & ".ENTITYREF WHERE "
cn.Open (connection)
With cm
.ActiveConnection = cn
.CommandType = adCmdText
For iiterator = 0 To UBound(varparameter)
If iiterator = 0 Then
sselect = sselect & range1name & "." & varparameter(iiterator) & " = ? "
Else
sselect = sselect & " AND " & range1name & "." & varparameter(iiterator) & " = ? "
End If
If Not CStr(varcriteria(iiterator)) = varcriteria(iiterator) Then
For Each varcriteriterator In varcriteria
Set pm = .CreateParameter(varparameter(iiterator), adNumeric, adParamInput)
If varnot(iiterator) = 0 Then
pm.Value = varcriteriaiterator
ElseIf varnot(iiterator) = 1 Then
pm.Value = "NOT" & varcriteriaiterator
End If
cm.Parameters.Append pm
Next
Else
Set pm = .CreateParameter(varparameter(iiterator), adNumeric, adParamInput)
If varnot(iiterator) = 0 Then
pm.Value = varcriteria(iiterator)
ElseIf varnot(iiterator) = 1 Then
pm.Value = "NOT" & varcriteria(iiterator)
End If
.Parameters.Append pm
End If
Next iiterator
End With
sselect = sselect & "GROUP BY " & range1name & ".ENTITYREF HAVING(((Count(" & range1name & ".AMT))>1) AND ((Count(" & range2name & ".AMT))>1));"
cm.CommandText = sselect
Set rs = cm.Execute
ThisWorkbook.Sheets("SourcePivot").range(sdestination).CopyFromRecordset rs
ThisWorkbook.Sheets("SourcePivot").range(sdestination, ThisWorkbook.Sheets("SourcePivot").range(sdestination).End(xlDown).Offset(, 2)).Name = srangename
ThisWorkbook.Sheets("Interface").range(sqlrange).Value = sselect
The above code is intended to create a query within an excel workbook which can be passed two ranges of data and create a functional SQL statement through microsoft query to draw the information into a destination range. VarNot is an array of 1&0's which mark whether the matching criteria should be a NOT, and the SQL range is a destination cell which houses the query for troubleshooting.
I have received the following error:
Multi-Step OLE DB operation generated errors. Check each OLE DB Status
value, if available. No work was done.
This is after the code executed properly and create a well-formed query:
SELECT Case1.ENTITYNUM, SUM(Case1.AMT), SUM(Case2.AMT) _
FROM Case1 Case1 INNER JOIN Case2 Case2 ON Case1.ENTITYNUM = Case2.ENTITYNUM _
WHERE Case1.Code = ? AND Case1.YEAR = ? _
GROUP BY Case1.ENTITYNUM HAVING(((Count(Case1.AMT))>1) AND ((Count(Case2.AMT))>1));
I will end passing the module a variety of criteria and parameters, but the parameters are, at this point, exclusive an array of text strings. The criteria are arrays of strings and ranges, which I believe is causing the issue.
I would appreciate any help in solving the error and successfully parameterizing this query with an array that may contain a string or variant range of cells.