Advertisement

03.09.2008 at 09:34PM PDT, ID: 23227551
[x]
Attachment Details

ADP calculated column and form footer sum that update when a row is updated

Asked by E-Squared in Microsoft ADP, Microsoft Access Database, MS SQL Server

Tags: Microsoft, Access, 2002, ADP (Access Data Project using a SQL Server 2000 back end)

Requirement: Display the sum of a calculated column in the footer of continuous form and keep the column and the sum updated when rows are updated. The recordsource can be a stored procedure (preferred), selection from a view, or any other method that will work. Back-end server is M SSQL 2000, though it will in a matter of months be upgraded to SQL 2005

Issue: Access ADP manages updates and refreshes behind the scenes. Because it queries the "unique table" directly to refresh updated values and skips the stored procedure entirely, it does not update the calculated column and thus does not update the sum expression. A requery of the entire recordset is not acceptable because then row selection and form scroll position are lost and it generates an additional hit on the database.

Setup:
See the attached code to create a SQL Server database, two tables, and a stored procedure. See the attached file for a working ADP connected with integrated security to "(local)" which demonstrates the problem (rename .txt to .zip and extract). Or use the instructions in the attached code to reproduce the ADP.

To reproduce the problem:
Open ExampleForm. See that the sum of the queried rows is displayed in the footer. If you change Number1 or Number2, the CalcTotal field is not updated and the sum is not updated.

Don't worry about the given form and subform's ability to add new records or other functionality, as I have that covered.

Please provide a solution that doesn't store the calculation in the database (or give good reasoning why this denormalization would be acceptable and how data integrity would be maintained). A calculated field is okay, but performance also matters: a calculated field that uses a function will be very slow, whereas a query that does the same calculation inline will be faster. Keep in mind potential reporting scenarios with where clauses using the calculated value.

Ideas:
- Create a WITH VIEW_METADATA view and make the SP select from this: in tests this failed because the recordset was not updatable, even with SCHEMABINDING and a clustered primary key index on the view. Maybe I messed this up.
- Calculated column in table. I am trying to avoid a function which would be required in order to pick up the multiplier value from the main table.
- Database redesign: suggest a design that reproduces the conceptual layout that doesn't suffer from the same problems.

I am open to better ways to link parent and child subforms, but a SQL profiler session to see what Access really does behind the scenes is necessary to help gauge the performance and elegance of the result.Start Free Trial
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
CREATE DATABASE Example
GO
USE Example
GO
CREATE TABLE ExampleMain (
	ExampleMainID int NOT NULL identity(1,1) CONSTRAINT PK_ExampleMain PRIMARY KEY CLUSTERED,
	Multiplier decimal(20,5) NOT NULL CONSTRAINT DF_Example_Main DEFAULT (0)
)
 
CREATE TABLE ExampleDetail (
	ExampleDetailID int identity(1,1) CONSTRAINT PK_ExampleDetail PRIMARY KEY NONCLUSTERED,
	ExampleMainID int NOT NULL CONSTRAINT FK_ExampleExampleDetail_ExampleMainID FOREIGN KEY REFERENCES ExampleMain(ExampleMainID),
	CalcID int NOT NULL CONSTRAINT CK_ExampleDetail_CalcID_Valid CHECK (CalcID BETWEEN 1 AND 5),
	Number1 decimal(20,5) NOT NULL CONSTRAINT DF_Example_Number1 DEFAULT (0),
	Number2 decimal(20,5) NOT NULL CONSTRAINT DF_Example_Number2 DEFAULT (0)
)
CREATE UNIQUE CLUSTERED INDEX IX_ExampleDetail ON ExampleDetail (ExampleMainID, CalcID)
 
INSERT ExampleMain VALUES (2)
INSERT ExampleMain VALUES (3)
INSERT ExampleMain VALUES (4)
 
INSERT ExampleDetail
SELECT
	M.ExampleMainID,
	C.CalcID,
	Power(2, CalcID),
	Power(3, CalcID)
