Access query accodamento da maschera

Anonimo
2016-05-29T14:07:11+00:00

Buon pomeriggio.

Una maschera, basata sulla tabella "combinazioni" e filtrata da una Query, elenca un serie di adempimenti che devono essere poi accodati nella tabella "adempimentipercliente".

Può darsi che sorga la necessità di accodare nella tabella di destinazione solamente alcuni adempimenti tra quelli elencati nella maschera; potrei in qualche modo deselezionare quelli da escludere.

Premetto che la tabella "Combinazioni" è una tabella generica, non riferita al cliente (il cliente viene filtrato dalla Query), per cui non posso (almeno credo)  inserirci una checkbox.

Esempio: la maschera per il cliente Rossi elenca i seguenti record (ID_Adempimenti):

  • telefonare;
  • cucinare;
  • uscire;
  • dormire.

Vorrei che "dormire" fosse escluso dall'accodamento, ad esempio deselezionandolo in qualche modo.

Grazie a tutti

Andrea

Microsoft 365 e Office | Access | Per la casa | Windows

Domanda bloccata. Questa domanda è stata eseguita dalla community del supporto tecnico Microsoft. È possibile votare se è utile, ma non è possibile aggiungere commenti o risposte o seguire la domanda.

0 commenti Nessun commento
Risposta accettata dall'autore della domanda
Anonimo
2016-12-10T17:45:23+00:00

ciao Andrea,

il modo più corretto per filtrare records in una form è l'impostazione di un filtro e non una query che compone la sua clausola where leggendo i parametri dalla form.

Inciso a parte, secondo me, per partecipare e rispondere in modo proficuo ai quesiti della community, spesso credo sia il caso non assecondare le intenzioni degli utenti ma cercare di indirizzarli verso la strada più tecnicamente corretta al limite dell'OT.

Vedo che qui sto fallendo alla grande, nel senso che il vero nodo cruciale è la messa a punto della base dati, non importa, ok, con maggiore padronanza dello strumento sarà un argomento che riprenderai più avanti.

Per quanto al quesito che poni la strada ed il ragionamento che fai è sostanzialmente corretto.

Qual è l'escamotage per filtrare la form dalla/dalle listboxes ?

E' possibile ricorrere alla funzione instriseca instr per farsi restituire la posizione di una stringa all'interno di un'altra.

Come fare nel tuo caso.

Supponiamo che tu stia selezionando, dalla demo che ti avevo preparato "agente di commercio" e "Brasile"

Se crei due campi calcolati su una query che restituiscono per ogni riga della query la posizione di "agente di commercio" e "Brasile" cosa otterrai? otterrai 0 quando la posizione è diversa da agente di commercio e 0 quando il paese non sarà Brasile, altrimenti un valore maggiore, giusto?

Lo stesso nel caso in cui la scelta dovesse essere multipla.

Ora viene la parte difficile.

Se imposti il filtro nella query >0 per la posizione e O >0 per il paese dovresti ottenere le righe corrispondenti al filtro.

Questo però solo nel caso in cui una della listBoxes non presenti selezioni perché se invece tutte le listboxes hanno una o più selezioni il criterio non è >0 O >0 ma >0 E >0.

Proviamo.

Nella demo che ti ho preparato inserisci due textBoxes nella form clienti.

La prima la chiami txtFilter, la seconda txtPaese.

modifichi la funzione per la creazione del filtro nel seguente modo :

Private Function createFilter2(ByVal lst As Access.ListBox) As String

Dim varItem   As Variant

Dim strFilter As String

' ciclo gli elementi selezionati della listBox passata come argomento lst

' concatenadoli tra loro per la creazione del filtro

For Each varItem In lst.ItemsSelected

    strFilter = strFilter & "," & lst.Column(0, varItem)

Next

strFilter = Mid$(strFilter, 2)

createFilter2 = strFilter

End Function

ed inserisci  un command button che assegna alle textBoxes il risultato della/delle selezioni e al contempo risolverà la query una volta ancora con le nuove impostazione aggiornando il recordSource della form :

Private Sub cmdFilter2_Click()

Me.txtFilter = createFilter2(Me.lstPosizione)

Me.txtPaese = createFilter2(Me.lstPaese)

Me.Requery

End Sub

imposti e salvi una query con il seguente statement sql che diventerà il recordSource della tua form :

SELECT Clienti.IDClienteTesto,

            Clienti.NomeSocietà,

            Clienti.Contatto, Clienti.Posizione,

            Clienti.Paese,

            InStr(forms!Clienti!txtpaese,[paese]) AS pae,

            InStr([forms]![clienti]![txtfilter],[posizione]) AS pos

FROM

            Clienti

