Explicação sobre os certificados de pipetas
Conforme mencionado em Elementos de configuração do módulo Pipette, são fornecidos dois exemplos de certificados Pipette: PIPETTE e PIPETTE COLUMNS. Os dois são idênticos, com exceção de algumas pequenas diferenças.
Começando pelas diferenças: o SubReport5 e o SubReport6 são utilizados para apresentar as amostras individuais, respetivamente.
No PIPETTE, o SubReport5: Report tem a opção Columns definida como 1, e o SubReport5: Detail tem a opção ColumnTraversal definida como ctTopToBottom.


Em contrapartida, nas PIPETTE COLUMNS, o SubReport5: Report tem a opção Columns definida para 4, e o SubReport5: Detail tem a opção ColumnTraversal definida para ctLeftToRight.


No restante desta discussão, será utilizado o modelo de certificado PIPETTE. Ao analisar a árvore de relatórios, os relatórios «Principal», «SubRelatório1», «SubRelatório3» e «SubRelatório4» relativos a Certificados, Eventos, Mestres e Procedimentos de Eventos são bastante comuns. Consequentemente, não serão analisados.

O SubReport2 e o SubReport5 são utilizados para apresentar os dados «tal como encontrados», caso existam. O SubReport7 e o SubReport6 são utilizados para apresentar os dados «Pendentes», caso existam.
Ao consultar o SubReport2, pode ver a configuração básica.

Uma vez que todos os dados ambientais relativos ao estado «tal como encontrado» estão armazenados em todos os pontos de teste, o título reflete isso. Cada grupo de quatro pontos de teste que representam um determinado canal/amostra tem o mesmo texto na coluna «Grupo», pelo que é definido um agrupamento nesse campo, com a menção «um ponto de teste» a aparecer no rodapé do grupo. A lógica das pastas do Calc é utilizada para organizar os dados de forma adequada. No certificado PIPETTE, o SubReport5 sobrepõe os dados de forma a que os dados da primeira amostra apareçam alinhados com os dados do resumo. Em PIPETTE COLUMNS, aparece abaixo dos dados resumidos.
O resto do que torna isto especial encontra-se no separador «Cálculo». A título de referência, os manipuladores de eventos para cada sub-relatório são apresentados abaixo:




Analisando-os por ordem de execução, começaremos pelo SubReport2.
procedimento TitleBeforeGenerate;
começar
se UncertaintyOn = '1', então
começar
Label61.visible := true;
Label70.Visible := true;
fim
ou
começar
Label61.visible := false;
Label70.Visible := false;
fim;
fim;
O único objetivo do TitleBeforeGenerate é ocultar a coluna «Incerteza» caso a «Incerteza» não esteja registada. Nos clientes a partir da versão 11, a incerteza é sempre registada.
procedimento TitleBeforePrint;
começar
se '0' = ReturnFromSQL('SELECT COUNT(*) FROM CALPNTSEXTRA WHERE EVENT_NUM='+IntToStr(Events['Event Number'])+' AND FIELD_NAME LIKE ''AS FOUND%''') então
começar
Title.Visible := false;
fim
ou
começar
Title.Visible := true;
fim;
fim;
O TitleBeforePrint é utilizado para determinar se existem dados «As Found» e para ocultar ou mostrar o título em conformidade.
procedimento GroupHeaderBand1BeforePrint;
começar
Label46.Caption := '';
Label47.Caption := '';
Label48.Caption := '';
Label49.Caption := '';
Label50.Caption := '';
Label51.Caption := '';
Label67.Caption := '';
Label70.Caption := '';
Label67.Caption := 'Aprovado';
se CalibrationTestPoints['As Found Num 4'] <> 0, então
Label100.Caption := FormatFloat('0.00000', CalibrationTestPoints['Valor medido n.º 1'] / CalibrationTestPoints['Valor medido n.º 4'])
ou
Label100.Caption := '';
fim;
GroupHeaderBand1BeforePrint é utilizado para reiniciar os dados no rodapé. Isto garante que não temos dados desatualizados. Também calcula o fator Z bruto (Label100).
No caso do DetailBeforePrint, vou dividir tudo em partes.
procedimento DetailBeforePrint;
Var
I, I2, I3, iNumResolution, iResResolution, iUncResolution : Inteiro ;
sRes, sRes2, sResUnc, sDummy : String ;
começar
iNumResolution := StrToIntDef(CalibrationTestPoints['Res.'], 6);
iResResolution := StrToIntDef(CalibrationTestPoints['Result Res.'], 0);
iUncResolution := StrToIntDef(CalibrationTestPoints['Uncertainty Res.'], 6);
sRes := '#######0';
sRes2 := '#######0';
sResUnc := '#######0';
Se ((iNumResolution >= 0) e
(iNumResolution <=12) então
i2 := iNumResolution; caso contrário, i2 := 6;
Se i2>0, então
começar
sRes := sRes + '.';
para i := 0 até i2-1, faça
começar
sRes := sRes + '0';
fim;
fim;
Se ((iResResolution > 0) e
(iResResolution <=12) então
começar
i3 := iResResolution;
sRes2 := sRes2 + '.';
para i := 0 até i3-1, faça
começar
sRes2 := sRes2 + '0';
fim;
fim; caso contrário, sRes2 := sRes;
Se ((iUncResolution > 0) e
(iUncResolution <=12) então
começar
i3 := iUncResolution;
sResUnc := sResUnc + '.';
para i := 0 até i3-1, faça
começar
sResUnc := sResUnc + '0';
fim;
fim; caso contrário, sResUnc := sRes;
A secção acima tem apenas um objetivo: criar as cadeias de caracteres para definir a resolução utilizadas nas chamadas FormatFloat abaixo. É assim que os dados do certificado são apresentados com a mesma resolução que na grelha de resultados.
se CalibrationTestPoints['Description'] = (CalibrationTestPoints['Group'] + 'média') então
começar
Label46.Caption := FormatFloat(sRes, CalibrationTestPoints['As Found']);
Label70.Caption := FormatFloat(sResUnc, CalibrationTestPoints['Uncertainty']);
fim
caso contrário, se CalibrationTestPoints['Description'] = (CalibrationTestPoints['Group'] + ' SD'), então
começar
Label47.Caption := FormatFloat(sRes, CalibrationTestPoints['As Found']);
fim
caso contrário, se CalibrationTestPoints['Description'] = (CalibrationTestPoints['Group'] + ' acc'), então
começar
Label48.Caption := FormatFloat(sRes, CalibrationTestPoints['As Found']);
Label49.Caption := FormatFloat(sRes, CalibrationTestPoints['Tolerância +']);
Label59.Caption := 'Precisão '+CalibrationTestPoints['Unit'];
Label104.Caption := FormatFloat(sRes, CalibrationTestPoints['As Found Num 5']);
fim
caso contrário, se CalibrationTestPoints['Description'] = (CalibrationTestPoints['Group'] + ' prec'), então
começar
Label50.Caption := FormatFloat(sRes, CalibrationTestPoints['As Found']);
Label51.Caption := FormatFloat(sRes, CalibrationTestPoints['Tolerância +']);
Label65.Caption := 'Precisão '+CalibrationTestPoints['Unit'];
Label105.Caption := FormatFloat(sRes, CalibrationTestPoints['As Found Num 5']);
fim;
se (CalibrationTestPoints['Verdict']='A') ou (CalibrationTestPoints['Verdict']='F') então
Label67.Caption := 'Falha';
fim;
Esta secção analisa os campos «Grupo» e «Descrição» e utiliza-os para determinar qual o dado que está a ser analisado (as linhas «if CalibrationTestPoints['Description']=(CalibrationTestPoints['Group']+»). Para cada secção, os valores «Conforme medido», «Tolerância» e «Unidade» são definidos no rodapé do grupo. Verifica também se os resultados do «As Found» falharam ou não.
Como pode ver, é aqui que se encontra a maior parte da lógica.
procedimento GroupFooterBand1BeforePrint;
começar
se '0' = ReturnFromSQL('SELECT COUNT(*) FROM CALPNTSEXTRA WHERE EVENT_NUM='+IntToStr(Events['Event Number'])+' AND SEQ='+CalibrationTestPoints['#']+' AND FIELD_NAME LIKE ''AS FOUND%''') então
começar
GroupFooterBand1.Visible := false;
fim
ou
começar
GroupFooterBand1.Visible := true;
fim;
fim;
GroupFooterBand1BeforePrint apenas oculta ou mostra o rodapé do grupo, dependendo da existência ou não de dados tal como encontrados para o «ponto de teste» atual. Isto irá ocultar todos os dados cuja recolha tenha sido ignorada.
Passando ao SubReport5, existe apenas um manipulador de eventos.
procedimento DetailBeforePrint;
Var
I, I2, iNumResolution : Inteiro ;
sRes, sDummy, sValue, sUnits : String ;
começar
iNumResolution := StrToIntDef(CalibrationTestPoints['Res.'], 6);
sRes := '#######0';
Se ((iNumResolution >= 0) e
(iNumResolution <=12) então
i2 := iNumResolution; caso contrário, i2 := 6;
Se i2>0, então
começar
sRes := sRes + '.';
para i := 0 até i2-1, faça
começar
sRes := sRes + '0';
fim;
fim;
DBText43.DisplayFormat := sRes;
sDummy := CalibrationTestPointsExtra['Valor de campo (Texto)'];
sValue := copy(sDummy, 1, pos(' ', sDummy) - 1);
sUnits := copy(sDummy, pos(' ', sDummy) + 1, length(sDummy));
Label96.Caption := FormatFloat(sRes, StrToFloat(sValue)) + ' ' + sUnits;
se copy(CalibrationTestPointsExtra['Nome do campo'],1,8) = 'CONFORME ENCONTRADO' então
começar
Label52.Caption := inttostr(strtoint(copy(CalibrationTestPointsExtra['Field Name'],10,10000)));
Detail.visible := true;
fim
ou
começar
Label52.Caption := inttostr(strtoint(copy(CalibrationTestPointsExtra['Field Name'],9,10000)));
Detail.visible := false;
fim;
fim;
O único objetivo desta lógica é calcular a sequência de resolução, aplicar essa resolução à massa e ao volume e controlar a visibilidade consoante se trate ou não de uma amostra «tal como encontrada».
As regras personalizadas para o SubReport7 e o SubReport6 são basicamente as mesmas, exceto que foram ajustadas para corresponder à opção «As Left» em vez de «As Found».