I am having an issue with a subform that I am filtering with a Combobox. when I created my example with a blank form the setup works properly, but once I add the data source to the form the subform doesn't work as intendend
if you see the top is how it works properly and the bottom is what happens when I add the source
here is what i did:
Private Sub Combo0_AfterUpdate()
Dim SQL As String
'SQL = "select keywordID, issueID from tblIssueKeyword where keywordID = " & Me.Combo0
SQL = "select * from tblIssueKeyword where keywordID = " & Me.Combo0
Me.tblIssueKeyword_subform.Form.RecordSource = SQL
End Sub
the form doesn't have a recordset
the Combobox is just a just of numbers representing the keyword ID. in my other example I generate the keyword list from a query but found out with this example it also isn't working.
and the only thing that changes is this:
and I need that data source for my main form
update:
I noted that the issue only happens when I put the tickets table. if I just put another table that I got the issue is not there... could it be that relations are wrong?
finally found my answer... seems like a table was created by mistake that had certain relationships with other tables.
when I was cleaning my tables I found this and deleted it, and tried again it worked.
Related
I have been using MS Access to aid in generating pdf reports based on a table. I have created a form that contains a text box for entering a client's name (this value is in the main table) and a button that when clicked runs the code:
Private Sub cmdPrintRecord_Click()
Dim strReportName As String
Dim strCriteria As String
strReportName = "Current SP Report"
strCriteria = "[Owner]='" & Me![Owner] & "'"
DoCmd.OpenReport strReportName, acViewPreview, , strCriteria
End Sub
The idea here is to generate an individual PDF report based on the clients name.
The above procedure has been able to do that successfully however, I have encountered that as I run it, the data in my table is affected, specifically the client name field.
For example: I'll run a report for client "Anthony" and it shows 10 products which is correct, but then if I go back and run that same report again it will show 11 products. It is as if the procedure here is altering the data table.
How can I troubleshoot this issue and or are there any alternatives recommended?
Thanks.
Attached is the MS link where I obtained the source code:
https://support.microsoft.com/en-us/kb/209560
If the Control Source of a form control (textbox, combo box) is linked to a table then it will modify that table. In your case, you want to receive user input based on selections from a table and not to modify the table itself. You want to use the "Row Source" property to limit the selection to table items and clear the Control Source. This pulls potential options from the table without changing existing table entries.
Like this:
Notice that the source of options for the combobox is a query that defines what items should appear in the dropdown but no Control Source is specified.
I can find plenty of examples of how to return specific records in a subform through altering the underlying source query in code and re-querying, but I'm struggling to use the same principle to alter the fields that are returned.
I have the following situation:
Combobox to select 1 of 5 fields. Subform is supposed to show the selected field plus a couple of static fields, lets call them fields 6 and 7
So in the case the user selects field 1 from the dropdown, subform should show fields 1, 6 and 7. In the case they pick field 4, subform should show fields 4, 6 and 7 etc.
This is what (amongst other things) I've tried:
Set the subform up through the wizard with a query (select field1, field6, field7) as source, amend said query after combobox selection is made:
Set qd = CurrentDb.QueryDefs("myqueryname")
qd.SQL = "Select " & mycomboboxselection & ",field6,field7 from mytablename"
Form_mymainformname.mysubformname.Requery
The query itself updates fine if I run that standalone after the change, but the subform within the main form doesn't change and when I click on the subform itself from the navigation window it seems to be stuck looking for field 1 as it asks me to input a parameter value
Can anyone help with how to achieve this please?
Set the RecordSource of the subform to the SQL:
Dim SQL As String
SQL = "Select " & mycomboboxselection & ",field6,field7 from mytablename"
Me!YourSubformControl.Form.RecordSource = SQL
It will force a requery of the subform.
Ok I found a solution after a few more hours searching and trial and error.
There are two seperate problems here. Firstly creating the subform uses the newly created form as the source object rather than directly using the query, and it seems that no matter how you try to manipulate the record source of said form, it doesn't like changing the fields it was built with.
So, create the subform, change the source object from the form to your query (and delete the now pointless newly created form), then you can use the code I started with:
Set qd = CurrentDb.QueryDefs("myqueryname")
qd.SQL = "Select " & mycomboboxselection & ",field6,field7 from mytablename"
Which works! sort of....
You have to close and reopen the form every time to see the actual updates though, which obviously isn't what we're going for
The other line does nothing:
Form_mymainformname.mysubformname.Requery
It works fine for a change of records, but apparently not for a change of fields. I suspect this is a bit of a ms quirk
The below, however, works, even though I feel like it should do exactly the same as the code line above:
Form_MyForm.MySubForm.SourceObject = Form_MyForm.MySubForm.SourceObject
I have a rather simple looking problem but it turned out to be more complicated than I thought.
I have a field (column) in my subForm which is a ComboBox.
I have a field (column) in another subForm by which I would like to filter this comboBox.
Basically, the comboBox before filtering has some 600 records, too many to scroll by casual user. I created a simple subForm whose field is linked to a mainForm and this works perfectly (ie. the selected record-field-ID is displayed on mainForm).
Now what I want is that this comboBox is filtered by this record (ie. only showing relevant fields). The problem is that if I simply Requery it with this given filter, the other fields show up blank.
I want this filter to apply only to NEW RECORDS comboBox, not the whole datasheet view.
What I did is:
Private Sub Sekacie_Operacie_GotFocus()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
Me.Sekacie_Operacie.RowSource = Replace(SQL, ";", "") & " WHERE Sekacie_Operacie.Operacia_ID = " & Me.Parent.Form!txtOP_ID
Me.Sekacie_Operacie.Requery
'works kinda as intended
End Sub
Private Sub Form_AfterInsert()
Me.Sekacie_Operacie.RowSource = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
Me.Refresh
End Sub
And when I select the record in my filter subForm:
Private Sub Form_Current()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
With Me.Parent.Form.subSekacie_Operacie_Modelu
.Form!Sekacie_Operacie.RowSource = SQL
.Form.Refresh
End With
End Sub
However, this workaround still shows "blank" records sometimes (I have to refresh the form by clicking different record) and I find it strange I had to go all the way to do this. Is there no simpler way of accomplishing this?
A couple of immediate things:
No need to refresh the whole sub form, just refresh the control.
Private Sub Form_AfterInsert()
' Me.Refresh ' replace this line with the following line
Me.Sekacie_Operacie.Refresh ' or is it Requery I can't remember
End Sub
The following code can be improved
Private Sub Form_Current()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
With Me.Parent.Form.subSekacie_Operacie_Modelu
.Form!Sekacie_Operacie.RowSource = SQL
.Form.Refresh
End With
End Sub
' by using code like this
Private Sub Form_Current()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
me.Sekacie_Operacie.RowSource = SQL
' I think the above line will cause the combo to refresh
' anyway (in some version of accees it might not,
' but, if needed add the following line
' me.Sekacie_Operacie.refresh
End Sub
The following line has the potential to produce and error
(perhaps when the main form is a new record)
WHERE Sekacie_Operacie.Operacia_ID = " & Me.Parent.Form!txtOP_ID
replace it with
WHERE Sekacie_Operacie.Operacia_ID = " & nz(Me.Parent.Form!txtOP_ID,0)
Note that adding such code will stop the subform from working independently of the main form and will require it to have a parent form.
You could get around this by using:
if not me.parent is nothing then
WHERE Sekacie_Operacie.Operacia_ID = " & nz(Me.Parent.Form!txtOP_ID,0)
end if
About your approach.
I find it a bit weird what you are doing. Consider this:
Say the query qrySekacie_Operacie returns 100 rows when run without any WHERE clause. When you are inserting a record into the subform you want to limit the combo by adding a WHERE clause that uses a value in the parent formMe.Parent.Form!txtOP_ID) , this might limit the number of rows displayed to 10.
It is worth noting that if any of the other rows in the subform contain value other than one of these 10 the combo will display a blank value. I think this is what you are experiencing.
My first question was why not use the on current event of the parent form to change the subform combo box SQL. It appears this is not what you need.
It appears that other values can exist in the dataset of the subform and that you only want certain value to be enterable in this subform but you want the subform to display any values that have been entered.
So that gets interesting. Here's what I would do:
Create a hidden combo control (with no control source) that is only visible when a new record is being entered. When this new combo is shown the other one is hidden.
Set up this new combo with the required SQL
use a before insert event to copy the value form the new combo to he old one.
Easy peezy?
Let me know ho you get on.
One other thing
I like to Ensure a subform encapsultes code that operates on it "private" controls.
As I general rule of thumb, where possible (which is 99% of the time), I like to try and keep subforms so that they will work as forms in their own right. They can be though of as an object, so if they work independently, it is an indication that their code has been encapsulated within their own code module.
So if the form has me.form.parent = nothing then the code behaves differently as it is a independent form.
So rather than the parent form code module having code that sets the SQL of the subforms combo, I would write a public sub in the subforms module (called SetComboSQL) that can be called (with the appropriate parameters. ie OPid ) to set the combo SQL.
To call the procedure in the parent form I would add
Private Sub Form_Current()
Me.MySubformControlName.Form.SetComboSQL(OPid:=Me.txtOP_ID)
End Sub
' note that intellisense won't pick up this proeprty BUT it will work. Use debugger to check it out.
I hope you find this tip useful (as it can be a massive headache saver. THE MOST BASIC OO PRINCIPAL is encapsulation. An object should own all the code that effects it's properties (and controls).
I have a report (ReportX) that I wish to open from two different forms (FormA and FormB) in my database. I wish to do this because FormA and FormB address different aspects of my data, even if they ultimately get to the same output. ReportX is based on data from QueryX.
The problem I have is that QueryX would ideally filter the data based on the current RecordID in the current form. But I don't know how to accomplish this. I'd like to design QueryX so that the criteria for RecordID is essentially CurrentForm!RecordID, but research suggests that I cannot do this. Must I make separate but otherwise identical queries and reports for each form? Or is there a way to use VBA to define the query criteria when I click on the OpenReportX command button?
I already tried using the WHERE condition in the OpenReport command:
DoCmd.OpenReport "ReportX", acViewPreview, ,"RecordID = " & RecordID
but that did not display the results I wished. I need the report header to display/print for each RecordID and the page count in the page footer to reflect only the current/total pages of the RecordID in question. (In other words, if record 1 is one page, record 2 is two pages and record 3 is three pages, then ReportX, when displaying the first page of record 2, should say "Page 1 of 2" and not "Page 2 of 6.") So being able to display and print a single record properly using record filters would also solve my problem.
Which is the least cumbersome/most possible solution?
You should be able to accomplish this using the WHERE condition argument when you open a report:
DoCmd.OpenReport "rptName", acViewPreview, ,"RecordID = " & Me!RecordID
In the case where a I need more control over a Report's recordsource than what the Where condition argument can do for me, I will set the Reports RecordSource to be blank (after designing the report). Next I write code create the correct SQL statement in the Open Report button's Click event, followed by code to open the report and pass in the SQL as an opening argument for the report.
Private Sub cmdOpenReport_Click()
Dim sSQL as string
sSQL = "SELECT * FROM tblWhatever WHERE RecordID = " & Me!RecordID
DoCmd.OpenReport "rptReportName", acViewPreview, , , ,sSQL
End Sub
Then in the report's Open event I write code to set the recordsource:
Private Sub Report_Open(Cancel As Integer)
If IsNull(Me.OpenArgs) = False Then
Me.RecordSource = Me.OpenArgs
End If
End Sub
If neither of those accomplish what you want then you have an issue of a different sort. It's a little difficult for me to understand why you need All Records to show up in the header but only one record in the detail area. And how you expect to accomplish this. You might be best off trying to write a query first that gives you the exact results that your looking for so you know that it can be done.
As a side note, I actually use very few saved queries in my designs. It's not that there's anything wrong with using them, as the option is there for your convenience. I frequently use raw SQL on both forms and reports and set the RecordSource to the SQL on the Form or Reports Open or Load events.
Yes you can point to form data items in a query, and subsequently use that query in a report. The forms need to be open before the report runs. As far as having a header for each record, that is controlled in the settings of the report and how it displays the data.
In the Field, or Critera you can use the format:
[Forms]![frm_Process_Candidates]![QuestionTemplate]
Where frm_Process_Candidates would be the name assigned to your form, and QuestionTemplate is either the name of a control on your form, or a field from the data source of your form.
If you have a sub-form, there will be another [Form] call in the middle there.
[Forms]![frm_Dropdown_Admin]![frm_Dropdown_Admin_Detail].[Form]![text22]
Access should figure it out from there.
Okay, friends, I'm leaving my job in a week and a half, and I'm trying to make what I've done easier for my boss to do. He has no access knowledge, so I'm trying to create a form that will automate the reports I've been generating. Rather than create a different form for all the different reports, I'm trying to automate it from a table of parameters. Here's what I'm going for:
I have a table, which I have created, which is comprised of 5 fields. I'd like to use these fields to fill parameter fields in a standard form template. The five fields in my table are as follows:
The type of query being run (the result spit out)
The queries that generate this report, separated by a comma and no space. "QRYNAMEA,QRYNAMEB"
The Table which these queries generate, which will be used by transferspreadsheet
The destination excel file, which already has a pivot table set up to feed of the data.
The input sheet of this excel file. Currently, all of these sheets are called "Input". (that isn't important)
My issue comes with having no idea where to go after I've made my combo box. I know enough visual basic to automate my queries, but not enough to populate the form with the information in 3,4 and 5 (so far, I've been manually changing these for different queries). I have no idea how to look up the record in the table from the choice in the 'choosebox', and then select individual fields from that in my automation.
I'm pretty confident in my ability to parse #2 and automate the queries, and to put the values into the fields I'm looking at, but I don't know how to actually pull those values from the table, before I can do these things. I also can't seem to describe this well enough for google to help me.
Has anyone done something like this before? I'm assuming I just lack knowledge of one of the VBA libraries, but I've not had any luck finding out which.
edit:
my inclination at this point is to create a query for this table, which will return a single field depending on the input I give. I can imagine doing this in SQL, but I still don't know how to populate the forms, nor extract the field object from the table once I get it.
I have to head out for the day, but I'll be back on Friday to keep working on this, and I'll post my solution, once I find it. This seems like a unique conundrum, and it would be nice to give an answer to it.
Final edit: code is polished (does not have much in the way of error handling):
The first method, which pulls the fields from the table and populates the form, is activated by choosing a new entry in the combo box and looks like this:
Private Sub QuerySelect_Change()
Dim db As Database
Dim rec As Recordset
Set db = CurrentDb
Set rec = db.OpenRecordset("SELECT [Queries to Run], [Source Table], [Destination Spreadsheet], [Destination Sheet Name] FROM TBL_QRY_SETTINGS WHERE TBL_QRY_SETTINGS.[Query Type] Like '" & [Forms]![QuerySelector]![QuerySelect] & "';")
[Forms]![QuerySelector]![QueriesToRun].Value = rec("Queries to Run")
[Forms]![QuerySelector]![SourceTable].Value = rec("Source Table")
[Forms]![QuerySelector]![FileDest].Value = rec("Destination Spreadsheet")
[Forms]![QuerySelector]![SheetName].Value = rec("Destination Sheet Name")
Set rec = Nothing
Set db = Nothing
End Sub
The second code pulls that data to run the query. I like how this turned out. It runs when a button near the combobox is clicked.
Private Sub DynamicQuery_Click()
Dim qryArray As Variant
Dim i As Integer
qryArray = Split([Forms]![QuerySelector]![QueriesToRun], ",")
DoCmd.SetWarnings False
For i = LBound(qryArray) To UBound(qryArray)
Debug.Print qryArray(i)
DoCmd.OpenQuery (qryArray(i))
Next
DoCmd.SetWarnings True
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, [Forms]![QuerySelector]![SourceTable], _
[Forms]![QuerySelector]![FileDest], _
True, [Forms]![QuerySelector]![SheetName]
End Sub
Note that the final code for part (1) is almost the same as the selected answer, except that I am grabbing more than one field. This works because I know that I have unique "Query Types", and my recordset will only contain one record.
Anyway, I hope some people stumble upon this and find it useful. Send me a message if you do. As far as I can tell from brief googling, this sort of automation work has not been done in access. It should make it easier for access-illiterate to run their own queries, and be simple for designers to add to, if they want all their queries available after a few clicks.
Someone could conceivably use this to automate a variety of reports in sequence, by iterating through a table like the one I reference.
I may be massively misunderstanding what you're doing, but I think it's as easy as creating a new form using the form wizard. It will let you choose the table that contains the data, and it will let you choose which fields you want to add.
You can later change any of the textboxes to combo boxes which will allow you to limit the choices available to fill in.
Am I understanding that correctly?
EDIT: This will fill a variable (MyRandomField) with the contents of a field in a table
Dim db as Database
Dim rec as Recordset
set db = CurrentDB
set rec = db.OpenRecordSet("Select SomeField from SomeTable Where Something = 'SomethingElse'")
MyRandomField = rec("SomeFieldName")
set rec = Nothing
set db = Nothing