Campo consecutivo en Access según año de campo fecha

He utilizado el código de una respuesta de la pregunta "Consecutivo access 2007" pero no me sale el consecutivo en función del año del campo fecha.

El campo del consecutivo se llama Doc y sería este formato 0000/AAAA (texto de 9 dígitos), siendo AAAA el año del campo Fecha de la tabla Movimientos

Este el el código utilizado:

Private Sub Doc_Enter()
Dim db As Database
Dim rs As Recordset
Dim rs1 As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("Movimientos")
Set rs1 = db.OpenRecordset("Select Max(val(Left(Doc,4))) as Mayor From Movimientos where Mid([Doc],6,4)=Right(Str(Year([Fecha])),4)")
If IsNull(rs1!mayor) = True Then
Form!Doc.Value = "0001/" + Right(Str(Year([Fecha])), 4)
Else
Form!Doc.Value = String(4 - Len(Str(rs1!mayor) + 1), "0") + Trim(Str(rs1!mayor + 1)) + "/" + Right(Str(Year([Fecha])), 4)
End If
End Sub

A ver si podéis echarme una mano con esto que me sería de gran utilidad para una base de datos que pretendo implantar en mi empresa para mejorar el control de tesorería.

Y ya puestos cómo sería el código si quisiera cambiar de numeración por cada mes del campo Fecha.

2 respuestas

Respuesta
2

Pruebe con esta función (Guárdela en un módulo)

Function sgte_doc(Optional dfecha As Date) As String
Dim db As Database
Dim rs As Recordset
Dim rs1 As Recordset
Dim periodo As Integer
If CLng(dfecha) = 0 Then
  periodo = Year(Date)
Else
  periodo = Year(dfecha)
End If
 Set db = CurrentDb
 Set rs1 = db.OpenRecordset("SELECT  Max(Left(Doc,4)) AS Mayor FROM Movimientos WHERE Right(Doc,4)=" & periodo)
    If IsNull(rs1!mayor) Then
      sgte_doc = "0001/" & periodo
    Else
      sgte_doc = Format(rs1!mayor + 1, "0000") & "/" & periodo
    End If
 rs1.Close
 Set rs1 = Nothing
End Function

Si trabaja en entorno monousuario puede llamarla al adicionar un nuevo movimiento, algo como

 Me.Doc=sgte_doc(Me.campoFecha)

En donde campoFecha es el campo de la fecha.

Respuesta
1

No he visto el original que se menciona (se da por supuesto que funcionara), pero la adaptación no creo que tenga su mismo final.

Tenemos un campo de texto que simula un autonumérico que se reinicia cada año, hay que diseccionarlo en sus dos componentes base: el numérico ascendente y el año.

El la serie numérica ascendente se puede obtener de dos formas,:

.- Tomando los cuatro primeros caracteres de 'Doc' como serie numerica
.- Los cuatro últimos como el año

.- Tomando como referente la barra, a su izquierda el numero, a su derecha el año.

Aplicare en el ejemplo la primera opción, cada año se reiniciara de forma automática la numeración

Nuevo_Doc = Format(Nz(DMax("Val(Left(DOC,4))", "Movimientos", "Right(Doc,4) = '" & Year(Date) & "'"), 0) + 1, "0000/") & Year(Date)

Lo habitual es que se 'auto-genere' el dato al iniciar un nuevo registro algo similar a esto:

Private Sub Form_Current()
If Me.NewRecord Then Me.Doc = Nuevo_Doc = Format(Nz(DMax("Val(Left(DOC,4))", "Facturas", "Right(Doc,4) = '" & Year(Date) & "'"), 0) + 1, "0000/") & Year(Date)
End Sub

Muchas gracias por la pronta respuesta Maestro Enrique, le acabo de pegar este último código cambiando la referencia a la tabla Movimientos en vez de Facturas quedando así:

Private Sub Form_Current()
If Me.NewRecord Then Me.Doc = Nuevo_Doc = Format(Nz(DMax("Val(Left(DOC,4))", "Movimientos", "Right(Doc,4) = '" & Year(Date) & "'"), 0) + 1, "0000/") & Year(Date)
End Sub

y al crear nuevo registro me sale 0.

Aprovecho para solicitar código a incluir un cambio de numeración además de por año por cada cuenta, que sería el campo Idcuenta de la misma tabla Movimientos, gracias.

