Newsgroup: it.comp.appl.access
Titolo: Query difficile, per favore aiuto.

Vi espongo il mio problema:
1^  Tabella: Clienti
---campi: IDCliente, Descrizione, ...
2^ Tablella: Articoli
---campi: IDArticolo, descrizione, ...
3^  Tabella: Listini:
---campi: IDCliente, IDArticolo, Prezzo, ...
4^ Tabella: TestataOrdine:
---campi: IDOrdine, IDCliente, ...
5^ Tabella: RigheOrdine:
---campi: IDOrdine, IDarticolo, Quantita', Prezzo, ...
Il problema si pone in fase di inserimento dell'ordine, una maschera
iniziale prevede la selezione del cliente, della data ed altre informazioni
classiche. Da qui si dovrebbe passare all'inserimento dell'ordine in una
maschera che dovrebbe essere basata su di una query composta dai seguenti
campi:
---Articolo (descrizione), Quantita', Prezzo
Nella maschera dovranno essere visualizzati tutti gli articoli presenti nel
listino del cliente selezionato in testata ovviamente con quantita' a zero
nel caso non vi sia alcun inserimento, altrimenti con le quantita'
preventivamente inserite.
Come procedere: (da qui in poi ipotizzo perche' sono arenato)
1) prima query selettiva nella tab listini in base al codice cliente (in
ogni caso come faccio a fare una query condizionata dal codice cliente?)
2) seconda query (o forse ne basta una sola) tra i record precedentemente
selezionati in tab listini ed
    eventuali quantita' inserite nelle righe d'ordine in base al IDOrdine
(stesso problema di query1)
3) in ogni caso, come abbinare le info delle righe ordine alle info del
listino del cliente?
Se ho scritto cagate insultatemi pure, ma aiutatemi altrimenti mi mangio il
PC.
(Non conosco molto bene access, si sara' capito, vengo dalla vecchia gloria
del clipper e per questo sono un po' castrato mentalmente)
Grazie, Pietro
pie...@distro.it

 del clipper e per questo sono un po' castrato mentalmente)
Alla fin fine non c'è poi questa grande differenza!
Bye, Ste

Meraviglia,
sei il primo che mi porta lontano dalle query e mi fa usare il codice, che
quantomeno riesco a stendere bene.
/*
Il suggerimento del listino l'avevo gia' preso in considerazione, ma la
tipologia del prodotto fa si' che non vi siano o quasi prezzi uguali per
differenti clienti, quindi inutile il passaggio dal listino a se' stante.
*/
Come mi suggerisci di procedere?
1) faccio una tabella temporanea, RigheOrdine:
---campi: IDOrdine, IDArticolo, Quantita', Prezzo, ...
che riempio subito prima di andare in inserimento ordine pescando l'articolo
ed il prezzo dal listino per quel cliente ?
nel pratico:
    FindFirst ( IDCliente in Listini)
    ciclo finche' codice cliente = IDCliente
        AddNewRec ( in RigheOrdine)
    fine ciclo
Potrebbe andare?
Puoi mica scrivere un esempio di codice anche semplice?
Pietro Favaro

 Puoi mica scrivere un esempio di codice anche semplice?
Fammi sapere se quanto ho scritto ti suona familiare, bisogna capire
quanta dimestichezza hai coi recordset...
Bye, Ste

    contiene le righe-ordini correnti
