MS Access report fails to total correctly - sql

I have a report in MS Access 2010 that had been working fine for a while. I had to make updates to the report to allow the run-time selection of one or more 'reasons' that would be included on the report.
My initial process dynamically built them into the report filter at run-time, but my totals came out wrong. I then dynamically altered the QueryDef.SQL (adding the final two AND statements in the code below) that the report is based on, but they still came out wrong. I then discovered (did I mention that I'm not the one who originally wrote the report) that the total field is based on another query entirely.
Quick background before everyone questions the sanity: We're calculating an audit score. Each audit is checked on several questions, most of which receive a Yes/No (pass/fail) answer. Some questions may receive a 'Total Fail' which results in a zero score for the entire audit, not just for the particular question. The individual audit score is percentage right OR zero if there is a 'Total Fail'. The overall score on the report is the average of the individual audit scores.
So, with that background, I would hope that there is enough information to make sense of the queries.
This is the query (qryRptAtt) that the report is based on:
SELECT vwAttorneys.CurrentAttorneyName AS PayeeID, tblAuditAtt.AttAudit_ID,
vwAttorneys.CurrentAttorneyName AS Attorney_Name, tblAuditAtt.Loan,
tblAuditAtt_A.A_ID, tblAuditAtt_Q.Question, tblAuditAtt_A.Answer,
tblAuditAtt_A.Comment, tblAuditAtt.EndDate, tblAuditAtt.Status,
tblAuditAttLoans.State, tblAuditAtt.Reason
FROM tblAuditAttLoans RIGHT JOIN ((vwAttorneys INNER JOIN tblAuditAtt ON
vwAttorneys.PayeeID = tblAuditAtt.PayeeID) INNER JOIN (tblAuditAtt_Q
INNER JOIN tblAuditAtt_A ON tblAuditAtt_Q.A_ID = tblAuditAtt_A.A_ID) ON
tblAuditAtt.AttAudit_ID = tblAuditAtt_A.AttAudit_ID) ON
tblAuditAttLoans.LoanNumber = tblAuditAtt.Loan
WHERE (((tblAuditAtt_A.Answer)<>"NA")
And ((tblAuditAtt.EndDate) Between Forms!frmRptAtt!txtFrom And Forms!frmRptAtt!txtTo)
And ((tblAuditAtt.Status)="Submitted"))
AND tblAuditAtt.Reason in ('reason1', 'Reason 2', 'Reason 3', 'Reason 4', 'Reason 5')
AND tblAuditAtt.PayeeID = '<removed for privacy>'
ORDER BY vwAttorneys.Attorney_Name, tblAuditAttLoans.State, tblAuditAtt.Loan, tblAuditAtt_A.A_ID
(All the horrendous parenthesis come from Access building the query from the visual designer. Yes, there are some columns selected twice - I will clean that up if possible.)
This query is correctly giving me all the detail information I need on the report. In the report itself, the overall score field in the footer section of the report has Control Source set to =IIf([txtA_TF]=0,DAvg("[Score]","[qryRptAttAggregateAudits]"),0). This is the one that is giving me the wrong answer. qryRptAttAggregateAudits is as follows:
SELECT qryRptAtt.PayeeID, qryRptAtt.AttAudit_ID, qryRptAtt.Loan,
Sum(IIf(Answer="Yes",1,0)) AS Yes,
Sum(IIf(Answer="No",1,0)) AS [No],
Sum(IIf(Answer="DC",1,0)) AS DC,
Sum(IIf(Answer="TF",1,0)) AS TF,
IIf(DC>0,0,IIf(TF>0,0,Sum(IIf(Answer="Yes",1,0))/(Sum(IIf(Answer="Yes",1,0))+Sum(IIf(Answer="No",1,0))))) AS Score
FROM qryRptAtt
WHERE (((qryRptAtt.PayeeID)=[Forms]![frmRptAtt]![cmbAttorney]))
AND qryRptAtt.Reason in ('Reason1', 'Reason2', 'Reason3', 'Reason4', 'Reason5')
AND qryRptAtt.PayeeID = '<removed for privacy>'
GROUP BY qryRptAtt.PayeeID, qryRptAtt.AttAudit_ID, qryRptAtt.Loan
The report total query selects from the report detail query qryRptAtt. In both queries, Forms!frmRptAtt is open and has had the appropriate fields filled with valid data.
I've tried the total query with both (((qryRptAtt.PayeeID)=[Forms]![frmRptAtt]![cmbAttorney])) and AND qryRptAtt.PayeeID = '<removed for privacy>' in the WHERE clause, with only one and with only the other (They both resolve to the same criteria, so it's really just redundant code & will be cleaned up once I get the major issue resolved).
I've exported the report to Excel and manually calculated the score there, and the report is showing a total that is about 0.6% off.
If anyone was able to follow this, do you have any suggestions?

