PBToolboxAI v4 ← Site

datagrid — u_pbt_datagrid #

← Referência dos componentes · Índice do guia

A grelha moderna de um DataStore: colunas tipadas e células ricas, ordenação, filtros, agrupamento com subtotais, edição no próprio sítio, paginação, origem por janela e exportação CSV — o DataWindow continua a ser o dono dos seus dados.

▶ Ver ao vivo — Aplicação de demonstração, mosaico Data grid: a pré-visualização, o código que o produz e esta página, lado a lado.


Em resumo #

Userobjectu_pbt_datagrid
Classe de itemsn_pbt_datagrid_column — uma coluna, obtida com of_column
Serve paraApresentar um DataStore numa grelha moderna — ordenação, filtros, agrupamentos, edição, volumes muito grandes — sem sair do seu DataWindow
Limite no modo de demonstração100 linhas apresentadas; exportações CSV e Excel desativadas — ver o modo de demonstração

O posicionamento #

O datagrid não é um substituto da DataWindow: é uma camada de apresentação que se coloca por cima. O SQL, os Retrieve(), os Update() e as impressões mantêm-se — e ganha-se uma grelha moderna para a visualização.

Visa dois pontos cegos da grelha DataWindow clássica:

A ligação à base de dados e a atualização permanecem fora do âmbito: pertencem à DataWindow.

O DataStore dos exemplos #

Todos os exemplos desta página — como os da aplicação de demonstração — partem do mesmo DataStore de contas de clientes, uma linha por conta: city, rep (o comercial), status, pipeline (uma percentagem), trend (sete valores mensais escritos "3,5,2,6,7,4,8"), revenue e rating (uma nota em cinco). A grelha chama-se uo_grid na janela, o DataStore ids. Uma linha carregada por of_from_datastore tem como chave o seu RowID no DataStore: não muda quando o DataStore ordena, filtra, insere ou elimina. Um evento devolve-lho, e ids.GetRowFromRowId(Long(as_key)) é o número da linha que designa agora.

Um DataStore só contém valores simples, e isso chega para as células ricas: um número é tudo o que um indicador (RENDERER_PROGRESS) e as estrelas (RENDERER_RATING) precisam, um nome dá um avatar, um texto "3,5,2,6" um minigráfico (RENDERER_SPARKLINE) tal como "vip, b2b" dá etiquetas (RENDERER_TAGS); a cor de uma pastilha (RENDERER_CHIP) dá-se por valor com is_tones.


Início rápido #

// open event of the window : the accounts, retrieved the way your application already does
ids = create datastore
ids.dataobject = "d_accounts"
ids.SetTransObject(SQLCA)
ids.Retrieve()

// 1. The grid reads the columns (typed) and every row of the DataStore
uo_grid.of_from_datastore(/*ads*/ ids)

// 2. The titles are the header texts of the DataWindow ; rename one if you like
uo_grid.of_column(/*key*/ "rep").is_title = "Account manager"

// 3. Rich cells : an avatar, a coloured status, a gauge, a mini chart, stars
uo_grid.of_column(/*key*/ "rep").is_renderer = n_pbt_datagrid_column.RENDERER_AVATAR
uo_grid.of_column(/*key*/ "status").is_renderer = n_pbt_datagrid_column.RENDERER_CHIP
uo_grid.of_column(/*key*/ "status").is_tones = "Active=" + n_pbt_datagrid_column.TONE_SUCCESS + "|At risk=" + n_pbt_datagrid_column.TONE_DANGER
uo_grid.of_column(/*key*/ "pipeline").is_renderer = n_pbt_datagrid_column.RENDERER_PROGRESS
uo_grid.of_column(/*key*/ "trend").is_renderer = n_pbt_datagrid_column.RENDERER_SPARKLINE
uo_grid.of_column(/*key*/ "rating").is_renderer = n_pbt_datagrid_column.RENDERER_RATING

// 4. A total, and the city stays in view
uo_grid.of_column(/*key*/ "revenue").is_summary = n_pbt_datagrid_column.SUMMARY_SUM
uo_grid.of_column(/*key*/ "city").is_pin = n_pbt_datagrid_column.PIN_START
// ue_row_clicked event of uo_grid : (string as_key)
// The key of a row loaded by of_from_datastore is its RowID : GetRowFromRowId gives
// the row it designates now, even after a sort or a delete in the DataStore.
wf_open_account(ids.GetRowFromRowId(Long(as_key)))

Propriedades #

PropriedadeTipoPredefiniçãoFunção
is_selection_modestringSELECT_NONEModo de seleção: nenhuma, uma linha, várias (Shift = intervalo, Ctrl = alternar)
is_densitystringDENSITY_COMFORTABLEAltura de linha: confortável ou compacta
is_quick_filterstring""Filtro rápido global: mantém apenas as linhas cujo texto — tal como apresentado (22/09/2026, 1 234,50) ou em bruto — contém este valor. O que o utilizador escreve espera pelo fim da escrita; oculto com uma origem por janelas
ib_filter_rowbooleanfalseApresenta a linha de introdução de filtro sob os cabeçalhos (equivalente ao botão Filtros)
ib_context_menubooleantrueMenu de contexto integrado numa linha: Copiar, Selecionar tudo, Limpar a seleção, Exportar para CSV, além das suas próprias entradas (of_add_row_menu_item). Ativo por predefinição. Um clique direito fora da seleção desloca-a para a linha visada, um clique direito dentro mantém-na. A false para mostrar o seu próprio menu a partir de ue_row_rclicked
ib_veto_editsbooleanfalsePergunta antes de manter um valor introduzido: emite ue_cell_editing, que pode recusar — a célula mantém então o seu valor anterior
ib_write_backbooleanfalseEscreve cada introdução no DataStore passado a of_from_datastore — SetItem na linha que a chave designa (o seu RowID, encontrado onde está), tipado pela coluna (datas, números, texto, códigos) — antes de ue_cell_edited. O Update continua a ser seu; uma data ou um número esvaziados passam a NULL, e um valor que o DataStore não pode manter (uma linha eliminada entretanto, um valor que SetItem recusa, um texto que não é uma hora) não é mantido: a célula retoma o que o DataStore tem, ue_write_back_failed diz porquê, e ue_cell_edited não é emitido. SetItem não aplica a regra Validation da coluna: verifique um valor em ue_cell_editing (ib_veto_edits)
ib_detail_on_demandbooleanfalseDetalhe a pedido: cada linha mostra a sua seta, e abri-la (a seta, ou of_expand_row) emite ue_detail_needed — preencha aí o painel com of_fill_detail, abre-se no regresso do evento. Nada preenchido: a linha fica fechada. O detalhe de 5 000 linhas nunca é lido antecipadamente
is_group_bystring""Agrupa as linhas por uma ou várias colunas, por ordem, as suas chaves unidas por | ("status|city"); cada cabeçalho de grupo tem os subtotais das colunas que têm um total. "" volta a uma lista simples. Relida em direto
ii_page_sizeinteger100Número de linhas por página, uma vez desencadeada a paginação
il_page_thresholdlong50000Número de linhas a partir do qual a grelha passa a páginas. 0 = paginar sempre, seja qual for o volume
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 coluna #

Cada coluna é um objeto por direito próprio, obtido por of_column("identificador") — o handle é criado no primeiro acesso e permanece válido a seguir.

// A column is reached by its key ; used once, it fits on one line
uo_grid.of_column(/*key*/ "amount").is_summary = n_pbt_datagrid_column.SUMMARY_SUM
uo_grid.of_column(/*key*/ "city").is_pin = n_pbt_datagrid_column.PIN_START
PropriedadeTipoPredefiniçãoFunção
is_titlestringa chaveTexto de cabeçalho da coluna; "" volta a mostrar a chave. of_from_datastore deixa os nomes de coluna do DataWindow: dê-lhes aqui um nome para o utilizador
is_tonesstring""Cor de uma pastilha (RENDERER_CHIP) segundo o seu valor, para o texto de um DataStore: pares valor=tom unidos por | ("Active=success|At risk=danger"), tons TONE_*; um valor não listado fica neutro
ii_widthintegerlargura declaradaLargura da coluna, em pixeis
ib_hiddenbooleanfalseOculta ou volta a apresentar a coluna
is_pinstringPIN_NONEFixa a coluna à esquerda ou à direita: mantém-se visível durante o deslocamento horizontal
ib_editablebooleanfalseAutoriza a introdução: duplo clique, escrita, Enter valida, Esc cancela → ue_cell_edited. Um valor que não convém à coluna (letras num número) é mostrado como recusado durante a escrita, e Enter mantém o editor aberto. Uma coluna booleana mostra uma verdadeira caixa de verificação: um clique, Espaço, Enter ou F2 inverte-a de imediato. Escrever um carácter numa célula de texto ou número abre o editor com esse carácter; durante uma edição, Tab e Shift+Tab mantêm o valor e abrem a célula modificável seguinte (anterior)
is_summarystringSUMMARY_NONETotal no rodapé da coluna; SUMMARY_NONE remove-o. SUMMARY_COUNT conta as células que têm um valor, como count() de um DataWindow
is_rendererstringRENDERER_NONECélula rica aplicada a posteriori; RENDERER_NONE regressa ao texto. RENDERER_BOOL mostra um visto para um valor verdadeiro; RENDERER_CUSTOM lê o valor como texto rico com etiquetas — para uma coluna que o seu código compõe: um valor escrito por um utilizador deve ter os parênteses retos escapados ([[ ]])
ii_indexintegerordem de declaraçãoPosição da coluna (primeira posição = 1); uma coluna que a grelha não tem relê-se 0
is_filterstring""Filtro por coluna. O texto é procurado no que a célula mostra (data formatada, número com máscara) ou no seu valor bruto; numa coluna numérica é reconhecido um operador inicial ("> 1000", "<= 50", "> 1,5" com o separador decimal da língua), numa coluna de data também ("> 22/09/2026", na ordem da língua, ou ISO). Cadeia vazia = filtro removido
is_formatstring""Formato de apresentação, na sintaxe da DataWindow: "#,##0.00", "$#,##0;($#,##0)", "0.0%", "dd/mm/yyyy", "mmmm d, yyyy", "hh:mm", "@@@-@@@@". Como numa DataWindow, a vírgula e o ponto designam os separadores da língua. Cadeia vazia = volta o formato da DataWindow; relê-se (o formato em vigor)

Constantes #

Devem utilizar-se sempre as constantes em vez das cadeias literais: o IDE completa-as e um erro de escrita torna-se impossível.

