gsSetDT

Una utilidad para cambiar la fecha y hora de los ficheros

 

Revisión del 30/Mar/1998
Actualizado: 05/Ago/2003

Pulsa este link para ver la versión del 05/Ago/2003

Pulsa este link para ver la nueva versión del 30/Abr/2001 (muy mejorada)

En esta página tienes la última versión del 29/Mar/2007



Me imagino que no seré el único al que el reloj del sistema se le va la "olla", es más, últimamente el reloj de mi equipo es un "chivato", ya que se queda con la fecha y hora que tenía cuando lo apagué. Al menos si lo dejo reposar unas cuantas horillas.
Lo de chivato es porque así no puedo "meter" una trola diciéndo que me he quedado hasta tal o cual hora, ya que sólo hay que encenderlo y ver si es así o no... pero eso son cosas mías... (
desde luego Guille, ¿a quién le importa eso? es que algunas veces, con tal de enrollarte...)

Después cuando lo enciendo, no me fijo en ese detalle, (realmente: no me fijaba, ya que ahora si que lo hago), y los ficheros que guardo, pues están "mal" al menos en lo que a la fecha y hora se refiere y como me gusta que los ficheros tengan la fecha y hora que deben tener... ya que sino a la hora de hacer una copia de los más recientes, puede que se queden sin copiar por culpa de un despiste.

De lo que se trata es de poder cambiar la fecha y hora de los ficheros que queramos, para que en casos como este que indico, estén como deben, ya que si usas un programa de copia de seguridad, puede que sea casi "imprescindible" que ese atributo esté bien.

Así que, aquí te traigo otra pequeña utilidad, para cambiar la fecha y la hora de los ficheros indicados.

Como quiero que sea ahora la costumbre, no me voy a conformar con darte los listados y/o el ejecutable y dejar que te comas el coco intentando navegar entre las líneas de código. Aunque ahora estoy intentando comentarlas más, algunas veces no viene mal una pequeña explicación. Además así te sirve para que tengas más claros los conceptos, ya que de eso se trata.

Por supuesto, si ya estás más experimentado en esto de la programación con el VB, puedes ir al final de la página y bajarte los listados y/o el ejecutable. Tanto los listados como el EXE están creados con el VB5. Así que si quieres usar el ejecutable, tendrás que disponer del runtime del VB5 SP3, ya sabes que lo puedes bajar de estas direcciones:

http://www.elguille.info/ftp/msvbvm50.zip o de http://www.chez.com/guille/ftp/Msvbvm50.zip

 

¿Cómo funciona esta utilidad?

Básicamente, para cambiar a un fichero la fecha y hora, lo que hay que hacer es re-grabarlo. De esta forma el sistema le asignará la fecha y hora en que se grabó.

Este método, así a "pelo", tiene un par de inconvenientes:
1.- La fecha/hora que se asigna es la actual... y lo mismo queremos indicar otra.
2.- Si el fichero en cuestión es muy grande, puede que la cosa sea lenta.

¿Cómo solucionamos estos problemillas?

En primer lugar, para que sea una utilidad "útil", deberíamos poder decidir que fecha y hora asignar. Esto lo conseguimos asignando al reloj del sistema la fecha y hora que queremos "plasmar" en cada uno de los ficheros, de esta forma, cuando se guarde, será la fecha/hora que queremos, la que se asigne.
Por supuesto, que tendremos la precaución de "recordar" la fecha/hora real, para volver a poner las cosas en orden, o al menos como estaban antes de asignar una nueva fecha a los ficheros.

El tema de que el fichero sea grande o pequeño, no es ningún inconveniente, ya que no vamos a leerlo entero, sólo hay que hacer una pequeña modificación, sin cambiar nada, claro, para que al guardarlo se asigne la fecha que hemos indicado.
Lo que hace el programa es abrir el fichero en modo binario, leer el primer byte y volver a guardarlo.
Osea que no hay inconveniente en el tamaño del los ficheros a procesar.

 

¿Que interface usar?

En principio el diseño de esta utilidad no tiene demasiada complicación, todo lo que hay que hacer es permitir al usuario poder seleccionar los ficheros que quiere modificar, indicar la fecha y hora a "plasmar" en los ficheros seleccionados y asignar esa fecha y hora.

Para seleccionar los ficheros, podríamos hacerlo de varias formas:
1.- Que el usuario escriba en un cuadro de texto el fichero al que le quiere cambiar la fecha.
2.- Usar controles Drive, Dir y FileListbox para la selección
3.- Usar un control CommonDialog para seleccionarlos.

Esta última me parece la más correcta y simple de implementar, demás de también la primera, pero las dos juntas dan más posiblidades de elección.
Aunque después veremos que no se va a usar el control (OCX) de los diálogos comunes, entre otras cosas para hacerla más fácil de "distribuir", así nos evitamos el tener que distribuir ese control.

 

El aspecto del programa

Antes de entrar en detalles, vamos a ver el aspecto que tendrá la aplicación de cara al usuario.

la apliación funcionando...
El aspecto de la aplicación

Como es natural, para poder cambiar la fecha/hora a los ficheros, antes hay que especificar que ficheros.
Para seleccionarlos, pulsaremos en el botón Examinar. Nos mostrará un cuadro de diálogo para que escojamos los que queramos, una vez que hayamos aceptado, esos ficheros se añadirán a la lista.
En el cuadro de texto, puedes indicar el path que mostrará el cuadro de diálogo.

También puedes especificar en este cuadro los ficheros a incluir en la lista, sin necesidad de pulsar en Examinar, para que esos ficheros se añadan a la lista, deberás pulsar en Añadir.
Si lo que especificas tiene signos comodines, una vez que se procesen los ficheros de la lista, la utilidad se encargará de "interpretar" esos nombres, es decir, puedes añadir: C:\VB5\*.BAS y después el programa se encargará de desmenuzar esa especificación en cada uno de los ficheros que concuerden con ella. Pero al darle a añadir no se "interpretan" los nombres.

De la lista puedes eliminar los ficheros que quieras, (bueno, eliminar no, sino quitar de la lista, no sea que pienses que se borrarán del disco); para ello, simplemente selecciona los que quieras quitar y pulsa SUPRIMIR.

Por supuesto, para poder asignar la fecha y la hora, tendrás que indicarlo en las cajas de texto que hay para ello. Por defecto indicará la fecha y hora actual, realmente de cuando arranques el programa. Y a pesar de que se indica el "formato" a usar, lo que debes tener en cuenta es que la fecha/hora introducida sea una fecha y/o hora válida, da igual que uses otro formato, el programa se encarga de convertirlo a ese formato.

Por ejemplo, en la fecha puedes especificar 31 Mar 1998 y el programa lo entenderá, porque es una fecha correcta, no porque el programa sea "listo"... ¡que conste!

Una vez que tienes los ficheros seleccionados y la fecha y hora que quieres "imprimirles", pues le das al botoncico ese que pone Asignar y ya está.

Una vez procesados los ficheros, un mensaje te indicará los ficheros procesados y los fallos que se hayan podido producir.

Como ves, no tiene nada de especial.

 

Ahora veamos el código empleado

Para seleccionar los ficheros, al pulsar en Examinar, no uso un control CommonDialog, ya que ello implicaría el uso de un OCX, y aunque es uno bastante común... puede que los usuarios no VB-maníacos no lo tengan instalado. Para solucionar ese "inconveniente", he usado una clase para este propósito.
Esta clase sólo muestra el cuadro de diálogo ABRIR, pero con eso tenemos más que suficiente. Además en la clasehe incorporado unas funciones que pueden ser útiles en otros contextos.
Una de ellas ya las he puesto antes en mis páginas, y sirve para cambiar o quitar los caracteres indicados a una cadena.
Las otras cosillas que tiene se usan para manejar los ficheros, por ejemplo hay una función para añadir a un listbox los ficheros seleccionados, cuando se han seleccionado múltiples ficheros, esto es una ventaja, así no hay que prepararse ninguan rutina que los manipule.

El único "fallillo" que tiene esta clase, no se aún si es culpa mia o del sistema operativo, pero cuando seleccionas, de forma múltiple, muchos ficheros, no se devuelven esos ficheros.
En las comprobaciones que he hecho, es la DLL usada la que no devuelve los ficheros, pero no se si será porque no la tengo bien "implementada".
En caso de que te ocurra eso, es decir que selecciones muchos ficheros y no te devuelva ninguno, lo que debes hacer es seleccionar menos y hacerlo en un par de veces.
Para comprobar esto que digo, selecciona de un directorio cuatro o cinco columnas de ficheros, verás cómo no te los devuelve todos... En fin...

NOTA: Acabo de comprobarlo con el control CommonDialog y también le ocurre...

