PBToolboxAI v5 ← Site

crosstab — u_pbt_crosstab #

← Riferimento dei componenti · Sommario della guida

Tabella crosstab completa: aree righe / colonne / valori alimentate da un DataStore, aggregazioni, filtri, formattazione condizionale, raggruppamento di date, misure calcolate ed esportazioni CSV / Excel.

▶ Vederlo dal vivo — Applicazione dimostrativa, riquadro Crosstab: l'anteprima, il codice che lo produce e questa pagina, affiancati.


In breve #

Userobjectu_pbt_crosstab
Classe degli itemn_pbt_crosstab_field (un campo, tramite of_field) · n_pbt_crosstab_value (un valore dell'area Valori, tramite of_value)
Serve perOffrire ai suoi utenti un'analisi incrociata dei suoi dati, che riorganizzano da soli, senza scrivere SQL né passare da Excel
Limite in modalità demo500 righe di origine elaborate — of_get_cell_value e of_get_cell_rows leggono queste 500 righe, le stesse cifre dello schermo; esportazioni CSV ed Excel e copia (Ctrl+C) disattivate — vedere la modalità demo

Il principio #

Lei fornisce al componente un insieme di dati piatto — un DataStore, quindi qualsiasi query già scritta nella sua applicazione. Al resto pensa il crosstab: ne deduce l'elenco dei campi e Lei li distribuisce in quattro aree.

AreaChe cosa contieneEffetto
RigheCampi di raggruppamentoUn livello di righe per campo, comprimibile
ColonneCampi di raggruppamentoUn livello di intestazioni di colonna per campo
ValoriCampi numerici e la loro aggregazioneCiò che viene calcolato nelle celle
FiltriCampi di selezioneUn filtro sopra la tabella, applicato a tutto

Tutto il calcolo avviene nel componente: una volta trasmessi i dati, riorganizzare la tabella non provoca alcun viaggio di andata e ritorno verso il database né verso PowerBuilder.


Avvio rapido #

// event open della finestra
// Local variables
datastore lds
lds = create datastore
lds.dataobject = "d_sales"
lds.SetTransObject(SQLCA)
lds.Retrieve()

// 1. Trasmettere i dati: i campi sono dedotti dalle colonne
uo_crosstab.of_from_datastore(/*ads*/ lds)

// 2. Distribuire i campi nelle aree
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. Presentare: formato degli importi e totali generali
uo_crosstab.of_field(/*field*/ "amount").is_format = "$#,##0"
uo_crosstab.ib_row_grand_total = true
uo_crosstab.ib_col_grand_total = true
// event ue_cell_double_clicked di uo_crosstab: (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value)
// L'utente vuole il dettaglio dietro una cifra: aprire l'elenco corrispondente.
of_open_detail(as_row_tuple_json, as_col_tuple_json)

Costanti #

CostanteValorePer
TOTALS_BOTTOM · TOTALS_TOP"bottom" "top"is_totals_position
VALUES_COLS · VALUES_ROWS"cols" "rows"is_values_axis
THOUSANDS_LOCALE · THOUSANDS_SPACE · THOUSANDS_NONE"locale" "space" "none"is_thousands
AGG_SUM · AGG_COUNT · AGG_COUNT_ROWS · AGG_DISTINCT_COUNT"sum" "count" "countrows" "dcount"of_add_value_field · is_agg
AGG_AVG · AGG_MIN · AGG_MAX"avg" "min" "max"of_add_value_field · is_agg
VALUEFILTER_TOP · VALUEFILTER_BOTTOM"top" "bottom"of_set_value_filter
VALUEFILTER_GT · VALUEFILTER_LT · VALUEFILTER_BETWEEN"gt" "lt" "between"of_set_value_filter
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
LABEL_BEFORE · LABEL_AFTER"before" "after"of_set_label_filter
DATE_YEAR · DATE_QUARTER · DATE_MONTH"year" "quarter" "month"of_group_date_field

Le costanti di aggregazione, di filtro, di data e di separatore si leggono sul componente: uo_crosstab.AGG_SUM. Quelle di un campo o di un valore (SHOW_*, CF_*) si leggono sulla classe del suo handle: n_pbt_crosstab_field.CF_SCALE, n_pbt_crosstab_value.SHOW_PCT_GRAND. AGG_COUNT conta i valori non vuoti, come il Conteggio di Excel; AGG_COUNT_ROWS conta le righe, comprese quelle vuote.


Proprietà #

ProprietàTipoPredefinitoRuolo
is_totals_positionstring"bottom"Dove si colloca la riga del totale generale: TOTALS_BOTTOM (in fondo, predefinito) o TOTALS_TOP (in cima, subito sotto le intestazioni). Si sposta solo il totale generale: il subtotale di un gruppo resta sulla riga del gruppo
is_values_axisstring"cols"Orientamento delle misure quando ce n'è più di una: VALUES_COLS (affiancate in colonne, predefinito) o VALUES_ROWS (impilate in righe)
is_currency_symbolstring""La valuta che il menu Formato numero di un chip di valore propone, accanto a « Nessun simbolo » e « % ». Vuoto = quella della lingua di visualizzazione ($ in inglese, € altrove)
is_thousandsstring"locale"Separatore delle migliaia dei valori che non hanno un formato proprio (is_format vuoto e nessun Format sulla colonna del DataWindow) — la stessa impostazione del menu Opzioni della griglia: THOUSANDS_LOCALE (quello della lingua di visualizzazione, predefinito), THOUSANDS_SPACE, THOUSANDS_NONE, o il separatore stesso (",", ".", " ")
ib_field_listbooleantrueMostra il pannello dei campi, dove l'utente riorganizza la tabella con il mouse
ib_row_subtotalsbooleantrueMostra il subtotale di ogni gruppo di righe, scritto sulla riga del gruppo stesso, sopra i suoi membri; disattivato, quella riga conserva l'etichetta senza cifra
ib_col_subtotalsbooleantrueMostra un subtotale per ogni gruppo di colonne
ib_row_grand_totalbooleantrueMostra la riga del totale generale sotto la tabella (la gemella di ib_col_grand_total)
ib_col_grand_totalbooleantrueMostra la colonna del totale generale dopo la tabella (la gemella di ib_row_grand_total). Senza campo in Colonne non c'è colonna di totale — l'unica colonna di valori È il totale — e la proprietà conserva il suo valore per quando un campo vi entra. Con più misure, la colonna Totale ha un'intestazione « Totale » poi un'intestazione per misura, ordinabile
ib_copy_headersbooleantrueCtrl+C copia le intestazioni con le celle selezionate: i nomi delle colonne su una prima riga (la misura vi è nominata solo se la tabella la mostra: più valori, o nessun campo in Colonne) e il membro di ogni riga — il suo percorso intero, « Nord / Lille » — in una prima colonna, il cui angolo porta i nomi dei campi in righe (« region / ville »). Un incolla in un foglio di calcolo dice così che cosa sono le cifre. false copia le sole cifre. Letta in diretta, riportata a true da of_reset
ib_enabledbooleantrueIn grigio: la griglia mostra ancora le sue cifre — un crosstab vuoto non è la stessa cosa di uno spento dall'applicazione — ma smette di rispondere al puntatore
is_theme_stylestring""Stile visivo del componente (costanti THEME_STYLE_*); vuoto = quello dell'applicazione, seguito a ogni cambio
is_theme_modestring""Variante chiara o scura (costanti THEME_MODE_*); vuoto = quella dell'applicazione, seguita a ogni cambio
il_theme_accentlong-1Colore d'accento di questo componente (-1 = accento dell'applicazione, o quello del tema)
is_tooltipstring""Tooltip semplice mostrato al passaggio del mouse sul componente
is_super_tooltip_titlestring""Titolo del tooltip avanzato (prevale su is_tooltip)
is_super_tooltip_textstring""Testo del tooltip avanzato (markup avanzato accettato)
is_super_tooltip_imagestring""Immagine del tooltip avanzato