FamíliaConstantesSuportadas por
Tipo de colunaTYPE_STRING, TYPE_NUMBER, TYPE_INT, TYPE_DATE, TYPE_DATETIME, TYPE_BOOLo componente (of_add_column)
Célula ricaRENDERER_AVATAR, RENDERER_CHIP, RENDERER_PROGRESS, RENDERER_SPARKLINE, RENDERER_RATING, RENDERER_TAGS, RENDERER_BUTTON, RENDERER_LINK, RENDERER_BOOL, RENDERER_CUSTOMo componente e o handle de coluna (is_renderer)
Célula rica: nenhumaRENDERER_NONEapenas o handle de coluna (is_renderer)
Tom da pastilhaTONE_SUCCESS, TONE_WARN, TONE_DANGER, TONE_INFO, TONE_NEUTRALo handle de coluna (is_tones)
Modo de seleçãoSELECT_NONE, SELECT_SINGLE, SELECT_MULTIPLEo componente (is_selection_mode)
DensidadeDENSITY_COMFORTABLE, DENSITY_COMPACTo componente (is_density)
Total de rodapéSUMMARY_NONE, SUMMARY_SUM, SUMMARY_AVG, SUMMARY_MIN, SUMMARY_MAX, SUMMARY_COUNTo handle de coluna (is_summary)
Lado de fixaçãoPIN_NONE, PIN_START, PIN_END (lógicos: START = margem de início de leitura)o handle de coluna (is_pin)

As constantes leem-se no objeto que as transporta: u_pbt_datagrid.SELECT_MULTIPLE para uma propriedade do componente, n_pbt_datagrid_column.PIN_START para uma propriedade de coluna.


Métodos #

Alimentar a grelha #

MétodoFunção
of_from_datastore (datastore ads)A ponte DataStore: lê as colunas (nome + tipo PowerBuilder, tipagem automática) e transfere todas as linhas numa só chamada, com o que o DataWindow diz de cada coluna — o seu texto de cabeçalho passa a ser o título, o seu formato de apresentação aplica-se, e uma tabela de códigos (Values, DropDown DataWindow, CheckBox) mostra o valor apresentado enquanto a linha mantém o dado. As colunas chegam pela ordem em que o DataWindow as mostra (o seu X), e uma coluna oculta no painter (Visible = 0) chega oculta: o utilizador volta a mostrá-la pelo botão Colunas. Um campo calculado não é uma coluna do DataStore: não chega; uma DropDown DataWindow cujo filho não tem linhas mostra os códigos. Volte a chamá-la após um Retrieve: as colunas mantêm o que lhes foi definido (título, célula rica, fixação, largura, total) e o seu lugar, o que o DataWindow diz (cabeçalho, formato, tabela de códigos) é relido, e cada valor chega sob a sua própria coluna, seja qual for a ordem que o utilizador lhes deu. A chave de cada linha é o seu RowID: não muda quando o DataStore ordena, filtra, insere ou elimina, e ids.GetRowFromRowId(Long(as_key)) é a linha que designa agora. Devolve 0 uma vez aplicado, -5 quando o DataStore não é válido ou não tem colunas, -2 quando o componente não está criado
of_add_column (string as_key, string as_title, string as_type)Adiciona uma coluna de largura automática, depois das outras: as que já existem mantêm o que lhes foi definido. Para alterar uma coluna depois, use o seu handle (of_column). Devolve 0 uma vez aplicado, -5 quando a chave está vazia, contém / ou `, ou nomeia uma coluna que a grelha já tem, -2` quando o componente não está criado
of_add_column (string as_key, string as_title, string as_type, long al_width)Idem, com uma largura em pixeis (0 = automática). Devolve 0 uma vez aplicado, -5 quando a chave está vazia, contém / ou `, ou nomeia uma coluna que a grelha já tem, -2` quando o componente não está criado
of_add_column (string as_key, string as_title, string as_type, long al_width, string as_renderer)Idem, com uma célula rica (RENDERER_*). Devolve 0 uma vez aplicado, -5 quando a chave está vazia, contém / ou `, ou nomeia uma coluna que a grelha já tem, -2` quando o componente não está criado
of_set_columns (string as_columns_json)Declara todas as colunas de uma só vez, com as respetivas opções detalhadas (formato, fixação, coluna modificável…). Os handles de coluna obtidos antes (of_column) são libertados: volte a obtê-los. Devolve 0 uma vez aplicado, -5 quando o texto não é um array JSON, -2 quando o componente não está criado
of_load_rows (string as_rows_json)Substitui as linhas apresentadas. O DataStore de um of_from_datastore anterior é esquecido: ib_write_back e of_reload_row deixam de o alcançar. Devolve 0 uma vez aplicado, -5 quando o texto não é um array JSON, -2 quando o componente não está criado
of_append_rows (string as_rows_json)Acrescenta linhas a seguir às linhas já apresentadas — deslocamento infinito, chegada em tempo real. Devolve 0 uma vez aplicado, -5 quando o texto não é um array JSON ou linhas dele foram deixadas de fora porque a grelha já tem a sua chave (as outras são acrescentadas), -2 quando o componente não está criado
of_update_row (string as_row_json)Substitui uma linha no lugar: aquela que tem a mesma chave _k. Devolve 0 uma vez aplicado, -5 quando o texto não é um objeto JSON ou a grelha não tem nenhuma linha com essa chave, -2 quando o componente não está criado
of_reload_row (long al_row)Volta a enviar uma linha do DataStore passado a of_from_datastore, lida agora: depois de o seu código a ter alterado. al_row é o seu número de linha hoje; a grelha encontra a linha pelo seu RowID, uma ordenação ou uma eliminação entretanto não mudam nada. Uma linha que a grelha ainda não tem (InsertRow, onde quer que seja) é adicionada depois das outras. Devolve 0 uma vez enviada, -5 quando nenhum DataStore está ligado ou a linha não existe, -2 quando o componente não está criado
of_reset_update ( )A chamar depois de o seu Update ter sido bem-sucedido: as células modificadas na grelha deixam de estar marcadas (um pequeno canto na cor de destaque). Devolve 0 uma vez enviado, -2 quando o componente não está criado
of_remove_row (string as_key)Remove uma linha, pela sua chave. Para uma linha de um DataStore a chave é o seu RowID: obtenha-a antes de ids.DeleteRow(ll_row), com String(ids.GetRowIdFromRow(ll_row)). Devolve 0 uma vez aplicado, -5 quando a grelha não tem nenhuma linha com esta chave, -2 quando o componente não está criado
of_clear_columns ( )Esvazia as colunas acumuladas por of_add_column, antes de reconstruir uma grelha. Os handles de coluna obtidos antes (of_column) são libertados: volte a obtê-los. Devolve 0 uma vez aplicado, -2 quando o componente não está criado

