Hojas de cálculo en Excel - página principal

Números aleatorios no repetidos

Ya hemos visto en varios artículos donde a través de unos ejemplos, ilustrábamos el uso de los números aleatorios. Entre ellos, una mini aplicación para obtener combinaciones de 6 números al azar entre 49 números, como hacer una tontería a través de números aleatorios dando el efecto de una máquina tragaperras, y como desplazarnos a una celda de forma aleatoria. En el primero de los ejemplos, a través de funciones propias de excel, y usando un bucle do while, íbamos controlando que no se repitieran los números aleatorios.

Ahora vamos a hacer eso mismo, pero utilizando exclusivamente funciones de visual basic para aplicaciones (VBA). Antes de poner el código, vamos a explicar como funcionará este sistema. En nuestro ejemplo generaremos tres números entre el 1 y el 100, y lo primero que haremos será generar un número aleatorio. En cuanto tengamos ese primer numerito, lo añadiremos al carro de la compra (valga el simil). A continuación generaremos un segundo número aleatorio, y comprobaremos si ya lo tenemos en el carrito de la compra (porque puede ser que el segundo número generado, sea igual que el primero). Si no lo tenemos en el carrito, lo añadiremos, y si ya lo tenemos previamente en el carrito, generaremos un nuevo número hasta encontrar uno que no tengamos en el carrito, y en ese momento lo añadiremos. Finalmente haremos lo mismo con el tercer número.

Una vez hecho eso, tendremos un carrito de la compra, donde habremos metido 3 números elegidos al azar. Estos números estarán separados por comas. Para llamar a cada uno de los números, nos bastará finalmente con buscar el elemento del carrito (del array): elemento 0, elemento 1, y elemento 2, …recordemos que por defecto, el elemento cero es el primero de la lista.

Esta sería una propuesta, para solucionar el problema de los números aleatorios y que no salgan repetidos:


Sub aleatorios_no_repetidos()
'llamamos a la función randomize,
'para que todo funcione correctamente

Randomize
'indicamos el nº máximo y el mínimo
maximo = 100
minimo = 1
For i = 1 To 3
'generamos el primer nº aleatorio
registro_obtenido = Int((maximo - minimo + 1) * Rnd + minimo)
'generamos un aleatorio hasta encontrar uno no repetido
Do While InStr(numeros, " " & registro_obtenido & ",") > 0
'lo añadimos al array
registro_obtenido = Int((maximo - minimo + 1) * Rnd + minimo)
Loop
'lo añadimos al array
numeros = numeros & " " & registro_obtenido & ","
Next
'quitamos la última coma
numeros = Mid(numeros, 1, Len(numeros) - 1)
'formamos un array como Dios manda
numeros = Split(numeros, ", ")
'escribiremos los números aleatorios
'en las celdas A1, A2, y A3

Range("A1") = numeros(0)
Range("A2") = numeros(1)
Range("A3") = numeros(2)
End Sub

Desde aquí podéis descargar el fichero, con el ejemplo que hemos visto en este artículo.



22 comentarios:

ElProfe dijo...

Apreciado Javier Marco:

Modestamente dices que "Si la información que has encontrado en este blog ha sido de tu interés, te agradecería que dejases un comentario ;-)"

Pues permíteme decirte que la información de tu blog no solo resulta de mi total interés, sino que es espectacularmente buena, útil, práctica, sencilla y te encargas de trasmitirla de una manera tan didáctica que difícilmente se podría pedir más!

De mi parte (y muy seguramente en nombre de muchos de tus lectores) recibe mis sinceros agradecimientos y mi especial reconocimiento por compartir tu conocimiento con el resto del mundo.

Saludos desde Colombia

Juan M. Beltrán V.

El pilt®afilla - www.3piesalgato.com dijo...

Muchas gracias por tu comentario. Me alegro que la información que has encontrado te haya sido útil.

Resultan tremendamente motivadores, los mensajes de aliento como el que acabo de leer.

Un saludo.

Anónimo dijo...

Javier Marco:
He tratado de utilizar el codigo para obtener 90 registros de un máximo de 500 numeros pero en el array se generan duplicados, te agradecería me des una mano.

Saludos

Fernando

Anónimo dijo...

Desde Universo de Marti, me complace hacerle entrega del Premio Blog de Oro.

Enhorabuena!!

http://universodemarti.blogspot.com

Kased dijo...

Muy bueno el codigo, no tenes idea el tiempo que perdi tratando de hacer algo parecido. Te felicito por la explicacion, muy sencilla.
Ahora tengo una consulta. Al codigo le coloque una variable para la cantidad de numeros aleatorios no repetidos, como puedo hacer para volcar todos los resultados en un rango de celdas??
Desde ya muchas gracias.

El pilt®afilla - www.3piesalgato.com dijo...

Puedes utilizar un bucle do while, para buscar la primera fila vacía, y empezar a escribir ahí. Échale un vistazo al blog, porque en muchos artículos uso ese tipo de bucle.

Anónimo dijo...

Javier, excelente tus articulos, dificilmente los podremos encontrar en otra parte con la misma explicacion tan sencilla y de tanta variedad de ejemplos, te felicito.