WHERE

       IIf(len(forms!Clienti!txtpaese & "")>0 And len(forms!clienti!txtfilter & "")>0,

            InStr(forms!Clienti!txtpaese,[paese])>0 And InStr(forms!clienti!txtfilter,[posizione])>0,InStr(forms!Clienti!txtpaese,[paese])>0 Or InStr(forms!clienti!txtfilter,[posizione])>0)

Or forms!Clienti!txtpaese Is Null Or forms!clienti!txtfilter Is Null;

come vedi la clausola where è complicata anche se facilmente comprensibile, ma con più listboxes da gestire lo statement diventa più verboso.

Attraverso la creazione di un filtro hai qualche riga di VBA in più, ma il procedimento è assolutamente più rigoroso, quindi prendi questa soluzione solo per scopo didattico per capire cosa non fare :-)

Tutto questo sempre IMHO.

Ciao, Sandro.

La risposta è stata utile?

0 commenti Nessun commento
Risposta accettata dall'autore della domanda
Anonimo
2016-12-04T11:50:39+00:00

ciao Andrea,

non ho dato seguito ulteriore al 3D e forse ho fatto male come credo di fare male mettendoti a disposizione una demo per impostare un filtro su selezione multipla via listbox. (poi di seguito capisci il perché).

Credo che la query che mostri, in cross join, non sia il modo più corretto di procedere e altresì credo che ci sia qualcosa di errato nell'impostazione del db.

In ogni caso prova a vedere qui : demo dove ti mostro molto semplicemente il modo per selezionare più elementi da una o più listBoxes ed impostare il filtro risultate dalle selezioni.

Ho cercato di commentare il codice per rendere il ragionamento applicato di facile comprensione, e spero di esserci riuscito.

Sono convito che l'impegno vada sempre considerato e premiato, e da qui il ragionamento che mi ha spinto verso la demo, però!