Proprietà di un campo #

of_field (string as_field) restituisce l'handle di un campo: lo recupera una volta, poi pilota il campo attraverso le sue proprietà. L'handle viene creato alla prima chiamata e riutilizzato in seguito.

ProprietàTipoPredefinitoRuolo
is_labelstringintestazione del DataWindowEtichetta leggibile del campo ("amount" → "Fatturato"). Per impostazione predefinita il testo di intestazione della colonna nel DataWindow, altrimenti il suo nome; una stringa vuota lo ripristina. Posta dal suo codice, sopravvive a of_from_datastore
is_showstring"normal"Ciò che la cella visualizza: "normal", "pctGrand" (% del totale generale), "pctRow" (% della riga), "pctCol" (% della colonna), "running" (totale progressivo), "diff" (scarto rispetto al precedente)
is_conditional_formattingstring"none"Formattazione condizionale: CF_NONE, CF_SCALE (scala di colori), CF_BARS (barre nella cella) o CF_ICONS (una freccia per terzo: su, stabile, giù)
is_formatstringFormat della colonnaFormato di visualizzazione dei valori del campo, un formato di visualizzazione PowerBuilder ("#,##0.00", "$#,##0;($#,##0)", "0.0%"), scritto con i separatori della lingua di visualizzazione. Vuoto = il Format della colonna del DataWindow, letto da of_from_datastore; senza né l'uno né l'altro, is_thousands e al massimo due decimali. Riletta: il formato in vigore, quello posto altrimenti quello della colonna

