Spanish ¿Como se utiliza indexof de una lista?

Sergio Castellari

Active Member
Licensed User
Hola gente,
Necesito "buscar" en una lista un determinado dato. Si se encuentra, sobreescribo con nueva informacion dicho registro de la lista. Caso contrario, agrego nuevo registro a la lista.
Tengo este codigo:
B4X:
ProgressDialogShow("Procesando...ESPERE...")
    Dim aRegistros, aCampos                                            As List
    Dim aCom()                                                                    As String
    Dim prove = lblProv.Text.SubString2(0,5)         As String
    Dim depo = lblDeposito.Text.SubString2(0,3) As String
    aRegistros.Initialize
    aCampos.Initialize
    'Consulto el STOCK existente por depositos
    Wait For (Main.jConex.GetRecord("select_stock", Null)) Complete (Respuesta As Map)
    If Respuesta.Get("Correcto") Then
        Dim rs     As DBResult
        Dim cStk,cArtDep,cCodArt,cNomArt,cCodDep,cCodPro,cUmd As String
        Dim nExiste As Double
        Dim nID As Int
        rs = Respuesta.Get("Datos")
    For Each row() As Object In rs.Rows
            cStk = row(13)                                                                                                                                'STOCKASOC
            cArtDep = Main.Func.AgregoCeros(row(0),6) & Main.Func.AgregoCeros(row(5),3)        'CODART+DEPOSITO
            cCodArt = Main.Func.AgregoCeros(row(0),6)                                                                            'CODART
            cNomArt = row(1)                                                                                                                            'NOMBRE
            cCodDep = row(6)                                                                                                                            'NOMDEP
            cCodPro = Main.Func.AgregoCeros(row(11),4) & "-" & row(12)                                        'CODPROV+NOMPROV
            cUmd = row(2)                                                                                                                                    'UMEDSTOCK
            nExiste = row(4)                                                                                                                            'EXISTENCIA
            nID = aRegistros.IndexOf(cArtDep)
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                aCampos.Initialize
                aCampos.Add(cArtDep)
                aCampos.Add(cCodArt)
                aCampos.Add(cNomArt)
                aCampos.Add(cUmd)
                aCampos.Add(nExiste)
                aCampos.Add(0)
                aCampos.Add(nExiste)
                aCampos.Add(cCodDep)
                aCampos.Add(cCodPro)
                aCampos.Add(cStk)
                aRegistros.Add(aCampos)
                Log("Cargo Articulo+Deposito: " & cArtDep)
            Else                            'Si lo encontró, actualizo existencia
                Dim aReg As List
                aReg = aRegistros.Get(nID)                'Obtengo el Registro a modificar
                aReg.Set(4,aReg.Get(4) + nExiste) 'Agrego existencia a Stk.DEP
                aReg.Set(6,aReg.Get(6) + nExiste) 'Agrego existencia a Stk.REAL
                aRegistros.Set(nID,aReg)                    'Actualizo el registro original con los nuevos valores
                Log("Actualizo Articulo+Deposito: " & cArtDep)
            End If
        Next
    Else
        ProgressDialogHide
         MsgboxAsync(Respuesta.Get("Mensaje"),"")
        Return
    End If

Del resultado del query, obviamente que existen registros repetidos que son necesarios actualizar. Pues NUNCA encuentra un registro repetido !!!!.. Evidentemente algo tengo mal codificado o mal interpretado.
¿Cual puede ser el motivo que no funciona?

Saludos
 

Sergio Castellari

Active Member
Licensed User
Sergio,

Donde le asignas los "datos" a "aRegistros"?


Saludos,

Edgar
Hola @edgar_ortiz

Le asigno los datos aqui:
B4X:
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                aCampos.Initialize
                aCampos.Add(cArtDep)
                aCampos.Add(cCodArt)
                aCampos.Add(cNomArt)
                aCampos.Add(cUmd)
                aCampos.Add(nExiste)
                aCampos.Add(0)
                aCampos.Add(nExiste)
                aCampos.Add(cCodDep)
                aCampos.Add(cCodPro)
                aCampos.Add(cStk)
                aRegistros.Add(aCampos)

Como verás, cArtDep se carga en el primer elemento del array de cada registro.
El contenido de cArtDep es un string que combina el codigo de articulo + el nro.de deposito, pe.: 000001002 (000001 = codigo de articulo, 002 = nro.de deposito)

Ya verifique que aRegistros contiene elementos que debieran ser encontrados...

