Format detail section data based on previous / next row data.

D

Dial222

I have a report detailing examination results by gender for
college courses. I wish to change the format of the current
row based on data in the next or previous row. Eg if Girls
outperform boys then the Girls total control would be shaded /
formatted one colour, alternately if the opposite is true then
format accordingly.

I can hold values in report variables but how do i access the
previous row data if I need to format it based on the data in
the next row?

Cheers
 
A

Allen Browne

The basic idea is to:
- Use a module level variable variable to hold the value between records.
- Store the value in the Print event of the section.
- Read the value and assign the formatting in the Format event of the
section.

1. Open the report's module, and declare a variable in the General
Declarations section (top of module, with the Option statements):
Dim mvarLastValue As Variant

2. In the Open event of the report, initialize the variable:
mvarLastValue = Null

3. In the Print event of the Detail(?) section, assign the value to the
variable, e.g.:
mvarLastValue = Me.Result

4. In the Format event of the Detail section, set the formatting you want,
based on the variable, e.g.:
If Me.Result > mvarLastValue Then
Me.Result.BackColor = vbRed
Else
Me.Result.BackColor = vbBlue
End If

Notes:
- If the Result is null or the previous result is Null, thte Else block will
execute (giving the blue color in the above example).

- If the user only prints some pages from the report (e.g. only page 5), the
events will not fire for the intervening pages, so the first line printed
may not be formatted correctly.
 
D

Dial222

The basic idea is to:
- Use a module level variable variable to hold the value between
records. - Store the value in the Print event of the section.
- Read the value and assign the formatting in the Format event of the
section.

1. Open the report's module, and declare a variable in the General
Declarations section (top of module, with the Option statements):
Dim mvarLastValue As Variant

2. In the Open event of the report, initialize the variable:
mvarLastValue = Null

3. In the Print event of the Detail(?) section, assign the value to
the variable, e.g.:
mvarLastValue = Me.Result

4. In the Format event of the Detail section, set the formatting you
want, based on the variable, e.g.:
If Me.Result > mvarLastValue Then
Me.Result.BackColor = vbRed
Else
Me.Result.BackColor = vbBlue
End If

Notes:
- If the Result is null or the previous result is Null, thte Else
block will execute (giving the blue color in the above example).

- If the user only prints some pages from the report (e.g. only page
5), the events will not fire for the intervening pages, so the first
line printed may not be formatted correctly.

Cheers Allen, will give it a look over in the morrow.

Carl
 
D

Dial222

thte

Cheers Allen, will give it a look over in the morrow.

Carl

Hi allen

Go tthis working for the current row, where it is the second
row of the detail section bu tin the case where i need to
format the previous(ie first) because that value is greater I
am unable to roll back to that row for formatting. Is there
any way I can force a retreat event for a single group of
data, since every course represents a group this would allow
me access to the row I need.

Is there any way I can manipulat the report recordset to
moveprev, with a cancel on the current format event?

Cheers again
 
A

Allen Browne

No. You cannot force the report to go back to the previous record and form
it based on the current record.

You might be able to add a subquery to the query that the report is based
on, to get the value from the next row into the current record. If you want
to give it a shot, this is the kind of thing you would type into the Field
row of your query, assuming:
- a table named "MyTable",
- a primary key field named "MyID",
- the field to return is named "MyField":

SELECT First([MyField]) FROM MyTable AS Dupe
WHERE Dupe.MyID > MyTable.MyID
ORDER BY MyID;

Potential drawbacks:
- It does not work correctly if you sort or filter the report.
- It will probably slow down the report significantly.
- It may end up with a "Multi-level group by not allowed" error.
- Occassionally, one of these subqueries just crashes instead of ever
producing results.
 
G

Guest

Allen Browne said:
No. You cannot force the report to go back to the previous record and form
it based on the current record.

You might be able to add a subquery to the query that the report is based
on, to get the value from the next row into the current record. If you want
to give it a shot, this is the kind of thing you would type into the Field
row of your query, assuming:
- a table named "MyTable",
- a primary key field named "MyID",
- the field to return is named "MyField":

SELECT First([MyField]) FROM MyTable AS Dupe
WHERE Dupe.MyID > MyTable.MyID
ORDER BY MyID;

Potential drawbacks:
- It does not work correctly if you sort or filter the report.
- It will probably slow down the report significantly.
- It may end up with a "Multi-level group by not allowed" error.
- Occassionally, one of these subqueries just crashes instead of ever
producing results.

--
Allen Browne - Microsoft MVP. Perth, Western Australia.

Reply to group, rather than allenbrowne at mvps dot org.