It turns out that there was an oddity in the report definition.
The 2nd query was being used to generate rows of data that were being totaled with DAvg() in the report. The DAvg() function worked on a query result before I made my changes, but didn't seem to want to work with the query after I made the changes.
I modified the 2nd query to build a temporary table, then modified the DAvg() call in the report to reference the table instead of the query, and that seems to have it working.

Related

Is there a way to filter which Form records are shown with Query results?

For background, I have 2 tables here. One is a JobTicket table with all of our required production info, and the other is a ScheduledItems table with all of our job ticket data, plus the dates we are supposed to run that Job. I am having no trouble getting all of the necessary data over there, my issue comes when I would like to do the opposite. I have created a Query to search for the Sales Order Number from both tables, and then set the criteria for Scheduled Items to null so it will only show the unscheduled Jobs. Query works great, shows me all of the jobs that have not been Scheduled yet, but for the life of me I cannot figure out the best way to go about filtering my Form JobTicket to show only those unscheduled Jobs. I don't want to just give my coworker those Query results and tell him to search Jobs one by one; some days we can get 25+ Jobs with 10+ Line Items, so the extreme end we would be looking at around 250 manual searches a day.
If anyone has dealt with this in the past and has any sort of jumping off point or recommendation for my methodology I would very sincerely appreciate it. Thanks all
the acess query
SELECT
Qry_JobTicket.Sales_Order_Number,
Qry_ScheduledItems.Sales_Order_Number
FROM Qry_JobTicket
LEFT JOIN Qry_ScheduledItems
ON Qry_JobTicket.Sales_Order_Number = Qry_ScheduledItems.Sales_Order_Number
WHERE (((Qry_ScheduledItems.Sales_Order_Number) Is Null));
Okay I have figured out how to go about it, all though I am sure it's not the best in the way of design principles. Here goes:
After creating the Query (SQL shown above, Qry_UnscheduledList) to find all of the Un-Scheduled Jobs, I created another query that brought in my Qry_JobTicket and my Qry_UnscheduledList. I inner joined on Sales Order Number, so we only see the Jobs yet to be scheduled, and brought in every field from Qry_JobTicket. Once that was done, I then created a button on my form and inserted the code below to change the Form's Record Source, similarly to as #HansUp suggested with the FormFilter property.
Private Sub Btn_ToBeScheduled_Click()
DoCmd.OpenForm "Frm_JobTicket"
With Forms("Frm_JobTicket")
If .RecordSource = "Qry_JobTicket" Then
.RecordSource = "Qry_ToBeScheduled"
ElseIf .RecordSource = "Qry_ToBeScheduled" Then
.RecordSource = "Qry_JobTicket"
End If
End With
End Sub
Now as I said earlier this may not be the best designing, but I was doing research for about an hour and couldn't find very many people who needed to filter their FormA records based off of corresponding records that don't exist in their FormB.

A solution for a join to get all the data that is not in the main query based on a field from the main query

