Is it possible to execute a prepared statement in MS Access on a local table in VBA like this:
UPDATE part SET part_description=? WHERE part_id=?
If so how is it done?
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strSql As String
Set db = CurrentDb
strSql = "UPDATE Month_Totals Set item_date = [which_date]" & _
" WHERE id = [which_id];"
Debug.Print strSql
Set qdf = db.CreateQueryDef(vbNullString, strSql)
With qdf
.Parameters("which_date").Value = Date()
.Parameters("which_id").Value = 1
.Execute dbFailOnError
End With
That example used a new, unsaved QueryDef. If you have a saved parameter query, you can use it instead by substituting this line for the CreateQueryDef line:
Set qdf = db.QueryDefs("YourQueryName")
Either way, you can then refer to individual parameters by their names as I did, or by their positions in the SQL statement ... so this will work same as above:
.Parameters(0).Value = Date()
.Parameters(1).Value = 1
Additional notes:
.Value is the default property for a Parameter, so including it here is not strictly required. On the other hand, it doesn't hurt to be explicit.
As Gord noted below, you can use "Bang notation" with the parameter's name like !which_id, which is more concise than .Parameters("which_id")
Related
I am trying to write a MS Access report based on a query that I can programically put the a date range in using VBA. I set up the query with Between [StartDate] and [EndDate] as the criteria. Then I have the following code on a form:
Private Sub AutoReport1_Click()
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set qdf = CurrentDb.QueryDefs("MixByRangeA")
qdf.Parameters("StartDate").Value = #10/2/2014#
qdf.Parameters("EndDate").Value = #11/2/2014#
Set rst = qdf.OpenRecordset()
End Sub
Nothing seems to happen. Should the query open and show on the screen? I have tried a few code variations of the above based on my internet searches but nothing works.
Nothing is happening because you're not doing anything with qdf and rst after you set them. I'm not entirely sure what you're trying to accomplish, but:
1. If you want to open a Report whose RecordSource is the results of the Query (with parameters dynamically set), try placing the following in the Report's code module:
Private Sub Report_Open(Cancel As Integer)
Dim db As DAO.Database: Set db = CurrentDb
Dim qdf As DAO.QueryDef
Dim sql As String
Set qdf = db.QueryDefs("MixByRangeA")
sql = qdf.sql
sql = Replace(sql, "[StartDate]", "#10/2/2014#")
sql = Replace(sql, "[EndDate]", "#11/2/2014#")
Me.RecordSource = sql
On Error Resume Next
qdf.Close: Set qdf = Nothing
db.Close: Set db = Nothing
End Sub
And in the Form, use this to open the Report:
Private Sub AutoReport1_Click()
DoCmd.OpenReport "Report1", acViewReport
End Sub
2. If instead you just want to open the Query (with parameters dynamically set), try the following:
Public Sub AutoReport1_Click()
Dim db As DAO.Database: Set db = CurrentDb
Dim qdf As DAO.QueryDef
Dim sql As String
Set qdf = db.QueryDefs("MixByRangeA")
sql = qdf.sql
sql = Replace(sql, "[StartDate]", "#10/2/2014#")
sql = Replace(sql, "[EndDate]", "#11/2/2014#")
qdf.sql = sql
DoCmd.OpenQuery (qdf.Name)
On Error Resume Next
qdf.Close: Set qdf = Nothing
db.Close: Set db = Nothing
End Sub
I don't think it can be done the way simple way you want.
This seems a shame because you've followed what could be considered 'best practise' by using a stored procedure with parameters parameters, rather than constructing dynamic SQL.
The truth is, even if it is good practise generally, you are guilty of going against the natural flow of how the Access Team want you use its software! Looks like you are compelled to dynamically construct a WHERE clause to squirt into the provided method :(
The easy method is to remove the parameters from the query and apply a filter to the report:
Dim StartDate As Date
Dim EndDate As Date
StartDate = #10/2/2014#
EndDate = #11/2/2014#
DoCmd.OpenReport "YourReport", , , "[YourDateField] Between #" & Format(StartDate, "yyyy\/mm\/dd") & "# And #" & Format(EndDate, "yyyy\/mm\/dd") & "#"
Is there any way I can make Access 2013 display created and modified date? Access 2003 used to display those features and can't seem to find any solution to Access 2013?
You can right-click the object list header, and do View -> Details. But that's still not a very good overview.
(Oh how I miss the Access 2003 database window...)
A better way is to query the MSysObjects table, e.g.:
SELECT MSysObjects.Type, MSysObjects.Name, MSysObjects.DateUpdate, MSysObjects.DateCreate
FROM MSysObjects
WHERE (((MSysObjects.Type)<>2 And (MSysObjects.Type)<>3 And (MSysObjects.Type)<>-32757)
AND ((Left([Name],1))<>'~') AND ((Left([Name],4))<>'Msys'))
ORDER BY MSysObjects.Type, MSysObjects.Name;
See here for the object type constants:
Meaning of MsysObjects values -32758, -32757 and 3 (Microsoft Access)
You may also be interested in this free "Database window replacement" add-in:
http://www.avenius.de/index.php?Produkte:DBC2007
If Access hasn't got a baked-in solution and you have a lot of objects to look at, you could always create your own with a table set up something like this:
And then write some VBA to loop through the object collections and write the properties you're interested in to the above table. The example below loops through the Tables and Queries collections, but you could write additional loops for Forms, Reports, etc. (There may even be a simpler way to just loop through all Access objects).
Public Sub CreatedModified()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim tdf As DAO.TableDef
Dim qdf As DAO.QueryDef
Dim strSql As String
strSql = "DELETE * FROM tblCreatedModified"
Set db = CurrentDb
db.Execute strSql
Set rs = db.OpenRecordset("tblCreatedModified")
With rs
' tables
For Each tdf In db.TableDefs
If Not (tdf.Name Like "*MSys*" Or tdf.Name Like "~*") Then
.AddNew
!ObjectType = "Table"
!ObjectName = tdf.Name
!DateCreated = tdf.DateCreated
!DateModified = tdf.LastUpdated
.Update
End If
Next
' queries
For Each qdf In db.QueryDefs
If Not (qdf.Name Like "*MSys*" Or qdf.Name Like "~*") Then
.AddNew
!ObjectType = "Query"
!ObjectName = qdf.Name
!DateCreated = qdf.DateCreated
!DateModified = qdf.LastUpdated
.Update
End If
Next
End With
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
This seemingly simple problem has me stopped dead in my tracks for three days now.
My code:
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("qryAutoOrder", dbOpenDynaset)
qryAutoOrder is a select query which runs just fine by itself and has no parameters (unless criteria in the query builder count).
When the code runs it hangs on the set rs = line and throws this error.
Run-time error '3061': Too few parameters. Expected 1.
There is more to the code where I would like it to run a loop for each record in the query results so that I can append data to another existing databases tables but it is currently commented out.
OpenRecordset does not resolve the form reference ([Forms]![completeRepair]![txtRepairID]) in the query. In that situation, it is interpreted as a parameter for which you have not supplied a value.
So give it the parameter value via Eval(prm.Name) ...
Dim rs As DAO.Recordset
Dim db As DAO.database
Dim prm As DAO.Parameter
Dim qdf As DAO.QueryDef
'Set rs = CurrentDb.OpenRecordset("qryAutoOrder", dbOpenDynaset)
Set db = CurrentDb
Set qdf = db.QueryDefs("qryAutoOrder")
For Each prm In qdf.Parameters
prm.value = Eval(prm.Name)
Next
Set rs = qdf.OpenRecordset(dbOpenDynaset)
You don't actually need a For loop there; that's just the way I set these up by habit. But you could just give it the single parameter value instead ...
qdf.Parameters(0).Value = [Forms]![completeRepair]![txtRepairID]
I have the following code:
Private Sub lst1Model_Operation_Click()
Dim db As Database
Dim sSQL As String
Dim rst As Recordset
Set db = CurrentDb
sSQL = "SELECT * FROM qryOrder_Model_Operation_Value WHERE Model_Operation_ID = " & CInt(Me![lst1Model_Operation].Value)
Debug.Print sSQL 'when pasted this into a query SQL, it works flawlessly.
Set rst = db.OpenRecordset(sSQL) 'error line
'some code here
rst.Close
Set db = Nothing
End Sub
I'm at loss at what to do. The Debug.Print looks like:
SELECT * FROM qryOrder_Model_Operation_Value WHERE Model_Operation_ID = 748
And as I said, if I paste that Debug.Print into a Query in the Access itself, it produces the desired results.
I have tried adding ' ' around the value, but using CInt() I already made sure it is parsed as integer. The Model_Operation_ID also expects to get an integer (otherwise it wouldn't work in a separate query either).
Edit:
The qryOder_Model_Operation_Value is as follows:
SELECT tbl1Model_Operation.Model_Operation_ID, tbl1Model_Operation.Model_ID, tbl1Model_Operation.Operation_Value_ID, tbl2Operation_Value.Operation_Name_ID, tbl3OperationsList.Operation_Name, tbl1Order_Model.Quantity AS [Počet párov], tbl1Order_Model.Order_ID
FROM tbl3OperationsList INNER JOIN (tbl2Operation_Value INNER JOIN (tbl1Model_Operation INNER JOIN tbl1Order_Model ON tbl1Model_Operation.Model_ID = tbl1Order_Model.Model_ID) ON tbl2Operation_Value.Operation_Value_ID = tbl1Model_Operation.Operation_Value_ID) ON tbl3OperationsList.Operation_ID = tbl2Operation_Value.Operation_Name_ID;
Make sure Access understands you want rst to be a DAO.Recordset instead of an ADODB.Recordset:
'Dim rst As Recordset
Dim rst As DAO.Recordset
Both the ADO and DAO object models include Recordset objects. Although similar in some respects, they can not be used interchangeably.
When your Access VBA project references include a version of ADO (ActiveX Data Objects) and that reference has a higher priority than the DAO reference, Dim rst As Recordset will give you an ADODB.Recordset. Avoid unwelcome surprises by always qualifying your Recordset declarations with DAO or ADODB as appropriate.
Try this way:
Set rst = db.OpenRecordset(sSQL,dbOpenTable)
or
Set rst = db.OpenRecordset(sSQL,dbOpenSnapshot)
I am trying to set a recordset that keeps giving me the error message - "Runtime Error 3061 Too few parameters. Expected 1".
The query checks to see what value is in a combo box and then returns two fields. This is the VBA code I tried -
Dim db As Database
Dim rst As Recordset2
Dim field As field
Dim n As Integer
Dim Qno As Integer
Dim sqlstr As String
Set db = DBEngine(0)(0)
Set rst = db.OpenRecordset("Get_Questions", dbOpenDynaset)
This is the SQL behind the Get_Questions Query -
SELECT Question_Lt.Qnumber, Question_Lt.Questions, Question_Lt.Freq
FROM Question_Lt
WHERE (((Question_Lt.ClientCd)=[Forms]![TestForm]![CmClient]));
Use your query as a QueryDef object, supply the parameter value, and then use its OpenRecordset method to populate your recordset.
'Set rst = db.OpenRecordset("Get_Questions", dbOpenDynaset)
Dim qdf As DAO.QueryDef
Set qdf = db.QueryDefs("Get_Questions")
qdf.Parameters(0).Value = [Forms]![TestForm]![CmClient]
Set rst = qdf.OpenRecordset(dbOpenDynaset)
i ve to few reputation points to comment your question. But what ist the SQL Statement exactly. It seems to me that your ' ' are not set but i don' t know
Im Just guessing: Sql Script for Get_Questions should be something like that. I don' t know the parameter "Get_Questions" is it a query-name?
sqlStr =
"SELECT...
FROM Question_LT
WHERE Client.Cd = " & [Forms]![TestForm]![CmClient]