VLOOKUP



  • VLOOKUP
    di Alone (utente non iscritto) data: 05/12/2013 23:42:24

    Buongiorno a tutti ragazzi. Ho bisogno del vostro aiuto!!
    Ho un valore nel Foglio1 in cella B2 che chiamerò X, nel Foglio2 ho un range di valori "B2:B3000" e vorrei trovare il valore più vicino al mio X. Potete darmi qualche idea? Mi date una mano a buttar giù del codice. GRAZIE MILLE a tutti.


  • numero più vicino
    di canapone (utente non iscritto) data: 06/12/2013 06:51:32


    Ciao,

    nel caso tu stia cercando 10 e nell'elenco compaia 9 e 11, a parità di scostamento, ti serve individuare il più piccolo o il più grande dei due.

    Saluti



  • di Alone (utente non iscritto) data: 06/12/2013 08:21:51

    Domanda interessante :)!! Vorrei prendere il più piccolo :).. Grazie per la risposta



  • di paolomath data: 06/12/2013 08:41:09

    Ciao, puoi provare quello che ho buttato giù.

    Non ho messo controlli sul tipo di dati nelle celle. Se sono presenti + valori che rispettano la condizione ti darà il primo che trova.

    Bye bye.
     
    Sub Vlookup()
    Dim Riga As Integer
    Dim Valore As Double
    Dim Diff As Double
    
    Riga = 3
    Valore = Cells(3, 2)
    Diff = Abs(Cells(2, 2) - Valore)
    
    For i = 4 To 11
        If Abs(Cells(i, 2) - Cells(2, 2)) < Diff Then
            Riga = i
            Valore = Cells(i, 2)
            Diff = Abs(Cells(i, 2) - Cells(2, 2))
        End If
        If Abs(Cells(i, 2) - Cells(2, 2)) = Diff Then
            If Cells(i, 2) < Cells(Riga, 2) Then
                Riga = i
                Valore = Cells(i, 2)
                Diff = Abs(Cells(i, 2) - Cells(2, 2))
            End If
        End If
    Next i
    
    MsgBox "Il valore + vicino è: " & Valore & " in posizione B" & Riga
    
    End Sub


  • cerca numero più vicino
    di canapone (utente non iscritto) data: 06/12/2013 09:39:13

    Ciao a tutti,

    solo per mettersi d'accordo sui risultati, potresti provare anche una formula matriciale.

    nell'esempio in D2 il numero da cercare in B2:B3000

    =SE(MIN(SE($B$2:$B$3000>=D2;$B$2:$B$3000))-D2<=D2-MAX(SE($B$2:$B$3000<=D2;$B$2:$B$3000));MIN(SE($B$2:$B$3000>=D2;$B$2:$B$3000));MAX(SE($B$2:$B$3000<=D2;$B$2:$B$3000)))

    La formula per funzionare deve essere copiata e confermata con control+maiusc+invio.

    Saluti



  • di Alone (utente non iscritto) data: 06/12/2013 11:42:06

    Grazie a tutti per il vostro aiuto. Le macro di excel sono un mondo nuovo per me.

    @paolomath
    Grazie mille appena ho un secondo la faccio girare sul mio pc e ti faccio sapere.

    @canapone
    La proposta matriciale è interessante ma purtroppo non posso utilizzarla perchè ho bisogno di una macro.

    Cerco di rappresentare al meglio il mio caso:
    - Ho nel mio Foglio1 4 o 5 celle con un numero all'interno
    - Nel foglio due avro 4 o 5 colonne di valori in un certo range, la dimensione è molto alta.
    - Devo estrarre da queste colonne il valore più vicino al mio preso dal foglio1.



  • di Alone (utente non iscritto) data: 07/12/2013 00:09:03

    @paolomath
    Ciao ho appena provato la macro e funziona. Devo chiederti una ulteriore cortesia..
    se volessi invece di dare la dimensione del vettore colonna prendere automaticamente la dimensione, come posso fare? Grazie ancora



  • di Raffaele_53 (utente non iscritto) data: 07/12/2013 12:58:46

    Scusate se mi intrometto.
    Qualcosa riesco a fare, mà questo codice a me non mi funziona bene.
    Se mi dite che è funzionante, ci riprovo ancora anche se non capisco il motivo.
    Idem per quello che stavo creando ieri in base alle ultime richieste (dovevo per forza selezionare il foglio2).
    Sarebbe stato un controllo preleminare se esisteva il numero esatto dopo di che pensavo di fare un qualcosa.

    Es come scritto ci potrebbero essere 4/5 celle da verificare in 4/5 colonne per circa 3000 dati.
    Confrontare 1 cella per 3000 = 3000
    Confrontarlo per 5 colonne = 15000
    Controntare 5 celle = 75000 operazioni

    Ci deve essere un "qualcosa" più veloce.
    Col VLOOKUP troviamo il numero precedente.

    Ora mi ricordo "un qualcosa" che se richiedevo il primo numero superiore dopo un determinato numero
    Purtroppo non ricordo la struttura.

    Ps. In questo caso farebbe pochissimi controlli.



  • di Alone (utente non iscritto) data: 07/12/2013 14:30:18

    Ciao Raffaele! Guardo ho fatto girare il codice su un foglio excel con una colonna con un 20 elementi e gira tranquillamente. Come dici tu effettivamente per l'uso che ne andrei a fare con un 3000 (se non di più) il tutto si rallenta abbastanza.

    La mia idea è questa:
    X=il mio dato
    B1:B3000=vettore colonna
    - Dato il valore da ricercare vado nel mezzo della mia colonna (inizio il controllo da B1500).
    - Se il valore (X) è maggiore del mio.. continuo la ricerca a ritroso (da B1500 a B1)
    - Se il valore è minore.. cerco nella seconda parte della colonna. (da B1500 a B3000)
    Questo mi permetterebbe di:
    1 - non controllare tutta la colonna
    2 - fermarmi molto prima dei 1500 controlli perchè.. perchè mi aspetto che sulle code la probabilatà di accadimento sia minore rispetto ai valori centrali.
    Tutto ciò ovviamente è implementabile se la colonna è ordinata.

    Cosa ne pensate?..
    Cmq questo forum è pazzesco.. Siete dei grandi :) .. Grazie mille a tutti per l'aiuto



  • di Mister_x (utente non iscritto) data: 07/12/2013 16:40:24

    ciao

    non mi sembra necessari fare su e giu per il range quando con un For Each si puo' risolvere in questo caso in un centesimo di secondo
    questa e' la sub che ho elaborato in base ai tuoi dati
    da mettere nel foglio di utilizzo

    ciao Mister_x
     
    Option Explicit
    
    Sub Valore_trov_min()
    Dim colonnaB_B As Range, B_B As Variant
    Dim valore1 As Single, val_ris As Single
    Dim Nriga As Long
    Set colonnaB_B = Range("B2:B3000")
    valore1 = Range("D2")
    val_ris = 0
    Application.Calculation = xlManual
    For Each B_B In colonnaB_B
     If B_B <= valore1 And B_B > val_ris Then
      val_ris = B_B
      Nriga = B_B.Row
     End If
    Next
    Range("F2") = val_ris
    Set colonnaB_B = Nothing
    MsgBox "Numero riscontrato " & val_ris & "cella B" & Nriga
    Application.Calculation = xlAutomatic
    End Sub
    






  • di Alone (utente non iscritto) data: 07/12/2013 17:16:48

    @Mister_X
    Ciao.. Grazie per il contributo!! Effettivamente potrebbe sembrare una cosa abbastanza inutile.
    Tuttavia questa operazione molto probabilmente andrò a farla un 3/4 volte su 3/4 colonne diverse. Ho fatto l'esempio di 3000 ma potrebbero essere molti di più.. Non ne capisco granchè di visual basic purtroppo e non so se questo può pesare o meno.. Se si tratta di millesimi di secondi ovviamente non importa :D!!

    In ogni modo proverò il tuo codice... ma ci sta un modo per non mettere la dimensione del range ma la rilevi da solo? Mi spiego meglio può darsi che avrò una colonna da 3000 una da 5000 non lo so.. come posso fare la prendera dimensione senza dichiararla io?

    grazie ancora!!!



  • di Raffaele_53 (utente non iscritto) data: 07/12/2013 18:09:52

    >>>i casi possono essere multipli,(fare su e giu per il range)

    Senza offesa me la puoi spiegare (se l'ho desideri)



  • di Alone (utente non iscritto) data: 07/12/2013 20:42:26

    @Raffaele_53

    Ciao...La precedente affermazione di Mister_X: "Fare su e giù per il range".. è riferita alla mia proposta di iniziare il controllo partendo da meta vettore ed eventualmente decidere se continuare la ricerca su o giù nel range. Tuttavia come mi state più volte evidenziando, una soluzione del genere è inutile perchè parliamo comunque di operazioni che spaccano il secondo.

    Correggetemi se sbaglio! Sono in questo forum non solo per risolvere un problema, ma soprattutto voglio imparare da gente più preparata di me in materia

    Grazie!!



  • di Raffaele_53 (utente non iscritto) data: 07/12/2013 23:58:30

    Non era riferito a Te

    Mi chiedevo solo (il primo codice non mi funzionava)
    Ora elaborare tante celle, mi sembra non idoneo

    Non saprei adesso, il minimo l'ho già trovato
    Mi manca il superiore con solo qualche dritta in VBA

    Vedrò bene il codice ni Mister_X



  • di paolomath data: 08/12/2013 00:06:26

    Ciao,

    scusate se ripondo solo ora:

    @Alone:

    >>>- Dato il valore da ricercare vado nel mezzo della mia colonna (inizio il controllo da B1500).
    >>>- Se il valore (X) è maggiore del mio.. continuo la ricerca a ritroso (da B1500 a B1)
    >>>- Se il valore è minore.. cerco nella seconda parte della colonna. (da B1500 a B3000)
    ...

    Questo è un algoritmo che può essere implementato se sai a priori che il tuo vettore è ordinato in modo crescente. Nella tua richiesta questo non era specificato.

    @Mister_x

    Stesso discorso, il codice che hai proposto non funziona se non è presente un ordinamento crescente, o se devi cercare numeri negativi. Prova ad esempio a cercare 2,15 nel vettore
    1
    2,2
    2,151
    2,3

    Oppure -3 nel vettore
    2
    -3
    2,1

    Non sapendo come era strutturato il tuo vettore (ordinato o meno, contiene o cerchi numeri negativi) ho solo cercato di essere più generale possibile.

    Bye bye.



  • di Alone (utente non iscritto) data: 08/12/2013 00:45:48

    @Paolo_math
    Ciao! per quanto riguarda l'ordinamento ne sono consapevole
    Infatti il mio vettore non è ordinato e non l'avevo specificato. pensavo però che fosse risolvibile con una funzione al massimo..
    Mentre per quanto riguarda la dimensione della colonna? come posso ovviare al problema di dare una dimensione fissa??

    Grazie!



  • di Mister_x (utente non iscritto) data: 08/12/2013 21:32:00

    per paolomath

    la sub() che ho passato, ha questa non interessa minimamente l'ordinamento dal piu' piccolo al piu' grande o viceversa, dato che utilizza le variabili per confronto alle celle, quindi non vedo dove dici che non funziona
    ti rispondo che nel primo caso dato che questi cerca il valore uguale o piu' piccolo se tu metti un valore di ricerca di 2,15 con i tuoi dati di riporta il valore di 1 , perche' 2,2 2,151 2,3 sono maggiori di 2,15
    comunque secondo te' cosa doveva trovare in questo caso
    seconda cosa tu ai messo un -3, ma in principio non si parlava di numeri inferiori allo 0
    comunque se proprio vuoi fare anche questo basta che alla variabile
    val_ris = 0 metti un bel
    val_ris = -99999
    e ti calcola anche i valori minori di 0

    ciao Mister_x





  • di Mister_x (utente non iscritto) data: 08/12/2013 22:03:01

    ciao Alone

    ti passo la sub() modificata nel suo insieme dove tu in
    A1 metti il valore da cercare
    A2 la colonna di ricerca
    e alla riga 1 della colonna di ricerca ti mette il valore cercato e la posizione della cella di riferimento con i riferimenti assoluti
    questa desso calcola da sola la fine della colonna iniziando sempre dalla riga 2 e dato che si e' detto anche di valori negativi ho gia' apportato io la modifica

    ciao Mister_x
     
    Option Explicit
    
    Sub Valore_trov_min()
    Dim colonnaB_B As Range, B_B As Variant
    Dim valore1 As Single, val_ris As Single
    Dim Nriga As Long
    Set colonnaB_B = Range(Cells(2, [A2]), Cells(Cells(Rows.Count, [A2]).End(xlUp).Row, [A2]))
    valore1 = Range("A1")
    val_ris = -999999
    Application.Calculation = xlManual
    For Each B_B In colonnaB_B
     If B_B <= valore1 And B_B > val_ris Then
      val_ris = B_B
      Nriga = B_B.Row
     End If
    Next
    Cells(1, [A2]) = val_ris & " - " & Cells(Nriga, [A2]).Address
    Set colonnaB_B = Nothing
    MsgBox "Numero riscontrato " & val_ris & " - " & Cells(Nriga, [A2]).Address
    Application.Calculation = xlAutomatic
    End Sub






  • di scossa data: 08/12/2013 22:07:04

    Propongo una variante al codice di Mister_x senza ciclo For..Next, ed una UDF che richiede come argomenti il valore da trovare ed il range di ricerca, restituendo il valore più vicino minore del valore cercato
    esempio =MagMinDi(A1;B2:B3000)
     
    Public Sub MagMinoreDi()
      Dim colonnaB_B As Range, B_B As Variant
      Dim valore1 As Double, val_ris As Double
      Set colonnaB_B = Range("B2:B3000")
      valore1 = Range("D2").Value
      val_ris = Evaluate("MAX(IF(" & colonnaB_B.Address & "<" & valore1 & "," & colonnaB_B.Address & "))")
      B_B = colonnaB_B.Find(val_ris).Address
      MsgBox "Numero riscontrato " & val_ris & " nella cella " & B_B
    End Sub
    
    
    Public Function MagMinDi(ByVal nVal As Double, rRange As Range) As Double
      MagMinDi = Evaluate("MAX(IF(" & rRange.Address & "<" & nVal & "," & rRange.Address & "))")
    End Function
    



  • di Alone (utente non iscritto) data: 08/12/2013 23:13:38

    @Scossa @MrX
    Grazie mille ragazzi..Siete grandi veramente..La disponibilità che ho trovato in questo forum, mai avuta prima :D!!!

    Grazie a tutti veramente!!



  • di Mister_x (utente non iscritto) data: 08/12/2013 23:20:13

    ciao Scossa

    attenzione che la funzione Find trova il primo valore uguale in un insieme di valori
    in questo caso, se tu hai il file in oggetto e metti in D2 il valere 11 questa ti riportera' si il valore min.o.uguale che e' 10 ma ti dice che in MsgBox si trova alla cella $B$9 mentre in realta' questi e' alla cella $B$148 e alla cella B9 abbiamo il valore di 2510 che e' il primo 10 scorporato dalla stringa incontrato

    quindi bisogna utilizzare unaltra funzione per intercettare tale cella

    ciao Mister_x

    PS Bella la funzione Proposta con Evaluate() , me la segno nelle mie scartoffie per ricordarmela





  • di paolomath data: 08/12/2013 23:27:04

    @ Mister_x

    >>ti rispondo che nel primo caso dato che questi cerca il valore uguale o piu' piccolo se tu metti un valore di ricerca di 2,15 con i tuoi dati di riporta il valore di 1 , perche' 2,2 2,151 2,3 sono maggiori di 2,15
    comunque secondo te' cosa doveva trovare in questo caso

    Dovrebbe trovare 2,151 in quanto era richiesto il valore più vicino a quello da ricercare, non quello più vicino E minore di quello da ricercare.

    In principio non si parlava di numeri inferiori a 0 ma neppure SOLO di numeri maggiori di 0.

    Bye bye.



  • di scossa data: 08/12/2013 23:40:33

    cit: "attenzione che la funzione Find trova il primo valore uguale in un insieme di valori
    in questo caso, se tu hai il file in oggetto e metti in D2 il valere 11 questa ti riportera' si il valore min.o.uguale che e' 10 ma ti dice che in MsgBox si trova alla cella $B$9 mentre in realta' questi e' alla cella $B$148 e alla cella B9 abbiamo il valore di 2510 che e' il primo 10 scorporato dalla stringa incontrato

    quindi bisogna utilizzare unaltra funzione per intercettare tale cella "


    Basta aggiungere il parametro lookat:=xlWhole


     
    B_B = colonnaB_B.Find(val_ris, lookat:=xlWhole).Address



  • di Textomb data: 08/12/2013 23:43:03

    @ Scossa.
    Bella la funzione proposta. Con una sola riga hai evitato un ciclo.
    L'ho provata da sola nella barra della formula e funziona. Ovviamente bisogna dargli il ctrl shift Invio.
    Non pesavo che Evaluate riuscisse ad essere così potente.



  • di scossa data: 08/12/2013 23:48:31

    cit. Textomb: "Ovviamente bisogna dargli il ctrl shift Invio."

    No, basta confermare con il semplice invio!



  • di scossa data: 08/12/2013 23:49:54

    Ops, scusa, intendevo la UDF, non la formula scritta in una cella.



  • di Textomb data: 08/12/2013 23:57:09

    probabilmente mi sono espresso male. Scusami.
    Intendevo dire che ho scritto, nella barra della formula, la seguente espressione
    ={MAX(SE(B1:B3000Il mio stupore si riferiva al fatto che Evaluate riuscisse ad eseguire una funzione matriciale.
    Non lo sapevo!!!
    Ottimo.



  • di Textomb data: 08/12/2013 23:58:58

    cioè volevo scrivere...
    ={MAX(SE(B1:B33



  • di paolomath data: 09/12/2013 08:25:59

    Ciao,

    buono l'uso della funzione matriciale.

    Ma scusate:

    val_ris = Evaluate("MAX(IF(" & colonnaB_B.Address & "<" & valore1 & "," & colonnaB_B.Address & "))")

    trova il massimo dei valori + piccoli rispetto a quello da cercare. La ricerca andava fatta sul numero che si discosta di MENO da quello da cercare (che non è detto sia più piccolo). O mi sono perso qualcosa ?

    Hai provato con i numeri decimali?

    Bye



  • di scossa data: 09/12/2013 08:40:51

    cit. paolomath: "O mi sono perso qualcosa "




    Domanda di Canapone: "nel caso tu stia cercando 10 e nell'elenco compaia 9 e 11, a parità di scostamento, ti serve individuare il più piccolo o il più grande dei due."

    Risposta di Alone (OP): "Domanda interessante :)!! Vorrei prendere il più **piccolo** :).. Grazie per la risposta"

    Quindi il tuo assunto: "La ricerca andava fatta sul numero che si discosta di MENO da quello da cercare" non è corretto.



  • di scossa data: 09/12/2013 08:42:36

    Però, però ..... forse mi sono perso qualcosa io ... "a parità di scostamento" ... muble..... muble......, mi sa che ho capito male la richiesta, sorry.



  • di paolomath data: 09/12/2013 08:45:55

    Ciao,

    "nel caso tu stia cercando 10 e nell'elenco compaia 9 e 11, a parità di scostamento"
    dovrebbe voler dire che SE ci sono DUE numeri che si discostano del solito valore (uno in + e uno in -) si vuole quello minore. Se ce n'è solo uno, ma è più grande, va bene quello .

    Se ad Alone poi va bene la ricerca del MAX dei minori, va bene anche a me.
    Ma comunque non è quello richiesto

    Bye.



  • di scossa data: 09/12/2013 08:46:43

    Infatti (vedi mio ultimo post).



  • di paolomath data: 09/12/2013 08:47:23



    Abbiamo scritto insieme.



  • di scossa data: 09/12/2013 09:31:11

    Allora ripropongo le due versioni (Sub ed UDF) senza ciclo For ... Next.

    Esempio di uso dell'UDF:
    =ValVicino(A1;B2:B3000)


     
    '--------------------  La sub  ------------------------------------
    '
    Public Sub ValoreProssimo()
      Dim rCerca As Range, sAddress As Variant
      Dim nCerca As Double, nValRis As Double
      Dim nValMin As Double, nValMax As Double
      Set rCerca = Range("B2:B3000")
      nCerca = ActiveSheet.Range("F2").Value
      nValMax = Evaluate("MAX(IF(" & rCerca.Address & "<" & nCerca & "," & rCerca.Address & "))")
      nValMin = Evaluate("MIN(IF(" & rCerca.Address & ">" & nCerca & "," & rCerca.Address & "))")
      nValRis = IIf((nValMin - nCerca) < (nCerca - nValMax), nValMin, nValMax)
      sAddress = rCerca.Find(nValRis).Address
      MsgBox "Numero riscontrato " & nValRis & " nella cella " & sAddress
      Set rCerca = Nothing
    End Sub
    
    
    '--------------------  UDF  ------------------------------------
    ' 
    Public Function ValVicino(ByVal nVal As Double, rRange As Range) As Double
      Dim nMin As Double, nMax As Double
      nMin = Evaluate("MIN(IF(" & rRange.Address & ">" & nVal & "," & rRange.Address & "))")
      nMax = Evaluate("MAX(IF(" & rRange.Address & "<" & nVal & "," & rRange.Address & "))")
      ValVicino = IIf(nMin - nVal < nVal - nMax, nMin, nMax)
    End Function



  • di paolomath data: 09/12/2013 09:51:50

    Ciao,

    dovresti mettere ">=" e "<=" al posto di ">" e "<" altrimenti perdi la corrispondenza esatta.

    >>Hai provato con i numeri decimali ? (Autocitazione).

    Bye.



  • di scossa data: 09/12/2013 10:16:09

    >>Hai provato con i numeri decimali ? (Autocitazione).

    Sì, e mi sembra funzionare perfettamente (almeno le prove che ho fatto) anche coi numeri negativi.
     
    '--------------- sub  --------------------
    Public Sub ValoreProssimo()
      Dim rCerca As Range, sAddress As Variant
      Dim nCerca As Double, nValRis As Double
      Dim nValMin As Double, nValMax As Double
      Set rCerca = Range("B2:B3000")
      nCerca = ActiveSheet.Range("F2").Value
      nValMax = Evaluate("MAX(IF(" & rCerca.Address & "<" & nCerca & "," & rCerca.Address & "))")
      nValMin = Evaluate("MIN(IF(" & rCerca.Address & ">=" & nCerca & "," & rCerca.Address & "))")
      nValRis = IIf((nValMin - nCerca) < (nCerca - nValMax), nValMin, nValMax)
      sAddress = rCerca.Find(nValRis).Address
      MsgBox "Numero riscontrato " & nValRis & " nella cella " & sAddress
    End Sub
    
    
    '--------------- UDF --------------------
    Public Function ValVicino(ByVal nVal As Double, rRange As Range) As Double
      Dim nMin As Double, nMax As Double
      nMin = Evaluate("MIN(IF(" & rRange.Address & ">=" & nVal & "," & rRange.Address & "))")
      nMax = Evaluate("MAX(IF(" & rRange.Address & "<" & nVal & "," & rRange.Address & "))")
      ValVicino = IIf(nMin - nVal < nVal - nMax, nMin, nMax)
    End Function
    
    



  • di scossa data: 09/12/2013 10:18:26

    Ho allegato un file di esempio.



  • di paolomath data: 09/12/2013 10:29:22

    E se in F2 metti 6,2 ???



  • di scossa data: 09/12/2013 10:51:52

    cit. paolomath: "E se in F2 metti 6,2 ??? "

    Interessante.
    Il problema è legato alla "localizzazione" e quindi all'uso della , come separatore decimale.

    Si dovrebbe risolvere come da codice sotto:
     
    Public Sub ValoreProssimo()
      Dim rCerca As Range, sAddress As Variant
      Dim nCerca As Double, nValRis As Double
      Dim nValMin As Double, nValMax As Double
      Dim rTarget As Range
      
      Set rCerca = Range("B2:B3000")
      Set rTarget = ActiveSheet.Range("F2")
      
      nCerca = rTarget.Value
      nValMax = Evaluate("MAX(IF(" & rCerca.Address & "<" & rTarget.Address & "," & rCerca.Address & "))")
      nValMin = Evaluate("MIN(IF(" & rCerca.Address & ">=" & rTarget.Address & "," & rCerca.Address & "))")
      nValRis = IIf((nValMin - nCerca) < (nCerca - nValMax), nValMin, nValMax)
      sAddress = rCerca.Find(nValRis).Address
      MsgBox "Numero riscontrato " & nValRis & " nella cella " & sAddress
      Set rCerca = Nothing
      Set rTarget = Nothing
    End Sub
    
    Public Function ValVicino(ByVal nVal As String, rRange As Range) As Double
      Dim nMin As Double, nMax As Double
      nVal = Replace(nVal, ",", ".")
      nMin = Evaluate("MIN(IF(" & rRange.Address & ">=" & nVal & "," & rRange.Address & "))")
      nMax = Evaluate("MAX(IF(" & rRange.Address & "<" & nVal & "," & rRange.Address & "))")
      ValVicino = IIf(nMin - nVal < nVal - nMax, nMin, nMax)
    End Function
    



  • di scossa data: 09/12/2013 11:04:34

    Correzione al codice (arrotondamento):
     
    Public Sub ValoreProssimo()
      Dim rCerca As Range, sAddress As Variant
      Dim nCerca As Double, nValRis As Double
      Dim nValMin As Double, nValMax As Double
      Dim rTarget As Range
      
      Set rCerca = Range("B2:B3000")
      Set rTarget = ActiveSheet.Range("F2")
      
      nCerca = rTarget.Value
      nValMax = Evaluate("MAX(IF(" & rCerca.Address & "<" & rTarget.Address & "," & rCerca.Address & "))")
      nValMin = Evaluate("MIN(IF(" & rCerca.Address & ">=" & rTarget.Address & "," & rCerca.Address & "))")
      nValRis = IIf((Round(nValMin - nCerca, 10) < Round(nCerca - nValMax, 10)), nValMin, nValMax)
      sAddress = rCerca.Find(nValRis).Address
      MsgBox "Numero riscontrato " & nValRis & " nella cella " & sAddress
      Set rCerca = Nothing
      Set rTarget = Nothing
    End Sub
    
    Public Function ValVicino(ByVal nVal As Double, rRange As Range) As Double
      Dim nMin As Double, nMax As Double
      Dim sVal As String
      
      sVal = Replace(nVal, ",", ".")
      
      nMin = Evaluate("MIN(IF(" & rRange.Address & ">=" & sVal & "," & rRange.Address & "))")
      nMax = Evaluate("MAX(IF(" & rRange.Address & "<" & sVal & "," & rRange.Address & "))")
      ValVicino = IIf(Round(nMin - nVal, 10) < Round(nVal - nMax, 10), nMin, nMax)
    End Function



  • di paolomath data: 09/12/2013 11:14:23

    Ciao,

    Anche "<=" al posto di "<" altrimenti perdi la corrispondenza esatta. (ad esempio -2,9)

    Inoltre ci vuole un controllo sulla ricerca di valori maggiori del + grande valore nella lista e minori del + piccolo valore nella lista.

    Alla fine non è poi così "pulita" come sembrava .

    Non ci sono cicli ma un bel po' di altre condizioni.

    Bye.



  • di paolomath data: 09/12/2013 11:19:45

    Ho scritto prima di vedere la "correzione", l'arrotondamento serve?
    In pratica introduci nel ciclo la valutazione di 2 funzioni in più senza aumentare la leggibilità.

    Bye



  • di scossa data: 09/12/2013 11:37:45

    cit.: "l'arrotondamento serve?"

    Purtoppo sì.
    Valore 6,2
    in colonna B sia 6,1 che 6,3

    nella finestra immediata prova:



     
    ?nMin
     6,3 
    ?nMax 
     6,1 
    ?(nMin - nVal)
     9,99999999999996E-02 
    ?(nVal - nMax)
     0,100000000000001 
    ?(nMin - nVal) < (nVal - nMax)
    Vero
    ?(nMin - nVal) < (nVal - nMax)
    Vero
    ?nMin
     6,3 
    ?nMax 
     6,1 
    ?(nMin - nVal)
     9,99999999999996E-02 
    ?(nVal - nMax)
     0,100000000000001 
    ?(nMin - nVal) < (nVal - nMax)
    Vero
    ?round(nMin - nVal,10) < round(nVal - nMax,10)
    Falso
    



  • di Raffaele_53 (utente non iscritto) data: 09/12/2013 15:14:53

    Ciao a tutti
    Tre giorni che ci provo (ieri sera trovavo differenze tra il MIN e MAX di "scossa")
    Come detto qualche post fà, l'ultima richiesta è stata fatta per dei valori di 4/5 celle in 4/5 colonne.
    Il tutto mi sembrava NON pesante, mà troppi calcoli per ottenere il fabbisogno.

    Sono ritornato sui miei passi e sono riuscito a fare un qualcosa.
    Si tratta, mà questo non lo sò se si può fare(di ordinare le colonne del foglio2 crescente). Usare solo il cerca.vert per trovare il più vicno sotto e il alto sopra.
    Se interessa lo inserisco (operazioni moltiplicate per 5 colonne un centinaio)



  • di Alone (utente non iscritto) data: 09/12/2013 22:01:16

    Grazie a tutti ragazzi!! Ho risolto! :) siete grandissimi!!