Credo che il db debba essere impostato in modo che, indipendentemente dalla complicatissima situazione fiscale italiana, della quale la mia ignoranza è maggiore alla sola padronanza di Access ( quindi vedi un po' come sei messo...), il db ti debba consentire, dicevo, di impostare la posizione fiscale di ogni cliente.

In questo modo, si, impostando un filtro hai la/le posizioni fiscali correttamente restituite, un cross join che restituisce oltre 700.000 righe mi da il sentore che qualcosa di errato per quanto all'impostazione dei dati.

Tutto questo sempre IMHO.

un saluto e buona domenica!

Ciao, Sandro.

La risposta è stata utile?

0 commenti Nessun commento

49 risposte aggiuntive

Ordina per: Più recente
  1. Anonimo
    2017-01-02T15:55:23+00:00

    ciao Andrea,

    [...]

    E' stato meno traumatico di quello che pensavo..................... e ci sono riuscito ! Grazie ancora, veramente tanta roba, da riadattare ad altre situazioni, ora che ho (forse) imparato. Mi sento una specie di mostro se penso che tre anni e mezzo fa non sapevo neanche cosa fosse Access e oggi, grazie soprattutto al tuo / vostro aiuto, comincio a "maneggiare", se pur in modo molto rudimentale, i codici Vba.......................

    [...]

    bene, questo è molto importante.

    ma ora.... :-).....mettiamo subito alla prova le tue nuove conoscenze acquisite di database developer, con qualche suggerimento,

    [...]

    1. nella tua demo (e di conseguenza nel mio database) la tabella clienti2 cresce all'infinito: all'apertura della maschera clienti potrei lanciare una query di eliminazione che azzeri i dati ?

    [...]

    ok io opterei per lo svuotamento sistematico della tabella in cui accodi le righe su scaricamento della form clienti, evento che precedente l'evento su chiusura.

    Se devi fare eseguire qualche routine con questa logica, sfrutta l'evento su scaricamento, primo perché precede l'evento su chiusura e quindi lo fai prima, e poi perché hai la possibilità di sfruttare il parametro cancel per annullare l'evento in caso succedesse qualche cosa.

    Vedo meglio l'evento su scaricamento di quello su apertura perché la tabella in cui accodi le righe si deve popolare nel mentre esegui filtri, una volta ultimato il tutto e prima di chiudere la form la svuoti.

    Per eseguire questo passaggio è sufficiente lanciare un'action query, prova.

    [...]

    1. se eseguo una prima volta il filtro e se poi cambio alcune selezioni all'interno della solita listbox non viene aggiornato il filtro stesso e rimangono le scelte effettuate in prima battuta; esempio: prima digito "Direttore marketing" e "Francia" funziona, poi lascio "direttore marketing" deseleziono "Francia" e seleziono "Germania": rimane Francia: va effettuato è meglio azzerare il filtro e rilanciarlo ex novo o effettuare un aggiornamento ? In questo secondo caso come ?

    [...]

    bug mio.

    sostituisci questa riga :

    strFilter = Mid$(.Name, 4) & " ='" & .ItemData(.ListIndex) & "'"

    così :

    strFilter = Mid$(.Name, 4) & " ='" & .ItemData(.ItemsSelected(0)) & "'"

    [...]

    1. Indipendentemente dal filtro che lancio nella maschera vorrei che la mia tabella clienti (su cui è basata la maschera) fosse sempre filtrata per i clienti cessati (datafinemandato diversa da null) e per i clienti occasionali (falsocliente = vero): ho provato ad inserire le due condizioni in createfilter ma non sono riuscito a farlo funzionare; ho provato anche ad inserire le medesime condizioni nella "Const cStrSql As String" ma senza successo.

    [...]

    hai la routine che imposta il filtro in base alle selezioni impostate nelle listboxes un'action query che accoda i dati, MA necessiti di impostare altri due campi su cui impostare altre due condizioni.

    come fai? alla fine delle selezioni, concateni una costante stringa che conterrà le condizioni che ti permettono di filtrare solo i clienti attivi e i non occasionali esattamente come hai intuito.

    Lascia stare la rotuine createfilter, il concatemento delle restanti condizioni, fisse, lo devi fare non appena la stringa del fitro è formata nelle sua interezza, la createFilter viene richiamata per ogni listbox che contiene elementi selezionati.

    Una volta ok la stringa può essere concatenata allo statement sql di accodamento, cioè, in pratica, non devi intervenire in alcun modo in questo ambito.

    Grazie e buon inizio anno

    Andrea

    prego e rinnovati auguri anche a te

    Facci sapere.

    Ciao, Sandro.

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2017-01-02T12:17:13+00:00

    E' stato meno traumatico di quello che pensavo..................... e ci sono riuscito ! Grazie ancora, veramente tanta roba, da riadattare ad altre situazioni, ora che ho (forse) imparato. Mi sento una specie di mostro se penso che tre anni e mezzo fa non sapevo neanche cosa fosse Access e oggi, grazie soprattutto al tuo / vostro aiuto, comincio a "maneggiare", se pur in modo molto rudimentale, i codici Vba.......................

    Rimangono però alcuni piccoli ritocchi da fare e vorrei un tuo consiglio, se possibile:

    1. nella tua demo (e di conseguenza nel mio database) la tabella clienti2 cresce all'infinito: all'apertura della maschera clienti potrei lanciare una query di eliminazione che azzeri i dati ?
    2. se eseguo una prima volta il filtro e se poi cambio alcune selezioni all'interno della solita listbox non viene aggiornato il filtro stesso e rimangono le scelte effettuate in prima battuta; esempio: prima digito "Direttore marketing" e "Francia" funziona, poi lascio "direttore marketing" deseleziono "Francia" e seleziono "Germania": rimane Francia: va effettuato è meglio azzerare il filtro e rilanciarlo ex novo o effettuare un aggiornamento ? In questo secondo caso come ?
    3. Indipendentemente dal filtro che lancio nella maschera vorrei che la mia tabella clienti (su cui è basata la maschera) fosse sempre filtrata per i clienti cessati (datafinemandato diversa da null) e per i clienti occasionali (falsocliente = vero): ho provato ad inserire le due condizioni in createfilter ma non sono riuscito a farlo funzionare; ho provato anche ad inserire le medesime condizioni nella "Const cStrSql As String" ma senza successo.

    Grazie e buon inizio anno

    Andrea

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2016-12-30T17:17:07+00:00

    ciao Andrea,

    [...]

    Grazie infinite Sandro.

    [...]

    prego!

    [...]

    Provo ad adattarla al mio database e penso che ne avrò per tutto il 2017 e forse anche per un po' del 2018........

    [...]

    beh, no è una patch che non dovrebbe ( il condizionale è d'obbligo non avendo visto il tuo sviluppo) essere troppo complicata, serve solo personalizzare il nome dei controlli e lo statement sql, riflettendolo nel tuo scenario reale.

    [...]

    Dì la verità: hai scritto un codice così complicato in modo che sparissi un po' dalla circolazione vero ?

    Ahahahaha....

    [...]

    mi diverto quasi sempre un sacco, ultimamente un po' meno, ma non per i quesiti che poni, anzi :-)

    Comunque la patch mi pare piuttosto lineare e nella sua logica assolutamente poco complicata :-).

    Devi deguggarla passo passo così capisci cosa fa esattamente nei vari passaggi.

    [...]

    B U O N     A N N O !

    Andrea

    [...]

    tanti auguri anche a Te :-DDDDDDD.

    Ciao, Sandro.

    La risposta è stata utile?

    0 commenti Nessun commento