Fill Field When All Checkboxes Toggled Access 2010 - ms-access

I have an expenditures subform in Access 2010 that lists the predicted costs associated with the project for each year. Most projects only have one year, but some have more than one. Each cost has a Final checkbox next to it that should be checked when the amount is confirmed, ie. at the end of each year.
It basically looks something like this:
Year | Cost | Final
--------+-----------+--------------------
2017 | $100 | [checked box]
2018 | $200 | [unchecked box]
| | [unchecked box]
I have another field outside the table, FinalCost, that adds up everything in the Cost field. Right now, it fills in the amount from any year which has a checked Final box. That should only be filled when all the Final boxes are checked.
Ex. Right now, it should show nothing even though Final for 2017 is checked. When 2018 is checked, it should show $300. Instead, it shows $100 even though there's still an empty checkbox.
This is the code for this form.
Private Sub Form_AfterUpdate()
Dim rs1, rs2 As Recordset
Dim sql, sql2 As String
sql = "SELECT Sum(Amount) as Final From Expenditures " & _
"Where ProjNo = '" + Me.ProjNo + "' And Final = True Group by ProjNo"
sql2 = "SELECT FinalExpenditure From ActivityCash " & _
"Where ProjNo = '" + Me.ProjNo + "'"
Set rs1 = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dpinconsistent)
Set rs2 = CurrentDb.OpenRecordset(sql2, dbOpenDynaset, dpinconsistent)
If rs1.RecordCount > 0 Then
If rs2.RecordCount > 0 Then
Do While Not rs2.EOF
rs2.Edit
rs2!FinalExpenditure = rs1!Final
rs2.Update
rs2.MoveNext
Loop
End If
End If
rs2.Close
rs1.Close
Set rs1 = Nothing
Set rs2 = Nothing
End Sub
What would be the best way to go about doing this?
EDIT: When the last box is checked, a new row is automatically added with an untoggled checkbox but no information.

Replace the statement beginning with sql = ... with this:
sql = "SELECT SUM(e1.Amount) AS Final " & _
" FROM Expenditures AS e1 " & _
" WHERE NOT EXISTS (SELECT 'x' FROM Expenditures e2 WHERE e2.Final=0 AND e1.ProjNo = e2.ProjNo) " & _
" AND e1.ProjNo = '" & Me.ProjNo & "'"
This query will return data only if there are all expeditures for the project marked as final. As you check for rs1.RecordCount > 0 there will be no update if this query returns no records.

So, before sql, I would verify that all records have True in your Final field.
To do that, let's just return a COUNT() of (any) records that have Final = False, and we can then decide to do what we want.
So, something like,
Dim Test as Integer
test = DCount("*", "YourTableName", "Final = False AND ProjNo = " & Me.ProjNo &"")
If test > 0 Then
'Don't fill the box
Else
'Fill the box, everything is True
'Read through your recordsets or whatever else you need to do
End If
To use a query, we essentially need to replicate the Dcount() functionality.
To do this, we need another Recordset variable, and we need to check the value of the Count() field from our query.
Create a query that mimicks this:
SELECT COUNT(*) As CountTest
FROM YourTable
HAVING Final = False
AND ProjNo = whateverprojectnumberyou'reusing
Save it, and remember that query's name.
Much like the DCount(), we need to make this "check" determine the route of your code.
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("YourQuery'sNameHere")
If rst!CountTest > 0 Then
'They are not all Checked (aka True)
Else
'Supply the value to the FinalCost
End If
Set rst = Nothing

Change this:
sql = "SELECT Sum(Amount) as Final From Expenditures " & _
"Where ProjNo = '" + Me.ProjNo + "' And Final = True Group by ProjNo"
For this:
"SELECT SUM(Amount) - SUM(IIF(Final,1,0)*Amount) as YetToConfirm, SUM(Amount) as Confirmed From Expenditures " & _
"Where ProjNo = '" + Me.ProjNo + "' Group by ProjNo"
rs1 will return two values, the total value if all costs were confirmed in the rs1!Confirmed, and the value yet to confirm in rs1!YetToConfirm
Then here:
Do While Not rs2.EOF
rs2.Edit
rs2!FinalExpenditure = rs1!Final
rs2.Update
rs2.MoveNext
Loop
change it to:
Do While Not rs2.EOF
rs2.Edit
rs2!FinalExpenditure = Iif(rs1!YetToConfirm = 0, rs1!Confirmed, 0)
rs2.Update
rs2.MoveNext
Loop

One way to process this would be check using a subquery whether last year(verified using a dmax function) in each project has been checked in the final column, if this is true, get your sum of checked amounts, else dont calculate the sum.
I have modified your sql string to include this and I tested it against your given example to confirm its showing a sum of $300 or nothing.
SQL = ""
SQL = SQL & " SELECT Sum(Amount) as Final From Expenditures "
SQL = SQL & " Where ProjNo = '" & Me.ProjNo & "' And Final = True "
SQL = SQL & " And (SELECT Expenditures.Final FROM Expenditures where year = ( "
SQL = SQL & " DMax('Year','Expenditures','ProjNo= " & Chr(34) & Me.ProjNo & Chr(34) & "'))) = true "
SQL = SQL & " Group by ProjNo "

Related

Dynamic variable holder with counter

I have two txt boxes and two combo boxes on a form. There is also a subform linked to the temptable that I want to have rebuilt/filter each time one of the controls is changed (using after update on each control to trigger the following sub)
I receive Run-time error '91: Object variable or with block variable not set on line Items(i) = Thing
I am not sure using " (i) " works with MS Access 365 or I am dimensioning incorrectly?
Thank you.
Private Sub Lookupstuff()
Dim i As Integer
Dim Items(1 To 4) As Object
sql = "DELETE * FROM tblTemp"
CurrentDb.Execute sql
i = 0
FilterArray = Array(Me.txtNew, Me.cmbS, Me.cmbP, Me.txtSl)
For Each Thing In FilterArray
If Not IsNull(Thing) Then
i = i + 1
Items(i) = Thing <--Error is here. Items(i) is empty.
End If
Next
If i = 0 Then
Forms!frmNew.Requery
Forms!frmNew.Refresh
End If
If i = 1 Then
Filter = Items1
End If
If i = 2 Then
Filter = Items1 & " AND " & Items2
End If
If i = 3 Then
Filter = Items1 & " AND " & Items2 & " AND " & Items3
End If
If i = 4 Then
Filter = Items1 & " AND " & Items2 & " AND " & Items3 & " AND " & Items4
End If
sql = "INSERT INTO tblTemp SELECT * FROM tblQ"
If Not IsNull(Filter) Then
sql = sql & " WHERE " & Filter
End If
CurrentDb.Execute sql
Forms!frmNew.Requery
Forms!frmNew.Refresh
End Sub
Since you are assigning a reference to object in the array, you must use Set, i.e.:
Set Items(i) = Thing
Also, presumably each reference to Items1, Items2 etc. should actually be Items(1), Items(2) in order to access the objects referenced at these indices of the array.

VB6 and MS Access, save time and date if user is true

