Page 1 of 2
Operaciones con fechas en ADO
Posted: Mon Mar 11, 2013 10:18 am
by Pedro
Hola a todos
Necesito hacer operaciones con fechas en ADO, búsqueda blanda (tipo SoftSeek), fitros de un campo y dos fechas, etc.
Alguno de ustedes podría tirarme un cable?
Les quedaría muy agradecido
Re: Operaciones con fechas en ADO
Posted: Mon Mar 11, 2013 12:52 pm
by Rick Lipkin
Pedro
If I understand your question correctly ( google translate ) .. there is no good SQL way of simulating an xbase 'softseek' with SQL and Date\time fields. The Sql LIKE operator only works on character fields.
Your best solution would be the use of the BETWEEN operator to find a range of dates high and low.
http://www.w3schools.com/sql/sql_between.asp
Rick Lipkin
Re: Operaciones con fechas en ADO
Posted: Mon Mar 11, 2013 1:52 pm
by Pedro
Rick
Thank you very much for the tip, but could you tell me how to put this?
SELECT FECHA, FACTURA, CODIGO,NOMBRE,VENCTO,IMPORTE FROM VENCTOS WERE VENCTO BETWEEN DFECHAINICIO AND DFECHAFINAL
I've tried these ways.
1.-
Code: Select all
Local cSql2 := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE, FROM VENCTOS WERE VENCTO BETWEEN "+Dtoc(dInicio)+" AND "+Dtoc(dFinal)
2.-
Code: Select all
Local dFIni := "#"+PADL(Month(dInicio),2,"0")+"/"+PADL(Day(dInicio),2,"0")+"/"+STR(YEAR(dInicio))+"#"
Local dFEnd := "#"+PADL(Month(dFinal),2,"0")+"/"+PADL(Day(dFinal),2,"0")+"/"+STR(YEAR(dFinal))+"#"
Local cSql1 := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE FROM VENCTOS WERE VENCTO BETWEEN '"+dFIni+"'"+" AND '"+dFEnd+"'"+" ORDER BY VENCTO"
Of all the ways I try, the recordset is nil, that is not open. Tell you that I'm using an Acces database
Re: Operaciones con fechas en ADO
Posted: Mon Mar 11, 2013 2:31 pm
by Rick Lipkin
Pedro
Ms Access ( unlike any other sql database ) does not treat dates as character... Trick is to use hash marks # instead of ' to delimit your dates .. you are on the right track with your second query but you still have to remove the ' .. also remove the last comma before the FROM in the first query .. make sure Century is on and designate str(year ..., 4 )
Try your query like this :
Code: Select all
Local cSql2,dFIni,dFEnd
// make sure century is on ( in your main startup )
// SET Century On
// added ctod() to match dtoc() in query
dFIni := ctod(PADL(Month(dInicio),2,"0")+"/"+PADL(Day(dInicio),2,"0")+"/"+STR(YEAR(dInicio,4)) )
dFEnd := ctod(PADL(Month(dFinal),2,"0")+"/"+PADL(Day(dFinal),2,"0")+"/"+STR(YEAR(dFinal,4)) )
// verify dates look correct
MsgInfo( dFIni )
MsgInfo( dFEnd )
cSql2 := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE "
cSql2 += "FROM VENCTOS WERE VENCTO "
cSql2 += "BETWEEN #"+Dtoc(dFIni)+"# AND #"+Dtoc(dFEnd)+"#"
Also .. if you are using a recent build of (x)Harbour .. DateTime values now have a valtype of "T" not "D" .. This only comes into play when you create a date variable from a SQL Field
dDate := oRs:Fields("Date"):Value // valtype dDate = T not D result "03/10/2013 12:03 PM"
dDate := TtoDate( dDate ) // valtype dDate = D and can be manipulated as expected
// add this function to your user defined functions in your program
Code: Select all
//--------------------------
Function TtoDate( tDate )
If empty( tDate)
Return( ctod("00/00/00"))
Endif
If ValType( tDate ) = "D"
Return(tDate )
Endif
Return( stod( substr( ttos( tDate ), 1, 8 ) ))
Re: Operaciones con fechas en ADO
Posted: Mon Mar 11, 2013 3:33 pm
by Simon
yo lo hago asi:
Code: Select all
cQuery := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE, FROM VENCTOS WERE VENCTO >= '"+DtoS( dInicio )+"' AND VENCTO <= '"+DtoS( dFinal ) + "'"
uso dtos en vez de dtoc para convertirlo a string y usar la fecha como ansi "yyyymmdd", asi no tienes problemas con el codigo sql, corre en sql server y mysql.
Re: Operaciones con fechas en ADO
Posted: Mon Mar 11, 2013 6:45 pm
by Pedro
Simon
No funciona, el recordset sigue viniendo a Nil
Rick
Este es el código que uso para hacer el recordset
Code: Select all
*-------------------------------------------------------------------------------
Function REPLISVTO(nOption,dInicio,dFinal,oRsVctos)
*-------------------------------------------------------------------------------
Local nReg := oRsVctos:BookMark()
Local aVtos := {}
Local dFIni := Ctod(PADL(Month(dInicio),2,"0")+"/"+PADL(Day(dInicio),2,"0")+"/"+STR(YEAR(dInicio)))
Local dFEnd := Ctod(PADL(Month(dFinal),2,"0")+"/"+PADL(Day(dFinal),2,"0")+"/"+STR(YEAR(dFinal)))
Local cSql1
Local cSql2
Local cSql
Local oRsLisVto
cSql1 := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE "
cSql1 += "FROM VENCTOS WERE VENCTO "
cSql1 += "BETWEEN #"+Dtoc(dFIni)+"# AND #"+Dtoc(dFEnd)+"#"
cSql2 := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE,FPAGO,TIPOPAGO "
cSql2 += "FROM VENCTOS WERE VENCTO "
cSql2 += "BETWEEN #"+Dtoc(dFIni)+"# AND #"+Dtoc(dFEnd)+"#"
If Dtos(dInicio)> Dtos(dFinal)
MsgStop("Parámetros de fechas incorrectos","ATENCION")
Return nil
EndIf
IIf(nOption== 1, cSql := cSql1, cSql := cSql2)
oRsLisVto := FW_OpenRecordSet(oConex,cSql,3) //<------------(Parametros, oConex = Conexión, cSql = Fuente de datos, 3 = LockType) Esta función está en fwh/source/functions/olefuncs.prg
Msginfo(oRsLisVto) //<-----------------( oRsLisVto --> Nil)
........
Este error es provocado para saber si los parámetros y las variables locales son correctas
Compiler version: xHarbour build 1.2.1 Intl. (SimpLex) (Rev. 9656)
FiveWin Version: FWHX 12.06
Windows version: 6.1, Build 7600
Time from start: 0 hours 1 mins 54 secs
Error occurred at: 11-03-2013, 17:30:30
Error description: Error BASE/1004 Class: 'NIL' has no exported method: EOF
Args:
[ 1] = U
Stack Calls
===========
Called from: => EOF( 0 )
Called from: D:\PROYEC~4\Pizarro\SOURCE\gesh0600.prg => REPLISVTO( 295 )
Called from: D:\PROYEC~4\Pizarro\SOURCE\gesh0600.prg => (b)IMPRIMEVENCTO( 257 )
Called from: .\source\classes\BUTTON.PRG => TBUTTONBMP:CLICK( 157 )
.........................................
Aqui las variables usadas
Variables in use
================
Procedure Type Value
==========================
EOF
Local 1: A Len: 0
Local 2: U
Local 3: U
REPLISVTO
Param 1: N 1
Param 2: D 01-02-2012
Param 3: D 11-03-2013
Param 4: O Class: TOLEAUTO
Local 1: N 1.00
Local 2: A Len: 0
Local 3: D 02-01-2012
Local 4: D 03-11-2013
Local 5: C "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE FROM VENCTOS WERE VENCTO BETWEEN #02-01-2012# AND #03-11-2013#"
Local 6: C "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE,FPAGO,TIPOPAGO FROM VENCTOS WERE VENCTO BETWEEN #02-01-2012# AND #03-11-2013#"
Local 7: C "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE FROM VENCTOS WERE VENCTO BETWEEN #02-01-2012# AND #03-11-2013#"
Local 8: U <--------------Esto debería ser oRsLisVto un objeto de la clase TOLEAUTO
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 12:55 pm
by Simon
Pedro con que motor de base de datos estas trabajando ?
tips.
1.- debes tener donde probar los querys, si usas sql server debes tener SQL SERVER MANAGAMENT STUDIO, si usas mysql yo uso EMS SQL MANAGER2005 for MySQL, pero hay muchos y gratis.
2.- una vez generes los querys pruebalos, muestralos com memodit lo copias y los pegas en el programa anteriormente mencionado y verificas la sintaxis SQL ejecutandolo, yo al principio cuando no sabia nada de sintaxis SQL lo use muchisssimo asi.
3.- hace rato deje de usar / en las fechas, porque va a depender de la persona que hizo la instalacion del servidor y tienes que estar pendiente de cambiarlo, tuve 2 clientes y les instale la misma aplicacion y en uno corria bien y en otro no, daba errores por las fechas, y comence a usarlas en formato ANSI YYYYMMDD talcual como las devuelve DTOS y ya no estoy pendiente de las fechas.
este codigo lo acabo de probar en mysql y corre perfecto
Code: Select all
select * from facturas where factura.emision between '20130101' AND '20130131'
ahora lo aplico con harbour
Code: Select all
Function main()
Local oAdoConnector := adoConnector()
Local cQuery := "select * from facturas where factura.emision between '20130101' AND '20130131'"
//memoedit( cQuery ) //para cortar y pegar en el manejador sql
adorecordset( oAdoConnector, cQuery )
Return nil
Function ADOConnector()
Local cStr := "Driver={MySQL ODBC 3.51 Driver};Server=localhost;Port=3306;Database=" + "BASE_DE_DATOS" + ";User=" + "USUARIO" + ";Password=" + "12345"+ ";Option=3;"
Local oReturn := tOleAuto():New("ADODB.connection")
oReturn:ConnectionSTring := cStr
try
oReturn:Open()
catch
oReturn := nil
end try
Return oReturn
Function ADORecordSet( oConnect, cSql, lConnect )
Local oRs
Local cError := "No se ha podido crear el objeto contenedor RECORDSET !"
try
oRs := CreateObject("ADODB.RecordSet")
oRs:CursorLocation := 3
oRs:LockType := 4
oRs:ActiveConnection:= oConnect
oRs:source := cSql
oRs:Open()
lConnect := .t.
catch
//MsgStop( cError + CRLF + CRLF + "Query : " + cSql,"Error de Datos (ADO)" )
msadoerror( cSql, "Error de Conexion con servidor" )
return nil
end try
Return oRS
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 2:02 pm
by Rick Lipkin
Pedro
Your code fails because you are not setting up your Recordset. Here is a sample of a MS Access connection string stored to the Public variable xConnect.
Again, this is for Ms Access .. you did say you were using MS Access ?
Rick Lipkin
Code: Select all
// Ms Access connection string
// place this in your top Main.prg
// modify xSource to your database name
Local xProvider,xSource,xPassword,cFile,mStart,cDefa
Public xConnect
// where .exe started from is default directory //
cFILE := GetModuleFileName( GetInstance() )
mSTART := RAT( "\", cFILE )
cDEFA := SUBSTR(cFILE,1,mSTART-1)
SET DEFA to ( cDEFA )
xPROVIDER := "Microsoft.Jet.OLEDB.4.0"
xSOURCE := cDEFA+"\Travel.mdb" // ms access table
xPASSWORD := "yourpassword"
xCONNECT := 'Provider='+xPROVIDER+';Data Source='+xSOURCE+';Jet OLEDB:Database Password='+xPASSWORD
//--
Local oRs,cSql,oErr,dFIni,dFEnd
dFIni := Ctod(PADL(Month(dInicio),2,"0")+"/"+PADL(Day(dInicio),2,"0")+"/"+STR(YEAR(dInicio)))
dFEnd := Ctod(PADL(Month(dFinal),2,"0")+"/"+PADL(Day(dFinal),2,"0")+"/"+STR(YEAR(dFinal)))
//Open the recordset
oRs := TOleAuto():New( "ADODB.Recordset" )
oRs:CursorType := 1 // opendkeyset
oRs:CursorLocation := 3 // local cache
oRs:LockType := 3 // lockoportunistic
cSql := "SELECT FECHA,FACTURA,CODIGO,NOMBRE,VENCTO,IMPORTE "
cSql += "FROM VENCTOS WERE VENCTO "
cSql += "BETWEEN #"+Dtoc(dFIni)+"# AND #"+Dtoc(dFEnd)+"#"
TRY
oRs:Open( cSQL,xCONNECT )
CATCH oErr
MsgInfo( "Error in Opening table" )
RETURN(.f.)
END TRY
xBrowse( oRs )
oRs:CLose()
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 2:09 pm
by Pedro
Simon, como ya he puesto antes, esto es con una tabla de ACCESS, no estoy usando MySql, ni SQL Server, eso lo dejo para un poco más adelante, cuando domine mejor ADO,
aunque esto mismo sirve para otras bases de datos.
El problema que se produce, creo yo, es que al establecer la apertura del recordset con esa sentencia, no general el recordset.
El query que tu pones queda muy bien con fechas fijas, pero no cuando las fechas las elije el usuario y tu has de pasar al query las variables que contienen los valores elegidos.
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 2:22 pm
by Simon
ah access.
las fechas funcionan de manera distinta a los servidores sql, una vez hice algo muy parecido para un control de acceso biometrico y la base de datos era mdb, hice varios reportes y debia buscar los registros tal cual lo necesitas tu por rango de fechas, dejame buscarlo y te paso el ejemplo.
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 2:37 pm
by Simon
ya lo encontre espero te sirva
Code: Select all
dDate := date()
cDate1 := "01/01/" + NTOC( str( year( dDate ) - 2, 4, 0 ), 4 )
cDate2 := NTOC( str( month( dDate ), 2, 0 ), 2 ) + "/" + NTOC( str( day( dDate ), 2, 0 ), 2) + "/" + NTOC( str( year( dDate ), 4, 0 ), 4 )
cQuery := "select checkinout.userid, userinfo.name, checkinout.checkTime, checkinout.checktype from checkinout " + CRLF + ;
"left join userinfo on checkinout.userid = userinfo.userid " + CRLF + ;
"where checkinout.checkTime >= #" + cDate1 + "# and checkinout.checkTime <= #" + cDate2 + "# " + CRLF + ;
"order by checkinout.userid, checkinout.checktime"
oDbf := Adorecordset( oApp:oAdoConnector, cQuery )
xbrowse( oDbf )
en el ejemplo hay 2 tablas una checkinout donde se almacenan los registros de entrada/salida de los trabajadores y userinfo donde se almacena la informacion de los trabajadores en el ejemplo traigo todos los registros de los trabajadores del año en curso hasta la fecha.
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 4:36 pm
by Pedro
Rick
In my module MAIN open the connection to the database. The variable connection (oConex) is public and I see all the sections, part I check that the connection is not closed. Below I'll put as the connection to the database.
The problem is that when trying to open the recordset, this does not open, FW_OpenRecordSet function (StringConect, Source, LokType) returns nil, so the recordset failed to create, and this is because the SQL statement to opening. Perhaps the issue is given by the type of field in the table, and there is no way to change it, go try it today start date and end date to TimeStamp to see if that way is created recordset.
This function is performed only choose the work area, the database with which we will work, because this program works with multiple databases.
Each work area is in a different folder
I hope you forgive me for using the Google translator
Code: Select all
Function Main()
Local aCorH[2]
Local hDlib
Local oBtnBal1,oBtnBal2,oBtnBal3,oBtnBal4,oBtnBal5
Local oPopBal1,oPopBal2,oPopBal3,oPopBal4,oPopBal5
Public oWMain, oFont,oIcon,oConex
Public cAreaTemp, cArea := "", aDatEmp[0],cTrabajo,aIva[7,3]
...........................................
DEFINE WINDOW oWMain MDI FROM 02, 02 TO ( MaxRow() - 2 ), ( MaxCol() - 10 );
.............................................
ACTIVATE WINDOW oWMain MAXIMIZED ;
ON INIT (EscogeArea(),VerificaConfig()) ; //<-----------------EscogeArea is where you choose the work area
.........................................................
*===============================================================================
function EscogeArea()
*===============================================================================
....................................
DEFINE DIALOG oDlgEmp RESOURCE "INICIO";
COLOR RGB(0,0,0), RGB(153,204,255)
REDEFINE BITMAP oBmp ID 101 OF oDlgEmp ;
FILENAME ".\BMP\LOGO2.BMP" ;
ADJUST;
UPDATE;
TRANSPARENT
REDEFINE BUTTONBMP ID 301 OF oDlgEmp BITMAP "ACEPTAR" TEXTRIGHT;
ACTION lSeguir := PonArea(oDEmpr,oLbx,oDlgEmp)
oLbx := TXBrowse():New(oDlgEmp)
.....................................................
for nFor := 1 to len(aCols)
oLbx:aCols[ nFor ]:blDClickData := {|| (lSeguir := PonArea(oDEmpr,oLbx,oDlgEmp),oLbx:Refresh()) }
oLbx:aCols[ nFor ]:bRClickData := {|| (lSeguir := PonArea(oDEmpr,oLbx,oDlgEmp),oLbx:Refresh()) }
oLbx:aCols[ nFor ]:bRClickHeader := {|r,c,f,o| NIL }
next
.................................................................
//----------------------------------------------------------------------------//
function PonArea(oDEmpr,oLbx,oDlgEmp)
//----------------------------------------------------------------------------//
Local cCarpeta, cEstacion
Local cDir := cArea
Local cSitio,lSeguir
Sysrefresh()
ASIZE(aDatEmp, EMP->( FCOUNT() ) )
AFILL(aDatEmp,.T.)
EMP->( IniCampo(@aDatEmp) )
EMP->( TabCampo(@aDatEmp,0) )
cEstacion := NetName(.t.)
cCarpeta := cDir+"\"+cEstacion
cSitio := cDir+"\"+oDEmpr:Codigo+"\"
cArea := cSitio
cAreaTemp := cCarpeta
cNomArea := oDEmpr:Nombre+" "+Str(oDEmpr:Ejercicio)
cTrabajo := "[ "+oDEmpr:codigo+" "+oDEmpr:nombre+" ]"
oWMain:SetText("Gestión Comercial "+cTrabajo)
oWMain:Refresh()
Set Path to (cArea)
Set Default to (cArea)
cEjercicio := Str(oDEmpr:Ejercicio)
lSeguir := AbreTablas() //<<=========================Here
If lSeguir
CARGAIVA()
EndIf
oLbx:Destroy()
oDlgEmp:End()
Return( lSeguir )
*-------------------------------------------------------------------------------
FUNCTION AbreTABLAS()
*-------------------------------------------------------------------------------
Local cServer := "localhost"
Local cUser := "root"
Local cPass := ""
Local lConecta := .T.
Local cSource := cArea+"Datos.mdb"
* Para aplicaciones en MySQL
* oConex := TOLEAUTO():new("adodb.connection")
* oConex:ConnectionString:="Driver={MySQL ODBC 3.51 Driver};Server=localhost;Database=LBRINQUIS;User='root'; Password='';Option=3;"
* TRY
* oConex:Open()
* MSGINFO("CONECTADO")
* CATCH
* MSGSTOP("NO SE CONECTO")
* RETURN NIL
* END
* Para aplicaciones con ACCES
* oConex := TOLEAUTO():NEW("ADODB.connection")
oConex := CREATEOBJECT("ADODB.connection")
oConex:open("Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+cSource+";")
If Empty(oConex)
MsgAlert(" No se Pudo Establecer la Conexion Con La Base De Datos..","Atencion")
lConecta := .F.
EndIf
If lConecta
* AbreBrochas()
EndIf
Return(lConecta)
Failure to connect to the database the program does not continue, if you disconnect the program ends
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 4:48 pm
by Pedro
Simon wrote:ya lo encontre espero te sirva
Code: Select all
dDate := date()
cDate1 := "01/01/" + NTOC( str( year( dDate ) - 2, 4, 0 ), 4 )
cDate2 := NTOC( str( month( dDate ), 2, 0 ), 2 ) + "/" + NTOC( str( day( dDate ), 2, 0 ), 2) + "/" + NTOC( str( year( dDate ), 4, 0 ), 4 )
cQuery := "select checkinout.userid, userinfo.name, checkinout.checkTime, checkinout.checktype from checkinout " + CRLF + ;
"left join userinfo on checkinout.userid = userinfo.userid " + CRLF + ;
"where checkinout.checkTime >= #" + cDate1 + "# and checkinout.checkTime <= #" + cDate2 + "# " + CRLF + ;
"order by checkinout.userid, checkinout.checktime"
oDbf := Adorecordset( oApp:oAdoConnector, cQuery )
xbrowse( oDbf )
en el ejemplo hay 2 tablas una checkinout donde se almacenan los registros de entrada/salida de los trabajadores y userinfo donde se almacena la informacion de los trabajadores en el ejemplo traigo todos los registros de los trabajadores del año en curso hasta la fecha.
El problema, Simon, como ya te comentaba, es (comentando tu ejemplo) que oDbf := Adorecordset( oApp:oAdoConnector, cQuery ) = Nil, es decir oDbf no se ha creado correctamente por la sentencia cQuery (o cSql en mi caso) .
Fijate un poco más arriba, donde expongo el error CLASS NIL has no exported METHOD Eof(), provocado al saber que no se va a crear el recordset, verifico que las variables tengan los valores correctos, y si los tienen. Si te fijas tu cDate2 tiene la misma forma que cSql1 y cSql, salvo que yo uso como separadores el guión y no la barra, pero eso no creo que sea relevante.
Como le indico a Rick Lipkin voy a intentar pasar los parámetros DATE a TimeStamp a ver si así crea el recordset
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 5:58 pm
by Rick Lipkin
Pedro
What is the code behind this connection Adorecordset()
oDbf := Adorecordset( oApp:oAdoConnector, cQuery )
Rick
Re: Operaciones con fechas en ADO
Posted: Tue Mar 12, 2013 7:14 pm
by Pedro
Rick
These functions are not mine, but as Simon has put the copy you.
Are practically the same that is in FWH / sources / function / olefuncs.prg
Code: Select all
Function ADOConnector()
Local cStr := "Driver={MySQL ODBC 3.51 Driver};Server=localhost;Port=3306;Database=" + "BASE_DE_DATOS" + ";User=" + "USUARIO" + ";Password=" + "12345"+ ";Option=3;"
Local oReturn := tOleAuto():New("ADODB.connection")
oReturn:ConnectionSTring := cStr
try
oReturn:Open()
catch
oReturn := nil
end try
Return oReturn
Function ADORecordSet( oConnect, cSql, lConnect )
Local oRs
Local cError := "No se ha podido crear el objeto contenedor RECORDSET !"
try
oRs := CreateObject("ADODB.RecordSet")
oRs:CursorLocation := 3
oRs:LockType := 4
oRs:ActiveConnection:= oConnect
oRs:source := cSql
oRs:Open()
lConnect := .t.
catch
//MsgStop( cError + CRLF + CRLF + "Query : " + cSql,"Error de Datos (ADO)" )
msadoerror( cSql, "Error de Conexion con servidor" )
return nil
end try
Return oRS