Colunas #

MétodoFunção
of_column (string as_key)O handle de uma coluna (n_pbt_datagrid_column): largura, fixação, ocultação, introdução, total, célula rica, posição, filtro — ver Propriedades de coluna

Ordenação, filtro, apresentação #

MétodoFunção
of_sort (string as_col, string as_dir)Ordena por uma só coluna: "asc", "desc" ou "none" (regresso à ordem carregada). Uma coluna com tabela de códigos ordena pelo seu dado, como um DataWindow. Várias colunas: of_sort("city A, revenue D"). Devolve 0 uma vez ordenado, -5 quando a grelha não tem essa coluna ou o sentido não é um dos três, -2 quando o componente não está criado
of_sort (string as_sort)Ordena por várias colunas, pela sua ordem: a primeira decide, as seguintes desempatam. as_sort escreve-se como o SetSort de um DataWindow o lê — "city A, revenue D"; asc e desc também são lidos, uma coluna sem sentido é crescente, e "" retira a ordenação (ordem carregada). Devolve 0 uma vez ordenado, -5 para uma coluna que a grelha não tem, outro sentido ou uma coluna nomeada duas vezes, -2 quando o componente não está criado
of_get_layout ( )O que o utilizador organizou, em JSON: as colunas pela sua ordem com largura, fixação e visibilidade, a ordenação (um array ordenado: "sort":[{"col":"city","dir":"asc"},{"col":"revenue","dir":"desc"}]), os filtros tal como escritos, a pesquisa rápida, o agrupamento e a linha de filtros. Para guardar (ficheiro, registo, tabela) e devolver a of_set_layout. Títulos, células ricas e formatos são seus: não constam dele
of_set_layout (string as_layout_json)Repõe uma disposição lida por of_get_layout ou recebida por ue_layout_changed. Uma coluna que não conhece (acrescentada entretanto) mantém o seu lugar depois das que ordena; uma coluna que nomeia e que já não existe é ignorada; é emitido ue_layout_changed, como em qualquer mudança da disposição. Uma ordenação escrita como objeto único ("sort":{"col":"city","dir":"asc"}) também é lida. Devolve 0 uma vez aplicada, -5 quando o texto está vazio ou não é um objeto JSON (um ficheiro truncado: nada é enviado), -2 quando o componente não está criado
of_clear_filters ( )Apaga o filtro rápido e todos os filtros por coluna. Devolve 0 uma vez aplicado, -2 quando o componente não está criado

Seleção, detalhe, exportação #

MétodoFunção
of_select_rows (string as_keys_json)Define a seleção a partir do seu código, por lista de chaves ('["1","4"]'); um array vazio anula toda a seleção, uma chave que a grelha não tem é deixada de fora. Como um clique, emite ue_selection_changed (nada se as mesmas linhas continuarem selecionadas). Devolve 0 uma vez aplicado, -5 quando o texto não é um array JSON, -2 quando o componente não está criado
of_selected_keys ( )Devolve as chaves selecionadas, como array JSON ('["1","4"]'), lidas na grelha no momento da chamada: uma seleção definida por of_select_rows, ou uma linha retirada entretanto, já é tida em conta
of_fill_detail (string as_key, string as_markup)Painel de detalhe de uma linha, em texto formatado. Devolve 0 uma vez aplicado, -5 quando a grelha não tem nenhuma linha com esta chave, -2 quando o componente não está criado
of_expand_row (string as_key) · of_collapse_row (string as_key)Expande / recolhe o painel de detalhe de uma linha; como o seu chevron, emite ue_row_expanded / ue_row_collapsed (nada se o painel já estiver nesse estado). Devolve 0 uma vez aplicado, -5 quando a grelha não tem nenhuma linha com esta chave, -2 quando o componente não está criado
of_expand_node (string as_key) · of_collapse_node (string as_key)Modo em árvore: expande / recolhe um nó (as linhas filhas levam _parent). Devolve 0 uma vez aplicado, -5 quando a grelha não tem nenhuma linha com esta chave, -2 quando o componente não está criado
of_export_csv (string as_path)Escreve o que a grelha mostra (filtros, ordenação, colunas visíveis) num ficheiro CSV: UTF-8 com BOM, separador ponto e vírgula — o gémeo da exportação do crosstab. A DLL escreve o ficheiro, ue_csv_saved confirma. Recusado sem licença. Devolve 0 uma vez pedido, -5 quando o caminho está vazio, -2 quando o componente não está criado
of_export_xlsx (string as_path)Escreve o que a grelha mostra (filtros, ordenação, colunas visíveis) num livro do Excel (.xlsx): os números continuam números, com o formato da sua coluna, a linha de cabeçalho a negrito. A DLL escreve o ficheiro, ue_xlsx_saved confirma; um caminho relativo é escrito na pasta onde a aplicação arrancou. Recusado sem licença e com uma fonte por janelas. Devolve 0 uma vez pedido, -5 quando o caminho está vazio, -2 quando o componente não está criado
of_add_row_menu_item (string as_key, string as_label)Acrescenta uma das suas entradas ao menu de contexto de linha, sob as integradas; a escolha volta em ue_row_menu_clicked com esta chave, uma etiqueta vazia mostra a chave. Devolve 0 uma vez acrescentada, -5 quando a chave está vazia, contém / ou ``, ou já é uma das suas entradas
of_add_row_menu_separator ( )Um separador entre dois grupos das suas entradas. Devolve 0
of_clear_row_menu ( )Retira as suas entradas: o menu de linha volta apenas às entradas integradas. Devolve 0 uma vez aplicado, -2 quando o componente não está criado

