Saber modificaciones access
Me vuelvo a poner en contacto contigo porque la ultima vez (hace un par de semanas :)) me ayudaste bastante con mi problema de formularios. Te lo agradezco :D
Ahora me planteo lo siguiente:
La base que estoy realizando está en red, con lo que varios usuarios van trabajar con ella al mismo tiempo. Está compuesta por bastantes formularios y sólo una tabla. La tabla es grande, con unas 160 columnas y más de 300 filas. Me gustaría saber si hay alguna manera de registrar las modificaciones que se hacen diariamente, como crear una nueva tabla exactamente igual que la mía en la que aparezcan solo los datos modificados...
Se me ocurre hacer una copia de mi tabla, vaciarla, e insertar los registros después de actualizar los combos en los formularios... Pero no sé como hacer para que se haga automáticamente todos los días (es decir, vaciar y llenar la tabla cada día, al final del día una persona se encargaría de hacer un extracto excel de la tabla que contiene las modificaciones).
Por otra parte, otra pregunta diferente (esta seguro que es más fácil :)), tengo un campo que es tipo texto, y tengo otros dos que son tipo fecha. Pues bien, me gustaría que cuando los dos campos tipo fecha contengan algo, el campo tipo texto se rellene automáticamente con la exprexion "Go travaux".
Muchas gracias por tu ayuda! :D Un saludo!
Ahora me planteo lo siguiente:
La base que estoy realizando está en red, con lo que varios usuarios van trabajar con ella al mismo tiempo. Está compuesta por bastantes formularios y sólo una tabla. La tabla es grande, con unas 160 columnas y más de 300 filas. Me gustaría saber si hay alguna manera de registrar las modificaciones que se hacen diariamente, como crear una nueva tabla exactamente igual que la mía en la que aparezcan solo los datos modificados...
Se me ocurre hacer una copia de mi tabla, vaciarla, e insertar los registros después de actualizar los combos en los formularios... Pero no sé como hacer para que se haga automáticamente todos los días (es decir, vaciar y llenar la tabla cada día, al final del día una persona se encargaría de hacer un extracto excel de la tabla que contiene las modificaciones).
Por otra parte, otra pregunta diferente (esta seguro que es más fácil :)), tengo un campo que es tipo texto, y tengo otros dos que son tipo fecha. Pues bien, me gustaría que cuando los dos campos tipo fecha contengan algo, el campo tipo texto se rellene automáticamente con la exprexion "Go travaux".
Muchas gracias por tu ayuda! :D Un saludo!
1 Respuesta
Respuesta de Neckkito Nck
1
1
Te propongo un proceso más simple y creo que un poco más efectivo que el que describes. Pruébalo en una copia de tu BD, a ver si la "idea" te convence.
1.- En esa tabla añades un nuevo campo y le pones de nombre [FechaMod], siendo de tipo Fecha/Hora
2.- En el formulario que quieres controlar añades ese nuevo campo en cualquier rincón (porque no se va a ver). Eliminas la etiqueta. Sacas sus propiedades y te vas a la pestaña Formato->Visible: NO
3.- Sacas las propiedades del formulario y te vas a la pestaña Eventos->En datos no guardados, y le generas el siguiente código:
...
Private Sub Form_Dirty(Cancel As Integer)
Me.FechaMod.Value = Date
End Sub
...
Cada vez que se añada un nuevo registro o se modifique uno existente el campo FechaMod te recogerá la fecha actual.
Con eso tienes varias posibilidades, y puedes elegir la que más te guste. Por ejemplo:
- Crear una consulta y filtrar por el campo FechaMod
- Crear la anterior consulta y exportarla a Excel
- Crear una copia de tu tabla, borrándole todos los registros, y crear una consulta que te anexe a esa copia los datos cuya FechaMod sea igual a la actual
Bueno... para gustos, colores ;)
---
Respecto de tu segunda consulta voy a suponer lo siguiente:
Que el campo de texto se llama [Texto], y que los campos de fecha se llaman [Fecha1] y [Fecha2]
1- Sacas las propiedades de [Fecha1] y te vas a la pestaña Eventos->Después de actualizar, y le generas el siguiente código:
...
Private Sub...
Dim vF1 as Variant, vF2 as variant
vF1=Me.[Fecha1].value
vF2=Me.[Fecha2].value
If not isnull(vF1) And not isnull(vF2) then
me.[Texto].value="Go travaux"
End If
End Sub
...
2.- Al campo [Fecha2], en el mismo evento, le generas el mismo código.
Y ya está.
1.- En esa tabla añades un nuevo campo y le pones de nombre [FechaMod], siendo de tipo Fecha/Hora
2.- En el formulario que quieres controlar añades ese nuevo campo en cualquier rincón (porque no se va a ver). Eliminas la etiqueta. Sacas sus propiedades y te vas a la pestaña Formato->Visible: NO
3.- Sacas las propiedades del formulario y te vas a la pestaña Eventos->En datos no guardados, y le generas el siguiente código:
...
Private Sub Form_Dirty(Cancel As Integer)
Me.FechaMod.Value = Date
End Sub
...
Cada vez que se añada un nuevo registro o se modifique uno existente el campo FechaMod te recogerá la fecha actual.
Con eso tienes varias posibilidades, y puedes elegir la que más te guste. Por ejemplo:
- Crear una consulta y filtrar por el campo FechaMod
- Crear la anterior consulta y exportarla a Excel
- Crear una copia de tu tabla, borrándole todos los registros, y crear una consulta que te anexe a esa copia los datos cuya FechaMod sea igual a la actual
Bueno... para gustos, colores ;)
---
Respecto de tu segunda consulta voy a suponer lo siguiente:
Que el campo de texto se llama [Texto], y que los campos de fecha se llaman [Fecha1] y [Fecha2]
1- Sacas las propiedades de [Fecha1] y te vas a la pestaña Eventos->Después de actualizar, y le generas el siguiente código:
...
Private Sub...
Dim vF1 as Variant, vF2 as variant
vF1=Me.[Fecha1].value
vF2=Me.[Fecha2].value
If not isnull(vF1) And not isnull(vF2) then
me.[Texto].value="Go travaux"
End If
End Sub
...
2.- Al campo [Fecha2], en el mismo evento, le generas el mismo código.
Y ya está.
Gracias! Muy rapido y eficaz :D
Me gustaría ir un poquito más allá si es posible. ¿Es qué se podrían identificar de alguna manera los registros que se han cambiado? Porque estoy probando lo que me has dicho, y efectivamente, he hecho una consulta para mostrar todos los campos que tienen una fecha en "fechModif" pero me muestra la fila entera y realmente no sé qué es lo que ha cambiado :S Por ejemplo, tengo 3 columnas, Color, Edad y Animal. Y tengo el primer registro así: rojo, 20, perro. Bien, realizo el cambio rojo por azul. Al hacer mi consulta en función de si hay una fecha de modificación, me aparece azul, 20, perro. Pues bien, se podría hacer que solo apareciera: azul, "en blanco", "en blanco". Es que es para controlar cambios en fechas provisionales, y son como 10 o 15 columnas de fechas a controlar.
Se me ocurre hacer otra consulta para anexar los datos en una copia de mi tabla y en la que mostrar las filas en las que hay fecha de modificación, y poner para cada columna, que su valor sea diferente al valor que hay en mi primera tabla.
¿Qué me dices?! ¿Podría ser viable?!
Gracias! Un saludo!
Me gustaría ir un poquito más allá si es posible. ¿Es qué se podrían identificar de alguna manera los registros que se han cambiado? Porque estoy probando lo que me has dicho, y efectivamente, he hecho una consulta para mostrar todos los campos que tienen una fecha en "fechModif" pero me muestra la fila entera y realmente no sé qué es lo que ha cambiado :S Por ejemplo, tengo 3 columnas, Color, Edad y Animal. Y tengo el primer registro así: rojo, 20, perro. Bien, realizo el cambio rojo por azul. Al hacer mi consulta en función de si hay una fecha de modificación, me aparece azul, 20, perro. Pues bien, se podría hacer que solo apareciera: azul, "en blanco", "en blanco". Es que es para controlar cambios en fechas provisionales, y son como 10 o 15 columnas de fechas a controlar.
Se me ocurre hacer otra consulta para anexar los datos en una copia de mi tabla y en la que mostrar las filas en las que hay fecha de modificación, y poner para cada columna, que su valor sea diferente al valor que hay en mi primera tabla.
¿Qué me dices?! ¿Podría ser viable?!
Gracias! Un saludo!
La idea anterior no me vale :( al estar vacía la tabla en principio, se me copiarían todos los datos y estaríamos en las mismas...
¿Podría hacer, para cada campo del formulario, después de actualizar, que se metiera el dato en la tabla nueva? Y aparte se modifique también en su tabla correspondiente..
Je je no lo veo claro...
¿Podría hacer, para cada campo del formulario, después de actualizar, que se metiera el dato en la tabla nueva? Y aparte se modifique también en su tabla correspondiente..
Je je no lo veo claro...
He hecho lo siguiente, y a simple vista parece que funciona... :D
He creado una tablaMODIF con la misma estructura que mi tabla, y he rellenado solo una columna que me permite identificar de manera única cada registro (llamémosle X).
A continuación he creado una consulta de actualización para actualizar cada campo de mi tablaMODIF con el valor del campo del formulario (con la condición general de que se cumpla que el valor de X en mi formulario es el mismo en mi tablaMODIF).
Bien, luego, en el formulario, en cada campo he puesto que se ejecute la consulta después de actualizar. La consulta no muestra nada, pero me actualiza los campos debidamente en mi tablaModif.
De momento parece que funciona, pero se me presenta un problema, tengo varios formularios y son bastantes campos, me pregunto si habría alguna manera de agilizar el proceso... je je porque me veo haciendo unas cuantas consultas y no pequeñas precisamente...
Gracias!
He creado una tablaMODIF con la misma estructura que mi tabla, y he rellenado solo una columna que me permite identificar de manera única cada registro (llamémosle X).
A continuación he creado una consulta de actualización para actualizar cada campo de mi tablaMODIF con el valor del campo del formulario (con la condición general de que se cumpla que el valor de X en mi formulario es el mismo en mi tablaMODIF).
Bien, luego, en el formulario, en cada campo he puesto que se ejecute la consulta después de actualizar. La consulta no muestra nada, pero me actualiza los campos debidamente en mi tablaModif.
De momento parece que funciona, pero se me presenta un problema, tengo varios formularios y son bastantes campos, me pregunto si habría alguna manera de agilizar el proceso... je je porque me veo haciendo unas cuantas consultas y no pequeñas precisamente...
Gracias!
Tu pregunta no es sencilla de responder. Quitando el hecho de que ahora estoy un poco saturado de trabajo, déjame pensar a ver qué sistema podría utilizarse para conseguir lo que quieres (si es que se me ocurre alguno ;).
A ver si este fin de semana saco un momentito para "meditar". Te ruego tengas un poco de paciencia.
Estamos en contacto,
Neckkito
A ver si este fin de semana saco un momentito para "meditar". Te ruego tengas un poco de paciencia.
Estamos en contacto,
Neckkito
:) Gracias! Je je no te preocupes que me esta dando resultado ;) si se te ocurre algo, me lo dices, pero si estas agobiaillo, de verdad que no hay problema :D ya me has ayudado mucho :D
Gracias!
Gracias!
Te propongo el siguiente sistema:
A) Tienes tu BD que, al abrirla, tiene una tabla (que yo he llamado TDatos) que contiene la información sin modificar todavía
B) Inmediatamente creas una copia de esa tabla (que yo he llamado TDatosOriginales)
C) Trabajas con tu BD normalmente
D) Al final de la jornada, antes de cerrar la BD, ejecutas el proceso de comparación. Eso te creará una nueva tabla (que yo he llamado TModificados) donde podrás qué registros que se han modificado y sólo qué campos se han modificado
E) Cierras la BD
Debo hacer unas pequeñas e importantes puntualizaciones:
1.- El sistema que te propongo te servirá siempre y cuando cuentes con una tabla original copiada al inicio de la sesión, y sólo te servirá para esa sesión y para ese día.
Es decir, si, por ejemplo, haces esto por la mañana y cierras la tabla sin haber ejecutado el proceso de comparación, y abres la tabla por la tarde y sí haces todo el proceso, los datos de la mañana no te saldrán en la "comparación", puesto que la tabla TDatosOriginales ya incorporará esas modificaciones.
2.- El sistema se basa en la existencia del campo FechaMod que te comentaba en un mensaje anterior, creado a partir del evento de formulario En Datos No Guardados
3.- Existe como primer campo de la tabla un identificador del registro, que yo he llamado Id. Es importante que sea el primero de todos.
4.- Si te decides a probarlo mejor que lo hagas en una copia de tu BD. El proceso no toca para nada tus datos, pero si tienes que hacer pruebas mejor que sea en esa copia.
5.- Si quieres ver cómo funciona te puedes bajar este mini ejemplo. Sólo tienes que ir pulsando los botones en el orden que se indica. El link está en: http://www.filebig.net/files/JgHpCX4Er3
Dicho lo anterior te explico cómo se puede hacer:
1.- Creas un formulario en blanco. En ese formulario en blanco creas un botón de comando y le pones de etiqueta "Duplicar tabla". A ese botón le generas el siguiente código en el evento Al hacer click:
...
Private Sub
DoCmd.SetWarnings False
DoCmd.CopyObject , "TDatosOriginales", acTable, "TDatos"
DoCmd.SetWarnings True
End Sub
...
2.- En ese mismo formulario en blanco creas otro botón de comando, y al evento Al hacer click le generas el siguiente código:
...
Private Sub
'Eliminamos, si existe, la tabla TModificados
Dim tbl As Object
For Each tbl In Application.CurrentData.AllTables
If tbl.Name = "TModificados" Then
DoCmd.DeleteObject acTable, "TModificados"
End If
Next
'Creamos la estructura de la tabla TModificados
CurrentDb.Execute "SELECT * INTO TModificados FROM TDatos WHERE 1=0"
'Rellenamos sólo el campo Id de la tabla TModificados con los registros
'modificados el día del analisis (día actual)
Dim regMod As String
Dim vAhora As Date
vAhora = Date
regMod = "INSERT INTO TModificados (Id)"
regMod = regMod & " SELECT [TDatos].[Id] FROM [TDatos]"
regMod = regMod & " WHERE [TDatos].[FechaMod]=#" & Format(vAhora, "mm/dd/yy") & "#"
DoCmd.SetWarnings False
DoCmd.RunSQL regMod
DoCmd.SetWarnings True
'Creamos el recordset que escribirá en la tabla TModificados
Dim rstModificados As Recordset
Set rstModificados = CurrentDb.OpenRecordset("TModificados")
'Si no hay registros en TModificados lanza un mensaje de advertencia y sale
If rstModificados.RecordCount = 0 Then
MsgBox "No se ha modificado ningún registro", vbInformation, "SIN MODIFICACIONES"
GoTo Salida
End If
'Creamos el recordset que leerá la tabla TDatos
Dim datosSql As String
datosSql = "SELECT * FROM [TDatos] WHERE [TDatos].[FechaMod]=#" & Format(vAhora, "mm/dd/yy") & "#"
Dim rstDatos As Recordset
Set rstDatos = CurrentDb.OpenRecordset(datosSql)
'Contamos el número de campos de la tabla TDatos
Dim numCampos As Integer, i As Integer
numCampos = rstDatos.Fields.Count
'Iniciamos el proceso
rstModificados.MoveFirst
rstDatos.MoveFirst
Do Until rstDatos.EOF
'Creamos el recordset que nos cogerá sólo el registro de la tabla TDatosOriginales
'que coincida con el registro que estamos examinando
Dim sqlOriginal As String
sqlOriginal = "SELECT * FROM TDatosOriginales WHERE [Id]=" & rstDatos.Fields(0).Value
Dim rstOriginal As Recordset
Set rstOriginal = CurrentDb.OpenRecordset(sqlOriginal)
'Si rstOriginal no devuelve ningún valor es que el registro es nuevo, y no modificado.
'En ese caso sale del procedimiento
If rstOriginal.RecordCount = 0 Then
Exit Do
End If
'Comparamos los valores de los campos
For i = 1 To numCampos - 1
If rstDatos.Fields(i).Value <> rstOriginal.Fields(i).Value Then
With rstModificados
.Edit
.Fields(i).Value = rstDatos.Fields(i).Value
.Update
End With
End If
Next
'Nos movemos al siguiente registro
rstModificados.MoveNext
rstDatos.MoveNext
Loop
'Lanzamos un mensaje de que el proceso ha finalizado correctamente
MsgBox "Proceso realizado correctamente", vbInformation, "OK"
'Cerramos conexiones y liberamos memoria
rstDatos.Close
rstOriginal.Close
Set rstDatos = Nothing
Set rstOriginal = Nothing
Salida:
rstModificados.Close
Set rstModificados = Nothing
End Sub
...
Recuerda que debes cambiar los nombres de:
- TDatos: por el nombre de tu tabla original
- Id: por el nombre de tu campo identificador de registro
Finalmente una última puntualización:
Si te aparecen registros en la tabla TModificados y no se muestra ningún cambio puede deberse a dos motivos:
- Primero: que se modificó el campo pero después se volvió a dejar como estaba (por un error de usuario, por ejemplo)
- Segundo: que los registros son nuevos registros, y por tanto no son susceptibles de comparación (porque no están en TDatosOriginales)
Ya me dirás qué tal.
A) Tienes tu BD que, al abrirla, tiene una tabla (que yo he llamado TDatos) que contiene la información sin modificar todavía
B) Inmediatamente creas una copia de esa tabla (que yo he llamado TDatosOriginales)
C) Trabajas con tu BD normalmente
D) Al final de la jornada, antes de cerrar la BD, ejecutas el proceso de comparación. Eso te creará una nueva tabla (que yo he llamado TModificados) donde podrás qué registros que se han modificado y sólo qué campos se han modificado
E) Cierras la BD
Debo hacer unas pequeñas e importantes puntualizaciones:
1.- El sistema que te propongo te servirá siempre y cuando cuentes con una tabla original copiada al inicio de la sesión, y sólo te servirá para esa sesión y para ese día.
Es decir, si, por ejemplo, haces esto por la mañana y cierras la tabla sin haber ejecutado el proceso de comparación, y abres la tabla por la tarde y sí haces todo el proceso, los datos de la mañana no te saldrán en la "comparación", puesto que la tabla TDatosOriginales ya incorporará esas modificaciones.
2.- El sistema se basa en la existencia del campo FechaMod que te comentaba en un mensaje anterior, creado a partir del evento de formulario En Datos No Guardados
3.- Existe como primer campo de la tabla un identificador del registro, que yo he llamado Id. Es importante que sea el primero de todos.
4.- Si te decides a probarlo mejor que lo hagas en una copia de tu BD. El proceso no toca para nada tus datos, pero si tienes que hacer pruebas mejor que sea en esa copia.
5.- Si quieres ver cómo funciona te puedes bajar este mini ejemplo. Sólo tienes que ir pulsando los botones en el orden que se indica. El link está en: http://www.filebig.net/files/JgHpCX4Er3
Dicho lo anterior te explico cómo se puede hacer:
1.- Creas un formulario en blanco. En ese formulario en blanco creas un botón de comando y le pones de etiqueta "Duplicar tabla". A ese botón le generas el siguiente código en el evento Al hacer click:
...
Private Sub
DoCmd.SetWarnings False
DoCmd.CopyObject , "TDatosOriginales", acTable, "TDatos"
DoCmd.SetWarnings True
End Sub
...
2.- En ese mismo formulario en blanco creas otro botón de comando, y al evento Al hacer click le generas el siguiente código:
...
Private Sub
'Eliminamos, si existe, la tabla TModificados
Dim tbl As Object
For Each tbl In Application.CurrentData.AllTables
If tbl.Name = "TModificados" Then
DoCmd.DeleteObject acTable, "TModificados"
End If
Next
'Creamos la estructura de la tabla TModificados
CurrentDb.Execute "SELECT * INTO TModificados FROM TDatos WHERE 1=0"
'Rellenamos sólo el campo Id de la tabla TModificados con los registros
'modificados el día del analisis (día actual)
Dim regMod As String
Dim vAhora As Date
vAhora = Date
regMod = "INSERT INTO TModificados (Id)"
regMod = regMod & " SELECT [TDatos].[Id] FROM [TDatos]"
regMod = regMod & " WHERE [TDatos].[FechaMod]=#" & Format(vAhora, "mm/dd/yy") & "#"
DoCmd.SetWarnings False
DoCmd.RunSQL regMod
DoCmd.SetWarnings True
'Creamos el recordset que escribirá en la tabla TModificados
Dim rstModificados As Recordset
Set rstModificados = CurrentDb.OpenRecordset("TModificados")
'Si no hay registros en TModificados lanza un mensaje de advertencia y sale
If rstModificados.RecordCount = 0 Then
MsgBox "No se ha modificado ningún registro", vbInformation, "SIN MODIFICACIONES"
GoTo Salida
End If
'Creamos el recordset que leerá la tabla TDatos
Dim datosSql As String
datosSql = "SELECT * FROM [TDatos] WHERE [TDatos].[FechaMod]=#" & Format(vAhora, "mm/dd/yy") & "#"
Dim rstDatos As Recordset
Set rstDatos = CurrentDb.OpenRecordset(datosSql)
'Contamos el número de campos de la tabla TDatos
Dim numCampos As Integer, i As Integer
numCampos = rstDatos.Fields.Count
'Iniciamos el proceso
rstModificados.MoveFirst
rstDatos.MoveFirst
Do Until rstDatos.EOF
'Creamos el recordset que nos cogerá sólo el registro de la tabla TDatosOriginales
'que coincida con el registro que estamos examinando
Dim sqlOriginal As String
sqlOriginal = "SELECT * FROM TDatosOriginales WHERE [Id]=" & rstDatos.Fields(0).Value
Dim rstOriginal As Recordset
Set rstOriginal = CurrentDb.OpenRecordset(sqlOriginal)
'Si rstOriginal no devuelve ningún valor es que el registro es nuevo, y no modificado.
'En ese caso sale del procedimiento
If rstOriginal.RecordCount = 0 Then
Exit Do
End If
'Comparamos los valores de los campos
For i = 1 To numCampos - 1
If rstDatos.Fields(i).Value <> rstOriginal.Fields(i).Value Then
With rstModificados
.Edit
.Fields(i).Value = rstDatos.Fields(i).Value
.Update
End With
End If
Next
'Nos movemos al siguiente registro
rstModificados.MoveNext
rstDatos.MoveNext
Loop
'Lanzamos un mensaje de que el proceso ha finalizado correctamente
MsgBox "Proceso realizado correctamente", vbInformation, "OK"
'Cerramos conexiones y liberamos memoria
rstDatos.Close
rstOriginal.Close
Set rstDatos = Nothing
Set rstOriginal = Nothing
Salida:
rstModificados.Close
Set rstModificados = Nothing
End Sub
...
Recuerda que debes cambiar los nombres de:
- TDatos: por el nombre de tu tabla original
- Id: por el nombre de tu campo identificador de registro
Finalmente una última puntualización:
Si te aparecen registros en la tabla TModificados y no se muestra ningún cambio puede deberse a dos motivos:
- Primero: que se modificó el campo pero después se volvió a dejar como estaba (por un error de usuario, por ejemplo)
- Segundo: que los registros son nuevos registros, y por tanto no son susceptibles de comparación (porque no están en TDatosOriginales)
Ya me dirás qué tal.
Hola! Te agradezco mucho el trabajo que has hecho, no es nada fácil! Lo he estado probando pero no me funciona. A lo mejor soy yo que lo hago mal. He estado jugando con el ejemplo que me has mandado y, por ejemplo, si borro un dato, en la tabla de modificaciones me aparece el registro entero en blanco, me explico: cojo el formulario, y para el registro 1, borro el contenido de Dato1 (en dato2 sigue habiendo algo), hago la comparación y abro la tbla de modificados. Me aparece el registro 1 (porque ha sido modificado) y Dato1 y Dato2 en blanco.
Por otra parte, la base se utiliza en red entre varios usuarios, y no será siempre la misma persona quien la abra primero y la cierre el último.
Lo que si me ha sugerido algo es el proceso de comparación. Cualquier persona podría hacer una copia de la tabla o bien una extracción a excel en cualquier momento. Entonces, hemos llegado a hacer bien el proceso de guardar un registro modificado y su fecha de modificación (aunque se guarden todas las columnas y no sepamos el campo que hemos cambiado). Y yo pregunto, ¿Se puede comparar el contenido de dos tablas que tienen una estructura idéntica poniendo como criterios, que los registros tengan una fecha de modificación y que coincidan sus números de identificación (cada registro es único)? He visto que tu haces algo parecido con tu código... pero la verdad que me he perdido un poco...
Muchas gracias, de veras te agradezco tu trabajo :)
Por otra parte, la base se utiliza en red entre varios usuarios, y no será siempre la misma persona quien la abra primero y la cierre el último.
Lo que si me ha sugerido algo es el proceso de comparación. Cualquier persona podría hacer una copia de la tabla o bien una extracción a excel en cualquier momento. Entonces, hemos llegado a hacer bien el proceso de guardar un registro modificado y su fecha de modificación (aunque se guarden todas las columnas y no sepamos el campo que hemos cambiado). Y yo pregunto, ¿Se puede comparar el contenido de dos tablas que tienen una estructura idéntica poniendo como criterios, que los registros tengan una fecha de modificación y que coincidan sus números de identificación (cada registro es único)? He visto que tu haces algo parecido con tu código... pero la verdad que me he perdido un poco...
Muchas gracias, de veras te agradezco tu trabajo :)
La verdad es que si me comentas que la BD está en red y hay varios usuarios la dificultad del proceso no se encuentra a nivel de código, sino a nivel de organización de usuario. Es decir, con código puedo hacerte lo que quieras (eso es fardar demasiado, pero me sirve como "expresión vulgar") pero lo que no puedo hacer es controlar a los usuarios.
En definitiva, la respuesta a tu pregunta es: sí se puede hacer una comparación entre dos tablas idénticas en estructura, y mostrarte qué datos han cambiado. Lo que no puedo controlar es el momento en que se cree una tabla original, que será la base de comparación.
Es por ello por lo que te voy a indicar sólo el código para el proceso de comparación, en atención a lo que me comentas de una fecha de modificación.
Por lo que respecta al tema de si se elimina o no un dato la verdad es que no puedo darte una solución. El problema radica en que no se puede escribir "ELIMINADO" porque el tipo de datos es, según me comentas, una fecha, lo que te dará error de código. No se me ocurre ninguna solución factible más que un apaño, que consiste en que si se borra una fecha te aparezca como modificación, por ejemplo, el 01/01/1900. Esa parte de código te la he dejado indicada como comentario. Si la quieres utilizar sólo tienes que quitarle la comilla simple del inicio de cada línea.
El proceso será el mismo: tenemos una tabla original (TDatosOriginal) y una tabla idéntica pero cuyos registros han sufrido modificaciones (TDatos), con un campo [Id] que identifica el registro y un campo [FechaMod] que recoge la fecha de la modificación. Las modificaciones aparecerán reflejadas en una tercera tabla TModificaciones.
El código es el siguiente:
...
Private Sub...
'Eliminamos, si existe, la tabla TModificados
Dim tbl As Object
For Each tbl In Application.CurrentData.AllTables
If tbl.Name = "TModificados" Then
DoCmd.DeleteObject acTable, "TModificados"
End If
Next
'Creamos la estructura de la tabla TModificados
CurrentDb.Execute "SELECT * INTO TModificados FROM TDatos WHERE 1=0"
'Solicitamos el día de análisis
Dim diaAnalisis As Variant
diaAnalisis = InputBox("¿Fecha de análisis? (Formato dd/mm/aa)", "FECHA", Date)
If StrPtr(diaAnalisis) = 0 Then Exit Sub
If diaAnalisis = "" Then
MsgBox "No ha introducido ninguna fecha", vbExclamation, "AVISO"
Exit Sub
End If
'Rellenamos sólo el campo Id de la tabla TModificados con los registros
'modificados el día del análisis
Dim regMod As String
regMod = "INSERT INTO TModificados (Id)"
regMod = regMod & " SELECT TDatos.Id FROM TDatos"
regMod = regMod & " WHERE TDatos.FechaMod=#" & Format(diaAnalisis, "mm/dd/yy") & "#"
DoCmd.SetWarnings False
DoCmd.RunSQL regMod
DoCmd.SetWarnings True
'Creamos el recordset que escribirá en la tabla TModificados
Dim rstModificados As Recordset
Set rstModificados = CurrentDb.OpenRecordset("TModificados")
'Si no hay registros en TModificados lanza un mensaje de advertencia y sale
If rstModificados.RecordCount = 0 Then
MsgBox "No se ha modificado ningún registro", vbInformation, "SIN MODIFICACIONES"
GoTo Salida
End If
'Creamos el recordset que leerá la tabla TDatos
Dim datosSql As String
datosSql = "SELECT * FROM TDatos WHERE TDatos.FechaMod=#" & Format(diaAnalisis, "mm/dd/yy") & "#"
Dim rstDatos As Recordset
Set rstDatos = CurrentDb.OpenRecordset(datosSql)
'Contamos el número de campos de la tabla TDatos
Dim numCampos As Integer, i As Integer
numCampos = rstDatos.Fields.Count
'Iniciamos el proceso
RstModificados. MoveFirst
RstDatos. MoveFirst
Do Until rstDatos.EOF
'Creamos el recordset que nos cogerá sólo el registro de la tabla TDatosOriginales
'que coincida con el registro que estamos examinando
Dim sqlOriginal As String
sqlOriginal = "SELECT * FROM TDatosOriginales WHERE [Id]=" & rstDatos.Fields(0).Value
Dim rstOriginal As Recordset
Set rstOriginal = CurrentDb.OpenRecordset(sqlOriginal)
'Si rstOriginal no devuelve ningún valor es que el registro es nuevo, y no modificado.
'En ese caso sale del procedimiento
If rstOriginal.RecordCount = 0 Then
Exit Do
End If
'Comparamos los valores de los campos
For i = 1 To numCampos - 1
'Si todos los campos son tipo fecha esto sería un "apaño". Sólo tienes que quitar las comillas simples
' If IsNull(rstDatos.Fields(i).Value) Then
' If Not IsNull(rstOriginal.Fields(i).Value) Then
' With rstModificados
' .Edit
' .Fields(i).Value = #1/1/1900#
' .Update
' End With
' End If
' End If
If rstDatos.Fields(i).Value <> rstOriginal.Fields(i).Value Then
With rstModificados
.Edit
.Fields(i).Value = rstDatos.Fields(i).Value
.Update
End With
End If
Next
'Nos movemos al siguiente registro
rstModificados.MoveNext
rstDatos.MoveNext
Loop
'Lanzamos un mensaje de que el proceso ha finalizado correctamente
MsgBox "Proceso realizado correctamente", vbInformation, "OK"
'Cerramos conexiones y liberamos memoria
rstDatos.Close
rstOriginal.Close
Set rstDatos = Nothing
Set rstOriginal = Nothing
Salida:
rstModificados.Close
Set rstModificados = Nothing
End Sub
...
Espero que te sea de utilidad lo anterior porque creo que ya he acabado "los cartuchos" con tu consulta... ;)
En definitiva, la respuesta a tu pregunta es: sí se puede hacer una comparación entre dos tablas idénticas en estructura, y mostrarte qué datos han cambiado. Lo que no puedo controlar es el momento en que se cree una tabla original, que será la base de comparación.
Es por ello por lo que te voy a indicar sólo el código para el proceso de comparación, en atención a lo que me comentas de una fecha de modificación.
Por lo que respecta al tema de si se elimina o no un dato la verdad es que no puedo darte una solución. El problema radica en que no se puede escribir "ELIMINADO" porque el tipo de datos es, según me comentas, una fecha, lo que te dará error de código. No se me ocurre ninguna solución factible más que un apaño, que consiste en que si se borra una fecha te aparezca como modificación, por ejemplo, el 01/01/1900. Esa parte de código te la he dejado indicada como comentario. Si la quieres utilizar sólo tienes que quitarle la comilla simple del inicio de cada línea.
El proceso será el mismo: tenemos una tabla original (TDatosOriginal) y una tabla idéntica pero cuyos registros han sufrido modificaciones (TDatos), con un campo [Id] que identifica el registro y un campo [FechaMod] que recoge la fecha de la modificación. Las modificaciones aparecerán reflejadas en una tercera tabla TModificaciones.
El código es el siguiente:
...
Private Sub...
'Eliminamos, si existe, la tabla TModificados
Dim tbl As Object
For Each tbl In Application.CurrentData.AllTables
If tbl.Name = "TModificados" Then
DoCmd.DeleteObject acTable, "TModificados"
End If
Next
'Creamos la estructura de la tabla TModificados
CurrentDb.Execute "SELECT * INTO TModificados FROM TDatos WHERE 1=0"
'Solicitamos el día de análisis
Dim diaAnalisis As Variant
diaAnalisis = InputBox("¿Fecha de análisis? (Formato dd/mm/aa)", "FECHA", Date)
If StrPtr(diaAnalisis) = 0 Then Exit Sub
If diaAnalisis = "" Then
MsgBox "No ha introducido ninguna fecha", vbExclamation, "AVISO"
Exit Sub
End If
'Rellenamos sólo el campo Id de la tabla TModificados con los registros
'modificados el día del análisis
Dim regMod As String
regMod = "INSERT INTO TModificados (Id)"
regMod = regMod & " SELECT TDatos.Id FROM TDatos"
regMod = regMod & " WHERE TDatos.FechaMod=#" & Format(diaAnalisis, "mm/dd/yy") & "#"
DoCmd.SetWarnings False
DoCmd.RunSQL regMod
DoCmd.SetWarnings True
'Creamos el recordset que escribirá en la tabla TModificados
Dim rstModificados As Recordset
Set rstModificados = CurrentDb.OpenRecordset("TModificados")
'Si no hay registros en TModificados lanza un mensaje de advertencia y sale
If rstModificados.RecordCount = 0 Then
MsgBox "No se ha modificado ningún registro", vbInformation, "SIN MODIFICACIONES"
GoTo Salida
End If
'Creamos el recordset que leerá la tabla TDatos
Dim datosSql As String
datosSql = "SELECT * FROM TDatos WHERE TDatos.FechaMod=#" & Format(diaAnalisis, "mm/dd/yy") & "#"
Dim rstDatos As Recordset
Set rstDatos = CurrentDb.OpenRecordset(datosSql)
'Contamos el número de campos de la tabla TDatos
Dim numCampos As Integer, i As Integer
numCampos = rstDatos.Fields.Count
'Iniciamos el proceso
RstModificados. MoveFirst
RstDatos. MoveFirst
Do Until rstDatos.EOF
'Creamos el recordset que nos cogerá sólo el registro de la tabla TDatosOriginales
'que coincida con el registro que estamos examinando
Dim sqlOriginal As String
sqlOriginal = "SELECT * FROM TDatosOriginales WHERE [Id]=" & rstDatos.Fields(0).Value
Dim rstOriginal As Recordset
Set rstOriginal = CurrentDb.OpenRecordset(sqlOriginal)
'Si rstOriginal no devuelve ningún valor es que el registro es nuevo, y no modificado.
'En ese caso sale del procedimiento
If rstOriginal.RecordCount = 0 Then
Exit Do
End If
'Comparamos los valores de los campos
For i = 1 To numCampos - 1
'Si todos los campos son tipo fecha esto sería un "apaño". Sólo tienes que quitar las comillas simples
' If IsNull(rstDatos.Fields(i).Value) Then
' If Not IsNull(rstOriginal.Fields(i).Value) Then
' With rstModificados
' .Edit
' .Fields(i).Value = #1/1/1900#
' .Update
' End With
' End If
' End If
If rstDatos.Fields(i).Value <> rstOriginal.Fields(i).Value Then
With rstModificados
.Edit
.Fields(i).Value = rstDatos.Fields(i).Value
.Update
End With
End If
Next
'Nos movemos al siguiente registro
rstModificados.MoveNext
rstDatos.MoveNext
Loop
'Lanzamos un mensaje de que el proceso ha finalizado correctamente
MsgBox "Proceso realizado correctamente", vbInformation, "OK"
'Cerramos conexiones y liberamos memoria
rstDatos.Close
rstOriginal.Close
Set rstDatos = Nothing
Set rstOriginal = Nothing
Salida:
rstModificados.Close
Set rstModificados = Nothing
End Sub
...
Espero que te sea de utilidad lo anterior porque creo que ya he acabado "los cartuchos" con tu consulta... ;)
- Compartir respuesta
- Anónimo
ahora mismo