I valori di is_show e is_conditional_formatting sono disponibili anche come costanti sull'handle (SHOW_PCT_COL, CF_SCALE…). Posti sul campo, is_show, is_conditional_formatting e is_format valgono per tutti i suoi valori dell'area Valori e per quelli che vi entrano dopo — posti prima che il campo sia in Valori, vengono conservati, riletti così come posti e applicati al suo arrivo. Per un solo valore (lo stesso campo due volte: l'importo, e la sua quota del totale), si usa l'handle del valore, qui sotto.

// Local variables
n_pbt_crosstab_field lnv_field

// Il campo importo : la sua etichetta e una scala di colori
lnv_field = uo_crosstab.of_field(/*field*/ "amount")
lnv_field.is_label = "Fatturato"
lnv_field.is_conditional_formatting = lnv_field.CF_SCALE

⚠️ Modifica non retrocompatibile. Questa proprietà si chiamava is_cf: l'abbreviazione non diceva nulla nel punto di chiamata. Il vecchio nome non esiste più: un codice che lo utilizza non compila. La sostituzione è meccanica: is_cf → is_conditional_formatting, senza alcun cambiamento di valori né di comportamento.

Proprietà di un valore #

of_value (integer ai_position) restituisce l'handle di un valore dell'area Valori, tramite la sua posizione (1 = il primo). Un campo può starvi due volte — l'importo, e la sua quota del totale generale — e ogni valore ha le sue impostazioni, che prevalgono su quelle del suo campo. L'handle designa una posizione: dopo of_remove_value, of_move_value, of_remove_field, of_remove_calc_measure, of_clear_layout o of_set_layout viene rilasciato — richieda of_value. Le sue costanti SHOW_* e CF_* sono quelle di n_pbt_crosstab_field.

ProprietàTipoPredefinitoRuolo
is_aggstringquella di of_add_value_fieldAggregazione di questo valore: una costante AGG_* del componente (uo_crosstab.AGG_AVG). Una misura calcolata non ne ha da scegliere: l'assegnazione è ignorata
is_showstring"normal"Ciò che le celle di questo valore mostrano: SHOW_NORMAL, SHOW_PCT_GRAND, SHOW_PCT_ROW, SHOW_PCT_COL, SHOW_RUNNING, SHOW_DIFF (come sul campo)
is_conditional_formattingstring"none"Formattazione condizionale di questo valore: CF_NONE, CF_SCALE, CF_BARS, CF_ICONS
is_formatstringFormat della colonnaFormato di visualizzazione di questo solo valore, un formato PowerBuilder ("#,##0.00", "$#,##0;($#,##0)"). Vuoto = il Format della colonna del DataWindow. Riletta: il formato in vigore
ib_negative_redbooleanfalseI numeri negativi di questo valore in rosso — sullo schermo e nell'esportazione Excel. La stessa impostazione della voce « Negativi in rosso » del menu del chip
is_labelstring""Etichetta di questo valore nelle intestazioni (« Quota delle vendite »); vuoto ripristina quella d'origine, l'aggregazione e l'etichetta del campo (« Somma di Importo »)
MetodoRuolo
of_field ( ) → stringIl campo che questo valore aggrega ("amount"); "" quando la posizione non contiene alcun valore
// Local variables
n_pbt_crosstab_value lnv_share, lnv_amount

// L'importo due volte in Valori : la somma, poi la sua quota del totale generale
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)

// Solo il secondo valore : la sua quota del totale generale, con la propria etichetta
lnv_share = uo_crosstab.of_value(/*position*/ 2)
lnv_share.is_show = n_pbt_crosstab_value.SHOW_PCT_GRAND
lnv_share.is_label = "Quota delle vendite"

// Il primo valore : due decimali, i negativi in rosso
lnv_amount = uo_crosstab.of_value(/*position*/ 1)
lnv_amount.is_format = "#,##0.00"
lnv_amount.ib_negative_red = true

Metodi #

Alimentare e denominare #

MetodoRuolo
of_from_datastore (datastore ads)Trasmette l'insieme di dati: i campi sono dedotti dalle colonne del DataStore, la loro etichetta dal testo di intestazione, il formato predefinito dei loro valori dal Format della colonna. Un testo che contiene una tabulazione o un a capo resta nella sua riga; un valore CHAR perde gli spazi di riempimento; un decimale si legge con il separatore della postazione; un valore vuoto (NULL, testo vuoto) è un solo membro (vuoto), messo per ultimo; le etichette poste con is_label sopravvivono al ricaricamento. Restituisce 0 una volta caricati i dati, -5 se il DataStore non è valido o non ha alcuna colonna, -2 se il componente non è creato
of_from_datastore (datawindow adw)Lo stesso caricamento da un DataWindow: la tabella incrociata legge le sue righe tramite un DataStore di lavoro che le condivide (ShareData, verificato) — ciò che il DataWindow mostra, la tabella lo incrocia. Restituisce 0, -5 quando adw non è valido, non ha colonne o non può condividere le sue righe (of_get_last_error dice quale), -2 quando il componente non è creato
of_from_datastore (datawindowchild adwc)Lo stesso caricamento da un DataWindowChild (un DataWindow a discesa). Stessi valori restituiti
of_field (string as_field)Restituisce l'handle di un campo, per etichettarlo o formattarlo (vedere Proprietà di un campo)
of_value (integer ai_position) → n_pbt_crosstab_valueRestituisce l'handle di un valore dell'area Valori, tramite la sua posizione (1 = il primo), per impostarne aggregazione, visualizzazione, formato o etichetta (vedere Proprietà di un valore)
of_value_count ( ) → longIl numero di valori dell'area Valori (un campo che vi sta due volte conta due volte); 0 quando l'area è vuota o il componente non è creato

Costruire la tabella #