Volumes muito grandes #

MétodoFunção
of_open_source (long al_total)Declara uma origem de al_total linhas sem as construir: a grelha solicita apenas aquelas que tem de apresentar, através de ue_rows_needed. As chaves são então posições na sua origem; o DataStore de um of_from_datastore anterior é esquecido. A pesquisa rápida e a linha de filtros ficam ocultas (a grelha só tem as linhas no ecrã); uma ordenação escolhida pelo utilizador chega-lhe por ue_sort_changed: ordene a sua origem, a grelha volta a pedir as suas linhas. Devolve 0 uma vez aplicado, -2 quando o componente não está criado
of_supply_rows (long al_from, string as_rows_json)Resposta a ue_rows_needed: o lote de linhas é colocado a partir da linha al_from, contada a partir de 1 como as de um DataStore. Devolve 0 uma vez aplicado, -5 quando o texto não é um array JSON, -2 quando o componente não está criado
of_clear_source ( )Abandona o modo por janela e regressa às linhas carregadas em memória. Devolve 0 uma vez aplicado, -2 quando o componente não está criado
of_go_to_page (long al_page)Apresenta uma dada página (a primeira = 1). Sem efeito enquanto a paginação não for desencadeada. Devolve 0 uma vez aplicado, -2 quando o componente não está criado
of_supply_grand_totals (string as_values_json)Define o total geral, que o programador calcula: '{"ca":128400000,"quantity":51230}'. Uma cadeia vazia retira-o. Devolve 0 uma vez aplicado, -5 quando o texto não é um objeto JSON, -2 quando o componente não está criado

Comuns #

MétodoFunção
of_reset ( )Esvazia colunas e linhas, e repõe o componente no seu estado inicial. Devolve 0 uma vez aplicado, -2 quando o componente não está criado
of_set_redraw (boolean)Agrupa uma rajada de alterações numa única representação. Devolve 0
of_save_as_png (string) · of_save_as_jpg (string)Exporta a representação como imagem. Devolve 0 uma vez escrita a imagem, -2 não criado, -4 captura falhada, -5 caminho vazio

Eventos #

