PBToolboxAI v3 ← 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 item— (i campi si collocano tramite metodi)
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; esportazioni CSV ed Excel 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
datastore lds
lds = create datastore
lds.dataobject = "d_ventes"
lds.SetTransObject(SQLCA)
lds.Retrieve()

// 1. Trasmettere i dati: i campi sono dedotti dalle colonne
uo_croise.of_set_data(lds)

// 2. Distribuire i campi nelle aree
uo_croise.of_add_row_field(/*campo*/ "region")
uo_croise.of_add_col_field(/*campo*/ "annee")
uo_croise.of_add_value_field(/*campo*/ "montant", /*aggregazione*/ uo_croise.AGG_SUM)

// 3. Presentare: formato degli importi e totali generali
uo_croise.of_set_value_format(/*campo*/ "montant", /*decimali*/ 0, /*migliaia*/ "locale", /*simbolo*/ "$", /*simbolo_prima*/ true)
uo_croise.ib_row_grand_total = true
uo_croise.ib_col_grand_total = true
// event ue_cell_double_clicked di uo_croise: (string as_row_tuple_json, string as_col_tuple_json, double ad_value)
// L'utente vuole il dettaglio dietro una cifra: aprire l'elenco corrispondente.
of_ouvrir_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
AGG_SUM · AGG_COUNT · AGG_DISTINCT_COUNT"sum" "count" "dcount"of_add_value_field
AGG_AVG · AGG_MIN · AGG_MAX"avg" "min" "max"of_add_value_field

Le costanti di aggregazione si leggono sul componente: uo_croise.AGG_SUM. Quelle di un campo (SHOW_*, CF_*) si leggono sull'handle del campo.


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)
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)
ib_field_listbooleantrueMostra il pannello dei campi, dove l'utente riorganizza la tabella con il mouse
ib_row_subtotalsbooleantrueMostra un subtotale per ogni gruppo di righe
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)
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_stylestringfluentStile visivo del componente (costanti THEME_STYLE_*)
is_theme_modestringlightVariante chiara o scura (costanti THEME_MODE_*)
il_theme_accentlong-1Colore d'accento di questo componente (-1 = accento 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_labelstring""Etichetta leggibile del campo ("montant" → "Fatturato")
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) o CF_BARS (barre nella cella)

I valori di is_show e is_conditional_formatting sono disponibili anche come costanti sull'handle (SHOW_PCT_COL, CF_SCALE…).

n_pbt_crosstab_field lnv_champ

lnv_champ = uo_croise.of_field(/*campo*/ "montant")
lnv_champ.is_label = "Fatturato"
lnv_champ.is_conditional_formatting = lnv_champ.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.


Metodi #

Alimentare e denominare #

MetodoRuolo
of_set_data (datastore ads_data)Trasmette l'insieme di dati: i campi sono dedotti dalle colonne del DataStore, la loro etichetta dal testo di intestazione. 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_field (string as_field)Restituisce l'handle di un campo, per etichettarlo o formattarlo (vedere Proprietà di un campo)

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). Restituisce 0 una volta applicato, -2 se il componente non è creato
of_add_col_field (string as_field)Aggiunge un campo nell'area Colonne. Restituisce 0 una volta applicato, -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. Restituisce 0 una volta applicato, -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, -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, AGG_DISTINCT_COUNT (conteggio di valori distinti), AGG_AVG, AGG_MIN, AGG_MAX.

Totali e subtotali #

MetodoRuolo

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). Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_clear_member_filter (string as_field)Rimuove questo filtro. Restituisce 0 una volta applicato, -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: "top" (i primi ad_a), "gt", "lt", "between". ai_measure_index designa la misura interessata (la prima = 1). Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_clear_value_filter (string as_field)Rimuove questo filtro. Restituisce 0 una volta applicato, -2 se il componente non è creato
of_set_label_filter (string as_field, string as_type, double ad_a, double ad_b)Filtra sul valore del campo stesso: "gt", "lt", "between". Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_clear_label_filter (string as_field)Rimuove questo filtro. Restituisce 0 una volta applicato, -2 se il componente non è creato

Formattare #

MetodoRuolo
of_set_value_format (string as_field, integer ai_decimals, string as_thousands, string as_suffix { , boolean ab_symbol_before })Formato di una misura: numero di decimali (da 0 a 6), separatore delle migliaia ("locale", "space", "none"), simbolo — dopo il numero per impostazione predefinita (1 234 EUR), PRIMA quando ab_symbol_before è true ($1,234). Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_clear_value_format (string as_field)Ritorno al formato predefinito. Restituisce 0 una volta applicato, -2 se il componente non è creato
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 con un argomento non valido, -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 data: "year", "quarter" o "month". Entra nell'elenco dei campi e si usa come gli altri. Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_add_calc_field (string as_name, string as_label, string as_formula)Campo calcolato riga per riga ("[montant] * 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 applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_remove_calc_field (string as_name)Rimuove un campo calcolato. Restituisce 0 una volta applicato, -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. Restituisce 0 una volta applicato, -5 con un argomento non valido, -2 se il componente non è creato
of_remove_calc_measure (string as_name)Rimuove una misura calcolata. Restituisce 0 una volta applicato, -2 se il componente non è creato

Una formula accetta gli operatori + - * / ( ), numeri e campi tra parentesi quadre. 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. 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, -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. Restituisce 0 una volta applicato, -5 con un argomento non valido, -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. 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, formattazione compresa; ue_xlsx_saved conferma. 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)L'utente ha riorganizzato la tabella (spostato un campo, cambiato un'aggregazione, compresso un gruppo…)
ue_cell_double_clicked (string as_row_tuple_json, string as_col_tuple_json, double ad_value)Doppio clic su una cella: i primi due argomenti descrivono l'incrocio, il terzo il valore visualizzato. È 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): spetta a Lei metterla negli appunti
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 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. Ognuno di questi gesti è raggiungibile senza mouse: 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ì.