MetodoRuolo
of_clear_layout ( )Svuota le quattro aree: la tabella torna vuota, i dati restano caricati. Restituisce 0 una volta applicato, -2 se il componente non è creato
of_add_row_field (string as_field)Aggiunge un campo nell'area Righe (l'ordine delle chiamate determina l'ordine dei livelli). Un campo già in Valori vi resta: può stare in entrambi (un conteggio distinto per membro). Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono o per una misura calcolata (va solo in Valori), -2 se il componente non è creato
of_add_col_field (string as_field)Aggiunge un campo nell'area Colonne. Un campo già in Valori vi resta: può stare in entrambi (un conteggio distinto per membro). Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono o per una misura calcolata (va solo in Valori), -2 se il componente non è creato
of_add_value_field (string as_field, string as_agg)Aggiunge una misura nell'area Valori, con la sua aggregazione (AGG_*, vuoto = AGG_SUM). Il campo conserva il suo posto in Righe, Colonne o Filtri. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono o un'altra aggregazione, -2 se il componente non è creato
of_add_filter_field (string as_field)Aggiunge un campo nell'area Filtri, sopra la tabella. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono o per una misura calcolata (va solo in Valori), -2 se il componente non è creato
of_remove_field (string as_field)Toglie un campo dalla tabella: da tutte le aree in cui si trova (Righe, Colonne, Filtri, e ciascuno dei suoi valori), con i suoi filtri — come « Rimuovi » dall'elenco dei campi. Il resto della disposizione resta com'è, e ue_layout_changed segnala quella nuova. Restituisce 0 una volta applicato, -4 quando il campo non è in nessuna area, -5 per un campo che i dati non contengono
of_remove_value (integer ai_position)Rimuove un valore dell'area Valori, tramite la sua posizione (la 2ª « Somma di Importo » mentre la 1ª resta); con l'ultimo valore di un campo posto in nessun altro luogo se ne vanno i suoi filtri. Restituisce 0 una volta applicato, -5 per una posizione senza valore, -2 se il componente non è creato
of_move_value (integer ai_from, integer ai_to)Sposta un valore dell'area Valori da una posizione a un'altra (1 = il primo): le sue impostazioni, i filtri e l'ordinamento che lo nominano lo seguono. Restituisce 0 una volta applicato, -5 per una posizione senza valore, -2 se il componente non è creato

Le aggregazioni accettate da of_add_value_field sono esposte dal componente come costanti: AGG_SUM (predefinito), AGG_COUNT (il numero di valori non vuoti, come il Conteggio di Excel), AGG_COUNT_ROWS (il numero di righe, comprese quelle vuote), AGG_DISTINCT_COUNT (conteggio di valori distinti, celle vuote ignorate come in Excel), AGG_AVG, AGG_MIN, AGG_MAX. Una somma senza alcun valore è una cella vuota, non 0; uno « scarto rispetto al precedente » in cui una delle due celle è vuota è vuoto anch'esso. Le percentuali si scrivono come le scrive la lingua di visualizzazione (57.9% in inglese, 57,9 % in francese).

Totali e subtotali #

I totali si impostano tramite proprietà, descritte sopra: ib_row_grand_total e ib_col_grand_total per i totali generali, ib_row_subtotals e ib_col_subtotals per i subtotali, is_totals_position per la posizione della riga del totale generale. Il menu Opzioni della griglia (l'ingranaggio) offre gli stessi quattro interruttori, una voce per asse: Riga del totale generale, Colonna del totale generale, Subtotali delle righe, Subtotali delle colonne.

Filtrare #

MetodoRuolo
of_set_member_filter (string as_field, string as_values_tab)Mantiene solo i valori elencati di un campo. I valori sono separati da tabulazioni (~t) e scritti come la griglia li conserva (vedere sotto la tabella); un elenco vuoto rimuove il filtro, come of_set_member_order. Un campo posto in nessuna area entra nell'area Filtri, perché il filtro si veda. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, -2 se il componente non è creato
of_clear_member_filter (string as_field)Rimuove questo filtro. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, -2 se il componente non è creato
of_set_value_filter (string as_field, string as_type, double ad_a, double ad_b, integer ai_measure_index)Filtra sul totale della misura n. ai_measure_index (la prima = 1): VALUEFILTER_TOP o VALUEFILTER_BOTTOM (i primi o gli ultimi ad_a), VALUEFILTER_GT, VALUEFILTER_LT (sopra, sotto ad_a), VALUEFILTER_BETWEEN (tra ad_a e ad_b). Su un campo posto sotto un altro della sua area, la classifica si fa all'interno di ciascun genitore (la città migliore di ogni regione); al primo livello, su tutta la tabella. I membri a pari merito con l'N-esimo restano tutti. Il campo deve stare in Righe o in Colonne. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, un altro tipo, un Top o un Bottom di meno di 1 membro o una posizione senza misura in Valori, -2 se il componente non è creato
of_clear_value_filter (string as_field)Rimuove questo filtro. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, -2 se il componente non è creato
of_set_label_filter (string as_field, string as_type, double ad_a, double ad_b)Filtro numerico sul valore del campo stesso: LABEL_GT, LABEL_LT, LABEL_BETWEEN. Un campo data prende dei giorni, tramite l'overload testo. Il campo deve stare in Righe o in Colonne. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, un altro tipo o un campo data, -2 se il componente non è creato
of_set_label_filter (string as_field, string as_type, string as_a, string as_b)Filtro testo sul valore del campo: LABEL_CONTAINS, LABEL_BEGINS, LABEL_ENDS (as_a, senza distinguere maiuscole e minuscole; as_b non serve). Su un campo data: LABEL_BEFORE, LABEL_AFTER (as_a, un giorno scritto yyyy-mm-dd) o LABEL_BETWEEN (as_a e as_b, giorni inclusi). Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, un tipo che non si addice al campo (LABEL_CONTAINS su una data, LABEL_BEFORE su un testo), un testo vuoto o un giorno che non lo è, -2 se il componente non è creato
of_clear_label_filter (string as_field)Rimuove questo filtro. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, -2 se il componente non è creato

I valori che of_set_member_filter e of_set_member_order attendono sono quelli che la griglia conserva, non sempre quelli che mostra: su un campo derivato da una data, un mese si scrive "01"…"12", un trimestre "1"…"4", un anno "2024"; un membro data non raggruppato si scrive yyyy-mm-dd. L'utente, da parte sua, trova il filtro di etichetta nel menu del chip di ogni campo — testo, numero o data.

Formattare #

Il formato di un valore si imposta tramite una proprietà: of_field("amount").is_format = "$#,##0.00" per tutti i valori di un campo, of_value(2).is_format per uno solo (vedere Proprietà di un campo e Proprietà di un valore). È un formato di visualizzazione PowerBuilder, letto dal motore di maschere della libreria; vuoto, il valore prende il Format della colonna del DataWindow. I negativi in rosso: of_value(n).ib_negative_red = true. Il separatore delle migliaia dei valori senza formato resta is_thousands, la valuta del menu del chip is_currency_symbol.

MetodoRuolo
of_set_member_order (string as_field, string as_values_tab)Ordine di visualizzazione imposto ai valori di un campo (separati da ~t); una stringa vuota ripristina l'ordine naturale. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, -2 se il componente non è creato

Date e campi calcolati #

MetodoRuolo
of_group_date_field (string as_field, string as_part)Crea un campo derivato da una colonna date, datetime o timestamp (un'ora sola non ha data da raggruppare): DATE_YEAR, DATE_QUARTER o DATE_MONTH, chiamato <colonna>__<parte>. Entra nell'elenco dei campi e si usa come gli altri. Restituisce 0 una volta applicato, -5 per un campo che i dati non contengono, un'altra parte o un campo che non contiene date (un testo, un'ora), -2 se il componente non è creato
of_add_calc_field (string as_name, string as_label, string as_formula)Campo calcolato riga per riga ("[amount] * 0.8" = il netto di ogni vendita, poi sommato come qualsiasi colonna), utilizzabile in qualsiasi area. Non per un rapporto di totali (prezzo medio): serve of_add_calc_measure. Restituisce 0 una volta creato, -5 per un nome o una formula vuoti, un nome che contiene / o `, un nome già preso da una colonna o una formula che non si compila — il motivo è allora in of_get_last_error, e ue_calc_field_error viene attivato —, -2` se il componente non è creato
of_remove_calc_field (string as_name)Rimuove un campo calcolato. Restituisce 0 una volta applicato, -5 se nessun campo calcolato ha questo nome, -2 se il componente non è creato
of_add_calc_measure (string as_name, string as_label, string as_formula)Misura calcolata cella per cella, sui totali ("[marge] / [ca]" = tasso di margine globale). Si colloca esclusivamente nell'area Valori. La sua formula cita solo campi di dati: un'altra misura calcolata è rifiutata. Stessi codici di of_add_calc_field: 0 una volta creata, -5 (il motivo in of_get_last_error, ue_calc_field_error attivato), -2 se il componente non è creato
of_remove_calc_measure (string as_name)Rimuove una misura calcolata. Restituisce 0 una volta applicato, -5 se nessuna misura calcolata ha questo nome, -2 se il componente non è creato

Una formula accetta gli operatori + - * / ( ), numeri (12, 0.5, .5, 1e3, sempre con il punto) e campi tra parentesi quadre; ^ non è un operatore. Una formula non valida attiva ue_calc_field_error — nulla va in crash.

Espandere, memorizzare, esportare #

MetodoRuolo
of_expand_all ( ) · of_collapse_all ( )Espande o comprime tutti i gruppi, di righe E di colonne. Restituisce 0 una volta applicato, -2 se il componente non è creato
of_expand_to_level (integer ai_level)Espande fino a un livello dato (1 = solo il primo livello). Restituisce 0 una volta applicato, -5 sotto 1, -2 se il componente non è creato
of_get_layout ( ) → stringRestituisce lo stato completo della tabella — da conservare così com'è, poi da riprodurre con of_set_layout
of_set_layout (string as_state_json)Ripristina uno stato ottenuto in precedenza (il JSON di of_get_layout o di ue_layout_changed, così com'è). ue_layout_changed segnala la nuova disposizione una volta, nulla se è quella già mostrata; gli handle dei valori vengono rilasciati. Restituisce 0 una volta applicato, -5 per un testo vuoto o che non è JSON, -2 se il componente non è creato
of_get_cell_value (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, ref double ad_value)Legge il valore di una cella, quello che la tabella mostra (0,8 sotto 80,0 %, il progressivo sotto un progressivo). La sua riga e la sua colonna sono i tuple forniti da ue_cell_double_clicked — {"region":"Nord","city":"Lille"}, un membro vuoto null, {} (o una stringa vuota) per il totale — e ai_measure è la posizione del valore nell'area Valori, a partire da 1. Un tuple nomina i campi della sua area a partire dal primo: {"region":"Nord"} è il subtotale di Nord. La risposta non dipende dalla visualizzazione: un ramo compresso o subtotali nascosti si leggono comunque. Restituisce 0 con il valore in ad_value (NULL per una cella senza valore), -4 quando la tabella non ha quella cella (un membro o un campo che non mostra lì) o non può essere letta ora — chiamata da un evento che la griglia ha attivato mentre un ordine di questo script era in attesa: of_get_last_error lo dice, legga dopo l'evento —, -5 per un tuple malformato o una posizione senza misura, -2 se il componente non è creato
of_get_cell_rows (string as_row_tuple_json, string as_col_tuple_json, ref long al_rows[]) → longLe righe del DataStore che una cella aggrega (drill-through): al_rows[] riceve i loro numeri di riga e viene restituito il loro numero. La cella si indirizza come per of_get_cell_value, senza misura — le stesse righe alimentano tutti i valori della cella. I numeri sono quelli che le righe hanno ora nel DataStore dato a of_from_datastore, anche dopo un ordinamento o un filtro di quel DataStore; contano solo le righe che passano tutti i filtri della tabella; in modalità demo le righe oltre il limite non sono usate, quindi non vengono date; una riga eliminata dopo il caricamento è omessa. Ricarichi la griglia dopo un Retrieve. Restituisce il numero (0 o più), -4 quando la tabella non ha quella cella o non può essere letta ora (vedere of_get_cell_value), -5 per un tuple malformato, -2 se il componente non è creato
of_export_csv (string as_path)Scrive un file CSV della vista corrente (UTF-8 con BOM, punto e virgola); ue_csv_saved conferma. I numeri prendono il separatore decimale della lingua di visualizzazione (la virgola in francese, tedesco, italiano, spagnolo, portoghese); un'etichetta che verrebbe letta come una formula (= + - @) è scritta preceduta da un apostrofo. Il gemello di of_export_xlsx. Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_export_xlsx (string as_path)Scrive un file Excel della tabella così come è visualizzata, formattazione compresa (negativi in rosso inclusi); ue_xlsx_saved conferma — o rifiuta con il motivo oltre 16 384 colonne o 1 048 576 righe, i limiti di un foglio Excel. Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato

Comuni #

MetodoRuolo
of_reset ( )Riporta il componente al suo stato iniziale. Restituisce 0 una volta applicato, -2 se il componente non è creato
of_set_redraw (boolean)Raggruppa una raffica di modifiche in un solo rendering. Restituisce 0 una volta applicato, -2 se il componente non è creato
of_save_as_png (string) · of_save_as_jpg (string)Esporta il rendering come immagine. Restituisce 0, -2 se il componente non è creato, -4 se la cattura non riesce, -5 con un percorso vuoto

Event #

EventAttivato quando
ue_layout_changed (string as_layout_json)La disposizione è cambiata — dall'utente (spostato un campo, cambiata un'aggregazione, ordinata una colonna, compresso un gruppo…) o dal codice: ogni ordine che cambia ciò che of_get_layout restituisce (of_set_layout compreso) lo attiva una volta, e una sola volta alla fine di una costruzione racchiusa tra of_set_redraw(false) … of_set_redraw(true); mai quando nulla cambia, né per of_reset. as_layout_json è tutto ciò che of_get_layout salva
ue_cell_double_clicked (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value)Doppio clic su una cella: i primi due argomenti descrivono l'incrocio ({"region":"Nord","city":"Lille"}, un membro vuoto vi vale null, {} per il totale), ai_measure la posizione del valore cliccato nell'area Valori, a partire da 1, e ad_value il valore che la cella mostra — 0.8 sotto « 80,0 % », il progressivo sotto un progressivo — oppure NULL per una cella vuota. I due tuple e ai_measure formano l'indirizzo che of_get_cell_value rilegge. È il punto di ingresso di un dettaglio
ue_csv_saved (string as_path, boolean ab_ok, string as_error)Il file CSV è stato scritto — oppure no, e as_error dice perché
ue_xlsx_saved (string as_path, boolean ab_ok, string as_error)Il file Excel è stato scritto — oppure no, e as_error dice perché
ue_calc_field_error (string as_field, string as_message)La formula di un campo o di una misura calcolata non è valida
ue_copy (string as_tsv)L'utente ha copiato una selezione di celle (Ctrl+C): la griglia ha già messo il testo negli appunti, l'evento le restituisce lo stesso testo — per registrarlo o riprenderlo altrove. as_tsv è un testo separato da tabulazioni che porta per impostazione predefinita le intestazioni — i nomi delle colonne su una prima riga, il membro di ogni riga (il suo percorso intero, « Nord / Lille ») in una prima colonna — o le sole cifre con ib_copy_headers = false. In modalità demo la copia è un'esportazione: rifiutata, e la griglia lo dice
ue_ready ( )Il componente ha terminato il caricamento; tutto ciò che è stato inviato prima è stato riprodotto
ue_runtime_missing ( )Il runtime WebView2 è assente: il componente resta vuoto
ue_bg_color (long al_color)Il componente ha calcolato il colore di sfondo del proprio tema; l'userobject lo ha già adottato (backcolor)

Che cosa può fare l'utente senza una riga di codice #

La tabella è viva: è tutto l'interesse del componente. Con il pannello dei campi visualizzato (ib_field_list = true), l'utente può:

Ognuna di queste manipolazioni, tranne la copia (che attiva ue_copy), viene segnalata in ue_layout_changed: unita a of_get_layout / of_set_layout, permette di offrire ai suoi utenti delle « viste salvate ».

Da tastiera. La costruzione della tabella si fa senza mouse — chip, menu, compressione e ordinamento: Tab porta su un campo, su un triangolo di chiusura o su un'intestazione ordinabile, Invio o Spazio lo attiva. Su un campo si apre il suo menu — quello che porta Aggiungi alle righe / alle colonne / ai valori / ai filtri e Rimuovi: tutta la costruzione della tabella passa di lì. Maiusc+F10 o il tasto Menu aprono anche questo menu, e il focus segue il campo appena spostato, anche in un'altra zona. Selezionare delle celle e copiarle (Ctrl+C) richiede oggi il mouse.


Esempi #

Un rapporto vendite completo #

// Righe: regione, poi citta all'interno di ogni regione
uo_crosstab.of_clear_layout()
uo_crosstab.of_add_row_field(/*field*/ "region")
uo_crosstab.of_add_row_field(/*field*/ "city")

// Colonne: una per anno
uo_crosstab.of_add_col_field(/*field*/ "year")

// Celle: l'importo totale
uo_crosstab.of_add_value_field(/*field*/ "amount", /*agg*/ uo_crosstab.AGG_SUM)

// Presentazione: importi leggibili, subtotali e totali generali
uo_crosstab.of_field(/*field*/ "amount").is_format = "$#,##0"
uo_crosstab.ib_row_subtotals = true
uo_crosstab.ib_row_grand_total = true
uo_crosstab.ib_col_grand_total = true

// Colorare le celle per individuare i grandi importi a colpo d'occhio
uo_crosstab.of_field(/*field*/ "amount").is_conditional_formatting = n_pbt_crosstab_field.CF_SCALE

Etichette leggibili #

Le sue colonne si chiamano spesso mt_ht o cd_reg. Le rinomini una volta per tutte, subito dopo of_from_datastore.

// Prima i dati : i campi prendono il nome delle colonne
uo_crosstab.of_from_datastore(/*ads*/ lds)

// Poi un'etichetta leggibile per ogni campo
uo_crosstab.of_field(/*field*/ "region").is_label    = "Regione"
uo_crosstab.of_field(/*field*/ "city").is_label     = "Città"
uo_crosstab.of_field(/*field*/ "category").is_label = "Categoria"
uo_crosstab.of_field(/*field*/ "year").is_label     = "Anno"
uo_crosstab.of_field(/*field*/ "amount").is_label   = "Fatturato"
uo_crosstab.of_field(/*field*/ "quantity").is_label  = "Quantità"

Analizzare quote anziché importi #

// Local variables
n_pbt_crosstab_field lnv_amount

// Ripartire da aree vuote, poi collocare i campi
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)