por otra parte, esta macro funciona muy bien, de 100 te da 3 numeros aleatorios, el problema que yo tengo es que le pongo minimo=1 maximo=12 y en el bucle le pongo for i = 1 to 12 porque quiero que los 12 numeros me los de aleatoriamente y la macro se me cicla y no logro detenerla hasta que cierro todo excel, ¿como corrijo esto?, pues yo quiero que de 12 numeros me de los 12 aleatorios.

El pilt®afilla - www.3piesalgato.com dijo...

Tienes toda la razón del mundo. Había un error en el macro, que hacía qeu en determinadas ocasiones, se entrase en un bucle.

Acabo de arreglarlo, y ya funciona (he editado el código del macro). Puedes probar a generar 12 aleatorios de 12 números, para que te los saque de forma discontínua y al azar, sin ningún problema.

También he resubido el ejemplo para descargar.

Muchas gracias por tu comentario.

Anónimo dijo...

te agradezco bastante al correccion

es muy bueno contar con el apoyo de personas como tú

saludos

Anónimo dijo...

¡Me acabas de salvar la vida! Muchísimas gracias.

Un saludo.

grovertapia dijo...

Excelente, cada vez más me convenzo que excel es una súper herramienta. Gracias por ilustrarme Maestro.

JoaoM dijo...

Coloco maximo en 999.

me presentará; 1, 2 y 3 numeros.
Seria posible que:
Cuando presente un numero solamente, me presente Ej. 005 o 011? y no 5 o 11?

Gracias

El pilt®afilla - www.3piesalgato.com dijo...

Debajo de esta línea:

registro_obtenido = Int((maximo - minimo + 1) * Rnd + minimo)

Pon esta otra (todo en una línea):

If Len(registro_obtenido) < 3 Then registro_obtenido = String(3 - Len(registro_obtenido), "0") & registro_obtenido

Luego, cambia esta línea:

numeros = numeros & " " & registro_obtenido & ","

Por esta otra, para eliminar el primer espacio vacío del primer número generado:

numeros = Trim(numeros & " " & registro_obtenido & ",")

Por último, a las celdas donde vayas a poner los números, dale formato de texto, para que no te desprecie los ceros de delante, porque sino, verás lo mismo que en el ejemplo del artículo.

Saludos.

JoaoM dijo...

No me funciona. Sigue presentando 4, 8, 11, 86 en ves de 004, 008, 011, 086

El pilt®afilla - www.3piesalgato.com dijo...

Debería funcionarte, si como te comentaba antes, le das formato de texto a las celdas donde vas a presentar los números aleatorios, es decir en A1, A2, y A3.

JoaoM dijo...

Aun con formato texto, no dá.
Probe desde un Formulario y lo mismo.

Lo del ImputBox, ya veremos el porque se esconde y de este, bueno, si tiene solucion agradezco un aviso porque queria usar el codigo en una suerte de terminales(3 numeros) pata jugar y para eso, tiene que estar los ceros cuando presente 4 o 80 356 (004, 080, 356)

El pilt®afilla - www.3piesalgato.com dijo...

En lugar de poner esto:

Range("A1") = numeros(0)
Range("A2") = numeros(1)
Range("A3") = numeros(2)

Por esto otro, y verás lo que obtienes:

MsgBox (numeros(0))
MsgBox (numeros(1))
MsgBox (numeros(2))

Comprobarás como obtienes los números con cero delante (siempre con 3 caracteres: 001, 023, 100, 095, etc.). Por tanto, es un tema de formato de la celda. Juega con los formatos, a ver si hay alguno que te lo muestre con formato de texto.

Otra opción es cambiar esto:

Range("A1") = numeros(0)
Range("A2") = numeros(1)
Range("A3") = numeros(2)

Por esto otro:

Range("A1") = "'" & numeros(0)
Range("A2") = "'" & numeros(1)
Range("A3") = "'" & numeros(2)

Saludos.

JoaoM dijo...

Tu insistencia en querer ayudarme, te la agradezco imensamente.

He probado con casi todos los formatos de celdas. en columnas a,B y C doy formato texto y nada, siempre me presenta 11 en ves de 011.
No voy a seguir molestandote con lo mio, vere como hago o desisto del tema.
Gracias por todo tu tiempo empleado

JoaoM dijo...

Tanto es que si inserto manualmente un numero (Ej. 025 o 0000025) si aparece tal como lo inserto porque están en formato texto las 3 columnas.
Digo columnas porque cambie de A1,A2,A3 a A, B, Y C

JoaoM dijo...

monte un formuklario con 3 textBox y tampoco me dá el cero.
Pongo una nota en un label que diga; los que salgan solamente 1 o 2 numeros, se le agregan 1 o 2 ceros Ej. 5 (005) 40 (040) y asi a ver si me va con el juego

JoaoM dijo...

tampoco cambiendo TextBox por Label.
Voy hacer como dije antes, un Label advertiendo la forma

JoaoM dijo...

ya vi que es una cuestion de transmision, de la macro hacia las celdas