No voy a explicar todo el código de la clase que maneja el diálogo de Abrir, salvo las cosas que crea necesaria, cuando estemos dentro del listado ya veré...

Antes de ver el código que se usa en cada uno de los botones, vamos a echarle una visual a "pequeños" detalles.

Si te has fijado, encima del botón SALIR hay una línea 3D de separación. Para conseguir esta línea, he usado dos controles LINE, uno con el BorderWidth = 2, y el BorderColor a gris oscuro, la otra línea, tiene un borde igual a 1 y el color es blanco, también debe estar encima de la oscura. Ambas en la misma posición, al menos en lo que a la "altura" se refiere, ya que el programa se encarga de adaptarlas al ancho del form.
Este es el código a usar en el evento Form_Resize:

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then
        Line1(0).X1 = 0
        Line1(0).X2 = ScaleWidth
        Line1(1).X1 = Line1(0).X1
        Line1(1).X2 = Line1(0).X2
    End If
End Sub

Como ves no es nada del otro mundo y le da un look "mu guai".
La comparación If WindowState <> vbMinimized Then, es para que sólo se "pinte" cuando esté el form en modo no minimizado, ya que si está minimizado, para que queremos las líneas...
A continuación, situamos una de ellas totalmente a la izquierda, para ello hay que asignar CERO a la propiedad X1, si fuese otro control "no gráfico", la propiedad a asignar sería LEFT. Ahora tenemos que hacer que llegue la línea hasta la otra esquina del form, ahora lo que hacemos es asignarle a la propiedad X2, el ancho del form y asunto arreglado. En otros controles, la propiedad a la que se le asignaría el ScaleWidth sería Width.
La verdad es que esto de que tenga otros "nombres" es un poco coñazillo, ya que si usasemos alguna rutina genérica para "colocar" los controles, habría que tener en cuenta que no todos los controles tienen las mismas propiedades para situarlos en la pantalla... pero en fin...

Cuando el programa se inicia, como ya te comenté antes, se asigna a las cajas de texto correspondientes, la fecha y hora actual. Esto se hace en el evento Form_Load:

Private Sub Form_Load()
    'poner la fecha y hora actual
    txtFecha = Format$(Now, "dd/mm/yyyy")
    txtHora = Format$(Now, "hh:mm")
    
End Sub

Creo que esto no necesita ningún comentario extra...

Vamos a por los botones:
El código del botón Añadir, lo que hace es agregar al ListBox lo que haya en el cuadro de texto del fichero:

Private Sub cmdAñadir_Click()
    'Si hay algo en el textBox, añadirlo
    Dim sTmp As String
    
    sTmp = Trim$(txtFichero)
    If Len(sTmp) Then
        List1.AddItem sTmp
    End If
    
End Sub

Aquí lo que se comprueba es que si el contenido de ese textbox no está vacio, se añade a la lista de ficheros a procesar.

El código del botón Examinar es algo más largo, ya que tenemos que hacer una serie de cosillas.
Veamos el código y después las explicaciones:

Private Sub cmdExaminar_Click()
    'Seleccionar los ficheros a añadir a la lista
    Dim CommonDialog1 As New cComDlgOpen
    
    On Local Error Resume Next
    
    'añadir archivo
    With CommonDialog1
        .hwnd = Me.hwnd
        .CancelError = True
        .FileName = txtFichero
        'Seleccionar ficheros a añadir a la lista
        .DialogTitle = "Seleccionar archivos"
        .Filter = "Todos los archivos (*.*)|*.*"
        .Flags = OFN_HIDEREADONLY Or OFN_ALLOWMULTISELECT _
                Or OFN_LONGNAMES Or OFN_EXPLORER Or OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST
        .ShowOpen
        If Err = 0 Then
            'Añadimos la selección al List1
            .AgregarALista .FileName, List1
        End If
    End With
    Err = 0
    
    Set CommonDialog1 = Nothing
End Sub

Aquí se crea una variable del tipo de la clase de diálogos comunes, el nombre lo he dejado como CommonDialog1, por si prefieres usar el control para este menester, en lugar de la clase. Aunque la clase te seguirá haciendo falta, salvo que agregues manualmente el procedimiento AgregarALista, además de otro que se encargue de "entender" las selecciones múltiples.

Como ves uso, el With para facilitar el manejo de las propiedades de esta clase.
La propiedad hWnd, no es propia del control OCX, pero en este caso la uso para que el cuadro de diálogo "pertenezca" al formulario, de esta forma, es como si se hiciera modal y hasta que no se cierre no se podrá pasar a nuestro formulario, prueba a no asignar el hWnd y verás que puedes "pasar" del diálogo y volver al formulario, pero no te recomiendo que lo hagas... a no ser que quieras que ocurran cosas "imprevisibles"... nada graves, pero...
Lo del CancelError es para que sepamos que no hemos elegido nada, es decir cuando pulsemos en cancelar, se producirá un error, como tenemos la rutina que los detecta, pues sólo tendremos que comprobar si el "objeto" Err vale cero, en caso de que sea así, es que no hemos pulsado cancelar y podremos "procesar" los ficheros seleccionados.
Fijate en los valores que he asignado a la propiedad FLAGS:
.Flags = OFN_HIDEREADONLY Or OFN_ALLOWMULTISELECT _
Or OFN_LONGNAMES Or OFN_EXPLORER Or OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST

Estas variables se corresponden con las del Visual Basic, lo único que en el VB empiezan por: cdlOFN en lugar de OFN_, pero la utilidad es la misma.
Si se especifica AllowMultiselect, es decir: permitir multiple selección, el diálogo cambia al formato "antiguo", tanto en mi clase como en el OCX, para que se pueda ver como es habitual en el Windows de 32 bits, hay que asignar los valores Explorer y LongNames, para que permita nombres largos. Los otros valores son habituales, es decir que el fichero indicado exista y el path también.

Antes de continuar, voy a comentarte una cosa que no es "visible" en este código, pero que debes saber si quieres usar el control OCX para procesar múltiples ficheros.
Cuando a la propiedad Flags, se le da el valor AllowMultiselect, lo que se devuelve en FileName es el nombre de todos los ficheros seleccionados, pero el Path se indica sólo en el primero de ellos, además cada uno de los ficheros está sepaqrado por un carácter CHR$(0), en el manual dice que por espacios, pero eso no es cierto.
Así que si usas el control OCX, deberás "filtrar" los códigos CHR$(0) y cambiarlos por un espacio, sino no verás más que el primer fichero seleccionado.
Por supuesto que deberás usar una función como AgregarALista para "convertir" esos nombres en algo "entendible".
En este caso AgregarALista añade el path a cada uno de los ficheros, par que todos tengan el path completo.

Este procedimiento no sólo añade los ficheros a un ListBox, también permite añadirlos a un combo, o a cualquier objeto que tenga el método Additem..., veamos el listado:

'Esta función pertenece a mi clase de diálogos comunes
Public Sub AgregarALista(ByVal sArchivos As String, queControl As Control, _
            Optional ByVal vAlPrincipio As Variant, _
            Optional ByVal vConDir As Boolean = True)
    'Agregar los archivos indicados a la lista
    'Parámetros:
    '   sArchivos       Los archivos estarán separados por
    '                   espacios y dentro de comillas
    '                   o simplemente será un archivo
    '   queControl      será un List o un Combo
    'Parámetros opcionales
    '   vAlPrincipio    si True se añade al principio de la lista
    '                   Por defecto= False
    '   vConDir         Si el primer parámetro es un directorio
    '                   Por defecto= True
    '
    Dim i&, j&
    Dim sTmp$, sDir$
    Dim bAlPrincipio As Boolean
    Dim colArchivos As New Collection
    
    sArchivos = Trim$(sArchivos)
    If Len(sArchivos) = 0 Then Exit Sub
    
    sDir = ""
    
    If IsMissing(vAlPrincipio) Then
        bAlPrincipio = False
    Else
        bAlPrincipio = CBool(vAlPrincipio)
    End If
    
    If InStr(sArchivos, Chr$(34)) Then
        'hay comillas, es que hay varios archivos
        j = 0
        Do While Len(sArchivos)
            Do While Left$(sArchivos, 1) = Chr$(34)
                sArchivos = Trim$(Mid$(sArchivos, 2))
            Loop
            i = InStr(sArchivos, Chr$(34))
            If i Then
                sTmp = Left$(sArchivos, i - 1)
                sArchivos = Trim$(Mid$(sArchivos, i + 1))
                If j Then
                    colArchivos.Add sDir & sTmp
                Else
                    'si se considera el primer parámetro
                    'como un directorio
                    If vConDir Then
                        'El primer parámetro es el directorio
                        j = j + 1
                        sDir = sTmp
                        'Si no tiene la barra ponersela
                        If Right$(sDir, 1) <> "\" Then
                            sDir = sDir & "\"
                        End If
                    Else
                        'Si no es así, añadirlo como fichero
                        colArchivos.Add sTmp
                    End If
                End If
            Else
                Exit Do
            End If
        Loop
        If Len(sArchivos) Then
            colArchivos.Add sDir & sArchivos
        End If
        'Por si sólo se selecciona un archivo
        If colArchivos.Count = 0 Then
            colArchivos.Add sTmp
        End If
    Else
        'no hay comillas, es sólo un archivos
        colArchivos.Add sArchivos
    End If
    
    For i = colArchivos.Count To 1 Step -1
        If bAlPrincipio Then
            queControl.AddItem colArchivos(i), 0
        Else
            queControl.AddItem colArchivos(i)
        End If
    Next
    
    Set colArchivos = Nothing