La verdad es que no logro comprender como funciona List.IndexOf. Se supone que debiera buscar dentro de todos los registros una cadena similar.
He buscado ejemplos por todo el foro, y no encontré algo similar. Tengo comprado el manual en castellano, y si bien leo la correspondiente sintaxis, pues no funciona.

Debo creer que tal vez es una pavada, pero no logro que funcione!!!

Saludos
 

José J. Aguilar

Expert
Licensed User
Hola:

Creo que lo que se refiere edgard, es ¿dónde cargas los registros en aregistros la primera vez?
Porque tienes un aregistros.initialize, por tanto, cuando llegas a comprobar nID = aRegistros.IndexOf(cArtDep), obviamente está siempre vacío, porque lo acabas de inicializar.
 

Sergio Castellari

Active Member
Licensed User
Hola:

Creo que lo que se refiere edgard, es ¿dónde cargas los registros en aregistros la primera vez?
Porque tienes un aregistros.initialize, por tanto, cuando llegas a comprobar nID = aRegistros.IndexOf(cArtDep), obviamente está siempre vacío, porque lo acabas de inicializar.
Hola @José J. Aguilar !!!!

Claro, en una primera vista, seguro se refiere a eso, y ovbiamente que el registro inicial siempre dará -1, es eso esta bien, porque como dije en la consulta se devuelven algunos casos donde "ese" campo clave se repite, y es ahi donde debiera encontrarlo, y hacer las operaciones correspondientes..
Segui haciendo pruebas y logré resolverlo con el siguiente codigo, pero creo que debe haber algun metodo por el cual funcione "indexOf" en un LIST.
B4X:
Private Sub CargarStock
    ProgressDialogShow("Procesando...ESPERE...")
    Dim aRegistros, aIndex      As List
    Dim prove = lblProv.Text.SubString2(0,5)         As String
    Dim depo = lblDeposito.Text.SubString2(0,3) As String
    aRegistros.Initialize
    aIndex.Initialize
    'Consulto el STOCK existente por depositos
    Wait For (Main.jConex.GetRecord("select_stock", Null)) Complete (Respuesta As Map)
    If Respuesta.Get("Correcto") Then
        Dim rs     As DBResult
        Dim cStk,cArtDep,cCodArt,cNomArt,cCodDep,cCodPro,cUmd As String
        Dim nExiste As Double
        Dim nID As Int
        rs = Respuesta.Get("Datos")
    For Each row() As Object In rs.Rows
            cStk = row(13)   
            cArtDep = Main.Func.AgregoCeros(row(0),6) & Main.Func.AgregoCeros(row(5),3)        'CODART+DEPOSITO
            cCodArt = Main.Func.AgregoCeros(row(0),6)                                                                            'CODART
            cNomArt = row(1)                                                                                                                            'NOMBRE
            cCodDep = row(6)                                                                                                                            'NOMDEP
            cCodPro = Main.Func.AgregoCeros(row(11),4) & "-" & row(12)                                        'CODPROV+NOMPROV
            cUmd = row(2)                                                                                                                                    'UMEDSTOCK
            nExiste = row(4)                                                                                                                            'EXISTENCIA
            nID = aIndex.IndexOf(cArtDep)
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                aRegistros.Add(Array As String(cArtDep,cCodArt,cNomArt,cUmd,nExiste,0,nExiste,cCodDep,cCodPro,cStk))
                aIndex.Add(cArtDep)   
                Log("Cargo Articulo+Deposito: " & cArtDep & " --->" & nID)
            Else                            'Si lo encontró, actualizo existencia
                Dim aReg2() As String
                aReg2 = aRegistros.Get(nID)                    'Obtengo el Registro a modificar
                aReg2(4) = aReg2(4) - nExiste
                aReg2(6) = aReg2(6) - nExiste
                aRegistros.Set(nID,aReg2)                        'Actualizo el registro original con los nuevos valores
                Log("Actualizo Articulo+Deposito: " & cArtDep & " --->" & nID)
            End If
        Next
    Else
        ProgressDialogHide
         MsgboxAsync(Respuesta.Get("Mensaje"),"")
        Return
    End If
    'Consulto las Salidas por PEDIDOS pendientes (Ventas)
    Log("................................")
    Wait For (Main.jConex.GetRecord("select_pedidos", Null)) Complete (Respuesta As Map)
    If Respuesta.Get("Correcto") Then
        Dim rs     As DBResult
        Dim cStk,cArtDep,cCodArt,cNomArt,cCodDep,cCodPro,cUmd As String
        Dim nExiste As Double
        Dim nID As Int
        rs = Respuesta.Get("Datos")
    For Each row() As Object In rs.Rows
            cStk = row(13)                                                                                                                                'STOCKASOC
            cArtDep = Main.Func.AgregoCeros(row(0),6) & Main.Func.AgregoCeros(row(5),3)        'CODART+DEPOSITO
            cCodArt = Main.Func.AgregoCeros(row(0),6)                                                                            'CODART
            cNomArt = row(1)                                                                                                                            'NOMBRE
            cCodDep = row(6)                                                                                                                            'NOMDEP
            cCodPro = Main.Func.AgregoCeros(row(11),4) & "-" & row(12)                                        'CODPROV+NOMPROV
            cUmd = row(2)                                                                                                                                    'UMEDSTOCK
            nExiste = row(4)                                                                                                                            'EXISTENCIA
            nID = aIndex.IndexOf(cArtDep)
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                Log("NO Encontro Pedido: " & cArtDep & " --->nID2: " & nID)
                nExiste = nExiste * -1        'Agregado para los casos donde NO EXISTE carga previa del articulo...06-08-2021
                aRegistros.Add(Array As String(cArtDep,cCodArt,cNomArt,cUmd,0,nExiste,nExiste,cCodDep,cCodPro,cStk))
                aIndex.Add(cArtDep)   
            Else                            'Si lo encontró, actualizo existencia
                Dim aReg2() As String
                aReg2 = aRegistros.Get(nID)                    'Obtengo el Registro a modificar
                aReg2(5) = aReg2(5) - nExiste
                aReg2(6) = aReg2(6) - nExiste
                aRegistros.Set(nID,aReg2)                        'Actualizo el registro original con los nuevos valores
                Log("Actualizo PEDIDO: " & cArtDep & " --->nID2: " & nID)
            End If
        Next
        B4XTable1.SetData(aRegistros)                             
        SeteoColumna("Cod", "CENTER", "LEFT",0,-1,-1)
        SeteoColumna("Articulo", "CENTER", "LEFT",0,-1,-1)
        SeteoColumna("xDep", "CENTER", "RIGHT",3,3,-1)
        SeteoColumna("xPed", "CENTER", "RIGHT",3,3,-1)
        SeteoColumna("REAL", "CENTER", "RIGHT",3,3,-1)
        SeteoColumna("Deposito", "CENTER", "CENTER",0,-1,-1)
        SeteoColumna("Provedor", "CENTER", "LEFT",0,-1,-1)
        ProgressDialogHide
    Else
        ProgressDialogHide
         MsgboxAsync(Respuesta.Get("Mensaje"),"")
        Return
    End If
