Error en código para crear los valores de un campo con dos condicionales

He compuesto el código, pero me da un error en su parte final y no entiendo como solucionarlo. Expongo a continuación mi problema a ver si alguien puede echarme una mano.

Tengo una tabla de Access en la que trato de automatizar la creación de datos del campo signatura (cuando éste está en blanco) a partir del campo caja.

Si el valor del campo caja de ese registro es igual al valor del campo caja del registro anterior, entonces se copia el campo signatura de ese registro anterior y ese será el valor de signatura en el registro actual.

Si por el contrario, el valor del campo caja es distinto en el registro anterior, entonces habría que sumarle 1 al valor de signatura del registro anterior. Como signatura es un campo cadena (ej.: 0101, 0102, 0103..) lo que hago es con una función seleccionar el último cáracter, convertirlo a número, sumarle 1, convertirlo a cadena y componer la actual signatura con la conjunción de los tres primeros cáracteres y el cuarto al que le he sumado 1 previamente.

Este es el código que he escrito:

Option Compare Database

Option Explicit

Sub bucle_signatura()

Dim miconexion As New ADODB.Connection

Set miconexion = CurrentProject.Connection

Dim instruccion_sql As String

instruccion_sql = "SELECT * FROM Tabla1 "

Dim mirecordset As New ADODB.Recordset

mirecordset.Open instruccion_sql, miconexion, adOpenKeyset, adLockOptimistic

Dim mirecordsetclone As String

Dim caja_anterior As Integer

Dim mirecordsetclone2 As String

Dim derecha_signatura As Integer

Dim izquierda_signatura As String

Dim nuevo_digito As Integer

Do Until mirecordset.EOF

    If IsNull(mirecordset!signatura) Then

        mirecordset.MovePrevious

        caja_anterior = mirecordset!Caja

        mirecordset.MoveNext

    End If

    If (mirecordset!Caja) = caja_anterior Then

        mirecordset.MovePrevious

        mirecordsetclone = mirecordset!signatura

        mirecordset.MoveNext

        mirecordset!signatura = mirecordsetclone

        mirecordset.Update

    Else

        mirecordset.MovePrevious

        mirecordsetclone2 = mirecordset!signatura

        izquierda_signatura = Left(mirecordsetclone2, 3)

        nuevo_digito = Val(Right(mirecordsetclone2, 1)) + 1

        derecha_signatura = CStr(nuevo_digito)

        mirecordset.MoveNext

        mirecordset!signatura = izquierda_signatura & derecha_signatura

        mirecordset.Update

    End If

mirecordset.MoveNext

Loop

MsgBox "Se han introducido los valores del campo Caja/signatura_archivo"

mirecordset.Close

Set mirecordset = Nothing

miconexion.Close

Set miconexion = Nothing

End Sub

El error que me da al intentar ejecutar el código es:

Se ha producido el error '3021' en tiempo de ejecución:

El valor de BOF o EOF es True, o el catual registro se eliminó; la operació solicitada requiere de un registro actual.

Y al presionar el botón de depurar me selecciona la parte correspondiente a:

mirecorsetclone2 = mirecordset!signatura

1 Respuesta

Respuesta
1

Te digo la verdad, no he mirado el código que has puesto. Si tengo la tabla Caja, con los campos IdCaja(autonumérico), Caja(texto) y Signatura(obviamente texto también) y con ella hago un formulario, cuando escribo el primer registro

Al pulsar Enter por ser el primero relleno el valor desde el que voy a comenzar, en este caso escribo 0101(aunque se le podría decir que lo hiciera el código) y a partir de ahí

El código del evento Después de actualizar del cuadro de texto Caja es

Private Sub Caja_AfterUpdate()
If Caja = DLast("caja", "caja", "idcaja<" & Me.IdCaja & "") Then
Signatura = DLast("signatura", "caja", "idcaja<" & Me.IdCaja & "")
ElseIf Caja <> DLast("caja", "caja", "idcaja<" & Me.IdCaja & "") Then
Signatura = Format(Val(DLast("signatura", "caja", "idcaja<" & Me.IdCaja & "") + 1), "0000")
End If
DoCmd.RunCommand acCmdSaveRecord
End Sub

Hola Julián, gracias por responder.

Pero tengo dudas sobre si el código me puede valer. Entiendo que este evento, tal como me indicas, se ejecuta despues de actualizar el cuadro de texto del campo caja del formulario. Es decir, crearía el valor del campo signatura_archivo, cuando yo introdujese el número de caja a mano.

El caso es que yo no meto a mano estos datos (caja), sino que a mi me pasan hojas de Excell con miles de registros. Yo las importo a mi base de datos Access y añado algunos campos (por ejemplo, signatura_archivo).

Además, si me pasan de cada vez aproximadamente 3.000 registros, tampoco puedo aplicar este código a todo el conjunto, sino a unos 100 de cada vez (luego signatura_archivo cambia mas de un digito). Esto lo solucionaba en el código que enviaba, porque ya delimitaba el recordset con el WHERE de la instrucción sql. Con el problema, claro, que el segundo condicional me daba el error mencionado.

Teniendo en cuenta lo anterior ¿el código que me indicas no funcionaría verdad?

Espero haberme explicado y no haber metido la pata (tengo conocimientos muy básicos de VBA y voy aprendiendo aquellas cosas que me pueden ser útiles.

Gracias y un saludo.

Da igual que sean 10 como 10000. Si tengo la tabla DetallePedido, que como puedes ver tiene 2155 registros, ya que no tengo otra más grande

Y construyo un formulario como

Donde el cuadro de texto pequeño se llama Contador y está como no visible y el cuadro de texto grande se llama Texto14, cuando abro el formulario me muestra sólo los 100 primeros registros que dices

Cuando pulso el botón 

Cuando lo vuelvo a pulsar

Es decir, sólo me muestra 100 de cada vez y en esos 100, en Signatura le puedo poner el valor que quiera, o bien con

Docmd. Runsql"update

O con

for I=1 to me.recordset.recordcount

Que vaya recorriendo los registros.

Por cierto, el código del formulario es mucho más sencillo

Private Sub Comando11_Click()
Contador = Nz([Contador]) + 1
Form.RecordSource = "select * from detallepedido where idpedido between (" & Me.Contador & "*100)+1 and (" & Me.Contador & "+1)*100"
Texto14 = "Del registro " & Contador * 100 & " al registro " & (Contador + 1) * 100
End Sub
Private Sub Form_Load()
Form.RecordSource = "select top 100 * from detallepedido"
End Sub

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas