I have a table tblCosts which i display on an msaccess front end which enables users to add new entries as well as update existing ones. The table is structured as below.
ExpenseType Month Year Cost
Hardware June 2017 $500
Software July 2017 $300
Hardware Sept 2017 $150
I have an update and insert queries which work fine when run manually.
However I am having trouble differentiating the condition when to fire the query on the form. For example, if the record exists in the table, it should run the update query, if record does not exist, it should run the insert query.
For example if someone puts in
- Hardware Sept 2017 $120 it should update the 3rd entry from 150 to 120 but if someone puts in
- Furniture Sept 2017 $350 it should recognize that Furniture is not part of the DB and run the insert query. I have the update and insert queries but need help in identifying the condition when to run them.
The Update query I'm using is:
Update tblCosts
set tblCosts.Cost=[Forms]![frmCost]![txtCost]
where tblCosts.ExpenseType = [Forms]![frmCost]![txtExpType]
and tblCosts.Month = [Forms]![frmCost]![txtMonth]
and tblCosts.Year = [Forms]![frmCost]![txtYear]
The Insert query I'm using is:
Insert into tblCosts (ExpenseType , Month, Year, Cost)
Select [Forms]![frmCost]![txtExpType] as Exp1,
[Forms]![frmCost]![txtMonth] as Exp2,
[Forms]![frmCost]![txtYear] as Exp 3,
[Forms]![frmCost]![txtCost] as Exp 4
Need code (VBA or macro) behind a form that determines which action query to run. In VBA something like:
If DCount("*", "tablename", "ExpenseType='" & Me.cbxExpense & "' AND [Month]='" & Me.tbxMonth & "' AND [Year]=" & Me.tbxYear) = 0 Then
CurrentDb.Execute "INSERT INTO tablename (Expense, [Month], [Year], Cost) VALUES ('" & Me.cbxExpense & "', '" & Me.tbxMonth & "', " & Me.tbxYear & ", " & Me.tbxCost & ")"
Else
CurrentDb.Execute "UPDATE tablename SET Cost=" & Me.tbxCost & " WHERE Expense='" & Me.cbxExpense & "' AND [Month]='" & Me.tbxMonth & ", [Year]=" & Me.tbxYear
End If
Probably also want some validation code to make sure all four controls have data before executing queries.
The real trick is figuring out what event to put code into - the Cost AfterUpdate will work as long as the other fields have data entered first, otherwise the validation will fail and user will have to re-enter cost.
Could have code that doesn't make each control available until previous value is entered.
Month and Year are reserved words and should not use reserved words as names for anything.
Would be better to save month numbers instead of month names for sorting purposes.
Why updating a value which really should be a calculated aggregation of transaction records?
I was wondering if the solution to the ticket at the following link was ever found
Pivot on multiple fields and export from Access.
I am trying to get results from an access table in the following format where: V1 (value 1) is a number and V2 (value 2) is timestamp (hh:mm:ss).
Basically the report pulls for current month so eventually there would be a day at the top for every day of the month and a corresponding Number and time value for each day.
April 1 April 2 April 3
Manager V1 V2 V1 V2 V1 V2
John Doe 4 5:43:12 1 0:56:32 2 3:15:12
It is an elapsed time. I have been looking at Allen Browne's post and I am most of the way there I think. I created two tables: 1) for V1 which is a number of dials; and 2) for V2 which is total talk time. I then used Allen Browne's method but I cannot get the format of the time to be in hh:mm:ss. It is that way in the base table but whatever I try it always seems to just show 1 digit.
TRANSFORM Sum(IIf([FldName]="DIALS",Val([DIALS].[DIALS]),
Val(Format([TALKTIME].[TT],"hh:nn:ss")))) AS TheValue
SELECT TALKTIME.Manager, DIALS.TW_Program_Code,
[DIALS]![VSE_FirstName] & " " & [DIALS]![VSE_Surname_Name] AS REP
FROM tblXtabColumns, TALKTIME
INNER JOIN DIALS
ON (TALKTIME.TW_Program_Code = DIALS.TW_Program_Code)
AND (TALKTIME.VSE_FirstName = DIALS.VSE_FirstName)
AND (TALKTIME.VSE_Surname_Name = DIALS.VSE_Surname_Name)
AND (TALKTIME.Period = DIALS.Period) AND (TALKTIME.[Manager] = DIALS.[Manager])
WHERE (((Month([TALKTIME].[Period])) = Month(Now())-1))
GROUP BY TALKTIME.Manager, DIALS.TW_Program_Code,
[DIALS]![VSE_FirstName] & " " & [DIALS]![VSE_Surname_Name]
PIVOT [DIALS].[Period] & " " & [FldName];
Is that time of day or elapsed time?
Review http://allenbrowne.com/ser-67.html#MultipleValues. Cannot have multi-line headers. The date would have to be concatenated with the field that provides the V1 and V2 header. Is there even a field that can be used to provide the "V1" and "V2" headers? If not, calculate it. One way:
SELECT *, DCount("*","Table1","Manager='" & [Manager] & "' AND ID <" & [ID])+1 AS Seq FROM Table1 WHERE Month([datefield]) = 4 AND Year([datefield])=2017;
Now use that query in CROSSTAB. Either build 2 CROSSTAB queries and join them or use Allen Browne approach. Example CROSSTAB to pivot only the "V1" data.
TRANSFORM First(Query1.Reading) AS DailyReading
SELECT Query1.Manager
FROM Query1
GROUP BY Query1.Manager
PIVOT Format([ReadDate],"mmm d") & " : " & [Seq] & "Reading";
I am somewhat new to MS Access/SQL and StackOverflow, so bear with me. I have a problem that I can't seem to figure out. I had posted this before, but got no responses, and editing my original post did not help.
I have quantity and distance data for assets for each week. Not all weeks have Quantity or distances (some just have 1 or the other). Here is a sample of the data for one asset(put in CSV):
Asset,Week,Qty,Dist,Actual_Dist
2153,1,,125,
2153,2,,65,
2153,3,50.1,118,
2153,4,,123,
2153,5,96.6,91,
2153,6,,103,
2153,7,,120,
2153,8,,106,
2153,9,100.6,,
2153,13,96,,
2153,14,,102,
2153,15,,40,
2153,18,84.82,,
2153,21,97.8,,
2153,25,96.7,,
2153,28,31.27,63,
2153,29,77.5,,
What I want to be able to do, is take a SUM of the "DIST" field until the row has a corresponding "QTY" field value, and this would be calculated in the "Actual_Dist" field.
Looking at my example, Weeks 1 and 2 have no Qty values, however in Week 3, Qty is 50.1 and I would want the "Actual_Dist" calculated as the sum of "Dist" from Weeks 1-3 inclusive. So essentially, Row 3's "Actual_Dist" would be SUM(125+65+118).
Right now I see 3 cases:
Case 1: as above, if no Qty, but has a Dist, then sum the distances until the next Qty value.
Case 2: If Qty exists, but no Dist, then disregard
Case 3: If Qty has a value, and Dist has a value, and Qty has previous values before (ie., Week 28), then "Actual_Dist" = Dist
So I was thinking of doing a select switch to cover the two main cases (1 & 3):
Select Asset, Week, Qty, Dist, Switch (Qty like 'NULL' AND Dist <> 'NULL', SUM(Dist) AS Actual_Dist, Switch (Qty <> 'NULL AND Dist <> 'NULL', DIST) AS Actual_Dist
**Not sure if my Switch is done right, but I think you get the picture?
Now my issues comes in the sum function above. How do I get it sum properly and take the distance values before a qty value is present (Case 2)? I apologize if the formatting or presentation of sample data is poor. Just signed up. I will likely have to clarify some points, so let me know and I will clarify as necessary.
It is also important to note that this is just one asset, and there are many. For the sum function above, I need it to be able to sum the records above for ANY given number of records.
Hope someone can help.
Thanks
EDIT: #Cha had posted the following:
SELECT Data.Asset, Data.Week, Data.Qty, Data.Dist, Switch(Not IsNull([Qty]) And Not IsNull([Dist]),[Dist], Not IsNull([Qty]),Nz(DSum("Dist","Data","Asset=" & CStr([Asset]) & " And Week <= " & CStr([Week]) & " And Week > " & CStr(Nz(DMin("Week","Data","Asset=" & CStr([Asset]) & " And Week < " & CStr([Week]) & " And Not IsNULL(Qty)"),0))),0)) AS Actual_Dist FROM Data;
This code gave me errors due to data mismatch, so I changed all the data types to "Number" and modified the code as follows:
SELECT Data.Asset, Data.Week, Data.Qty, Data.Dist, Switch(Not IsNull([Qty]),Nz(DSum("Dist","[Data]","Asset=" & [Asset] & " And Week <= " & [Week] & " And Week > " & Nz(DMin("Week","[Data]","Asset=" & [Asset] & " And Week < " & [Week] & " And Not IsNULL([Qty])"),0)),0)) AS Actual_Dist
FROM Data;
The above code now satisfies Case 1, but only satisfies it for Row 3 and 5. This Case does not satisfy Rows 9 and 13, and it needs to apply there too. I believe the issue with those rows is that the "Dist" is NULL.
There is another issue, Case 1 and Case 3 overwrite eachother occasionally (when both Qty and Dist are not NULL. Is there a way to create 1 switch to run Case 1, and another (with the same code) to apply Case 3 but not Case 1?
Any help would be much appreciated!
Thanks
If you can use VBA, then try this:
Public Sub GetActual_Dist()
Const TABLE_NAME As String = "tblAssets"
Dim sTemp_Dist As Single
With CurrentDb.OpenRecordset("SELECT * FROM [tblAssets] WHERE NOT ([Qty] is not Null AND [Dist] is Null);")
If .EOF And .BOF Then
MsgBox "No data"
Exit Sub
End If
Do Until .EOF
If ![Qty] Is Null Then
sTemp_Dist = sTemp_Dist + ![Dist]
Else
.Edit
![Actual_Dist] = sTemp_Dist
.Update
sTemp_Dist = 0
End If
.MoveNext
Loop
End With
End Sub
Change the TABLE_NAME to the one in your database.
I'm using SQL to code a combobox which will display names from one table (students), minus any students in my other table (Bookings) who have made a booking on a specific day.
In my "students" table I have one field, "Name". In my "Bookings" table I have two fields, "Name" and "Day".
Here is the code I am using to tell what is going in my combobox;
Combobox.RowSource = "SELECT Name FROM Students" & _
"LEFT OUTER JOIN Bookings " & _
"ON Students.Name = Bookings.Name" & _
"WHERE Bookings.Day = 'Monday';"
To my knowledge this should display all of the names in Students.Name minus any names in Bookings which are on the day Monday. But it's just opening an error message "Syntax error in FROM clause."
Thanks in advance for any advice.
Udate:
I found out how to make it work. Instead of a "Left Outer Join" you have to use a "Not In" clause.
Here' s the code I used.
combobox.RowSource = "SELECT Name FROM Students " & _
"WHERE Name " & _
"NOT IN (SELECT Bookings.Name FROM Bookings WHERE Bookings.Day = ""Monday"") "
Assume the following table:
ID COMPANY SUBSIDIARY NR_LIVES INSURANCE_LINE FACTOR_CALC
1 COMPANY_X SUB_1 860 LIFE YES
2 COMPANY_X SUB_1 860 DISABILITY YES
3 COMPANY_X SUB_1 860 MEDICAL YES
4 COMPANY_X SUB_2 46 LIFE YES
5 COMPANY_X SUB_2 689 MEDICAL YES
6 COMPANY_X SUB_3 852 LIFE YES
I need an SQL string that returns to me the value 2401.
This is done by making the sum of the highest NR_Of_Lives per subsidiary where FACTOR_CALC = Yes.
I probably would know how to do it loading everything in a recordset and then using VBA, but I would appreciate it if it were possible in one SQL command.
UPDATE:
The current query:
sSQL_Select = "SELECT SUM(NR_LIVES) FROM (SELECT SUBSIDIARY, MAX(NR_LIVES) FROM T_WILMA WHERE PARENT=" & lParent & " AND ACC_YEAR=" & lAcc_Year & _
" AND FACTOR_CALCULATION=TRUE GROUP BY SUBSIDIARY);"
throws an error: Too few parameters, expected 1.
The subquery on its own works as expected.
Thanks to replies so far, but I haven't succeeded to make it work so far.
You can determine the maximum per subsidiary in a subquery. The outer query can then sum the maximums.
select sum(MaxLives)
from (
select company
, subsidiary
, max(nr_lives) as MaxLives
from YourTable
where factor_calc = 'yes'
group by
company
, subsidiary
) as SubQueryAlias
I'll suggest you include some aliasing to see whether that helps unconfuse the db engine.
sSQL_Select = "SELECT SUM(sub.MaxOfNR_LIVES) AS NR_LIVES" & vbcrlf & _
"FROM (" & vbCrLf & _
"SELECT SUBSIDIARY, MAX(NR_LIVES) AS MaxOfNR_LIVES" & vbCrLf & _
"FROM T_WILMA WHERE PARENT=" & lParent & _
" AND ACC_YEAR=" & lAcc_Year & _
" AND FACTOR_CALCULATION=TRUE GROUP BY SUBSIDIARY) AS sub;"
Debug.Print sSQL_Select
SELECT SUM(NR_LIVES)
from(
SELECT SUBSIDIARY,MAX(NR_LIVES) as NR_LIVES
from <Table>
where FACTOR_CALC='YES'
group by SUBSIDIARY)a
You need to let the system know which NR_LIVES it's trying to add up. On your table (and taking out the extra stuff in the WHERE that is not in your example, this returns 2401
SELECT Sum(MAXNR_LIVES) AS Expr1
FROM (SELECT SUBSIDIARY, MAX(NR_LIVES) AS MAXNR_LIVES FROM T_WILMA
WHERE FACTOR_CALC=TRUE GROUP BY SUBSIDIARY);