Skip to main content

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: ReportColumns set to 1
  • SubReport5: DetailColumnTraversal set to ctTopToBottom

PIPETTE — SubReport5: Report

PIPETTE — SubReport5: Report

PIPETTE — SubReport5: Detail

PIPETTE — SubReport5: Detail

In PIPETTE COLUMNS:

  • SubReport5: ReportColumns set to 4
  • SubReport5: DetailColumnTraversal set to ctLeftToRight

PIPETTE COLUMNS — SubReport5: Report

PIPETTE COLUMNS — SubReport5: Report

PIPETTE COLUMNS — SubReport5: Detail

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

Pipette cert report tree

  • SubReport2 and SubReport5 display As Found data, if any.
  • SubReport7 and SubReport6 display As Left data, if any.

SubReport2 — As Found summary

Looking at SubReport2, you can see the basic setup:

SubReport2 layout

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 — SubReport2

Event handlers — SubReport5

Event handlers — SubReport5

Event handlers — SubReport6

Event handlers — SubReport6

Event handlers — SubReport7

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.