He cometido un error, al aplicar la expresión la segunda vez no he eliminado la referencia al campo que recibe el dato que utilice como ejemplo.
En la segunda se le asigna al campo correcto (pero sobra la anterior asignación)

Lo marcado en negrita sobra
If Me.NewRecord Then Me.Doc = Nuevo_Doc = Format( ....

Debiera haberlo trasferido asi:
If Me.NewRecord Then Me.Doc = Format( ....

Para añadir una referencia a otro dato, este tiene que formar parte del código (o se repetira la numeración y Access no lo aceptara)

Diseña un formato que permita distinguir al 'idcuenta' para independizar las series, actualmente la serie se crea con los datos:
serie_numérica + separador + año

Se necesita añadir el 'idserie' para obtener un formato tal que : 

serie_numerica + separador  + idcuenta (+ separador_opcional) + año

Si a cada parte se le da un tamaño fijo (en el actual es: 4 + 1 + 4) pueden eliminarse los separadores y si se utiliza separador puede ser cualquiera (barra, guion, punto ...) y no importara la longitud de cada parte, pero al ordenarlos la información puede parecer confusa

Analiza tus datos y diseña un formato que en una ojeada rápida te permita ver el contenido y que al ordenarlos mantenga una lógica.

En este caso no se podrá utilizar el evento Current, pues necesita conocer el IDcuenta al que se le asignara la factura (y disponible el dato, un botón genera el nuevo registro o asigna el numero)

Muchas gracias Enrique, ahora sí que va perfecto. Sólo hice un cambio para que cambie la serie con el año de la Fecha no con el actual, es decir cambié esto Year(Date) por: Year([Fecha]).

Del cambio de numeración de la serie por cada valor  de Idcuenta creo que no me he explicado bien. Lo que pretendo es que manteniendo el mismo formato 0000/AAAA se reinicie el contador para cada Idcuenta.

Replantea la respuesta.

Lo que deseas no funcionara si se pretende hacer en/con un solo campo y si se hace con dos campos (o mas), se complicara el resto de la programación así como el diseño y manejo de las tablas al exigir siempre y en cada relación todos los campos que la componen y distinguen como único al registro.

Si se pretende utilizar otro campo mas el actual, crear el dato actual ha sido 'un tiempo perdido' en base a ese dicho de:
'Donde caben dos, caben tres'
.- En un campo el ascendente, en otro el año, y en un tercero el -Idcuenta-.

El planteamiento a resolver es: como informar a Access que el un dato (0001/2023) pertenece al la cuenta 899 y no a la cuenta 777 que también requiere un (0001/2023).

Cualquier 'falso autonumérico' (es así como se conoce a este tipo de campo) de los que he creado y de los que he visto crear, siempre han estado presentes todas las referencias a su origen, dos en el caso actual pero pueden ser mas: los indispensables para diferenciar cada 'falso ID' y convertirlo en dato único en el mismo campo de la tabla.

Al respecto de cambiar el año actual por una fecha externa:

.- Verifica el cambio de año y que ese dato externo [fecha] este disponible y se corresponda con la fecha del sistema para que se reinicie al cambiar de año.

La fecha del sistema se obtiene con una función que esta disponible a cualquier nivel.

En VBA es Date (por eso es una 'palabra reservada'), fuera de VBA se utiliza Date() que Access traduce a 'Fecha()'

Al revisar la exposición inicial, inicial, no me fije en la línea final:
... Y ya puestos cómo sería el código si quisiera cambiar de numeración por cada mes del campo Fecha...

Como el mes se puede obtener de la misma forma que el año (es parte de un a fecha), para mantener el mismo formato de 4+1+4 (nueve caracteres), en lo que queda de siglo la opción seria utilizar dos dígitos para el año y otros dos para el mes: YYMM, y en este orden para que mantengan de forma correcta el orden del conjunto.

Me.Doc = Format(Nz(DMax("Val(Left(DOC,4))", "Movimientos", "Right(Doc,4) = '" & Format(Date, "YYMM") & "'"), 0) + 1, "0000/") & Format(Date, "YYMM")

Perdona por no responder antes pero estuve offline unos días. Muchas gracias por las respuestas que me sirven mucho para ir afinando mi objetivo, un saludo.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas