usare Max su delle variabili



  • usare Max() su delle variabili
    di Luca.Donati data: 02/04/2014 12:14:01

    Ciao a tutti.
    La funzione Max() permette di trovare il valore più alto in una lista.
    Quando uno la usa nelle celle, va tutto bene.
    Quando invece bisogna usarla in VBA per trovare la variabile che ha il valore più alto, allora non ci capisco più niente, perché il VBE mi dice che la funzione non è definita e l'help parla addirittura di un'espressione: espressione.Max(Arg1, Arg2 ... Arg30).
    La mia situazione è la seguente:
    Ho preso gli orari di entrata e di uscita dell'impiegato nelle celle di una determinata riga corrispondente al giorno e le ho messe in variabile (e1, u1, e2, u2... e4, u4 - quindi prevedo la possibilità di avere fino a quattro entrate/uscite). I valori sono immessi sottoforma "hh:mm" ma le variabili non mi è riuscito di dichiararle come Time (il tipo non corrisponde, pare) e quindi le ho messe come String, che chissà come funziona lo stesso anche per i calcoli.
    Ora, ovviamente, non è detto che l'impiegato entri ed esca quattro volte dall'ufficio! La gente di solito esce per pranzo, torna, poi riesce per tornare a casa, oppure si porta il panino e non esce per niente. Quindi possiamo avere un numero di timbrate assai variabile. Per fare certi calcoli sull'ora di fine giornata, mi serve di determinare qual'è, fra u1, u2, u3 e u4, l'ultima timbrata in uscita.
    Come posso fare?
    Qui sotto il codice, ma considerate che è in corso di costruzione.
    Grazie a tutti.
     
    Sub rigaDiOre()
    '
    ' rigaDiOre Macro
    ' tratta una giornata secondo una regola
    '
    
    'prima parte da mettere in constant
    Dim e1 As String, e2 As String, e3 As String, e4 As String 'colonne entrate
    Dim u1 As String, u2 As String, u3 As String, u4 As String 'colonne uscite
    Dim uu As String, uus As String ' ultima uscita e scrematura
    Dim colReg As Range, cReg As String, rReg As String
    Dim rOre As String, regola As String
    Dim rIM, rFS
    Dim rPD, rPS, rPQ, PQ, effe, difp, difn
    Dim rT, rPr
    
    'CARICA DATI DA RIGA DI ORE
    rOre = ActiveCell.Row ' andrà tolto passandolo in parametro
    regola = Cells(rOre, 12).Value
    ass = Cells(rOre, 18).Value
    
    e1 = Cells(rOre, 3).Value
    u1 = Cells(rOre, 4).Value
    e2 = Cells(rOre, 5).Value
    u2 = Cells(rOre, 6).Value
    e3 = Cells(rOre, 7).Value
    u3 = Cells(rOre, 8).Value
    e4 = Cells(rOre, 9).Value
    u4 = Cells(rOre, 10).Value
    'inserire qui un controllo sul numero di valori presenti nelle variabili "e" e "u" sopra
    'se dispari, Cells(rOre, 17).Value = "ERRORE" e poi exit sub
    '---------continuo controllando manualmente di eseguire solo su righe perfette
    
    '--------parte da sostituire con TrovaColonna
    With Sheets("monitor").UsedRange
        Set colReg = .Find(regola, LookIn:=xlValues)
        If Not colReg Is Nothing Then
            cReg = colReg.Column
            rReg = colReg.Row
        Else
            cReg = "Non Trovato"
        End If
    End With
    'MsgBox ("la regola sta in: " & cReg & "," & rReg)
    '--------fine parte da sostituire con TrovaColonna
    
    'CARICA CARATTERISTICHE REGOLA
    rIM = Sheets("monitor").Cells(rReg, cReg + 1).Value 'inizio mattina
    rFS = Sheets("monitor").Cells(rReg, cReg + 2).Value 'fine sera
    rPD = Sheets("monitor").Cells(rReg, cReg + 3).Value 'pausa dopo quanto
    rPS = Sheets("monitor").Cells(rReg, cReg + 4).Value 'pausa se ore > x
    rPQ = Sheets("monitor").Cells(rReg, cReg + 5).Value 'pausa imposta, quanti minuti
    rT = Sheets("monitor").Cells(rReg, cReg + 6).Value 'orario teorico
    rPr = Sheets("monitor").Cells(rReg, cReg + 7).Value 'eventuale premio
    
    'CALCOLA
    If e1 < rIM Then e1 = rIM
    uu = Max(u1, u2, u3, u4) '   <== QUI CASCA L'ASINO !!!
    If uu > rFS Then
        uus = uu - rFS 'scrematura ultima uscita se oltre rIM
    Else
        uus = 0
    End If
    
    p1 = u1 - e1 'sono i periodi di lavoro della giornata: uscita meno entrata
    If Not e2 = "" Then
        p2 = u2 - e2
    Else
        p2 = 0
    End If
    If Not e3 = "" Then
        p3 = u3 - e3
    Else
        p3 = 0
    End If
    If Not e4 = "" Then
        p4 = u4 - e4
    Else
        p4 = 0
    End If
    
    If u1 > rPD And p1 > rPS Then
        p1 = p1 - rPQ
    Else
        rPQ = "ok"
    End If
    effe = p1 + p2 + p3 + p4 - uus
    If effe > rT Then
        difp = effe - rT
    Else
        difn = rT - effe 'bisogna far precedere il segno "-"
    End If
    
    'MsgBox (rPQ & " " & effe & " " & rT)
    
    'SCRIVE
    Cells(rOre, 15) = rPQ
    Cells(rOre, 16) = rT
    Cells(rOre, 17) = effe
    Cells(rOre, 20) = difp
    Cells(rOre, 21) = difn
    End Sub



  • di Grograman (utente non iscritto) data: 02/04/2014 12:30:47

    Ciao!

    Non ho letto il codice, ma tanto per dare un input, devi usare la funzione MAX applicata, ad esempio, ad un range di celle:
     
    Dim lmax As Double
    lmax = Application.WorksheetFunction.Max(Range("A1:C200"))



  • di Luca.Donati data: 02/04/2014 12:39:46

    Grazie della risposta, Grograman.
    Lo farò senz'altro, se non c'è altra soluzione.
    Ma mi pare strano che non si possa fare la stessa cosa tra variabili...



  • di lepat (utente non iscritto) data: 02/04/2014 12:53:57

    le variabili non c'entrano, la funzione max non esiste in vba, esiste oltanto questa
    Application.WorksheetFunction.Max



  • di isy data: 02/04/2014 12:55:03

    Ciao

    Altre soluzioni...
    Il codice cerca l'ultima riga in più range ("B", "C", "G")
    Utilizzando gli array
     
    Sub UltimaRiga()
        Dim Coln As Long, Surface
        Surface = Array("B", "C", "G")    'Qui indico le lettere delle colonne della ricerca
        For Coln = 0 To UBound(Surface)
            Surface(Coln) = Cells(Rows.Count, Surface(Coln)).End(xlUp).Row 'Inserisco il valore dell'ultima riga
        Next
        MsgBox Application.Max(Surface)  'Utilizzo l'array per la ricerca
    End Sub



  • di Luca.Donati data: 02/04/2014 14:20:34

    Grazie anche a isy per il suggerimento Array, che però nel mio caso è più laborioso che recuperare i dati dalle celle.
    Alla fine userò il suggerimento di Grograman e lepat:

    uu = Application.WorksheetFunction.Max(Cells(rOre, 4), Cells(rOre, 6), Cells(rOre, 8), Cells(rOre, 10))

    Laborioso ma efficace.
    Una curiosità, isy: se volessi comunque usare l'array, posso popolare quest'ultima con le variabili così come sono, vero? Non c'è bisogno di riappoggiarmi alle celle...?



  • di Luca.Donati data: 02/04/2014 14:24:36

    Mi sono spiegato malissimo.
    Intendevo dire: se nell'array ci sono valori in formato string che in realtà sono ore (v. spiegazione nel primo post), Application.Max funziona lo stesso? Perché nel tuo esempio, l'array alla fine era popolata di celle...