Il problema e' qui:
in genere il listino del cliente prevede 4 o 5 articoli a lui riservati,
pertanto all'entrata nel corpo ordine bisognerebbe presentare tutti gli
articoli previsti dal listino (ovviamente senza quantita' in ordine) e non
una listbox vuota con l'inserimento di un articolo alla volta.
per capirci:
---intestazione: Cliente: XXX ddddddddddd
                           Numero ordine: XXXXX, del: XX/XX/XX
---corpo:
    articolo                 q.ta'          prezzo
    ddddddddddd                       1.500
    ddddddddddd                       1.000
    ddddddddddd                       1.200
    ddddddddddd                          900
(spero renda l'idea)
....
Come procedo?

 ha scritto nel messaggio
news:91pt2r$i1g$1...@fe1.cs.interbusiness.it...

Visto che la struttura delle tue tabelle è sostanzialmente esatta,
aggiungiamo un paio di campi, facciamo qualche precisazione, lavoriamo un pò
sul modo di mettere le tabelle in relazione fra di loro e usiamo un pò di
autocomposizione ricerca. Insomma lavoriamo di più sulle tabelle per creare
alcuni automatismi di Access e vedrai che con una piccola query, una
maschera ed una sottomaschera risolviamo il tuo problema.
Cominciamo con ripassare in rassegna le tue tabelle.
Clienti
-------
IDCliente            Contatore e chiave primaria
RagioneSociale    Testo
ecc. ecc.
Niente da commentare
----------------------------------------------
Articoli
--------
IDArticolo            Contatore e chiave primaria
Descrizione           Testo
ecc. ecc.
Niente da commentare
----------------------------------------------
Listini
------
IDListino            Contatore e chiave primaria
IDCliente            Numerico
IDArticolo          Numerico
Prezzo                Numerico
ecc. ecc.
Ho aggiunto il campo IDListino solo per adoperarlo come chiave primaria,
altrimenti avresti dovuto dichiararti come chiave primaria l'insieme dei due
campi IDCLiente e IDArticolo, con qualche piccola complicanza in più nei
passaggi successivi.
Per il campo IDCliente esegui l'Autocomposizione Ricerca... basandola sulla
tabella Clienti; ciò ti permetterà di memorizzare il codice cliente ma di
visualizzare automaticamente nel controllo delle maschere associato a questo
campo la ragione sociale del cliente e non il suo codice (tutto ciò senza
ricorrere esplicitamente a delle query, che mi sembra non sono il tuo
cavallo di battaglia); così facendo creerai inoltre implicitamente una
relazione tra la la tabella Clienti e la tabella Listini.
Per lo stesso motivo indicato nel precedente paragrafo, esegui
l'Autocomposizione Ricerca... anche per il campo IDArticolo e basala sulla
tabella Articoli.
-----------------------------------------
TestataOrdine
---------------
IDOrdine                Contatore e chiave primaria
IDCliente                Numerico
DataOrdine             Data/ora
ecc. ecc.
Per il campo IDCliente esegui l'Autocomposizione Ricerca... basandola sulla
tabella Clienti.
--------------------------------------------
RigheOrdini
------------
IDRigheOrdini        Contatore e chiave primaria
IDOrdine                Numerico
IDArticolo              Numerico
Prezzo                    Numerico
Quantità                 Numerico
ecc. ecc.
Ho aggiunto il campo IDRigheOrdine per lo stesso motivo per cui
precedentemente ho aggiunto il campo IDListino.
Per il campo IDAticolo esegui l'Autocomposizione Ricerca... basandola sulla
tabella Articoli.
-----------------------------------------------
Ora che abbiamo finito con le tabelle, sistemiamo il modo in cui sono in
relazione fra di loro.
Apri la finestra Relazioni: dovresti vedere le tue cinque tabelle con già
tracciate le relative relazioni; aggiungi per tutte le relazioni l'itegrità
referenziale.
Crea una relazione uno-a-molti tra la tabella TestateOrdine e la tabella
RigheOrdini, aggiungendo anche in questo caso l'integrità referenziale.
Ora che le relazioni stanno a posto, creati una query (chiamala Query1) che
abbia il seguente codice SQL:
SELECT Listini.IDArticolo, Articoli.Descrizione, Listini.Prezzo,
Listini.IDCliente
FROM Articoli INNER JOIN Listini ON Articoli.IDArticolo = Listini.IDArticolo
WHERE (((Listini.IDCliente)=[Forms]![Maschera]![IDCliente]));
Questa è l'unica query che devi crearti esplicitamente.
Ora tocca alle maschere.
Creati una maschera (chiamala Sottomaschera) che abbia come Origine record
la tabella RigheOrdine; deve avere una visualizzazione a Maschere continue;
dovrà contenere, nell'ordine, i controlli IDArticolo, Prezzo e Quantità
associati ai relativi campi della tabella RigheOrdine.
Con la struttura di Sottomaschera aperta indica Query1 come "Origine riga"
del controllo IDArticolo (dovresti vederlo come casella combinata).
Sempre per il il controllo IDArticolo, nella sezione Formato delle
Proprietà, indica 3 come Numero colonne e come Larhezza colonne scrivi
0cm;2,54cm,0cm ovvero dichiara a zero la lunghezza della prima e ultima
colonna.
A fronte dell'evento "Dopo aggiornamento" del controllo IDArticolo genera il
seguente codice VBA:
Private Sub IDArticolo_AfterUpdate()
Me!Prezzo = Me!IDArticolo.Column(2)
End Sub
Così facendo, scegliendo l'articolo, otterrai riempito automaticamente il
controllo Prezzo.
A questo punto creati una seconda maschera (chiamala Maschera) che abbia
come Origine record la tabella TestataOrdine; deve avere una visualizzazione
a Maschera singola; dovrà contenere, nell'ordine, i controlli IDOrdine,
IDCliente e DataOrdine associati ai relativi campi della tabella
TestataOrdine.
In Maschera inserisci, tramite l'Autocomposizione Controllo, un controllo
sottomaschera nel quale chiedi di inserire la maschera Sottomaschera di cui
sopra; indica che vuoi vedere solamente i record che hanno lo stesso
IDCliente di Maschera.
A fronte dell'evento "Dopo aggiornamento" di Maschera genera il seguente
codice VBA:
Private Sub Form_Current()
If Not IsNull(Me!IDCliente) Then
[Forms]![Maschera]![Sottomaschera]![IDArticolo].Requery
End If
End Sub
A fronte dell'evento "Dopo aggiornamento" del controllo IDCliente (che
dovresti vedere come casella combinata) genera il seguente codice VBA:
Private Sub IDCliente_AfterUpdate()
[Forms]![Maschera]![Sottomaschera]![IDArticolo].Requery
End Sub
Il gioco è fatto.
Apri Maschera, scegli il cliente dalla relativa casella combinata, digita la
data, spostati nella casella combinata dell'articolo posta nella
sottomaschera e scegli l'articolo di cui vuoi digitare la quantità, spostati
sul controllo Quantità e digitala; come vedrai per sceglire l'articolo ti si
presenterà un elenco contenente gli articoli contenuti nel listino di quel
cliente e il prezzo comparirà automaticamente, e sarà appunto quello
relativo a quel prodotto per quel cliente.
Dopo sta faticata, spero che sia quello che ti serviva.
Facci sapere.
Buon Natale.
--
Roberto
---------------------------------------------
il Sito Comune di it.comp.appl.access:
http://members.xoom.it/it_db_access/
---------------------------------------------


OK, tutto chiaro.
In questo caso allora la soluzione obbligata è sicuramente l'utilizzo di una
tabella "temporanea" come avevi già proposto tu, sulla selezione del cli
la tronchi/ricrei ciclando in parole povere sulle righe dei listini; sulla
conferma
te la ricicli e per ogni riga con quantità valorizzata ti crei una
riga-ordine.
In questo caso allora l'applicazione si presta molto ad essere risolta con
un pesante utilizzo di sql da codice, ti facilita sicuramente la vita e
dovrebbe rendere
il tutto un poco più performante; con due docmd.runsql dovresti riuscire
ad troncare/inizializzare la tabella temporanea e lo stesso sulla conferma
(accodamento a righe-ordini e troncamento).
Ovviamente sarà difficile riuscire a fare inserimento/variazione con una
sola
maschera!
Bye, Ste


Sai benissimo che avremmo dovuto continuare il dialogo nel NG, ma visto che
è Natale.....
Mi era sfuggito che per te fosse essenziale precompilare la sottomaschera;
non è un problema e secondo me non è necessario passare per una tabella
temporanea.
Alla soluzione che ti avevo dato con il mio messaggio precedente apporta le
seguenti modifiche:
Sottomaschera
---------------------
Ai controlli IDArticolo e Prezzo della maschera Sottomaschera setta la
proprietà Abilitato a NO, la proprietà Bloccato a SI e la proprietà
Seleziona con tabulazione a NO.
Elimina il codice VBA che hai generato a fronte dell'evento "Dopo
aggiornamento" del controllo IDArticolo.
Maschera
-------------
A fronte dell'evento "Su corrente" di Maschera genera il seguente codice
VBA:
Private Sub Form_Current()
If Not IsNull(Me!IDCliente) Then
    [Forms]![Maschera]![Sottomaschera]![IDArticolo].Requery
End If
End Sub
che nel messaggio precedente erroneamente ti avevo detto di generare a
fronte dell'evento "Dopo aggiornamento" di Maschera.
A fronte dell'evento "Dopo aggiornamento" del controllo IDCliente ora genera
(invece di quello che ti ho scritto nel messaggio precedente) il seguente
codice VBA:
Private Sub IDCliente_AfterUpdate()
' *** Salva il record corrente ***
DoCmd.DoMenuItem acFormBar, acRecordsMenu, acSaveRecord, , acMenuVer70
Dim dbMio As Database
Dim rstListino As Recordset
Dim qdfMio As QueryDef
Dim rstRighe As Recordset
' *** Apri il database e i due recordset ***
Set dbMio = CurrentDb
Set qdfMio = dbMio.QueryDefs("Query1")
qdfMio.Parameters("[Forms]![Maschera]![IDCliente]") = Me!IDCliente
Set rstListino = qdfMio.OpenRecordset
Set rstRighe = dbMio.OpenRecordset("RigheOrdini")
' *** Cancella gli eventuali record RigheOrdine già
' esistenti per l'ordine corrente ***
If Not IsNull([Forms]![Maschera]![Sottomaschera]![IDArticolo]) Then
    rstRighe.MoveFirst
    Do Until rstRighe.EOF
        If rstRighe!IDOrdine = Me!IDOrdine Then
            rstRighe.Delete
        End If
        rstRighe.MoveNext
    Loop
End If
' *** Precompila i record di Sottomaschera ***
rstListino.MoveFirst
Do Until rstListino.EOF
        rstRighe.AddNew
        rstRighe!IDOrdine = Me!IDOrdine
        rstRighe!IDArticolo = rstListino!IDArticolo
        rstRighe!Prezzo = rstListino!Prezzo
        rstRighe!Quantità = 0
        rstRighe.Update
        rstListino.MoveNext
Loop
[Forms]![Maschera]![Sottomaschera].Requery
[Forms]![Maschera]![Sottomaschera]![IDArticolo].Requery
' *** Chiudi i recordset e il database ***
rstRighe.Close
rstListino.Close
qdfMio.Close
dbMio.Close
End Sub
Così facendo, quando apri Maschera, dopo aver selezionato il cliente, nella
sottomaschera ti compaiono automaticamente gli articoli del listino di quel
cliente completi di prezzo e con la quantità a zero; puoi passare quindi a
digitare la quantità per i soli articoli venduti per quell'ordine.
Naturalmente nella tabella RigheOrdine avrai anche i record con la quantità
a zero che occuperanno spazio.
Se desideri eliminarli, creati una query di eliminazione (elimina i record
con quantità zero) che puoi eseguire periodicamente o al limite eseguila
automaticamente per ogni ordine, a fronte dell'evento "Dopo aggiornamento"
di Maschera (bisognerebbe però valutare, in questo caso, di quanto si
appesantisce l'esecuzione del programma).
Alla prossima nel NG.
Buon Natale
Roberto
---------------------------------------------
il sito comune di it.comp.appl.access:
http://members.xoom.it/it_db_access/
---------------------------------------------