PBToolboxAI v4 ← Site

datagrid — u_pbt_datagrid #

← Referencia de componentes · Índice de la guía

La cuadrícula moderna de un DataStore: columnas tipadas y celdas enriquecidas, ordenación, filtros, agrupación con subtotales, edición en el sitio, paginación, origen por ventana y exportación CSV — el DataWindow sigue siendo el dueño de sus datos.

▶ Verlo en vivo — Aplicación de demostración, mosaico Data grid: la vista previa, el código que lo genera y esta página, uno al lado del otro.


De un vistazo #

Userobjectu_pbt_datagrid
Clase de itemsn_pbt_datagrid_column — una columna, alcanzada con of_column
Sirve paraPresentar un DataStore en una cuadrícula moderna — ordenación, filtros, agrupaciones, edición, volúmenes muy grandes — sin dejar su DataWindow
Límite en modo demo100 filas mostradas; exportaciones CSV y Excel desactivadas — véase el modo demo

El posicionamiento #

El datagrid no sustituye a la DataWindow: es una capa de presentación que se coloca encima. Usted conserva su SQL, sus Retrieve(), sus Update(), sus impresiones — y gana una cuadrícula moderna para la visualización.

Cubre dos puntos ciegos de la cuadrícula DataWindow clásica:

La conexión a la base de datos y la actualización quedan fuera del alcance: pertenecen a la DataWindow.

El DataStore de los ejemplos #

Todos los ejemplos de esta página — como los de la aplicación de demostración — parten del mismo DataStore de cuentas de clientes, una fila por cuenta: city, rep (el comercial), status, pipeline (un porcentaje), trend (siete cifras mensuales escritas "3,5,2,6,7,4,8"), revenue y rating (una nota sobre cinco). La cuadrícula se llama uo_grid en la ventana, el DataStore ids. Una fila cargada por of_from_datastore tiene como clave su RowID en el DataStore: no cambia cuando el DataStore ordena, filtra, inserta o elimina. Un evento se lo devuelve, e ids.GetRowFromRowId(Long(as_key)) es el número de la fila que designa ahora.

Un DataStore solo contiene valores simples, y basta para las celdas enriquecidas: un número es todo lo que necesitan un indicador (RENDERER_PROGRESS) y las estrellas (RENDERER_RATING), un nombre da un avatar, un texto "3,5,2,6" un minigráfico (RENDERER_SPARKLINE) igual que "vip, b2b" da etiquetas (RENDERER_TAGS); el color de una pastilla (RENDERER_CHIP) se da por valor con is_tones.


Inicio 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)))

Propiedades #

PropiedadTipoPredeterminadoFunción
is_selection_modestringSELECT_NONEModo de selección: ninguna, una fila, varias (Mayús = intervalo, Ctrl = alternar)
is_densitystringDENSITY_COMFORTABLEAltura de fila: cómoda o compacta
is_quick_filterstring""Filtro rápido global: solo conserva las filas cuyo texto — tal como se muestra (22/09/2026, 1.234,50) o en bruto — contiene este valor. Lo que el usuario teclea espera al final de la escritura; oculto con una fuente por ventanas
ib_filter_rowbooleanfalseMuestra la fila de entrada de filtro bajo los encabezados (equivalente del botón Filtros)
ib_context_menubooleantrueMenú contextual integrado en una fila: Copiar, Seleccionar todo, Borrar la selección, Exportar a CSV, más sus propias entradas (of_add_row_menu_item). Activo de forma predeterminada. Un clic derecho fuera de la selección la desplaza a la fila apuntada, un clic derecho dentro la conserva. A false para mostrar su propio menú desde ue_row_rclicked
ib_veto_editsbooleanfalsePregunta antes de conservar un valor introducido: emite ue_cell_editing, que puede rechazar — la celda conserva entonces su valor anterior
ib_write_backbooleanfalseEscribe cada entrada en el DataStore pasado a of_from_datastore — SetItem en la fila que la clave designa (su RowID, encontrado donde está), tipado por la columna (fechas, números, texto, códigos) — antes de ue_cell_edited. El Update sigue siendo suyo; una fecha o un número vaciados pasan a NULL, y un valor que el DataStore no puede conservar (una fila eliminada desde entonces, un valor que SetItem rechaza, un texto que no es una hora) no se conserva: la celda recupera lo que tiene el DataStore, ue_write_back_failed dice por qué, y ue_cell_edited no se emite. SetItem no aplica la regla Validation de la columna: compruebe un valor en ue_cell_editing (ib_veto_edits)
ib_detail_on_demandbooleanfalseDetalle a demanda: cada fila muestra su flecha, y abrirla (la flecha, o of_expand_row) emite ue_detail_needed — rellene ahí el panel con of_fill_detail, se abre al volver el evento. Nada rellenado: la fila sigue cerrada. El detalle de 5.000 filas nunca se lee por adelantado
is_group_bystring""Agrupa las filas por una o varias columnas, en orden, sus claves unidas por | ("status|city"); cada encabezado de grupo lleva los subtotales de las columnas que tienen un total. "" vuelve a una lista plana. Se relee en directo
ii_page_sizeinteger100Número de filas por página, una vez activada la paginación
il_page_thresholdlong50000Número de filas a partir del cual la cuadrícula pasa a páginas. 0 = paginar siempre, sea cual sea el volumen
is_theme_stylestring""Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio
is_theme_modestring""Variante clara u oscura (constantes THEME_MODE_*); vacío = la de la aplicación, seguida en cada cambio
il_theme_accentlong-1Color de acento de este componente (-1 = acento de la aplicación, o el del tema)
is_tooltipstring""Tooltip simple mostrado al pasar el ratón por el componente
is_super_tooltip_titlestring""Título del tooltip enriquecido (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto del tooltip enriquecido (se acepta el marcado enriquecido)
is_super_tooltip_imagestring""Imagen del tooltip enriquecido

Propiedades de columna #

Cada columna es un objeto en sí misma, obtenido mediante of_column("identificador") — el handle se crea en el primer acceso y sigue siendo válido después.

// 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
PropiedadTipoPredeterminadoFunción
is_titlestringla claveTexto de encabezado de la columna; "" vuelve a mostrar la clave. of_from_datastore deja los nombres de columna del DataWindow: nómbrelas aquí para el usuario
is_tonesstring""Color de una pastilla (RENDERER_CHIP) según su valor, para el texto de un DataStore: pares valor=tono unidos por | ("Active=success|At risk=danger"), tonos TONE_*; un valor no listado queda neutro
ii_widthintegerancho declaradoAncho de la columna, en píxeles
ib_hiddenbooleanfalseOculta o vuelve a mostrar la columna
is_pinstringPIN_NONEFija la columna a la izquierda o a la derecha: permanece visible durante el desplazamiento horizontal
ib_editablebooleanfalsePermite la entrada de datos: doble clic, escritura, Intro confirma, Esc cancela → ue_cell_edited. Un valor que no conviene a la columna (letras en un número) se muestra rechazado mientras se escribe, e Intro mantiene abierto el editor. Una columna booleana muestra una verdadera casilla de verificación: un clic, Espacio, Intro o F2 la invierte al instante. Escribir un carácter en una celda de texto o número abre el editor con ese carácter; durante una edición, Tab y Mayús+Tab conservan el valor y abren la celda modificable siguiente (anterior)
is_summarystringSUMMARY_NONETotal al pie de columna; SUMMARY_NONE lo retira. SUMMARY_COUNT cuenta las celdas que tienen un valor, como count() de un DataWindow
is_rendererstringRENDERER_NONECelda enriquecida aplicada a posteriori; RENDERER_NONE vuelve al texto. RENDERER_BOOL muestra una marca para un valor verdadero; RENDERER_CUSTOM lee el valor como texto enriquecido con etiquetas — para una columna que compone su código: un valor escrito por un usuario debe tener sus corchetes escapados ([[ ]])
ii_indexintegerorden de declaraciónPosición de la columna (primera posición = 1); una columna que la cuadrícula no tiene se relee 0
is_filterstring""Filtro por columna. El texto se busca en lo que la celda muestra (fecha formateada, número con máscara) o en su valor bruto; en una columna numérica se reconoce un operador inicial ("> 1000", "<= 50", "> 1,5" con el separador decimal del idioma), en una columna de fecha también ("> 22/09/2026", en el orden del idioma, o ISO). Cadena vacía = filtro retirado
is_formatstring""Formato de visualización, en la sintaxis de la DataWindow: "#,##0.00", "$#,##0;($#,##0)", "0.0%", "dd/mm/yyyy", "mmmm d, yyyy", "hh:mm", "@@@-@@@@". Como en una DataWindow, la coma y el punto designan los separadores del idioma. Cadena vacía = vuelve el formato de la DataWindow; se relee (el formato vigente)

Constantes #

Utilice siempre las constantes en lugar de las cadenas literales: el IDE las completa y una errata resulta imposible.

FamiliaConstantesPortadas por
Tipo de columnaTYPE_STRING, TYPE_NUMBER, TYPE_INT, TYPE_DATE, TYPE_DATETIME, TYPE_BOOLel componente (of_add_column)
Celda enriquecidaRENDERER_AVATAR, RENDERER_CHIP, RENDERER_PROGRESS, RENDERER_SPARKLINE, RENDERER_RATING, RENDERER_TAGS, RENDERER_BUTTON, RENDERER_LINK, RENDERER_BOOL, RENDERER_CUSTOMel componente y el handle de columna (is_renderer)
Celda enriquecida: ningunaRENDERER_NONEúnicamente el handle de columna (is_renderer)
Tono de pastillaTONE_SUCCESS, TONE_WARN, TONE_DANGER, TONE_INFO, TONE_NEUTRALel handle de columna (is_tones)
Modo de selecciónSELECT_NONE, SELECT_SINGLE, SELECT_MULTIPLEel componente (is_selection_mode)
DensidadDENSITY_COMFORTABLE, DENSITY_COMPACTel componente (is_density)
Total de pieSUMMARY_NONE, SUMMARY_SUM, SUMMARY_AVG, SUMMARY_MIN, SUMMARY_MAX, SUMMARY_COUNTel handle de columna (is_summary)
Lado de fijaciónPIN_NONE, PIN_START, PIN_END (lógicos: START = borde de inicio de lectura)el handle de columna (is_pin)

Las constantes se leen en el objeto que las lleva: u_pbt_datagrid.SELECT_MULTIPLE para una propiedad del componente, n_pbt_datagrid_column.PIN_START para una propiedad de columna.


Métodos #

Alimentar la cuadrícula #

MétodoFunción
of_from_datastore (datastore ads)El puente DataStore: lee las columnas (nombre + tipo PowerBuilder, tipado automático) y transfiere todas las filas en una sola llamada, con lo que el DataWindow dice de cada columna — su texto de encabezado pasa a ser el título, su formato de visualización se aplica, y una tabla de códigos (Values, DropDown DataWindow, CheckBox) muestra su valor visible mientras la fila conserva el dato. Las columnas llegan en el orden en que el DataWindow las muestra (su X), y una columna oculta en el painter (Visible = 0) llega oculta: el usuario la vuelve a mostrar con el botón Columnas. Un campo calculado no es una columna del DataStore: no llega; una DropDown DataWindow cuyo hijo no tiene filas muestra los códigos. Vuelva a llamarla tras un Retrieve: las columnas conservan lo que se les ha puesto (título, celda enriquecida, fijación, ancho, total) y su lugar, lo que dice el DataWindow (encabezado, formato, tabla de códigos) se vuelve a leer, y cada valor llega bajo su propia columna, sea cual sea el orden que el usuario les dio. La clave de cada fila es su RowID: no cambia cuando el DataStore ordena, filtra, inserta o elimina, e ids.GetRowFromRowId(Long(as_key)) es la fila que designa ahora. Devuelve 0 una vez aplicado, -5 cuando el DataStore no es válido o no tiene columnas, -2 cuando el componente no está creado
of_add_column (string as_key, string as_title, string as_type)Añade una columna de ancho automático, después de las demás: las que ya están conservan lo que se les ha puesto. Para cambiar una columna después, use su handle (of_column). Devuelve 0 una vez aplicado, -5 cuando la clave está vacía, contiene / o `, o nombra una columna que la cuadrícula ya tiene, -2` cuando el componente no está creado
of_add_column (string as_key, string as_title, string as_type, long al_width)Ídem, con un ancho en píxeles (0 = automático). Devuelve 0 una vez aplicado, -5 cuando la clave está vacía, contiene / o `, o nombra una columna que la cuadrícula ya tiene, -2` cuando el componente no está creado
of_add_column (string as_key, string as_title, string as_type, long al_width, string as_renderer)Ídem, con una celda enriquecida (RENDERER_*). Devuelve 0 una vez aplicado, -5 cuando la clave está vacía, contiene / o `, o nombra una columna que la cuadrícula ya tiene, -2` cuando el componente no está creado
of_set_columns (string as_columns_json)Declara todas las columnas de una vez, con sus opciones detalladas (formato, fijación, columna modificable…). Los handles de columna obtenidos antes (of_column) se liberan: vuelva a tomarlos. Devuelve 0 una vez aplicado, -5 cuando el texto no es un array JSON, -2 cuando el componente no está creado
of_load_rows (string as_rows_json)Sustituye las filas mostradas. El DataStore de un of_from_datastore anterior se olvida: ib_write_back y of_reload_row ya no lo alcanzan. Devuelve 0 una vez aplicado, -5 cuando el texto no es un array JSON, -2 cuando el componente no está creado
of_append_rows (string as_rows_json)Añade filas a continuación de las ya mostradas — desplazamiento infinito, llegada en tiempo real. Devuelve 0 una vez aplicado, -5 cuando el texto no es un array JSON o se descartaron filas porque la cuadrícula ya tiene su clave (las demás se añaden), -2 cuando el componente no está creado
of_update_row (string as_row_json)Sustituye una fila en su sitio: la que lleva la misma clave _k. Devuelve 0 una vez aplicado, -5 cuando el texto no es un objeto JSON o la cuadrícula no tiene ninguna fila con esa clave, -2 cuando el componente no está creado
of_reload_row (long al_row)Vuelve a enviar una fila del DataStore pasado a of_from_datastore, leída ahora: después de que su código la haya cambiado. al_row es su número de fila hoy; la cuadrícula encuentra la fila por su RowID, una ordenación o una eliminación entretanto no cambian nada. Una fila que la cuadrícula aún no tiene (InsertRow, donde sea) se añade después de las demás. Devuelve 0 una vez enviada, -5 cuando no hay ningún DataStore vinculado o la fila no existe, -2 cuando el componente no está creado
of_reset_update ( )Llámelo una vez que su Update haya tenido éxito: las celdas modificadas en la cuadrícula dejan de estar marcadas (una pequeña esquina en el color de acento). Devuelve 0 una vez enviado, -2 cuando el componente no está creado
of_remove_row (string as_key)Retira una fila, por su clave. Para una fila de un DataStore la clave es su RowID: tómela antes de ids.DeleteRow(ll_row), con String(ids.GetRowIdFromRow(ll_row)). Devuelve 0 una vez aplicado, -5 cuando la cuadrícula no tiene ninguna fila con esta clave, -2 cuando el componente no está creado
of_clear_columns ( )Vacía las columnas acumuladas por of_add_column, antes de reconstruir una cuadrícula. Los handles de columna obtenidos antes (of_column) se liberan: vuelva a tomarlos. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado

Columnas #

MétodoFunción
of_column (string as_key)El handle de una columna (n_pbt_datagrid_column): ancho, fijación, ocultación, entrada de datos, total, celda enriquecida, posición, filtro — véase Propiedades de columna

Ordenación, filtro, presentación #

MétodoFunción
of_sort (string as_col, string as_dir)Ordena por una sola columna: "asc", "desc" o "none" (vuelta al orden cargado). Una columna con tabla de códigos ordena por su dato, como un DataWindow. Varias columnas: of_sort("city A, revenue D"). Devuelve 0 una vez ordenado, -5 cuando la cuadrícula no tiene esa columna o el sentido no es uno de los tres, -2 cuando el componente no está creado
of_sort (string as_sort)Ordena por varias columnas, en su orden: la primera decide, las siguientes deshacen sus empates. as_sort se escribe como lo lee el SetSort de un DataWindow — "city A, revenue D"; también se leen asc y desc, una columna sin sentido es ascendente, y "" quita la ordenación (orden cargado). Devuelve 0 una vez ordenado, -5 para una columna que la cuadrícula no tiene, otro sentido o una columna nombrada dos veces, -2 cuando el componente no está creado
of_get_layout ( )Lo que el usuario ha organizado, en JSON: las columnas en su orden con ancho, fijación y visibilidad, la ordenación (un array ordenado: "sort":[{"col":"city","dir":"asc"},{"col":"revenue","dir":"desc"}]), los filtros tal como se escribieron, la búsqueda rápida, la agrupación y la fila de filtros. Para guardar (archivo, registro, tabla) y devolver a of_set_layout. Títulos, celdas enriquecidas y formatos son suyos: no figuran en él
of_set_layout (string as_layout_json)Restablece una disposición leída por of_get_layout o recibida mediante ue_layout_changed. Una columna que no conoce (añadida desde entonces) conserva su lugar tras las que ordena; una columna que nombra y que ya no existe se ignora; se emite ue_layout_changed, como en todo cambio de la disposición. Una ordenación escrita como objeto único ("sort":{"col":"city","dir":"asc"}) también se lee. Devuelve 0 una vez aplicada, -5 cuando el texto está vacío o no es un objeto JSON (un archivo truncado: no se envía nada), -2 cuando el componente no está creado
of_clear_filters ( )Borra el filtro rápido y todos los filtros por columna. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado

Selección, detalle, exportación #

MétodoFunción
of_select_rows (string as_keys_json)Establece la selección desde su código, mediante una lista de claves ('["1","4"]'); un array vacío deselecciona todo, una clave que la cuadrícula no tiene se descarta. Como un clic, emite ue_selection_changed (nada si siguen seleccionadas las mismas filas). Devuelve 0 una vez aplicado, -5 cuando el texto no es un array JSON, -2 cuando el componente no está creado
of_selected_keys ( )Devuelve las claves seleccionadas, como array JSON ('["1","4"]'), leídas en la cuadrícula en el momento de la llamada: una selección establecida por of_select_rows, o una fila retirada desde entonces, ya se tiene en cuenta
of_fill_detail (string as_key, string as_markup)Panel de detalle de una fila, en texto enriquecido. Devuelve 0 una vez aplicado, -5 cuando la cuadrícula no tiene ninguna fila con esta clave, -2 cuando el componente no está creado
of_expand_row (string as_key) · of_collapse_row (string as_key)Despliega / pliega el panel de detalle de una fila; como su chevron, emite ue_row_expanded / ue_row_collapsed (nada si el panel ya está en ese estado). Devuelve 0 una vez aplicado, -5 cuando la cuadrícula no tiene ninguna fila con esta clave, -2 cuando el componente no está creado
of_expand_node (string as_key) · of_collapse_node (string as_key)Modo árbol: despliega / pliega un nodo (las filas hijas llevan _parent). Devuelve 0 una vez aplicado, -5 cuando la cuadrícula no tiene ninguna fila con esta clave, -2 cuando el componente no está creado
of_export_csv (string as_path)Escribe lo que la cuadrícula muestra (filtros, orden, columnas visibles) en un archivo CSV: UTF-8 con BOM, separador punto y coma — el gemelo de la exportación del crosstab. La DLL escribe el archivo, ue_csv_saved lo confirma. Rechazado sin licencia. Devuelve 0 una vez pedido, -5 cuando la ruta está vacía, -2 cuando el componente no está creado
of_export_xlsx (string as_path)Escribe lo que la cuadrícula muestra (filtros, orden, columnas visibles) en un libro de Excel (.xlsx): los números siguen siendo números, con el formato de su columna, la fila de encabezado en negrita. La DLL escribe el archivo, ue_xlsx_saved lo confirma; una ruta relativa se escribe en la carpeta donde arrancó la aplicación. Rechazado sin licencia y con una fuente por ventanas. Devuelve 0 una vez pedido, -5 cuando la ruta está vacía, -2 cuando el componente no está creado
of_add_row_menu_item (string as_key, string as_label)Añade una de sus entradas al menú contextual de fila, bajo las integradas; la elección vuelve en ue_row_menu_clicked con esta clave, una etiqueta vacía muestra la clave. Devuelve 0 una vez añadida, -5 cuando la clave está vacía, contiene / o ``, o ya es una de sus entradas
of_add_row_menu_separator ( )Un separador entre dos grupos de sus entradas. Devuelve 0
of_clear_row_menu ( )Retira sus entradas: el menú de fila vuelve únicamente a las entradas integradas. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado

Volúmenes muy grandes #

MétodoFunción
of_open_source (long al_total)Declara una fuente de al_total filas sin construirlas: la cuadrícula solo reclama las que debe mostrar, mediante ue_rows_needed. Las claves son entonces posiciones en su fuente; el DataStore de un of_from_datastore anterior se olvida. La búsqueda rápida y la fila de filtros se ocultan (la cuadrícula solo tiene las filas en pantalla); una ordenación elegida por el usuario le llega por ue_sort_changed: ordene su fuente, la cuadrícula vuelve a pedir sus filas. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado
of_supply_rows (long al_from, string as_rows_json)Respuesta a ue_rows_needed: el lote de filas se coloca a partir de la fila al_from, contada desde 1 como las de un DataStore. Devuelve 0 una vez aplicado, -5 cuando el texto no es un array JSON, -2 cuando el componente no está creado
of_clear_source ( )Sale del modo con ventana y vuelve a las filas cargadas en memoria. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado
of_go_to_page (long al_page)Muestra una página determinada (la primera = 1). Sin efecto mientras la paginación no esté activada. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado
of_supply_grand_totals (string as_values_json)Establece el total general, que calcula usted: '{"ca":128400000,"quantity":51230}'. Una cadena vacía lo retira. Devuelve 0 una vez aplicado, -5 cuando el texto no es un objeto JSON, -2 cuando el componente no está creado

Comunes #

MétodoFunción
of_reset ( )Vacía columnas y filas, y devuelve el componente a su estado inicial. Devuelve 0 una vez aplicado, -2 cuando el componente no está creado
of_set_redraw (boolean)Agrupa una ráfaga de modificaciones en una sola representación. Devuelve 0
of_save_as_png (string) · of_save_as_jpg (string)Exporta la representación como imagen. Devuelve 0 una vez escrita la imagen, -2 no creado, -4 captura fallida, -5 ruta vacía

Eventos #

EventoSe activa cuando
ue_row_clicked (string as_key)Se hace clic en una fila
ue_row_dblclicked (string as_key, string as_col)Se hace doble clic en una fila: el gesto que abre una ficha. as_col es la columna bajo el puntero. En una celda modificable el doble clic abre el editor y no lanza este evento
ue_cell_clicked (string as_key, string as_col)Se hace clic en una celda
ue_selection_changed (string as_keys_json)La selección cambia: un clic selecciona solo esa fila, Ctrl+clic añade o quita una, Mayús+clic toma un intervalo, y of_select_rows hace lo mismo desde su código; as_keys_json es el array JSON de las claves seleccionadas ('["1","4"]'). También se avisa de una selección que su código vacía (una recarga, SELECT_NONE)
ue_sort_changed (string as_col, string as_dir, string as_sort)La ordenación ha cambiado: un clic en un encabezado (Mayús+clic añade una columna a la ordenación), el menú de una columna, o of_sort — una orden del código emite el evento como un gesto; nada cuando la ordenación sigue siendo la misma. as_col / as_dir: la columna de la que se trata y su sentido ahora ("none" una vez fuera de la ordenación); as_sort: la ordenación entera, las columnas en su orden, escrita como la lee SetSort ("city A, revenue D", "" para ninguna). Con una fuente por ventanas (of_open_source), ordene su DataStore con ella — ids.SetSort(as_sort) y luego ids.Sort(): la cuadrícula vuelve a pedir sus filas en el nuevo orden
ue_action_clicked (string as_key, string as_col, string as_action)Se hace clic en un botón colocado en una celda (RENDERER_BUTTON)
ue_row_expanded (string as_key)Una fila maestro-detalle se despliega, por su chevron o por of_expand_row — el buen momento para alimentar su detalle al vuelo
ue_row_collapsed (string as_key)Una fila maestro-detalle se repliega, por su chevron o por of_collapse_row
ue_detail_needed (string as_key)Con ib_detail_on_demand: se abre una fila que aún no tiene detalle (su flecha, o of_expand_row). Rellénela aquí con of_fill_detail(as_key, …): el panel se abre al volver el evento; nada rellenado, la fila sigue cerrada
ue_filter_changed (string as_filters_json)El usuario ha introducido un filtro, en la búsqueda rápida o en la fila de filtro por columna (la búsqueda: una vez terminada la escritura). as_filters_json dice cada filtro tal como se escribió y la búsqueda — {"filters":{"revenue":"> 1000"},"quick":"bos"}: los textos que is_filter e is_quick_filter retoman tal cual
ue_cell_edited (string as_key, string as_col, string as_value)Una celda modificable se confirma con un nuevo valor; as_value es ese valor en texto. Con ib_veto_edits, solo una vez que ue_cell_editing lo ha aceptado. Con ib_write_back, un valor que el DataStore rechaza no se conserva: la celda vuelve atrás, ue_write_back_failed dice por qué, y este evento no se emite
ue_cell_editing (string as_key, string as_col, string as_value)Antes de que se conserve un valor introducido, solo si ib_veto_edits es verdadero. Devuelva false para dejar el valor anterior en la celda (ue_cell_edited no se emite entonces); true por defecto
ue_write_back_failed (string as_key, string as_col, string as_value, string as_reason)Con ib_write_back: el DataStore no ha podido conservar un valor introducido (su fila eliminada desde la carga, un valor que SetItem rechaza, un texto que no es una hora). La celda ha recuperado lo que tiene el DataStore y ue_cell_edited no se ha emitido; as_reason dice por qué — para avisar al usuario, o recargar la fila
ue_layout_changed (string as_layout_json)La disposición ha cambiado, ya sea por el usuario o por su código: una columna redimensionada, desplazada, fijada u ocultada, la ordenación, los filtros, la búsqueda rápida, la agrupación, la fila de filtros — of_set_layout incluido. No se emite nada cuando nada cambia. as_layout_json es la disposición entera, tal como la devuelve of_get_layout: guárdela y luego devuélvala a of_set_layout
ue_rows_needed (long al_from, long al_to)Modo por ventana: la cuadrícula pide las filas al_from a al_to, incluidas, contadas desde 1 — los números de fila de un DataStore. Responda con of_supply_rows
ue_page_changed (long al_page, long al_pages)La página mostrada cambia, por los botones de paginación o por of_go_to_page. al_page es la página actual (la primera = 1), al_pages el número total de páginas. Solo informa: con una fuente por ventanas las filas de la nueva página las pide ue_rows_needed — responda a ese, no a los dos
ue_csv_saved (string as_path, boolean ab_ok, string as_error)El CSV pedido por of_export_csv — o por la entrada Exportar a CSV del menú de fila, que pide el archivo al usuario — se ha escrito, o no: ab_ok, y as_error dice por qué
ue_xlsx_saved (string as_path, boolean ab_ok, string as_error)El libro pedido por of_export_xlsx se ha escrito — o no: ab_ok, y as_error dice por qué. as_path es el archivo escrito, una ruta relativa resuelta
ue_copy (string as_tsv)El usuario ha pulsado Ctrl+C. as_tsv contiene las filas seleccionadas con su línea de encabezado, o únicamente la celda con el foco si no hay nada seleccionado
ue_row_rclicked (string as_key, string as_col, long al_x, long al_y)Una fila ha recibido un clic derecho (o la tecla Menú / Mayús+F10 pulsada sobre ella). Se lanza tanto si el menú integrado está activo como si no. al_x / al_y son píxeles de pantalla, no unidades PowerBuilder: para colocar su propio menú donde el usuario ha apuntado, use PopMenu(PointerX(), PointerY()) en su ventana
ue_row_menu_clicked (string as_menu_key, string as_row_key, string as_keys_json)Se ha elegido una de sus entradas (of_add_row_menu_item): as_menu_key es su clave, as_row_key la fila sobre la que se abrió el menú; as_keys_json es la selección entera, sobre la que debe trabajar una acción de lote
ue_ready ( )El componente ha terminado de cargarse; todo lo enviado antes se ha reproducido
ue_runtime_missing ( )El runtime WebView2 está ausente: el componente permanece vacío
ue_bg_color (long al_color)El componente ha calculado el color de fondo de su tema; el userobject ya lo ha adoptado (backcolor)

Lo que el usuario puede hacer sin una línea de código #

La cuadrícula incorpora su propia barra de herramientas y sus menús de encabezado. Nada de todo esto exige código por su parte:

Cada cambio de disposición vuelve en ue_layout_changed: anchos, orden, columnas fijadas u ocultas. Consérvelo y devuélvalo con una sola llamada a of_set_layout en la próxima apertura; of_get_layout lo relee en cualquier momento.

Con el teclado — la cuadrícula es una única parada de tabulación. Una vez alcanzada, se recorre enteramente con el teclado:

TeclaEfecto
FlechasDesplazan la celda con el foco, celda a celda
Inicio / FinPrimera / última columna de la fila
Ctrl+Inicio / Ctrl+FinPrimera / última celda de la cuadrícula
Re Pág / Av PágSe desplazan una pantalla, siguiendo la altura real de la vista
Mayús + flechasExtienden la selección desde el ancla (modo SELECT_MULTIPLE)
EspacioSelecciona o deselecciona la fila con el foco y coloca el ancla en ella; sobre una casilla editable, la invierte
Intro o F2Pone la celda en edición si su columna es editable; una casilla se invierte al instante
Un carácterEn una celda de texto o número modificable, abre el editor con ese carácter, como una hoja de cálculo
Tab / Mayús+Tab (en edición)Conserva el valor y abre la celda modificable siguiente (anterior), la fila siguiente al final de una fila
Ctrl+CCopia la selección — véase ue_copy

La celda con el foco está rodeada por un filete del color de acento y se anuncia a los lectores de pantalla mediante aria-activedescendant. El foco sobrevive al desplazamiento: al estar la cuadrícula virtualizada, se mantiene en memoria y se vuelve a colocar tras cada renderizado. En cambio, desaparece si su fila sale de la vista por una ordenación o un filtro.

⚠️ El portapapeles del navegador puede ser rechazado en una WebView alojada. Por eso ue_copy le devuelve el texto: colóquelo usted mismo con ClipBoard(as_tsv) para estar seguro del resultado.


Ejemplos #

Cuentas de clientes en pocas líneas #

// 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 y luego por ciudad #

// 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 desde su 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 varias columnas #

La ordenación se escribe como la de un DataWindow: la primera columna decide, las siguientes desempatan. El usuario hace lo mismo con el ratón con Mayús+clic en los encabezados; un clic simple vuelve a empezar desde una sola columna.

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

Lo que la cuadrícula lee en la DataWindow #

of_from_datastore no toma solo los datos: el texto de encabezado de cada columna (<columna>_t) se convierte en su título, su formato de visualización (Format, o la máscara de un EditMask) se aplica, y una tabla de códigos — los Values de un Edit, de una DDLB o de botones de opción, una DropDown DataWindow, una CheckBox — muestra el valor visible (Active) mientras la fila conserva el dato (A). Se ordena y se busca sobre lo que se ve; una columna con tabla de códigos se edita mediante una lista, y vuelve el dato.

// 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 en el sitio, guardar en el DataStore #

La cuadrícula edita, el DataStore guarda la verdad: con ib_write_back, cada entrada se escribe en él en la fila que la clave designa (su RowID, encontrado donde está), tipada por la columna, antes de ue_cell_edited — y el indicador lo sigue. Una celda modificada conserva una pequeña esquina en el color de acento hasta 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

Una columna booleana hecha editable (TYPE_BOOL, o una columna CheckBox de un DataWindow leída por of_from_datastore) muestra una verdadera casilla de verificación en cada celda: un clic, Espacio, Intro o F2 la invierte al instante — sin editor de texto, y un doble clic no la invierte dos veces. La celda recibe el valor del otro estado — true/false, o los valores ON/OFF de la CheckBox del DataWindow — por el mismo camino que una entrada: veto ib_veto_edits / ue_cell_editing, luego ue_cell_edited, marca «modificada» e ib_write_back. En solo lectura, una columna booleana conserva su marca ✓.

// 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

Una fila desplegable, escrita desde el 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 en lugar de un desplazamiento, y el total de todo #

Una vez paginada, la cuadrícula solo contiene una página: su pie totaliza la página. El total de todas las cuentas lo tiene el DataStore.

// 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())

Un origen que la cuadrícula nunca tiene entero #

Para cientos de miles de filas, la cuadrícula solo conoce su número y pide las que muestra. Es aquí donde su aplicación lee de la base el tramo pedido; los números de fila empiezan en 1, como los del 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 lo que se muestra #

// 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

Sus propias entradas en el menú de fila #

// 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

Reaccionar a la selección #

// 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)

Recordar la disposición del usuario #

// 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", ""))

Buenas prácticas #

Heredado de la base común #

Estos miembros existen en todos los componentes visuales — no son propios de este. Se detallan una sola vez, en los capítulos transversales; esta tabla solo dice dónde leerlos.

MiembrosFunciónDetallado en
of_count · of_keys_at · of_hasRecorrer lo que el componente contiene3.2 Los items
of_resetPoner el componente a cero3.6 Poner un componente a cero: of_reset()
of_register_shortcut · of_clear_shortcutsAtajos de teclado del componente3.5 Los atajos de teclado
of_is_created · of_is_ready · of_get_last_errorSi ha nacido, si está listo, qué ha fallado3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar el render como imagen3.8 Exportar la representación como imagen
of_set_redrawAgrupar los cambios en un solo repintado3.10 Buenas prácticas
of_preload_iconsIconos mostrados sin retardoVisualización instantánea: of_icon
of_set_translationTraducir una etiqueta del componente5.2 Adaptar una etiqueta: of_set_translation
of_focus_webviewDar el foco al componente6.4 Teclado y foco
of_print · of_print_to_pdfImprimir, o escribir un PDF6.9 Imprimir
of_set_property · of_get_property · of_component_nameControlar una propiedad por su nombre3.1 El motor de propiedades

Dos ayudas no se heredan: of_icon y of_escape_markup viven en n_pbt_utils. Declare uno — n_pbt_utils lnv_utils, nada que crear — y llámelas sobre él.

← Referencia de componentes · Índice de la guía