Curso Básico de Programación
en Visual Basic
Entrega
Trece: 10/Feb/98
por Guillermo "guille" Som
Si necesitas
ver cualquiera de las entregas anteriores, aquí tienes los
links:
La Primera, la Segunda, la Tercera, la Cuarta, la Quinta, la Quinta++, la Sexta, la Séptima, la Octava, la Novena, la Décima, la Undécima, la Doce
![]()
Desde luego que los días pasan
como horas... no sé si será la edad, pero... ¡Jo! Cuando he
visto la fecha de la entrega anterior... ¡¡¡ Hace un mes !!!
No voy a prometerte nada, pero haré un pequeño esfuerzo para
acelerar los plazos de entrega, sino, puede que te aburras o
decidas cambiar de profe...
La solución sería: disponer de un portátil... pero... en
fin... Esto de la esponsorización no da para tanto... lo mismo a
tí te sobra uno... ejem!
Bueno, después de la "necesaria" introducción, vamos a lo que te ha traido por aquí; ya que me imagino que no es precisamente el saber que "necesito" un portátil... esto... si es un Pentium 200, con un mínimo de 32 megas de RAM, pantalla SVGA color, disco duro de un par de Gigas y modem... pues mejor... je,je, nunca se sabe si te puedes encontrar con un alma caritativa... y, como dice el refrán: "El que no llora no mama..." ;-)
¡Guille! ¡Déjate de chorradas y vamos al tema! (esta es la voz de mi conciencia: mi otro yo)
En la entrega anterior ya vimos cómo guardar y recuperar información de un fichero; vamos a seguir con el tipo secuencial, pero esta vez vamos a leer todo el contenido de una sola vez, para ello vamos a usar dos nuevas funciones: LOF e INPUT.
No te confundas con la función INPUT, ahora verás que no se usa de igual forma de como usamos anteriormente la "instrucción", recuerda que esta nueva, es una función y las funciones siempre devuelven un valor. La que antes usamos era una instrucción y las instrucciones hacen algo, pero no devuelven valores... ya verás que esto mismo se puede aplicar a las funciones; ya que estamos en ello, y a título de curiosidad, si no quieres usar el valor devuelto por una función, cosa que se hace muchas veces con las llamadas al API de Windows, deberás hacerlo anteponiéndole a la función la instrucción CALL. Esto lo veremos cuando empecemos con el API, que, aunque te parezca que es un tema avanzado, lo empezaremos a ver muy pronto.
Ahora veamos cómo usar esas dos
funciones:
variable = LOF(#canal)
Esta función devuelve, en bytes, el tamaño del fichero abierto
con el canal indicado dentro del paréntesis.
LOF es la abreviatura de: Length Of
File (longitud del fichero).
Por tanto si queremos saber la longitud de un fichero, lo
abrimos, asignamos a una variable el valor devuelto por LOF y
después hacemos lo que tengamos que hacer... Que sólo quieres
averiguar la longitud, pues lo cierras y ya está, por ejemplo:
Dim nFic As Integer Dim sFic As String Dim tamFic As Long sFic = "C:\Autoexec.bat" nFic = Freefile Open sFic For Input As nFic tamFic = Lof(nFic) Close nFic MsgBox "El tamaño de " & sFic & vbCrLf & "es de " & tamFic & " bytes"
La verdad es que si lo que
pretendes es saber la longitud de un fichero, puedes usar la
función FileLen, ésta se usa poniendo el
nombre del fichero entre los paréntesis y también devuelve el
tamaño en bytes:
(Tanto una función como la otra devuelven un valor LONG)
Dim sFic As String
sFic = InputBox("Nombre del fichero:", "Mostrar tamaño", "C:\Autoexec.bat")
If Len(sFic) Then
MsgBox "El tamaño de " & sFic & vbCrLf & "es de " & FileLen(sFic) & " bytes"
End If
Este trozo de código te
preguntará, (usando InputBox), el nombre de un fichero, por
defecto te mostrará C:\Autoexec.bat y si se ha escrito algo,
mostrará el tamaño en bytes.
Fijate que el valor devuelto por una función no sólo se puede
asignar a una variable, sino que también se puede usar
directamente. Si, ya sé que lo he dicho en otras ocasiones, pero
lo repito para que no te quede duda.
Ahora veamos cómo
"funciona" la función INPUT:
Esta función devuelve una cadena con el contenido de un fichero
que esté abierto... realmente devuelve el número de caracteres
que le indiquemos y esos caracteres los tomará del fichero
abierto con el "canal" indicado, veamos cómo usarla:
cadena = Input$(numCar, #canal)
El signo dólar ($), lo uso para
saber que estoy trabajando con una función que devuelve un valor
de cadena...
La mayoría de este tipo de funciones del Visual Basic, devuelven
indistintamente un valor variant o string, para obligarle a que
devuelva una cadena, debemos ponerle al final el signo $, ni que
decir tiene que esto sólo es válido para las funciones que
devuelvan cadenas de caracteres, no para las que devuelvan otro
tipo de datos... Pero no te preocupes de este tema, ya que el VB
se encarga de hacer lo que tenga que hacer para que obtengas lo
que tienes que obtener... ¡¡¡Que lio!!!
Ahora vamos a ver cómo podemos leer todo el contenido de un fichero y asignarlo en una variable de cadena:
Dim nFic As Integer
Dim sFic As String
Dim tamFic As Long
Dim sContenido As String
sFic = InputBox("Nombre del fichero:", "Mostrar fichero", "C:\Autoexec.bat")
If Len(Dir$(sFic)) Then
nFic = FreeFile
Open sFic For Input As nFic
tamFic = LOF(nFic)
sContenido = Input$(tamFic, nFic)
Close nFic
MsgBox sContenido
End If
Fijate que uso un MsgBox para mostrarlo, en caso de que el contenido del fichero sea "demasiado" grande, el botón Aceptar no se verá... tienes dos opciones: pulsar Intro o ESC, de esta forma quitarás el mensaje de la pantalla, a pesar de que no tenga "visible" el botón Aceptar.
Un par de detalles, la función
Input$() devuelve una cadena de caracteres, el tamaño máximo de
caracteres que admite estará delimitado por el sitema operativo
y sobre todo por la versión del VB, en 32 bits este tamaño
"casi" no tiene límite, pero en 16 bits, será de 64
KB como máximo.
El otro detalle es que la comprobación que se hace para saber si
existe el fichero, no es a prueba de "manazas". Me
explico: si el nombre que se indica en sFic no existe y/o el path
indicado tampoco, no pasa nada, todo funcionará bien; pero si le
indicas la unidad A, o cualquier otra, cuando no hay disco
insertado, la cosa deja de funcionar y te mostrará un error.
Pero todo esto tiene solución,
ahora mismo te diré cual es, pero antes voy a desglosarte el
funcionamiento de Len(Dir$(...))
Fijate que aquí se usan dos funciones:
| Len(Cadena) | Esta función devuelve el número de caracteres de la cadena indicada | |
| Dir$(sFichero) | Esta otra, lo que devuelve es el nombre del primer fichero que coincida con la "especificación" indicada en sFichero, en caso de que no haya coincidencias, devolverá una cadena vacía. |
Por tanto, si no existe el fichero, Dir$ devuelve una cadena vacía y la longitud de una cadena vacía es CERO, así que en la comparación, If Len(Dir$(sFic)) Then Visual Basic sustituirá Len(Dir$(sFic)) por el valor devuelto, recuerda que para IF un cero significa FALSO y cualquier otro valor será VERDADERO, insisto en este punto, ya explicado anteriormente, para que se te quede claro.
Lo que quizás no sepas es que en
Dir$(sFic), sFic puede contener signos comodines (? y/o *), para
indicar cualquier tipo de fichero. Esto se suele usar también en
las rutinas de búsqueda que se hacen en las bases de datos, así
que mejor que te vayas enterando cómo usarlo y
"buscar" por ahí información, ya que aquí te voy a
explicar un poco el significado, para que lo puedas usar al
indicar los ficheros.
Como "añadido", decirte que en el sistema de búsqueda
del Windows 95, también puedes buscar ficheros o contenidos,
usando estos comodines.
| La interrogación (?) se usa para indicar que no nos importa el carácter que haya en esa posición. | |
| El asterisco (*) sirve para que nos devuelva todos los que tengan los caracteres anteriores a este signo, pero que los restantes no los tenga en cuenta. |
Ejemplos: (las pruebas se pueden hacer desde una ventana del MS-DOS, usando el comando DIR)
| Dir Auto*.bat | Mostrará todos los ficheros que empiecen por Auto y que la extensión sea .bat | |
| Dir
Auto* o Dir Auto*.* |
Todos
los ficheros que empiecen por Auto, sin importar ni la
extensión ni nada, ya que al usar .* se indica que
cualquier cosa es válida. Es recomendable usar la segunda forma. |
|
| Dir A?t*.* | Mostrará todos los ficheros que la primera letra sea A y la tercera T, como se usan *, esto indica que nos da igual lo que haya después de la T, por tanto si tuviesemos ficheros llamados: Arte.txt, Autoexec.bat, Automovil.doc, Arial.ttf, nos devolvería los tres primeros, porque coinciden en lo indicado. | |
| Dir Dato??98.txt | Nos
devolverá todos los ficheros que tengan en las 4
primeras letras la palabra dato y en las posiciones 7 y 8
el número 98, la extensión será txt. Además en las
posiciones 5 y 6 podrá tener cualquier cosa, pero
deberá tener 8 caracteres. Así que Dato0198.txt, dato1298.txt sería nombre encontrados, pero no lo sería: data0198.txt ni dato0298.doc, en el primer caso, porque empieza con la palabra data y en el segundo porque la extensión no es txt |
Una vez visto, por encima, esto de
los signos comodines, vamos a ver cómo hacer nuestra forma de
comprobar si existe un ficheros, algo más fiable y segura.
Para ello, vamos a crear una función que se llame: Existe y esta
función devolverá FALSO (cero) si el fichero no existe y en
caso de que exista, devolverá VERDADERO (-1)
Esta función podremos usarla de cualquiera de estas dos formas:
If Existe(unFichero) Then
'Si existe, hacer lo que corresponda
End If
If Not Existe(unFichero) Then
'El fichero en cuestión no existe
End If
Para poder "detectar", o
interceptar, los posibles errores que se produzcan al intentar
comprobar si existe el fichero, usaremos esto:
On [Local] Error Resume Next
Con estas instrucciones, se le indica al Visual Basic que en caso
de que se produzca un error, "pase" de ese error y
continue con la siguiente instrucción.
Esto está bien, pero... ¿cómo
sabremos que se ha producido el error? ya que, si continua...
pues... eso, no se detiene...
Respuesta: Usando la función ERR.
Esta función devuelve el número
del error que se haya producido, o cero si no se produjo error.
A partir del VB4, esta función se puede sustituir por la
propiedad Number del objeto Err,
por tanto Err.Number también nos dirá que
número de error se ha producido, ten en cuenta que Number es la
propiedad por defecto de este objeto.
Pero como quiero que este curso básico sea lo más genérico
posible y no se incline sólo por el VB4 o superior... pues
intentaré usar funciones que sean compatibles... aunque tampoco
prometo nada, así que te recomiendo que dejes de lado las
versiones de 16 bits o al menos la versión 3 del VB, porque esta
"consideración" que estoy teniendo puede que cambie...
de hecho seguramente pondré cosas que sólo estarán disponibles
a partir de la versión 4... y cuando la cosa vaya avanzando
más, incluso sólo cosas de la versión 5... aunque para esas
fechas ya estará en el mercado el VB7, por lo menos...
El caso es que yo estoy acostumbrado a usar ERR, así que... eso es lo que hay... je, je.
Y ya sin más rodeos, veamos cómo quedaría la función Existe, si te fijas es casi igual que la que puse hace ya algunas entregas, pero usando la detección de errores:
Private Function Existe(ByVal unFichero As String) As Boolean
On Local Error Resume Next
Existe = Len(Dir$(unFichero))
If Err Then
Existe = False
End If
Err = 0
On Local Error GoTo 0
End Function
Te explico cada una de las líneas:
Private Function Existe(ByVal unFichero As String) As Boolean
Esta es la declaración de la
función, el Private es por si lo quieres usar en un form, o en
cualquier otro módulo, pero que sólo sea visible para el
código de ese módulo.
Si quieres que esté visible en todo el proyecto, cosa
recomendable para este tipo de funciones, cambia el Private por
Public y escribe el código en un módulo BAS. Así podrás
usarlo en cualquier form o módulo que tengas en tu proyecto.
Veamos porqué he declarado el
parámetro de esta forma: Byval unFichero As String
Este es el parámetro que le pasamos a la función, es decir: el
fichero o especificación que queremos comprobar si existe. Lo de
especificación es porque puedes usar esta función para saber si
existen archivos que empiecen por la A, asignando al parámetro
los comodines que creas necesarios: If
Existe("C:\A*.*") Then comprobará si en el
directorio raiz de la unidad C hay archivos que empiecen por la
letra A.
El ByVal le indica al Visual que use una copia del parámetro, con lo cual evitaremos que el código de nuestra función lo modifique; ya que al usar una copia, no tenemos acceso al original, esto también acelera el manejo de nuestra función.
El As Boolean del final, es el tipo de dato que devolverá nuestra función, también se podría usar Integer, de esta forma, si estás usando el VB3, podrás usar la función, sin mayor problema.
On Local Error Resume Next
Esta es la instrucción que pone
en marcha la detección de errores.
Local es para indicarle al VB que sólo esté operativa dentro de
esta función, sirve para que, en caso de que externamente haya
otro mecanismo de detección de errores, el que esté operativo
sea el que acabamos de declarar... cuando abandonemos la función
seguirá funcionando la otra rutina que hubiera.
Existe = Len(Dir$(unFichero))
Asigna a Existe la cantidad de
caracteres devueltos por la función DIR. Al ser del tipo
Boolean, el VB automáticamente asigna Verdadero o Falso.
En el caso de que la función se haya declarado como Integer, un
cero indica que es falso y cualquier otro valor que es verdadero,
por tanto la cosa funcionará igualmente independientemente del
tipo devuelto por esta función.
¿Seguro?
Veamos un ejemplo:
If Not Existe("algo.txt") Then
MsgBox "El fichero indicado no existe"
End If
Prueba esto cambiando el tipo de
dato devuelto por la función Existe, cuando lo pongas como
Integer, siempre te dirá que no existe el
fichero...
La explicación de porqué ocurre esto, ya lo vimos
anteriormente, y es porque NOT Un_Número,
devuelve un número, no un cero... Y recuerda que, cuando Existe
es del tipo Integer, devuelve el número de caracteres...
Si quieres que sólo devuelva 0 ó
-1 para que sea igual que False/True, podrías hacer esto otro:
Existe = Len(Dir$(unFichero)) <> 0
De esta forma se evalua la expresión y en caso de que sea cierto
que el resultado es distinto de cero, se asignará un -1, en
cualquier otro caso se asignará un cero y ahora si que actuará
igual que si el tipo devuelto fuese boolean.
If Err Then
Ahora comprobamos si se produjo algún error al intentar buscar el fichero en cuestión.
En el supuesto de que se produzca
un error, se pasará a la línea después del IF, asignando FALSE
al valor que devolverá la función. Como sabrás o te habrás
imaginado, el valor que debe devolver una función se asigna al
nombre de la función, en otros lenguajes se usa RETURN
valor, por ejemplo en C o en el JavaScript...
Por tanto, Existe = False, sólo se asignará
cuando se produzca un error.
Err = 0
Esta es una de esas
recomendaciones "obligatorias" que yo haría siempre
que uses el Resume Next, en este caso no es necesario porque el
código de la función termina ahí, pero si hubiese más
código, ese valor de error seguiría asignado a Err y cualquier
otra comparación posterior al objeto Err, podría
"alterar" el buen funcionamiento de nuestro programa.
(Recuerda que en VB4 o posterior, realmente se asigna a la
propiedad Number del objeto Err)
On Local Error Goto 0
Esta última línea "libera" la detección de errores de esta función, en nuestro caso, tampoco es necesaria, ya que al finalizar un procedimiento, cualquier rutina de detección de errores se elimina. Esto, al igual que lo dicho anteriormente, sirve si queremos dejar de detectar errores en las siguientes líneas de nuestra rutina. Como ya no hay más líneas de código, la verdad es que no es necesaria, pero suelo usarla siempre, costumbres que tiene uno de saber cuando dejo de interceptar los errores.
Bien, ya tenemos nuestra función
a prueba de usuarios inexpertos o con malas intenciones...
también para los olvidadizos...
¿Por qué me miras?
¿Es que nunca has intentado acceder a la unidad A cuando aún no
has insertado un disquete?
Pues yo sí... je, je...
Vamos a probarla.
Crea un nuevo proyecto, agrega un
módulo bas.
Asegurate que tiene Option Explicit al principio, ya sabes que
esto es para que cualquier error tipográfico al escribir una
variable, no obligará al VB a crearla, sino que nos avisará de
que esa variable no existe, es decir, sirve para obligarnos a
declarar todas las variables que vayamos a usar.
Ahora copia y pega o escribela nuevamente, la declaración de la
función Existe, asegurate que sea pública y no privada.
Cierra el módulo y asegurate que
el Form1 esté visible y en modo de diseño, es decir que se vea
el Form. Añade un Label, un TextBox y un CommandButton.
Modifica el caption del label para que contenga este texto:
Fichero a comprobar:
En el caption del botón escribe: Comprobar.
Situa los controles para que tengan un aspecto
"agradable" y escribe lo siguiente en el
Command1_Click:
Private Sub Command1_Click()
If Existe(Text1.Text) Then
MsgBox "Si existe el fichero: " & Text1.Text
Else
MsgBox "NO EXISTE el fichero: " & Text1.Text
End If
End Sub
Prueba a escribir en el TextBox
signos comodines para comprobar que todo funciona, por ejemplo:
*.bas
Igualmente escribe algún nombre que sepas que no existe... y
para salir de dudas, intenta acceder a un fichero de la unidad A,
pero sin poner un disco...
Todo correcto, ¿verdad?
Pues me alegro, de que así sea...
No, no te preocupes que no hay "gato" encerrado... bueno, sí, los tres que tengo en mi casa, pero esos no tienen nada que ver con el programa...
No te voy a poner ningún ejercicio en esta entrega, ya lo haré en la siguiente, así que paciencia y no desesperes, que ya la tengo escrita en papel, por tanto puede que mañana mismo esté en línea... es que si continúo, se me va a pasar la hora y quiero que sea hoy dia diez el día que publique esta entrega... chorradillas que se le ocurren a uno...
Como es habitual, y las buenas
costumbres no hay que perderlas, si quieres hacer algún
comentario sobre esta entrega o sobre el curso básico en
general... o tienes ese portátil que me haría tan feliz... y me
lo quieres regalar, claro, usa este link
Te repito por enésima vez que no aproveches el link para las
consultas... que ya nos vamos conociendo... a pesar de que no des
la cara...
Nos vemos.
Guillermo
![]()