Avere la somma di più caselle di testo senza origine controllo in una maschera.

Anonimo
2017-06-10T21:08:20+00:00

Ciao,

fosse stato in Excel, nella cella avrei scritto:

=Somma(C1 : C18)

In una casella di testo di Access come si potrebbe fare senza dover per forza scrivere:

=C1 + C2 + C3 ecc...

Vladimiro

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

4 risposte

Ordina per: Più utili
  1. Anonimo
    2017-06-11T15:30:48+00:00

    ciao Vladimiro,

    mi sovvengono due modi.

    il primo.

    Sfruttare la proprietà tag del controllo textBox e in un loop sommare il valore dei controlli ed assegnarli alla textBox in cui vuoi visualizzare la somma :

    oppure, volendo evitare la proprietà tag assegnare alla textBoxes, oggetto di somma, un nome che possa essere riconosciuto in un loop nella collection controls della forms.

    il tag è la x e nel loop solo il valore dei controlli textbox contrassegnati in tal modo vengono sommati :

    Option Compare Database

    Option Explicit

    Private Sub cmdsomma_Click()

    Dim ctl    As Access.Control

    Dim lngTot As Long

    For Each ctl In Me.Section(0).Controls

        If TypeName(ctl) = "textBox" And ctl.Tag = "x" Then

            lngTot = lngTot + Nz(ctl, 0)

        End If

    Next

    Set ctl = Nothing

    Me.txtSomma = lngTot

    End Sub

    il controllo con sfondo rosso non ha il tag x e di conseguenza anche se valorizzata non viene considerato nella somma.

    Serve un command button per attivare la somma

    L'alternativa è sfruttare l'evento afterupdate e su ogni evento procedere con il calcolo...ma un po' ridondante.

    l'atra soluzione è un po' più difficile è volta all'evitare il richiamo di n eventi afterupdate per la somma.

    Definisci una classe clsSomma che utilizzerai per popolare una collection contenente l'oggetto myTxt, le tue textBoxes di cui vuoi la somma.

    su evento dopo aggiornamento effetui la somma.

    clsSomma:

    Option Compare Database

    Option Explicit

    Private WithEvents myTxt As Access.textBox

    Private myParent         As Form_Maschera2

    Private mOldValue        As Long

    Private mCurValue        As Long

    '

    Public Sub init(ByVal ctl As Access.Control, ByVal clsObj As Form_Maschera2)

        Set myTxt = ctl

        myTxt.AfterUpdate = "[event procedure]"

        myTxt.BeforeUpdate = "[event procedure]"

        Set myParent = clsObj

    End Sub

    Private Sub myTxt_AfterUpdate()

    Dim lngValue As Long

    lngValue = mCurValue

    If IsNull(myTxt) Or Not Me.isNum Then

        lngValue = mOldValue * -1

        mOldValue = 0

    End If

    myParent.calcola lngValue:=lngValue

    End Sub

    Public Property Get textBox() As Access.textBox

        Set textBox = myTxt

    End Property

    Public Function isNum() As Boolean

            Dim lngNum As Long

            On Error Resume Next

            lngNum = myTxt.Value

            isNum = (Err.Number = 0)

    End Function

    Private Sub myTxt_BeforeUpdate(Cancel As Integer)

    If Me.isNum Then

        mCurValue = myTxt - mOldValue

        mOldValue = myTxt

    End If

    End Sub

    Private Sub Class_Terminate()

    Set myTxt = Nothing

    Set myParent = Nothing

    End Sub

    instanzi la classe nella form su apertura :

    Option Compare Database

    Option Explicit

    Private cls    As clsSomma

    Private col    As VBA.Collection

    Private Sub Form_Open(Cancel As Integer)

    Dim ctl    As Access.Control

    Dim lngTot As Long

    Set col = New VBA.Collection

    For Each ctl In Me.Section(0).Controls

        If TypeName(ctl) = "textBox" And ctl.Tag = "x" Then

            Set cls = New clsSomma

            cls.init ctl, Me

            col.Add cls, ctl.name

        End If

    Next

    Set ctl = Nothing

    End Sub

    Public Sub calcola(ByVal lngValue As Long)

    Me.txtSomma = Nz(Me.txtSomma) + lngValue

    End Sub

    Private Sub Form_Unload(Cancel As Integer)

    Dim c As clsSomma

    For Each c In col

        col.Remove c.textBox.name

    Next

    Set col = Nothing

    Set cls = Nothing

    End Sub

    nella classe qualora il valore assegnato alla textBox sia non numerico la somma non si valorizza.

    Un po' difficile tutto questo mi rendo conto, sicuramente più flessibile rispetto alla somma delle singole txtBoxes nell'origine riga della txtSomma, ma la tua idea iniziale credo sia la migliore... :-)

    qui trovi la demo.

    Ciao e buona domenica.

    Sandro.

    La risposta è stata utile?

    1 persona ha trovato utile questa risposta.
    0 commenti Nessun commento
  2. Anonimo
    2017-06-12T18:20:15+00:00

    Ciao Sandro,

    grazie per l'ulteriore consiglio, anche se la proprietà tag già la conoscevo in quanto l'ho già sfruttata in altre occasioni :-)

    Tornando alla scelta di avere un'unica lettera seguita da numeri crescenti mi permette, ad esempio con un ciclo For Next, di ricercare in maniera velocissima un determinato valore all'interno di una delle tante caselle di testo, oppure di scrivere in maniera velocissima dei cicli Do Loop ecc... 

    Questo naturalmente non esclude di avere allo stesso tempo impostato il tag su ogni casella di testo ed all'occorrenza sfruttarlo.

    Debbo ammettere che mi hai spiazzato! :-)

    Vladimiro

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2017-06-12T05:43:06+00:00

    ciao Vladimiro,

    qualche ulteriore dettaglio.

    La proprietà tag ti permette di svincolarti completamente dal nome dei controlli e dalla loro numerosità.

    Se devi aggiungere od eleminare una textBox ti basterà eliminare il controllo nel primo caso, nel secondo, non dovrai fare altro che aggiungerlo, rinominarlo a tuo piacimento, pippo, pluto, minni, o c19, ricordandoti semplicemente di impostare la x come tag, per farsi che essa concorra alla formazione del totale.

    Certo, il ciclo da 1 a 18 gestito concatenando in un loop il nome del controllo e la variabile che controlla il ciclo è più veloce, ma ancora, nel caso di eliminazione o aggiunta devi rivedere il codice modificando il limite della variabile del loop ( a 19 o 20 nel caso di aggiunta oppure a 17 o 16 nel caso di eliminazione)...in più è sempre bene evitare le costanti hard coded.

    Il caricamento in una collection delle textBoxes, consente di ereditare eventi, proprietà e metodi della textBox rendendo il codice maggiormente snello e lineare.

    Concordo ancora che è un po' complicato, ma con tanti controlli da gestire non scarterei l'iterazione tra una classe form e un' oggetto personalizzato ( clsSomma ).

    Anche nel caso di inserimento nell'origine di controllo di tutti gli addendi =c1+c2+c3+c4, dovresti comunque wrappare con la funzione intrinseca nz rendendo poco agevole la manutenzione...

    Ciao e buon inizio di settimana!

    Sandro.

    La risposta è stata utile?

    0 commenti Nessun commento
  4. Anonimo
    2017-06-11T19:40:07+00:00

    Ciao Sandro,

    sinceramente mi aspettavo qualcosa di più semplice vista l'assegnazione del nome volutamente data alle caselle di testo; cioè una C ed una numerazione crescente:

    C1,C2,C3...C18

    Premio comunque la tua buona volontà e ne farò sicuramente tesoro per altre situazioni che si dovessero presentare più complesse.

    Grazie Vladimiro

    La risposta è stata utile?

    0 commenti Nessun commento