--
I badly need your help guys. I'm stuck with these problems for a almost a month . I need to get the time and date if the user tap on the scanner.
Private Sub Command1_Click()
Adodc1.RecordSource = "select * from tbl_login where user = '" + Text1.text + "'"
Adodc1.Refresh
If Adodc1.Recordset.EOF Then
MsgBox "Login Failed", vbCritical + vbOKOnly, "Error"
Else
Adodc1.RecordSource = "update tbl_login set dte = '" & Label1.Caption & "' set tme '" & Label2.Caption & "' where user = '" + Text1.text + "'"
MsgBox "Login Successful!", vbExclamation + vbOKOnly, "Welcome"
Text1.text = ""
Text2.text = ""
End If
End Sub
Private Sub Timer1_Timer()
Label1.Caption = Format(Now, "dddd mmmm dd, yyyy")
Label2.Caption = Format(Now, "hh: mm: ss ampm")
End Sub
It shows the Login Successful, but it doesn't record the time and date of the user.
Help please, help me fix this.
Simply insert date and time:
Adodc1.RecordSource = "update tbl_login set dte = Date(), tme = Time() where user = '" & Text1.text & "'"
Firstly, I would suggest always using the ampersand operator (&) for string concatenation, not the addition operator (+).
Assuming that your fields dte and tme are datetime fields, then the reason that your UPDATE query fails is because you are not providing the date & time data in an appropriate format required for SQL.
However, rather than using concatenation to insert the data into your UPDATE query, I would instead suggest parameterising the query and passing the date, time, and username to the parameters, for example:
With CurrentDb.CreateQueryDef("", "update tbl_login set tbl_login.dte = #dte, tbl_login.tme = #tme where tbl_login.user = #usr")
.Parameters(0) = Date
.Parameters(1) = Now
.Parameters(2) = Text1.Text
.Execute
End With
You can find out more about parameterised queries from this excellent answer.

How to accommodate insertion of new line of code

I have the following code below which builds/creates a description based on the Value field (where contains data) in sequential order. For example, I have a table which has the following fields...
Item
Classification
Attribute Name
Value
UOM
Status
What I'm trying to do is insert a line of code that will only build the description from the Value field (where contains data) where the Status field = Active. The Status field info is either "Active" Or "Foreign". Currently, if the Status field shows "Foreign" the code will also build the description for these records which I just learned should not be included.
Any help would be greatly appreciated! Again, below is the code...
Sub SD()
DoCmd.SetWarnings False
Dim db As DAO.Database
Dim rsMara, rs_cou As DAO.Recordset
Dim rs, rs2, x As DAO.Recordset
Dim SD, strAttribute, strValue, sdvalue As String
Dim seq, d, count1 As Integer
Set db = CurrentDb
db.Execute ("UPDATE Item_Template SET Description = '', Long_Description = '';")
Set rsMara = db.OpenRecordset("select * from [Item_Template] order by [Item]")
While Not rsMara.EOF
If rsMara.Fields("Classification") & "" <> "" Then
SD = UCase(rsMara.Fields("Classification")) & ": "
seq = 1
Set rs = db.OpenRecordset("select * from All_Item_Attributes where [Item] = '" & rsMara.Fields("Item") & "' and [Value] & '' <> '' order by [Item],[Sequence (Cls Attribute Mapping)]")
While Not rs.EOF
If (rs.Fields("UOM") Like "IN*" Or rs.Fields("UOM") Like "O*") Then
SD = SD & rs.Fields("Value") & " " & UCase(rs.Fields("UOM")) & ", "
Else
SD = SD & rs.Fields("Value") & " " & UCase(rs.Fields("UOM")) & ", "
End If
rs.MoveNext
Wend
SD = Trim(SD)
rsMara.Edit
SD = Trim(Mid(SD, 1, Len(SD) - 1))
rsMara.Fields("Description") = Trim(SD)
rsMara.Fields("Description") = Replace(rsMara.Fields("Description"), " ,", ", ")
rsMara.Fields("Description") = Replace(rsMara.Fields("Description"), " ", " ")
rsMara.Update
End If
DoEvents
rsMara.MoveNext
Wend
End Sub
You don't say which table the field Status is in.
You have two lines of code opening recordsets so it will be one of these lines of code:
Set rsMara = db.OpenRecordset("select * from [Item_Template] WHERE Status='Active' order by [Item]")
or
Set rs = db.OpenRecordset("select * from All_Item_Attributes where [Item] = '" & rsMara.Fields("Item") & "' and [Value] & '' <> '' AND Status='Active' order by [Item],[Sequence (Cls Attribute Mapping)]")
Basically adding Status='Active' into the WHERE clause. This won't work if your Status field is a lookup field in which case you'd need to use the Foreign Key value that links it to your Status type table. Status=1 for example.