So I have the below case in crystal reports
Main Report which has a query that shows the batch details of an invoice
Sub-report which shows the details of the batches included in the main report but are not included in that document. So for example
Invoice A has 10 items all with the same batch (this will show in the main report)
Invoice B, C, an D has 3 more items in the same batch (so total 13 items for that batch in 4 different documents) and the 3 items that are not in document A is what appears in the sub-report.
Now it's easy to achieve that in Crystal Reports because you can link sub-reports with fields to filter directly without linking the queries, however since CR is not a database engine the filtration is super slow and to solve that I need a solution in an SQL query:
I tried converting it to UNION ALL so it's
Main Report
Union ALL
Sub Report
The problem is I am unable to replicate the sub-report case since the grouping needs to be by Document then Batch and the 3 items from the sub-report are not on the same document so they are not grouped by the same dimension now and that ruins the report.
I know it's not logical but after trying all the solutions that came to my mind I thought maybe someone more experienced would have a different opinion, basically for every invoice in the main report I need to show all items that are not in that specific invoice so right now I have no links because the Item is not the same, the document is not the same, and only the batch is the same but that's a many to many link.
EDIT: For simplicity let's say this is the main query
SELECT
T0.DocumentNumber,
T2.ItemCode,
T2.ItemName,
T3.BatchNumber,
T3.Quantity
FROM DocHeader T0
JOIN DocRows T1 ON T0.DocumentEntry = T1.DocumentEntry
JOIN ItemMaster T2 ON T1.ItemCode = T2.ItemCode
JOIN BatchTransaction T3 ON T1.Document Entry = T3.DocumentEntry and
T3.DocumentType = T1.DocumentType and T3.DocumentLine = T1.DocumentLine
The report is grouped by Document Number, so what i need is the same query but for every other document number that is not in the main query joined on the main query. The 2 problems are 1. They can leave the document number parameter blank and select all the documents in the table so this process needs to happen for each document seperately. 2. the document number in the sub query will never be the same so the grouping is an issue because the report needs to be grouped on the main query document number.
It would help if you wrote out your main query and some of the secondary queries you've tried, but assuming I understand your issue correctly, you should be able to just create an additional JOIN on the Batches table. This will have your SQL query list off ALL the Item rows for the Batch, then you can try to use conditional formatting and/or grouping in Crystal to to show/hide the rows as needed.
Alternatively, using the query described above, you may be able to use the linked Invoice Numbers you're now getting from your main report query to drive your Sub-Report, as opposed to going by the Batch # -- this may result in better performance.
EDIT: Based on your comment and update, I think the right approach here is to create a Stored Procedure. Doing a single query is probably not going to work, I took a crack at it and it's not worth the hassle.
Using a Stored Procedure you can create a table variable in memory, add the main invoice records to the table, then add the records for the secondary Invoices linked by the Batch number. Use some kind of column/flag in your table that indicates whether it's a 'Main Invoice' record or not, and use this flag to drive the Crystal display logic for how you want to show the main vs secondary/linked invoices.
It's doable!

Access Query / Report - Error: This expression is typed incorrectly or it is too complex to be evaluated on calculated field

