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 #
| Userobject | u_pbt_crosstab |
| Classe degli item | n_pbt_crosstab_field (un campo, tramite of_field) · n_pbt_crosstab_value (un valore dell'area Valori, tramite of_value) |
| Serve per | Offrire ai suoi utenti un'analisi incrociata dei suoi dati, che riorganizzano da soli, senza scrivere SQL né passare da Excel |
| Limite in modalità demo | 500 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.
| Area | Che cosa contiene | Effetto |
|---|---|---|
| Righe | Campi di raggruppamento | Un livello di righe per campo, comprimibile |
| Colonne | Campi di raggruppamento | Un livello di intestazioni di colonna per campo |
| Valori | Campi numerici e la loro aggregazione | Ciò che viene calcolato nelle celle |
| Filtri | Campi di selezione | Un 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 #
| Costante | Valore | Per |
|---|---|---|
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à | Tipo | Predefinito | Ruolo |
|---|---|---|---|
is_totals_position | string | "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_axis | string | "cols" | Orientamento delle misure quando ce n'è più di una: VALUES_COLS (affiancate in colonne, predefinito) o VALUES_ROWS (impilate in righe) |
is_currency_symbol | string | "" | 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_thousands | string | "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_list | boolean | true | Mostra il pannello dei campi, dove l'utente riorganizza la tabella con il mouse |
ib_row_subtotals | boolean | true | Mostra 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_subtotals | boolean | true | Mostra un subtotale per ogni gruppo di colonne |
ib_row_grand_total | boolean | true | Mostra la riga del totale generale sotto la tabella (la gemella di ib_col_grand_total) |
ib_col_grand_total | boolean | true | Mostra 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_headers | boolean | true | Ctrl+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_enabled | boolean | true | In 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_style | string | "" | Stile visivo del componente (costanti THEME_STYLE_*); vuoto = quello dell'applicazione, seguito a ogni cambio |
is_theme_mode | string | "" | Variante chiara o scura (costanti THEME_MODE_*); vuoto = quella dell'applicazione, seguita a ogni cambio |
il_theme_accent | long | -1 | Colore d'accento di questo componente (-1 = accento dell'applicazione, o quello del tema) |
is_tooltip | string | "" | Tooltip semplice mostrato al passaggio del mouse sul componente |
is_super_tooltip_title | string | "" | Titolo del tooltip avanzato (prevale su is_tooltip) |
is_super_tooltip_text | string | "" | Testo del tooltip avanzato (markup avanzato accettato) |
is_super_tooltip_image | string | "" | 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à | Tipo | Predefinito | Ruolo |
|---|---|---|---|
is_label | string | intestazione del DataWindow | Etichetta 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_show | string | "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_formatting | string | "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_format | string | Format della colonna | Formato 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à | Tipo | Predefinito | Ruolo |
|---|---|---|---|
is_agg | string | quella di of_add_value_field | Aggregazione di questo valore: una costante AGG_* del componente (uo_crosstab.AGG_AVG). Una misura calcolata non ne ha da scegliere: l'assegnazione è ignorata |
is_show | string | "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_formatting | string | "none" | Formattazione condizionale di questo valore: CF_NONE, CF_SCALE, CF_BARS, CF_ICONS |
is_format | string | Format della colonna | Formato 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_red | boolean | false | I 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_label | string | "" | Etichetta di questo valore nelle intestazioni (« Quota delle vendite »); vuoto ripristina quella d'origine, l'aggregazione e l'etichetta del campo (« Somma di Importo ») |
| Metodo | Ruolo |
|---|---|
of_field ( ) → string | Il 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 #
| Metodo | Ruolo |
|---|---|
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_value | Restituisce 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 ( ) → long | Il 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 #
| Metodo | Ruolo |
|---|---|
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 #
| Metodo | Ruolo |
|---|---|
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.
| Metodo | Ruolo |
|---|---|
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 #
| Metodo | Ruolo | |
|---|---|---|
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 #
| Metodo | Ruolo |
|---|---|
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 ( ) → string | Restituisce 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[]) → long | Le 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 #
| Metodo | Ruolo |
|---|---|
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 #
| Event | Attivato 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ò:
- trascinare un campo da un'area all'altra e riorganizzare l'incrocio a piacimento;
- cambiare l'aggregazione di una misura (somma, media, conteggio…);
- filtrare i valori di un campo tramite un elenco con caselle di spunta;
- comprimere o espandere un gruppo di righe o di colonne;
- ordinare da un'intestazione;
- selezionare e poi copiare un blocco di celle, con le sue intestazioni perché un incolla in un foglio di calcolo dica che cosa sono le cifre (
ib_copy_headers).
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 #
- Chiami
of_from_datastoreuna sola volta per insieme di dati: riorganizzare la tabella in seguito non costa nulla, ritrasmettere i dati costa caro. - Imposti le etichette (
of_field("...").is_label) subito dopoof_from_datastore: seguono il campo dappertutto, anche nel pannello dei campi e nelle esportazioni. - Filtri lato SQL ciò che non è destinato a essere analizzato: il crosstab è rapido, ma un DataStore due volte più piccolo si apre due volte più in fretta.
of_clear_layout()svuota le aree senza ritrasmettere i dati: è la chiamata giusta per proporre più analisi sulla stessa origine.- Un campo data si incrocia sempre tramite
of_group_date_field, mai direttamente. - Lasci il pannello dei campi visibile sulle schermate di analisi, lo nasconda sui cruscotti fissi.
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.
| Membri | Ruolo | Descritto in |
|---|---|---|
of_count · of_keys_at · of_has | Percorrere ciò che il componente contiene | 3.2 Gli item |
of_reset | Riportare il componente a zero | 3.6 Riportare un componente a zero: of_reset() |
of_set_property · of_get_property · of_component_name | Pilotare una proprietà per nome | 3.1 Il motore delle proprietà |
is_accessible_name · is_accessible_description | Il nome e la descrizione che dice un lettore di schermo | 3.4 Proprietà ed event opzionali |
of_register_shortcut · of_clear_shortcuts | Scorciatoie da tastiera del componente | 3.5 Le scorciatoie da tastiera |
of_is_created · of_is_ready · of_get_last_error | Se è nato, se è pronto, cosa è fallito | 3.7 Diagnostica |
of_save_as_png · of_save_as_jpg | Esportare il rendering in immagine | 3.8 Esportare il rendering come immagine |
of_set_redraw | Raggruppare le modifiche in un solo ridisegno | 3.10 Buone pratiche |
of_preload_icons | Icone mostrate senza ritardo | Visualizzazione istantanea: of_icon |
of_set_translation | Tradurre una dicitura del componente | 5.2 Adattare un'etichetta: of_set_translation |
of_focus_webview | Dare il focus al componente | 6.4 Tastiera e focus |
of_print · of_print_to_pdf | Stampare, o scrivere un PDF | 6.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.