A family of Microsoft relational database management systems designed for ease of use.
Hi Emily
I'm so glad you got it working :-)
I got an email notification a few minutes ago to say you were having problems, but I couldn't find the message. I guess you solved the problem and deleted that message but, just for curiosity, what was the solution?
I'm very happy to give you a step-by-step explanation of how it works, so I'll repost my original message with comments interspersed in bold italics:
Create a normal subreport, based on ActiveMilestonesQuery, and add the subreport twice to the main report, side-by-side. Set LinkMasterFields and LinkChildFields for both to "Docket". Name the left-hand subreport control "MilestonesSubreportColumn1" and the right-hand one "MilestonesSubreportColumn2" (just as you have them named currently).
Nothing especially tricky about this – you have simply placed the same two linked subreports side-by-side on the main report. If we do nothing else then the two will display identically.
Now, make the following tweaks to your subreport:
- Add a textbox to the report header named txtRecordCount, with this ControlSource:
=Count(*)
This textbox will contain a count of all the records displayed in this instance of the subreport (after the link fields filter has been applied)
- Add a textbox to the detail section named txtRecordNum, with this ControlSource:
=1
and set its RunningSum property to "Over All"
This textbox simply contains the constant value of 1. However, since we have set the RunningSum property, each record will add the value to the previous value, so we get 1, 2, 3 ... This is an old trick to get a running record number in a report.
(Both these textboxes can be made invisible, as you wish)
They will still perform their functions even if we can’t see them!
- Add these two lines to the Declarations section of the subform module:
Public p_ColumnNum As Integer
Public p_ColumnCount As Integer
Because these variables are declared as Public, they become exposed as custom properties of the report (hence the “p_” prefix) and we can set their values from code in other modules. Because they are declared “As Integer”, their values will be initialised to zero.
- Add the following code to the Format event procedure for the Detail section:
The Format event occurs when a report section is being constructed and placed on the page prior to the final rendering. You can use it to show or hide certain controls or set their values, to draw lines or load images, or to stop this instance of the section from printing entirely. To stop the section from printing, you set the Cancel argument to True (or any non-zero value). Each line of code is explained below:
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Declare a variable for the number of records per column
Dim RecordsPerColumn As Long
If our property variables have not been set up, or are invalid, then exit and do nothing special
If p_ColumnCount <= 1 Or p_ColumnNum = 0 Or p_ColumnNum > p_ColumnCount Then Exit Sub
Calculate the records per column by dividint the total number of records by the column count
RecordsPerColumn = (txtRecordCount \ p_ColumnCount)
If the columns don’t divide exactly (there is a remainder) then add one to the records per column
If (txtRecordCount Mod p_ColumnCount) <> 0 Then RecordsPerColumn = RecordsPerColumn + 1
The tricky bit :-)
We subtract one from the record number in the textbox (so the numbering starts from zero) and divide without remainder by the number of records per column. This will give us 0 for the first column of records, 1 for the second, and so on. If this value is NOT equal to one less than the column number for this subreport, then don’t print the record.
If ((txtRecordNum - 1) \ RecordsPerColumn) <> p_ColumnNum - 1 Then Cancel = True
End Sub
Now, open your main report (ActiveItemsReport) and you should see two columns, each listing ALL the milestones for each docket.
We haven’t set the subreports’ custom properties yet, so the code above will not run.
Now, the icing on the cake :-)
In the Format event procedure of the report header section of ActiveItemsReport, add these four lines of code:
Now set the custom properties. This must be executed after the subreports are loaded, but before they start to format any data. The best place is in the Format event of the main report’s header section.
Refer to the properties by Me.<subreport control name>.Report.<variable name>
Private Sub ReportHeader_Format(Cancel As Integer, FormatCount As Integer)
Me.MilestonesSubreportColumn1.Report.p_ColumnCount = 2
Me.MilestonesSubreportColumn2.Report.p_ColumnCount = 2
Me.MilestonesSubreportColumn1.Report.p_ColumnNum = 1
Me.MilestonesSubreportColumn2.Report.p_ColumnNum = 2
End Sub
Now you should get the first half of the milestones in the left-hand subreport, and the others on the right.
This is completely general and reusable, and uses no special queries or other constructs. Also, if you ever wanted to split the report into three columns instead of two, all you need to do is copy and paste a subreport, rename it, and add two more lines to your ReportHeader_Format procedure.
I hope you followed that, and that anyone else who comes along might find it useful.
Good luck! :-)
Graham