Sorting Data on Form in Access 2010 by VBA - vba

I have the following setup:
Table "Mitarbeiter" (Users) with fields: "UNummer" / "Sortierung" /....
Table "Mo01" (a sheet for every month) with fields: "UNummer" / "01" / "02" / ....
The Field UNummer in Table Mo01 is a combination field that gets Mitarbeiter.UNummer and saves it as text
I call a Form "Monatsblatt" that is based on the table Mo01.
In that Form I have a Field "fldSort" that is calling "Sortierung" from table "Mitarbeiter". The Data in that field is based on "=DomWert("Sortierung";"Mitarbeiter";"UNummer = '" & [ID] & "'")"
This works and looks like this:
I am trying to sort the form by that "fldSort" in Form "Monatsblatt" by using this code:
Form_Monatsblatt.OrderBy = "fldSort"
Form_Monatsblatt.OrderByOn = True
When I start the form with that code running, Access asks for parameters:
I tried a lot of different ways of writing the code, referencing to the field in different ways. I do NOT want to base the form on anything other then the table.

Why not ask the wide world watch "Why Access asking me for Parameter"? That would have brought you to the clue I think. Debug.Print or MsgBox your .OrderBy and you see it's "fldSort", not a valid sort. Access is assuming you want to use a parameter called fldSort, but you want the string in the variable fldSort, but it's not recognized, because of the double quotes surrounding it. Everything between 2 double quotes is interpreted as a string, even it's a var name.
Delete the quotes and everything will work fine (if your sort string is sufficent)!
Form_Monatsblatt.OrderBy = fldSort
[Update]
Late, but now I see the clue. You added a calculated field to the form, but you can't sort or filter them.
Instead of appending this field to the table, create a query and add it there, then you bind the form to the query and add the field to the form. Now you can filter and sort as you like!
The query looks like this:
SELECT *,
Dlookup("Sortierung","Mitarbeiter","UNummer = '" & [ID] & "'") AS ldSort
FROM Mo01;
Or with a join:
SELECT
Mo01.*,
Mitarbeiter.Sortierung AS fldSort
FROM
Mo01
LEFT JOIN
Mitarbeiter
ON
Mo01.ID = Mitarbeiter.UNummer;
Now you can use
Form_Monatsblatt.OrderBy = "fldSort"
Form_Monatsblatt.OrderByOn = True
because you have a bound control called fldSort.
[/Update]

Related

MS Access select query inside another select query for selecting another field value

I don't think of any better way.
What I am trying to do is grab some data from table where the field childitem="NL" and the complex part in selecting fields to show is that, I need to make new field Consumption but this field value will be same childqty but when the field processname first 2 character is SC, I need to make the Consumption value to a childqty of another field: current father (4-SCF-329...[id:30]) is child to another father (4-FCM-3290...[id:17]) which is indeed child to another father (4-MCS-329....[id:21])
My Query:
SELECT tblBom.processname AS Process,
tblBom.child AS [SAP Code],
tblBom.childname AS Material,
iif(LEFT(tblBom.processname,2)="SC",
(SELECT childqty FROM tblBom WHERE tblBom.child like (SELECT father FROM tblBom WHERE child Like tblBom.father)),
tblBom.childqty
) AS consumption,
tblBom.childrate AS [Landed Rate],
tblBom.childrate * tblBom.childqty As RATE
FROM tblBom
WHERE tblBom.childitem Like "NL";
I want the tblBom.father last in the 5th line of code to be the main Queries father. Is there a way to make it as variable somewhere or any way. If I change it to "4-SCF*" that will work.
My Table
Excel Detailed View:
Orange: Condition checking for word "SC"
Yellow: The value that need to be replaced
Green: The value that will be placed on the yellow
ReddishPink: The path to Green value for query
Desired OutPut
My solution requires two calculated fields and two queries. The calculated fields are UltimateFather and consumption. we require two queries because the problem doesn't guarantee that a child's father has a value of childitem like "NL". Hence we can't throw out any data before calculating each child's UltimateFather. Ultimate Father is based on adding the public function GetUltimateFather to a code module. Getting the UltimateFather is a recursive problem so see here for commentary on recursive functions in queries:
Is it possible to create a recursive query in Access?
'calculated fields
UltimateFather: GetUltimateFather([child])
consumption: IIf([processname] Like ("SC*"),DLookUp("childqty","tblBom","father = '" & [UltimateFather] & "'"),[childqty])
Public Function GetUltimateFather(childid As String) As String
Dim currentchild, hasfather As String
currentchild = childid
'string variables make sure to escape and delimit strings properly'
hasfather = Nz(DLookup("father", "tblBom", "child = '" & currentchild & "'"), "")
If hasfather = "" Then
GetUltimateFather = currentchild
Else
GetUltimateFather = GetUltimateFather(hasfather) 'get next father in chain
End If
End Function

SQL Injection from a textbox