EventoAcionado quando
ue_row_clicked (string as_key)Uma linha é clicada
ue_row_dblclicked (string as_key, string as_col)Uma linha recebe um duplo clique: o gesto que abre uma ficha. as_col é a coluna sob o ponteiro. Numa célula modificável o duplo clique abre o editor e não lança este evento
ue_cell_clicked (string as_key, string as_col)Uma célula é clicada
ue_selection_changed (string as_keys_json)A seleção muda: um clique seleciona apenas essa linha, Ctrl+clique acrescenta ou retira uma, Shift+clique toma um intervalo, e of_select_rows faz o mesmo a partir do seu código; as_keys_json é o array JSON das chaves selecionadas ('["1","4"]'). Uma seleção que o seu código esvazia (um recarregamento, SELECT_NONE) também é dita
ue_sort_changed (string as_col, string as_dir, string as_sort)A ordenação mudou: um clique num cabeçalho (Shift+clique acrescenta uma coluna à ordenação), o menu de uma coluna, ou of_sort — uma ordem do código emite o evento como um gesto; nada quando a ordenação se mantém. as_col / as_dir: a coluna em causa e o seu sentido agora ("none" uma vez fora da ordenação); as_sort: a ordenação inteira, as colunas pela sua ordem, escrita como SetSort a lê ("city A, revenue D", "" para nenhuma). Com uma fonte em janela (of_open_source), ordene o seu DataStore com ela — ids.SetSort(as_sort) e depois ids.Sort(): a grelha volta então a pedir as suas linhas pela nova ordem
ue_action_clicked (string as_key, string as_col, string as_action)Um botão colocado numa célula (RENDERER_BUTTON) é clicado
ue_row_expanded (string as_key)Uma linha mestre-detalhe é expandida, pelo seu chevron ou por of_expand_row — o momento certo para alimentar o seu detalhe de imediato
ue_row_collapsed (string as_key)Uma linha mestre-detalhe é recolhida, pelo seu chevron ou por of_collapse_row
ue_detail_needed (string as_key)Com ib_detail_on_demand: uma linha que ainda não tem detalhe está a ser aberta (a sua seta, ou of_expand_row). Preencha-a aqui com of_fill_detail(as_key, …): o painel abre-se no regresso do evento; nada preenchido, a linha fica fechada
ue_filter_changed (string as_filters_json)O utilizador introduziu um filtro, na pesquisa rápida ou na linha de filtro por coluna (a pesquisa: quando a escrita para). as_filters_json diz cada filtro tal como escrito e a pesquisa — {"filters":{"revenue":"> 1000"},"quick":"bos"}: os textos que is_filter e is_quick_filter retomam tal como estão
ue_cell_edited (string as_key, string as_col, string as_value)Uma célula modificável é validada com um novo valor; as_value é esse valor em texto. Com ib_veto_edits, só depois de ue_cell_editing o ter aceitado. Com ib_write_back, um valor que o DataStore recusa não é mantido: a célula volta atrás, ue_write_back_failed diz porquê, e este evento não é emitido
ue_cell_editing (string as_key, string as_col, string as_value)Antes de um valor introduzido ser mantido, só se ib_veto_edits for verdadeiro. Devolva false para deixar o valor anterior na célula (ue_cell_edited não é então emitido); true por predefinição
ue_write_back_failed (string as_key, string as_col, string as_value, string as_reason)Com ib_write_back: o DataStore não pôde manter um valor introduzido (a sua linha eliminada desde o carregamento, um valor que SetItem recusa, um texto que não é uma hora). A célula retomou o que o DataStore tem e ue_cell_edited não foi emitido; as_reason diz porquê — para avisar o utilizador, ou recarregar a linha
ue_layout_changed (string as_layout_json)A disposição mudou, seja pelo utilizador ou pelo seu código: uma coluna redimensionada, deslocada, fixada ou ocultada, a ordenação, os filtros, a pesquisa rápida, o agrupamento, a linha de filtros — of_set_layout incluído. Nada é emitido quando nada muda. as_layout_json é a disposição inteira, tal como of_get_layout a devolve: guarde-a e depois devolva-a a of_set_layout
ue_rows_needed (long al_from, long al_to)Modo por janela: a grelha pede as linhas al_from a al_to, incluídas, contadas a partir de 1 — os números de linha de um DataStore. Responda com of_supply_rows
ue_page_changed (long al_page, long al_pages)A página apresentada muda, através dos botões de paginação ou de of_go_to_page. al_page é a página atual (a primeira = 1), al_pages o número total de páginas. Apenas informa: com uma origem por janelas as linhas da nova página são pedidas por ue_rows_needed — responda a esse, não aos dois
ue_csv_saved (string as_path, boolean ab_ok, string as_error)O CSV pedido por of_export_csv — ou pela entrada Exportar para CSV do menu de linha, que pede o ficheiro ao utilizador — foi escrito, ou não: ab_ok, e as_error diz porquê
ue_xlsx_saved (string as_path, boolean ab_ok, string as_error)O livro pedido por of_export_xlsx foi escrito — ou não: ab_ok, e as_error diz porquê. as_path é o ficheiro escrito, um caminho relativo resolvido
ue_copy (string as_tsv)O utilizador premiu Ctrl+C. as_tsv contém as linhas selecionadas com a respetiva linha de cabeçalho, ou apenas a célula com o foco quando nada está selecionado
ue_row_rclicked (string as_key, string as_col, long al_x, long al_y)Uma linha recebeu um clique direito (ou a tecla Menu / Shift+F10 premida sobre ela). Lançado quer o menu integrado esteja ativo quer não. al_x / al_y são píxeis de ecrã, não unidades PowerBuilder: para colocar o seu próprio menu onde o utilizador apontou, use PopMenu(PointerX(), PointerY()) na sua janela
ue_row_menu_clicked (string as_menu_key, string as_row_key, string as_keys_json)Uma das suas entradas (of_add_row_menu_item) foi escolhida: as_menu_key é a sua chave, as_row_key a linha sobre a qual o menu foi aberto; as_keys_json é a seleção inteira, sobre a qual uma ação de lote deve trabalhar
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 grelha integra a sua própria barra de ferramentas e os seus menus de cabeçalho. Nada disto exige código da sua parte:

Cada alteração da disposição volta em ue_layout_changed: larguras, ordem, colunas fixadas ou ocultas. Guarde-a e devolva-a com uma única chamada a of_set_layout na próxima abertura; of_get_layout relê-a a qualquer momento.

No teclado — a grelha é uma única paragem de tabulação. Uma vez alcançada, percorre-se inteiramente pelo teclado:

TeclaEfeito
SetasDeslocam a célula com o foco, célula a célula
Home / EndPrimeira / última coluna da linha
Ctrl+Home / Ctrl+EndPrimeira / última célula da grelha
Page Up / Page DownDeslocam-se um ecrã, seguindo a altura real da vista
Shift + setasEstendem a seleção a partir da âncora (modo SELECT_MULTIPLE)
EspaçoSeleciona ou desseleciona a linha com o foco e coloca aí a âncora; numa caixa de verificação editável, inverte-a
Enter ou F2Passa a célula a edição se a sua coluna for editável; uma caixa de verificação inverte-se de imediato
Um carácterNuma célula de texto ou número modificável, abre o editor com esse carácter, como uma folha de cálculo
Tab / Shift+Tab (em edição)Mantém o valor e abre a célula modificável seguinte (anterior), a linha seguinte no fim de uma linha
Ctrl+CCopia a seleção — ver ue_copy

A célula com o foco é contornada por um filete da cor de destaque e anunciada aos leitores de ecrã através de aria-activedescendant. O foco sobrevive ao deslocamento: sendo a grelha virtualizada, é mantido em memória e reposto após cada renderização. Desaparece, no entanto, se a sua linha sair da vista por uma ordenação ou um filtro.

⚠️ A área de transferência do navegador pode ser recusada numa WebView alojada. É por isso que ue_copy lhe devolve o texto: coloque-o você mesmo com ClipBoard(as_tsv) para ter a certeza do resultado.


Exemplos #

Contas de clientes em poucas linhas #

// ids : the accounts DataStore (see above). One repaint for the whole setup.
uo_grid.of_set_redraw(/*on*/ false)

// 1. The grid reads the columns (typed) and every row of the DataStore
uo_grid.of_from_datastore(/*ads*/ ids)

// 2. The titles are the header texts of the DataWindow ; rename one if you like
uo_grid.of_column(/*key*/ "rep").is_title = "Account manager"

// 3. Rich cells : an avatar, a coloured status, a gauge, a mini chart, stars
uo_grid.of_column(/*key*/ "rep").is_renderer = n_pbt_datagrid_column.RENDERER_AVATAR
uo_grid.of_column(/*key*/ "status").is_renderer = n_pbt_datagrid_column.RENDERER_CHIP
uo_grid.of_column(/*key*/ "status").is_tones = "Active=" + n_pbt_datagrid_column.TONE_SUCCESS + "|At risk=" + n_pbt_datagrid_column.TONE_DANGER
uo_grid.of_column(/*key*/ "pipeline").is_renderer = n_pbt_datagrid_column.RENDERER_PROGRESS
uo_grid.of_column(/*key*/ "trend").is_renderer = n_pbt_datagrid_column.RENDERER_SPARKLINE
uo_grid.of_column(/*key*/ "rating").is_renderer = n_pbt_datagrid_column.RENDERER_RATING

// A total, a column that stays in view, several rows selectable
uo_grid.of_column(/*key*/ "revenue").is_summary = n_pbt_datagrid_column.SUMMARY_SUM
uo_grid.of_column(/*key*/ "city").is_pin = n_pbt_datagrid_column.PIN_START
uo_grid.is_selection_mode = u_pbt_datagrid.SELECT_MULTIPLE
uo_grid.of_set_redraw(/*on*/ true)

Agrupar por estado e depois por cidade #

// The subtotal every group header shows
uo_grid.of_column(/*key*/ "revenue").is_summary = n_pbt_datagrid_column.SUMMARY_SUM

// Two levels : the status, then the city inside it ; "" goes back to a flat list
uo_grid.is_group_by = "status|city"

// The rating stays in view on the right
uo_grid.of_column(/*key*/ "rating").is_pin = n_pbt_datagrid_column.PIN_END

Filtrar a partir do seu código #

// The filter row under the headers : the user types in it
uo_grid.ib_filter_row = true

// Only the accounts in Paris, and only those above one million
uo_grid.is_quick_filter = "Paris"
uo_grid.of_column(/*key*/ "revenue").is_filter = "> 1000000"

Ordenar por várias colunas #

A ordenação escreve-se como a de um DataWindow: a primeira coluna decide, as seguintes desempatam. O utilizador faz o mesmo com o rato com Shift+clique nos cabeçalhos; um clique simples recomeça a partir de uma só coluna.

// City first, then the largest revenue in each city
uo_grid.of_sort(/*sort*/ "city A, revenue D")

O que a grelha lê na DataWindow #

of_from_datastore não leva só os dados: o texto de cabeçalho de cada coluna (<coluna>_t) torna-se o seu título, o seu formato de apresentação (Format, ou a máscara de um EditMask) aplica-se, e uma tabela de códigos — os Values de um Edit, de uma DDLB ou de botões de opção, uma DropDown DataWindow, uma CheckBox — mostra o valor apresentado (Active) enquanto a linha mantém o dado (A). Ordena-se e pesquisa-se sobre o que se vê; uma coluna com tabela de códigos edita-se através de uma lista, e volta o dado.

// The grid reads titles, formats and code tables in the DataWindow
uo_grid.of_from_datastore(/*ads*/ ids)

// A format of your own on one column, in the DataWindow's syntax
uo_grid.of_column(/*key*/ "revenue").is_format = "$#,##0.00;($#,##0.00)"

// The rating is picked in its code table (Poor to Excellent) ; the number goes into the DataStore
uo_grid.of_column(/*key*/ "rating").ib_editable = true
uo_grid.ib_write_back = true

// Your code changed a row of the DataStore : show it again
ids.SetItem(12, "rating", 5)
uo_grid.of_reload_row(/*row*/ 12)

Editar no próprio sítio, gravar no DataStore #

A grelha edita, o DataStore guarda a verdade: com ib_write_back, cada introdução é escrita nele na linha que a chave designa (o seu RowID, encontrado onde está), tipada pela coluna, antes de ue_cell_edited — e o indicador acompanha. Uma célula modificada mantém um pequeno canto na cor de destaque até of_reset_update.

// The pipelines can be edited : double-click, type a percentage, Enter
uo_grid.of_column(/*key*/ "pipeline").ib_editable = true

// Every edit goes into the DataStore itself, on the row the key designates
uo_grid.ib_write_back = true

Uma coluna booleana tornada editável (TYPE_BOOL, ou uma coluna CheckBox de um DataWindow lida por of_from_datastore) mostra uma verdadeira caixa de verificação em cada célula: um clique, Espaço, Enter ou F2 inverte-a de imediato — sem editor de texto, e um duplo clique não a inverte duas vezes. A célula recebe o valor do outro estado — true/false, ou os valores ON/OFF da CheckBox do DataWindow — pelo mesmo caminho que uma introdução: veto ib_veto_edits / ue_cell_editing, depois ue_cell_edited, marca «modificada» e ib_write_back. Só de leitura, uma coluna booleana mantém o seu visto ✓.

