Presentazione grafica di una tabella di un bd

Chiedo scusa a tutti ma ho bisogno di un aiuto:
ho connesso il mio db mysql e da cosice riesco a leggere e scrivere nelle tabelle ma non so come presentare in una maschera una tabella affinch l’utente possa solo modificare i campi di alcune colonne… Che oggetto devo usare graficamente?
Tenete presente che sono alle prime armi con xojo…

Grazie infinite

si … non difficile
l’oggetto si chiama listbox
lo inserisci e gli dai un nome … io uso lista di solito …

poi … facciamo conto che ti servono 9 colonne ( da 0 a 8 )
imposti nella listbox il numero delle colonne.
poi nel campo columwidts imposti le dimensioni, ti mostro un esempio : 0,10%,,8%,8%,8%,10%,10%,10%
non fare caso al fatto che la somma delle percentuali supera 100%, la listbox ti mostrer la barra di scorrimento orizzontale
come vedi sulla seconda colonna trovi '
’ vuol dire… tutta la restante dimensione per quella colonna…

nel metodo dove visualizzi, oppure ne crei uno nuovo inserisci

lista.Heading(0) = “Id”
lista.Heading(1) = “Codice”
lista.Heading(2) = “Descrizione”
lista.Heading(3) = “Ord.”
lista.ColumnAlignment(3) = 3
lista.Heading(4) = “Rid”
lista.ColumnAlignment(4) = 3
lista.Heading(5) = “Nuovo”
lista.ColumnAlignment(5) = 3
lista.Heading(6) = “Conto Immob.”
lista.Heading(7) = “Fondo Ammort.”
lista.Heading(8) = “Costo Ammort.”

avrai notato che la colonna 3,4,5 ho inserito l’allineamento ( 3 sta per allineamento a destra )

oppure per impostare le intestazioni sempre dall’oggetto listbox nel campo ‘initialvalue’ metti i nomi delle colonne senza " iniziali e separate da TAB

Adesso andiamo a scrivere le righe

hai gi dichiarato il database
hai gi impostato la query
hai gi impostato il recordset

quindi avrai rsitem ad esempio che contiene il tuo recordset.

prima svuoto la listbox:

lista.deleteallrow
while not rsitem.eof
lista.addrow “” // metti in pratica una nuova riga vuota della listbox
lista.cell(lista.listcount -1,0) = rsitem.field(“id”).stringvalue
lista.cell(lista.listcount -1,1) = rsitem.field(“codice”).stringvalue
lista.cell(lista.listcount -1,2) = rsitem.field(“descrizione”).stringvalue
lista.cell(lista.listcount -1,3) = format(rsitem.field(“percord”).currencyvalue,"###,00")
lista.cell(lista.listcount -1,4) = format(rsitem.field(“percrid”).currencyvalue,"###,00")
lista.cell(lista.listcount -1,5) = format(rsitem.field(“percnuovo”).currencyvalue,"###,00")
lista.cell(lista.listcount -1,6) = rsitem.field(“contoimmobilizzazioni”).stringvalue
lista.cell(lista.listcount -1,7) = rsitem.field(“fondoammortamento”).stringvalue
lista.cell(lista.listcount -1,8) = rsitem.field(“costoammortamento”).stringvalue
rsitem.movenext // non dimenticarlo altrimenti vai in looop infinito
wend

Mi sembra semplice…

Se poi vuoi ordinare le colonne nell’evento comparerow della listbox inserisci :

select case column
case 3,4,5
  if  (CDbl(me.cell(row1,column)) > CDbl(me.cell(row2,column))) then
    Result = 1
  else
    result = -1
  end if
  Return true
case else
  return false
end select

se vuoi colorare le righe utilizzi l’evento ‘cellbackgroundpaint’

if (row mod 2)=0 then
  g.foreColor = rgb(237,243,254)
  g.fillrect 0,0,g.Width,g.height
end if

se vuoi inve colorare il testo della listbox nell’evento ‘celltextpaint’

if me.RowTag(row) = "rosso" then
  g.ForeColor = rgb(255,0,0) // red
end if

if me.RowTag(row) = "blu" then
  g.ForeColor = rgb(0,0,255) // blue
end if

if me.RowTag(row) = "verde" then
  g.ForeColor = rgb(50,100,30) // green
end if

if me.RowTag(row) = "viola" then
  g.ForeColor = rgb(255,0,255) // green
end if

per utilizzarlo in fase di riempimento della listbox :
while not …
lista.addrow “”
if rsitem.field(“prova”).integervalue = 1 then
lista.rowtag(lista.listcount -1) = “rosso”
elseif rsitem.field(“prova”).integervalue = 2 then
lista.rowtag(lista.listcount -1) = “blu”
elseif rsitem.field(“prova”).integervalue = 3 then
lista.rowtag(lista.listcount -1) = “verde”
elseif rsitem.field(“prova”).integervalue = 4 then
lista.rowtag(lista.listcount -1) = “viola”
end if

avrai notato che ho preferito utilizzare un ciclo IF / ENDIF al posto di SELECT CASE in quanto SELECT CASE pi lento ad elaborare le informazioni e se hai tanti record ci mette un pochino a riempire la listbox.

