Acquista i nostri libri consigliati su Amazon.it
+ Rispondi al messaggio
Visualizzazione dei risultati da 1 a 9 su 9

[Access 2003/ VBA] - inserire valore campo di query in controllo

  1. #1
    L'avatar di liodevac
    liodevac non è in linea Scolaretto
    salve a voi tutti utilissimi sempre!
    vi chiedo supporto per effettuare la seguente operazione:
    ho una maschera continua che mi presenta un elenco dati di fatture;
    fra i dati di ognuna è compreso un campo 'numprog' (numerico intero) al quale voglio assegnare io un valore (con un click su specifico button nella riga del record nuovo) al momento dell'inserimento di un nuovo record cioè di nuova fattura;
    questo valore deriva da una query sul massimo valore assunto da quel campo in base a determinati filtri;

    nel codice della maschera (su click del button) ho inserito la query che restituisce esattamente 1 campo con il valore max esistente prima dell'inserimento nuovo record, per cui dopo mi 'basterà' incrementarlo di 1 per ottenere il valore aggiornato da assegnare al campo 'numprog' del nuovo record.

    riporto inizio codice:
         
    Dim strsql As String
    strsql = "SELECT Max(FATTURE_EMESSE.numprog) AS MaxDinumprog FROM FATTURE_EMESSE WHERE (((FATTURE_EMESSE.Punto_Prelievo)=[Forms]![FORNITORI_FATTURE]![Punto_Prelievo]) AND ((FATTURE_EMESSE.Anno)=[Forms]![FORNITORI_FATTURE]![Anno]) AND ((FATTURE_EMESSE.Mese)=[Forms]![FORNITORI_FATTURE]![Mese]));"
    
    DOMANDA:

    per impostare in controllo su maschera il nuovo valore:
    Me.numprog = (il contenuto restituito dalla query summenzionata)
    devo far eseguire la query con
    docmd.runsql strsql
    
    e poi?
    ...ma ho l'impressione di stare seguendo una strada tortuosa, è vero? mi suggerite la scorciatoia? grazie in anticipo

  2. #2
    L'avatar di @Alex
    @Alex non è in linea Moderatore Globale
    Non stai seguendo una strada tortuosa... ma sbagliata...

    Ti leggo io la guida in linea...., magari ti è sfuggito... o magari non lo hai letto..., in merito al metodo RUNSQL:
    È possibile utilizzare l'azione EseguiSQL(RunSQL) per eseguire una query di comando
    (query di comando: Query che copia o modifica i dati:
    [includono query di :
            accodamento
            eliminazione
            aggiornamento)
    oppure o una query di definizione dati (DDL per la modifica struttura del DB(ALTER TABLE ecc...))
    
    Detto questo è evidente che una SELECT non rientri in nessuna delle 2 opzioni indicate... tant'è che non va bene...

    Quello che devi fare è aprire un RECORDSET basato su quel predicato SQL ed estrarre l'unico elemento FIELD esposto che è [MaxDinumprog] che conterrà quello che hai chiesto.
    Dim rs ad DAO.Recordset
    Set rs=DbEngine(0)(0).OpenRecordset(strsql)
    If rs.eof then
         ValoreEstratto=0 'Questo è il valore in caso in cui non ci siano Records che soddisfano
    Else
         ValoreEstratto=rs.Fields("MaxDinumprog").Value+1
    End if
    rs.close
    set rs=nothing
    
    Detto questo il tuo predicato SQL è decisamente poco ottimizzato... perchè prendere il MAX che è una funzione di Raggruppamento, quando ti basta ordinare in senso DISCENDENTE e prendere il 1°... con TOP...???
    SELECT TOP 1 (numprog) AS MaxDinumprog
    FROM FATTURE_EMESSE 
    WHERE Punto_Prelievo=[Forms]![FORNITORI_FATTURE]![Punto_Prelievo] AND 
               Anno=[Forms]![FORNITORI_FATTURE]![Anno]) AND 
               Mese=[Forms]![FORNITORI_FATTURE]![Mese]
    ORDER BY numprog DESC
    
    Questa restituisce 1 Record, se esiste ma questo è uguale con il tuo metodo, solo che la Query è decisamente più performante.
    Ovviamente sai già che i campi oggetto di CRITERIO dovrebbero essere INDICIZZATI... a tal proposito non capisco perchè tu abbia 2 campi come ANNO e MESE... non hai un campo DATA...?
    ℹ️ Leggi di più su @Alex ...

  3. #3
    L'avatar di liodevac
    liodevac non è in linea Scolaretto
    prima di tutto, grazie Alex

    ti rispondo sui particolari e successivamente adotterò la preziosa soluzione che mi hai fornito.

    1) i campi indicati sono indicizzati, sì perché nell'applicazione sono usati spesso per diversi tipi di ricerche;
    2) la presenza di campi anno-mese separati è dovuta al fatto che, pur presente un altro campo data della fattura, nella gestione quella si riferisce solo al giorno di emissione della fattura (info che serve all'operatore) ma il contenuto (euro - la prestazione, per così dire) ha competenza e riferimento ad un determinato anno e mese che normalmente non coincide con la data emissione, e sono separati perché in più l'operatore, con altre form, ha occasionalmente bisogno di fare operazioni di raggruppamento delle fatture di competenza di un determinato mese a prescindere dall'anno.

    detto questo: ma ti sembra non corretto logicamente aver creato e gestire appunto nella tabella fatture i campi data, anno, mese separati? grazie anche per il supporto teorico.

  4. #4
    L'avatar di @Alex
    @Alex non è in linea Moderatore Globale
    Con quanto hai detto può avere concretamente una Logica, io tuttavia avrei usato una Data di validità e Mese/Anno li ricavi come Year(...) Month(...) questo perchè in tutti i modi con un campo Data completo è sempre più agevole fare calcoli anche differenziali su date... esempio tutte le fatture entro 3 anni... si usa DateDiff...
    ℹ️ Leggi di più su @Alex ...

  5. #5
    L'avatar di MaurizioBruni
    MaurizioBruni non è in linea Scribacchino
    Quote Originariamente inviato da @Alex Visualizza il messaggio
    Detto questo il tuo predicato SQL è decisamente poco ottimizzato... perchè prendere il MAX che è una funzione di Raggruppamento, quando ti basta ordinare in senso DISCENDENTE e prendere il 1°... con TOP...???
    SELECT TOP 1 (numprog) AS MaxDinumprog
    FROM FATTURE_EMESSE 
    WHERE Punto_Prelievo=[Forms]![FORNITORI_FATTURE]![Punto_Prelievo] AND 
               Anno=[Forms]![FORNITORI_FATTURE]![Anno]) AND 
               Mese=[Forms]![FORNITORI_FATTURE]![Mese]
    ORDER BY numprog DESC
    
    Questa restituisce 1 Record, se esiste ma questo è uguale con il tuo metodo, solo che la Query è decisamente più performante.
    Grazie Alex, è sempre utile leggere le tue risposte, sei una miniera
    Spero che il braccio vada meglio
    PS scusate, non volevo offendere tutti gli altri;
    è sempre utile leggere le risposte di tutti, ma di qualcuno è un pò più utile, e tra questi c'è Alex
    Ultima modifica di MaurizioBruni; 17-11-2010 10:12  Motivo: imprecisione
    ℹ️ Leggi di più su MaurizioBruni ...

  6. #6
    L'avatar di liodevac
    liodevac non è in linea Scolaretto
    Alex, grazie per il suggerimento su uso campi date;
    quanto alla soluzione problematica ho attuato quello che mi hai indicato (con poche variazioni) e sono andato a cercare anche altri messaggi sull'argomento (dbengine, etc.) e ho ritrovato esempi simili con il particolare non trascurabile che l'enunciato sql quando si adotta DAO non può essere superiore a 256 caratteri (se ho capito bene);

    ho trovato e riporto link a messaggi - esempi:
    1) http://forum.masterdrive.it/visual-b...195/#post79090
    2) PRB: Proprietà Name di Recordset è limitata a 256 caratteri
    3) FAQIndex
    4) (altro forum, chiedo venia ai moderatori) Esosa richiesta di parametri
    5) http://forum.masterdrive.it/ms-offic...-3061-a-37668/
    ed altri minori...
    ORA: riporto il codice che ho inserito e che mi va in errore in fase di esecuzione, mentre su DEBUG è ok:
    Private Sub nprog_agg_Click()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim qdf As DAO.QueryDef
    Dim strsql As String
    
    strsql = "PARAMETERS [Punto_Prelievo] Text ( 14 ), [Anno] Text ( 4 ), [Mese] Short, [tipodoc] Text ( 15 ); SELECT Max(FATTURE_EMESSE.numprog) AS MaxDinumprog FROM FATTURE_EMESSE;"
    Set db = CurrentDb
    Set qdf = db.QueryDefs(strsql)     'QUI segnalato errore di run-time 3265: "Elemento non trovato in questo insieme"
    
    qdf.Parameters!Punto_Prelievo = Eval(Forms![FORNITORI_FATTURE]![Punto_Prelievo]) & ""
    qdf.Parameters!anno = Eval(Forms![FORNITORI_FATTURE]![anno]) & ""
    qdf.Parameters!Mese = Eval(Forms![FORNITORI_FATTURE]![Mese])
    qdf.Parameters!tipodoc = "<> 'servizi di rete'"
    
            Set rs = qdf.OpenRecordset(dbOpenDynaset, dbReadOnly)
                If rs.EOF Then
                    Me.contafatture = 0 'Questo è il valore in caso in cui non ci siano Records che soddisfano
                Else
                    Me.contafatture = rs.Fields("MaxDinumprog").Value + 1
                End If
    
        rs.Close: Set rs = Nothing
    End Sub
    
    ho smanettato un po' qui e là ma non riesco a comprendere l'inghippo: cortesemente un ulteriore ragguaglio sarebbe illuminante, come di consueto, grazie.

  7. #7
    L'avatar di @Alex
    @Alex non è in linea Moderatore Globale
    Nemmeno prendendo 10 Esempi e mettendo il codice nel MIXER potevi fare tanti errori...
    Dei LINK che hai postato, e li ho guardati tutti, non ne ho trovato uno che riportasse nemmeno lontanamente quello che hai scritto...!
    Mi chiedo se la guida serve a qualche cosa...????

    Per ovviare al problema dei 256Char.. crea da QBE la tua Query semplice, accedi all'editor SQL ed incolli la stringa
    PARAMETERS
        [Punto_Prelievo] Text ( 14 ), 
        [Anno] Text ( 4 ), 
        [Mese] Short, 
        [tipodoc] Text ( 15 ); 
    SELECT Max(FATTURE_EMESSE.numprog) AS MaxDinumprog FROM FATTURE_EMESSE
    WHERE Campoxx=[Punto_Prelievo] 
        AND Campoyy=[Anno]
       AND CampoZZ=[Mese] 
       AND TipoDocum= [tipodoc];
    
    Spero che i Type dei Parameters siano corretti... mi puzza moltissimo Anno TEXT e Mese Short... ma se tu sei sicuro...!
    Salva la query chiamandola QT

    Private Sub nprog_agg_Click()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim qdf As DAO.QueryDef
    Dim strsql As String
    With DbEngine(0)(0).QueryDefs("QT")
       .Parameters!Punto_Prelievo = Forms![FORNITORI_FATTURE]![Punto_Prelievo]
       .Parameters!anno = Forms![FORNITORI_FATTURE]![anno]
       .Parameters!Mese = Forms![FORNITORI_FATTURE]![Mese]
       .Parameters!tipodoc = "<> 'servizi di rete'"
        Set rs = .OpenRecordset()
                If rs.EOF Then
                    Me.contafatture = 0 'Questo è il valore in caso in cui non ci siano Records che soddisfano
                Else
                    Me.contafatture = rs.Fields("MaxDinumprog").Value + 1
                End If
    
        rs.Close: Set rs = Nothing
    End Sub
    
    Ti risparmio i commenti sugli errori ma ti suggerisco di STUDIARE, erano veramente cose banali che con una letta alla guida sarebbero state evidenti.
    Ultima modifica di @Alex; 19-11-2010 19:15 
    ℹ️ Leggi di più su @Alex ...

  8. #8
    L'avatar di liodevac
    liodevac non è in linea Scolaretto
    prima di tutto grazie del codice, e aggiungo poche note;
    io sono un dilettante del VBA, e siccome davvero non posso dedicare il tempo che sarebbe necessario per studiare allora sto adottando un metodo cosiddetto "learning by doing" ossia prendo delle applicazioni già realizzate in precedenza, individuo singole procedure/oggetti (molto) inefficienti e cerco nuove strade e soluzioni.
    la guida la consulto e mi son messo a scrivere sul forum dopo qualche tentativo autonomo fallito.

    tipi di dati: per il campo mese avevo sbagliato a scrivere il codice perché in realtà è di tipo Long, mentre il campo Anno confermo è di tipo text.

    ho provato il codice suggerito (ovviamente cambiando i nomi Campoxx, etc.) ma ancora mi si è presentato lo stesso tipo errore run-time 3265, allora proseguendo ricerche e consultando:

    MS ACCESS Code Sample - versione usabile/accessibile

    ho realizzato la procedura che adesso funziona senza problemi e riporto la soluzione così tutti ne potranno usufruire.

    Query denominata "nmaxprog_fattem":
    SELECT TOP 1 (numprog) AS MaxDinumprog
    FROM FATTURE_EMESSE
    WHERE tipodoc<>'servizi di rete' AND Punto_Prelievo=[Punto_Prelievo:] AND Anno=[Anno:] AND Mese=[Mese:]
    ORDER BY FATTURE_EMESSE.numprog DESC;
    
    Codice attivato su click su button denominato "nprog_agg" (presente nel rigo del record corrente che l'operatore sta trattando) nella form che elenca le fatture emesse:
    Private Sub nprog_agg_Click()
    Dim qdf As DAO.QueryDef
    Dim rs As DAO.Recordset
    
        Set qdf = CurrentDb.QueryDefs("nmaxprog_fattem")
        qdf.Parameters![Punto_Prelievo:] = Me.Punto_Prelievo
        qdf.Parameters![Anno:] = Me.anno
        qdf.Parameters![Mese:] = Me.Mese
        
        Select Case tipodoc
        Case "1° fattura"
            Me.numprog = 1
        Case "conguaglio"
        Set rs = qdf.OpenRecordset(dbOpenDynaset, dbReadOnly)
                If rs.EOF Then
                    Me.numprog = 0 'Questo è il valore in caso in cui non ci siano Records che soddisfano
                Else
                    Me.numprog = rs.Fields("MaxDinumprog").Value + 1
                End If
        Case Else
            Me.numprog = ""
        End Select
    
        rs.Close: Set rs = Nothing
    End Sub
    
    spero sia una soluzione valutabile come efficiente per un, ripeto, dilettante come me; magari più in là saprò far di meglio e il merito è di quello che leggo in questo forum.
    alla prossima.

  9. #9
    L'avatar di @Alex
    @Alex non è in linea Moderatore Globale
    Quello che hai trovato è un link al mio sito... ma se guardi bene è esattamente quello che ti avevo suggerito io... con le opportune modifiche...!

    P.S. Sono come te Autodidatta e Non Professionista della programmazione... ma questo non può essere un'alibi non credi...!?
    ℹ️ Leggi di più su @Alex ...

+ Rispondi al messaggio

Potrebbero interessarti anche ...

  1. Risposte: 8
    Ultimo Post: 23-03-2012, 09:19
  2. Risposte: 3
    Ultimo Post: 09-03-2012, 17:55
  3. [access 2003]Inserire un file in un campo
    Da Franco84 nel forum Microsoft Access
    Risposte: 2
    Ultimo Post: 10-11-2011, 14:25
  4. Risposte: 1
    Ultimo Post: 16-02-2011, 11:03
  5. Risposte: 5
    Ultimo Post: 11-09-2008, 10:31