// Tenere solo due categorie sullo schermo (valori separati da una tabulazione)
uo_crosstab.of_set_member_filter(/*field*/ "category", /*values_tab*/ "Informatique~tMobilier")

// Il campo importo, per regolarne la visualizzazione
lnv_amount = uo_crosstab.of_field(/*field*/ "amount")

// Mostrare la quota di ogni cella nel totale della sua colonna
lnv_amount.is_show = lnv_amount.SHOW_PCT_COL

// Una piccola barra in ogni cella per confrontare le quote a colpo d'occhio
lnv_amount.is_conditional_formatting = lnv_amount.CF_BARS

Una misura tutta sua: il prezzo medio #

Una misura calcolata si valuta sui totali di ogni cella, non riga per riga: è ciò che rende corretto un rapporto.

// Ripartire da aree vuote, poi collocare i campi
uo_crosstab.of_clear_layout()
uo_crosstab.of_add_row_field(/*field*/ "region")

// I due totali che serviranno da base al calcolo
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)

// Prezzo medio = importo totale diviso per la quantita totale
uo_crosstab.of_add_calc_measure(/*name*/ "avg_price", /*label*/ "Prezzo medio", /*formula*/ "[amount] / [quantity]")
uo_crosstab.of_field(/*field*/ "avg_price").is_format = "$#,##0.00"

