ADODB Recordset Find: filtro su campi multipli

di il
8 risposte

ADODB Recordset Find: filtro su campi multipli

Ciao a tutti.
Mi stanno chiedendo di fare un lavoro che credo sia al di là delle mie capacità ... ma ci sto provando.
Devo fare una sorta di previsione tramite i dati del conto economico dell'azienda.
Il conto economico elenca le voci dei conti che, credo, siano standard per quasi tutte le aziende italiane (almeno le srl).
Da una tabella che raccoglie i dati periodici (identificabili con una chiave tipo: anno+mese+codice) devo fare una previsione. Ad esempio per gli acquisti di materie prime che corrispondono al conto 004010 (è un esempio, non so se è realmente così), prendo i valori degli anni precedenti nel mese di competenza e faccio una sorta di previsione. I dati storici sono ad esempio:
  • 2019080004010 (agosto 2019 voce 004010);
  • 2020080004010 (agosto 2020 voce 004010);
  • 2021080004010 (agosto 2021 voce 004010);
Ho una tabella di tutti questi dati storici (i conti tipo 00... sono circa 200), prendo come base i 3 anni precendenti a quello in corso e tutte le voci le trasferisco su una tabella temporanea. Su questa devo inserire poi delle righe con i valori di "previsione"
ad esempio la voce 202208004010 avrà un valore che dipende da quelli sopra elencati ma aumentata o diminuita a seconda del criterio (in una release successiva si potrà impostare un criterio differente per ogni conto .... oltre 200 criteri, ma lasciamo perdere per il momento).

La tabella che elenca tutti i tipi di conto (oltre 2000) deve essere filtrata con solo quelli che servono, in modo che per ciascuno possa andarmi a calcolare il valore previsionale (per ciascuna voce), la selezione deve essere fatta su più campi ma non capisco perché non riesco:

dim rst3 as ADODB.Recordset
dim t3 as String 'tabella da filtrare
dim strFiltro as String
t3="nome_tabella_"
strFiltro="(campo_1 Like '004%' OR campo_1 Like '005%' OR campo_1 Like '006%' ) AND (campo_2 <> Null)"

Set rst3=New ADODB.Recordset

rst3.open t3, CurrentProject.Connection, adOpenKeyset, adLockOptimistic, adCmdTable

Debug.print "N° record: " & rst3.RecordCount 'mi serve per vedere i valori prima del filtro

Set rst3.filter(strFiltro)
Debug.Print "N° record dopo filtro: " & rst3.RecordCount
Non trovo il problema perché se il filtro è:
strFiltro="(campo_1 Like '004%' OR campo_1 Like '005%' OR campo_1 Like '006%' )"
oppure
strFiltro="(campo_2 <> Null)"
il codice funziona e mi restituisce il recordset filtrato (ovviamente il numero di record sarà diverso a seconda dei casi)
ma se uso la sequenza originaria, in cui il filtro è quello riportato nel codice mi restituisce un errore di runtime 3001.
Ho provato a mettere gli "*" al posto dei "%" come caratteri jolly, ho riquadrato i nomi dei campi con parentesi e naturlamente ho cercato ovunque su google e sui manuali che ho a disposizione, ma la sintassi dovrebbe essere quella che ho scritto.

I nomi dei campi nella tabella originaria (che non è fatta da me ma dal gestionale) hanno l'underscore non so se questo può essere un problema, solo che dovrebbe esserlo sempre, non capisco perché quando compongo il filtro su 2 campi diversi vada in errore.

Il codice sopra per il momento è in una public function, sto facendo solo delle prove.
Con Find sono riuscito ad estrarre i dati dalla tabella principale ed accodarli in quella di appoggio (nella quale ho aggiunto 2 campi, uno in cui la funzione now mi scrive il momento in cui l'inserimento del record viene eseguito e uno per differenziare questo ti po di record che è un dato storico dai record di previsione che saranno inseriti quando risolverò questo problema e andrò avanti).

Grazie in anticipo

8 Risposte

  • Re: ADODB Recordset Find: filtro su campi multipli

    Ma è Filter o Find?

    oierpa ha scritto:


    ...
    
    Set rst3.filter(strFiltro)
    
    Perché c'è un Set in quella riga?
    Non basta qualcosa tipo
    rst3.Filter = strFiltro
    ?
    Il codice l'hai riscritto a mano o hai fatto copia-incolla? E' strano che Filter sia scritto con la lettera minuscola. Di solito l'earlybinding/intellisense intervengono a mettere i nomi di proprietà e metodi come devono essere, cioè in questo caso con la F iniziale maiuscola. Quando non lo fa ci sono problemi di dichiarazioni di variabili o altro, tipo il Set ad inizio riga.
  • Re: ADODB Recordset Find: filtro su campi multipli

    Ciao Phil
    Il codice l'ho riscritto a mano, perché così ho voluto controllarlo un'ultima volta prima di scrivere il post.
    Il codice che ho scritto è il seguente, prima ho scritto una breve funzione:
    
    Public Sub filtrolike(rst as ADODB.Recordset, txtFiltro as string) as ADODB.Recordset
    rst.Filter=txtfiltro
    set filtrolike = rst
    end function
    
    usata nel codice così:
    
    ....
    Set rst3=filtrolike(rst3, strFiltro)
    ....
    
    Ho scritto un paio di funzioni come "filtrolike" per usarle a seconda dei casi.
    Anche inserendo direttamente il filtro nel corpo del programma il risultato non cambia.
    Non so se può servire sapere che la tabella che sto filtrando proviene da Oracle.

    Inizialmente avevo predisposto una Query (che filtrava i dati della tabella come serve a me), ma se cerco di usarla come recordset non funziona, provando ad importare un recordset tipo:
    
    Dim rst4 as ADODB.Recordset
    Dim qName as string
    qName ="Nomequery"
    Set rst4 = New ADODB.Recordset
    rst4.open
    
    Debug.print "N° record query: " & rst4.RecordCount
    
    Restituisce zero.
    Probabilmente non si può con ADO usare una query come recordset, ma questo forse va al di là delle mie conoscenze di ADO...
  • Re: ADODB Recordset Find: filtro su campi multipli

    oierpa ha scritto:


    questo forse va al di là delle mie conoscenze di ADO...
    Stiamo parlando di ADO, di cui ho imparato qualcosa solo negli ultimi giorni, di un back end Oracle che non ho mai usato, quindi è probabile che tu ne sappia più di me.

    oierpa ha scritto:


    Dim rst4 as ADODB.Recordset
    Dim qName as string
    qName ="Nomequery"
    Set rst4 = New ADODB.Recordset
    rst4.open
    Debug.print "N° record query: " & rst4.RecordCount
    Restituisce zero.
    Lo credo bene! dov'è che usi la query? ne hai scritto il nome in una stringa ma non la usi minimamente nell'apertura di rst4. Questo dice l'intuito, la conoscenza non sa come risolvere però.

    oierpa ha scritto:


    ....
    Set rst3=filtrolike(rst3, strFiltro)....
    Prova a non associare a se stesso il recorset filtrato, per scrupolo. Quindi usa un'altro recordset, non rst3. Se poi rst3 non serve più lo chiudi e distruggi. Togliamo un potenziale problema.
  • Re: ADODB Recordset Find: filtro su campi multipli

    Ciao Phil
    il codice corretto con cui la query viene richiamata come recordset (non so se questa è la terminologia corretta, anzi, quasi sicuramente non lo è ...) è:
    
    Dim rst4 as ADODB.Recordset
    Dim qName as string
    qName ="Nomequery"
    Set rst4 = New ADODB.Recordset
    rst4.open qName
    
    Ho trascritto male, ma il risultato non cambia, viene sempre restituito "0" se conto i record.

    In merito a non riassegnare rst3 dopo il filtro, ho già provato, non cambia nulla.

    Forse il problema è la tabella collegata di oracle, magari c'è una sintassi leggermente diversa da usare, ma non saprei quale.

    Ho provato anche a filtrare in due passaggi successivi ma non cambia nulla.
  • Re: ADODB Recordset Find: filtro su campi multipli

    oierpa ha scritto:


    In merito a non riassegnare rst3 dopo il filtro, ho già provato, non cambia nulla.
    Passo, ti devo lasciare in mano di qualcuno che ne capisce. Ti ho avvisato perché non mi piace abbandonare un thread non risolto ma non riesco ad essere d'aiuto.
  • Re: ADODB Recordset Find: filtro su campi multipli

    Grazie lo stesso, buon lavoro.
  • Re: ADODB Recordset Find: filtro su campi multipli

    Faccio un paio di osservazioni.
    La prima è sulla funzione [filtrolike] che è concettualmente errata.

    Le funzioni che hanno come parametri un'oggetto, ed il RS è definibile Oggetto, lo attribuirscono ByRef, di conseguenza riassegnare il RS alla funzione non serve veramente a NULLA perchè l'applicazione del Filter avviene alla prima riga ed essenfo il parametro Oggetto usato byRef... va da se che usare il RS riferito alla funzione è inutile.

    Quindi la funzione dovrebbe essere scritta così:
    
    Public Sub filtrolike(rst as ADODB.Recordset, txtFiltro as string)
    rst.Filter=txtfiltro
    end function
    A questo punto basta un Sub...?

    Per capire il perchè non funziona servirebbe capire anche come apri il RS... ti suggerisco di guardare questo esempio:
    https://www.oreilly.com/library/view/programming-excel-with/0596007663/re754.html
    http://aspdoc.indoglobal.com/Ch11_ADO115.htm
    https://stackoverflow.com/questions/15904535/information-about-syntax-of-ado-recordset-filter-queries
    https://www.devhut.net/how-to-filter-an-existing-recordset/
  • Re: ADODB Recordset Find: filtro su campi multipli

    Ciao Alex.
    Prima di tutto grazie per i link che hai inoltrato, era ciò che cercavo, me li studierò per bene.

    Per quanto riguarda invece la funzione "filtroLike" ho appena provato a modificarla su un DB di prova e ottengo un errore di runtime 424 (necessario oggetto).
    Io non sono un programmore, mi sono occupato di dati anni fa e alla fine sono caduto anche nella gestione di DB in azienda, poco male, ma le lacune di una formazione strutturata in certi frangenti si fanno sentire.
    Nel caso specifico, ho provato a fare un paio di tentativi sulla funzione ed essendo particolarmente semplice ho notato che, modificando la funzione come hai suggerito non inserendo la riga
    Set filtroLike = rst1
    mi viene restituito l'errore 424.

    Come dicevo non sono così bravo da capirne il motivo.

    In merito al problema del filtro SQL invece, dopo un milione di tentativi sono riusciuto, costruendo il filtro così:
    Dim strSql="SELECT campo_1, campo_2, campo_3 FROM Tabella WHERE ((campo_1) Like '00%*' or (campo_1) Like '005%' or (campo_1) Like '006%') and (campo_2) like '00%'
    Cercando su google ho trovato che invece di usare "*" come carattere jolly, si doveva usare "%" (ma non so se è stato determinante, appena riesco provo). Mentre penso che il punto fondamentale sia stato usare
    campo_2 like '00%'
    invece di scrivere "not null" o "<> null" (il campo deve essre non nullo).
    Quest'ultimo punto non riesco a spiegarlo perché se uso questo come filtro da solo, non ho errori ed effettivamente il recordset viene filtrato come deve (ho verificato con una query e ho lo stesso numero di record).
    Se tu, o chiunque altro, riuscite a darmi una spiegazione o un link da leggere approfondisco.

    Grazie in anticipo.
Devi accedere o registrarti per scrivere nel forum
8 risposte