End Sub

Fijate que hay dos parámetros Opcionales, el segundo de ellos tiene asignado un valor "predeterminado", es decir que si no se especifica ese parámetro, se le da el valor indicado, en este caso True. El otro parámetro no tiene ningún valor predeterminado, pero podría tenerlo, ya que después se comprueba si se ha omitido y en caso de que sea así, se asigna un valor False a la variable que va a controlar si se añaden al principio de la lista o no.

A continuación se comprueba si el nombre con los ficheros tiene el signo de comillas CHR$(34), en caso de que sea así se considera que son varios los nombres que hay, de forma que se procesan cada uno de ellos, añadiendolos a una colección temporal. Si se indica True en el valor vConDir, entonces se interpreta que el primer parámetro será el nombre del directorio, esto siempre es cierto cuando se hace múltiple selección, por eso su valor por defecto es True.
La variable j es la que lleva la cuenta de los ficheros añadidos a la colección, cuando vale cero, es que es el primero, por tanto asigna ese nombre a la variable que guardará el nombre del directorio.
Otro detalle es que cuando se asignan los nombres al ListBox, se hacen desde atrás hacia adelante, por eso el bucle se hace desde colArchivos.Count hasta 1, esto es necesario, porque la librería de Diálogos comunes invierte el orden de los ficheros seleccionados, no se si te habrás fijado cuando seleccionas varios ficheros en el Explorador de Windows, los copias y después los pegas en otra carpeta, se invierte el orden de la selección... un detallico sin importancia, pero que en esta rutina se tiene en cuenta...

Ahora le toca el turno al botón clave de esta utilidad: Asignar.
Empecemos viendo el código y después explico:

Private Sub cmdAsignar_Click()
    'Asignar la fecha/hora indicada a los ficheros de la lista
    Dim vFecha As Date
    Dim vHora As Date
    Dim i As Long
    Dim sTmp As String
    Dim Ficheros As Long
    Dim Fallos As Long
    Dim TotalFicheros As Long
    Dim TotalFallos As Long
    Dim Procesados As Double
    
    On Local Error Resume Next
    
    If List1.ListCount = 0 Then
        MsgBox "No hay ficheros a procesar"
        txtFichero.SetFocus
    Else
        If Len(Trim$(txtFecha)) = 0 Then
            vFecha = Format$(Now, "dd/mm/yyyy")
        Else
            vFecha = txtFecha
        End If
        vFecha = Format$(vFecha, "dd/mm/yyyy")
        If Err Then
            MsgBox "La fecha introducida no es correcta"
            txtFecha.SetFocus
        Else
            If Len(Trim$(txtHora)) = 0 Then
                vHora = Format$(Now, "hh:mm")
            Else
                vHora = txtHora
            End If
            vHora = Format$(vHora, "hh:mm")
            If Err Then
                MsgBox "La hora no es correcta"
                txtHora.SetFocus
            Else
                For i = 0 To List1.ListCount - 1
                    sTmp = List1.List(i)
                    Procesados = ProcesaEspec(sTmp, vFecha, vHora)
                    Ficheros = Fix(Procesados)
                    sTmp = CStr(Procesados - Ficheros)
                    Fallos = Val(Mid$(sTmp, 3))
                    TotalFicheros = TotalFicheros + Ficheros
                    TotalFallos = TotalFallos + Fallos
                Next
                MsgBox "Se han procesado un total de " & TotalFicheros & vbCrLf & _
            "se han producido " & TotalFallos & " fallos"
            End If
        End If
    End If
    
    Err = 0
