crosstab — u_pbt_crosstab #
← Referência dos componentes · Índice do guia
Tabela dinâmica completa: zonas de linhas / colunas / valores alimentadas a partir de um DataStore, agregações, filtros, formatação condicional, agrupamento de datas, medidas calculadas e exportações CSV / Excel.
▶ Ver ao vivo — Aplicação de demonstração, mosaico Crosstab: a pré-visualização, o código que o produz e esta página, lado a lado.
Em resumo #
| Userobject | u_pbt_crosstab |
| Classe de items | — (os campos são colocados através de métodos) |
| Serve para | Dar aos utilizadores uma análise cruzada dos dados, que eles próprios reorganizam, sem escrever SQL nem recorrer ao Excel |
| Limite no modo de demonstração | 500 linhas de origem processadas; exportações CSV e Excel e cópia (Ctrl+C) desativadas — ver o modo de demonstração |
O princípio #
O componente recebe um conjunto de dados plano — um DataStore, ou seja, qualquer consulta já escrita na aplicação. O crosstab trata do resto: deduz a lista dos campos, que devem ser distribuídos por quatro zonas.
| Zona | O que contém | Efeito |
|---|---|---|
| Linhas | Campos de agrupamento | Um nível de linhas por campo, recolhível |
| Colunas | Campos de agrupamento | Um nível de cabeçalhos de coluna por campo |
| Valores | Campos numéricos e a respetiva agregação | O que é calculado nas células |
| Filtros | Campos de seleção | Um filtro acima da tabela, aplicado a tudo |
Todo o cálculo é feito no componente: uma vez transmitidos os dados, reorganizar a tabela não desencadeia qualquer ida e volta à base de dados nem ao PowerBuilder.
Início rápido #
// event open de la fenetre
datastore lds
lds = create datastore
lds.dataobject = "d_sales"
lds.SetTransObject(SQLCA)
lds.Retrieve()
// 1. Transmitir os dados: os campos sao deduzidos das colunas
uo_crosstab.of_from_datastore(/*data*/ lds)
// 2. Distribuir os campos pelas zonas
uo_crosstab.of_add_row_field(/*field*/ "region")
uo_crosstab.of_add_col_field(/*field*/ "year")
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)
// 3. Apresentar: formato dos montantes e totais gerais
uo_crosstab.of_set_value_format(/*field*/ "amount", /*decimals*/ 0, /*thousands*/ "locale", /*suffix*/ "$", /*symbol_before*/ true)
uo_crosstab.ib_row_grand_total = true
uo_crosstab.ib_col_grand_total = true
// event ue_cell_double_clicked de uo_crosstab : (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value)
// O utilizador quer o detalhe por tras de um numero: abrir a lista correspondente.
of_open_detail(as_row_tuple_json, as_col_tuple_json)
Constantes #
| Constante | Valor | Para |
|---|---|---|
TOTALS_BOTTOM · TOTALS_TOP | "bottom" "top" | is_totals_position |
VALUES_COLS · VALUES_ROWS | "cols" "rows" | is_values_axis |
AGG_SUM · AGG_COUNT · AGG_DISTINCT_COUNT | "sum" "count" "dcount" | of_add_value_field |
AGG_AVG · AGG_MIN · AGG_MAX | "avg" "min" "max" | of_add_value_field |
LABEL_GT · LABEL_LT · LABEL_BETWEEN | "gt" "lt" "between" | of_set_label_filter |
LABEL_CONTAINS · LABEL_BEGINS · LABEL_ENDS | "contains" "begins" "ends" | of_set_label_filter |
As constantes de agregação leem-se no componente: uo_crosstab.AGG_SUM. As de um campo (SHOW_*, CF_*) leem-se no handle do campo.
Propriedades #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_totals_position | string | "bottom" | Onde se coloca a linha de total geral: TOTALS_BOTTOM (no rodapé, predefinição) ou TOTALS_TOP (no topo, logo abaixo dos cabeçalhos). Só o total geral se desloca: o subtotal de um grupo fica na linha do grupo |
is_values_axis | string | "cols" | Orientação das medidas quando existe mais do que uma: VALUES_COLS (lado a lado em colunas, predefinição) ou VALUES_ROWS (empilhadas em linhas) |
is_currency_symbol | string | "" | A moeda que o menu Formato do número de um chip de valor propõe, ao lado de « Sem símbolo » e « % ». Vazio = a da língua de apresentação ($ em inglês, € nas restantes) |
is_thousands | string | "locale" | Separador de milhares das medidas que não definem nenhum (of_set_value_format com separador vazio) — a mesma definição que o menu Opções da grelha: THOUSANDS_LOCALE (o da língua de apresentação, predefinição), THOUSANDS_SPACE, THOUSANDS_NONE, ou o próprio separador (",", ".", " ") |
ib_field_list | boolean | true | Mostra o painel de campos, onde o utilizador reorganiza a tabela com o rato |
ib_row_subtotals | boolean | true | Mostra o subtotal de cada grupo de linhas, escrito na linha do próprio grupo, acima dos seus membros; desativado, essa linha mantém o rótulo sem valor |
ib_col_subtotals | boolean | true | Mostra um subtotal por grupo de colunas |
ib_row_grand_total | boolean | true | Mostra a linha de total geral sob a tabela (a gémea de ib_col_grand_total) |
ib_col_grand_total | boolean | true | Mostra a coluna de total geral após a tabela (a gémea de ib_row_grand_total) |
ib_copy_headers | boolean | true | Ctrl+C copia os cabeçalhos com as células selecionadas: os nomes das colunas numa primeira linha (a medida só é nomeada se a tabela a mostrar: vários valores, ou nenhum campo em Colunas) e o membro de cada linha — o seu caminho completo, « Nord / Lille » — numa primeira coluna, cujo canto traz os nomes dos campos em linhas (« region / ville »). Uma colagem numa folha de cálculo diz assim o que são os valores. false copia apenas os valores. Lida em direto, reposta a true por of_reset |
ib_enabled | boolean | true | Esbatido: a grelha continua a mostrar os seus valores — uma tabela dinâmica vazia não é o mesmo que uma desligada pela aplicação — mas deixa de responder ao ponteiro |
is_theme_style | string | "" | Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança |
is_theme_mode | string | "" | Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança |
il_theme_accent | long | -1 | Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema) |
is_tooltip | string | "" | Tooltip simples apresentado ao passar sobre o componente |
is_super_tooltip_title | string | "" | Título do tooltip enriquecido (prevalece sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto do tooltip enriquecido (aceita marcação enriquecida) |
is_super_tooltip_image | string | "" | Imagem do tooltip enriquecido |
Propriedades de um campo #
of_field (string as_field) devolve o handle de um campo: obtém-se uma vez e, a partir daí, o campo é controlado através das suas propriedades. O handle é criado na primeira chamada e reutilizado depois.
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_label | string | cabeçalho do DataWindow | Etiqueta legível do campo ("amount" → "Volume de negócios"). Por defeito o texto de cabeçalho da coluna no DataWindow, senão o seu nome; uma cadeia vazia repõe-no. Definida pelo seu código, sobrevive a of_from_datastore |
is_show | string | "normal" | O que a célula apresenta: "normal", "pctGrand" (% do total geral), "pctRow" (% da linha), "pctCol" (% da coluna), "running" (acumulado), "diff" (diferença face ao anterior) |
is_conditional_formatting | string | "none" | Formatação condicional: CF_NONE, CF_SCALE (escala de cores), CF_BARS (barras na célula) ou CF_ICONS (uma seta por terço: subida, estável, descida) |
Os valores de is_show e de is_conditional_formatting estão também disponíveis como constantes no handle (SHOW_PCT_COL, CF_SCALE…). Definidos antes de o campo estar em Valores, são guardados, relidos tal como definidos e aplicados à sua chegada.
// Local variables
n_pbt_crosstab_field lnv_field
// O campo montante : a sua etiqueta e uma escala de cores
lnv_field = uo_crosstab.of_field(/*field*/ "amount")
lnv_field.is_label = "Volume de negócios"
lnv_field.is_conditional_formatting = lnv_field.CF_SCALE
⚠️ Alteração incompatível. Esta propriedade chamava-se
is_cf: a abreviatura nada dizia no ponto de utilização. O nome antigo já não existe — um código que o utilize não compila. A substituição é mecânica:is_cf→is_conditional_formatting, sem alteração de valores nem de comportamento.
Métodos #
Alimentar e nomear #
| Método | Função |
|---|---|
of_from_datastore (datastore ads_data) | Transmite o conjunto de dados: os campos são deduzidos das colunas do DataStore e a respetiva etiqueta do texto de cabeçalho. Um texto com uma tabulação ou uma quebra de linha fica na sua linha; um valor vazio (NULL, texto vazio) é um único membro (vazio), colocado em último; as etiquetas definidas por is_label sobrevivem ao recarregamento. Devolve 0 depois de carregados os dados, -5 se o DataStore não for válido ou não tiver qualquer coluna, -2 se o componente não estiver criado |
of_field (string as_field) | Devolve o handle de um campo, para o etiquetar ou formatar (ver Propriedades de um campo) |
Construir a tabela #
| Método | Função |
|---|---|
of_clear_layout ( ) | Esvazia as quatro zonas: a tabela volta a ficar vazia, os dados permanecem carregados. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_add_row_field (string as_field) | Adiciona um campo à zona Linhas (a ordem das chamadas determina a ordem dos níveis). Um campo já em Valores fica lá: pode estar nos dois (uma contagem distinta por membro). Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm ou para uma medida calculada (só vai para Valores), -2 se o componente não estiver criado |
of_add_col_field (string as_field) | Adiciona um campo à zona Colunas. Um campo já em Valores fica lá: pode estar nos dois (uma contagem distinta por membro). Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm ou para uma medida calculada (só vai para Valores), -2 se o componente não estiver criado |
of_add_value_field (string as_field, string as_agg) | Adiciona uma medida à zona Valores, com a respetiva agregação (AGG_*, vazio = AGG_SUM). O campo mantém o seu lugar em Linhas, Colunas ou Filtros. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm ou outra agregação, -2 se o componente não estiver criado |
of_add_filter_field (string as_field) | Adiciona um campo à zona Filtros, acima da tabela. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm ou para uma medida calculada (só vai para Valores), -2 se o componente não estiver criado |
of_remove_field (string as_field) | Retira um campo da tabela: de todas as zonas onde está (Linhas, Colunas, Filtros, e cada um dos seus valores), com os seus filtros — como «Remover» a partir da lista de campos. O resto da disposição fica como está, e ue_layout_changed comunica a nova. Devolve 0 depois de aplicado, -4 quando o campo não está em nenhuma zona, -5 para um campo que os dados não contêm |
As agregações aceites por of_add_value_field são disponibilizadas pelo componente sob a forma de constantes: AGG_SUM (predefinição), AGG_COUNT, AGG_DISTINCT_COUNT (contagem de valores distintos, as células vazias são ignoradas como no Excel), AGG_AVG, AGG_MIN, AGG_MAX.
Totais e subtotais #
Os totais definem-se através de propriedades, descritas acima: ib_row_grand_total e ib_col_grand_total para os totais gerais, ib_row_subtotals e ib_col_subtotals para os subtotais, is_totals_position para a posição da linha de total geral.
Filtrar #
| Método | Função |
|---|---|
of_set_member_filter (string as_field, string as_values_tab) | Mantém apenas os valores listados de um campo. Os valores são separados por tabulações (~t); uma lista vazia remove o filtro, como of_set_member_order. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
of_clear_member_filter (string as_field) | Remove este filtro. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
of_set_value_filter (string as_field, string as_type, double ad_a, double ad_b, integer ai_measure_index) | Filtra sobre o total da medida n.º ai_measure_index (a primeira = 1): VALUEFILTER_TOP ou VALUEFILTER_BOTTOM (os ad_a primeiros ou últimos), VALUEFILTER_GT, VALUEFILTER_LT (acima, abaixo de ad_a), VALUEFILTER_BETWEEN (entre ad_a e ad_b). Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, outro tipo ou uma posição sem medida em Valores, -2 se o componente não estiver criado |
of_clear_value_filter (string as_field) | Remove este filtro. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
of_set_label_filter (string as_field, string as_type, double ad_a, double ad_b) | Filtro numérico sobre o próprio valor do campo: LABEL_GT, LABEL_LT, LABEL_BETWEEN. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm ou outro tipo, -2 se o componente não estiver criado |
of_set_label_filter (string as_field, string as_type, string as_a, string as_b) | Filtro de texto sobre o valor do campo: LABEL_CONTAINS, LABEL_BEGINS, LABEL_ENDS (as_a, sem distinguir maiúsculas e minúsculas; as_b não é usado). Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, outro tipo ou um texto vazio, -2 se o componente não estiver criado |
of_clear_label_filter (string as_field) | Remove este filtro. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
Formatar #
| Método | Função |
|---|---|
of_set_value_format (string as_field, integer ai_decimals, string as_thousands, string as_suffix { , boolean ab_symbol_before }) | Formato de uma medida: número de casas decimais (0 a 6), separador de milhares (",", ".", " ": o próprio separador, "," com um ponto decimal e "." com uma vírgula decimal; "space" espaço fino, "none", "locale" o da língua de apresentação; "" deixa a medida em is_thousands, a predefinição do menu Opções), símbolo — após o número por defeito (1 234 EUR), ANTES quando ab_symbol_before é true ($1,234). As três definições pertencem a ESTA medida; definidas antes de o campo estar em Valores, são guardadas e aplicadas à sua chegada. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
of_clear_value_format (string as_field) | Regresso ao formato predefinido. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
of_set_member_order (string as_field, string as_values_tab) | Ordem de apresentação imposta aos valores de um campo (separados por ~t); uma cadeia vazia repõe a ordem natural. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm, -2 se o componente não estiver criado |
Datas e campos calculados #
| Método | Função |
|---|---|
of_group_date_field (string as_field, string as_part) | Cria um campo derivado de uma coluna date, datetime ou timestamp (uma hora sozinha não tem data para agrupar): DATE_YEAR, DATE_QUARTER ou DATE_MONTH, chamado <coluna>__<parte>. Junta-se à lista dos campos e utiliza-se como os restantes. Devolve 0 depois de aplicado, -5 para um campo que os dados não contêm ou outra parte, -2 se o componente não estiver criado |
of_add_calc_field (string as_name, string as_label, string as_formula) | Campo calculado linha a linha ("[amount] * 0.8" = o líquido de cada venda, depois somado como qualquer coluna), utilizável em qualquer zona. Não para um rácio de totais (preço médio): isso é of_add_calc_measure. Devolve 0 depois de aplicado, -5 num argumento inválido, -2 se o componente não estiver criado |
of_remove_calc_field (string as_name) | Remove um campo calculado. Devolve 0 depois de aplicado, -5 se nenhum campo calculado tiver este nome, -2 se o componente não estiver criado |
of_add_calc_measure (string as_name, string as_label, string as_formula) | Medida calculada célula a célula, sobre os totais ("[marge] / [ca]" = taxa de margem global). Coloca-se unicamente na zona Valores. A sua fórmula só cita campos de dados: outra medida calculada é recusada (ue_calc_field_error). Devolve 0 depois de aplicado, -5 num argumento inválido, -2 se o componente não estiver criado |
of_remove_calc_measure (string as_name) | Remove uma medida calculada. Devolve 0 depois de aplicado, -5 se nenhuma medida calculada tiver este nome, -2 se o componente não estiver criado |
Uma fórmula aceita os operadores + - * / ( ), números e campos entre parênteses retos. Uma fórmula inválida desencadeia ue_calc_field_error — nada falha.
Expandir, memorizar, exportar #
| Método | Função |
|---|---|
of_expand_all ( ) · of_collapse_all ( ) | Expande ou recolhe todos os grupos, de linhas E de colunas. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_expand_to_level (integer ai_level) | Expande até um determinado nível (1 = apenas o primeiro nível). Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_get_layout ( ) → string | Devolve o estado completo da tabela — guarde-o tal como está e reproduza-o com of_set_layout |
of_set_layout (string as_state_json) | Restaura um estado obtido anteriormente. Devolve 0 depois de aplicado, -5 para um texto vazio ou que não seja JSON, -2 se o componente não estiver criado |
of_get_cell_value (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, ref double ad_value) | Lê o valor de uma célula, o que a tabela apresenta (0,8 sob 80,0 %, o acumulado sob um acumulado). A sua linha e a sua coluna são os tuplos que ue_cell_double_clicked fornece — {"region":"Nord","city":"Lille"}, um membro vazio null, {} (ou uma cadeia vazia) para o total — e ai_measure é a posição do valor na zona Valores, a partir de 1. Um tuplo nomeia os campos da sua zona a partir do primeiro: {"region":"Nord"} é o subtotal de Nord. A resposta não depende da apresentação: um ramo recolhido ou subtotais ocultos leem-se na mesma. Devolve 0 com o valor em ad_value (NULL para uma célula sem valor), -4 quando a tabela não tem essa célula (um membro ou um campo que não mostra aí), -5 para um tuplo mal formado ou uma posição sem medida, -2 se o componente não estiver criado |
of_export_csv (string as_path) | Escreve um ficheiro CSV da vista atual (UTF-8 com BOM, ponto e vírgula); ue_csv_saved confirma. Os números tomam o separador decimal da língua de apresentação (a vírgula em francês, alemão, italiano, espanhol, português); um rótulo que seria lido como uma fórmula (= + - @) é escrito precedido de um apóstrofo. O gémeo de of_export_xlsx. Devolve 0 depois de aplicado, -5 num argumento inválido, -2 se o componente não estiver criado |
of_export_xlsx (string as_path) | Escreve um ficheiro Excel da tabela tal como é apresentada, formatação incluída (negativos a vermelho incluídos); ue_xlsx_saved confirma — ou recusa com o motivo acima de 16 384 colunas ou 1 048 576 linhas, os limites de uma folha Excel. Devolve 0 depois de aplicado, -5 num argumento inválido, -2 se o componente não estiver criado |
Comuns #
| Método | Função |
|---|---|
of_reset ( ) | Repõe o componente no seu estado inicial. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_set_redraw (boolean) | Agrupa uma série de modificações numa única representação. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_save_as_png (string) · of_save_as_jpg (string) | Exporta a representação como imagem. Devolve 0, -2 se o componente não estiver criado, -4 se a captura falhar, -5 num caminho vazio |
Eventos #
| Evento | Acionado quando |
|---|---|
ue_layout_changed (string as_layout_json) | O utilizador reorganizou a tabela (deslocou um campo, alterou uma agregação, ordenou uma coluna, recolheu um grupo…): tudo o que of_get_layout guarda |
ue_cell_double_clicked (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value) | Duplo clique numa célula: os dois primeiros argumentos descrevem o cruzamento ({"region":"Nord","city":"Lille"}, um membro vazio vale null, {} para o total), ai_measure a posição do valor clicado na zona Valores, a partir de 1, e ad_value o valor que a célula apresenta — 0.8 sob « 80,0 % », o acumulado sob um acumulado — ou NULL para uma célula vazia. Os dois tuplos e ai_measure formam o endereço que of_get_cell_value volta a ler. É o ponto de entrada de um detalhe |
ue_csv_saved (string as_path, boolean ab_ok, string as_error) | O ficheiro CSV foi escrito — ou não, e as_error diz porquê |
ue_xlsx_saved (string as_path, boolean ab_ok, string as_error) | O ficheiro Excel foi escrito — ou não, e as_error indica porquê |
ue_calc_field_error (string as_field, string as_message) | Uma fórmula de campo ou de medida calculada é inválida |
ue_copy (string as_tsv) | O utilizador copiou uma seleção de células (Ctrl+C): cabe ao programador colocá-la na área de transferência. as_tsv é um texto separado por tabulações que traz por predefinição os cabeçalhos — os nomes das colunas numa primeira linha, o membro de cada linha (o seu caminho completo, « Nord / Lille ») numa primeira coluna — ou apenas os valores com ib_copy_headers = false. No modo de demonstração a cópia é uma exportação: recusada, e a grelha di-lo |
ue_ready ( ) | O componente terminou o carregamento; tudo o que foi enviado antes foi reproduzido |
ue_runtime_missing ( ) | O runtime WebView2 está ausente: o componente permanece vazio |
ue_bg_color (long al_color) | O componente calculou a cor de fundo do respetivo tema; o userobject já a adotou (backcolor) |
O que o utilizador pode fazer sem uma linha de código #
A tabela é viva: é esse todo o interesse do componente. Com o painel de campos visível (ib_field_list = true), o utilizador pode:
- arrastar um campo de uma zona para outra e reorganizar o cruzamento à vontade;
- alterar a agregação de uma medida (soma, média, contagem…);
- filtrar os valores de um campo através de uma lista de seleção;
- recolher ou expandir um grupo de linhas ou de colunas;
- ordenar através de um cabeçalho;
- selecionar e depois copiar um bloco de células, com os seus cabeçalhos para que uma colagem numa folha de cálculo diga o que são os valores (
ib_copy_headers).
Cada uma destas manipulações é comunicada em ue_layout_changed: em conjunto com of_get_layout / of_set_layout, permite oferecer «vistas guardadas» aos utilizadores.
Com o teclado. Cada um destes gestos é alcançável sem rato: Tab leva a um campo, a um triângulo de dobragem ou a um cabeçalho ordenável, Enter ou Espaço aciona-o. Num campo abre o respetivo menu — aquele que tem Adicionar às linhas / às colunas / aos valores / aos filtros e Remover: toda a construção da tabela passa por aí. Shift+F10 ou a tecla Menu também abrem esse menu, e o foco segue o campo acabado de mover, mesmo para outra zona.
Exemplos #
Um relatório de vendas completo #
// Linhas: regiao e depois cidade dentro de cada regiao
uo_crosstab.of_clear_layout()
uo_crosstab.of_add_row_field(/*field*/ "region")
uo_crosstab.of_add_row_field(/*field*/ "city")
// Colunas: uma por ano
uo_crosstab.of_add_col_field(/*field*/ "year")
// Celulas: o montante total
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)
// Apresentacao: montantes legiveis, subtotais e totais gerais
uo_crosstab.of_set_value_format(/*field*/ "amount", /*decimals*/ 0, /*thousands*/ "locale", /*suffix*/ "$", /*symbol_before*/ true)
uo_crosstab.ib_row_subtotals = true
uo_crosstab.ib_row_grand_total = true
uo_crosstab.ib_col_grand_total = true
// Colorir as celulas para identificar os grandes montantes num relance
uo_crosstab.of_field(/*field*/ "amount").is_conditional_formatting = n_pbt_crosstab_field.CF_SCALE
Etiquetas legíveis #
As colunas chamam-se muitas vezes mt_ht ou cd_reg. Devem ser renomeadas de uma vez por todas, logo a seguir a of_from_datastore.
// Primeiro os dados : os campos tomam o nome das colunas
uo_crosstab.of_from_datastore(/*data*/ lds)
// Depois uma etiqueta legivel para cada campo
uo_crosstab.of_field(/*field*/ "region").is_label = "Região"
uo_crosstab.of_field(/*field*/ "city").is_label = "Cidade"
uo_crosstab.of_field(/*field*/ "category").is_label = "Categoria"
uo_crosstab.of_field(/*field*/ "year").is_label = "Ano"
uo_crosstab.of_field(/*field*/ "amount").is_label = "Volume de negócios"
uo_crosstab.of_field(/*field*/ "quantity").is_label = "Quantidade"
Analisar proporções em vez de montantes #
// Local variables
n_pbt_crosstab_field lnv_amount
// Partir de zonas vazias e depois colocar os campos
uo_crosstab.of_clear_layout()
uo_crosstab.of_add_row_field(/*field*/ "category")
uo_crosstab.of_add_col_field(/*field*/ "year")
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)
// Manter apenas duas categorias no ecra (valores separados por uma tabulacao)
uo_crosstab.of_set_member_filter(/*field*/ "category", /*values_tab*/ "Informatique~tMobilier")
// O campo montante, para definir como e apresentado
lnv_amount = uo_crosstab.of_field(/*field*/ "amount")
// Mostrar a proporcao de cada celula no total da sua coluna
lnv_amount.is_show = lnv_amount.SHOW_PCT_COL
// Uma pequena barra em cada celula para comparar as proporcoes num relance
lnv_amount.is_conditional_formatting = lnv_amount.CF_BARS
Uma medida à medida: o preço médio #
Uma medida calculada é avaliada sobre os totais de cada célula, e não linha a linha: é isso que torna um rácio correto.
// Partir de zonas vazias e depois colocar os campos
uo_crosstab.of_clear_layout()
uo_crosstab.of_add_row_field(/*field*/ "region")
// Os dois totais que vao servir de base ao calculo
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)
uo_crosstab.of_add_value_field(/*field*/ "quantity", /*agg*/ uo_crosstab.AGG_SUM)
// Preco medio = montante total dividido pela quantidade total
uo_crosstab.of_add_calc_measure(/*name*/ "avg_price", /*label*/ "Preço médio", /*formula*/ "[amount] / [quantity]")
uo_crosstab.of_set_value_format(/*field*/ "avg_price", /*decimals*/ 2, /*thousands*/ "locale", /*suffix*/ "$", /*symbol_before*/ true)
// Depois coloca-la entre os valores como qualquer campo (o agregado nao conta: uma medida calcula-se)
uo_crosstab.of_add_value_field(/*field*/ "avg_price", /*agg*/ uo_crosstab.AGG_SUM)
// event ue_calc_field_error de uo_crosstab : (string as_field, string as_message)
// Formula invalida: avisar sem nada quebrar, a tabela permanece visivel.
uo_status.of_panel(/*key*/ "main").is_text = "Fórmula " + as_field + " : " + as_message
Analisar por mês, trimestre ou ano #
Uma coluna de data não se cruza tal como está — cada dia daria origem à sua própria linha. É necessário derivar primeiro o nível pretendido.
// Criar tres campos derivados da coluna sale_date
uo_crosstab.of_group_date_field(/*field*/ "sale_date", /*part*/ "year")
uo_crosstab.of_group_date_field(/*field*/ "sale_date", /*part*/ "quarter")
uo_crosstab.of_group_date_field(/*field*/ "sale_date", /*part*/ "month")
// Depois cruza-los como qualquer outro campo: ano em colunas, trimestre por baixo
uo_crosstab.of_add_col_field(/*field*/ "sale_date__year")
uo_crosstab.of_add_col_field(/*field*/ "sale_date__quarter")
O ranking das dez melhores regiões #
// Manter apenas as 10 regioes com maior total na primeira medida
uo_crosstab.of_set_value_filter(/*field*/ "region", /*type*/ "top", /*a*/ 10, /*b*/ 0, /*measure_index*/ 1)
Exportar #
A exportação reproduz exatamente a vista em curso: os mesmos filtros, os mesmos totais, a mesma formatação.
// Para Excel: o ficheiro e escrito diretamente no caminho indicado
uo_crosstab.of_export_xlsx(/*path*/ "C:\temp\ventes.xlsx")
// event ue_xlsx_saved de uo_crosstab : (string as_path, boolean ab_ok, string as_error)
// inv_notif = um n_pbt_toaster declarado como variavel de instancia da window
if ab_ok then
inv_notif.is_title = "Exportação concluída"
inv_notif.is_text = as_path
inv_notif.is_kind = inv_notif.KIND_SUCCESS
else
inv_notif.is_title = "Exportação impossível"
inv_notif.is_text = as_error
inv_notif.is_kind = inv_notif.KIND_ERROR
end if
inv_notif.of_show()
// Para CSV: um ficheiro, como para o Excel; ue_csv_saved confirma
uo_crosstab.of_export_csv(/*path*/ "C:\exports\ventes.csv")
Oferecer vistas guardadas #
// Local variables
string ls_view
// Guardar a vista atual : of_get_layout responde de imediato
ls_view = uo_crosstab.of_get_layout()
// Guardar o conteudo TAL COMO ESTA : reproduz-se sem transformacao.
of_save_view(is_current_view, ls_view)
// Mais tarde: repor uma vista guardada
uo_crosstab.of_set_layout(/*state_json*/ of_read_view("Ventes par region"))
Descer ao detalhe por trás de um número #
// event ue_cell_double_clicked de uo_crosstab : (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value)
// Os dois primeiros argumentos descrevem o cruzamento (que valores de linhas,
// que valores de colunas): o suficiente para reconstruir uma consulta de detalhe.
w_sales_detail lw_detail
// Abrir a janela de detalhe com o cruzamento como parametro
OpenWithParm(lw_detail, as_row_tuple_json + "|" + as_col_tuple_json)
Os dois tuplos e ai_measure formam o endereço da célula: of_get_cell_value volta a lê-lo mais tarde, tal como a tabela o apresenta nesse momento.
// ue_cell_double_clicked event of uo_crosstab : the address of the cell, read again later
// Local variables
double ld_value
// Read the cell again from its address : 0 when it exists
if uo_crosstab.of_get_cell_value(/*row_tuple_json*/ as_row_tuple_json, /*col_tuple_json*/ as_col_tuple_json, /*measure*/ ai_measure, /*value*/ ld_value) = 0 then
// ld_value is what the cell shows ; NULL for an empty cell
end if
Uma célula também se lê sem clique, pelos seus membros: um tuplo parcial designa um subtotal. E of_remove_field retira um campo de todas as suas zonas de uma só vez, filtros incluídos.
// The sales of Nord in 2025, first measure of Values
// Local variables
double ld_north
// A partial address : the region and the year, no other member
uo_crosstab.of_get_cell_value(/*row_tuple_json*/ '{"region":"Nord"}', /*col_tuple_json*/ '{"year":"2025"}', /*measure*/ 1, /*value*/ ld_north)
// Take the year out of the table, filters included
uo_crosstab.of_remove_field(/*field*/ "year")
Boas práticas #
- Chamar
of_from_datastoreuma única vez por conjunto de dados: reorganizar a tabela em seguida não tem custo, retransmitir os dados é dispendioso. - Colocar as etiquetas (
of_field("...").is_label) logo a seguir aof_from_datastore: acompanham o campo em toda a parte, incluindo no painel de campos e nas exportações. - Filtrar do lado do SQL aquilo que não se destina a ser analisado: o crosstab é rápido, mas um DataStore duas vezes mais pequeno abre-se duas vezes mais depressa.
of_clear_layout()esvazia as zonas sem retransmitir os dados: é a chamada indicada para propor várias análises sobre a mesma origem.- Um campo de data cruza-se sempre através de
of_group_date_field, nunca diretamente. - O painel de campos deve permanecer visível nos ecrãs de análise e ser ocultado nos painéis de bordo fixos.
Herdado da base comum #
Estes membros existem em todos os componentes visuais — não são próprios deste. São detalhados uma só vez, nos capítulos transversais; esta tabela apenas diz onde os ler.
| Membros | Função | Detalhado em |
|---|---|---|
of_count · of_keys_at · of_has | Percorrer o que o componente contém | 3.2 Os items |
of_reset | Repor o componente a zero | 3.6 Repor um componente a zero: of_reset() |
of_set_property · of_get_property · of_component_name | Controlar uma propriedade pelo nome | 3.1 O motor de propriedades |
of_register_shortcut · of_clear_shortcuts | Atalhos de teclado do componente | 3.5 Os atalhos de teclado |
of_is_created · of_is_ready · of_get_last_error | Se nasceu, se está pronto, o que falhou | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar a renderização como imagem | 3.8 Exportar a representação como imagem |
of_set_redraw | Agrupar as alterações num único repinte | 3.10 Boas práticas |
of_preload_icons | Ícones mostrados sem atraso | Apresentação instantânea: of_icon |
of_set_translation | Traduzir uma legenda do componente | 5.2 Adaptar uma etiqueta: of_set_translation |
of_focus_webview | Dar o foco ao componente | 6.4 Teclado e focus |
of_print · of_print_to_pdf | Imprimir, ou escrever um PDF | 6.9 Imprimir |
Duas ajudas não são herdadas: of_icon e of_escape_markup vivem em n_pbt_utils. Declare um — n_pbt_utils lnv_utils, nada a criar — e chame-as nele.