Is there a difference in performance (speed, memory used, etc.) when using the Access UI and setting a property to add a value to a textbox (or other control) as opposed to using VBA to do the same thing when object variables are correctly used?
For example, let's say that I want to select an item from a listbox and add values from the selected record to 2 textbox controls. I can do this by using the following VBA code in the AfterUpdate event procedure of the listbox:
Private Sub lstTest_AfterUpdate()
Dim lstA As Control
Set lstA = Me.lstTest
Me.txtTest1 = lstA.Column(0)
Me.txtTest2 = lstA.Column(1)
Set lstA = Nothing
End Sub
I can also set the ControlSource property using the MS Access UI via the Properties window in the txtTest1 and txtTest2 controls to the following to achieve the same result.
txtTest1 ControlSource: =[lstTest].[Column](0)
txtTest2 ControlSource: =[lstTest].[Column](1)
Is there any difference between these 2 approaches as far as performance is concerned? Any documentation on this would be greatly appreciated.
There is a “bit” of difference, but not really anything that going to make or break the application performance wise.
The first example could be considered better, since the values are “stuffed” into the other controls. The problem of course is next time you load the form, if txtTest1/2 are UNBOUND then next time the form loads, you would presumably have to run some code to re-load up the values again. (so this makes the first example worse)
Thus in your first case, the values will NOT persist and next time you load the form (or navigate to a different record), then such values will not update since your first example ONLY updates the values WHEN the after update event fires. That after update event ONLY fires WHEN you change the combo box, not on a general form load or navigate.
So the issue likely not performance, but simply that of your first example will NOT work nor display the data next time the form loads (unless of course the textboxes were bound to underlying columns).
Since the code is required to always run when the form loads, or record navigation occurs, you likely best use the control source approach since in BOTH cases you likely want these values to display correctly and thus in both cases you have to reference the .column() property anyway.
Related
I have 2 dropdown in a view. First drop down is automatically populated when the view get's loaded with the list of options. when an item is selected I would like to populate the dropdown # 2.
What's the best way of doing this?
A couple ways of doing this. You can either do an AJAX call (responding to the selection of a value in dropdown #1). The downside to this is that it requires a round-trip call to the server, then updating the value of dropdown #2 with the result.
The other way is to pre-load all possible values for dropdown #2 when the page first loads, and just change it in the browser with JavaScript as soon as the value is changed (rather than making a call all the way back to the server to get the values).
Either way, you're modifying the DOM, most likely, so it'll be some kind of JavaScript solution. Whether you choose AJAX, or preload and change it immediately will probably depend on how it affects the original page load speed, how much data you want to load onto the client, etc. If it's a relatively small number of options possible in dropdown #2, then pre-loading might be your best bet.
Using autogenerated form from a single database table. The form uses the class WizBtns included in c:\Program Files\Microsoft Visual FoxPro 9\Wizards. The form has Top, Previous, Next and Bottom buttons.
Although the form only has textboxes to enter data for the fields in the table, I have added a custom Text Box from the toolbox which basically intends to display the sum of some fields. I have bound the ControlSource of the text box to a PUBLIC variable costTotal that is created on the form init.
Now the problem is updating the sum of fields in the text box, or simply updating value of costTotal. Where to add the code for this? Adding the code in the form's Refresh method mixes up the value of costTotal, when I press Next button to update all fields with new values, the custom text box displays the sum of the last record which is mysterious.
I would add a method to the form to do the calculation. Then, call that method from the Valid method of each of the textboxes involved in the calculation.
There is nothing wrong with using the refresh event to recalculate the values, just make sure that you call the refresh each time the record changes
If you are using navigation buttons to move between records then the click event of EACH button is an ideal place to issue the refresh request :-
Assuming the textbox is called txtSum and is located on the same form as the navigation buttons then in each buttons click event add this code
dodefualt()
with thisform
.txtSum.refresh()
endwith
Couple of things:
1) do not use the wizards! Make your own base classes. Trying to figure out what the wizard classes do and how to add functionality will take more time that coding your own base classes. Also, the wizard generated code and classes must be at around 10/20 years old, much has changed since then (a polite way to say they suck).
2) Do not EVER use public variables in FoxPro, except for maybe an app object.
If this is a one shot thing, just add default textboxes and buttons and design the form yourself. You will have total control and you will know what each thing does.
Can we use an alternate function other than group to perform the same action. The scenario I am trying to workout using group is - I have multiple pages in a form and a summary button on the first page which on being clicked should show the summary of all pages.
The logic we tried was using group to club each individual pages by having a form variable which turns true when the summary button is clicked and we check this variables value in all pages and so when the summary button is clicked this condition satisfies and all the pages are displayed.
The Code Snippet
<Xforms:group id="page-1"
ref=".[instance('form')/current-page = '1'
or
instance('form')/summary = 'true']">
Using group fn drastically depreciates the performance. Is there any method to perform the same scenario. Kindly advise.
At this point, hidden groups and hidden cases work differently:
The controls in hidden groups are non-relevant.
The controls in hidden cases are relevant.
As a result, using a switch/case, the server has to do more work to maintain and update the state of controls in hidden cases, but switching to a another case is very fast: it is pretty much just a matter of changing a class in the HTML, as the values of all the controls are already there. With hidden groups, when "switching to another group", the values for the controls in that group are sent by the server to the browser. Updating the values can take a little bit of time, especially if you have a lot of controls, say in a repeat.
It is hard to give a recommendation without really running your code, but if the time taken to do a switch is mostly spent on the browser, you could investigate using the full update mechanism. If the time is mostly spent on the server, then I'd look into XPath analysis. (Note that both features are PE-only.)
This is my first time building a UI in Access (using Access 2007), and I'm wondering what is the Right Way (TM) of going about this.
Essentially, I have several different queries that I'd like to display as pivot charts, pivot tables, tables, and reports. Eventually I'm also going to have to build forms to manipulate the data as well, but the application's primary function is to display data.
I'm thinking of having a button for each different display down the left side of the main window, and having the rest of the window display each button's corresponding contents (e.g. a pivot chart).
I have an idea that this can be accomplished using a single subform in the main form, and setting the subform's Source Object property within a function such as this one:
Public Function SetSubformSourceObject(newSourceObject) As Variant
subform.SourceObject = newSourceObject
End Function
Then, for each button I'd set its OnClick property to call this function with the name of the query I'd like to run.
Now, I have no idea if this is the best way of going about things, and would really appreciate some input :)
The principle seems fair to me. You have to give it a try. You do not even need a form-subform structure. You can set your sourceObject at the form level, and have your buttons in a commandBar instead of having them as controls on the form, so you do not have any 'form specific' code (like "onCLick") and controls. action/command controls on a form are space, code and maintenance consuming, while commandbars are more generic and are THE object that can hold all your action controls.
I'm attempting to create a Wizard type control in VB6 and have run into a stumbling block.
I'd like to allow users of the control to be able to add and manage CWizardPage(s) to the design time control using a property page.
The first approach I used was to add the Wizard pages to the OCX directly using a Collection, however I ran into two problems in that the Collection class is not persistable (and I couldn't find an easy way to make it so) and that VB6 seems very limited in it's ability to instantiate controls at run time - so it would seem to be a struggle to actually re-instantiate them.
My next thought was to just allow the users to draw the wizard pages at design time. This sort of works, however it's far too easy to draw one of the wizard pages inside another wizard page instead of inside the CWizardContainer.
So can anyone please tell me how to add controls to a form at design time without using drag 'n' drop?
You can dynamically add controls to a form or other container (such as a UserControl) using the Add method of the container's Controls collection. For example, to add a TextBox named myTextBox to a form called frmMyForm, you could do this:
frmMyForm.Controls.Add "VB.TextBox", "myTextBox"
Here is a snippet from the VB6 help file:
Add Method (Controls Collection)
Adds a control to the Controls
collection and returns a reference to
the control.
Syntax
object.Add (***ProgID, name, container*)**
The Add method syntax has these parts:
object (Required)
An object expression that evaluates to
an object in the Applies To list.
ProgID (Required)
A string that
identifies the control. The ProgID of
most controls can be determined by
viewing the Object Browser. The ProgID
is composed of the Library and Class
of the control. For example, the
CommandButton control's ProgID is
VB.CommandButton. In cases where the
ProgID differs from that shown in the
Object Browser, Visual Basic displays
an error message that contains the
correct ProgId.
name (Required)
A string that identifies the member of
the collection.
container (Optional)
An object reference that specifies a
container of the control. If not
specified or NULL, defaults to the
container to which the Controls
collection belongs. You can put a
control in any existing container
control (such as the Frame control) by
specifying this argument. A user
control or an ActiveX document can
also be a container.
...VB6 seems very limited in it's
ability to instantiate controls at run
time...
Nothing could be further from the truth. Instantiating controls at run time in VB6 is trivial.
At design time, set the Index
property of the control to 0. This
turns the control into a control
array.
At runtime, load new instances of the control as needed.
As an example, create new Standard EXE project drop a TextBox onto the form, set its Index to 0 and put the following in the Form_Load event:
Private Sub Form_Load()
Dim newIndex As Integer
newIndex = Text1.UBound + 1
Load Text1(newIndex)
Text1(newIndex).Top = Text1(newIndex - 1).Top + Text1(newIndex - 1).Height
Text1(newIndex).Visible = True
End Sub
I have worked on an application that regularly made many whole data entry screens dynamically based on the desired fields. It's verbose to specify the Top, Left, Width, and Height all the time. So, you usually have a "template" of the control and copy those settings to the additional one.