I am trying to preview a report of the current tracking number which is on the main form(main form name is:frmReviewReleaseLogWrapper) by using a command button.
Each tracking number has different part numbers, so each tracking number has many records in the DB table (Depending upon the number of partnumbers, that is each partnumber has a record)
I wrote the following code and it is not working, It is just displaying report name and column names and not the records.
Code is as follows:
Private Sub Command225_Click()
On Error GoTo Err_Command225_Click
Dim stDocName As String
DoCmd.OpenReport "rptEventLog", acPreview, , "[TrackingNumber] = Forms!frmReviewReleaseLogWrapper"
Exit_Command225_Click:
Exit Sub
Err_Command225_Click:
MsgBox Err.Description
Resume Exit_Command225_Click
End Sub
What's the name of the control on the frmReviewReleaseLogWrapper form that contains the tracking number? You need to reference it in your OpenReport statement, like so:
DoCmd.OpenReport "rptEventLog", acPreview, , _
"[TrackingNumber] = Forms!frmReviewReleaseLogWrapper!txtField"
Incidentally, you might do better to give your command button a name that reflects its actual function, so it'll be easier to find later.
Related
Completely new to MS Access - I'm trying to do a simple modification to the MS Access Lending Library template using VBA.
Going into the Asset List form and clicking New Asset pops up the Asset Details form, where I can click the Save and New button. This calls the VBA code cmdSaveandNew_Click().
My question is, within this VBA method, how do I reference the values of the fields in the Asset Details form - For example getting the value that the user entered in the Category field and storing it in a variable.
I've tried several strings of code to try to get the value back, but I keep getting various errors, saying it can't find the referenced form, or Object Required, or this method is supported. I think it's likely just that I don't fully understand the structure of what I'm trying to reference or the syntax for specifying how to reference it.
Right now (after I've been trying many different combinations of things, I have:
text = Forms![Asset List].[Asset Details].Form.Category
which is giving me the "can't find the field '|1' referred to in your expression" error.
Edit - code currently looks like this:
Private Sub cmdSaveandNew_Click()
'On Error GoTo cmdSaveandNew_Click_Err
Dim someVar As String
Dim num As Integer
Dim objtf
'objtf = Forms![Asset List].[Asset Details].Form.Category
objtf = Me.Category
'num = Form.Controls.Count
Msg.Box (TypeName(objtf))
someVar = InputBox("How many?")
On Error Resume Next
If (Form.Dirty) Then
DoCmd.RunCommand acCmdSaveRecord
End If
If (MacroError.Number <> 0) Then
Beep
MsgBox MacroError.Description, vbOKOnly, ""
Exit Sub
End If
On Error GoTo 0
DoCmd.GoToRecord , "", acNewRec
DoCmd.GoToControl "Item"
MsgBox someVar
cmdSaveandNew_Click_Exit:
Exit Sub
cmdSaveandNew_Click_Err:
MsgBox Error$
Resume cmdSaveandNew_Click_Exit
End Sub
The variable must be declared global in a general module if you want to reference from various modules. Then setting it by code behind the Asset Details form would be simply: SomeVariableName = Me.Category.
Don't use reserved words as names - text is a reserved word.
I have a very complex process that involves downloading a number of files from different shares, concatenating those files into working tables, manipulating and calculating related information, and then exporting specific fields (and calculations) as reports into a number of Excel workbooks.
I have this process coded so that I can click one button and the entire process will execute end to end. I have a series of text boxes that function as 'indicators' (red - this part failed, green - this part succeeded). As you can imagine, the code for the entire process is HUGE (32 pages when copied into MSWord) and difficult to weed through when I have a problem.
I got it into my mind that I wanted to put the code into a table so that it was much more modular and easier to deal with. I have setup a combo box with the action that I want to take and a second combo box with the report/file/object that I want to work with (ie Delete - Table 2, Acquire - File 1, Export - Report 4). I have been successful at creating the SQL statement to do simple things like del * from tbl_test and execute that from the combo boxes without any issue.
What I need to know is if there is a way to put what is essentially a code snippet into the table (memo field) and then have that vba code execute when I select the matching combos.
IE the code for 'Acquire - File1' is completely VBA code; it maps a network drive, locates the file, downloads the file, and moves it to a directory.
IE the code for 'Scrub - tblMain_Part1' is a combination of vba and sql code; it checks for the existence of a file (vba), if it finds it, it deletes a portion of the main table (sql) and appends the contents of the file it finds (sql), then it updates the monitor to indicate that it is completed (vba). If the file is not found, it changes the monitor box to red and updates a command button caption (vba)
I am NOT a genius with vba, but I hold my own. The thought process I had was that if I can essentially get the code broken into managable chunks in the table, I could call the code smippets in order if I want to run the entire process, or I could just re-execute portions of the code as needed by selecting the action and report/file/object combination.
Any thoughts/ideas are appreciated.
I think it would be best to split the code into Subs. The table you loop through would have a Sub-Name field and a blnSuccess field. Your code would loop though the table running each sub and then updating blnSuccess based on any errors you receive. This would give you queryable result set when you try to see what happened.
Consider using macros. You shouldn't need a table. Also, consider moving your hard-coded SQL to queries.
I think that you shouldn't use a table, just create a module with different subs for each operation. On your button event, after the combo selections, I would do a case statement.
dim strOperation as string
strOperation = me!selectionOne
Select Case strOperation
Case "delete": deleteTable(me!selectionTwo)
Case "export": export(me!selectionTwo)
case "acquire": acquire(me!selectionTwo)
End Select
Of course, you'd have your acquire, delete, and export methods written in a module and have whatever parameters you need for each operation there.
This is just one idea of many that you could use to approach this.
I was going to edit the original answer but this seems to be off on a different tack....
I think it would be best to split the code into functions that return a string if there is an error. The table you loop through would have a strFunction,strError and strObject fields. Your code would loop though the table running each function based on the case statement while passing the strObject as a string and then updating strError based on any errors you receive. You could query the table after this process to see which records have errors in them.
If the button is called cmdRunAll here is the code for it.
Private Sub cmdRunAll_Click()
On Error GoTo ErrHandler
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("tblCode", dbOpenDynaset, dbSeeChanges)
If Not rst.EOF Then
With rst
.MoveFirst
Do While Not .EOF
.Edit
Select Case !strFunction
Case "fExport"
!strError = fExport(!strObject)
End Select
.Update
.MoveNext
Loop
End With
End If
rst.Close
Set rst = Nothing
MsgBox "Processes complete"
Exit Sub
ErrHandler:
Debug.Print Err.Description & " cmdRunAll_Click " & Me.Name
Resume Next
End Sub
Here is a simple sample function
Public Function fExport(strTable As String) As String
On Error GoTo ErrHandler
Dim strError As String
strError = ""
DoCmd.TransferText acExportDelim, , strTable, "C:\users\IusedMyUserNameHere\" & strTable & ".txt"
fExport = strError
Exit Function
ErrHandler:
strError = Err.Description
Resume Next
End Function
I have a form which allows the user to edit the properties of a filter via some combo boxes, then open a report. The report is opened with
DoCmd.OpenReport rptName, acViewReport, , whereClause, acWindowNormal
'whereClause = "Building = '005'" for instance
Some reports open fine, by which I mean they populate with the filtered info. Others, however, even though they are based off the same in-house template, IGNORE the filter all together and display a report based on ALL data (not the filtered data).
Why would a report ignore the filter? When I edit the reports in design mode after opening them with the form:
Working Report | Non Working Report
Filter: Building = '005' | Filter:
Filter On Load: No | Filter On Load: No
What could be causing the non-working report to not register the filter argument? There's no On Load VBA, nor any VBA, in these reports (except for an Export to PDF and a close button which is copy-paste for each report).
EDIT
Should have checked before, this happens regardless of whether or not the query driving the report is empty (ie the filter is never applied to some reports, regardless of blankness)
Not sure if the code will help, but:
Private Sub btnOpenSummary_Click()
If IsNull(Me.cboSummary) Then
MsgBox "Please select a building for the SUMMARY report."
Exit Sub
End If
strCrit = "Building = '" & Me.cboSummary & "'"
MsgBox strCrit
survArray = getSurveyArray()
For Each Survey In survArray
DoCmd.OpenReport Survey, acViewReport, , strCrit, acWindowNormal
Next Survey
DoCmd.OpenReport "Total Summary", acViewReport, , , , Me.cboSummary
End Sub
My fault.. there was code which had for some reason been linefed all the way down the code page and out of view. There was an On Open which played with the Control Source. It ended up being useless (as the control source only needed to be set once, not every time) but it was disabling the filter for some reason. Anybody else who may have this problem:
Make sure the control source is not being altered in your VBA for the report.
Thanks to those that helped, sorry my information was wrong.
My OnOpen code:
Private Sub Form_Open(Cancel as Integer)
Me.RecordSource = Me.Name
End Sub
It takes the name of the report, which corresponds to a name of a query, and puts it as the recordsource. (I have about 40 reports done this way, so it's dependent on names to make it fast to duplicate for different items).
Removing this made it work perfectly using Access 2010. Not sure if this was a problem specific to my setup or what, but, this change directly fixed it.
This is not a direct solution, but rather a workaround which should almost certainly work. Instead of applying filtering to the report, dynamically change the report data source by passing the where clause as a parameter.
To open the report use:
DoCmd.OpenReport rptName, acViewReport, , , acWindowNormal, whereClause
Note that the whereClause string is being passed as the OpenArgs parameter.
Then in the report VB:
Private Sub Report_Open(Cancel As Integer)
On Error GoTo ReportOpenError
If Not(IsNull(Me.OpenArgs)) Then
Me.RecordSource = Replace(Me.RecordSource,";"," WHERE " & Me.OpenArgs & ";")
End If
Exit Sub
ReportOpenError:
MsgBox "Unable to open the specified report"
Cancel = 1
End Sub
This solution assumes the report RecordSource is defined as a semicolon terminated SQL query (not a query name) and the record source does not already contain any WHERE, GROUP BY, etc., clauses. In those cases, it may be easier to redefine the query from scratch.
This problem may also occur when a report is copied and re-purposed. I had a report that was working fine then made a copy of it and was no longer able to filter it.
Perhaps there is a glitch in Access that causes it to ignore the filter when the report is copied under certain circumstances.
Solution: Instead of copying and re-naming the report, try creating a new report, linking the data source, and copying the fields back into place. If you are dealing with a new report, try re-creating it.
I have a report with details of jobs/tasks, and also a form which contributes the majority of the data towards that report. Given that a report is a nice way of looking at the larger picture of the data, and a form is the best way of editing data, I would like to be able to click on a row, and have it open up the relevant record in the form view.
Does anyone know how to do this through VBA? In my mind it should be possible, though my knowledge of objects in Access is limited.
Update
I've implemented the following code for my report:
Private Sub Edit_Click()
Dim EntityName As String
Dim DocName As String
DocName = "Entity: Overview"
strWhere = "[Entity Name]='" & Entity & "'"
DoCmd.OpenForm DocName, acNormal, , EntityName
End Sub
It successfully opens the correct form, and it also grabs the correct entity name, however it isn't filtering properly. I can't see what the issue is with the code.
In your Edit_Click() procedure, you have EntityName as the WhereCondition parameter to OpenForm.
DoCmd.OpenForm DocName, acNormal, , EntityName
However, you haven't assigned anything to EntityName, so it's an empty string. I think you should use strWhere as the WhereCondition.
Private Sub Edit_Click()
Dim strWhere As String
Dim DocName As String
DocName = "Entity: Overview"
strWhere = "[Entity Name]='" & Me.Entity & "'"
DoCmd.OpenForm DocName, acNormal, , strWhere
End Sub
I assumed Entity is the name of a control, and that's where you get a value to build strWhere. If there is no control in the report by the name of Entity, then the code won't work even if there is an Entity in the original query.
You should be able to add an On Click event in the Detail section of the report, then add something like this in the VBA handler:
DoCmd.OpenForm "MyForm", acNormal, "", "ID=" & ID.Text
(where MyForm is the target form, and ID is a hidden or visible control in your report that identifies the current record).
You say report, but you should not be using a report but a continuous form or datasheet. You can then add events to any of the controls on any line, and add a double-click event, if you do not want to drive your users insane. You could also add a command button if that would be clearer to your users, or format the "link" textbox to underline. The record opened by the action shown by #dbaseman will open which even record has the focus (current record). And that will lead you to discover what you can and can't do with a continuous form :D
I have a custom build print dialog that is used for many reports. Its arguments are the report name, filter string, open args for the report etc. What I would like to do is to display the caption of the report specified for printing on the form. For performance reasons, I would rather not open the report, get the caption and close it again. I would rather get it from the database somehow without actually opening the report itself.
One thing that DOES work is to call the report using it's class name report_some_report.caption but there is no way to do this without with a report name stored in a variable. I would have expected Reports("some_report").caption to work also but it only works for open reports.
Is there a better way to do this or am I going to have to do something like the following? (Which works)
docmd.OpenReport "schedule_simple",acViewDesign,,,acHidden
strCaption = Reports("schedule_simple").Caption
docmd.Close acReport,"schedule_simple"
There's no way to get a report caption from a report without first opening the report or using the report class object (as you know). It's also worth noting that "lightweight" reports (ie, ones whose HasModule property = False) do not have class objects.
You have a couple of options.
You could create a local table with a RptName and RptCaption field and query that. Of course, then you need to keep it updated somehow.
You could write a function that "memoizes" the results, so that you only have to open a given report once each time the program runs. For example:
.
Function GetReportCaption(RptName As String) As String
Static RptCaptions As Collection
If RptCaptions Is Nothing Then Set RptCaptions = New Collection
On Error Resume Next
GetReportCaption = RptCaptions(RptName)
If Err.Number = 0 Then Exit Function
On Error GoTo 0
DoCmd.OpenReport RptName, acViewDesign, , , acHidden
RptCaptions.Add Reports(RptName).Caption, RptName
DoCmd.Close acReport, RptName
GetReportCaption = RptCaptions(RptName)
End Function