i have a table like this and now my task is to fill the empty field with respect to vol and country of the respective column
rule : i have to see the highest volume in the vol field and take the country of that vol and put it in the empty field (ie i have to fill empty cell with country JP because the vol of japan is more )
like this i have to fill .
the remaining fileds like RB , Plant, MCR are changing for remaining empty cells.
i had use Dlookup for this but i coudnt get the solution could any one please help me it is very helpful if you find me the solution.
like this i have to fill all empty line in the table
Ok i am giving more clear view of my table view so that you can understand easily
this is the only table i have to do the task
and now my task is i have to fill the empty cells in the country field but the condition is i should look the RB , Plant ,MCM with respect to vol field (ie: if you see the table the RB , plant ,MCM feilds are same but the country and vol are changing for one group so i have to also consider the fields, that means if the RB, plant, mcm fields are same then i have to take the one of the country in the group with the highest volume) (i just give example in the first thre rows RB , plant , MCM are same so i have to take the highest volume country ie IN so the empty cell should be IN and secodn group empty cells should be TH like that i have to fill.
As I mentioned in my comment to Johnny Bones' answer, your original requirement could have been accomplished with an UPDATE statement that used the DLookup() and DMax() functions like this:
UPDATE MyTable
SET Country=DLookup("Country","MyTable","Vol=" & DMax("Vol","MyTable"))
WHERE Country IS NULL
Even with your revised requirements it is still possible, just more scary-looking:
UPDATE MyTable
SET Country=DLookup("Country","MyTable","RB='" & RB & "' AND Plant='" & Plant & "' AND MCM='" & MCM & "' AND Country IS NOT NULL AND Vol=" & Nz(DMax("Vol","MyTable","RB='" & RB & "' AND Plant='" & Plant & "' AND MCM='" & MCM & "' AND Country IS NOT NULL"),0))
WHERE Country IS NULL
The above query was tested and verified as working in Access 2010.
You can do it in VBA, and have more control over how it reacts. Something like this will do:
Dim db As Database
Dim rec As Recordset
Dim MySQL As String
Set db = CurrentDb
Set rec = db.OpenRecordset("Select Top 1 MyTable.Country FROM MyTable ORDER BY MyTable.Vol DESC")
MyCountry = rec(0)
rec.Close
SetWarnings = False
MySQL = "UPDATE MyTable SET MyTable.Country = '" & MyCountry & "' WHERE IsNull(MyTable.Country) or Len(MyTable.Country) < 2"
DoCmd.RunSQL MySQL
SetWarnings = True
db.Close
I tested the above and it works, although if your table's field's properties are different you may need to tweak some of the code.
Obviously, anywhere you see "MyTable" you should use your own table's name.
Related
Hopefully I can explain this in a way that someone will understand what I am trying to achieve and be able to offer a possible solution.
I am creating a database for managing Health and Safety at my workplace. I have one table created to store employees - "Table: Employees". This table has the usual fields (First Name, Last Name etc.) but specifically has the following fields: "Departments" (Multiple selection as employees can move between), "Additional Competencies" (e.g. Forklift, Order Picker etc. (Again multiple selection)), and "Gender".
I have a second table ("Table: Toolbox Talks") which is where the system stores tool box talks (created by the user through a form. "Form: Toolbox Talk"). The intended recipients of a toolbox talk will generally be limited to either one or more departments, or maybe just all forklift drivers or all of one gender. When the user creates a new toolbox talk (record), they will in the form (Form: Toolbox Talk) select from drop down lists the appropriate variables (Department, Competency, Gender). (N.B. a toolbox talk can sometimes be relevant to more than just one.)
What I am trying to achieve is to some how create a query that for each toolbox talk, it will return only the employees who are required to participate in the toolbox talk.
For example:
Say a toolbox talk is required to be carried out for all "female" employees who work in "warehousing".
I would then want my database in a datasheet subform on form - "Form: Toolbox Talk" to return all employees who are female and are marked as able to work in warehousing department.
I'll just add that I would like to avoid the intended system user using the filter buttons on the ribbon and my preference would be to use query's or vba if possible.
What I have tried so far:
1. I created a query ("Query: EmployeesperToolboxTalk") and added two tables ("Query: EmployeesExtended" & "Query: ToolboxTalksExtended"). I tried creating joins between the relevant fields (e.g. Gender to Gender, Department to Department etc.) but this did not work as either join properties 1, 2, or 3.
If I limit my join to say just departments, then that seems to do what I want but it doesn't include the other two variables which isn't really how I want it to work.
SELECT [Query: EmployeesExtended].[Employee Name], [Query: EmployeesExtended].Department, [Query: ToolboxTalksExtended].[Toolbox Talk], [Query: ToolboxTalksExtended].ToolTalkID, [Query: ToolboxTalksExtended].RecipientVariables
FROM [Query: EmployeesExtended] INNER JOIN [Query: ToolboxTalksExtended] ON ([Query: EmployeesExtended].Gender = [Query: ToolboxTalksExtended].RelatedGender) AND ([Query: EmployeesExtended].AdditionalCompetency.Value = [Query: ToolboxTalksExtended].RelatedCompetency.Value) AND ([Query: EmployeesExtended].Department.Value = [Query: ToolboxTalksExtended].RelatedDepartment.Value);
2. Following that, I created a union query to combine all the different variables into one:
SELECT [Table: Competencies].Competency
FROM [Table: Competencies];
UNION
SELECT [Table: Departments].Department
FROM [Table: Departments];
UNION SELECT [Table: Gender].Gender
FROM [Table: Gender];
I then added a field "RecipientVariables" to table: "Table: Toolbox Talks" and set the row source to:
SELECT [Query: RecipientVariables].Competency
FROM [Query: RecipientVariables];
I then created a join from "RecipientVariables" to Departments, AdditionalCompetency and Gender:
SELECT [Query: EmployeesExtended].[Employee Name], [Query: EmployeesExtended].Department, [Query: ToolboxTalksExtended].[Toolbox Talk], [Query: ToolboxTalksExtended].ToolTalkID, [Query: ToolboxTalksExtended].RecipientVariables
FROM [Query: ToolboxTalksExtended] INNER JOIN [Query: EmployeesExtended] ON ([Query: ToolboxTalksExtended].RecipientVariables.Value = [Query: EmployeesExtended].Department.Value) AND ([Query: ToolboxTalksExtended].RecipientVariables.Value = [Query: EmployeesExtended].AdditionalCompetency.Value) AND ([Query: ToolboxTalksExtended].RecipientVariables.Value = [Query: EmployeesExtended].Gender);
This returns no results using join properties 1, 2 or 3.
3. The last thing I have tried is to create a second union query from my employees table ("Table: Employees"):
SELECT [Table: Employees].AdditionalCompetency.Value
FROM [Table: Employees];
UNION
SELECT [Table: Employees].Gender
FROM [Table: Employees];
UNION SELECT [Table: Employees].Department.Value
FROM [Table: Employees];
I then added a new field into my employee table: "AreasofCompetency" and set the Row Source as:
"Query: EmployeeVariables"
This also doesn't work.
I am now at a loss of what to try next.
Perhaps what I want to do is not possible or its much easier than I realise.
If someone can please give some guidance or perhaps offer an alternative suggestion, I would be very grateful. Please let me know if any additional info is required and I will gladly provide it.
Many thanks in advance.
as per my comment first normalize your table structure. For instance something like:
Then create a query that selects everything related to employees. Here that is everything. Select that query and click create form and access will make a form for you:
The unbound combobox and unbound listbox in the header are actually not there yet and the form shows every variable in the record source and hence is not user friendly. add comboboxes and listboxes to the header for every variable you want to filter employees by. Also delete and or move the labels and textboxes as you want. Here I got:
Then you want to edit the after update event for the various unbound controls to filter the records. for instance see Filter form based on two combo box selections
Private Sub cmbCompetency_AfterUpdate()
'cheap example hookup, same code for lstDepartments
Me.Filter = "EmployeesCompetencies.CompetencyID = " & cmbCompetency & " AND EmployeesDepartments.DepartmentID = " & cmbDepartment
Me.FilterOn = True
End Sub
this gets you:
Database Design
First you need to get rid of the multivalue columns. Using a multivalue columns never a good idea for several reasons and they are an especially bad idea when the same values appear in two or more tables and you want to join on those columns. Here is a normalized database design.
Department table
Column Name
Data type
Required
Description
Id
Autonumber
Y
Primary key
Name
Short text
Y
Competency table
Column Name
Data type
Required
Description
Id
Autonumber
Y
Primary key
Name
Short text
Y
Employee table
Column Name
Data type
Required
Description
Id
Autonumber
Y
Primary key
First_Name
Short text
Y
Last_Name
Short text
Y
Gender
Short text
Y
Employee_Department table
Column Name
Data type
Required
Description
Employee_Id
int
Y
Foreign key references Employee (Id)
Department_Id
int
Y
Foreign key references Department (Id)
Employee_Competency table
Column Name
Data type
Required
Description
Employee_Id
int
Y
Foreign key references Employee (Id)
Competency_Id
int
Y
Foreign key references Competency (Id)
Toolbox_Talk table
Column Name
Data type
Required
Description
Id
Autonumber
Y
Primary key
Title
Short text
Y
Target_Gender
Short text
N
Null indicates no specific target gender (i.e., any value of gender)
Toolbox_Talk_Target_Department table
Column Name
Data type
Required
Description
Toolbox_Talk_Id
int
Y
Foreign key references Toolbox_Talk (Id)
Department_Id
int
Y
Foreign key references Department (Id)
Toolbox_Talk_Target_Competency table
Column Name
Data type
Required
Description
Toolbox_Talk_Id
int
Y
Foreign key references Toolbox_Talk (Id)
Competency_Id
int
Y
Foreign key references Competency (Id)
Query Design
Your query selection criteria are too complex to represent in SQL but you can use VBA to build your query in memory and then execute it like this.
Dim db As Database
Dim rs As Recordset
Dim sql As String
Dim whereClause As String
Set db = CurrentDb
Set rs = db.OpenRecordset(sql, dbOpenForwardOnly, dbReadOnly)
Do Until rs.EOF
' Process recordset
rs.MoveNext
DoEvents
Loop
rs.Close
Set rs = Nothing
The sql statement should select all employees who match the selection criteria for the talk. I assume you want each employee to appear only once, even if they match on several criteria. The sql statement looks like this.
sql = "Select E.Id, E.First_Name, E.Last_Name "
sql = sql & "From Employee E "
sql = sql & "Inner Join ("
sql = sql & "Select Distinct Id "
sql = sql & "From Employee "
sql = sql & whereClause
sql = sql & ") As Qry1 "
sql = sql & "On E.Id = Qry1.Id "
Query Selection Criteria
Given a Toolbox_Talk_Id, you can get the target gender like this.
Dim targetGender As Variant
targetGender = DLookup("Target_Gender", "Toolbox_Talk", "Id = " & Toolbox_Talk_Id)
You can get the target departments like this.
Dim targetDepartments As Collection
Set targetDepartments = New Collection
Set rs = db.OpenRecordset("Select Department_Id From Toolbox_Talk_Target_Department Where Toolbox_Talk_Id = " & Toolbox_Talk_Id, dbOpenForwardOnly, dbReadOnly)
Do Until rs.EOF
targetDepartments.Add rs!Department_Id.Value
rs.MoveNext
DoEvents
Loop
rs.Close
Set rs = Nothing
You can get the target competencies by querying the Toolbox_Talk_Target_Competency table the same way.
Given the target gender, departments, and competencies for the talk, you can now assemble the query's where clause.
If the talk target gender is not null, select only employees matching that gender.
If Not IsNull(targetGender) Then
If Len(whereClause) = 0 Then
whereClause = "WHERE "
Else
whereClause = whereClause & " AND "
End If
whereClause = whereClause & "Employee.Gender = " & Chr(34) & targetGender & Chr(34)
End If
If one or more target departments were specified, select only employees associated with those departments through the Employee_Department table.
If targetDepartments.Count > 0 Then
If Len(whereClause) = 0 Then
whereClause = "WHERE "
Else
whereClause = whereClause & " AND "
End If
If targetDepartments.Count = 1 Then
' one department
whereClause = whereClause & "EXISTS (Select 1 From Employee_Department Where Employee_Id = Employee.Id And Department_Id = " & targetDepartments(1) & ") "
Else
' two or more departments
whereClause = whereClause & "EXISTS (Select 1 From Employee_Department Where Employee_Id = Employee.Id And Department_Id In (" & targetDepartments(1)
For idx = 2 To targetDepartments.Count
whereClause = whereClause & ", " & targetDepartments(idx)
Next idx
whereClause = whereClause & ")) "
End If
End If
The end result should be a sql statement that looks something like this.
Select E.Id, E.First_Name, E.Last_Name
From Employee E
Inner Join (
Select Distinct Id
From Employee
Where Employee.Gender = "NB"
And EXISTS (Select 1 From Employee_Department Where Employee_Id = Employee.Id And Department_Id In (3, 4))
) As Qry1
On E.Id = Qry1.Id
I know this has probably been asked thousands of times before, but I seem to be having trouble finding an existing question that addresses this question in a wy I can understand.
My question in how can I access a value located in the last record of a table? For example, if this is my table:
personID personName personNumber
1 Sally PR32
2 Emily PR33
3 Joseph PR34
I want to access the value "PR34" (and then be able to manipulate it if possible). I know how to find the last record with Dmax, but I'm struggling to figure out how to find a value within it. I'm ultimately trying to take the value, parse the string down to just the numbers, and increment it by one (and then append the letters back on).
You can do this in a query as well:
UPDATE T
SET T.personNumber = "PR" & CLng(Replace([personNumber], "PR", "")) + 1
WHERE (((T.personID)=(SELECT Max(personID) FROM T)));
Where T is the name of your Table.
If you're in the DLookUp/DMax workflow, you can just use the following:
This gives you the ID, you already figured this out:
DMax("PersonID", "MyTable")
Then lookup the associated personNumber with that ID:
DLookUp("personNumber", "MyTable", "personID = " & DMax("PersonID", "MyTable"))
But if you want to manipulate it (or just be more efficient), using a recordset is the way to go:
'Create a recordset
Dim rs As Recordset
'Query the last value, get the personNumber
Set rs = CurrentDb.OpenRecordset("SELECT TOP 1 personNumber FROM MyTable ORDER BY personID DESC")
'Open it up for editing
rs.Edit
'Increment the number by 1
rs.Fields("personNumber").Value = Left(rs.Fields("personNumber").Value, 2) & CInt(Mid(rs.Fields("personNumber").Value, 3, Len(rs.Fields("personNumber").Value) - 2)) + 1
'Update the recordset
rs.Update
I have a form which is used to submit entries to a Table.
The ‘Monthly Adjustment $’ Field currently posts new table entries which works fine.
I would like to display the total balance from the Raw Data Table in the ‘Current Balance $’ field filtered based on the Company and Accrual ID that is selected by the user in the Form.
Each time the user selects a new Company and Accrual ID combination in the Form I want the ‘Current Balance $’ field to display the total $ for that Company and Accrual combination from the Raw Data Table.
To start with I have tried using a DSUM in expression builder to sum the ‘Amount $’ field in the Raw Data table, where the Accrual ID is equal to whatever value the user has selected in the Form’s ‘Accrual ID’ field. The next step would be to then add a second filter for the company selected (which I will do once I figure this first bit out). I have included the expression I am using below.
=Nz(DSum("[Amount $]","Accruals Raw Data","[Accruals Raw Data]![Accrual ID]= ' " & [Forms]![Single Accrual Entry - Form]![Accrual ID] & " ' "))
However when I select an option in the Accrual ID field in the form it does not return any results in the Current Balance $ field. It just displays a blank box.
I can get the ‘Current Balance $’ to display the total $ amount from the table using DSUM (i.e. with no filters applied) but can’t get it to do the above.
Would appreciate your help.
Many Thanks
Remove spaces if ID is text:
=Nz(DSum("[Amount $]","Accruals Raw Data","[Accrual ID]= '" & [Accrual ID] & "'"),0)
and remove quotes too if ID is numeric:
=Nz(DSum("[Amount $]","Accruals Raw Data","[Accrual ID]= " & [Accrual ID] & ""),0)
For two criteria try:
=Nz(DSum("[Amount $]","Accruals Raw Data","[Accrual ID]= '" & [Accrual ID] & "' And [Company] = '" & [Company] & "'"),0)
I have made a search form that allows the user to search within company expense reports for certain clients, projects, employees, and date ranges.
For the Date Criteria Box I have the following formula:
Between [Forms]![Search Form]![txtDateFrom] And [Forms]![Search Form]![txtDateTo]
This works fine but if I don't input any dates then no records show up, I want to change this so that all records will show up if they are left blank.
I've been able to do this for the project, client, and employee fields with the following formulas:
Like "*" & [Forms]![Search Form]![cboProject] & "*"
Like "*" & [Forms]![Search Form]![cboClient] & "*"
Like "*" & [Forms]![Search Form]![txtEmployee] & "*"
You guys probably know exactly what this means but I'll briefly explain it anyways: when I enter something in the textbox for Employee, the combo box for Project, or the combo box for Client in my search for and run the query, only the values that match what I entered appear. The Like "*" bit makes it so that if nothing is entered all the values show up.
I want to do the same for the date range but it is a bit trickier for me to do, can anyone help me with the syntax of this to make my date from and date to boxes show everything if left empty? Because right now if i leave them empty no records are shown which is a huge problem for the user side.
I've tried:
Like "*" & (Between [Forms]![Search Form]![txtDateFrom] And [Forms]![Search Form]![txtDateTo]) & "*"
But it didn't work for me and when I would input date ranges the incorrect date ranges would appear in the query.
What is the correct way to write this?
Sound like now your query returns the correct rows when both txtDateFrom and txtDateTo contain non-Null values.
But you want all rows returned when either txtDateFrom or txtDateTo is Null. In that case you can add 2 conditions to your WHERE clause:
WHERE
your_date_field Between [Forms]![Search Form]![txtDateFrom] And [Forms]![Search Form]![txtDateTo]
OR [Forms]![Search Form]![txtDateFrom] Is Null
OR [Forms]![Search Form]![txtDateTo] Is Null
Dim A As String
Dim B As String
Dim p As String
A = Nz(Forms!frmsearchInv!txtDateFrom, "1")
B = Nz(Forms!frmsearchInv!txtDateFor, "1")
If A = "1" Then
A = "0000-01-01"
End If
If B = "1" Then
B = "9999-01-01"
End If
p = "select * from orders where [orderDate] >= #" & A & "# AND [orderDate] <=#" & B & "# "
I'm new to Access and SQL so I'm having a bit of trouble with this undoubtedly simple issue.
I'm using VBA and SQL to update a table based on a few listbox selections.
One of the fields I'm updating is an "instance" field which tracks the instance number of each ID. For example, the first time ID 5 was added to the table its instance number would be 1. The second time it was added to the table its instance would be 2. So it would look like this:
ID | Date | InstanceNUM |
005 | 11/22/2013 | 1 |
005 | 11/23/2013 | 2 |
and so on. It's likely that other records would/will separate the two records in the example above.
After doing some research, it seems like DLast is the best function for this job since the last instance of the particular ID will also contain the instance number in field three. However, when I use this syntax:
Dim i As Long
Dim IDnum As Long
i = DLast("[InstanceNum]", "tbl_Data", [ID] = IDnum)
'where [InstanceNum] is the field name for the value I want to return, _
'"tbl_Data" is the table name where the value I want to return exists, _
'and [ID] is the field name where the ID exists.
I get the Run-time error '94': Invalid use of Null. My understanding of this error is that DLast couldn't find a value based on this criteria (and it can't store that result in a Long data type variable), but I know that the record exists (I've checked the table for the value and I've checked the variable for the value).
EDIT
The [ID] field is a text data type. I set the IDnum variable this way:
Dim IDnum As String
Set ctlList = Me!List7
For i = 0 To ctlList.ListCount - 1
If ctlList.Selected(i) = True Then
IDnum = ctlList.Column(0, i)
Exit For
End If
Next I
The above code loops through a listbox in a form I have and sets the IDnum variable as the ID number in the first column.
Per HansUp's suggestion, I have updated my code to this:
i = DLast("InstanceNum", "tbl_Data", "[ID] =" & IDnum)
But now I get the Run-time error '3464': Data type mismatch in criteria expression.
I'm at a loss for why this is happening. Perhaps there's an easy answer to this, but I haven't been able to find one... And maybe there's an easier way to do this? Does anyone know why this error is happening?
Since [ID] is text type, add quotes around the value of IDnum for DLast.
i = DLast("InstanceNum", "tbl_Data", "[ID] = '" & IDnum & "'")
However if the stored [ID] values include leading zeros, you must Format IDnum to include those.
i = DLast("InstanceNum", "tbl_Data", "[ID] = '" & Format(IDnum, "000") & "'")