End Sub
 

José J. Aguilar

Expert
Licensed User
No puedo ahora ver el código bien, pero no me entero. Si inicializas la lista siempre, borras lo que haya. Inicializa antes, o pon if not(aRegistros.isInitialized) then aRegistros.Initialize
 

Sergio Castellari

Active Member
Licensed User
No puedo ahora ver el código bien, pero no me entero. Si inicializas la lista siempre, borras lo que haya. Inicializa antes, o pon if not(aRegistros.isInitialized) then aRegistros.Initialize
La lista, siempre que entra en este sub, es inizializada.
Creo que no funciona el IndexOf, por la sencilla razón de que fue rellenado con otros LIST...aunque si ves el código, lo cambié por un array y tampoco funcionó
 

angel_

Well-Known Member
Licensed User
Es para asegurar que dentro de IndexOf va una cadena, a pesar de definir la variable como String a veces he tenido problemas al buscar un valor numérico dentro de la lista.
 

edgar_ortiz

Active Member
Licensed User
Hola @edgar_ortiz

Le asigno los datos aqui:
B4X:
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                aCampos.Initialize
                aCampos.Add(cArtDep)
                aCampos.Add(cCodArt)
                aCampos.Add(cNomArt)
                aCampos.Add(cUmd)
                aCampos.Add(nExiste)
                aCampos.Add(0)
                aCampos.Add(nExiste)
                aCampos.Add(cCodDep)
                aCampos.Add(cCodPro)
                aCampos.Add(cStk)
                aRegistros.Add(aCampos)

Como verás, cArtDep se carga en el primer elemento del array de cada registro.
El contenido de cArtDep es un string que combina el codigo de articulo + el nro.de deposito, pe.: 000001002 (000001 = codigo de articulo, 002 = nro.de deposito)

