This is my table
Software
-----------------
ID(Auto-Number)
ProductName(Text)
Total License(Number)
I'm using microsoft office access 2007 and I'm creating a form to display the above fields.
I want to display the data in total license field according to changes in combobox which select the different data in the ProductName field.
Textbox ID = TbTotalLicense
ComboBox ID = CbProductName
My combobox is running on a query
SELECT Employee.EmpName, Employee.EmpCode, Employee.CompanyID, Employee.DeptID,
Employee.ComputerID, Software.ProductName
FROM
Software
INNER JOIN ((Computer
INNER JOIN Employee ON Computer.CompID=Employee.ComputerID)
INNER JOIN Application ON Computer.ComputerName=Application.[A-ComputerID])
ON Software.ID=Application.SoftwareID
WHERE (((Application.SoftwareID) = [Forms]![Form2]![CbProductName]));
Private Sub CbProductName_AfterUpdate()
Me!Softwareuserlist.Form.Requery
Me!TbNoOfLicense.Requery
Me!TbRemainingNoOfLicense.Requery
Me!TbTotalLicense.Requery
End Sub
Private Sub CbProductName_Change()
Me!TbTotalLicense = Me!CbProductName.Column(3)
End Sub
This is what I have code out but I keep getting error, it keep telling me to debug, it doesn't even display the data on the textbox whenever I run. My other textbox works fine.
Well, if it is telling you to debug, then debug!
See on which code line the problem occurs. Open the locals window (menu View > Locals Window) and inspect the values of the involved variables, controls etc.
You can also open the immediate window with Ctrl-G and type an expression to be printed with
?Me!CbProductName.Column(3)
The "?" is a shortcut for Debug.Print
You can also set breakpoints. Klick on the gray bar on the left of a code line in order to set a breakpoint. Run the code. It will stop on that line, giving you the possibility to inspect the variables as explained above.
See:
- ACC: Tips for Debugging Access Basic Code
- Error Handling and Debugging Tips and Techniques for Microsoft Access, VBA, and Visual Basic 6 (VB6)
Related
Instead of using DoCmd.OpenQuery "qrySearch", , acReadOnly to view the results of a query I'm looking at using a form instead to help with presentation, including a couple of command buttons for things like export to Excel etc.
Note that the query can display a variable number of fields depending on the user's chosen criteria.
To do this I created 2 forms: frmResults and frmSub
frmSub was placed within frmResults by dragging frmSub from the Forms tab into frmResults (opened in Design view).
Under Properties of the frmSub:-
Source Object was changed from frmSub to Query.qrySearch.
The Name set at frmResultsSub
Since the original frmSub is now no longer used, I've deleted it (at least, with my limited Access experience I'm assuming it's safe to do so since there appears no effect on the query getting displayed in frmResults - the form displays nicely and the fields and field numbers vary according to the search criteria.
Question:
If the user performs another search, and frmResults is currently open, in order to update the results I have to close frmResults and Open it again. This does work but I'm thinking it's not the recommended way - is there any way to refresh frmResults while it's still open? I've tried various permutations of
Forms!frmResults!frmResultsSub.Requery / .Refresh
from behind the Search form itself but nothing works.
[ms Access 2003 compliance still required]
EDIT: based on HansUp and Alexander's 1st replies...
Alexander: the .Requery (/frmResults display) takes place close to the end of the VBA behind the Search button on form used to take in the user search criteria (frmSearch, a separate form not detailed above)...
If CurrentProject.AllForms("frmResults").IsLoaded Then
Forms!frmResults!frmResultsSub.Requery
Else: DoCmd.OpenForm "frmResults"
End If
--> it's the Forms!frmResults!frmResultsSub.Requery that is not updating for a new user search on the currently opened frmResults form.
HansUp: replacing the above line
Forms!frmResults!frmResultsSub.Requery
to
Forms!frmResults!frmResultsSub.SourceObject = "Query.qrySearch"
...did the trick, and works well - all new searches on an already open frmResults are updated without having to re-open the form. But I'm confused!...I though I already set SourceObject of the subform to the same value as detailed above (under the subform's properties in design view) - why does Access not honour this setting?
In your example code ...
Forms!frmResults!frmResultsSub.Requery
... frmResultsSub is a subform control which contains a query instead of a form. In other words, its SourceObject property is set to "Query.qrySearch".
In that situation, Requery of the subform control does not recognize changes to the query design.
Setting the subform's SourceObject property to its original value is enough to make Access recognize the query design change ...
Forms!frmResults!frmResultsSub.SourceObject = "Query.qrySearch"
MS Access 2007, Win 7 32-bits
Is there a way where I can access an open query in datasheet view in access to get the current field value and current field name?
I won't put it into a form since it is a crosstab query and i'd have to generate and get rid of controls dynamically but i'm not fond of messing with forms controls that way with VBA. I know i can put a dynamic column report and bind an event on the controls but I'm asking if there are events or objects that can let me access directly the query.
Perhaps a recordset clone? But I haven't find anything on google.
Of course this is in VBA
Best regards,
It may be possible to work around your requirements. The crosstab is contained by a subform:
Source Object : Query.xtab
The Control Source for the two textboxes is:
Ctrl : =[screen].[activecontrol].[name]
Content: =[screen].[activecontrol]
Which means they show which ever column ans column contents the user selects in the crosstab subform. However, they will also show any other selected control on the form. ClickMe does not change the selected control, so the selected items remain the same in the textboxes.
You can also enter MacDermott's code for getting the current control's index, so the current control selected on the xtab query subform is displayed dynamically
Public Function ControlIndex(ctl as Control) as long
Dim i as Integer
For i=0 to Me.Controls.Count-1
if me.Controls(i) is ctl then
ControlIndex=i
exit for
end if
next
End Function
And finally this can help when changing from one control to another in the same record to keep the textboxes current.
So in MS Access 2010 I have a main form for viewing client details, and tabbed subform navigation with subforms showing information in different tables for said client. On one page, i have a combobox to select a date for viewing a testing session related to the client. I am trying to get the first combobox value to be selected automatically when the user goes to this tab and/or cycles through other users while viewing this tab. My simple VB code is below:
Private Sub Form_Current()
Me.DateOfScreening.Requery
Me.DateOfScreening.Selected(2) = True
End Sub
The requery command is executing (paging through different clients will update the combobox values, and commenting that line out stops that behavior, so I know this code block is getting executed), but the Selected command appears to not select anything.
I hope I am just missing something obvious
For some reason, setting the selected row index for a combo box has not behaved well for me.
Could you just set the combobox value directly, as in
Me.DateOfScreening = "yourValue"
Also, when referencing the control, you can use either
me.dateofScreening.column(0) 'if 0 is your bound col index
or maybe
me.dateofScreening.itemdata(0)
Also, could you do a debug.print(me.dateofScreening.column(0)) or msgbox (me.dateofScreening.column(0)) and let me know if it says anything.
When a custom UI XML file is used to add several custom ribbon tabs in Access, the selected ribbon tab changes back to the first custom tab whenever a form is closed.
We load a custom ribbon programatically from VBA. I've create an accdb that reproduces the problem. The folder also includes an XML file that contains the ribbon definition. It must be in the same directory as the .accdb file.
The problem can easily be demonstrated:
open the database RibbonTest.accdb,
switch to Tab2 and open Form2 using the button on the ribbon and
close Form2.
Notice that Tab1 is now active.
Of course, in this small example db this problem seems very minor. However, we have a very large project with many custom tabs, each containing numerous groups and buttons. Our users are finding it very frustrating indeed that they keep losing their place on the ribbon every time they close a form.
We have investigated a workaround where we programatically store the selected tab and restore it when we think we need to. However, it is proving difficult to do this reliably. (There isn't an Office API for automating the ribbon like this, but this article helped.)
Has anyone else encountered this problem? Have you found a way to prevent the tab from changing automatically?
Edit: It seems that this problem was introduced with a fix implemented in Office 2010 SP1 . (Sorry, no link: don't think I can have more than two.) The problem is not present in the RTM version. The fix list for SP1 includes this: "Access does not activate or return the user to the correct Ribbon tab for a previously opened database object when the user returns to that object." It seems that they've tried to fix use of the Form.RibbonName property (which supports contextual ribbons), but have broken the default ribbon in the process.
This one line fixes the issue:
<tab id="tabBogus" label="Bogus" visible="false"></tab>
Just make it your first tab in <tabs>. Big thanks to Scott's Potential Workaround answer!! (Tried to Vote it up and/or comment, but just signed up so not enough reputation.) This saved hours (or days) of work versus the other complicated workaround! Thanks!
Potential Workaround
Something I stumbled across that's been working for me is to hide the first tab in the XML using the visible tag. I haven't tested it much, but I have a copy of the standard Home tab that is hidden (no idea if it needs to be a populated tab or not). It appears to me that since Access can't actually activate the hidden tab when you close a form, it remains on the currently selected one.
I don't know if this was fixed in Access 2013 or not, but hopefully the info isn't too late to be of use to someone.
It's A Bug!
MS support has accepted a bug submission for this, and commented regarding Office 2010 SP1, "The change that was implemented allows us to track the active tab for each database object (forms, reports, etc) using the tab’s TCID so that as you move between objects the active tab is restored. However custom tabs all use the same TCID value, so with this change the active tab for custom tabs will always move to the first custom tab."
We hope that they will release a hotfix to resolve this in the future.
Workarounds
The following information has proved useful for us in creating a workaround.
See the answer from Johanness above regarding the IRibbonUI.ActivateTab method. This was introduced in Office 2010.
There is no Office API (AFAIK) for getting the currently selected tab. Therefore we use code from this article helpful. We
create an array when we generate our ribbon containing the id value of each ribbon tab,
handle Form_Deactivate and use it to start a timer in another hidden form and also store the index of the selected tab,
in the Timer_Tick handler in the hidden form we disable the timer and look up the id value of the tab whose index we stored in Form_Deactivate, and
activate the tab using IRibbonUI.ActivateTab.
This article shows an interesting use of IRibbonUI.Invalidate and the getVisible callback to select a particular tab.
There seems to be a way to get the selected tab (as you mentioned and probably already have the code for, and as you can find here)
In the RibbonCode module:
Save the ribbonObject to a module-variable:
in the xml change the first line:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onload="OnRibbonLoad" >
and add this:
Private MyRibbon as IRibbonUI
Private ActiveRibbonTab as string
Sub OnRibbonLoad(ribbon As IRibbonUI)
Set MyRibbon = ribbon
End Sub
Sub RememberRibbonTab
ActiveRibbonTab=<Do the IAccessibleMagic here>
End
Sub RecallActiveTab
If ActiveRibbonTab<>"" then MyRibbon.ActivateTab(ActiveRibbonTab)
ActiveRibbonTab=""
End
Now in every form add
Private Sub Form_Close()
Remember_RibbonTab
End Sub
Private Sub Form_GotFocus()
RecallActiveTab
End Sub
Create an enumerator variable in a general code module corresponding to your ribbon tab numbers (ALT+Y)
' Used By Send Keys to Select Correct Ribbon Tab.
Enum eRibTabs
DataEntry = 1
Reporting = 2
StockAndParts = 3
AdminFinance = 4
DataImport = 5
OtherAdmin = 6
Admin = 7
LocalSystem = 8
End Enum
Create a form in ms Access called "zFrmRibbonSelect" and put an unbound text box called txtTabValue and then put the following code in your new form. (Suggest set form mode to hidden.
Private Sub Form_Current()
' Select Correct Tab Menu Item
Me.txtTabValue = Me.OpenArgs
End Sub
Private Sub Form_Close()
'Select Correct Tab Menu Item
Dim varTab As Variant
varTab = Me.txtTabValue
SendKeys "%Y" & varTab
SendKeys "{ESC}"
SendKeys "{ESC}"
End Sub
Private Sub Form_Timer()
DoCmd.Close acForm, Me.Name, acSaveNo
End Sub
Set form timer interval to 500 and check on event for timer shows in property box etc.
On your report put the following code: (use the enumerator value you want.)
Private Sub Report_Close()
'Select Correct Tab Menu Item
DoCmd.OpenForm "zFrmRibbonSelect", , , , , acHidden, eRibTabs.StockAndParts
End Sub
For Forms that close use the following code int the form
Private Sub Form_Close()
'Select Correct Tab Menu Item
SendKeys "%Y" & eRibTabs.StockAndParts
SendKeys "{ESC}"
SendKeys "{ESC}"
End Sub
Actually one approach that works well is to reduce or eliminate the tabs in the forms you open. If you specify the ribbon (other tab in properties sheet), then when you switch between forms the ribbon displayed switches for you automatic and without code.
Now while this is not really a solution to your problem, the idea and concept here is that if you have to start writing a bunch of code to engage and switch to what tab then this really becomes difficult as you point out.
As noted for Access/office 2010 you can use code to set the active tab (this feature is not available in Access/office 2007).
So about the only suggest I have here is trying and limit most forms to one tab when possible. The other tip is that while in the menus might be grouped by "type of task" and thus you might have a menu that cascades down to a whole bunch of reports. Now with the ribbon when working on a invoice, then you have:
Create invoice
Balance invoice
Post invoice
Print invoice (a report).
So all of the above options are different things but are group in one ribbon to allow you to get one job done.
So the idea here is to group ribbon options not by type of option such as all reports, but group + create a ribbon based on doing ONE task that includes the options that the user requires for given task at the given time.
As noted, the above may not be a solution to your issue(s), but avoiding additional tabs often will solve a lot of these issues.
I would like to know if there is a way to set the parameters in an Access 2007 query using VBA. I am new to using VBA in Access, and I have been tasked with adding a little piece of functionality to an existing app.
The issue I am having is that the same report can be called in two different places in the application. The first being on a command button on a data entry form, the other from a switchboard button. The report itself is based on a parameter query that has requires the user to enter a Supplier ID.
The user would like to not have to enter the Supplier ID on the data entry form (since the form displays the Supplier ID already), but from the switchboard, they would like to be prompted to enter a Supplier ID.
Where I am stuck is how to call the report's query (in the report's open event) and pass the SupplierID from the form as the parameter. I have been trying for a while, and I can't get anything to work correctly. Here is my code so far, but I am obviously stumped.
Private Sub Report_Open(Cancel As Integer)
Dim intSupplierCode As Integer
'Check to see if the data entry form is open
If CurrentProject.AllForms("frmExample").IsLoaded = True Then
'Retrieve the SupplierID from the data entry form
intSupplierCode = Forms![frmExample]![SupplierID]
'Call the parameter query passing the SupplierID????
DoCmd.OpenQuery "qryParams"
Else
'Execute the parameter query as normal
DoCmd.OpenQuery "qryParams"?????
End If
End Sub
I've tried Me.SupplierID = intSupplierCode, and although it compiles, it bombs when I run it. And here is my SQL code for the parameter query:
PARAMETERS [Enter Supplier] Long;
SELECT Suppliers.SupplierID, Suppliers.CompanyName, Suppliers.ContactName, Suppliers.ContactTitle
FROM Suppliers
WHERE (((Suppliers.SupplierID)=[Enter Supplier]));
I know there are ways around this problem (and probably an easy way as well) but like I said, my lack of experience using Access and VBA makes things difficult. If any of you could help, that would be great!
The suggestion being made here is to 100% REMOVE the parameter from the query. This not only solves your problem, but then means you can use the query for code, other forms and not have your whole design fall apart because one stupid form is not open (hence the VERY reason for your question).
So, remove the parameters from the query. This also means that your report will now not need some form that already opened. And again, if some silly form is not opened, why should your report fail to work?
So, remove the parameter. Now, in your form that opens the report, it can pass the filter, and more in point use what is a called a "where" clause. This "where" clause is designed in MS-access to solve the problem of having to know ahead of time what kind of parameters and filters you need. It occurs at runtime, and thus MANY DIFFERENT forms can call and open that report.
Now in the form that calls and opens the form, you go:
Docmd.OpenReport "rptSuppliers",acViewPreview, , _
"SupplierCode = " & me.SupplierCode
So, in the above, the parameter is created on the fly. The great advantage is tomorrow you can have another form open the same report and perhaps filter by region.
In the case of NO where clause being passed and a user simply opening the form, then no filters will be used and no prompts will occur and all records will show. This is probably your best approach.
However if for some strange reason you still deem it REALLY necessary to have some report prompt when one silly form just happens to not be opened, then place the following code in the forms on-open event.
If CurrentProject.AllForms("form1").IsLoaded = False Then
Me.Filter = "SupplierID = " & InputBox("Enter Supplier ID")
Me.FilterOn = True
End
However, I would really make efforts to avoid hard coding some silly form name in the reports open event. Not only does this mean your hard coding dependencies of some silly form that is now attached to a report, but if you later on copy that report, or even copy the original form (or even rename any of these objects), then you have to go into the application and hunt about and now find the places you as a developer introduced dependences. This approach can substantially increase the maintenance costs of an application and thus should be advoied.
So, the suggestion here is to dump the parameter query. Simply provide a form or some prompt system to launch the reports. Those forms should prompt the user for the information you wish to filter. Or as in your case the bound form and it current record provides that information. The beauty of this system is now there is no depdancy from the report.
Any form, or even any code down the road is free to pass a pramaeter, and it will not be limited to SupplierID, but can be any type of filter or parameter you wish.
Keep in mind that perhaps the user might not want that form to be open and perhaps they don't want the prompt. With your design and question the user will be forced to enter a parameter value even when launching the report without any forms open and not desiring to be prompted to allow them to view all reocrds in that report.
As I outlined in a recent post, I tend never to hardwire any parameters or form control references into the recordsources of reports or forms. Instead, I set them at runtime. The simplest way is by passing the WhereCondition property in the DoCmd.OpenForm/DoCmd.OpenReport:
DoCmd.OpenReport "MyReport", , , "[SupplierID]=" & Me!SupplierID
That assumes you're running it from a form that has the relevant SupplierID already present in its recordsource (i.e., you're on a record with that SupplierID).
More complicated is to use the OnOpen event of the report to set the reports's recordsource. That's what I outlined in the cited post above. But that example hardwires the choice to a selection form, whereas you might want to instead offer different sets of choices depending on context. There are two ways to handle that:
if A2003 and later, pass an OpenArg (the last parameter of the DoCmd.OpenReport) to tell the OnOpen event what to do to collect the information on what to filter to.
use an outside structure like a standalone class module to store criteria that the OnOpen event will read and act upon accordingly.
I suspect that the WhereCondition in the DoCmd.OpenReport is your easiest solution, but if you want details on the other two, just ask.