Spero di essere stato abbastanza chiaro.
Ciao, Massimiliano.

Mi dimenticavo, scusa, posta nel forum ‘Italiano’, sicuramente il moderatore sposter questo thread.

Grazie mille
davvero ottimo questo forum fatto di persone disponibili… con gente come te si apprende subito.
Spero in futuro di poter esser io di aiuto.

Grazie ancora

Ciao Alfredo,
io utilizzo il Listbox per presentare elenchi di record (esempio: voglio modificare i dati di un cliente, ma non ne conosco il codice. Presento un listbox che contiene le colonne più significative dei clienti, magari ordinato per ragione sociale, e magari con la possibilità di filtrare i record su uno o più campi).
Dal Listbox quindi scelgo il cliente che voglio gestire. La gestione vera e propria io la farei utilizzando una Window che conterrà dei TextField relativi ai campi che intendo far modificare all’utente.
Naturalmente sottoporrò i dati inseriti dall’utente al controllo di validità, segnalando le varie situazioni di errore: finchè ci sono errori non sarà possibile salvare il record.
Una cosa che ti consiglio è di utilizzare le classi per accedere/modificare/cancellare record da una tabella (ma occorre avere le conoscenze di programmazione ad oggetti che hai detto di non avere ancora).
Una buona documentazione è presente in questo link (spero che con l’inglese tu non abbia problemi) http://developer.xojo.com/userguide/object-oriented-programming

Per qualunque chiarimento/dubbio/approfondimento sono a tua disposizione.

Ok Alfredo, si … Nedi non ha tutti i torti, ho trovato comodo anche io utilizzare le classi per gestire i dati dal database.
Sono molto flessibili, e quando devi utilizzare gli stessi dati in giro per la tua applicazione vengono davvero comode.

Faccio un piccolo esempio la classe per gestire un semaforo sui record …
creo una classe vuota che chiamo tablelock
nella classe aggiungo due propriet, la prima la chiamo procredura, di tipo string, e la seconda un’array con il nome delle tabelle da bloccare, la chiamo tabelle() sempre di tipo string

creo un metodo che chiamo contructor

[code]Public Sub constructor(nomeprocedura as string)
procedura = nomeprocedura

End Sub
[/code]

e una seconda classe che chiamo destructor

Public Sub destructor() if tabelle.Ubound > -1 then // probabilmente non sono state sbloccate tutte le tabelle self.unlock end if End Sub

In realt constructor istanziato quando dichiaro una nuova classe di tipo ‘tablelock’ e destructor quando la distruggo.

Il metodo ‘addtable’ per aggiungere nuove tabelle alla classe

[code]Public Sub addtable(tabella as String)
// aggiunge una tabella all’array delle tabelle bloccate
tabelle.Append(tabella)

End Sub
[/code]

Ora la classe che effettua il lock delle tabelle, in realt va a scrivere su una tabella del db l’elenco delle tabelle che sono in sola lettura…

[code]if tabelle.Ubound < 0 then
Return true
exit Function
end if

// blocca una o pi tabelle
// se una di queste gi bloccata mi fermo
// e ritorno false

If Not app.db.Connected() then
koalamsgbox(app.msg_errore_aperturadatabase + ": " + app.db.errormessage,“Blocco Tabelle”)
Return false
exit Function
else
// 21/05/2014 Mods per codicepage Mysql
if app.db.type = “MySQL” then app.db.SQLExecute(“SET NAMES utf8 COLLATE utf8_general_ci; SET CHARACTER SET utf8”)
Dim sql As String

sql = “”
sql = sql + “SELECT * from semafori "
‘sql = sql + “WHERE utente = '” + app.utente + "’ "
if tabelle.Ubound > 0 then
sql = sql + “WHERE tabella in (”
sql = sql + “’” + join(tabelle(),”’,’") + “’”
sql = sql + “);”
else
sql = sql + “WHERE tabella = '” + tabelle(0) + "’ "
sql = sql + “AND utente <> '” + app.utente + “’;”
end if

dim rsitem as RecordSet

rsitem = app.db.SQLSelect(sql)

if app.db.Error then
koalamsgbox("Errore durante la selezione dei dati dalla tabella semafori : " + app.db.ErrorMessage,“Blocco Tabelle”)
Return false
exit Function
else

if rsitem.eof then 
  // perfetto non ho blocchi !!!
  // quindi andesso li metto 
  
  for contatore as integer = 0 to tabelle.Ubound
    dim row as new DatabaseRecord
    row.Column("utente") = app.utente
    row.Column("procedura") = procedura
    row.Column("tabella") = tabelle(contatore)
    row.Column("host") = gethostname()
    if app.db.type = "Sqlite" then app.db.sqlexecute("BEGIN Transaction;")
    app.db.InsertRecord("semafori",row)
    if app.db.Error then 
      koalamsgbox("Errore durante l'inserimento di un blocco nella tabella semafori : " + app.db.ErrorMessage,"Blocco Tabelle")
      Return false
      exit Function
    else
      app.db.Commit()
      if app.db.Error then 
        koalamsgbox("Errore durante l'apporto delle modifiche alla tabella semafori : " + app.db.ErrorMessage,"Blocco Tabelle")
        Return false
        exit Function
      end if
    end if
  next
  
  Return true
  exit Function
  
else
  dim msg as string
  msg = "Attenzione, alcune tabelle risultano impegnate : " + EndOfLine
  
  while not rsitem.eof
    msg = msg + "- " + rsitem.Field("utente").utfValue + ", Proc. : " + rsitem.Field("procedura").utfValue + EndOfLine
    rsitem.MoveNext
  wend
  
  msg = msg + "attendere qualche secondo e riprovare"
  koalamsgbox(msg,"Blocco Tabelle")
  Return false
end if

end if
end if

[/code]

koalamsgbox un messaggio di dialogo …
E ora il metodo unlock per elimanare dalla tabella dei semafori le tabelle che non sono pi bloccate.

[code]
If Not app.db.Connected() then
koalamsgbox(app.msg_errore_aperturadatabase + ": " + app.db.errormessage,“Blocco Tabelle”)
exit sub
else
// 21/05/2014 Mods per codicepage Mysql
if app.db.type = “MySQL” then app.db.SQLExecute(“SET NAMES utf8 COLLATE utf8_general_ci; SET CHARACTER SET utf8”)
Dim sql As String

sql = “”
sql = sql + “DELETE from semafori "
sql = sql + “WHERE utente = '” + app.utente + “’ "
if tabelle.Ubound > 0 then
sql = sql + “AND tabella in (”
sql = sql + “’” + Join(tabelle(),”’,’”) + “’”
sql = sql + “);”
else
sql = sql + “AND tabella = '” + tabelle(0) + “’;”
end if

if app.db.type = “Sqlite” then app.db.sqlexecute(“BEGIN Transaction;”)
app.db.SQLExecute(sql)

if app.db.Error then
koalamsgbox("Errore durante lo sbloccaggio delle tabelle : " + app.db.ErrorMessage,“Blocco Tabelle”)
exit sub
else
app.db.Commit
if app.db.Error then
koalamsgbox("Errore durante l’apporto delle modifiche alla tabella semafori : " + app.db.ErrorMessage,“Blocco Tabelle”)
exit sub
end if
end if
end if[/code]

come la uso.
mettiamo caso devo emettere una fattura e st salvando i dati …
avr diverse tabelle ( tante ) che devo bloccare per impedire ad altri utenti che utilizzano lo stesso programma di andare a fare casini con i dati .

quindi

dim dlock as new tablelock(“Emissione Documenti”)
dlock.addtable(“testedocumenti”)
dlock.addtable(“righedocumenti”)
dlock.addtable(“movimentimagazzino”)
dlock.addtable(“giacenze”)
dlock.addtable(“righe”)
dlock.addtable(“teste”)
dlock.addtable(“saldi”)
dlock.addtable(“scadenze”)
dlock.lock

… metto il codice per salvare la mia fattura, creare i movimenti di contabili, inserire i movimenti di magazzino, aggiornare saldi contabili, saldi di magazzino e creare le scadenze

dlock.unlock
dlock = NIL

oppure semplicemente
dlock = NIL ( hai presente abbiamo un metodo destructor che si istanzia proprio adesso )

Esattamente cosa fa questa classe
se una delle tabelle aggiunte non sono impegnate e quindi non sono a sola lettura mi consente di salvare un nuovo documento
se in caso contrario mi avvisa, blocca l’operazione di salvataggio perch la tabella e/o le tabelle sono impegnate.

Nella classe sopra descritta in realt st utilizzando altre classi inserite
app.db una classe di tipo koaladatabase, che mi permette di utilizzare pi tipi diversi di database nella mia applicazione
E funzioni che ho creato per fare prima …

utfValue ad esempio per salvare i dati nel formato UTF8 su db mysql per un problema di localizzazione ( se utilizzassimo la app in america non avremmo problemi )
Koalamsgbox una funzione che mostra una finestra di dialogo personalizzata, come msgbox

Listbox:

No:

lista.addrow "" // metti in pratica una nuova riga vuota della listbox lista.cell(lista.listcount -1,0) = rsitem.field("id").stringvalue

Si:

[code]Dim Loc_Row As Integer

lista.AddRow “” // Metti in pratica una nuova riga vuota della Listbox
Loc_Row = lista.ListIndex // Qual il numero della riga che ho appena aggiunto?
lista.cell(Loc_Row,0) = rsitem.field(“id”).stringvalue // Non necessario calcolare il numero di riga per ogni cella!
lista.cell(Loc_Row,1) = etc.[/code]

[quote=409681:@Emile Schwarz]Loc_Row = lista.ListIndex // Qual è il numero della riga che ho appena aggiunto?
[/code][/quote]

Emile, forse volevi dire Loc_Row = lista.LastIndex

allora fai prima con loc_row = lista.listcount -1;
Negli esempi di XOJO riportato lista.listcount -1;

ListCount-1 valido solo se fai add, vale a dire quando inserisci il dato come ultima riga
LastIndex valido sempre, sia come ultima riga che con insert, vale a dire quando lo inserisci