Page 1 of 1

Problema con Dtos

Posted: Fri Nov 08, 2013 5:34 am
by Luis
Estimados :

Tengo ésta función :

STATIC Function Ultcomb(vVar)
Local xbus
xbus := vVar[01]+Dtos(vVar[05])
Set SoftSeek On
COMBUS->(dbSeek(xbus))
vVar[13] := COMBUS->Guifec
vVar[14] := COMBUS->Hubome
Set SoftSeek Off
COMBUS->(dbGotop())
Return Nil

Aquí la forma que indexo :
USE COMBUS
Inde on Coduni+Dtos(Guifec) to COMBUS1

Cuando hago la búsqueda no encuentra nada a pesar que tiene 1 solo registro que coincide el código, uso el Set Softseek On para que llegue a la coincidencia pero tampoco y eso me pasa en todas las bases de datos que uso dtos()+_; sin embargo cuando la uso sóla (Dtos(fecha)) si funciona.
Esta función trabajaba normal cunado utilizaba Clipper.
Alguna idea? Que estoy haciendo mal?.
Gracias de antemano por sus respuestas.

harbour 2.1, fivewin 12.02, BCC5.82

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 8:29 am
by hmpaquito
Luis,

DToS() debe funcionar sin problemas, igual que dtoc() o str() o strzero() o ... lo que sea... al final todas traducen a una cadena que es la que se almacena en el indice.
Varias cosas:

1º Comprueba el tamaño de entrada de vVar[01], si llevara por ejemplo un espacio final haria que la busqueda no coincidiese.
2º Asegura que el indice de COMBUS es el apropiado, a no ser que sea uno solo. En mis busquedas, en las funciones yo tengo esta estructura
FUNCTION Busca()
GUARDA recno() e indice activo de COMBUS
ESTABLECE indice de COMBUS
SET SOFTSEEK ON
debSeek( xBus)
SET SOFTSEEK OFF // SIEMPRE justo detras del SEEK( para que no se olvide y ademas es mas claro)
RESTAURA "ENTORNO" DEL COMBUS // No hagas dbGotop() porque puedes alterar por ejemplo la visualizacion de un browse.
RETURN NIL

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 12:44 pm
by MarioG
Luis;
Coduni, es un campo numerico?, indexado como char? (como dice Paquito), DToS no debe ser el problema

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 1:34 pm
by Luis
Gracias por responder.

Coduni es un campo de caracteres de 4 espacios
coduni+dtos(guifec)
1234F E C H A
Osea se arma así : "T00120130109"

ya lo comprobé no hay espacios entre coduni y la fecha.

Y tengo que entregar éste sistema pronto, me dí cuenta cuando comencé a realizar las pruebas.
Es un DBF con un sólo registro y no lo encuentra sin embargo separados si; osea fecha solo lo encuentra, coduni solo lo encuentra pero
compuestos NO.
Por donde debo seguir investigando. Realmente es algo bien raro. Por favor una ayuda.

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 1:47 pm
by MarioG
Solo para descartar que no es problema en tu código (aunque por lo que escribis no lo es).
Que tipo de RDD usas?
Buscaste con otra aplicación?, como DBU, DBWide?

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 1:56 pm
by fgondi
Como dice paquito:
>1º Comprueba el tamaño de entrada de vVar[01], si llevara por ejemplo un espacio final haría que la búsqueda no coincidiese.
Comprueba que la longitud de vVar[01] también sea de 4 caracteres.

Sustituye la cadena de búsqueda e introduce: COMBUS->(dbSeek( "T00120130109")) (Suponiendo que "T00120130109" es un valor existente en la dbf) y comprueba si funciona.
Así se puede descartar si es un problema del rdd.

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 2:09 pm
by hmpaquito
fgondi wrote: Así se puede descartar si es un problema del rdd.
Fernando, estamos de acuerdo, si con problema del rdd te refieres a que el indice podria estar desactualizado con respecto a la dbf, porque seguro que estamos de acuerdo en que los rdds de harbour son rocks :D

Ya le dije a Luis que comprobara que el ORDER al hacer la busqueda era el apropiado. Que esa forma de hacer las busquedas sin "asegurar" el indice no me parece apropiada, sobre todo en una funcion de caracter general.

Luis comprueba/visualiza el valor xbus, su len(xbus). Mira el COMBUS->( indexkey(0) ): a ver si la clave la estas montando con dtoc() en vez de dtos() (varia solo un caracter en el nombre de la funcion). Comprueba que el record no lo tengas Deleted(). Haz reconstruccion del indice. El problema esta en "el ambiente de tu programa", el codigo que muestras es correcto, y el rdd de harbour es infalible.

Finalmente, no recuerdo si el DTOS puede estar afectado por el SET CENTURY o por SET EPOCH, me imagino que no, aunque lo comprobaria.