// Poi metterla tra i valori come qualsiasi campo (l'aggregato non conta: una misura si calcola)
uo_crosstab.of_add_value_field(/*field*/ "avg_price", /*agg*/ uo_crosstab.AGG_SUM)
// event ue_calc_field_error di uo_crosstab: (string as_field, string as_message)
// Formula non valida: avvisare senza rompere nulla, la tabella resta visualizzata.
uo_status.of_panel(/*key*/ "main").is_text = "Formula " + as_field + " : " + as_message

Analizzare per mese, trimestre o anno #

Una colonna data non si incrocia così com'è — ogni giorno formerebbe una riga a sé. Derivi prima il livello desiderato.

// Creare tre campi derivati dalla colonna sale_date
uo_crosstab.of_group_date_field(/*field*/ "sale_date", /*part*/ uo_crosstab.DATE_YEAR)
uo_crosstab.of_group_date_field(/*field*/ "sale_date", /*part*/ uo_crosstab.DATE_QUARTER)
uo_crosstab.of_group_date_field(/*field*/ "sale_date", /*part*/ uo_crosstab.DATE_MONTH)

// Poi incrociarli come qualsiasi altro campo: anno in colonne, trimestre sotto
uo_crosstab.of_add_col_field(/*field*/ "sale_date__year")
uo_crosstab.of_add_col_field(/*field*/ "sale_date__quarter")

La classifica delle dieci migliori regioni #

