Familia de sistemas de administración de bases de datos relacionales de Microsoft diseñados para un uso fácil.
EL problema tanbién se da con este código
Option Compare Database
Option Explicit
'========================
' Utilidades
'========================
Private Function TblExiste(ByVal nombre As String) As Boolean
On Error Resume Next
Dim t As DAO.TableDef
For Each t In CurrentDb.TableDefs
If StrComp(t.Name, nombre, vbTextCompare) = 0 Then TblExiste = True: Exit Function
Next t
TblExiste = False
End Function
Private Sub DropSiExiste(ByVal nombre As String)
On Error Resume Next
CurrentDb.Execute "DROP TABLE [" & nombre & "]"
On Error GoTo 0
End Sub
Private Function FmtISO(ByVal d As Date) As String
FmtISO = Format(d, "yyyy-mm-dd")
End Function
'========================
' Lectura de configuración
'========================
Private Sub LeerConfig( _
ByRef tablaLlamadas As String, ByRef campoIdUsu1 As String, ByRef campoInicio As String, ByRef campoFin As String, _
ByRef tablaClasif As String, ByRef campoIdUsu2 As String, ByRef campoFechaReg As String)
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM tblConfig")
If rs.EOF Then Err.Raise vbObjectError + 7001, "LeerConfig", "tblConfig no tiene registros."
tablaLlamadas = Nz(rs!TablaLlamadas, "")
campoIdUsu1 = Nz(rs!CampoIdUsuario1, "")
campoInicio = Nz(rs!CampoInicio, "")
campoFin = Nz(rs!CampoFin, "")
tablaClasif = Nz(rs!TablaClasificador, "")
campoIdUsu2 = Nz(rs!CampoIdUsuario2, "")
campoFechaReg = Nz(rs!CampoFechaRegistro, "")
rs.Close
If Len(tablaLlamadas) = 0 Or Len(campoIdUsu1) = 0 Or Len(campoInicio) = 0 Or Len(campoFin) = 0 _
Or Len(tablaClasif) = 0 Or Len(campoIdUsu2) = 0 Or Len(campoFechaReg) = 0 Then
Err.Raise vbObjectError + 7002, "LeerConfig", "Faltan campos en tblConfig."
End If
End Sub
'========================
' Crear tablas finales (desde cero) clonando tipos
'========================
Private Sub RecrearTablasFinales(ByVal tablaLlamadas As String, ByVal tablaClasif As String)
' tblCruce_Final = L.* + C.* (sin filas), luego agrega FechaProceso
DropSiExiste "tblCruce_Final"
CurrentDb.Execute "SELECT TOP 0 L.*, C.* INTO tblCruce_Final FROM [" & tablaLlamadas & "] AS L, [" & tablaClasif & "] AS C"
CurrentDb.Execute "ALTER TABLE tblCruce_Final ADD COLUMN FechaProceso DATETIME"
' tblSinLlamada_Final = C.* (sin filas), luego FechaProceso
DropSiExiste "tblSinLlamada_Final"
CurrentDb.Execute "SELECT TOP 0 C.* INTO tblSinLlamada_Final FROM [" & tablaClasif & "] AS C"
CurrentDb.Execute "ALTER TABLE tblSinLlamada_Final ADD COLUMN FechaProceso DATETIME"
' tblSinClasif_Final = L.* (sin filas), luego FechaProceso
DropSiExiste "tblSinClasif_Final"
CurrentDb.Execute "SELECT TOP 0 L.* INTO tblSinClasif_Final FROM [" & tablaLlamadas & "] AS L"
CurrentDb.Execute "ALTER TABLE tblSinClasif_Final ADD COLUMN FechaProceso DATETIME"
End Sub
'========================
' Procesar un día (sin mensajes, acumula totales)
'========================
Private Sub ProcesarDiaInterno( _
ByVal tablaLlamadas As String, ByVal campoIdUsu1 As String, ByVal campoInicio As String, ByVal campoFin As String, _
ByVal tablaClasif As String, ByVal campoIdUsu2 As String, ByVal campoFechaReg As String, _
ByVal fechaProc As Date, _
ByRef totalCruce As Long, ByRef totalSinLlamada As Long, ByRef totalSinClasif As Long)
Dim db As DAO.Database: Set db = CurrentDb
Dim sqlText As String
Dim f As String: f = FmtISO(fechaProc)
' 1) Cruce en rango
sqlText = "INSERT INTO tblCruce_Final SELECT L.*, C.*, #" & f & "# AS FechaProceso " & _
"FROM [" & tablaLlamadas & "] AS L INNER JOIN [" & tablaClasif & "] AS C " & _
"ON L.[" & campoIdUsu1 & "] = C.[" & campoIdUsu2 & "] " & _
"AND C.[" & campoFechaReg & "] BETWEEN L.[" & campoInicio & "] AND L.[" & campoFin & "] " & _
"WHERE DateValue(C.[" & campoFechaReg & "]) = #" & f & "#"
db.Execute sqlText
totalCruce = totalCruce + db.RecordsAffected
' 2) Cruce por última llamada previa
sqlText = "INSERT INTO tblCruce_Final SELECT L.*, C.*, #" & f & "# AS FechaProceso " & _
"FROM [" & tablaLlamadas & "] AS L INNER JOIN [" & tablaClasif & "] AS C " & _
"ON L.[" & campoIdUsu1 & "] = C.[" & campoIdUsu2 & "] " & _
"WHERE L.[" & campoFin & "] = (" & _
" SELECT MAX(L2.[" & campoFin & "]) FROM [" & tablaLlamadas & "] AS L2 " & _
" WHERE L2.[" & campoIdUsu1 & "] = C.[" & campoIdUsu2 & "] " & _
" AND L2.[" & campoFin & "] < C.[" & campoFechaReg & "]" & _
") AND DateValue(C.[" & campoFechaReg & "]) = #" & f & "#"
db.Execute sqlText
totalCruce = totalCruce + db.RecordsAffected
' 3) Clasificaciones sin llamada
sqlText = "INSERT INTO tblSinLlamada_Final SELECT C.*, #" & f & "# AS FechaProceso " & _
"FROM [" & tablaClasif & "] AS C " & _
"WHERE DateValue(C.[" & campoFechaReg & "]) = #" & f & "# " & _
"AND NOT EXISTS (" & _
" SELECT 1 FROM tblCruce_Final AS X " & _
" WHERE X.[" & campoFechaReg & "] = C.[" & campoFechaReg & "] " & _
" AND X.FechaProceso = #" & f & "# " & _
")"
db.Execute sqlText
totalSinLlamada = totalSinLlamada + db.RecordsAffected
' 4) Llamadas sin clasificaciones
sqlText = "INSERT INTO tblSinClasif_Final SELECT L.*, #" & f & "# AS FechaProceso " & _
"FROM [" & tablaLlamadas & "] AS L " & _
"WHERE DateValue(L.[" & campoInicio & "]) = #" & f & "# " & _
"AND NOT EXISTS (" & _
" SELECT 1 FROM tblCruce_Final AS X " & _
" WHERE X.[" & campoInicio & "] = L.[" & campoInicio & "] " & _
" AND X.[" & campoFin & "] = L.[" & campoFin & "] " & _
" AND X.[" & campoIdUsu1 & "] = L.[" & campoIdUsu1 & "] " & _
" AND X.FechaProceso = #" & f & "# " & _
")"
db.Execute sqlText
totalSinClasif = totalSinClasif + db.RecordsAffected
End Sub
'========================
' Principal (híbrido): procesa todo o un rango
'========================
Public Sub ProcesarRango(Optional ByVal fIni As Variant, Optional ByVal fFin As Variant)
On Error GoTo EH
Dim tablaLlamadas As String, tablaClasif As String
Dim campoIdUsu1 As String, campoInicio As String, campoFin As String
Dim campoIdUsu2 As String, campoFechaReg As String
Dim rsDias As DAO.Recordset
Dim sqlDias As String
Dim minDia As Date, maxDia As Date
Dim fechaDia As Date
Dim totalCruce As Long, totalSinLlamada As Long, totalSinClasif As Long
Dim rangoIniTxt As String, rangoFinTxt As String
' 1) Config
Call LeerConfig(tablaLlamadas, campoIdUsu1, campoInicio, campoFin, tablaClasif, campoIdUsu2, campoFechaReg)
' 2) Recrear tablas finales
Call RecrearTablasFinales(tablaLlamadas, tablaClasif)
' 3) Días disponibles
sqlDias = "SELECT DISTINCT DateValue([" & campoFechaReg & "]) AS Dia FROM [" & tablaClasif & "] ORDER BY Dia"
Set rsDias = CurrentDb.OpenRecordset(sqlDias)
If rsDias.EOF Then
MsgBox "No hay registros en el insumo para procesar.", vbInformation
Exit Sub
End If
minDia = rsDias!Dia
rsDias.MoveLast: maxDia = rsDias!Dia
rsDias.MoveFirst
' 4) Definir rango efectivo
If IsMissing(fIni) Or IsNull(fIni) Then fIni = minDia
If IsMissing(fFin) Or IsNull(fFin) Then fFin = maxDia
rangoIniTxt = Format(CDate(fIni), "dd/mm/yyyy")
rangoFinTxt = Format(CDate(fFin), "dd/mm/yyyy")
' 5) Recorrer días y procesar
Do Until rsDias.EOF
fechaDia = rsDias!Dia
If fechaDia >= CDate(fIni) And fechaDia <= CDate(fFin) Then
Call ProcesarDiaInterno(tablaLlamadas, campoIdUsu1, campoInicio, campoFin, _
tablaClasif, campoIdUsu2, campoFechaReg, fechaDia, _
totalCruce, totalSinLlamada, totalSinClasif)
End If
rsDias.MoveNext
Loop
rsDias.Close
' 6) Resumen final
MsgBox "Procesamiento completado del " & rangoIniTxt & " al " & rangoFinTxt & vbCrLf & vbCrLf & _
"Totales insertados:" & vbCrLf & _
" tblCruce_Final: " & totalCruce & vbCrLf & _
" tblSinLlamada_Final: " & totalSinLlamada & vbCrLf & _
" tblSinClasif_Final: " & totalSinClasif, vbInformation
Exit Sub
EH:
MsgBox "Error: " & Err.Number & " - " & Err.Description, vbCritical, "ProcesarRango"
End Sub