// A yes/no column the user ticks : a check box in every cell
uo_grid.of_add_column(/*key*/ "vip", /*title*/ "VIP", /*type*/ u_pbt_datagrid.TYPE_BOOL)
uo_grid.of_column(/*key*/ "vip").ib_editable = true
// Saving stays with the DataStore : when the user confirms
if ids.Update() = 1 then
	COMMIT USING SQLCA;

	// the edited cells are no longer marked as modified
	uo_grid.of_reset_update()
else
	ROLLBACK USING SQLCA;
end if

Uma linha expansível, escrita a partir do DataStore #

// Local variables
long ll_row

// A detail panel for the first 20 accounts, written from their DataStore row
for ll_row = 1 to 20
    uo_grid.of_fill_detail(/*key*/ String(ll_row), /*markup*/ "[b]" + ids.GetItemString(ll_row, "rep") + "[/b] follows the " + ids.GetItemString(ll_row, "city") + " account")
next

// The first one is open right away ; the chevron opens the others
uo_grid.of_expand_row(/*key*/ "1")

Páginas em vez de um deslocamento, e o total de tudo #

Uma vez paginada, a grelha só contém uma página: o seu rodapé totaliza a página. O total de todas as contas é o DataStore que o tem.

// Local variables
n_pbt_json lnv_totals
double ld_revenue
long ll_row

// Pages of 25 rows past 100 rows ; the footer totals the page
uo_grid.ii_page_size = 25
uo_grid.il_page_threshold = 100
uo_grid.of_column(/*key*/ "revenue").is_summary = n_pbt_datagrid_column.SUMMARY_SUM

// The grand total of ALL the accounts, from the DataStore
for ll_row = 1 to ids.RowCount()
    ld_revenue = ld_revenue + ids.GetItemDecimal(ll_row, "revenue")
next
lnv_totals.of_set_number(/*path*/ "revenue", /*value*/ ld_revenue)
uo_grid.of_supply_grand_totals(/*values_json*/ lnv_totals.of_text())

Uma origem que a grelha nunca contém inteira #

Para centenas de milhares de linhas, a grelha só conhece o seu número e pede as que mostra. É aqui que a sua aplicação lê da base de dados a fatia pedida; os números de linha começam em 1, como os do DataStore.

// The grid only learns HOW MANY rows exist ; it asks for the ones on screen
uo_grid.of_open_source(/*total*/ ids.RowCount())
// ue_rows_needed event of uo_grid : (long al_from, long al_to)
// Rows al_from to al_to, both included, counted from 1 like the DataStore
n_pbt_json lnv_row
string ls_rows
long ll_row

// One JSON row per DataStore row asked for, its key being the row number
ls_rows = "["
for ll_row = al_from to Min(al_to, ids.RowCount())
    lnv_row.of_clear()
    lnv_row.of_set_string(/*path*/ "_k", /*value*/ String(ll_row))
    lnv_row.of_set_string(/*path*/ "city", /*value*/ ids.GetItemString(ll_row, "city"))
    lnv_row.of_set_string(/*path*/ "rep", /*value*/ ids.GetItemString(ll_row, "rep"))
    lnv_row.of_set_string(/*path*/ "trend", /*value*/ ids.GetItemString(ll_row, "trend"))
    lnv_row.of_set_number(/*path*/ "revenue", /*value*/ Double(ids.GetItemDecimal(ll_row, "revenue")))
    if ll_row > al_from then ls_rows = ls_rows + ","
    ls_rows = ls_rows + lnv_row.of_text()
next
uo_grid.of_supply_rows(/*from*/ al_from, /*rows_json*/ ls_rows + "]")
// ue_sort_changed event of uo_grid : (string as_col, string as_dir, string as_sort)
// as_sort is the whole sort, written as SetSort reads it ("" for none) :
// sort the source with it, the grid then asks for its rows again
ids.SetSort(as_sort)
ids.Sort()

Exportar o que é mostrado #

// What is shown - filters, sort, visible columns - to a CSV file
uo_grid.of_export_csv(/*path*/ "C:\exports\accounts.csv")
// ue_csv_saved event of uo_grid : (string as_path, boolean ab_ok, string as_error)
if ab_ok then
    st_status.Text = "Written : " + as_path
else
    st_status.Text = as_error
end if

As suas entradas no menu de linha #

// The row menu, entry by entry
uo_grid.of_add_row_menu_item(/*key*/ "open", /*label*/ "Open the account")
uo_grid.of_add_row_menu_separator()
uo_grid.of_add_row_menu_item(/*key*/ "call", /*label*/ "Call the sales rep")
// ue_row_menu_clicked event of uo_grid : (string as_menu_key, string as_row_key, string as_keys_json)
choose case as_menu_key
    case "open"
        wf_open_account(Long(as_row_key))
    case "call"
        wf_call(ids.GetItemString(Long(as_row_key), "rep"))
end choose

Reagir à seleção #

// ue_selection_changed event of uo_grid : (string as_keys_json)
// '["3","7"]' : the RowIDs of the selected accounts (ids.GetRowFromRowId gives their rows)
cb_delete.Enabled = (Pos(as_keys_json, "[]") = 0)

Lembrar a disposição do utilizador #

// ue_layout_changed event of uo_grid : (string as_layout_json)
// Order, widths, pins, hidden columns, sort, filters, grouping : keep it
SetProfileString(gs_ini, "grids", "accounts", as_layout_json)
// open event of the window, once the grid is filled : the layout of last time
uo_grid.of_set_layout(/*layout_json*/ ProfileString(gs_ini, "grids", "accounts", ""))

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_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
of_set_property · of_get_property · of_component_nameControlar uma propriedade pelo nome3.1 O motor de propriedades

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