Medidas calculadas
Para criar uma medida calculada, precisamos configurar o tipo de agregado como "Cálculo" ou "Cálculo (detalhe)" no editor de medidas.
Os dois tipos de medida calculada são:
- Cálculo baseado em outros valores de medida ("Cálculo")
Medidas que são calculadas depois que outras medidas tenham sido criadas, usando o processamento padrão de medidas. A função de cálculo tem acesso a outros valores de medida, valores de dimensão e valores de medida prévios. A caixa de seleção "Calcular todas as células" ativa o cálculo para todas as células, inclusive as células "vazias" (células que não possuem fileiras correspondentes nos dados de origem).
- Cálculo baseado nos dados de origem ("Cálculo (detalhe)")
Medidas que são calculadas com base nos dados de origem e criadas junto com medidas padrão. A função de cálculo tem acesso à fileira atual de dados de origem e aos valores de dimensão. A caixa de seleção "Calcular todas as células" é desabilitada para este tipo de cálculo.
A utilização de ambos os tipos de medida calculada requer escrever uma nova função de cálculo ou escolher uma função existente no campo "Função". Clicar duas vezes no campo "Função" abre o editor de medidas. Se o campo "Função" estiver vazio, então uma função nova é criada automaticamente.
O campo "Ordem" ordena o cálculo.
A janela do editor de medidas possui três áreas:
- a barra de ferramentas
- o editor de texto com realce de sintaxe
- o modo de exibição de árvore com as variáveis, funções e classes disponíveis
A barra de ferramentas contém as ações para verificar a sintaxe, salvar alterações, cancelar alterações e escolher a linguagem de programação.
O editor de texto é usado para compor e editar o código da função (um 'script'). O código da função é um programa escrito na linguagem escolhida que é interpretado pelo FastScript no momento do cálculo. O código da função deve retornar um valor através da variável "Resutado".
O script tem acesso aos seguintes elementos da grade:
- lista de dimensões - Dimensions : TDimensions;
- lista de medidas - Measures : TMeasures;
- lista de campos - SliceFields : TfcxSliceFields;
- variável de serviço - CustomObject: TfcxCustomObject.
A variável de serviço habilita a leitura e gravação de dados do usuário para uma célula de medida específica. Por exemplo, um ponteiro de uso futuro pode ser atribuído a qualquer objeto criado na função de cálculo. Cada célula possui sua própria variável de serviço. A variável CustomObject somente pode ser usada em medidas criadas a partir dos dados de origem. Se a variável CustomObject conter um ponteiro para um objeto ou área de memória alocados, então ela deve ser desalocada após o uso. Para isso, um argumento 'Final: boolean' é passado para o corpo da função. Se 'Final' = 'True' então o procedimento de finalização é ativado, o que inclui a desalocação de memória.
As classes a seguir estão disponíveis para o uso em funções de medidas calculadas:
// Lista de medidas
TMeasures = class
published
property Items[AIndex: Integer]: TMeasure;
property ItemByCaption[AIndex: String]: TMeasure;
property ItemByName[AIndex: String]: TMeasure;
property Count: Integer;
property RecordCount: integer;
property DetailValue[ARecordIndex: Integer; AFieldName: String]: Variant;
property XLevel: integer;
property YLevel: integer;
end;
// Lista de dimensões
TDimensions = class
published
property Items[AIndex: Integer]: TDimension;
property ItemByCaption[AIndex: String]: TDimension;
property ItemByName[AIndex: String]: TDimension;
property XAxisItems[AIndex: Integer]: TDimension;
property YAxisItems[AIndex: Integer]: TDimension;
property IsTotalByCol: boolean
property IsTotalByRow: boolean
property XLevel: integer;
property YLevel: integer;
property XAxisLevelsCount: integer;
property YAxisLevelsCount: integer;
end;
// Lista de campos
TfcxSliceFields = class
published
property Items[Index: Integer]: TfcxSliceField;
property ItemByCaption[AIndex: String]: TfcxSliceField;
property ItemByName[AIndex: String]: TfcxSliceField;
property Count;
end;
// Medida
TMeasure = class
published
property Caption: String;
property CurrentValue: Variant;
property CurrentCaption: String;
property FieldName: String;
property ColOffsetValue[Offset: integer]: Variant;
property RowOffsetValue[Offset: integer]: Variant;
property ColOffsetValueWithDimValue[ADimValue: Variant]: Variant;
property RowOffsetValueWithDimValue[ADimValue: Variant]: Variant;
property TotalValueForDims[ADimNames: String]: Variant;
property ColRowOffsetValue[ColOffset, RowOffset: integer]: Variant;
property ColRowOffsetValueWLevel[ColOffset, RowOffset, ColLevelOffset, RowLevelOffset: integer]: Variant
end;
// Dimensão
TDimension = class
published
property FieldName: String;
property Caption: String;
property CurrentValue: Variant;
property CurrentCaption: String;
property SubGroup: TDimension;
end;
// Campo
TfcxSliceField = class(TPersistent)
published
property FieldName: String;
property Caption: String;
property CurrentValue: Variant;
property CurrentCaption: String;
property FilterCount: Integer;
property IsFiltered: Boolean;
end;
// Objeto de serviço
TfcxCustomObject = class(TPersistent)
published
property Value: Pointer;
property ValueIsNil: Boolean;
end;
Aqui seguem descrições detalhadas dos métodos e propriedades das classes listadas acima:
TMeasure
- Caption - legenda da medida
- FieldName - nome do campo da medida
- CurrentValue - valor atual
- CurrentCaption - legenda do valor atual
- ColOffsetValue[Offset: integer] - valor da medida da célula com um deslocamento da coluna a partir do valor atual
- RowOffsetValue[Offset: integer] - valor da medida da célula com um deslocamento da fileira a partir do valor atual
- ColOffsetValueWithDimValue[ADimValue: Variant] - valor da medida que corresponde ao valor da dimensão atual ADimValue das dimensões da coluna
- RowOffsetValueWithDimValue[ADimValue: Variant] - valor da medida que corresponde ao valor da dimensão atual ADimValue das dimensões da fileira
- TotalValueForDims[ADimNames: String] - valor do total das dimensões requisitadas (DimNames separadas por ',')
- ColRowOffsetValue[ColOffset, RowOffset: integer] - valor da medida da célula com deslocamento de coluna e fileira a partir do valor atual
- ColRowOffsetValueWLevel[ColOffset, RowOffset, ColLevelOffset, RowLevelOffset: integer] - valor da medida da célula com deslocamento de coluna e fileira a partir do valor no nível requisitado
TDimension
- Caption - legenda da dimensão
- FieldName - nome do campo da dimensão
- CurrentValue - valor atual
- CurrentCaption - legenda do valor atual
- SubGroup - subgrupo da dimensão
TfcxSliceField
- Caption - legenda do campo
- FieldName - nome do campo
- CurrentValue - valor atual (disponível somente para o script de filtro)
- CurrentCaption - legenda atual (disponível somente para o script de filtro)
- FilterCount - número de valores filtrados
- IsFiltered - verdadeiro quando os valores do campo são filtrados, de outro modo falso
TMeasures
- Items[AIndex: Integer] - matriz de medidas com acesso através do índice
- ItemByCaption[AIndex: String] - matriz de medidas com acesso através da legenda
- ItemByName[AIndex: String] - matriz de medidas com acesso através do nome (propriedade padrão)
- Count - número de medidas
- RecordCount - número de fileiras de detalhe
- DetailValue[ARecordIndex: Integer; AFieldName: String] - valor do campo na fileira de detalhe
- XLevel - nìvel do eixo X ao qual pertence a célula atual
- YLevel - nìvel do eixo Y ao qual pertence a célula atual
TDimensions
- Items[AIndex: Integer] - matriz de dimensões com acesso através do índice
- ItemByCaption[AIndex: String] - matriz de dimensões com acesso através da legenda
- ItemByName[AIndex: String] - matriz de dimensões com acesso através do nome (propriedade padrão)
- Count - número de dimensões
- XAxisItems[AIndex: Integer] - dimensão no eixo X
- YAxisItems[AIndex: Integer] - dimensão no eixo Y
- IsTotalByCol - é verdadeiro quando a célula for uma célula total no eixo X, de outro modo falso
- IsTotalByRow - é verdadeiro quando a célula for uma célula total no eixo Y, de outro modo falso
- XAxisLevelsCount - número de dimensões no eixo X
- YAxisLevelsCount - número de dimensões no eixo Y
- XLevel - nìvel do eixo X ao qual pertence a célula atual
- YLevel - nìvel do eixo Y ao qual pertence a célula atual
TfcxSliceFields
- Items[Index: Integer] - matriz de campos com acesso através do índice
- ItemByCaption[AIndex: String] - matriz de campos com acesso através da legenda
- ItemByName[AIndex: String] - matriz de campos com acesso através do nome (propriedade padrão)
- Count - número de campos
TfcxCustomObject
- Value - ponteiro para um objeto de usuário ou uma área de memória
- ValueIsNil - verifica se um valor é vazio: usado para a verificação antes da criação do objeto ou a alocação de memória iniciais
Aqui segue um exemplo de um valor de medida calculado baseado em outras medidas:
```Code Example Sum = Price * Amount + WorkPrice
||procedure func\_3(var Result: Variant);|cabeçalho do procedimento|
| ----- | ----- | ----- |
||var wp: Variant;|declarar variável wp|
||begin||
||` wp := Measures['Work price'].CurrentValue;`|atribuir o valor atual da medida "Work price" à variável wp|
||` if VarType(wp) <= 1 then wp := 0;`|se wp não existir (Null ou UnAssigned), então tratar o valor de wp como 0 (usamos este teste para prevenir a adição usando valores Null e UnAssigned)|
||` Result :=`` Measures['Price'].CurrentValue*`` Measures['Amount'].CurrentValue+`` wp;`|define Result como o valor atual da medida "Price" multiplicado pelo valor atual da medida "Amount" mais o valor de wp.|
||end;||

Uma função que calcula o valor da medida baseada em outras medidas é chamada uma vez para cada célula (interseção de dimensões). Se "Calcular todas as células" não for definido, então a função não é chamada para células vazias.
A função que calcula o valor da medida baseada nos dados de origem é chamada para cada célula um número de vezes que corresponde ao número de fileiras nos dados de origem. A função possui dois argumentos: Result e Final:
Result - valor atual da medida
Final - verdadeiro quando esta for a última chamada, de outro modo falso
A chamada final ocorre para cada célula não vazia quando o percurso dos dados de origem tiver acabado. Neste caso, o argumento Final da função possui o valor "True". A chamada final é necessária para cálculos suplementares de desempenho e para a desalocação de memória.
No exemplo a seguir há duas funções:
AmountScriptOnGetValue function - calcula a soma do campo "Amount": observe que a soma ocorre somente quando Final = False
AveragePriceOnGetValue function - calcula o preço médio: requer a soma dos valores das medidas "Amount" e "Cost" e o cálculo da média na chamada final. Observe que a variável CustomObject é usada para armazenar a soma da medida "Amount". A desalocação de memória não é necessária, já que a memória não foi alocada anteriormente
