Explanation of Pipette Certs
As mentioned in Configuration Elements of the Pipette Module, there are two example pipette certificates provided: PIPETTE and PIPETTE COLUMNS. They're identical except for a couple of small differences.
Differences between PIPETTE and PIPETTE COLUMNS
SubReport5 and SubReport6 are used to display the individual samples (As Found and As Left, respectively).
In PIPETTE:
SubReport5: Report—Columnsset to 1SubReport5: Detail—ColumnTraversalset toctTopToBottom

PIPETTE — SubReport5: Report

PIPETTE — SubReport5: Detail
In PIPETTE COLUMNS:
SubReport5: Report—Columnsset to 4SubReport5: Detail—ColumnTraversalset toctLeftToRight

PIPETTE COLUMNS — SubReport5: Report

PIPETTE COLUMNS — SubReport5: Detail
Report-tree overview
For the rest of this discussion, the PIPETTE cert template is used. In the report tree, Main, SubReport1, SubReport3, and SubReport4 correspond to Certificates, Events, Masters, and EventProcedures respectively. They're fairly standard, so they aren't reviewed here.

Pipette cert report tree
SubReport2andSubReport5display As Found data, if any.SubReport7andSubReport6display As Left data, if any.
SubReport2 — As Found summary
Looking at SubReport2, you can see the basic setup:

SubReport2 layout
Since all the environmental data for As Found is stored in all the test points, the Title contains it. Each group of four test points that represent a given channel/sample shares the same text in the Group column, so a grouping is set up on that field, with "a test point" displaying in the Group Footer. The Calc tab logic assembles the data appropriately.
For the PIPETTE cert, SubReport5 overlaps the data so the first sample data appears in line with the summary data. In PIPETTE COLUMNS, it appears beneath the summary data.
Calc-tab logic
The rest of what makes this special lives in the Calc tab. For reference, the Event Handlers for each SubReport:

Event handlers — SubReport2

Event handlers — SubReport5

Event handlers — SubReport6

Event handlers — SubReport7
SubReport2 handlers
TitleBeforeGenerate
procedure TitleBeforeGenerate;
begin
if UncertaintyOn = '1' then
begin
Label61.visible := true;
Label70.Visible := true;
end
else
begin
Label61.visible := false;
Label70.Visible := false;
end;
end;
The only purpose of TitleBeforeGenerate is to hide the Uncertainty column if Uncertainty isn't registered. In clients since version 11, Uncertainty is always registered.
TitleBeforePrint
procedure TitleBeforePrint;
begin
if '0' = ReturnFromSQL('SELECT COUNT(*) FROM CALPNTSEXTRA WHERE EVENT_NUM='+IntToStr(Events['Event Number'])+' AND FIELD_NAME LIKE ''AS FOUND%''') then
begin
Title.Visible := false;
end
else
begin
Title.Visible := true;
end;
end;
TitleBeforePrint determines whether there's any As Found data, and shows or hides the title accordingly.
GroupHeaderBand1BeforePrint
procedure GroupHeaderBand1BeforePrint;
begin
Label46.Caption := '';
Label47.Caption := '';
Label48.Caption := '';
Label49.Caption := '';
Label50.Caption := '';
Label51.Caption := '';
Label67.Caption := '';
Label70.Caption := '';
Label67.Caption := 'Passed';
if CalibrationTestPoints['As Found Num 4'] <> 0 then
Label100.Caption := FormatFloat('0.00000',CalibrationTestPoints['As Found Num 1']/CalibrationTestPoints['As Found Num 4'])
else
Label100.Caption := '';
end;
GroupHeaderBand1BeforePrint resets the data in the footer (so we don't carry lagging data) and calculates the raw Z-factor in Label100.
DetailBeforePrint
The detail handler is long enough to break into sections.
procedure DetailBeforePrint;
var
I, I2, I3, iNumResolution, iResResolution, iUncResolution : Integer;
sRes, sRes2, sResUnc, sDummy : String;
begin
iNumResolution := StrToIntDef(CalibrationTestPoints['Res.'], 6);
iResResolution := StrToIntDef(CalibrationTestPoints['Result Res.'], 0);
iUncResolution := StrToIntDef(CalibrationTestPoints['Uncertainty Res.'], 6);
sRes := '#######0';
sRes2 := '#######0';
sResUnc := '#######0';
If ((iNumResolution >= 0) and (iNumResolution <= 12)) then
i2 := iNumResolution else i2 := 6;
If i2 > 0 then
begin
sRes := sRes + '.';
for i := 0 to i2 - 1 do
sRes := sRes + '0';
end;
If ((iResResolution > 0) and (iResResolution <= 12)) then
begin
i3 := iResResolution;
sRes2 := sRes2 + '.';
for i := 0 to i3 - 1 do
sRes2 := sRes2 + '0';
end else sRes2 := sRes;
If ((iUncResolution > 0) and (iUncResolution <= 12)) then
begin
i3 := iUncResolution;
sResUnc := sResUnc + '.';
for i := 0 to i3 - 1 do
sResUnc := sResUnc + '0';
end else sResUnc := sRes;
The first section creates the resolution-format strings used in FormatFloat calls below. This is how the cert displays data with the same resolution as the results grid.
if CalibrationTestPoints['Description']=(CalibrationTestPoints['Group']+' mean') then
begin
Label46.Caption := FormatFloat(sRes,CalibrationTestPoints['As Found']);
Label70.Caption := FormatFloat(sResUnc,CalibrationTestPoints['Uncertainty']);
end
else if CalibrationTestPoints['Description']=(CalibrationTestPoints['Group']+' SD') then
begin
Label47.Caption := FormatFloat(sRes,CalibrationTestPoints['As Found']);
end
else if CalibrationTestPoints['Description']=(CalibrationTestPoints['Group']+' acc') then
begin
Label48.Caption := FormatFloat(sRes,CalibrationTestPoints['As Found']);
Label49.Caption := FormatFloat(sRes,CalibrationTestPoints['Tolerance +']);
Label59.Caption := 'Accuracy '+CalibrationTestPoints['Unit'];
Label104.Caption := FormatFloat(sRes,CalibrationTestPoints['As Found Num 5']);
end
else if CalibrationTestPoints['Description']=(CalibrationTestPoints['Group']+' prec') then
begin
Label50.Caption := FormatFloat(sRes,CalibrationTestPoints['As Found']);
Label51.Caption := FormatFloat(sRes,CalibrationTestPoints['Tolerance +']);
Label65.Caption := 'Precision '+CalibrationTestPoints['Unit'];
Label105.Caption := FormatFloat(sRes,CalibrationTestPoints['As Found Num 5']);
end;
if (CalibrationTestPoints['Verdict']='A') or (CalibrationTestPoints['Verdict']='F') then
Label67.Caption := 'Failed';
end;
This section uses Group and Description to identify which piece of data is being processed. For each section, the As Found, Tolerance, and unit are set for the Group Footer. The Verdict is also checked to see if the As Found results failed.
This is where the bulk of the logic lives.
GroupFooterBand1BeforePrint
procedure GroupFooterBand1BeforePrint;
begin
if '0' = ReturnFromSQL('SELECT COUNT(*) FROM CALPNTSEXTRA WHERE EVENT_NUM='+IntToStr(Events['Event Number'])+' AND SEQ='+CalibrationTestPoints['#']+' AND FIELD_NAME LIKE ''AS FOUND%''') then
begin
GroupFooterBand1.Visible := false;
end
else
begin
GroupFooterBand1.Visible := true;
end;
end;
GroupFooterBand1BeforePrint shows or hides the Group Footer based on whether there's any As Found data for the current "test point". This suppresses any test point you skipped collecting data for.
SubReport5 handlers
SubReport5 has only one Event Handler:
procedure DetailBeforePrint;
var
I, I2, iNumResolution : Integer;
sRes, sDummy, sValue, sUnits : String;
begin
iNumResolution := StrToIntDef(CalibrationTestPoints['Res.'], 6);
sRes := '#######0';
If ((iNumResolution >= 0) and (iNumResolution <= 12)) then
i2 := iNumResolution else i2 := 6;
If i2 > 0 then
begin
sRes := sRes + '.';
for i := 0 to i2 - 1 do
sRes := sRes + '0';
end;
DBText43.DisplayFormat := sRes;
sDummy := CalibrationTestPointsExtra['Field Value (Text)'];
sValue := copy(sDummy, 1, pos(' ', sDummy) - 1);
sUnits := copy(sDummy, pos(' ', sDummy) + 1, length(sDummy));
Label96.Caption := FormatFloat(sRes, StrToFloat(sValue)) + ' ' + sUnits;
if copy(CalibrationTestPointsExtra['Field Name'], 1, 8) = 'AS FOUND' then
begin
Label52.Caption := IntToStr(StrToInt(copy(CalibrationTestPointsExtra['Field Name'], 10, 10000)));
Detail.visible := true;
end
else
begin
Label52.Caption := IntToStr(StrToInt(copy(CalibrationTestPointsExtra['Field Name'], 9, 10000)));
Detail.visible := false;
end;
end;
The handler calculates the resolution string, applies that resolution to the mass and volume values, and controls visibility based on whether the data is an As Found sample.
SubReport6 and SubReport7
The custom rules for SubReport7 and SubReport6 are basically the same as the SubReport2 / SubReport5 rules above, except they've been tweaked to correspond to As Left rather than As Found.