Un saludo a los dos.

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 2:22 pm
by Luis
Gracias por sus prontas respuestas.
Efectivamente he realizado las pruebas respectivas y si NO ES EL DTOS(), puse la cadena "T00220130105" (es el dato que existe en el DBF) y si lo encuentra pero cuando puse "T00220131108" (FECHA DE HOY) NO LO UBICA, OJO en mi código está SET SOFTSEEK ON debería encontrar la coincidencia aproximada entonces el problema es por ahí. Alguna otra sugerencia para solucionar esto?

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 2:59 pm
by hmpaquito
Luis, "T00220131108" no encuentra nada porque es una clave MAYOR a "T00220130105". Prueba con una clave MENOR a "T00220130105" y SI TE FUNCIONARA.

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 3:14 pm
by Luis
Efectivamente amigo hmpaquito te agradezco tu tiempo e interés. Lo que quiero hacer es cuando ingreso un código de un trayler busco su última fecha de carga de combustible y tomo 2 datos (fecha y kilometraje) para calcular el promedio recorrido entre cada carga de combustible, por eso uso "T00220131108" pero con
Set Softseek On debería tomar el más cercano o el que más se aproxime, y eso es lo que no ocurre. En programas antiguos ya lo he realizado sin ningún problema por eso es mi extrañeza porque ahora no lo hace. Quizá halla otra forma de hacerlo. Gracias.

Re: Problema con Dtos

Posted: Fri Nov 08, 2013 5:08 pm
by hmpaquito
Luis,

Entonces lo tienes que hacer de otra forma. Dudo mucho que anteriormente ese codigo te funcionara en Harbour, Clipper o dBase.
Mira, el Dtos() nos va a servir para mantener el orden de trailer + fecha, pero no sirve para la busqueda en si. Es bien facil.
Si no he entendido mal, lo que necesitas es conocer cual es el ultimo movimiento de un determinado trailer.
Lo que hay que hacer es EFECTIVAMENTE utilizar el SOFTSEEK pero SOLO CON LA PARTE DE LA CLAVE DE TRAILER (sin la fecha), porque vamos a buscar el siguiente trailer y luego retrocedemos.
Manteniendo EXACTAMENTE el mismo indice que tienes actualmente lo podemos hacer asi:

Code: Select all

STATIC Function Ultcomb(vVar)
Local xbus
xbus := vVar[01]                               // Solo necesitamos el codigo, la fecha en el indice es para mantener el orden.             //+Dtos(vVar[05])
xbus:= Left(xbus, Len(xbus)- 1)+;
           Chr(Asc(Right(xBus, 1))+ 1)    //  El siguiente 'caracter'  y asi tendremos EXACTAMENTE la siguiente palabra alfabetica.
Set SoftSeek On
COMBUS->(dbSeek(xbus))                 // Buscamos el siguiente al que queremos, sea el que sea el siguiente.
Set SoftSeek Off
COMBUS-> (dbSkip(-1))                     // Retrocedemos para encontrar el que buscamos  
IF Coduni == vVar[01] 
   // El trailer tiene algun movimiento. Coge el ultimo.
   vVar[13] := COMBUS->Guifec
   vVar[14] := COMBUS->Hubome
ELSE
   // Este trailer no ha tenido movimiento todavia. Devolvemos los datos a cero que indicaran que no se ha encontrado datos para ese trailer.
   vVar[13] := DToC("")
   vVar[14] := 0
ENDIF  
Return Nil
 
Esto es lo que necesitas.

Un saludo.

Re: Problema con Dtos

Posted: Sat Nov 09, 2013 11:01 am
by fgondi
La función dbseek permite un tercer parametro que realiza exactamente eso:

Code: Select all

Combu->( DbSeek("T002", .T., .T.) )
El primer .T., como todos sabemos, significa activar la busqueda blanda "SoftSeek"
El segundo .T. lo que hace es posicionarse en el último valor que cumpla la condición.

En el ejemplo que he puesto, buscaría el último valor dentro de la dbf que empiece por "T002".

Si lo que se quiere es buscar la fecha mas cercana anterior a un trailer, yo lo haría de esta forma:
Por ejemplo, buscar la última carga de combustible igual o menor a 31/10/2013, sabiendo puede haber cargas posteriores a esa fecha:

Code: Select all

vVar[01] := "T002"
vVar[05] := ctod("31/10/2013")
xBus :=  vVar[01]+Dtos(vVar[05])
if Combu->( DbSeek(xBus, .T.) )  //Hay movimento a esa fecha
   vVar[13] := COMBUS->Guifec
   vVar[14] := COMBUS->Hubome
else
  Combu->( DbSkip(-1) )
  if !Combu->( Bof() ) .and. Combu->CodUni==vVar[01]    // No hay movimento a esa fecha pero el registro anterior pertenece al mismo trailer
    vVar[13] := COMBUS->Guifec
    vVar[14] := COMBUS->Hubome    
  else                     //No hay movimentos de ese trailer a ninguna fecha
    vVar[13] := ...
    vVar[14] := ...
  endif
endif

Re: Problema con Dtos

Posted: Sat Nov 09, 2013 6:41 pm
by hmpaquito
Un cambio:

Code: Select all

vVar[01] := "T002"
vVar[05] := ctod("31/10/2013")
xBus :=  vVar[01]+Dtos(vVar[05])
if Combu->( DbSeek(xBus, .T.) .and. Combu->CodUni==vVar[01]  )  // ** Puesta condicion
   vVar[13] := COMBUS->Guifec
   vVar[14] := COMBUS->Hubome
else
  Combu->( DbSkip(-1) )
  if  Combu->CodUni==vVar[01]                                     
    vVar[13] := COMBUS->Guifec
    vVar[14] := COMBUS->Hubome    
  else                     
    vVar[13] := ...
    vVar[14] := ...
  endif
endif

Re: Problema con Dtos

Posted: Fri Nov 15, 2013 4:25 pm
by Luis
Gracias por la ayuda a los amigos hmpaquito, fgondi y mariog. :D