Esempi #

Un rapporto vendite completo #

// Righe: regione, poi citta all'interno di ogni regione
uo_croise.of_clear_layout()
uo_croise.of_add_row_field(/*campo*/ "region")
uo_croise.of_add_row_field(/*campo*/ "ville")

// Colonne: una per anno
uo_croise.of_add_col_field(/*campo*/ "annee")

// Celle: l'importo totale
uo_croise.of_add_value_field(/*campo*/ "montant", /*aggregazione*/ uo_croise.AGG_SUM)

// Presentazione: importi leggibili, subtotali e totali generali
uo_croise.of_set_value_format(/*campo*/ "montant", /*decimali*/ 0, /*migliaia*/ "locale", /*simbolo*/ "$", /*simbolo_prima*/ true)
uo_croise.ib_row_subtotals = true
uo_croise.ib_row_grand_total = true
uo_croise.ib_col_grand_total = true

// Colorare le celle per individuare i grandi importi a colpo d'occhio
uo_croise.of_field(/*campo*/ "montant").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_set_data.

uo_croise.of_set_data(lds)

uo_croise.of_field("region").is_label    = "Regione"
uo_croise.of_field("ville").is_label     = "Città"
uo_croise.of_field("categorie").is_label = "Categoria"
uo_croise.of_field("annee").is_label     = "Anno"
uo_croise.of_field("montant").is_label   = "Fatturato"
uo_croise.of_field("quantite").is_label  = "Quantità"

Analizzare quote anziché importi #

n_pbt_crosstab_field lnv_montant

uo_croise.of_clear_layout()
uo_croise.of_add_row_field(/*campo*/ "categorie")
uo_croise.of_add_col_field(/*campo*/ "annee")
uo_croise.of_add_value_field(/*campo*/ "montant", /*aggregazione*/ uo_croise.AGG_SUM)

// Tenere solo due categorie sullo schermo (valori separati da una tabulazione)
uo_croise.of_set_member_filter(/*campo*/ "categorie", /*valori*/ "Informatique~tMobilier")

lnv_montant = uo_croise.of_field(/*campo*/ "montant")

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

// Una piccola barra in ogni cella per confrontare le quote a colpo d'occhio
lnv_montant.is_conditional_formatting = lnv_montant.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.

uo_croise.of_clear_layout()
uo_croise.of_add_row_field(/*campo*/ "region")

// I due totali che serviranno da base al calcolo
uo_croise.of_add_value_field(/*campo*/ "montant",  /*aggregazione*/ uo_croise.AGG_SUM)
uo_croise.of_add_value_field(/*campo*/ "quantite", /*aggregazione*/ uo_croise.AGG_SUM)

// Prezzo medio = importo totale diviso per la quantita totale
uo_croise.of_add_calc_measure(/*nome*/ "prix_moyen", /*etichetta*/ "Prezzo medio", &
                              /*formula*/ "[montant] / [quantite]")
uo_croise.of_set_value_format(/*campo*/ "prix_moyen", /*decimali*/ 2, /*migliaia*/ "locale", /*simbolo*/ "$", /*simbolo_prima*/ true)

// Poi metterla tra i valori come qualsiasi campo (l'aggregato non conta: una misura si calcola)
uo_croise.of_add_value_field(/*campo*/ "prix_moyen", /*aggregato*/ uo_croise.AGG_SUM)
// event ue_calc_field_error di uo_croise: (string as_field, string as_message)
// Formula non valida: avvisare senza rompere nulla, la tabella resta visualizzata.
uo_statut.of_item("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 date_vente
uo_croise.of_group_date_field(/*campo*/ "date_vente", /*livello*/ "year")
uo_croise.of_group_date_field(/*campo*/ "date_vente", /*livello*/ "quarter")
uo_croise.of_group_date_field(/*campo*/ "date_vente", /*livello*/ "month")

// Poi incrociarli come qualsiasi altro campo: anno in colonne, trimestre sotto
uo_croise.of_add_col_field("date_vente__year")
uo_croise.of_add_col_field("date_vente__quarter")

La classifica delle dieci migliori regioni #

// Tenere solo le 10 regioni con il totale piu alto sulla prima misura
uo_croise.of_set_value_filter(/*campo*/ "region", /*tipo*/ "top", &
                              /*a*/ 10, /*b*/ 0, /*misura*/ 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_croise.of_export_xlsx("C:\temp\ventes.xlsx")
// event ue_xlsx_saved di uo_croise: (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_croise.of_export_csv(/*percorso*/ "C:\exports\ventes.csv")

Offrire viste salvate #

string ls_vue

// Salvare la vista corrente : of_get_layout risponde subito
ls_vue = uo_croise.of_get_layout()

// Conservare il contenuto COSI COM E : si riproduce senza trasformazioni.
of_enregistrer_vue(is_vue_courante, ls_vue)
// Piu tardi: riprodurre una vista salvata
uo_croise.of_set_layout(of_lire_vue("Ventes par region"))

Scendere al dettaglio dietro una cifra #

// event ue_cell_double_clicked di uo_croise: (string as_row_tuple_json, string as_col_tuple_json, double ad_value)
// I primi due argomenti descrivono l'incrocio (quali valori di righe,
// quali valori di colonne): quanto basta per ricostruire una query di dettaglio.
w_detail_ventes lw_detail

OpenWithParm(lw_detail, as_row_tuple_json + "|" + as_col_tuple_json)

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