lunes, 24 de noviembre de 2008

Generación de números aleatorios únicos (sin repetición)

Descargar el fichero RNDunicos.xlsm


Generar números aleatorios en Excel es tarea sencilla. Con la función =ALEATORIO(), con la función =ALEATORIO.ENTRE, y en lenguaje de Visual Basic con la función RND, que es la abreviatura de random. Por el contrario, si lo que deseamos es generar una serie de números aleatorios sin repetición la tarea se complica un poco, ya que debemos ir comprobando por cada número nuevo, si se encuentra entre los anterioremente generados y en caso afirmativo desecharle y generar otro.



La siguiente macro nos permite realizar la tarea descrita.


Código:

Sub unicos1()
Dim i As Integer, j As Integer
Dim A() As Long
Dim esta As Boolean
Dim x As Long, y As Long, z As Long, num As Long
x = Application.InputBox(prompt:="Entre el número aleatorio inicial" _
        , Title:="Generador de Números Aleatorios", Default:=1, Type:=1)
y = Application.InputBox(prompt:="Entre el número aleatorio final" _
        , Title:="Generador de Números Aleatorios", Default:=1000, Type:=1)
z = Application.InputBox(prompt:="¿Cuantos números aleatorios desea generar?" _
        & " (<15000 _="" default:="100," exit="" if="" sub="" then="" title:="Generador de Números Aleatorios" type:="1)" z=""> 15000 Then z = 15000
If z > y - x + 1 Then
    MsgBox "!Ha especificado más números " _
    & "de los que son posibles en el rango!"
    Exit Sub
End If
ReDim A(z)
Randomize
A(1) = Int((y - x + 1) * Rnd + x)
For i = 2 To z
    Do
        num = Int((y - x + 1) * Rnd + x)
        esta = False
        For j = 1 To i - 1
           If num = A(j) Then esta = True: Exit For
        Next j
    Loop While esta
    A(i) = num
Next i
For i = 1 To z
    Cells(i, 2) = A(i)
Next i
End Sub

Existe otra variante de esta macro que utiliza el comando Find para buscar el nuevo número aleatorio generado entre los anteriores. Si le encuentra entre los ya generados en la columna B buscará un nuevo número aleatorio. Al comando Find es necesario añadirle la propiedad LookAt:=xlWhole para que localice exactamente el número buscado. Si esto no se hiciera así, sucede que busca por las cifras, y si esta buscando el número 1, piensa que se encuentra, por ejemplo, en la cifra 107, o en la 819, esto es, siempre que aparezca un 1.


Código:

Sub unicos2()
    Dim x As Long, y As Long, z As Long, num As Long
    Dim control As Boolean
    Dim i As Long
    Dim celda As Range
    x = Application.InputBox("Entre el número aleatorio inicial" _
        , "Generador de Números Aleatorios", 1, , , , , 1)
    y = Application.InputBox("Entre el número aleatorio final" _
        , "Generador de Números Aleatorios", 1000, , , , , 1)
    z = Application.InputBox("¿Cuantos números aleatorios desea generar?" _
        & " (<15000 100="" 1="" _="" aleatorios="" de="" enerador="" exit="" if="" meros="" n="" sub="" then="" z=""> 15000 Then z = 15000
    If z > y - x + 1 Then
        MsgBox "!Ha especificado más números " _
            & "de los que son posibles en el rango!"
        Exit Sub
    End If
    Randomize
    Cells(1, 2) = Int((y - x + 1) * Rnd + x)
    For i = 2 To z
        Do
            control = False
            Randomize
            num = Int((y - x + 1) * Rnd + x)
            Set celda = Range("b1", Range("b1").End(xlDown).Address). _
            Find(num, LookIn:=xlValues, LookAt:=xlWhole)
            If Not (celda Is Nothing) Then
                control = True
            End If
        Loop Until Not control
        Cells(i, 2) = num
    Next
End Sub

24 comentarios:

  1. Felicidades por la web y sus contenidos. He estado buscando como generar números aleatorios y justo estas instrucciones me vienen muy bien.

    La cuestión es que me he liado a la hora de indicar que comienze la serie de números en otra celda que no sea b1, por ejemplo si quisiera b10 que se modificaría del codigo

    muchas gracias

    ResponderEliminar
  2. Hola Reyes.

    Para comenzar en la celda B10, debes sustituir la línea de código que dice:

    Cells(i, 2) = A(i)

    por esta:

    Cells(i+9, 2) = A(i)

    La instrucción Cells(fila,columna) nos permite movernos por la hoja.

    La columna 2 es la B, y la fila i+9 es la fila 10 inicialmente ya que i comienza en 1.

    Espero que te sea de utilidad esta macro.

    Un cordial saludo.

    Adolfo Aparicio

    ResponderEliminar
  3. Muchísimas gracias, me ha sido muy útil. Felicidades por el trabajo.

    ResponderEliminar
    Respuestas
    1. hola buenas noches siguiendo este hilo si ponemos que empieze en b10 luego a cuando le damos a limpia no funciona, no entiendo nada de codigo si me podeis hechar un cable lo agradeceria mucho

      Eliminar
  4. He adaptado la idea que propones a un proyecto personal y he podido comprobar sus excelentes resultados. Gracias por esta gran aportación.

    ResponderEliminar
  5. Excelente aporte, Disculpen mi falta de conociemiento pero como podria hacer si quisiera que me ordenara en forma aleatoria unica numeros con extremo incial 1 y extremo final 100 y 100 numeros aleatorios a generar (por poner un ejemplo), pero que se repitera esta operacion hasta la fila 50,000 o mas pero solo con esos rangos y que inicie en la fila al final de cada 100

    ResponderEliminar
  6. Me ha servido de maravilla, que bueno tu trabajo, sigue así, existe muchisima gente que no conoce sobre este tema que es tu especialidad.
    Víctor - Perú

    ResponderEliminar
  7. Estimado Adolfo, buena tarde, me ha gustado mucho el sitio y más esta aportación pero mi duda es cómo poner esta macro en una hoja de excel, ya que no tengo ni idea de cómo hacerlo para que no abra el enlace de la página web. gracias

    ResponderEliminar
  8. Buen día, muy interesante y útil esta macro. Sin embargo, se pueden crear números aleatorios sin repetir, sólo con fórmulas, con la ayuda de la fórmula JERARQUIA. Saludos. Fabian Mesa. zabianza@gmail.com

    ResponderEliminar
  9. Hola Zabianza.

    Efectivamente se pueden generar números aleatorios únicos (sin repetición) basándonos en la función JERARQUIA, pero el proceso es laborioso. Se han de emplear varias columnas y celdas, y requiere intervención manual.

    Es cierto que como filosofía general debemos usar fórmulas preferiblemente a macros cuando ello es posible. En este caso se justifica la utilización de una macro que genere los aleatorios únicos por no necesitar la intervención del usuario.

    Es más, entendido el código lo puedes adaptar a tu proyecto personal, como ha realizado alguno de los amigos que han comentado previamente, y esto evitará que tengas que tocar lo más mínimo la hoja de cálculo para obtener los resultados pretendidos.

    ResponderEliminar
  10. Facinante, soy un principiante en las macros... y me gustaría saber como hacer para en vez de que se ordenen hacia abajo de ordenen a la derecha o izquierda...

    ResponderEliminar
  11. Hola Dracko.

    Para determinar la celda donde se escribe en la hoja de cálculo se utiliza el comando:

    CELLS(fila,columna)

    Si quieres escribir en horizontal, debes hacer variable la columna, y dejar fija la fila.

    Un saludo.

    ResponderEliminar
  12. genial, pero para lo que yo necesito me falta una cosa y no soy informatico. el tema es como pedirle numeros aleatorios pero sin repetir los que ya tengo en una lista previa, un otra hoja o incluso dentro de la misma, me es igual. muchas gracias

    ResponderEliminar
  13. Estoy muy agradecido por su información, gracias a la misma he podido completar mi proyecto.

    Generador de series dodecafonicas

    ResponderEliminar
  14. hola soy nuevo en esto de las macros, y me gustaría saber como hago que cada numero que me de lo ponga en una celda especifica ejemplo si creo 10 numero al asar sin repetir quiero que el primero numero dado se valla a la celada A2 y el segundo se valla a la celda D3 y el 3 a la Celda E5 y asi

    ResponderEliminar
  15. Buenas tardes, me ha servido muchisimo este macro, pero como puedo dividir los resultado en 2 columnas para no tener que andar bajando y subiendo.

    Gracias

    ResponderEliminar
  16. Usando esta macro modificada ¿cómo podría hacer el sorteo de uno en uno? Es decir, que en vez de elegir todos los números de golpe, vayan saliendo uno a uno, teniendo en cuenta que no se puede repetir uno que ya ha salido antes? Gracias

    ResponderEliminar
  17. Hola Adolfo. Es que aprendo mucho contigo y estoy sumamente agradecido. Ahora, tengo una duda y desearía que puedas ayudarme: necesito generar a partir de una lista de números dados de un dígito (máximo 10) que pueden repetirse, otra lista en la cual dichos números resulten combinados recíprocamente agrupados de a 4 que no pueden repetirse.
    Lo he intentado con la función combinat.entre pero no me resultao. Es que quizás me falta algo? o directamente el programa no puede ejecutar esta tarea?

    ResponderEliminar
    Respuestas
    1. Hola.
      Te dejo el link a un archivo que genera 4 aleatorios sin repetición que parten de una lista de 10 aleatorios con repetición. El fichero es el siguiente. Tiene una macro que se lanza con un botón.
      busca4aleatorios.xlsm

      Eliminar
  18. Estimado Adolfo:
    Hasta el día de hoy he buscado mucho e incansablemente los "números aleatorios sin duplicados". Le agradezco enormemente su trabajo. Con él he podido terminar un programa en excel que permite organizar torneos de gran importancia para el mundo del deporte del la petanca, al que yo pertenezco, y en el que durante dos jornadas pueden competir hasta 90 equipos o más. Mil gracias. enardiz@yahoo.es

    ResponderEliminar
  19. Estupendo aporte, Adolfo.
    Cómo habría que adaptar esta macro si, en vez de generar estos números aleatorios, hubiera que extraerlos, también de forma aleatoria, de una columna que ya contiene 300 registros.
    Muchísimas gracias.

    ResponderEliminar