FROM
	ExampleMain M
	CROSS JOIN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5) C (CalcID)
GO
CREATE PROCEDURE ExampleP @ExampleMainID int, @ExampleDetailID int = NULL
AS
SELECT
	M.ExampleMainID,
	D.CalcID,
	D.ExampleDetailID,
	M.Multiplier,
	D.Number1,
	D.Number2,
	CalcTotal = M.Multiplier * D.Number1 * D.Number2
FROM
	ExampleMain M
	INNER JOIN ExampleDetail D ON M.ExampleMainID = D.ExampleMainID
WHERE
	M.ExampleMainID = @ExampleMainID
	OR D.ExampleDetailID = @ExampleDetailID
GO
/*
Now use the provided ADP, and set its connection properties to the database you just created.
It is set up to use (local) and integrated security.
 
If you want or need to make the ADP yourself:
 
1. Open MS Access 2002 and select New Project (Existing Data). Provide connection information to the database you just created.
2. Create a form and set the following form properties:
Record Source: EXEC ExampleP 0
Unique Table: ExampleDetail
Resync Command: EXEC ExampleP NULL, ?
Default View: Continuous Forms
Navigation Buttons: No
Scroll Bars: Vertical Only
3. Drop all available fields from the field list onto the form, creating text boxes.
4. Lock and slightly darken the background of the ExampleDetailID, Multiplier, and CalcTotal text boxes to indicate they cannot be edited.
5. Add the prefix "txt" to all text boxes.
6. Right-click on the detail bar and choose "Form Header/Footer" to add these. Add a locked and slightly darkened textbox in the form footer called txtSumCalcTotal with Control Source: =Sum([CalcTotal])
7. Arrange the controls suitable for a continuous form (I put the labels in the header and the textboxes in a single row).
8. Save the form as ExampleSubform
9. Create a new form and set its properties:
Record Source: SELECT * FROM ExampleMain
10. Drop all fields onto the form from the Field List.
11. Make the ExampleMainID textbox locked and slightly darken the background.
12. Drop a subform control and set properties:
Source Object : ExampleSubform
Name: ExampleSubform
Record Selectors: No
Do not link the subform and the main form with the wizard (though built-in Access linking can be part of your solution if necessary).
13. Set form properties:
On Current: [Event Procedure]
and click the "..." button to access the VB code for this event and set it as follows:
Private Sub Form_Current()
   Me.ExampleSubform.Form.RecordSource = "EXEC ExampleP " & CStr(Nz(Me.ExampleMainID, 0))
End Sub
14. Set form properties:
After Update: [Event Procedure]
Set the code behind this event to:
Private Sub Form_AfterUpdate()
   Me.ExampleSubform.Form.Requery
End Sub
15. Save the form as ExampleForm.
16. Proceed as in the given experts-exchange question.
*/
GO
-- When you're done, close the ADP and then clean up (make sure to close all open connections to the database):
USE Master
GO
DROP DATABASE Example
Attachments:
 
ADP file demonstrating the problem (rename to .zip and extract) or use attached instructions to recreate the file.
 
 
Loading Advertisement...
 
[+][-]03.11.2008 at 03:55PM PDT, ID: 21101304

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]03.11.2008 at 04:30PM PDT, ID: 21101501

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 7-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]03.11.2008 at 09:24PM PDT, ID: 21103034

View this solution now by starting your 7-day free trial. Setting up your free trial is quick, easy, and secure. We will return you to this solution, unlocked, when you're done.

 

About this solution

Zones: Microsoft ADP, Microsoft Access Database, MS SQL Server
Tags: Microsoft, Access, 2002, ADP (Access Data Project using a SQL Server 2000 back end)
Sign Up Now!
Solution Provided By: vadimrapp1
Participating Experts: 2
Solution Grade: A
 
 
[+][-]03.12.2008 at 08:18AM PDT, ID: 21106905

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 7-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]03.12.2008 at 08:56AM PDT, ID: 21107358

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
 
Loading Advertisement...
20080716-EE-VQP-32 / EE_QW_2_20070628