I have one textbox basically the user is going to enter in a 9 digit number or letters. From there I want to have a buttonclick event that validates this against 2 columns in a MSSQL Database. First to check if the number exists, next to check if it is active or inactive.
There are about 27000 rows of numbers so my main question is what is the best approach to handling something like this.
Should I create a view and validate in the click event.
Should I create a stored procedure in sql that takes an input parameter and call it in the click event.
I was also reading about storing the information in a dataset however with that many records i am assuming that is going to be a slow process.
If none of these approaches are right I would appreciate the correct way to go about doing this and maybe a few links that can get me started. I searched but most people are using a dataset and if that is not going to affect my performance I will more than happy to approach it that way just not too sure.
Thanks
Stored Procedures and Views should work the same as long as you have a where clause that filters down to exactly the data you want, rather than (in the case of the view) returning all rows from the view and then filtering in memory. It would need to look like this:
Select Number, Activer from ViewName where number = (your number)
or
EXEC spValidateNumber #Number = (your number)
As for when to do your validation, if this procedure takes more than, say, one second, you should probably have the user ask for validation by clicking a button, so that they anticipate the delay. If it runs on the textbox's lostfocus event, it should run without any noticable delay for the user.
Related
In my SSRS report I am attempting to incorporate entitlements. If a user puts a specific person ID in the parameter, I'd like to be able to compare it against the up to 50,000 ids they are entitled to use and to put up an error message if not.
The available values feature only allows me to use a dropdown, which is incovenient for so many ids. What are my options?
A drop down would be very inconvenient for that many choices. Is it possible to break them down by a category or something like that? You could then create cascading parameters to make the list easier to deal with.
Otherwise it would have to be a free text field. Depending on the complexity of the report contents you could handle it a couple of ways.
If it is a very simple report with just a tablix you can set the no data row value to your error message.
If it is more complex you can display the error message using two rectangles. The first one would simply contain a text box with the error message in it. Then put the actual report comments in the second box. Control the visibility of these rectangles based on an expression that checks the number of rows returned by the dataset or some other indication that the input was invalid. You may even need to create a second dataset to check for input validity if there isn't a reliable way to use your normal query.
I have a query that accepts input from a form. The query works as expected when I run it, manually typing in the form input values. However, when I run the query from the form, the query returns blank - no error, just blank.
I don't understand what's causing it - at it's most basic, the user is simply entering a Start and Stop date. I'm entering the data exactly the same, and made sure my form text box is formatted as a date.
Furthermore, when I run the form, I am not prompted for any values, so I know it's reading them accurately. This system works for several similar queries, but not this one.
What I've tried
Changing the format of the text box to specify Short Date (which is how I type it)
Visually confirming the values are making it from the form to the hidden staging area the query references - these values match what I manually enter into the prompts
The query I'm runnning references another query; running the other one by itself only yields one set of "date" prompts, not two. So I created a seperate date input box for each to read off of, but to no avail
Question: Does Access try and format (or not format) parameter input boxes differently than it would handle form references?
Additional detail - when I run the query manually, it prompts me for the dates twice - I don't know why or it's pertinent, but I thought I'd mention it.
use instead Temporary variable in your Query for the specified dates. After you select the dates from the Form, make sure that the values are assigned to the temporary variables and that you requery the record source of the form
I was able to get this working by tweaking my query in the designer - specifically by splitting up my expression into multiple pieces and writing the criteria in segments.
I'm not sure why this did the trick, but it at least got me where I needed to go.
Good luck to anyone else experiencing this!
tldr: Can not update records from query because of aggregate functions. What workarounds do you suggest?
I have a table containing decision criteria to which a user can assign a relative weight. I calculate the absolute weight in an SQL query using an aggregate function (as described here Divide the value of each row by the SUM of this column).
qryDecisionCriteria
name relative_weight absolute_weight (calculated)
price 2 50 %
quality 1 25 %
experience 1 25 %
I would like to present the query result in a form, where the user can update the relative weights, and then sees the absolute_weights.
However, the query results are not updatable, because the query involves an aggregate function.
What alternative methods or workarounds could I use, so that a user can edit relative_weights and view absolute_weights as a kind of visual feedback?
I read about temporary tables here http://www.fmsinc.com/MicrosoftAccess/query/non-updateable/index.html but I'm not sure, how to implement this.
Maybe I could also create an additional "edit form" based on a simple query, that is automatically invoked when the user selects a record in qryDecisionCriteria data?
Or maybe just display data from two queries (one updatable, one with the calculated field) next to each other in the form?
Which options would you recommend and why?
Make the Record Source for the form the updatable base query. In the text box which shows the calculated absolute weight set the control source to
=DSum("relative_weight","<base table name>")/Forms!<Form Name>!relative_weight
You'll need to be sure that you do two things with this
When you drag fields onto a form in Access it makes the name of the control the same as the control source column. this is really annoying and can cause a lot of headaches. Rename your control to something like txtColumnName. That way Forms!<Form Name>!relative_weight is guaranteed to reference the field and not the textbox.
in the AfterChange event for the relative_weight textbox you should add an event handler in which the following code is run
txtabsolute_weight.Requery
This will make sure the formula is recalculated whenever someone changes a weight. Otherwise they need to hit F5.
So I've been researching for days now on how to filter a rowsource result on a control in a way that is comfortable, hopefully you understand what I mean by that as I explain. I have found solutions, a bunch of solutions. I'm more concerned with evaluating their benefits and negatives.
I have a specific example, but my concern is really more generic. This, to me, seems like the backbone of my application and so I want to make sure it's being done correctly, the best way, not just in a way that "works".
Basically, I have progressive combo box filters. The first box filters the second box, which then selects a record in a Single Form view. The two combo boxes are in the header of the form.
Lets say I have a table CanadianCities. The two combo boxes might be, cboProvinceFilter "Filter by Province", and cboCitySelect "Select City"
When I load the form the province filter is off, so the cities list is populated with a rowsource that selects ALL the cities (SELECT ID, CityName FROM CanadianCities). But that's a big list, so I have the second combo box to narrow that list down by province (SELECT ID, ProvinceName FROM CanadianProvinces).
So the goal is that on cboProvinceFilter.AfterUpdate to requery cboCitySelect with an altered where clause ("[...] WHERE ProvinceID = [cboProvinceFilter]").
The problem is in how to alter the where clause. Ideally, the above would work right in the designer, but SQL designs seem to be out of the form's scope so cboProvinceFilter doesn't exist there. I agree with the opinion that direct referencing forms is bad. I don't want to marry my sql to the form like that. Plus, I want to use a navigation form, but also have a mobile option, so running the forms individually AND in navigation would be ideal, absolute referencing can't do this.
Having my repetitious SQL statements buried in code feels like poor design, and repeating the same queries with slightly different filtering is terrible when Parameters are exactly for that reason.
And some will scoff at this, but it also feels bad to rewrite the functionality of the Access designer in VBA. If I build my own SQL, execute my own queries, and populate my own lists, why did Microsoft put all the effort into building this productivity assisting tool for? Filtering is not exactly an obscure feature of database management... I feel like there must be a reasonable way to do this sort of thing.
Also, popup forms are obnoxious, so I won't be making specific forms just to have reliable absolute references. That definitely feels like a cop-out.
Solutions that do feel good but I haven't made work...
SQL Parameters
The most sensible way of doing this I feel should be with SQL Parameters, as that's what they're intended for right? The QueryDef would store values for it's parameters that could I could change as needed. However, I would let the queries execute naturally on requery.
So instead of writing the handful of lines to execute the Query and populate the control, I'd just set the parameter values and call requery on my control, which has all that functionality built into it.
So defined some parameters in the SQL statement, then tried to set the values of those parameters in VBA before the Query was executed, but JET always seems to pop-up for the parameters if it doesn't reference an actual object, it wasn't checking my code-set querydefs.
For that to work, it seems that I'd have to execute the SQL manually, and parse my own recordset, and populate the control. Which feels like an excessive amount of repetition for every filter option I'd want to offer.
Relative Referencing
I don't mind referencing forms as long as it's a relative path. Unfortunately [Screen].[ActiveForm] refers to the navigation form, not the actual, active form... So that seems to be out.
Right now I'm thinking my only option is to set rowsource manually then call the control's requery. that's the less offensive feeling option. Might be best to take the current query and string replace the where portion, so i don't have to update every event if the query structure changes.
Final Thought
Anyway, this is getting ranty, so let me know your thoughts. I'm not really looking for code solutions, which is why I offered few to no hard examples. I'm looking for a paradigm for managing this kind of filtering that isn't too restrictive (absolute referencing) or too repetitive/wheel-re-inventing (hard coded sql, executing, control populating).
If your Access version is >= 2007, you can use the TempVars Collection. Here is an Immediate window session.
' add a TempVar with value
TempVars.which_id = 12
' or do it explicitly with Add method
TempVars.Add "which_id", 12
? TempVars!which_id
12
' asking for the value of non-existent TempVar returns Null
? TempVars!bogus
Null
A query can reference the TempVar to filter the result set.
SELECT f.*
FROM tblFoo AS f
WHERE f.id=[TempVars]![which_id] OR [TempVars]![which_id] Is Null;
So you could use that approach in the row source query for the cboCitySelect combo box. Then assign the TempVar value in the After Update event of cboProvinceFilter and next Requery cboCitySelect.
For Access versions < 2007, the TempVars Collection is not available. In that situation you could use a custom VBA function to hold a static value which can be referenced in a query.
SELECT f.*
FROM tblFoo AS f
WHERE f.id=TargetId() OR TargetId() Is Null;
Public Function TargetId(Optional ByVal pValue As Variant) As Variant
Static varReturn As Variant
If IsMissing(pValue) Then
If VarType(varReturn) = vbEmpty Then
varReturn = Null
End If
Else
varReturn = pValue
End If
TargetId = varReturn
End Function
In an alternate application, the user has the ability to update their address and phone number. When these are changed, three fields will update: Old Value, New Value, and Field Changed. If the Field Changed was the address, I need to create two report pages - one with the old address and one with the new. However, if the Field Changed was the phone number, I only need to create one report page for the current address.
My initial plan was to do a Union that would have one record with the Old Value and another with the New Value. This should work when only the Address has changed. However, it won't whenever the Phone Number has changed. I assume I need to do some sort of case statement, but I'm not really sure if this is the right approach. Sorry if the data is a little confusing (I didn't design the data structure. This was provided by our professor's assistant). If you need more information, I'll try to provide it.
I'm not looking for exact SQL, but I am wondering if I'm approaching this the correct way.
What do you mean by a 1 or 2 page report? Are you outputting to a CSV, PDF, XLSX or something eles?
If you need to do this through "pure" sql I would recommend a stored procedure that is given a value stating whether it's the address or phone number that is being updated. It can then do the update and you can simply do an if statement which determines which report to run and return.
I'd recommend handling it programatically if possible. Have your code run the sql update and then call the appropriate function within your code to get the report you need. You can then easily re-use the code for that report in other ways.