I have created a query OrderAllQuery from 3 related tables. One of the fields is a date field that has the same name in the original table and the query named OrdDate.
I have a simple sub to run the query and then run a report for a specific date range. OrdDate must fall within the range. The sub (see below) shows a 2465 on the Odate = line.
Can't see the problem. Any advice would be welcome
Private Sub cmdOrders_Click()
DoCmd.OpenQuery "OrderAllQuery"
Dim Odate As Date
Odate = [OrderAllQuery.OrdDate]
DoCmd.Close acQuery, "OrderAllQuery"
Call RunReport("Orders Report", Odate, Me.txtDateFrom, Me.txtDateTo)
End Sub
Note that the OpenQuery method of the DoCmd object will merely open a query of the given name in datasheet view (assuming that the query is not an action query, and the view argument has not been specified); you cannot then obtain data directly from the datasheet view through your code.
To obtain a value from the query, you could either open the query as a DAO or ADO recordset, e.g.: (using DAO):
Private Sub cmdOrders_Click()
With CurrentDb.OpenRecordset("OrderAllQuery")
If Not .EOF Then
.MoveFirst
Call RunReport("Orders Report", !OrdDate, Me.txtDateFrom, Me.txtDateTo)
End If
.Close
End With
End Sub
Or use a domain aggregate function such as DLookup or DFirst if you are indifferent about which record is returned:
Private Sub cmdOrders_Click()
Dim odate As Date
odate = DFirst("OrdDate", "OrderAllQuery")
If Not IsNull(odate) Then
Call RunReport("Orders Report", odate, Me.txtDateFrom, Me.txtDateTo)
End If
End Sub
Related
The code is supposed to check if a filed "YearBigins" is empty and request an input then checks if the date value in "YearBigins" filed in older than one year and sets the value in the "counter" filed to 0. I have the following codes but does not work:
Private Sub Form_Load()
Me.Caption = Date
YearBegins_AfterUpdate
End Sub
Private Sub YearBegins_AfterUpdate()
Dim rst As Recordset
Do While Not rst.EOF
If IsNull(rst.Fields("YearBegins").Value) Then
YearBegins = InputBox("Please Enter the Beginning of counter Year Date as:
dd/mm/yyyy")
Else: YearBegins = YearBegins.Value
End If
rst.MoveNext
If (DateTime.Now - YearBegins.Value) < 365 Then
counter.Value = 0
End If
Loop
End Sub
You're missing the part where you actually update the recordset.
Private Sub Form_Load()
Me.Caption = Date
YearBegins_AfterUpdate
End Sub
Private Sub YearBegins_AfterUpdate()
Dim rst As Recordset
Do While Not rst.EOF
If IsNull(rst.Fields("YearBegins").Value) Then
YearBegins = InputBox("Please Enter the Beginning of counter Year Date as: dd/mm/yyyy")
rst.Edit '<---
rst("YearBegins") = cdate(YearBegins) '<---
rst.Update '<---
Else
YearBegins = YearBegins.Value
End If
rst.MoveNext
If (DateTime.Now - YearBegins.Value) < 365 Then
counter.Value = 0
End If
Loop
End Sub
With that said there are better ways to do this. You could open another form with only the data you want to update which will allow you to give your users some context. Just having a popup dialog with no data validation doesn't let them even really see what record they're updating. How do they know what value to put in?
It would be better if you could refactor your code in YearBegins_AfterUpdate to a new function and call that from Form_Load instead of calling an event handler like YearBegins_AfterUpdate.
I don't see where you're setting rst. You go from Dim rst As Recordset to using it but given the code you provided rst will always be null.
I have an Access database frontend that houses 16 different forms. All of them have three buttons in common namely Show All, Clear and Refresh, that perform that exact same function using their respective subforms. For instance, for viewing data from a table named tbl_Students the 'On Click' event of these buttons on the Students Form have the following code:
Option Explicit
'Show all records button
Private Sub cmdShowAll_Click()
Dim task As String
task = "SELECT * FROM tbl_Students"
Me.frm_Students_subform.Form.RecordSource = task
Me.frm_Students_subform.Form.Requery
End Sub
'Clear displayed records button
Private Sub cmdClear_Click()
Dim task As String
task = "SELECT * FROM tbl_Students WHERE (StudentID) is null"
Me.frm_Students_subform.Form.RecordSource = task
Me.frm_Students_subform.Form.Requery
End Sub
'Refresh records button
Private Sub cmdRefresh_Click()
Me.frm_Students_subform.Form.Requery
End Sub
Currently, I'm using the exact same code, but with different respective subform names, in all my 16 forms. Is there a better, more efficient way to do it, with code reuse? Thanks.
Consider creating one generalized subroutine in a standard module that all 16 forms call passing needed parameters. Specifically use CurrentProject and Controls to reference objects dynamically by string.
Module save in a named standard module (not behind any form)
Option Explicit
Public Sub ProcessForms(task As String, mainform As String, subform As String)
On Error GoTo ErrHandle
CurrentProject.AllForms(mainform).Controls(subform).Form.RecordSource = task
CurrentProject.AllForms(mainform).Controls(subform).Requery
Exit Sub
ErrHandle:
Msgbox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
Exit Sub
End Sub
Example Form single line calls
Option Explicit
'Show all records button
Private Sub cmdShowAll_Click()
Call ProcessForms("SELECT * FROM tbl_Students", _
"frm_students", "frm_Students_subform")
End Sub
'Clear displayed records button
Private Sub cmdClear_Click()
Call ProcessForms("SELECT * FROM tbl_Students WHERE (StudentID) IS NULL", _
"frm_students", "frm_Students_subform")
End Sub
'Refresh records button
Private Sub cmdRefresh_Click()
' Re-assigns same recordsource in line with others
Call ProcessForms(Me.Controls("frm_Students_subform").Form.RecordSource, _
"frm_students", "frm_Students_subform")
End Sub
Is it possible to have a user choose yes/no and add a parameter in a query based upon that answer?
I have a table that has a 'status' field. One of the statuses can be complete. There is a report that prints out that has this field. Sometimes I want the records that are marked as complete, and sometimes I do not.
Is it possible to prompt the user and ask if they want the completed records, using the criteria/expression builder in a query?
I think the best way to handle this would be to use a yes-no msgbox to learn whether the criteria should be shown, then run the report using the "where" parameter on the DoCmd.OpenReport command.
Dim intAnswer As Integer
Dim intAnswer As Integer
intAnswer = MsgBox("Show the details?", vbYesNo)
If intAnswer = vbYes Then
DoCmd.OpenReport "Form1", acViewPreview, , "[Status] <> ""Completed""", acWindowNormal, "Yadda Yadda"
Else
DoCmd.OpenReport "Form1", acViewPreview, , , acWindowNormal, "Zippity Doohdah"
End If
If you would like to inform the report of what the user selected one method is to pass an OpenArgs string and then have a label on the report that shows that string. (Above I pass the phrase "Yadda Yadda", or "Zippity Dodah")
On the report, add a label (here called Label1) and set its Caption equal to the OpenArgs:
Private Sub Report_Open(Cancel As Integer)
If Not IsNull(Me.OpenArgs) Then
Me.Label1.Caption = Me.OpenArgs
End If
End Sub
I have a subform with a datasheet view. On the parent form I am trying to edit records based on what is selected in the child datasheet. The forms are not linked using master/child fields.
I'm capable of getting the top row that is selected and the number of selected rows using SelTop and SelHeight like below.
Dim rs As New ADODB.Recordset
Set rs = Me.Child_Form.Form.RecordsetClone
If SelHeight > 0 Then
rs.MoveFirst
rs.Move SelectionTop - 1
For i = 1 To SelectionHeight
If Not rs.EOF Then
Debug.Print rs("ID")
rs.MoveNext
End If
Next i
End If
What I cannot do is get, say, the 10 records selected on the subform if I have filtered or sorted the form at all. The Filters and Sorts are at the form level and cannot be applied to the underlying recordset.
I've tried creating a new recordset with a query something like this
sql = "Select * from [" & Me.RecordSource & "] where " & Replace(Me.Filter, """", "'") & " order by " & Me.OrderBy
but there are multiple problems here. 1) ADO does not support the IN clause which the form filter will sometimes generate, and 2) the order order is not always the same and predictable.
How can I get a sorted, filtered recordset and find only those records which a user has selected in a datasheet view?
I am connecting to Sql Server with an ADP file.
I came up with a frustrating solution but it seems to work.
added an unbound (to my recordset) checkbox control to my subform.
named it chkSelect.
made the controlsource =IsChecked(ID)
I have this code running in the subform
Dim selectedRecords As Dictionary
Private Sub chkSelect_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If selectedRecords.Exists(Me("Analytical_ResultID").Value) Then
selectedRecords.Remove Me("Analytical_ResultID").Value
Else
selectedRecords.Add Me("Analytical_ResultID").Value, Me("Analytical_ResultID").Value
End If
chkSelect.Requery
End Sub
Private Function IsChecked(Analysis_ResultID As Long) As Boolean
IsChecked = selectedRecords.Exists(Analysis_ResultID)
End Function
Private Sub Form_Load()
If selectedRecords Is Nothing Then
Set selectedRecords = New Dictionary
End If
End Sub
This works but it's flickery and not ideal. I would much prefer another answer.
Right now, I've got a database that allows a user to create a basic report based on a query from a table using a parameter. Pretty straightforward. What I want to do now is to use VBA to add a record into a separate table every time a report is created. Each report has the information from the query PLUS some new information (concatenated IDs, dates, etc.). The new table ("Summary") would include some of that new information plus a few sources from the original query. It would be sort of a dynamic log of reports created.
Is there any way to use VBA to combine data from the two sources (data displayed on report from original query and native report data) into one record on a table?
Here's the code I've got so far.
Option Compare Database
Public Sub Log_Report()
'System definitions
Dim dbs As DAO.database
Dim rs As DAO.Recordset
Dim rep As [Report_Custom MARS Report]
'Original report sources
Dim Text267 As String
Dim TableName As String
Dim Company_Name As String
Dim ReportID As String
'Summary table destination
Dim ID As Integer
Dim Date_Created As Date
Dim Source As String
Dim Title As String
Dim report_ID As String
Dim Attachment As Attachment
End Sub
I'm probably way off, so if I have to start over, I'm fine with that. I'm no expert in VBA by any means, so it's been a lot of trial and error so far.
I can clarify if needed.
If the record set for your report is a single row, it would be relatively easy to use the on load event to read the fields and assign them to variables. All of the calculations have been done by the time your Report_Load event fires and you could then use them as inputs to a function which writes the values to your summary table.
'Code to placed in a public function
'strVar = text267 'is ReportID = report_ID ?
'Unfortunately I have no experience with attachments, sorry
function writeReportSummary(intID as Integer, dtmDate_Created as Date, strSource as String, strTitle as string, strReportID as string, strVar as string, strTableName as string, strCompanyName as string, attAttachment as attachment) AS boolean
Dim strSQL as string
On error goto Err_Handler
strSQL = "INSERT INTO summary( ID, Date_Created, Source, Title, report_ID, Text267, tableName, Company_Name, ReportID) SELECT """ & intID & """ , """ & dtmDate & """;" 'etc
CurrentDb.execute strSQL, dbFailOnError
Debug.print CurrentDB.recordsAffected & ": Record(s) Inserted at " & now()
writeReportSummary = True
Exit function
Err_Handler:
debug.print err.number
debug.print err.description
writeReportSummary = false
end function
'Code to be placed in Report_load'
Sub Report_Load
if Not(writeReportSummary(intID, dtmDate, etc)) then debug.print "Failed to write report to summary table"
End Sub