I am trying to "convert" a more complex Access database/user interface into a custom app using VB .NET. I am also a NOOB in .NET so please be gentle.
Here are the steps I'm trying to take to duplicate my results in .NET
1) Create a Data Source (dsServer) to my SQL Server that pulls all tables and all data. I created this Data Source in my project already using the UI.
2) Create a Data Table (dtResults) in my Data Source that pulls all the info I need from 3 tables:
[Person] - This is a single entry list.
[Primary Teacher] - This is linked through column (Primary) on the [Person] table. This will return single results.
[Test] - This is liked by [Person].ID. This table has multiple entries per [Person]
I have also created this data table in my project under the data source using the UI.
3) Populate 12 comboboxes on a form that will be used to "filter" my results onto a DataGridView. Each combobox needs to be a DISTINCT list of what is in dtResults. Each time a combobox changes, the results in the DataGridView need to be updated as well as all the other comboboxes. (narrowing the choices to only what is available)
4) Create a DataGridView on the same form that will display the filtered results.
I don't seem to have any issues with creating the datasource or the datatable. What I can't figure out is how to populate the comboboxes from the datatable or how to bring back my filtered results to the datagridview.
Any help on the best way to accomplish this would be great.
It sounds like you want a single results gridview to be filtered by the optional selection of 8 different combo boxes.
When you generate the query for the gridview, you'll need to selectively include the where clauses for each combo box with a value. That should be as simple as sql += " AND Combobox2Column = #Combobox2Value " for each combo box. Don't bother using the column like '%' pattern for combo boxes with no selection. That can have negative performance impacts and is not necessary if you build your query in VB before sending to the database.
(This is a scenario when using "WHERE 1=1" as the first predicate in the where clause comes in handy. It does have a little bit of overhead, but it standardizes all the rest of the predicates to always start with AND to prevent the additional overhead of determining if the specific combo box is the only combo box with a value selected. If your query requires any other filters not based on the combo box, this becomes unnecessary)
Another important factor is that changing any combo box will trigger the event to refresh the contents of the grid view. Put your combo box refresh logic in a dedicated method, separate from an event handler. Then you can easily call that method from the event handler for each combo box (or any other control/event).
Hope that helps.
Related
I have a series of combo boxes on a form - and I have connected them to lists of data in the past by using a pass-through query to a sql server, and while this performs well in most cases, many of my users have been accessing the database using a VPN, and the response to populate them seems slow.
I started programming the system to populate a local table from the pass through query on form load - then, used a local query to show results in the proper order. Once they select the first combo box the second combobox filters from there, to the third, and the fourth (in some cases I have more than 4 too),
All of this is intended so I don't have to connect to the server each time they change selections. However, I am thinking that having a value list that is hard coded might be faster in performance for the lists that don't change - such as the highest level in the selection hiearchy (think of 3 or 4 comboboxes that effect each other and filter the next ones results).
Does anyone know if using a hardcoded value list in a combobox has a performance gain over a local query to a local table in MS Access? I am using MS Access 2016 if it helps.
Ok, a few things: you do NOT want to use a pass-through query for a listbox/combo box. NEVER!!!!
Why? The Access client cannot filter a PT query. This seems contradictory here.
First, lets be clear: the fastest way to pull data is a PT query - hands down.
However lets assume the combo box is large - say 3000 rows.
AND ALSO assume the combo box is bound (that means it saves a value to the form's bound recordset.
Well, remember the above rule!!! - Access client NEVER is able to filter the PT query.
So, if you have a report that you run? If your PT query is not PRE-FILTERED (the criteria exists in the PT query - even a stored procedure), then adding a where clause to the form (or report), or in this case a combo box WILL NOT WORK - the FULL data set is returned and can not be filtered.
So, if you have a PT query with 500,000 rows, and you do this:
docmd.OpenReport "rtpInvoice", acViewPreview,,"InvoiceNumber = 1234"
The above will pull 500,000 rows.
However, if you used a plane jane linked table, or best link to a view, and it ALSO has 500,000 rows? Well only 1 record comes down the network pipe!
So, if that combo box is bound to 5000 rows, and a simple navigation to the NEXT record occurs? Well, the combo box will of course have a single value - the underlying recordset of the bound form. But, it cannot filter + display the ONE value for the combo box (most combo boxes are multi-column - 1st column = PK, and 2nd column = some kind of description.
So, access is actually quite smart, and it will attempt to ONLY pulls the ONE value from the 5000 rows driving the combo box. But the exception to the rule is of course a PT query!
Again: Access client cannot filter a PT query.
So, if the combo box has a large data set AND ALSO is feed by a PT query, then things run slow as a dog. I had one system in which the PT query was returning about 100,000 rows. Just a simple navigation to the next record was slow as a dog.
Replacing the PT query with a linked view made the form work near instant. This is because out of the 100,000 rows, Access is able to ONLY pull the ONE row for display of the combo box and that 2nd column.
So, while a PT query is the fastest way to pull data? Yes, 100% true, but you ONLY want to use that speed advantage WHEN you need ALL OF the records of that PT query. If you going to filter AFTER or AGAINST the PT query (such as is done for a bound combo box), then a full scan of all records driving that combo box will occur.
The best approach? Dump the PT queries for a combo box, and replace them with linked views. You can even specify a sort in the view (yes, it does shove in the top 100%). So ONLY place the view name in the combo box - don't fire up the query builder.
And, you can even get away using a direct link to a linked table. Again, Access client can filter that data set for the combo box.
So, there is no need to waste all that developer time building a PT query for a combo box and there is no need (nor advantage in speed) attempting to use code to load up and fill a combo box. But, if the PT query is going to return more than about 30 rows, then you want to dump the PT query and use a linked table, or even better is a linked view.
I would not mess around with pulling a table from server to local - you could do that, but that's just extra code, extra pain, and it really gains you very little. And often it can make things worse. Why pull a whole table of lots of rows for a combo box, when just launching the form, access is smart enough to ONLY pull the one row required for display of the combo box. It will not pull the data until you click on the combo to make a choice.
If your PT queries are say over 50 or 100 rows to fill the combo box, and that combo box i a bound combo box? Then you have to dump the PT query, and use a linked table/view - and you get much better performance.
Rather than using tables linked from SQL server, consider using local tables for any values that rarely change, such as countries.
Have the master tables held within SQL server. When changes are needed, update the master table, and then import to your front end before deploying.
This way you will get better speed than from non-local tables, and are able to use these tables within queries and the like. And as the same data is held both within the Access front end and SQL Server back end, you can still create views within SQL server using the same data.
Regards,
For the life of me, I haven't been able to find this anywhere (other than solutions that exclude using the tableAdapter....
I have a simple setup. I have a datagridview. I have a tableadapter that is bound to the datagridview. This all works marvelously, but brings in the entire table. On the tableadapter itself, I have created a query called "nonServers" which returns the data I want.
So my question is, how can i bind the results of the tableadapter's QUERY to the datagridview, rather than the full results? When I try to add the query, it adds a button up top to trigger the query (as it's meant to do). But this is not what I want - i want the initial value to be the results of the query only.
any help appreciated, i reckon it's probably embarassingly simple
You're under some misconceptions. Firstly, your grid is not bound to a table adapter. The adapter is just a means to move data back and forth between the database and the application. The data is stored in the application a DataTable that is part of a DataSet. That's what your grid is bound to.
The default query for each table adapter is a SELECT * with no WHERE clause, so all columns and all rows. The table adapter has two methods - Fill and GetData - that execute that query. Fill will populate an existing DataTable, which will probably be part of a DataSet, while GetData creates and returns a new, standalone DataTable.
When you add a new query with a WHERE clause to filter, you are prompted to name the new methods that will execute that query. They are named FillBy and GetDataBy by default and you're supposed to append a meaningful suffix to that, e.g. if you were to filter by a ParentId column then you'd name the methods FillByParentId and GetDataByParentId. I'm not sure what exactly your query looks like but you might go with FillWithNonServers and GetDataWithNonSevers.
If you drag a table from the Data Sources window onto your form then that will add a bunch of controls and components by default and it will also generate some code, including a call to the Fill method of the appropriate table adapter to the Load event handler. In your case, you simply have to change that Fill call to a call to your new method and it will then invoke your custom query instead of the default.
I have a form with two unbounded comboboxes that work fine (one lists several age values and the other lists several region). I have a subform, which is a query that refers to the comboboxes, but I can't get it to update when I change values in the comboboxes.
My query is:
Select * from mastertable where (age=[form]![masterform]![age] and region=[form]![masterform]![region]
The query works in the sense that if I run it and input the parameters manually it works. It also works in the sense that if I create a button that runs the query on the form, it produces the correct table/query.
My question is how do I get the query to work as a subform? I'd like to be able to select values in the combo box and see the subform update, rather than having to click on a button that runs the query separately from the form.
I also tried creating a table that the parameters on the form can bound to, then relating those variables to the mastertable, but that also didn't work.
How do I get a table/query subform to update as information about the parameters changes in the form? I'm guessing it will require some VBA code on the "after update" event associated with the comboboxes. Any idea how to do this?
Thanks
I figured it out. I just put a little VBA code that requeries the subtable after update.
Code is [subform].requery
I have a SQL database where one of my fields 'Status' has one of 10 entries in it (not from a dropdown list). I let some people have access to the data through an Access database, they can add and modify entries.
My question is, in Access, how can I make it so that the 'Status' field is a drop-down list from which the users can choose from (the 10 entries which are already in the SQL database)? It would be easier for them and also mean that mistakes cannot be made.
Many thanks
Scott
The usual way to do this is to use a combo box on a form with the row source taken from the look-up table and the bound column set to the field (column) of the table to be updated.
In Access you can add lookup information to a column. That will automatically display a dropdown list.
Step 1: Start the lookup wizard:
Step 2: After the wizard, the lookup settings should look like this:
Step 3: When your users open a table, they should see the dropdown box:
In addition to the solution described by Andomar you must not use another table as the source for your lookup. You can also provide the lookup-values in a list, which is hardcoded in the table-definition. This is fine for simple scenarios where the lookup is something that is not likely to be changed.
Several issues here:
table datasheets are not suitable user interface for users.
you can create a saved QueryDef and if you view the properties of a field, the second tab is just like the second tab in table design, and allows you to use a combo box as your display type in your query. I would generally recommend against this, as, like table datasheets, a QueryDef is not a proper UI element, and if you use the saved query in other queries, you can run into the same problems that cause lookups in table fields to be such as bad idea.
you're building a UI, so use the tools that Access provides you for building a UI. That means a form. Your form's recordsource would have the bare data, and you'd create a combo box on your form that is bound to the field in the table behind your form, and displays the values from the lookup tables. There's a wizard to step you through this. If you like the look of datasheets so much (column sizing, sorting, show/hiding are all features that are nice in datasheets), you can set your form to display as a datasheet.
My advice is that for building a user interface, use the tools Access provides for creating user interface. In my opinion, a dropdown list belongs in a form, and nowhere else. While I occasionally might add one to a query for quick-and-dirty editing, I would never do that in objects that users are going to use.
On a VB.NET 2008 form I have a DataGridView, BindingSource and TableAdapter.
The BindingSource DataSource is a dataset.
In the dataset I have a Fill command that joins three tables and this is displayed without a problem in the DataGridView.
However, I am unable to Update the dataGridView because it has multiple tables from a single TableAdapter?
Does anyone know a simple way I can update. The tables has over 200 columns and I only want to update the columns that are changed. If I use a single table I can edit data in the DataGridView and the database is updated ok.
Any help would be appreciated?
Thank you.
Unfortunately, the Windows.Forms BindingSource, does not support complex properties (which I assume you are after).
You would have to craft your own custom BindingSource (and it will likely be bespoke to you) to handle complex property values and assignments.