Ya verifique que aRegistros contiene elementos que debieran ser encontrados...

La verdad es que no logro comprender como funciona List.IndexOf. Se supone que debiera buscar dentro de todos los registros una cadena similar.
He buscado ejemplos por todo el foro, y no encontré algo similar. Tengo comprado el manual en castellano, y si bien leo la correspondiente sintaxis, pues no funciona.

Debo creer que tal vez es una pavada, pero no logro que funcione!!!

Saludos
Sergio,

Hasta donde me imagino, el problema es que la variable "aRegistros" es "local", así que deberías de volverla "Global" para que mantenga la información durante "la vida útil" de la aplicación.

Saludos,

Edgar
 

Sergio Castellari

Active Member
Licensed User
Chicos, gracias por todos sus aportes, realmente me sirvieron para lograr el objetivo final:
En este caso, son dos querys diferentes que pueden repetir articulos, y que ademas deben "unirse"....y como si fuera poco, debo poder filtrarlos por Proveedor, Por deposito o ambos, y todo andar como piñas! jaja
Pues lo logré, y aqui les paso el codigo (que seguramente para ustedes es facil pero quizas a otros colegas novatos como Yo, les sirva)

B4X:
Private Sub CargarStock
    ProgressDialogShow("Procesando...ESPERE...")
    Dim aRegistros,aIndex,aFinal      As List
    Dim prove = lblProv.Text.SubString2(0,5)         As String
    Dim depo = lblDeposito.Text.SubString2(0,3) As String
    aRegistros.Initialize
    aFinal.Initialize
    aIndex.Initialize
    'Consulto el STOCK existente por depositos
    Wait For (Main.jConex.GetRecord("select_stock", Null)) Complete (Respuesta As Map)
    If Respuesta.Get("Correcto") Then
        Dim rs     As DBResult
        Dim cStk,cArtDep,cCodArt,cNomArt,cCodDep,cCodPro,cUmd,xDepo,xProv As String
        Dim nExiste As Double
        Dim nID As Int
        rs = Respuesta.Get("Datos")
    For Each row() As Object In rs.Rows
            cStk = row(13)   
            cArtDep = Main.Func.AgregoCeros(row(0),6) & Main.Func.AgregoCeros(row(5),3)        'CODART+DEPOSITO
            cCodArt = row(0) & CRLF & row(14)                                                                                            'CODART+CODIFICADO
            cNomArt = row(1)                                                                                                                            'NOMBRE
            cCodDep = Main.Func.AgregoCeros(row(5),3) & "-" & row(6)                                            'DEPOSITO+NOMDEP
            cCodPro = Main.Func.AgregoCeros(row(11),5) & "-" & row(12)                                        'CODPROV+NOMPROV
            cUmd = row(2)                                                                                                                                    'UMEDSTOCK
            nExiste = row(4)                                                                                                                            'EXISTENCIA
            xDepo = Main.Func.AgregoCeros(row(5),3)                                                                                'DEPOSITO (Usado para filtro)
            xProv = Main.Func.AgregoCeros(row(11),5)                                                                            'CODPROV (Usado para filtro)
            nID = aIndex.IndexOf(cArtDep)
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                aRegistros.Add(Array As String(cArtDep,cCodArt,cNomArt,cUmd,nExiste,0,nExiste,cCodDep,cCodPro,cStk,xDepo,xProv))
                aIndex.Add(cArtDep)   
                Log("Cargo Articulo+Deposito: " & cArtDep & " --->" & nID)
            Else                            'Si lo encontró, actualizo existencia
                Dim aReg2() As String
                aReg2 = aRegistros.Get(nID)                    'Obtengo el Registro a modificar
                aReg2(4) = aReg2(4) - nExiste
                aReg2(6) = aReg2(6) - nExiste
                aRegistros.Set(nID,aReg2)                        'Actualizo el registro original con los nuevos valores
                Log("Actualizo Articulo+Deposito: " & cArtDep & " --->" & nID)
            End If
        Next
    Else
        ProgressDialogHide
         MsgboxAsync(Respuesta.Get("Mensaje"),"")
        Return
    End If
    'Consulto las Salidas por PEDIDOS pendientes (Ventas)
    Log("................................")
    Wait For (Main.jConex.GetRecord("select_pedidos", Null)) Complete (Respuesta As Map)
    If Respuesta.Get("Correcto") Then
        Dim rs     As DBResult
        Dim cStk,cArtDep,cCodArt,cNomArt,cCodDep,cCodPro,cUmd,xDepo,xProv As String
        Dim nExiste As Double
        Dim nID As Int
        rs = Respuesta.Get("Datos")
    For Each row() As Object In rs.Rows
            cStk = row(13)                                                                                                                                'STOCKASOC
            cArtDep = Main.Func.AgregoCeros(row(0),6) & Main.Func.AgregoCeros(row(5),3)        'CODART+DEPOSITO
            cCodArt = row(0) & CRLF & row(14)                                                                                        'CODART+CODIFICADO
            cNomArt = row(1)                                                                                                                            'NOMBRE
            cCodDep = Main.Func.AgregoCeros(row(5),3) & "-" & row(6)                                            'DEPOSITO+NOMDEP
            cCodPro = Main.Func.AgregoCeros(row(11),5) & "-" & row(12)                                        'CODPROV+NOMPROV
            cUmd = row(2)                                                                                                                                    'UMEDSTOCK
            nExiste = row(4)                                                                                                                            'EXISTENCIA
            xDepo = Main.Func.AgregoCeros(row(5),3)                                                                                'DEPOSITO (Usado para filtro)
            xProv = Main.Func.AgregoCeros(row(11),5)                                                                            'CODPROV (Usado para filtro)
            nID = aIndex.IndexOf(cArtDep)
            If nID = -1 Then    'Si NO encontro ningun CODART+DEPOSITO, agrego el registro
                Log("NO Encontro Pedido: " & cArtDep & " --->nID2: " & nID)
                nExiste = nExiste * -1        'Agregado para los casos donde NO EXISTE carga previa del articulo...06-08-2021
                aRegistros.Add(Array As String(cArtDep,cCodArt,cNomArt,cUmd,0,nExiste,nExiste,cCodDep,cCodPro,cStk,xDepo,xProv))
                aIndex.Add(cArtDep)   
            Else                            'Si lo encontró, actualizo existencia
                Dim aReg2() As String
                aReg2 = aRegistros.Get(nID)                    'Obtengo el Registro a modificar
                aReg2(5) = aReg2(5) - nExiste
                aReg2(6) = aReg2(6) - nExiste
                aRegistros.Set(nID,aReg2)                        'Actualizo el registro original con los nuevos valores
                Log("Actualizo PEDIDO: " & cArtDep & " --->nID2: " & nID)
            End If
        Next
        B4XTable1.SetData(aRegistros)                             
        Filtrar
        SeteoColumna("Cod", "CENTER", "LEFT",0,-1,-1)
        SeteoColumna("Articulo", "CENTER", "LEFT",0,-1,-1)
        SeteoColumna("xDep", "CENTER", "RIGHT",3,3,-1)
        SeteoColumna("xPed", "CENTER", "RIGHT",3,3,-1)
        SeteoColumna("REAL", "CENTER", "RIGHT",3,3,-1)
        SeteoColumna("Deposito", "CENTER", "CENTER",0,-1,-1)
        SeteoColumna("Provedor", "CENTER", "LEFT",0,-1,-1)
        B4XTable1.Refresh
        ProgressDialogHide
    Else
        ProgressDialogHide
         MsgboxAsync(Respuesta.Get("Mensaje"),"")
        Return
    End If
End Sub

Private Sub Filtrar
    Dim prove = lblProv.Text.SubString2(0,5)         As String
    Dim depo = lblDeposito.Text.SubString2(0,3) As String
    Dim cFiltrar = "c9 = " & $""S""$                                        As String
    If prove <> "00000" Then
        cFiltrar = cFiltrar & " and c11 = " & $"""$ & prove & $"""$
    End If
    If depo <> "000" Then
        cFiltrar = cFiltrar & " and c10 = " & $"""$ & depo & $"""$
    End If
    Log($"${Col_CodDepo.SQLID} > 0 or ${Col_CodProv.SQLID} > 0"$)   
    Log("Filtrado: " & cFiltrar)
    B4XTable1.CreateDataView(cFiltrar)
End Sub

Un detalle: Tuve que agregar dos columnas ocultas para poder "obtener" el filtro ya que no sé como se hace en SQLite para comparar "x" primeros caracteres de un campo, prove con esto pero no funciono:
If prove <> "00000" Then
cFiltrar = cFiltrar & " and c11.Substring2(0,5) = " & $"""$ & prove & $"""$ <----NO FUNCIONO por que no reconoce 'substring2'
End If

Abrazos totales!
 
Top