// Tenere solo le 10 regioni con il totale piu alto sulla prima misura
uo_crosstab.of_set_value_filter(/*field*/ "region", /*type*/ uo_crosstab.VALUEFILTER_TOP, /*a*/ 10, /*b*/ 0, /*measure_index*/ 1)

Su un campo posto sotto un altro, la classifica si fa all'interno di ciascun genitore: la città migliore di ogni regione, non la città migliore del paese. I pari merito restano tutti.

// Le citta sotto le regioni
uo_crosstab.of_add_row_field(/*field*/ "region")
uo_crosstab.of_add_row_field(/*field*/ "city")

// La citta migliore di ogni regione, sulla prima misura
uo_crosstab.of_set_value_filter(/*field*/ "city", /*type*/ uo_crosstab.VALUEFILTER_TOP, /*a*/ 1, /*b*/ 0, /*measure_index*/ 1)

Esportare #

L'esportazione riprende esattamente la vista corrente: stessi filtri, stessi totali, stessa formattazione.

// Verso Excel: il file viene scritto direttamente nel percorso indicato
uo_crosstab.of_export_xlsx(/*path*/ "C:\temp\ventes.xlsx")
// event ue_xlsx_saved di uo_crosstab: (string as_path, boolean ab_ok, string as_error)
// inv_notif = un n_pbt_toaster dichiarato come variabile d'istanza della finestra
if ab_ok then
    inv_notif.is_title = "Esportazione completata"
    inv_notif.is_text  = as_path
    inv_notif.is_kind  = inv_notif.KIND_SUCCESS
else
    inv_notif.is_title = "Esportazione impossibile"
    inv_notif.is_text  = as_error
    inv_notif.is_kind  = inv_notif.KIND_ERROR
end if
inv_notif.of_show()
// Verso CSV: un file, come per Excel; ue_csv_saved conferma
uo_crosstab.of_export_csv(/*path*/ "C:\exports\ventes.csv")

Offrire viste salvate #

// Local variables
string ls_view

// Salvare la vista corrente : of_get_layout risponde subito
ls_view = uo_crosstab.of_get_layout()

// Conservare il contenuto COSI COM E : si riproduce senza trasformazioni.
of_save_view(is_current_view, ls_view)
// Piu tardi: riprodurre una vista salvata
uo_crosstab.of_set_layout(/*state_json*/ of_read_view("Ventes par region"))

Scendere al dettaglio dietro una cifra #

// event ue_cell_double_clicked di uo_crosstab: (string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value)
// Local variables
long ll_rows[], ll_count, ll_i

// Le righe del DataStore dietro la cifra cliccata due volte
ll_count = uo_crosstab.of_get_cell_rows(/*row_tuple_json*/ as_row_tuple_json, /*col_tuple_json*/ as_col_tuple_json, /*rows*/ ll_rows)

// Niente da mostrare : nessuna riga, o una cella non leggibile ora
if ll_count <= 0 then return

// Copiarle nell'elenco di dettaglio : ids_sales e il DataStore dato a of_from_datastore
dw_detail.Reset()
for ll_i = 1 to ll_count
	ids_sales.RowsCopy(ll_rows[ll_i], ll_rows[ll_i], Primary!, dw_detail, dw_detail.RowCount() + 1, Primary!)
next

I due tuple e ai_measure formano l'indirizzo della cella: of_get_cell_value lo rilegge più tardi, così come la tabella lo mostra in quel 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

Una cella si legge anche senza clic, attraverso i suoi membri: un tuple parziale designa un subtotale. E of_remove_field toglie un campo da tutte le sue aree in un colpo solo, filtri compresi.

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

Buone pratiche #

Ereditato dalla base comune #

Questi membri esistono su tutti i componenti visivi — non sono propri di questo. Sono descritti una sola volta, nei capitoli trasversali; questa tabella dice solo dove leggerli.

MembriRuoloDescritto in
of_count · of_keys_at · of_hasPercorrere ciò che il componente contiene3.2 Gli item
of_resetRiportare il componente a zero3.6 Riportare un componente a zero: of_reset()
of_set_property · of_get_property · of_component_namePilotare una proprietà per nome3.1 Il motore delle proprietà
is_accessible_name · is_accessible_descriptionIl nome e la descrizione che dice un lettore di schermo3.4 Proprietà ed event opzionali
of_register_shortcut · of_clear_shortcutsScorciatoie da tastiera del componente3.5 Le scorciatoie da tastiera
of_is_created · of_is_ready · of_get_last_errorSe è nato, se è pronto, cosa è fallito3.7 Diagnostica
of_save_as_png · of_save_as_jpgEsportare il rendering in immagine3.8 Esportare il rendering come immagine
of_set_redrawRaggruppare le modifiche in un solo ridisegno3.10 Buone pratiche
of_preload_iconsIcone mostrate senza ritardoVisualizzazione istantanea: of_icon
of_set_translationTradurre una dicitura del componente5.2 Adattare un'etichetta: of_set_translation
of_focus_webviewDare il focus al componente6.4 Tastiera e focus
of_print · of_print_to_pdfStampare, o scrivere un PDF6.9 Stampare

Due aiuti non sono ereditati: of_icon e of_escape_markup vivono su n_pbt_utils. Ne dichiari uno — n_pbt_utils lnv_utils, niente da creare — e li chiami su di esso.


← Riferimento dei componenti · Sommario della guida