Datasheet dynamic load and lost of parameters value from a query - ms-access

I have a datasheet form in MS Access 2016, and I set the dynamic source via VBA code as below
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb
Set qdf = CurrentDb.QueryDefs("qry_GetSumEmployeesHoursByPeriodAndProject")
qdf.Parameters("projectID") = IIf(ProjectID = -1, Null, ProjectID)
qdf.Parameters("periodID") = IIf(PeriodID = -1, Null, PeriodID)
Set Me.Recorset = qdf.OpenRecordset()
qdf.Close
dbs.Close
Set qdf = Nothing
Set dbs = Nothing
As you can see, the data is loaded via a parameterized query qry_GetSumEmployeesHoursByPeriodAndProject and it expects 2 parameters:
PARAMETERS periodID Long = NULL, projectID Long = NULL;
SELECT ...
Initially, when the form loads, everything is fine, but whenever I click on a column header for sorting or filtering, the form loads from the same query qry_GetSumEmployeesHoursByPeriodAndProject, but doesn't applies the parameters periodID and projectID, so it takes their values as NULL.
How can I prevent this from happening? Maybe to catch the forms' "Sort" even somehow and apply it to the query, but I was not able to find when and how that event is fired.
Any help is appreciated

You could place the parameters on a form instead of specifying them in the code.
Any form that happens to be open will be fine because you can make them hidden textboxes, and this way you know for sure that the parameter values will be available, not only to the query, but to any other part of the database as well.
You would refer to a the "parameter control" from elsewhere with:
Forms!YourFormName.YourTextboxName
More info:
Office.com : Use parameters in queries, forms, and reports

Related

Store table as recordset of Dynaset type

I am passing a table in the current database to a recordset with 2 dimensions. Currently:
Public Sub MySub(obj As Variant)
Dim dbs As DAO.Database
Dim tbl As DAO.Recordset
Set dbs = CurrentDb
Set tbl = dbs.OpenRecordset("TABLE")
tbl.MoveLast
Records = tbl.GetRows(tbl.RecordCount)
Stop
...
End Sub
Stepping through in my locals window (and checking in the immediate window), I can see that the tbl.RecordCount = 1074 but Records is still only getting the active record with all of the fields, i.e. Records Type is Variant(0 to 37, 0 to 0).
I am able to execute a similar approach when storing a query. I have also tried the syntax:
Set tbl = dbs.OpenRecordset("TABLE",dbOpenDynaset)
And
Set tbl = dbs.OpenRecordset("TABLE",dbOpenTable)
The former had the same issue, and the latter returned Run-time error '3219'.
Edit: example of GetRows with Query (see comments)
Set dbs = CurrentDb
Set rsQuery = dbs.OpenRecordset("QUERY", dbOpenDynaset)
varRecords = rsQuery.GetRows(rsQuery.RecordCount)
If you had read the GetRows Docs, you would have recognized, thatGetRowsreturns records from the actual cursor position and moves the cursor to the next not retrieved row (like.Move).
As you move the cursor to the last record(tbl.MoveLast), no more records are remaining to get.
Solution:
Just move the cursor to the beginning of the Recordset and everything is fine
tbl.MoveLast
tbl.MoveFirst
Records = tbl.GetRows(tbl.RecordCount)
dbOpenTable raises error 3219, if opened table is not local and .OpenRecordset("TABLE",dbOpenDynaset)is equal to .OpenRecordset("TABLE")asdbOpenDynasetis the default value, for non-local tables. (Docs reveal that too ;)

Inserting records in MS Access by means of macros

Good evening!
At this moment I'm learning to work in MS Access for my job purposes. I gained some understanding of the program's basics, such as creating tables or making easy forms (though not yet working ideally), and by now I've got stuck in solving the following task.
I have a database BooksDatabase, which consists of three tables: Books, Authors and AuthorsInfo. First one contains information about books (name, genre, country, release year etc.), third one is about authors (first name, last name etc.) and the second one links ever book with its author(s). The task is to import data from text file to those tables, so that it would be almost automatic. I understand how to import files to MS Access (at least, the ones of *.txt extension) and I do this into the table BooksToImport, but I have some difficulties with inserting imported data. Here is the code of my function ImportBooks(), which I execute from macros of the same name:
' Procedure which imports data about books from the table BooksToImport
Function ImportBooks()
Dim dbBooks As Database
Dim rstImBooks, rstBooks, rstAuthors, rstBALink As DAO.Recordset
Dim codeI, codeB, codeA, codeL As Variant
'initializing database
Set dbBooks = CurrentDb
Set rstImBooks = dbBooks.OpenRecordset("Query_BooksToImport",dbOpenDynaset) 'receiving data from query
'checking if the query has any records
If rstImBooks.RecordCount = 0 Then
MsgBox "There are no records for importing!", vbInformation, "Attention!"
rstImBooks.Close
Set dbBooks = Nothing
Exit Function
End If
'if it's OK, we're making a loop on query's records
rstBooks = dbBooks.OpenRecordset("Books",dbOpenDynaset)
rstAuthors = dbBooks.OpenRecordset("AuthorsInfo",dbOpenDynaset)
rstBALink = dbBoks.OpenRecordset("Authors",dbOpenDynaset)
rstImBooks.MoveLast
rstImBooks.MoveFirst
Do While rstImBooks.EOF = False
'checking if there is a book in out database with the same name as in imported data
codeB = DLookup("[ID]","[Books]","[BookName] = '" & rstImBooks![BookName] & "'")
If IsNull(codeB) Then
'inserting new record
With rstBooks
.AddNew
![BookName] = rstImBooks![BookName]
.Update
.Bookmark = .LastModified
codeB = ![ID]
End With
End If
'in much the same way we're treating the data about authors and making the links
rstImBooks.MoveNext
Loop
rstImBooks.Close
rstBooks.Close
rstAuthors.Close
rstBALink.Close
Set dbBooks = Nothing
End Function
I have two problems with this function:
method .AddNew for rstBooks is not working — MS Access shows me a message with error 438 ("Object doesn't support this property or method");
also I cannot assign variable rstBALink to the recordset because compiler says "Invalid use of property".
So my question is this: how should I solve these two problems? What do I do wrong that my function is not working properly?
A few issues with your code that I see. These may or may not fix your problem.
Your declarations are implicit, meaning you aren't being specific with your code about what your recordset objects are. Instead of using:
Dim rstImBooks, rstBooks, rstAuthors, rstBALink As DAO.Recordset
Try:
Dim rstImBooks As DAO.Recordset
Dim rstBooks As DAO.Recordset
Dim rstAuthors As DAO.Recordset
Dim rstBALink As DAO.Recordset
You can put them all on one line separated by commas, but you still need to declare the type for each or Access will assume it's a variant.
Secondly, recordset objects need to be created using the Set keyword, not by using an = alone.
This was done correctly in the top portion of your code, but is incorrect here:
rstBooks = dbBooks.OpenRecordset("Books",dbOpenDynaset)
rstAuthors = dbBooks.OpenRecordset("AuthorsInfo",dbOpenDynaset)
rstBALink = dbBoks.OpenRecordset("Authors",dbOpenDynaset)
Should be:
Set rstBooks = dbBooks.OpenRecordset("Books",dbOpenDynaset)
Set rstAuthors = dbBooks.OpenRecordset("AuthorsInfo",dbOpenDynaset)
Set rstBALink = dbBooks.OpenRecordset("Authors",dbOpenDynaset)
I think that will solve your issues, but I didn't review every line of your code admittedly. Let me know if you still have problems.
EDIT:
Found a typo:
rstBALink = dbBoks.OpenRecordset("Authors",dbOpenDynaset)
Should be:
Set rstBALink = dbBooks.OpenRecordset("Authors",dbOpenDynaset)
(missed an 'o' in dbBooks)

Using an Input Box to assign value to a parameter

I have the following code
command_Click()
rDate = InputBox("MM/YYYY")
end sub
When I click the command the input box appears and I input my value. But then I get another pop up asking for the parameter value for rDate.
Any thoughts?
I assume you have a query that's like
Select *
From SomeTable
Where acolumn = rDate
The rDate defined in your command_click() sub is not the same thing. That rDate is a local variable which has nothing to do with your query.
You likely want to pass your parameter to a query. Let's say your query is called vikesQuery. Your command button click code would look like this
Dim qdef As DAO.QueryDef
Set qdef = CurrentDb.QueryDefs("vikesQuery")
If qdef Is Nothing Then
Exit Sub
End If
qdef.Parameters("rDate") = InputBox("MM/YYYY") 'though there are much better ways of getting your parameter like a textbox on a form
Dim rs As DAO.Recordset
Set rs = qdef.OpenRecordset
Now your query is in a recordset where you can do lots with it. Typically you would show this on a form.
Dim frm As Form
DoCmd.OpenForm "vikesForm", acNormal
Set frm = Forms("vikesForm")
Set frm.Recordset = rs 'sets the recordset of the form to the recordset you generated from your query.
This last step assumes you have a form set up to accept the structure of this recordset. i.e. textboxes bound to the right columns.

why MS Access2013 is giving "you must enter a value in 'Desc' field" when there is a value already?

I'm new to MS Access and Sharepoint. I've a requirement to link to a sharepoint list within Access (2013) and Insert new record in this linked table (the table which gets created in the Access when we link the sharepoint list). The linked table has multivalued columns. So I'm using the recordset approach to run the INSERT query. Below is what I'm doing.
Option Compare Database
Sub Insert_Query()
Dim dbs As DAO.Database
Dim rs_parent As DAO.Recordset2
Dim rs_child As DAO.Recordset2
Set dbs = CurrentDb
Set rs_parent = dbs.OpenRecordset("TABLENAME")
With rs_parent
.AddNew
![T1] = "test_title"
![W1] = "test_w"
![P1] = "Low"
![A1] = "saleem, Shaik"
![Desc] = "test description" 'LongText type field 'Required Field
Set rs_child = rs_parent![Assigned To].Value
With rs_child
rs_child.AddNew
rs_child!Value = 3160
rs_child.Update
rs_child.Close
End With
rs_parent.Update 'Getting run time error 3314(You must enter a value in 'Desc' Field) on this line
rs_parent.Close
End With
End Sub
I've tried changing rs_parent![Desc] to rs_parent.Fields("Desc") and rs_parent.Fiedls(7)---> 7 is the item number in that collection, but all of them are giving the same error.
Any idea what could be the reason for the error and how to fix it please? Feel free to ask me if you need any further information.
Edit: The above error comes only when I execute the procedure when Access is 'online with Sharepoint'. But The same code works just fine if I convert the TABLENAME into a local table and execute the procedure.

Access VBA recordets - updating a field based on the result of a function that uses other fields as input

I have a simple_table with 4 fields:
a,b,x,P
I am trying to update the field p based on the output of a function that uses the other fields as input parameters. In this case the function is an excel function.
I was using SQL server but really need to access some statistical functions. So yesterday I opened access for the first time. Eeek. I've spent the last day trying to learn vba and following various tutorials on recordsets.
The bit I'm struggling with is how to I update a the P field based on the other fields? In a loop?
Thanks very much.
Dim objExcel As Excel.Application
Set objExcel = CreateObject("Excel.Application")
'Test it works
MsgBox objExcel.Application.BetaDist(0.4, 2, 5)
'OK, that works :)
'set up the ADO stuff
Dim cnn1 As ADODB.Connection
Dim MyRecordSet As New ADODB.Recordset
Set cnn1 = CurrentProject.Connection
MyRecordSet.ActiveConnection = cnn1
'Load data into MyRecordSet
MySQLcmd = "SELECT * FROM simple_table"
MyRecordSet.Open MySQLcmd
'HELP WITH THE NEXT BIT PLEASE!
'Some kind of loop to go through the recordset to set the field P
' equal to the result of the excel function betadist(x,a,b)
'I imagine looping through something like the following semi pseudo code ???
myRecordSet.Fields(“P”).Value = objExcel.Application.BetaDist(myRecordSet.Fields(“x”).Value, myRecordSet.Fields(“a”).Value, myRecordSet.Fields(“b”).Value)
'end of the loop
objExcel.Quit
Set objExcel = Nothing
MyRecordSet.Close
cnn1.Close
Set MyRecordSet = Nothing
Set cnn1 = Nothing
Since your code works with "Dim objExcel As Excel.Application", that means you have a reference set for the Excel object library. In that case, you don't need a full Excel application instance in order to use the BetaDist function. You can set an object variable to Excel.WorksheetFunction and call the function as a method of that object. However, I don't know whether that makes a significant difference. I didn't test the CreateObject("Excel.Application") alternative.
In this sample, I used a DAO recordset instead of ADO. The reason is I've found DAO can be significantly faster with native Access (Jet/ACE) data sources. You can switch to ADO if you prefer, but I don't see an advantage.
Notice I opened the table directly rather than via a query. The DAO dbOpenTable option can also benefit performance.
With those details out of the way, it's just a simple matter of looping through the recordset, calling the function with values from the current row, and storing the function's result in the P field ... pretty much what you outlined in your pseudo-code. :-)
Dim objWFunction As Object ' Excel.WorksheetFunction
Dim MyRecordSet As DAO.Recordset
Dim db As DAO.database
Set objWFunction = Excel.WorksheetFunction ' Excel reference required
Set db = CurrentDb
Set MyRecordSet = db.OpenRecordset("simple_table", dbOpenTable)
With MyRecordSet
Do While Not .EOF
'Debug.Print objWFunction.BetaDist(!x, !a, !b)
.Edit
!p = objWFunction.BetaDist(!x, !a, !b)
.Update
.MoveNext
Loop
.Close
End With
Set MyRecordSet = Nothing
Set db = Nothing
Set objWFunction = Nothing