Dial222 said:
Hi allen

Go tthis working for the current row, where it is the second
row of the detail section bu tin the case where i need to
format the previous(ie first) because that value is greater I
am unable to roll back to that row for formatting. Is there
any way I can force a retreat event for a single group of
data, since every course represents a group this would allow
me access to the row I need.

Is there any way I can manipulat the report recordset to
moveprev, with a cancel on the current format event?

Cheers again

Ykes this WAS frustrating.

I couldnt get the subquery solution to return anything. I then tried a
module level recordset but had problems keeping the set sychronised 1 row
ahead all the time.

In the end i jumped for the following solution primarily because its simple
and works, the rport isnt speedy anyway so the overhead of the recordset and
the search was acceptable in a report that will not be ran so frequently
anyway.

Thanks for your ideas all the same.

Carl
 
G

Guest

Here it is:

Option Compare Database
Option Explicit

Private rs As DAO.Recordset

Private Sub Report_Open(Cancel As Integer)
Set rs = CurrentDb.OpenRecordset(RecordSource)
End Sub

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
On Error Resume Next

rs.FindFirst "[Level] = '" & LEVEL & "' AND [Subject] = '" & SUBJECT &
"' AND [Gender] <> '" & Gender & "'"
If Pass_Rate_A > rs![Pass Rate A] Then
Pass_Rate_A.ForeColor = vbRed
Else
Pass_Rate_A.ForeColor = 0
End If

If Pass_Rate_H1 > rs![Pass Rate H1] Then
Pass_Rate_H1.ForeColor = vbRed
Else
Pass_Rate_H1.ForeColor = 0
End If

If Pass_Rate_H > rs![Pass Rate H] Then
Pass_Rate_H.ForeColor = vbRed
Else
Pass_Rate_H.ForeColor = 0
End If
End Sub


Dial222 said:
Allen Browne said:
No. You cannot force the report to go back to the previous record and form
it based on the current record.

You might be able to add a subquery to the query that the report is based
on, to get the value from the next row into the current record. If you want
to give it a shot, this is the kind of thing you would type into the Field
row of your query, assuming:
- a table named "MyTable",
- a primary key field named "MyID",
- the field to return is named "MyField":

SELECT First([MyField]) FROM MyTable AS Dupe
WHERE Dupe.MyID > MyTable.MyID
ORDER BY MyID;

Potential drawbacks:
- It does not work correctly if you sort or filter the report.
- It will probably slow down the report significantly.
- It may end up with a "Multi-level group by not allowed" error.
- Occassionally, one of these subqueries just crashes instead of ever
producing results.

--
Allen Browne - Microsoft MVP. Perth, Western Australia.

Reply to group, rather than allenbrowne at mvps dot org.

Dial222 said:
The basic idea is to:
- Use a module level variable variable to hold the value
between
records. - Store the value in the Print event of the
section.
- Read the value and assign the formatting in the Format
event of the
section.

1. Open the report's module, and declare a variable in the
General
Declarations section (top of module, with the Option
statements):
Dim mvarLastValue As Variant

2. In the Open event of the report, initialize the
variable:
mvarLastValue = Null

3. In the Print event of the Detail(?) section, assign the
value to
the variable, e.g.:
mvarLastValue = Me.Result

4. In the Format event of the Detail section, set the
formatting you
want, based on the variable, e.g.:
If Me.Result > mvarLastValue Then
Me.Result.BackColor = vbRed
Else
Me.Result.BackColor = vbBlue
End If

Notes:
- If the Result is null or the previous result is Null,
thte
Else
block will execute (giving the blue color in the above
example).

- If the user only prints some pages from the report (e.g.
only page
5), the events will not fire for the intervening pages, so
the first
line printed may not be formatted correctly.


Cheers Allen, will give it a look over in the morrow.

Carl


Hi allen

Go tthis working for the current row, where it is the second
row of the detail section bu tin the case where i need to
format the previous(ie first) because that value is greater I
am unable to roll back to that row for formatting. Is there
any way I can force a retreat event for a single group of
data, since every course represents a group this would allow
me access to the row I need.

Is there any way I can manipulat the report recordset to
moveprev, with a cancel on the current format event?

Cheers again

Ykes this WAS frustrating.

I couldnt get the subquery solution to return anything. I then tried a
module level recordset but had problems keeping the set sychronised 1 row
ahead all the time.

In the end i jumped for the following solution primarily because its simple
and works, the rport isnt speedy anyway so the overhead of the recordset and
the search was acceptable in a report that will not be ran so frequently
anyway.

Thanks for your ideas all the same.

Carl
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top