End Sub

Fijate que no se usa ningún tipo de función para comprobar si la fecha introducida es correcta, lo único que hago es detectar que se produzca un error, en caso de que sea así, quiere decir que no es una fecha "buena".
Aquí te darás cuenta que si se deja en blanco alguno de los dos campos de fecha y hora, se asigna la actual. También se podría haber hecho que si no se especificaba alguna de ellas, que se dejara la que tuviese el fichero, pero eso es complicarse un poco más la vida...
Bien, este procedimiento relamente no cambia la fecha/hora de los ficheros, simplemente se encarga de enviar el contenido de cada elemento de la lista a una función (ProcesaEspec) la cual recibe una cadena con un nombre, el cual puede tener comodines, con lo cual se pueden especificar distintos grupos de ficheros que cumplan un "patrón"; el segundo y tercer parámetro es la fecha y la hora a asignar a ese fichero o grupo de ficheros.
El valor devuelto por esta función, contiene realmente dos valores, uno en la parte entera, será el número de ficheros procesados y el otro, que estará en la parte decimal, serán los fallos que se han producido, estos fallos pueden ser porque el fichero sea de sólo lectura, etcétera.

Como el número devuelto por esa función está compuesto de dos valores, (como ya he mencionado, uno de ellos estará en la parte entera y el otro en la parte fraccionaria), hay que "desmenuzarlo", para ello, asignamos a la variable Ficheros el valor sin decimales, fijate que uso FIX en lugar de INT, esto es para que no se "redondee" el número.
Como sabrás, FIX toma la parte entera sin hacer ningún tipo de redondeo.

Para convertir el valor fraccionario en un entero, lo que hago es restarle al número devuelto el que ya he obtenido de la parte entera y después lo asigno a la variable Fallos. Realmente he usado una conversión previa a cadena de caracteres.
De esta forma, le quito el cero y el signo de decimales y me quedo con el número entero.
Puede que parezca demasiado rebuscado, pero... es lo mejor que he encontrado...

Estos valores se van guardando en unas variables para que una vez procesados todos los "elementos" del ListBox, se muestre un cuadro de diálogo con el resultado de los "fallos" que hayan podido producirse.

Veamos lo que hace la función ProcesaEspec:

Private Function ProcesaEspec(  ByVal sFic As String, _
                ByVal vFecha As Date, _
                ByVal vHora As Date) As Double
    'Procesar los ficheros especificados y asignar la fecha/hora
    Dim sTmp As String
    Dim Ficheros As Long
    Dim Fallos As Long
    Dim sDir As String
    
    On Local Error Resume Next
    
    'Obtener el path de este fichero o especificación
    sDir = elPath(sFic)
    
    sTmp = Dir$(sFic)
    If Err Then
        Ficheros = 1
        Fallos = 1
    Else
        Do While Len(sTmp)
            Ficheros = Ficheros + 1
            If AsignarHora(sDir & sTmp, vFecha, vHora) Then
                Fallos = Fallos + 1
            End If
            sTmp = Dir$
        Loop
    End If
    sTmp = CStr(Ficheros) & "." & CStr(Fallos)
    ProcesaEspec = Val(sTmp)
    
    Err = 0
End Function

En esta función se usa DIR$ para procesar cada uno de los ficheros, en caso de que se haya usado algún commodín, que se indican en sFic.
El bucle Do While Len(sTmp) se repetirá como mínimo una vez, en caso de que no se haya producido un error a la hora de asignar a sTmp el valor devuelto por Dir$.
Dentro de este bucle se llama a otra función, que, ahora si, es la que asigna la fecha y hora.
Fijate que se ha averiguado el Path del fichero o especificación, para que en caso de introdicir C:\VB5\*.BAS,se procesen realmente todos los ficheros BAS de ese directorio, ya que si no usaramos el path, se intentaría cambiar la fecha y hora de los ficheros con esa extensión, pero en el directorio actual.
Esa función (AsignarHora) devolverá TRUE en caso de que se haya producido un error, con lo cual se incrementará la variable que cuenta los fallos.
Al final de la función se convierten los Ficheros procesados y los fallos en un Double, ya sabes que el valor entero es el número de ficheros procesados y la parte fraccionaria es el número de fallos.

Ahora vamos a ver el "corazón" de esta función:

Private Function AsignarHora(ByVal sFic As String, _
                ByVal vFecha As Date, ByVal vHora As Date) As Boolean
    'Asignar la fecha y hora al fichero indicado
    Dim FechaActual As Date
    Dim HoraActual As Date
    Dim nFic As Long
    Dim unChar As String * 1
    
    FechaActual = Format$(Now, "dd/mm/yyyy")
    HoraActual = Format$(Now, "hh:mm")
    
    On Local Error Resume Next
    
    'Asignar la fecha/hora a estampar
    Date$ = Format$(vFecha, "mm-dd-yyyy")
    Time = Format$(vHora, "hh:mm")
    
    nFic = FreeFile
    'Abrirlo en modo binario y compartido
    Open sFic For Binary Shared As nFic
    Get nFic, 1, unChar
    Put nFic, 1, unChar
    Close nFic
    
    'Asignar la fecha/hora del sistema
    Date$ = Format$(FechaActual, "mm-dd-yyyy")
    Time = Format$(HoraActual, "hh:mm")
    
    AsignarHora = CBool(Err)
    
    Err = 0
End Function

Lo primero que se hace, es guardar la fecha y la hora actual, a continuación se asigna al sistema la fecha y hora que queremos darle al fichero, después abrimos el fichero como binario y compartido, leemos el primer carácter y lo volvemos a grabar, en cuanto cerramos el fichero, se habrá asignado la fecha y hora que queriamos. Ahora sólo nos queda volver a asignar al sistema la hora que tenía antes de todo esto... no creo que sea significativo el "lapsus" de tiempo en procesar el fichero, ya que de serlo... nos encontraríamos conque el reloj del ordenador habría retrasado... En cuanto haga pruebas con miles de ficheros haré una media de cuanto es lo que tarda y pondré la correspondiente "corrección" a esta utilidad.

Para devolver True si se produjo un error, se convierte el valor del objeto Err a Boolean, de esta forma si hubo un error se devolverá TRUE.

 

Bueno, ya está todo lo que realmente interesa de esta utilidad.

Lo que queda es una mejora: Poder "soltar" ficheros en el listbox, de esta forma podrás usar el Explorador de Windows para seleccionar los ficheros a procesar.
Para conseguir esto, se deben asignar la propiedad OLEDropMode del ListBox a 1-Manual, la propiedad OLEDragMode, dejala con el valor 0-Manual.
Escribe este código en el evento OLEDragDrop:

Private Sub List1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
    Add2Lista Data, List1
End Sub

Este es el procedimiento que añade a la lista los ficheros soltados:

Private Sub Add2Lista(Data As DataObject, unaLista As Control, _
            Optional ByVal sExtension As String = "")
    'Añadir los archivos soltados a la lista        (16/Nov/97)
    Dim i As Long
    Dim conExt As Boolean
    
    If Len(Trim$(sExtension)) Then
        conExt = True
    End If
    
    With Data.Files
        For i = 1 To .Count
            'Añadir a la lista
            'Si se especifica la extensión...
            If conExt Then
                If InStr(.Item(i), sExtension) Then
                    unaLista.AddItem .Item(i)
                End If
            Else
                unaLista.AddItem .Item(i)
            End If
        Next
    End With
End Sub

Lo que se hace es recorrer los ficheros soltado, que están en la colección Files del objeto Data, y añadirlos al ListBox, hay un parámetro sExtension, que lo uso cuando quiero que sólo se añadan a la lista ficheros de una determinada extensión, esto es útil si por ejemplo sólo quieres que "suelten" ficheros de un tipo determinado.

 

Bueno, ahora si que está todo... o casi, ya que hay parte del código que no he puesto, como por ejemplo que se hace para quitar del ListBox los ficheros seleccionados... además de la clase de Diálogos Comunes. Esa a lo mejor lo explico con otra utilidad.

 

Para bajarte los listados, recuerda que son para VB5, pulsa en este link. (gsSetDT_cod.zip 8.30 KB)
Este otro link es para que descargues el ejecutable, también muy pequeñito pero... (gsSetDT.zip 9.64KB)

Te recuerdo que son para VB5 con el runtime del SP3, aunque en la versión diga que es SP2.

Espero tu comentario, si crees que esta utilidad te sirve para algo, claro... Si no es así, al menos confío que toda la explicación y el código pueda resultarte interesante.

¡Que lo disfrutes!

 

Nos vemos.
Guillermo


ir al índice