So after reading 9 posts about the same error on Stack I didn't really find an answer to my problem, hence me posting this question.
So in my Access I have a query that inherits from several other queries. With this query a User can get information with a certain Date range. This data is put in a report where the records are shown and internally (in the report) some calculation is done of the record fields.
The problem is, when A user wants data until the date 2016-4-22 the report shows up fine. Though when the User wants data until the date 2016-4-30 (from day 23 and on it just gives the same errors) the report tries to load but after a while fails with the error:
This expression is typed incorrectly or it is too complex to be evaluated
So this made me test a few things which I have list down below:
First I thought the Query itself or the given WHERE clause were corrupted / not good so I put the Report recordsource with the WHERE clause in a separate test query and executed it. This all worked fine (no errors).
This made me believe that perhaps a single record was corrupted so I went to the date from which on it gave the error (2016-4-23) and checked this record. Nothing weird was found.
Then I thought it could be some field on the report that was giving the error so I removed several fields and after removing a few Calculated Sum(total) fields the error disappeared.
So I created another query and did the Sum in this query as well based on my created test query - this gave the same error.
After these tests I was pretty sure that perhaps the calculated data was just too much to calculate. I also copied the queries data into Excel and did a SUM of the field there as well. The outcome was roughly 15 million. I can hardly imagine that a number of 15 million is too complex to be evaluated...
Besides that, I also tried to create another SUM query on the specific field but with the date based on 2016-4-22 (so the one that initially DID work). But now it also givers the error on this date... So there goes my theory..
Anyone has a clue what is going wrong?
The 'base' query in question is:
SELECT qryOHW6Verdicht.*
, CStr([nummer] & "." & [qryOHW6Verdicht].[positie]) AS NummerPos
, [ArbeidTot]+[MateriaalTot]+[UitbesteedTot] AS Kosten
, CDbl([AangenomenprijsPositie])+CDbl([MeerwerkPrijsPositie]) AS OpdrachtSom
, IIf([nacalculatie],[Kosten],IIf(IsNull([kostenverwacht]),(100-[otwinstpercentage])/100*[opdrachtsom],[kostenverwacht])) AS VerwachteKosten
, IIf([nacalculatie],[kosten],IIf([Kosten]<[VerwachteKosten],[Opdrachtsom]-[VerwachteKosten],[Opdrachtsom]-[Kosten])) AS VerwachteWinst
, [Kosten]-[VerkoopTot] AS WaardeOHW
, DatePart("yyyy",[gereeddatum]) AS GereedJaar
, [OtOverhead]*[VerkoopTot]/100 AS Overhead
, qryVCBoekingenVerdicht.KostenVerwacht
FROM qryOHW6Verdicht LEFT JOIN qryVCBoekingenVerdicht
ON (qryOHW6Verdicht.[Positie] = qryVCBoekingenVerdicht.[Positie])
AND (qryOHW6Verdicht.[Nummer] = qryVCBoekingenVerdicht.[Offerte])
The report opens with the previous query as recordsource and with this WHERE filter:
1=1 AND (Gereeddatum is null OR Gereeddatum>=#2016-4-30# )
AND Project IS NULL AND NOT (WaardeOHW=0 AND Kosten=0) AND GarantieOrder=0
In the report I got a few Calculated fields and one of them that goes wrong is:
=Sum([OpdrachtSom])

VBA, SQL, Queries

I have an access form with few controls on it, like start-date, end-date, move_type, mover_name etc, when user fills this field n clicks on query command button, a select query is run and it fetches records from various tables depending upon the criteria mentioned by the user.
Later the same records are exported to excel file and a report is generated for user.
Now I need to do more with this, my select query has a field "quoted-price", depending upon the price quoted the records need to be sorted out.
EX : if quoted_price < 500 then it is a "domestic apartment1", if quoted-price is >500 And <1500 it is "domestic Apartment1" etc.
Now I need to do more with this, my select query has a field "quoted-price", depending upon the price quoted the records need to be sorted out.
EX : if quoted_price < 500 then it is a "domestic apartment1", if quoted-price is >500 And <1500 it is "domestic Apartment1" etc. and when all the records generated through select query are searched on this criteria, the records need to be grouped accordingly. Later the count for individual category is multiplied by a unit value and total charge is calculated.
I tried building many queries to do this and tables to refer to value but of no use. Any help will be much appreciated.
are you looking to create a new field depending on the condition? That may be step one of what you are trying to do, If so that is pretty easy. See here: http://allenbrowne.com/casu-14.html

simple average calculation in Access XP report

i have a database used at work for evaluating calls, the database is somewhat dated and originally created on Access XP. Once evaluated these calls are given a score out of 5 which is entered along with other data (such as date, employee name, etc) on a form. I have the reports set up so they generate when you enter the employee name and then the start of a date period and the end of a date period, the report will then generate and show the entries made between those 2 dates. i am trying to include a section on the report which shows an average of the call score for the employee for the period chosen. I understand this may be pretty simple but i'm struggling! cheers, Kris
If you want to work out group calculations on reports, you can either put them in the group header/footer, or report header/footer (for calculations over the whole report).
In this case, placing a textbox with something like =AVG([CallScore]) as the control source in the Report Footer should work.
This page should explain more about using aggregate functions in reports: http://office.microsoft.com/en-gb/access-help/summing-in-reports-HA001122444.aspx