PBToolboxAI v4 ← Site

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 #

Userobjectu_pbt_crosstab
Classe de items— (os campos são colocados através de métodos)
Serve paraDar 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ção500 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.

ZonaO que contémEfeito
LinhasCampos de agrupamentoUm nível de linhas por campo, recolhível
ColunasCampos de agrupamentoUm nível de cabeçalhos de coluna por campo
ValoresCampos numéricos e a respetiva agregaçãoO que é calculado nas células
FiltrosCampos de seleçãoUm 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 #

ConstanteValorPara
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 #

PropriedadeTipoPredefiniçãoFunção
is_totals_positionstring"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_axisstring"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_symbolstring""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_thousandsstring"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_listbooleantrueMostra o painel de campos, onde o utilizador reorganiza a tabela com o rato
ib_row_subtotalsbooleantrueMostra 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_subtotalsbooleantrueMostra um subtotal por grupo de colunas
ib_row_grand_totalbooleantrueMostra a linha de total geral sob a tabela (a gémea de ib_col_grand_total)
ib_col_grand_totalbooleantrueMostra a coluna de total geral após a tabela (a gémea de ib_row_grand_total)
ib_copy_headersbooleantrueCtrl+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_enabledbooleantrueEsbatido: 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_stylestring""Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança
is_theme_modestring""Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança
il_theme_accentlong-1Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema)
is_tooltipstring""Tooltip simples apresentado ao passar sobre o componente
is_super_tooltip_titlestring""Título do tooltip enriquecido (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto do tooltip enriquecido (aceita marcação enriquecida)
is_super_tooltip_imagestring""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.

PropriedadeTipoPredefiniçãoFunção
is_labelstringcabeçalho do DataWindowEtiqueta 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_showstring"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_formattingstring"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étodoFunçã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étodoFunçã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étodoFunçã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étodoFunçã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étodoFunçã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étodoFunçã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 ( ) → stringDevolve 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étodoFunçã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 #

EventoAcionado 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:

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 #

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.

MembrosFunçãoDetalhado em
of_count · of_keys_at · of_hasPercorrer o que o componente contém3.2 Os items
of_resetRepor o componente a zero3.6 Repor um componente a zero: of_reset()
of_set_property · of_get_property · of_component_nameControlar uma propriedade pelo nome3.1 O motor de propriedades
of_register_shortcut · of_clear_shortcutsAtalhos de teclado do componente3.5 Os atalhos de teclado
of_is_created · of_is_ready · of_get_last_errorSe nasceu, se está pronto, o que falhou3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar a renderização como imagem3.8 Exportar a representação como imagem
of_set_redrawAgrupar as alterações num único repinte3.10 Boas práticas
of_preload_iconsÍcones mostrados sem atrasoApresentação instantânea: of_icon
of_set_translationTraduzir uma legenda do componente5.2 Adaptar uma etiqueta: of_set_translation
of_focus_webviewDar o foco ao componente6.4 Teclado e focus
of_print · of_print_to_pdfImprimir, ou escrever um PDF6.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.


← Referência dos componentes · Índice do guia