Why doesn't this DAO recordset query return any results?

I am working on an Access 2007 database and I have set up a DAO recordset query, however, it is not returning any results. It does not throw up any errors, just no results. Me.ProID is a text field, it includes letters and numbers. I think it has something to do with the text field, maybe the placement of quotations.
Dim contractSQL As String
Dim contractDB As DAO.Database
Dim contractRS As DAO.Recordset
contractSQL = "SELECT Top 1 ContractName, ItemDescription, Price FROM ContractPricing WHERE AccountNo = " & Me.Parent.[AccntNumber] & " AND PartNo = " & """ & Me.ProdID & """ & " ORDER BY Price Asc"
Set contractDB = CurrentDb
Set contractRS = contractDB.OpenRecordset(contractSQL)
Debug.Print contractRS.RecordCount
That string concatenation is likely wrong. " & """ & Me.ProdID & """ & " should almost certainly be '" & Me.ProdID & "'
I don't know if you're referring to this:
contractSQL = "SELECT Top 1 ContractName, ItemDescription, Price FROM ContractPricing WHERE AccountNo = " & Me.Parent.[AccntNumber] & " AND PartNo = " & Me.ProdID & " ORDER BY Price Asc"
I'm not sure if this would help you. I'm also new to this. But hopefully it will.

Access 2010 - Check data in recordset before adding new record

I'm new to Access so bear with me here.
I have a form that allows me to add new data to a table
ID | Name | City | Zip Code
1 | John | Newark | 12340
2 | Alex | Boston | 98760
So on and so forth...
Before proceeding to add a new record with the above data fields, I need to create a check that will look at the table to determine if the combinations of Name, City and Zip Code already exist. If they do, I want it to Exit Sub; Else continue with the rest of the macro.
I've been looking to build this using some form of the OpenRecordset command, but I'm not sure where to begin. Can someone point me in the right direction? Thanks!
I just wrote this code to recreate your situation and it worked fine. You just need to rename your columns and your table in the query.
Dim strSQL As String
Dim qdf As QueryDef
'if these columns are not text change to approriate type
strSQL = "PARAMETERS [NameToCheck] Text(255),[CityToCheck] Text(255),[Zip] Text(255); "
'change table name and column names here
strSQL = strSQL & "SELECT Count(*) FROM address " _
& "WHERE FName = [NameToCheck] AND City = [CityToCheck] AND ZipCode = [Zip];"
Set qdf = CurrentDb.CreateQueryDef("", strSQL)
qdf("NameToCheck") = txtName.Value 'change to that textfield on form
qdf("CityToCheck") = txtCity.Value 'change to that textfield on form
qdf("Zip") = txtZipCode.Value 'change to that textfield on form
If qdf.OpenRecordset(dbOpenSnapshot)(0) > 0 Then
MsgBox "This record is already in the database"
Else
'Insert statement goes here.
End If
If you want to use recordsets as you requested then you would need to use a SQL statement to select all or use it to find something by name.
Dim myR as Recordset
Dim strSQL as String
'run a SQL statement to select a record with the same info
strSQL = "SELECT [Name], [City], [Zip Code] FROM table_name_here " & _
"WHERE [Name] = '" & form_control_name & "' " & _
"AND [City] = '" & form_control_city & "' " & _
"AND [Zip Code] = '" & form_control_zip & "'"
'set your recordset to the SQL statment
Set myR = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
'if your count is greater than 0, then you'll have a duplicate
If myR.RecordCount > 0 then
MsgBox "This already exists"
Else
MsgBox "All clear"
End if
Set myR = Nothing