I'm new to MS Access.
So, I wrote a SQL query(query name = qryEmployeeInfo) which shows employee information. The query outputs two columns. The employee ID(header name = employee_ID) and the corresponding employee address(header name = employee_address).
My Access form has a text box(text box name = txtEmployeeID) that I want the user to be able to enter the employee_ID into and have it output the corresponding employee_address into another text box (text box name = txtEmployeeAddress). I also want the employee_address to be in the format of a string variable so I can perform other VBA checks on it later(for example - if LIKE "California" THEN...something).
I want to write what (I think) is called an injection SQL query so that I can pull the address data from the query for that specific employee_ID. I believe the format should look like this:
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("select employee_address from qryEmployeeInfo where employee_ID = "' & txtEmployeeID & "'", dbOpenDynaset)
Do I have this written correctly?
If so, then how do I get that output into a string variable format(variable name = strEmployeeAddress)?
After I get the employee address into a string variable format I want to simply use txtEmployeeAddress.value = strEmployeeAddress to populate the employee address text box. Again, I also want the employee_address to be in the format of a string variable so I can perform other VBA checks on it later(for example - if LIKE "California" THEN...something).
Any help you could provide would be greatly appreciated.
If employee_ID is a number field, remove apostrophe delimiters.
If employee_ID is a text field, move first apostrophe so it is within quote marks.
"select employee_address from qryEmployeeInfo where employee_ID = '" & txtEmployeeID & "'"
Then txtEmployeeAddress = rs!employee_address
However, instead of opening a recordset object, could just use DLookup.
txtEmployeeAddress = DLookup("employee_address", "qryEmployeeInfo", "employee_ID =" & txtEmployeeID)
Or even better, eliminate the VBA. The DLookup() expression can be in textbox ControlSource property, just precede with = sign.
However, domain aggregate functions can perform slowly. So instead of textbox, use a combobox for selecting employee. Include employee information in combobox RowSource. Expression in textbox references column of combobox: =combobox.Column(1). Issue is combobox has limit on how many characters can be pulled into column so if field is memo (long text) type, this approach is not feasible and should use DLookup.
The address will be available in textbox for use as long as this form is open. If you want the address to be available to other procedures even after form is closed, then need to set a global or public variable. Such variable must be declared in a module header to make it available to multiple procedures. TempVars are another way to hold values for future use. I have never used them.

Use an Access Forms Unbound text box as a Field filter in a table

Access 2013 - Reference an Unbound text box on a Form
I am currently trying to use an unbound text box [Text161] on a Form name [DCM_Gap_Servers] to sort information through a table. I want the query that I created to be able to take the users input from [DCM_Gap_Servers]![Text161] as the field that is being sorted from the table names 'Server'.
This is the SQL I am using right now in the query:
SELECT * FROM Servers WHERE "Forms![DCM_Gap_Servers]![Text161]" IS NULL
** I have already Tried:
"Forms![DCM_Gap_Servers]![Text161]" ; (Forms![DCM_Gap_Servers]![Text161]); Forms.[DCM_Gap_Servers]![Text161]
This will work at any time if I replace the Text Box reference with the actual Field name I am using, but since there are hundreds of combinations of fields, I need the reference to work.
I have looked all over, and I can't seem to find the correct answer. I am willing to do it in VBA if needed, whatever it takes to get the filtering done correctly.
Thank You.
It is:
SELECT * FROM Servers WHERE Forms.[DCM_Gap_Servers].[Text161] IS NULL
but that will just select all records whenever your textbox is Null.
So it rather is:
SELECT * FROM Servers WHERE SomeField = Forms.[DCM_Gap_Servers].[Text161]
To use the form value as a field name, you must use concatenated SQL:
strSQL = "SELECT * FROM Servers WHERE " & Forms![DCM_Gap_Servers]![Text161].Value & " IS NULL"
This you might pass to the SQL property of an existing query object:
MyQueryDef.SQL = strSQL
Or:
Constant SQL As String = "SELECT * FROM Servers WHERE {0} IS NULL"
FieldName = Forms![DCM_Gap_Servers]![Text161].Value
MyQueryDef.SQL = Replace(strSQL, "{0}", FieldName)
Of course, take care the the field name isn't a zero length string.

MS Access multi field search with empty fields

I have a problem very similar to this one, but I just can't seem to solve it!
In MS Access (2003), I want to search a table based on entries in a number of fields, some of which may be empty.
I have:
text fields
date fields
integer fields, and
a memo field (but we can probably not bother searching this one if it is difficult).
They map onto a table exactly.
I am trying to create a query that will return matching rows when data is entered into one or more of these fields, but some fields can be left blank. How the heck do I do this?
A query like the one on the linked question works for text fields, but what do I do about the number fields, date fields (and possibly even the memo field)?
To give a clear example, the following code block works for TextField1, but not NumberField1:
PARAMETERS [Forms]![SearchForm]![FilterTextField1] Text ( 255 ), [Forms]![SearchForm]![FilterNumberField1] Text ( 255 );
SELECT Table1.[TextField1], Table1.[NumberField1], Table1.[TextField2], Table1.[TextField3], Table1.[DateField1], Table1.[DateField2], Table1.[DateField3]
FROM Table1
WHERE (Len([Forms]![SearchForm]![FilterTextField1] & '')=0 OR Table1.[TextField1] Like '*' & [Forms]![SearchForm]![FilterTextField1] & '*') AND (Len([Forms]![SearchForm]![FilterNumberField1] & '')=0 OR Table1.[NumberField1] Like '*' & [Forms]![SearchForm]![FilterNumberField1] & '*');
I do hope you can help. I'm sure I'm missing something really obvious, but for some reason my brain feels like it is leaking out of my ears at the moment.
Thank you!
If you need it, this is the basic design of the relevant entities:
Table1
SomePrimaryKeyWeDontCareAboutRightNow
TextField1
TextField2
TextField3
NumberField1
DateField1
DateField2
DateField3
MemoField1
SearchForm
FilterTextField1
FilterTextField2
FilterTextField3
FilterNumberField1
FilterDateField1
FilterDateField2
FilterDateField3
FilterMemoField1
You can check fo null values or cast to string
You could certainly spend a great deal of time crafting a huge and very hard to debug SQL query for this, or just jump into VBA and write some code to construct just the SQL you need.
VBA is there just for these kinds of scenario, where something is either impossible or becoming too complex to do otherwise.
With VBA, you can use an initial SELECT query that collect all the data, and then construct a WHERE clause based on the content of your search form to filter it.
For instance, I have a form like this, that allows the user to enter any criteria to filter a list of prices:
Some code to implement this could look like:
' Call this whenever the use click the Apply button '
Private Sub btApply_Click()
' Construct the filter '
Dim filter As String
If Not IsBlank(cbSupplierID) Then
If Not IsBlank(filter) Then filter = filter & " AND "
filter = filter & "(SupplierID=" & cbSupplierID & ")"
End If
If Not IsBlank(txtPartNumber) Then
If Not IsBlank(filter) Then filter = filter & " AND "
filter = filter & "(PartNumber LIKE '*" & txtPartNumber & "*')"
End If
If Not ckShowLocked Then
If Not IsBlank(filter) Then filter = filter & " AND "
filter = filter & "(NOT PriceLocked)"
End If
' ... code snipped, you get the jest ... '
' Now re-construct the SQL query '
Dim sql As String
sql = "SELECT * FROM Price"
If Not IsBlank(filter) Then
sql = sql & " WHERE " & filter
End If
SubForm.Form.RecordSource = sql
End Sub
It may seem like a lot of code, but each block only does one thing, and it's a lot easier to debug and maintain than cramming everything into a query.

how to replace text in a multifield value column in access

I've got a tablea such as below, I know its bad design having multifield value column but I'm really looking for a hack right now.
Student | Age | Classes
--------|------|----------
foo | 23 | classone, classtwo, classthree, classfour
bar | 24 | classtwo, classfive, classeight
When I run a simple select query as below, I want the results such a way that even occurrence of classtwo is displayed as class2
select student, classes from tablea;
I tried the replace() function but it doesnt work on multivalued fields >_<
You are in a tough situation and I can't think of a SQL solution for you. I think your best option would be to write a VB function that will take the string of data, parse it out (replacing) the returning you the updated string that you can update your data with.
I can cook up quite a few ways to solve this.
You can explode the mv by using Classes.Value in your query. This will cause one row to appear for each value in the query and thus you now can use replace on that. However, this will result in one separate row for each class.
So use this:
Select student, classes.Value from tablea
Or, for this example:
Select student, replace(classes.Value,"classtwo","class2") as myclass
from tablea
If you want one line, AND ALSO the multi value classes are NOT from another table (else they will be returning ID not text), then then you can use the following trick
Select student, dlookup("Classes","tablea","id = " & [id]) as sclasses
from tablea
The above will return the classes separated by a space as a string if you use dlookup(). So just add replace to the above SQL. I suppose if you want, you could also do replace on the space back to a "," for display.
Last but not least, if this those classes are coming from another table, then the dlookup() idea above will not work. So just simply create a VBA function.
You query becomes:
Select student, strClass([id]) as sclasses from tablea
And in a standard code module you create a public function like this:
Public Function strClass(id As Variant) As String
Dim rst As DAO.Recordset
If IsNull(id) = False Then
Set rst = CurrentDb.OpenRecordset("select Classes.Value from tableA where id = " & id)
Do While rst.EOF = False
If strClass <> "" Then strClass = strClass & ","
strClass = strClass & Replace(rst(0), "classtwo", "class2")
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
End If
End Function
Also, if you sending this out to a report, then you can DUMP ALL of the above ideas, and simply bind the above to a text box on the report and put the ONE replace command around that in the text box control. It is quite likely you going to send this out to a report, but you did ask how to do this in a query, and it might be the wrong question since you can "fix" this issue in the report writer and not modify the data at the query level. I also think the replace() command used in the report writer would likely perform the best. However, the above query can be exported, so it really depends on the final goal here.
So lots of easy ways to do this.