Newsgroup: it.comp.lang.visual-basic
Titolo: Combolist

Ho un problema: devo caricare in una combolist circa 8500 voci da un
database in access. Il problema è che ci mette alcuni secondi a fare tale
operazione. Che suggerimenti avete da darmi. (Ho già messo un indice nel
campo relativo).
Grazie.
Mirko Tedaldi.
--
Posted from 
mta01-acc.tin.it
 [212.216.176.32]
via Mailgate.ORG Server - 
http://www.mailgate.org

...


...
Ho un problema: devo caricare in una combolist circa 8500 voci da un
database in access. Il problema è che ci mette alcuni secondi a fare tale
operazione. Che suggerimenti avete da darmi. (Ho già messo un indice nel
campo relativo).
Grazie.
Mirko Tedaldi.
Anch'io ho avuto un problema del genere per la società per cui lavoro anche
se invece di 8500 ne dovevo scaricare qualcosa come 147000... fai un po te.
E ho trovato un sistema non molto ortodosso ma che indubbiamente ha i suoi
vantaggi. A parte il fatto che io usavo una lista e programmavo il vb per
Access ma credo che funzioni lo stesso, allora:
premettendo che deve caricare tutti gli elementi della tabella(altrimenti
occorrono alcune piccole modifiche)
1-fare una seek per >= in modo da avere la tabella ordinata come vuoi tu (ti
sconsiglio sql perché se su una certa dimensione di dati e sicuramente un
vantaggio se lo devi fare su tabelle di dimensioni "notevoli" ti assicuro
che i tempi di attesa possono diventare estremamente lunghi.
2- una volta che hai la tua tabella belle che pronta devi fare un piccolo
ciclo che ti carichi (se visualizzi diciamo 15 elementi ) una 50 di elementi
sulla lista o combo che sia. E fin qui... tutto normale. ti consiglio di
creare una procedura per questo.Devi inoltre dichiarare una variabile
diciamo TempoDiAccesso praticamente all'avvio della visualizzazione devi
mettere questo codice
tempodiaccesso=0
caricadati()
tempodiaccesso=timer
3-nel form_timer
devi aggiungere la stessa procedura che della caricadati ma che carica
diciamo 500 elementi alla volta o meno vedi tu praticamente metti un
controllo che se è passato un tot di secondi a tua scelta dall'ultimo tempo
di accesso  gli fai caricare altri 500 elementi. Preoccupati solo di gestire
tempodiaccesso un maniera intelligente, ossia se sei alla fine del record
inmpostalo su 999999999999999999999 non stò scherzando questo lo blocherà e
non effettuerà più la procedura nel timer.Idem se in caso di qualunque altro
caso tuvoliga bloccare il caricamento.
Scusa per il tema ma spero ti serva. Lo so non è molto elegante però è
indubbiamente efficace in quanto l'utente dell'applicazione non deve stare
achiedersi che cosa cavolo combini la macchina.
 Ciao by Zolfo
zo...@tin.it


campo relativo).
Difficile se non ci dici come carichi la combo. Comunque ho fatto un po di
prove supponendo che la tabella da cui vuoi caricare i dati sia composta da
soli due campi (un campo contatore e un campo testo), e che tale tabella
venga aperta con l'esclusivo scopo di caricare la combo.
La prima prova utilizza il sistema "normale", cioè i metodi addItem e
ItemData, mentre il secondo utilizza le API SendMessage. Ti allego il codice
di entrambe le prove con i risultati a cui sono giunto.
1° prova
    Dim Test As New cVbQuickTest
    Dim db As Database, rs As Recordset, x as integer
    Dim Hwnd As Long
    Hwnd = Combo1.Hwnd
    Set db = DBEngine.OpenDatabase("c:\documenti\prova.mdb")
    Set rs = db.OpenRecordset("Tabella1", dbOpenForwardOnly)
    Test.BeginTest
    Do Until rs.EOF
        Combo1.AddItem rs("Testo")
        Combo1.ItemData(x) = rs("Codice")
        x = x + 1
        rs.MoveNext
    Loop
    Test.EndTest
    MsgBox Test.ReturnSecond
il valore restituito è stato di  25651 microsecondi
2° prova
    Dim Test As New cVbQuickTest
    Dim db As Database, rs As Recordset, x as integer
    Dim Hwnd As Long
    Hwnd = Combo1.Hwnd
    Set db = DBEngine.OpenDatabase("c:\documenti\prova.mdb")
    Set rs = db.OpenRecordset("Tabella1", dbOpenForwardOnly)
    SendMessage Hwnd, WM_SETREDRAW, 0, &H0
    Test.BeginTest
    Do Until rs.EOF
        SendMessageString Hwnd, CB_ADDSTRING, &H0, rs("Testo")    '
rs("Testo") deve contenere il testo
        SendMessage Hwnd, CB_SETITEMDATA, x, rs("Codice")            '
rs("Codice") deve essere un long
        x = x + 1
        rs.MoveNext
    Loop
    Test.EndTest
    SendMessage Hwnd, WM_SETREDRAW, 1, &H0
    MsgBox Test.ReturnSecond
il valore restituito è stato di 11700 microsecondi
La dichiarazione di SendMessageString è:
Declare Function SendMessageString Lib "user32" Alias "SendMessageA" (ByVal
Hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As
String) As Long
le altre le puoi ricavare dal visualizzatore api.
Per favore puoi confermarmi la bontà dell'ottimizzazione?
Grazie Bruno