Clase TMySql de Harbour

Este es un breve resumen de la clase TMySQL.

Una guía de referencia para utilizar sus métodos.

/*
MariaDB/MySql Harbour Contribution Library


TMySQLServer:  manages access to a MySQL server and returns an oServer object
               to which you'll send all your queries;

TMySQLQuery:   a standard query to an oServer with joins. Every query has a
               GetRow() method which on every call returns a TMySQLRow object
               which, in turn, contains requested fields. Query objects convert
               MySQL answers (which is an array of strings) to Clipper level types.
               At present time N (with decimals), L, D, and C Cl*pper types are
               supported.

TMySQLTable:   It's a descendant of a TMySQLQuery and you'll receive it when your
               query has no joins. It adds Update(), Append() and Delete() methods
               which receive a TMySQLRow object and reflect changes to the MySQL
               table from which they come. Please note that TMySQLQuery objects
               don't have these methods, so, if you want to change a row received
               from a TMySQLQuery object you need to construct a valid SQL query
               and submit it to an oServer object.

TMySQLRow:     Every row returned by a SELECT is converted to a TMySQLRow object.
               This object handles fields and has methods to access fields given
               a field name or position.
*/

CLASS TMySQLServer  /* Every available MySQL server */

      DATA  nSocket  /* Connection handle to server
                        (currently pointer to a MYSQL structure) */

      DATA  cServer  /* Server name */

      DATA  cDBName  /* Selected DB */

      DATA  cUser    /*	User accessing db */

      DATA  cPassword /* His/her password */

      DATA  lError /* .T. if occurred an error */

      DATA  cCreateQuery

      METHOD   New(cServer, cUser, cPassword, nPort) /*	Opens connection to a
                                                        server, returns a
                                                        server object */

      METHOD   Destroy() /* Closes connection to server */

      METHOD   SelectDB(cDBName) /* Which data base I will use
                                    for subsequent queries */

      METHOD   CreateTable(cTable, aStruct,cPrimaryKey,cUniqueKey,cAuto)
                                                 /* Create new table using the
                                                    same syntax of dbCreate() */

      METHOD   DeleteTable(cTable) /* Delete table */

      METHOD   TableStruct(cTable) /* Returns a structure array compatible
                                      with clipper's dbStruct() ones */

      METHOD   CreateIndex(cName, cTable, aFNames, lUnique)
                                                 /* Create an index (unique)
                                                    on field name(s) passed as
                                                    an array of strings aFNames */

      METHOD   DeleteIndex(cName, cTable) /* Delete index cName from cTable */

      METHOD   ListDBs()  /* Returns an array with list of data bases available */

      METHOD   ListTables() /* Returns an array with list of
                               available tables in current database */

      METHOD   Query(cQuery) /* Gets a textual query and returns a
                                TMySQLQuery or TMySQLTable object */

      METHOD   NetErr() INLINE ::lError  /* Returns .T. if something went wrong */

      METHOD   Error() /* Returns textual description of last error */

      METHOD   CreateDatabase( cDataBase ) /* Create an New Mysql Database */

      METHOD   sql_Commit() /* Commits transaction */

      METHOD   sql_Rollback() /* Rollbacks transaction */

      METHOD   sql_Version() /* Server version as numeric */

ENDCLASS


CLASS TMySQLQuery  /* Every single query submitted to MySQL server */

      DATA  nSocket /* Connection handle to MySQL server */

      DATA  nResultHandle /* Result handle received from MySQL */

      DATA  cQuery /* Copy of query that generated this object */

      DATA  nNumRows /*	Number of rows available on answer NOTE MySQL is 0 based */

      DATA  nCurRow  /*	I'm currently over row number */

      DATA  lBof

      DATA  lEof

      DATA  lFieldAsData  /* Use fields as object DATA. For compatibility
                             Names of fields can match name of TMySQLQuery/Table
                             DATAs, and it is dangerous. ::lFieldAsData:=.F.
                             can fix it */

      DATA  aRow          /* Values of fields of current row */

      DATA  nNumFields    /* How many fields per row */

      DATA  aFieldStruct  /* Type of each field, a copy is
                             here a copy inside each row */

      DATA  lError        /* .T. if last operation failed */

      METHOD   New(nSocket, cQuery) /* New query object */

      METHOD   Destroy()

      METHOD   End()

      METHOD   Refresh() /* ReExecutes the query (cQuery) so that
                            changes to table are visible */

      METHOD   GetRow(nRow) /* Return Row n of answer */

      METHOD   Skip(nRows) /* Same as clipper ones */

      METHOD   Bof()

      METHOD   Eof()

      METHOD   RecNo()

      METHOD   LastRec()

      METHOD   GoTop()

      METHOD   GoBottom()

      METHOD   GoTO(nRow)

      METHOD   FCount()

      METHOD   NetErr() /* Returns .T. if something went wrong */

      METHOD   Error()  /* Returns textual description of
                           last error and clears ::lError */

      METHOD   FieldName(nNum)

      METHOD   FieldPos(cFieldName)

      METHOD   FieldGet(cnField)

      METHOD   FieldLen(nNum) /* Length of field N */

      METHOD   FieldDec(nNum) /* How many decimals in field N */

      METHOD   FieldType(nNum) /* Clipper type of field N */

ENDCLASS


CLASS TMySQLTable   /* A query without joins; Insert() e Delete() rows are allowed.
                       NOTE: it's always a SELECT result, so it will contain a
                       full table only if SELECT * FROM ... was issued */

      DATA  cTable  /* Name of table */

      DATA  aOldValue	/* Keeps a copy of old value */

      METHOD   New(nSocket, cQuery, cTableName)

      METHOD   GetRow(nRow)

      METHOD   Skip(nRow)

      METHOD   GoTop()

      METHOD   GoBottom()

      METHOD   GoTo(nRow)

      METHOD   Update(oRow, lOldRecord, lRefresh) /* Gets an oRow and
                                                     updates changed fields */

      METHOD   Save()

      METHOD   Delete(oRow, lOldRecord, lRefresh) /* Deletes passed row
                                                     from table */

      METHOD   Append(oRow, lRefresh) /* Inserts passed row into table */

      METHOD   GetBlankRow( lSetValues ) /* Returns an empty row with
                                            all available fields empty */

      METHOD   SetBlankRow() /*	Compatibility */

      METHOD   Blank()

      METHOD   FieldPut(cnField, Value) /* Field identifier, not only a number */

      METHOD   Refresh()

      METHOD   MakePrimaryKeyWhere() /*	Returns a WHERE x=y statement which
                                        uses primary key (if available) */

ENDCLASS


CLASS TMySQLRow   /* Every single row of an answer */

      DATA  aRow  /* A single row of answer */

      DATA  aDirty  /* Array of booleans set to .T. if
                       corresponding field of aRow has been changed */

      DATA  aOldValue   /* If aDirty[n] is .T. aOldValue[n] keeps a copy of changed
                           value if aRow[n] is part of a primary key  */

      DATA  aOriValue  /* Original values ( same as TMySQLtable:aOldValue ) */

      DATA  aFieldStruct /* Type of each field */

      DATA  cTable  /* Name of table containing this row,
                       empty if TMySQLQuery returned this row */

      METHOD	New(aRow, aFStruct, cTableName) /* Create a new Row object */

      METHOD   FieldGet(cnField)  /* Same as clipper ones, but FieldGet()
                                     and FieldPut() accept a string as */

      METHOD   FieldPut(cnField, Value) /* Field identifier, not only a number */

      METHOD   FieldName(nNum)

      METHOD   FieldPos(cFieldName)

      METHOD   FieldLen(nNum)  /* Length of field N */

      METHOD   FieldDec(nNum)  /* How many decimals in field N */

      METHOD   FieldType(nNum) /* Clipper type of field N */

      METHOD   MakePrimaryKeyWhere() /*	Returns a WHERE x=y statement
                                        which uses primary key (if available) */

ENDCLASS

Agenda de Contactos MySQL

En esta oportunidad mostraremos el código para gestionar una agenda de contactos que utiliza una base de datos MySQL, se usa como recursos OOHG y TMySQL que viene como contribución por defecto, con Harbour.

2015-06-06_131341
2015-06-06_131412
2015-06-06_131435
2015-06-06_131456

/*
 *  Agenda de Contactos 2
 *  Humberto Fornazier - Marzo 2003 <[email protected]>
 *
 *  Agenda de Contactos 2 ADO
 *  Adapted by Ivanil Marcelino <[email protected]>
 *
 *  Agenda de Contactos 2 MySQL
 *  Adapted and Enhanced by MigSoft - 2015 <migsoft at oohg.org>
 *
 */

#Include "oohg.ch"

#define DARKCYAN   { 0,139,139 }

*------------------------------------------------------------*
Function Main()
*------------------------------------------------------------*
    Local i := 0
    PUBLIC cServer := "localhost"
    PUBLIC cUser   := "root"
    PUBLIC cPaswd  := ""

    oServer := TMySQLServer():New( cServer, cUser, cPaswd )
    if oServer:NetErr()
        oServer := Nil
        msgstop( "Conexión no establecida","Error !!! ONE")
        Return Nil
    ENDIF

    Prepare_Data( oServer )

    SET CENTURY ON
    Private lNuevo := .F.
    DEFINE WINDOW Form_1   ;
        AT 0,0               ;
        WIDTH 450  ;
        HEIGHT 470 ;
        TITLE "Agenda de Contactos MySQL";
        MAIN                 ;
        ICON "AGENDA"  ;
        NOMAXIMIZE ;
        NOSIZE     ;
        ON RELEASE Finaliza_Sistema(oServer) ;
        BACKCOLOR DARKCYAN

        @ 010,415 Grid GIndice Of Form_1 WIDTH 20 ;
            HEIGHT 360 HEADERS {""} WIDTHS { 16 } ;
            FONT "Arial" SIZE 07.5 ;
            TOOLTIP "Click en Letra Deseada"  ;
            ON DBLCLICK captura_Agenda()

        @ 010,010 GRID Grid_Agenda        ;
            WIDTH  398           ;
            HEIGHT 360           ;
            HEADERS {"Código","Nombre"}    ;
            WIDTHS  {53,324}     ;
            FONT "Arial" SIZE 09     ;
            ON DBLCLICK Nuevo_Registro(.F.)

        @ 385,010  BUTTON Btn_Nuevo Of Form_1  ;
            CAPTION '&Nuevo'       ;
            ACTION Nuevo_Registro(.T.)       ;
            WIDTH 120 HEIGHT 27     ;
            FONT "Arial" SIZE 09      ;
            TOOLTIP "Nuevo Registro"       ;
            FLAT

        @ 385,165  BUTTON Btn_Imprimir Of Form_1  ;
            CAPTION '&Imprimir'       ;
            ACTION Imprimir()       ;
            WIDTH 120 HEIGHT 27     ;
            FONT "Arial" SIZE 09      ;
            TOOLTIP "Imprime Contactos"    ;
            FLAT

        @ 385,318  BUTTON Btn_Salir Of Form_1  ;
            CAPTION '&Salir'       ;
            ACTION  Finaliza_Sistema( oServer )   ;
            WIDTH 120 HEIGHT 27     ;
            FONT "Arial" SIZE 09      ;
            TOOLTIP "Finalizar Sistema"   ;
            FLAT

    END WINDOW
    For i := 1 To 26
        ADD ITEM { CHR(i+64) } TO GIndice OF Form_1
    Next
    MODIFY CONTROL GIndice OF Form_1 VALUE 1
    captura_Agenda()
    CENTER WINDOW   Form_1
    ACTIVATE WINDOW Form_1
Return
*------------------------------------------------------------*
Function Finaliza_Sistema(oServer)
*------------------------------------------------------------*
    oServer := Nil
    Form_1.Release
Return .t.
*------------------------------------------------------------*
Function captura_Agenda()
*------------------------------------------------------------*
    Local cPesq

    cPesq  := ValorDeColumna("GIndice","Form_1",1)
    cPesq  := IIf( Empty(cPesq), "A" , cPesq )
    oQuery := oServer:Query("Select * from agenda where nombre like '"+;
              cPesq+"%'"+" order by nombre")
    IF !(oQuery:Neterr())
        DELETE ITEM ALL FROM Grid_Agenda OF Form_1
        Do While ! oQuery:Eof()
            ADD ITEM {oQuery:FieldGet("codigo"),oQuery:FieldGet("nombre")} ;
                     TO Grid_Agenda OF Form_1
            oQuery:Skip()
        EndDo
    ELSE
        msgstop( "Conexión no establecida","Error!!! TWO")
    ENDIF

Return Nil
*------------------------------------------------------------*
Function Nuevo_Registro( lNuevo_Registro  )
*------------------------------------------------------------*
    Local cCodigo	:= ""
    Local cNombre       := ""
    Local cFone1	:= ""
    Local cFone2	:= ""
    Local cFone3        := ""
    Local cFone4	:= ""
    Local cEmpresa	:= ""
    Local cDireccion	:= ""
    Local cPais	        := ""
    Local cEmail	:= ""

    cCodigo := ValorDeColumna( "Grid_Agenda" ,  "Form_1" , 1 )

    IF  oServer  != NIL
        Form_1.Btn_Nuevo.Enabled	:= .F.
        Form_1.Btn_Salir.Enabled	:= .F.

        lNuevo := lNuevo_Registro

        If ! lNuevo
            oQuery := oServer:Query("Select * from agenda where codigo='"+cCodigo+"'")
            if oQuery:Eof()
                Release Window ALL
                Return
            endif
            cNombre      := oQuery:FieldGet("Nombre")
            cFone1       := oQuery:FieldGet("Fono1")
            cFone2       := oQuery:FieldGet("Fono2")
            cFone3       := oQuery:FieldGet("Fono3")
            cFone4       := oQuery:FieldGet("Fono4")
            cEmpresa     := oQuery:FieldGet("Empresa")
            cDireccion   := oQuery:FieldGet("Direccion")
            cEmail       := oQuery:FieldGet("Email")
            cPais        := oQuery:FieldGet("Pais")
        EndIf

        DEFINE WINDOW Form_2   ;
            AT 0,0	              ;
            WIDTH 528	;
            HEIGHT 344	;
            TITLE "Agenda de Contactos - " + ;
                   Iif( lNuevo , "Nuevo Registro" , "Modificando Registro");
            ICON "AGENDA"	       ;
            MODAL		       ;
            NOSIZE		       ;
            ON RELEASE  Salida_F2()    ;
            BACKCOLOR WHITE

            DEFINE FRAME Frame_1
            ROW    10
            COL    10
            WIDTH  500
            HEIGHT 250
            OPAQUE .T.
            END FRAME

            @ 30,20 LABEL Label_Codigo	;
                VALUE 'Código'		;
                WIDTH 140		;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @ 60,20 LABEL Label_Nombre	;
                VALUE 'Nombre'		;
                WIDTH 80		;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @ 90,20 LABEL Label_Fone1	;
                VALUE 'Teléfono 1'		;
                WIDTH 80		;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @120,20 LABEL Label_Fone2	;
                VALUE 'Teléfono 2'		;
                WIDTH 80		;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @90,270 LABEL Label_Fone3       ;
                VALUE 'Teléfono 3'		;
                WIDTH 80			;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @120,270 LABEL Label_Fone4	;
                VALUE 'Teléfono 4'		;
                WIDTH 80		;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @150,20 LABEL Label_Empresa	;
                VALUE 'Empresa'		;
                WIDTH 80			;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @180,20 LABEL Label_Direccion ;
                VALUE 'Dirección'		;
                WIDTH 80			;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @210,20 LABEL Label_Email ;
                VALUE 'E-Mail'		;
                WIDTH 80			;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @210,325 LABEL Label_Estado	;
                VALUE 'País'		;
                WIDTH 50		;
                HEIGHT 30		;
                FONT 'Arial' SIZE 09      ;
                BACKCOLOR WHITE   ;
                FONTCOLOR DARKCYAN BOLD

            @ 30,120 TEXTBOX T_Codigo		;
                WIDTH 80			;
                VALUE cCodigo      ;
                TOOLTIP 'Código de Contacto'

            @ 60,120 TEXTBOX T_Nombre      ;
                OF Form_2		;
                WIDTH 370		;
                VALUE cNombre		;
                TOOLTIP 'Nombre de Contacto'	;
                MAXLENGTH 40		;
                UPPERCASE		;
                ON ENTER Iif( ! Empty( Form_2.T_Nombre.Value ) , ;
                   Form_2.T_Direccion.SetFocus , Form_2.T_Nombre.SetFocus )

            @ 90,120 TEXTBOX T_Fone1   ;
                OF Form_2      ;
                WIDTH 120        ;
                VALUE cFone1      ;
                TOOLTIP 'Teléfono de Contacto';
                MAXLENGTH 10     ;
                UPPERCASE        ;
                ON GOTFOCUS Form_2.Btn_Salvar.Enabled := .T.  ;
                ON ENTER Form_2.T_Fone2.SetFocus

            @120,120 TEXTBOX T_Fone2     ;
                OF Form_2      ;
                WIDTH 120		;
                VALUE cFone2		;
                TOOLTIP 'Teléfono de Contacto'	;
                MAXLENGTH 10		;
                UPPERCASE		;
                ON ENTER Form_2.T_Fone3.SetFocus

            @90,370 TEXTBOX T_Fone3       ;
                OF Form_2     ;
                WIDTH 120      ;
                VALUE cFone3		;
                TOOLTIP 'Teléfono de Contacto'	;
                MAXLENGTH 10		;
                UPPERCASE		;
                ON ENTER Form_2.T_Empresa.SetFocus

            @120,370 TEXTBOX T_Fone4     ;
                OF Form_2     ;
                WIDTH 120		;
                VALUE cFone4		;
                TOOLTIP 'Teléfono de Contacto'	;
                MAXLENGTH 10		;
                UPPERCASE		;
                ON ENTER Form_2.T_Empresa.SetFocus

            @150,120 TEXTBOX T_Empresa    ;
                OF Form_2     ;
                WIDTH 370		;
                VALUE cEmpresa		;
                TOOLTIP 'Empresa';
                MAXLENGTH 40		;
                UPPERCASE		;
                ON ENTER Form_2.T_Direccion.SetFocus

            @180,120 TEXTBOX T_Direccion      ;
                OF Form_2       ;
                WIDTH 370		;
                VALUE cDireccion		;
                TOOLTIP 'Dirección de Contacto';
                MAXLENGTH 40		;
                UPPERCASE		;
                ON ENTER Form_2.T_Email.SetFocus

            @210,120 TEXTBOX T_Email ;
                OF Form_2     ;
                WIDTH 180		;
                VALUE cEmail		;
                TOOLTIP 'E-Mail de Contacto';
                MAXLENGTH 30		;
                ON ENTER Form_2.T_Pais.SetFocus

            @210,370 TEXTBOX T_Pais      ;
                OF Form_2       ;
                WIDTH 120		;
                VALUE cPais		;
                TOOLTIP 'País de Contacto'	;
                MAXLENGTH 02		;
                UPPERCASE		;
                ON ENTER Form_2.Btn_Salvar.SetFocus

            @ 270,150 BUTTON Btn_Salvar Of Form_2	;
                CAPTION '&Salvar'     ;
                ACTION Salvar_Registro()        ;
                WIDTH 100 HEIGHT 28     ;
                FONT "Arial" SIZE 09      ;
                TOOLTIP "Salvar Registro" ;
                FLAT

            @ 270,280  BUTTON Btn_Excluir Of Form_2   ;
                CAPTION '&Eliminar'        ;
                ACTION Excluir_Registro()   ;
                WIDTH 100 HEIGHT 28     ;
                FONT "Arial" SIZE 09      ;
                TOOLTIP "Excluir Registro"    ;
                FLAT

            @ 270,410  BUTTON Btn_Cancelar Of Form_2  ;
                CAPTION '&Cancelar'       ;
                ACTION Salir_do_Form2()      ;
                WIDTH 100 HEIGHT 28     ;
                FONT "Arial" SIZE 09      ;
                TOOLTIP "Cancelar Operación"   ;
                FLAT

        END WINDOW
        Form_2.T_Codigo.Enabled := .F.

        If lNuevo
            Form_2.Btn_Salvar.Enabled := .F.
            Form_2.Btn_Excluir.Enabled := .F.
        EndIf

        CENTER WINDOW   Form_2
        ACTIVATE WINDOW Form_2

    ELSE
        msgstop( "Conexión no establecida","Error!!! NUEVO")
    ENDIF
Return Nil
*------------------------------------------------------------*
Procedure Salida_F2
*------------------------------------------------------------*
    Form_1.Btn_Nuevo.Enabled    := .T.
    Form_1.Btn_Salir.Enabled    := .T.
    Form_2.Btn_Excluir.Enabled := .T.
    captura_Agenda()
    Form_1.Grid_Agenda.SetFocus()
Return
*------------------------------------------------------------*
Function Salvar_Registro()
*------------------------------------------------------------*
    Local ProximoCodigo := "", cSQL
    Local cCodigo := ""

    If Empty( Form_2.T_Nombre.Value )
        MsgINFO( "Se debe Indicar Nombre!!!" , "Agenda" )
        Form_2.T_Nombre.SetFocus
        Return Nil
    EndIf

    oQuery := oServer:Query("Select Codigo from agenda order by codigo desc")
    oQuery:GoTop()

    IF !(oQuery:Neterr())

        If  lNuevo

            if oQuery:Eof()
                ProximoCodigo:="0001"
            else
                ProximoCodigo := StrZero( Val(oQuery:FieldGet("Codigo")) + 1 , 4 )
            endif

            Form_2.T_Codigo.Value := ProximoCodigo

            cSql:="INSERT INTO AGENDA (Codigo,Nombre,Fono1,Fono2,Fono3,Fono4,";
                  +"Empresa,Direccion,Email,Pais) VALUES ('"
            cSql+=ProximoCodigo             +"','"
            cSql+=Form_2.T_Nombre.Value     +"','"
            cSql+=Form_2.T_Fone1.Value      +"','"
            cSql+=Form_2.T_Fone2.Value      +"','"
            cSql+=Form_2.T_Fone3.Value      +"','"
            cSql+=Form_2.T_Fone4.Value      +"','"
            cSql+=Form_2.T_Empresa.Value    +"','"
            cSql+=Form_2.T_Direccion.Value  +"','"
            cSql+=Form_2.T_Email.Value      +"','"
            cSql+=Form_2.T_Pais.Value       +"')"
        Else
            cSql:="UPDATE AGENDA SET "
            cSql+="Nombre='"+Form_2.T_Nombre.Value        +"',"
            cSql+="Fono1='"+Form_2.T_Fone1.Value          +"',"
            cSql+="Fono2='"+Form_2.T_Fone2.Value          +"',"
            cSql+="Fono3='"+Form_2.T_Fone3.Value          +"',"
            cSql+="Fono4='"+Form_2.T_Fone4.Value          +"',"
            cSql+="Empresa='"+Form_2.T_Empresa.Value      +"',"
            cSql+="Direccion='"+Form_2.T_Direccion.Value  +"',"
            cSql+="Email='"+Form_2.T_Email.Value          +"',"
            cSql+="Pais='"+Form_2.T_Pais.Value            +"'"
            cSql+=" Where codigo='"+Form_2.T_Codigo.Value +"'"
        Endif

        oServer:Query( cSQL )

        If !( oServer:NetErr() )
            MsgInfo( "Registo "+Iif( lNuevo , "Incluído" ,"Modificado!!" )  )
        Endif

    ELSE
        msgstop( "Conexión no establecida","Error!!! SAVE")
    ENDIF

    PosicionaIndice( Left(Form_2.T_Nombre.Value,1) )
    captura_Agenda()
    Form_2.Release

Return Nil
*------------------------------------------------------------*
Function Salir_do_Form2()
*------------------------------------------------------------*
    Form_1.Btn_Nuevo.Enabled	:= .T.
    Form_1.Btn_Salir.Enabled	:= .T.
    Form_2.Btn_Excluir.Enabled := .T.
    Form_2.Release
    captura_Agenda()
    Form_1.Grid_Agenda.SetFocus()
Return Nil
*------------------------------------------------------------*
Function Excluir_Registro()
*------------------------------------------------------------*
    Local cCodigo:=Form_2.T_Codigo.Value,cSql
    If MsgOkCancel ("Confirma Exclusión de Registro??", "Excluir "+cCodigo)
        cSql:="DELETE FROM AGENDA WHERE CODIGO='"+cCodigo+"'"
        oServer:Query( cSQL )
    EndIf
    PosicionaIndice( Left(Form_2.T_Nombre.Value,1) )
    captura_Agenda()
    Form_2.Release
    Form_1.Grid_Agenda.SetFocus
Return Nil
*------------------------------------------------------------*
Function ValorDeColumna( ControlName, ParentForm , nCol )
*------------------------------------------------------------*
    Local aRet := {}
    If GetControlType (ControlName,ParentForm) != "GRID"
        MsgBox( "Objeto no esta en un Grid!!")
        Return( aRet )
    EndIf
    nCol := Iif( nCol == Nil .Or. nCol == 0 , 1 , nCol )
    aRet := GetProperty (  ParentForm  , ControlName , 'Item' ,;
            GetProperty( ParentForm , ControlName , 'Value' ) )
Return( aRet[ nCol ] )
*------------------------------------------------------------*
Function PosicionaIndice(cLetra)
*------------------------------------------------------------*
    Local i := 0
    For i := 1 To 26
        If CHR(i+64) == cLetra
            MODIFY CONTROL GIndice OF Form_1 VALUE i
        EndIf
    Next
    Form_1.GIndice.SetFocus
Return Nil
*------------------------------------------------------------*
Function Imprimir()
*------------------------------------------------------------*
    Local nLinea:=i:=nReg:=0,cLetra:="",oQuery,Handle,cLinea,Cr:=Chr(13)+chr(10)
    Private nFont := 11
    Private cArquivo := ""

    IF  oServer != NIL
        Handle:=fCreate("Rel.tmp")
        if Handle<=0
            Return
        endif
        cLetra := ValorDeColumna( "GIndice" ,  "Form_1" , 1 )
        oQuery := oServer:Query("Select * from agenda where nombre like '"+;
                  cLetra+"%'"+" order by nombre")
        Do While ! oQuery:Eof()
            If nLinea == 0.or.nLinea>55
                cLinea := PadC(" Agenda de Contactos",78)+Cr
                cLinea += PadC("Contactos por letra "+cLetra,78)+Cr
                cLinea += "Código  Nombre"+Cr
                cLinea += Replicate("-",78)+cr
                Fwrite(Handle,cLinea)
                nLinea:=5
            EndIf
            nLinea += 1
            nReg   += 1
            Fwrite(Handle,"  "+oQuery:FieldGet("Codigo") +;
                     "   "+oQuery:FieldGet("Nombre")+Cr)
            oQuery:Skip()
        EndDo
        cLinea := Replicate("-",78)+cr
        cLinea+="Registros Impresos: "+StrZero(nReg,4)
        Fwrite(Handle,cLinea)
        fClose(Handle)
        cArquivo :=memoRead("REL.TMP")
        Define Window Form_3;
            At 0,0              ;
            Width 450        ;
            Height 500       ;
            Title "Contactos por Letra "+cLetra;
            ICON "AGENDA";
            CHILD ;
            NOSYSMENU;
            NOSIZE       ;
            BACKCOLOR WHITE

            @20,-1 EDITBOX Edit_1 ;
                WIDTH 460 ;
                HEIGHT 510 ;
                VALUE cArquivo ;
                TOOLTIP "Contactos por Letra "+cLetra ;
                MAXLENGTH 255

            @ 01,01 BUTTON Bt_Zoom_mas  ;
                CAPTION '&Zoom(+)'             ;
                WIDTH 120 HEIGHT 17    ;
                ACTION ZoomLabel(1);
                FONT "MS Sans Serif" SIZE 09 FLAT

            @ 01,125 BUTTON Bt_Zoom_menos  ;
                CAPTION '&Zoom(-)'             ;
                WIDTH 120 HEIGHT 17    ;
                ACTION ZoomLabel(2);
                FONT "MS Sans Serif" SIZE 09 FLAT

            @ 01,321 BUTTON Salir_1  ;
                CAPTION '&Salir'             ;
                WIDTH 120 HEIGHT 17    ;
                ACTION Form_3.Release;
                FONT "MS Sans Serif" SIZE 09 FLAT

        End window
        MODIFY CONTROL Edit_1 OF Form_3 FONTSIZE nFont
        Center Window Form_3
        Activate Window Form_3
    ELSE
        msgstop( "Conexión no establecida", "Error!!! IMPRIMIR")
    ENDIF

Return Nil
*------------------------------------------------------------*
Function ZoomLabel(nmm)
*------------------------------------------------------------*
    If nmm == 1
        nFont++
    Else
        nFont--
    Endif
    MODIFY CONTROL Edit_1 OF Form_3 FONTSIZE nFont
Return Nil
*------------------------------------------------------------*
Function Prepare_data( oServer )
*------------------------------------------------------------*
    Local lResp1 := .F., lResp2 := .F.

    Database_Create( "test", oServer )
    Database_Connect( "test", oServer )
    Table_Create( "agenda", oServer )

Return Nil
*------------------------------------------------------------*
Function Database_Connect( cDatabase, oServer )
*------------------------------------------------------------*
    Local i:= 0
    Local aDatabaseList:= {}

    cDatabase:= Lower(cDatabase)
    If oServer == Nil
        MsgInfo("No conectado con Servidor MySQL!")
        Return Nil
    EndIf

    aDatabaseList:= oServer:ListDBs()
    If oServer:NetErr()
        MsgInfo("Error verificando lista de bases de datos: " + oServer:Error())
        Return Nil
    Endif

    If AScan( aDatabaseList, Lower(cDatabase) ) == 0
        MsgInfo( "Base de Datos "+cDatabase+" no existe!")
        Return Nil
    EndIf

    oServer:SelectDB( cDatabase )
    If oServer:NetErr()
        MsgInfo("Error conectando con base de datos "+cDatabase+": "+oServer:Error() )
        Return Nil
    Endif

Return Nil
*------------------------------------------------------------*
Function  Database_Create( cDatabase, oServer )
*------------------------------------------------------------*
    Local aDatabaseList := {}, lResp := .F.

    cDatabase := Lower( cDatabase )

    If oServer == Nil
        MsgInfo("No conectado con Servidor MySQL!")
        lResp := .F.
        Return lResp
    EndIf

    aDatabaseList := oServer:ListDBs()

    If oServer:NetErr()
        MsgInfo("Error verificando lista de base de datos: " + oServer:Error())
        lResp := .F.
        Return lResp
    Endif

    If AScan( aDatabaseList, Lower(cDatabase) ) != 0
        //MsgInfo( "Base de Datos ya existe!")
        lResp := .F.
        aDatabaseList := {}
        Return lResp
    EndIf

    oServer:CreateDatabase( cDatabase )

    If oServer:NetErr()
        MsgInfo("Error creando Base de Datos: " + oServer:Error() )
        lResp := .F.
    Else
        lResp := .T.
    Endif

Return( lResp )
*------------------------------------------------------------*
Function Table_Create( cTable, oServer )
*------------------------------------------------------------*
    Local aTableList := {}
    Local cQuery, lResp := .F.

    If oServer == Nil
        MsgStop("No conectado con Servidor MySQL...")
        lResp := .F.
        Return lResp
    EndIf

    aTableList := oServer:ListTables()
    If oServer:NetErr()
        MsgStop("Error verificando lista de tablas: " + oServer:Error() )
        lResp := .F.
        Return lResp
    Endif

    If AScan( aTableList, Lower(cTable) ) != 0
        //MsgStop( "Tabla "+cTable+" ya existe!")
        lResp := .F.
        Return lResp
    EndIf

    cQuery:= "CREATE TABLE "+cTable+" ( CODIGO Char(4), NOMBRE Char(40),"+ ;
             "FONO1 Char(10), FONO2 Char(10), FONO3 Char(10), FONO4 Char(10),"+ ;
             "EMPRESA Char(40), DIRECCION Char(40), EMAIL Char(30), PAIS Char(2) ) "

    oQuery := oServer:Query( cQuery )

    If oServer:NetErr()
        MsgStop("Error creando tabla "+cTable+": "+oServer:Error() )
        lResp := .F.
    Else
        lResp := .T.
    Endif

    oQuery:Destroy()

Return lResp

 

AMD Sexta Generación de procesadores

 

AMD (NASDAQ: AMD) anunció su sexta generación de procesadores serie A, la primera unidad de procesamiento acelerado (APU) de alto rendimiento con un diseño de “sistema en chip” (SoC).

AMD-procesador

Anteriormente conocido bajo el nombre código “Carrizo”, el chip sería, según AMD, “el procesador para notebooks más versátil nunca antes producido”. Con ello, la empresa pone de relieve que se trata del primer hardware para notebooks de codificado de videos de alta eficiencia (HEVC) del mundo, primer diseño compatible con arquitectura de sistemas heterogéneos (HSA) 1.0 y la primera APU de alto rendimiento compatible con ARM TrustZone.

El nuevo procesador incorpora hasta 12 núcleos de cómputo; 4 CPU “Excavator” y 8 GPU Graphics Core Next (GCN) de AMD. “El resultado es un procesador innovador que cuenta con más del doble de duración de batería que su antecesor, rendimiento en juegos dos veces más rápido que los procesadores de la competencia, experiencias innovadoras habilitadas a través de HSA y una experiencia premium de Microsoft Windows 10 con soporte para DirectX 12”, escribe AMD en su sitio.

Satisfacción en Microsoft

“AMD y Microsoft siguen innovando en lo relacionado con la informática personal con sus avances en Windows 10 y en DirectX 12, y hoy con la introducción de la sexta generación de procesadores serie A de AMD”, dice Roanne Sones, gerente general del Grupo de Sistemas Operativos, de Microsoft Corp.

Fuente: DiarioTI

Dolphin para MySQL

A continuación un acercamiento breve a lo que ofrece la clase Dolphin de Daniel García Gil, para la gestión de bases de datos MySQL.

Mayor información y descargas en https://bitbucket.org/danielgarciagil/tdolphin/downloads

CLASS TDolphinSrv

   CLASSDATA nQueryId
   CLASSDATA nServerId  INIT 1

   DATA bDecrypt       /*codeblock to evaluate in connect process (C Level), ;
                         to decrpty Host, User, Password and Database*/
   DATA bOnError       /*Custom manager error message
                         ( Self, nError, lInternal ) */
   DATA bOnBackUp      /*codeblock to evaluate in backup process*/

   DATA bOnRestore     /*codeblock to evaluate in restore process*/
   DATA bOnMultiQry    /*codeblock to evaluate for each Query in METHOD MultiQuery*/
   DATA bOnAfterQuery   /*codeblock to evaluate after execute a MySql Statement*/
#ifdef DEBUG
   DATA bDebug         /*codeblock to evaluate for each Query, ;
                         Arg cQuery, ProcName( 1 ), ProcLine( 1 )*/
#endif

   DATA cDBName        /*Data base selected*/
   DATA cPassword      /*Data contains the password for user*/
   DATA cHost          /*Host name, may be either a host name or an IP address */
   DATA cUser          /*DAta contains the user's MySQL login ID*/
   DATA cNameHost

   DATA cBuild     INIT "25-Jan-12 6:41:25 AM"

   DATA hMysql         /*MySQL connection handle*/
                       
   DATA lReConnect     
   
   DATA Cargo          /*For programmer use*/
                       
   DATA lError         /*Error detection switch*/
                  
   DATA nFlags         /*Client flags*/
   DATA nInternalError /*error manager, no come from MySQL*/
   DATA nPort          /*value is used as the port number for the TCP/IP connection*/
   
   DATA aQueries       /*Array queries actives*/
   
   METHOD New( cHost, cUser, cPassword, nPort, nFlags, bOnError, cDBName )
   METHOD ssl( cHost, cUser, cPassword, nPort, nFlags, bOnError, cDBName, cSslKeyFile, ;
                                      cSslCertFile, cSslCaFile, cCertsPath, cSslCipher )
   
   METHOD AddUser( cHost, cUser, cPassword, cDb, lCreateDB, acPrivilegs, cWithOption )
                              /*The AddUser() enables system administrators to grant privileges ;
                                to MySQL user accounts. 
                                AddUser also serves to specify other account characteristics such ;
                                as use of secure connections and limits on access to server resources. 
                                To use AddUser(), you must have the GRANT OPTION privilege, 
                                and you must have the privileges that you are granting.*/
                                
   METHOD AddQuery( oQuery )          INLINE AAdd( ::aQueries, oQuery )
                              /*used internally*/

   METHOD Backup( aTables, cFile, lDrop, lOver, nStep, cHeader, cFooter, lCancel )

   METHOD BeginTransaction()          INLINE ::SqlQuery( "BEGIN" )    
   
   METHOD Call( /*...*/ )  /*run a function/procedure with n parameters, 
                             1st parameter must be a function/procedure name,
                             this method does not return any result in query */

   METHOD Debug( cText )     INLINE  If(  ::bDebug != NIL, Eval( ::bDebug, cText, ;
                                                  ProcName( 1 ), ProcLine( 1 ) ), )
   METHOD ReturnCall( /*...*/ ) /*same METHOD Call but this return a result set*/
   
   METHOD ChangeEngine( cTable, cType )  INLINE ::SqlQuery( "ALTER TABLE " + D_LowerCase( cTable ) + ;
                                                             " ENGINE = " + D_LowerCase( cType ) )

   METHOD ChangeEngineAll( cType )  
   
   METHOD CheckError( nError )

   METHOD CloseQuery( nId )
   
   METHOD CloseAllQuery()             

   METHOD Compact( cTable )
 
   METHOD Connect( cHost, cUser, cPassword, nPort, nFlags, cDBName )    
                     /*to establish a connection to a MySQL database engine running on server*/

   METHOD SSLConnect( cHost, cUser, cPassword, nPort, nFlags, cDBName, cSslCaFile, ;
                                             cSslCertFile, cSslKeyFile, cSslCipher )


   METHOD CommitTransaction()       INLINE ::Debug( "COMMITED" ),  MySqlCommit( ::hMySql ) == 0 
                              /*Commits the current transaction.*/

   METHOD CreateForeign( cName, cTabParent, aIndColName, cTabChild, aIndColRef, ;
                         lOnDelete, nActionDelete, lOnUpdate, nActionUpdate ) 
                              /* Create Foreign Key cName Symbol Name */
   
   METHOD CreateIndex( cName, cTable, aFNames, nCons, nType )                              
   
   METHOD CreateInfo( cTable )
                              
   METHOD CreateTable( cTable, aStruct, cPrimaryKey, cUniqueKey, cAuto, cExtra )
                              /*creates a table with the cTable name*/

   METHOD DBCreate( cName, lIfNotExist, cCharSet, cCollate )
                              /* Create Database in current active connection*/

                                
   METHOD DBExist( cDB )  INLINE If( ! Empty( cDB ), Len( ::ListDBs( D_LowerCase( cDB ) ) ) > 0, .F. )
                              /* verify is Data Base exist, return logical value*/

   METHOD DeleteDB( cDB, lExists )
                              /*Delete Tables*/
                              
   METHOD DeleteForeign( cName, cTable ) 
                              /*Delete Foreign*/

   METHOD DeleteIndex( cName, cTable )         
                              /*Delete Index*/                     
   
   METHOD DeleteTables( acTable, lExists )
                              /*Delete Tables*/
                              
   METHOD DropUser( cUser )             INLINE ::SqlQuery( "DROP USER " + cUser )
                              /*Drop User*/
   
   METHOD Embedded( cDataBase, aOptions, aGroups )
   
   METHOD End()
   
   METHOD ErrorTxt()          INLINE  If( ::hMysql != NIL, MySqlError( ::hMysql ), "" )
                              /* Returns a string containing the error message for 
                                 the most recently invoked API function that failed.*/
   
   METHOD ErrorNo()           INLINE ::lError := .F., MySqlGetErrNo( ::hMysql )
                              /* Returns the error code for the most recently invoked 
                                API function that can succeed or fail. 
                                A return value of zero means that no error occurred.*/
                                
   METHOD Execute( cQuery, uParams )   INLINE ::SqlQuery( cQuery, uParams )
   
   METHOD ExecuteScript( cFile ) 

   METHOD GetAutoIncrement( cTable )
                                /*Retrieve next Auto increment value in specified table;
                                 in current database selected*/   

   METHOD GetEngine( cTable, cSchema )
      
   METHOD GetServerInfo()       INLINE If( ::hMysql != NIL, MyServerInfo( ::hMysql ), "" ) 
                                /*Returns a string that represents the server version number.*/

   
   METHOD GetClientInfo()       INLINE If( ::hMysql != NIL, MyClientInfo(), "" ) 
                           /*Return a string that represents the MySQL client library version.*/

   
   METHOD GetPrivileges()
   
   METHOD GetQueryId()   
   

   METHOD GetRowsFromTable( cTable )
                               /*Retrieve total row avalaible in  specified table;
                                in current database selected*/    

   METHOD GetRowsFromQry( oQuery )
                               /*Retrieve total row avalaible in  specified query;
                                in current database selected*/    
   
   METHOD hInsert( ctable, hValues, cDuplicateKey )
   
   METHOD Insert( cTable, aColumns, aValues, cDuplicateKey )
                              /*inserts new rows into an existing table.*/
                              
   METHOD InsertFromDbf( cTable, cAlias, nLimit, aStruct, bOnInsert, cDuplicateKey ) 
                              /*insert new rows into an existing table from DBF file,
                                the table should be contain same fieldname that DBF */

   METHOD IsAutoIncrement( cField, cTable )
                              /* Verify is a field is Auto Increment*/
   
   METHOD LastDownData( cTable, cCol, uDef )
   
   METHOD LastInsertID()      /*Returns the first automatically generated value that was 
                                set for an AUTO_INCREMENT column by the most recently 
                                executed INSERT statement to affect such a column.*/
   
   METHOD ListDBs( cWild )    /* Returns a array set consisting of database names on the server 
                                 that match the simple regular expression specified by the wild  
                                 parameter.wild may contain the wildcard characters n++%n++ or 
                                 n++_n++, or may be a "" to match all databases.*/
   
   METHOD ListTables( cWild ) /* Returns a array set consisting of tables names in current satabase 
                                 that match the simple regular expression specified by the wild 
                                 parameter. wild may contain the wildcard characters n++%n++ 
                                 or n++_n++, or may be a "" to match all tables.*/
                                 
   METHOD MultiQuery( aQuery, lTransaction )
   
   METHOD NextResult() INLINE mysql_next_result( ::hMysql )
                               /* Use only for MULTIPLE STATEMENT or stored PROCEDURE/FUNCTION */   
   
   METHOD Ping()       INLINE If( MySqlPing( ::hMysql ) > 0, ( ::CheckError(), .F.), .T. )
                   /* Checks whether the connection to the server is working. 
                      If the connection has gone down and auto-reconnect is enabled an attempt 
                      to reconnect is made. If the connection is down and auto-reconnect is disabled,
                      ::ping() returns an error.*/

   METHOD Query( cQuery )   

   METHOD ReConnect()

   METHOD RenameUser( cFromUser, cServer, cRename )
                              /*Rename User*/
                              
   METHOD Restore( cFile, lCancel )                              

   METHOD RevokePrivileges( cHost, cUser, cDB, acPrivilegs )
                              /*The RevokePrivileges() enables system administrators 
                                              to revoke privileges from MySQL accounts.*/
   

   METHOD RollBack()        INLINE ::Debug( "ROLLBACK" ), MySqlRollBack( ::hMysql )
                              /* Rolls back the current transaction.*/
                             
   METHOD SelectDB( cDBName ) 
                              /*Select data base in current active connection*/
   

   METHOD SelectTable( aColumns, aTables, cWhere, cGroup, cHaving, cOrder, cLimit, lWithRoll )
   
   METHOD SetNameServer( cName )
   
   METHOD SetMultiStatement( lOnOf ) INLINE SetMultiStatement( ::hMysql, lOnOf )
   
   METHOD SqlQuery( cQuery, uParams )  /*Executes the SQL statement pointed to by cQuery, 
                              Normally, the string must consist of a single SQL statement 
                              and you should not add a terminating semicolon (n++;n++) 
                              or \g to the statement. If multiple-statement execution has 
                              been enabled, the string can contain several statements 
                              separated by semicolons.*/
 
   METHOD TableExist( cTable )  INLINE If( ! Empty( cTable ), ;
                                       Len( ::ListTables( D_LowerCase( cTable ) ) ) > 0, .F. )
                              /* verify is table exist, return logical value*/ 

   METHOD TableInitValues( cTable )
   
   METHOD TableStructure( cTable )  
   
   METHOD hUpdate( cTable, hValues, cWhere ) 
                             /*update specific rows into an existing table from a hash, ;
                               the index of hash shold be field name.*/
                             
   METHOD Update( cTable, aColumns, aValues, cWhere )
                             /*update specific row into an existing table.*/
                                 
ENDCLASS



CLASS TDolphinQry

   DATA aColumns,;    // query active columns (select)
        aTables,;     // query active tables
        aRow,;        // info currect record selected
        aStructure    // type of each field, a copy is here a copy inside each row
   DATA aOldRow       // Value copy
   DATA aRowOriginal  // Original data values (without changes, like return from mysql)

   DATA bBof,;        //codeblock to evaluate if the value is the first row
        bEof,;        //codeblock to evaluate if the value is the last row
        bOnFillArray,;//codeblock to evaluate while is filling array
        bOnChangePage,; //codeblock to evaluate when paginmation is activated and change page
        bOnLoadQuery,;  //codeblock to evaluate before load new Query
        bOnNewFilter   //codeblock to evaluate before set new query, 
                       //should return .t./.f. to call BuildQuery

   DATA cQuery,;        // copy of query that generated this object
        cWhere,;        // copy of WHERE command
        cGroup,;        // copy of GROUP BY command
        cHaving,;       // copy of HAVING command
        cOrder,;        // copy of OREDER BY command
        cLimit          // copy of LIMIT command

   DATA Cargo           // For programmer use
   
   DATA hOldRow                // Hash Last row selected
   DATA hResult                 
   DATA hRow                   // Hash current row selected

   DATA lBof                   // Begin of query, compatibility with dbf*/
   DATA lEof                   // End of Query, compatibility with dbf*/
   DATA lAppend
   DATA lPagination
   DATA lInverted              // Seek in inverted order

   DATA nFCount                // number of fields in the query
   DATA nRecCount              // number of rows in the current query
   DATA nRecNo                 // Current query row position
   DATA nQryId
   
   
   //Paginations datas
   DATA nCurrentPage           // Current page
   DATA nTotalRows             // Total row without limits
   DATA nPageStep              // total rows for page
   DATA nMaxPages              // Max pages avalaible in query
   DATA nCurrentLimit          // Current limit value
   
   DATA oServer
   DATA oRow


   METHOD New( cQuery, oServer )
   METHOD End()        INLINE ::oServer:CloseQuery( ::nQryId ), ::oRow := NIL

   METHOD Bof()        INLINE ::lBof  
   
   METHOD BuildDatas( cQuery ) 
   METHOD BuildDataWhere()     /* build a where with oldrow values */
   
   METHOD BuildQuery( aColumns, aTables, cWhere, cGroup, cHaving, ;
                      cOrder, cLimit, lWithRoll )   
                      
   METHOD CheckError( nError, cExtra )  INLINE ::oServer:CheckError( nError, cExtra )
                               /*Compatibility with CheckError from TDolphinSrv*/

   METHOD Delete( lAll )       /*Delete current record active*/
#ifdef __WIN__
   METHOD Export( nType, cFieldName, aColumns, aPictures )   ;
                INLINE TDolphinExport():New( nType, Self, cFieldName, aColumns, aPictures )
#endif __WIN__
   METHOD Eof()        INLINE ::lEof  
                      
   METHOD FCount()     INLINE    ::nFCount
                        /*returns the number of fields in the query, compatibility with dbf*/

   METHOD FieldLen( cnField )
   METHOD FieldDec( cnField )

   METHOD FieldName( nNum )     /*returns the name of the specified field as a character string.*/
   METHOD FieldPos( cFieldName )
                                /*returns the position of the specified field*/
   METHOD FieldGet( cnField )   /*returns the value of the specified field*/
   METHOD FieldType( cnField )  /*returns the field type of the specified field*/
   METHOD FieldMySqlType( cnField ) 
                                /*returns the MySql field type of the specified field*/
                                
   METHOD FieldPut( cnField, uValue )
                         /*Set the value of a field variable using the ordinal position of the field.
                                 returns the value assigned to the designated field.*/  
                                  
   METHOD FieldToNum( cnField ) HIDDEN                                                            

   METHOD FillArray( bOnFillArray, aColumns ) /*Fill and return a array with all query information*/
   METHOD FillHRow( lEmpty )          /*Fill (or not) and return a Hash with current record selected*/

   METHOD FirstPage()   INLINE ::PrevPage( ::nCurrentPage - 1 )
                                /*Go to first page in pagination*/
   METHOD Find( aValues, aFields, nStart, nEnd, lRefresh )                                
   
   METHOD GetBlankRow()                       
   METHOD GetRow( nRow )        /*Fill aRow and Hash with current data row selected*/
   METHOD GoTo( nRow ) INLINE   ::GetRow( nRow )
                                /*Goto specific Row (RecNo) and fill aRow/Hash*/
                                
   METHOD GetFieldsModified()   /*Return a Array with fields modified*/                             

   METHOD GetRowObj( nRow )     /*Return TDolphinRow Object*/
                                
   METHOD GoBottom()   INLINE   ::GetRow( ::nRecCount  ) 
                                /*Goto BOTTOM of Query and fill aRow/Hash*/
                                
   METHOD GoTop()      INLINE   ::GetRow( 1 )
                                /*Goto TOP of Query and fill aRow/Hash*/
                                
   METHOD IsEqual( nIdx )                                

   METHOD IsSingleTable() INLINE Len( ::aTables ) == 1  
   METHOD IsCommand()     INLINE ( ::IsSingleTable() .AND. Len( ::aColumns ) == 0 ) .OR. ;
                                 ( Len( ::aTables ) < 1 .AND. Len( ::aColumns ) >= 1 )


   METHOD LastPage() INLINE ::NextPage( ::nMaxPages - ::nCurrentPage )
                               /*Go to Last page in pagination*/

                                  
   METHOD LastRec()    INLINE     ::nRecCount
                   /*returns the number of rows in the current query, compatibility with dbf*/

   METHOD LoadQuery()          /*Load and fill current query*/
   METHOD LoadNextQuery( lBuildData ) 
                               /*Load next result with multiple statement*/
   
   METHOD Locate( aValues, aFields, nStart, nEnd, lSoft, lRefresh )

   METHOD MakePrimaryKeyWhere() 
                               /*Build Make Primary key if exist*/
   
   METHOD GoToPage( nPage ) INLINE If( nPage > ::nCurrentPage, ;
                            ::NextPage( nPage - ::nCurrentPage ), ;
                            If( nPage < ::nCurrentPage, ;
                            ::PrevPage( ::nCurrentPage - nPage ), ) )
       
   METHOD NextPage( nSkip )    /* Go to next page avalaible with pagination active */
   
   METHOD PrevPage( nSkip )    /* Go to previous page avalaible with pagination active */

   METHOD RecNo()      INLINE    ::nRecNo
                               /*returns the identity found at the position of the row pointer.*/
                               
   METHOD RecCount()   INLINE ::LastRec()
                               /*Compatibility with TMysql*/
                               
   METHOD Refresh( lBuildData )    
   
   METHOD Save()               /*Save current data*/
                 
   METHOD Seek( cSeek, cnField, nStart, nEnd, lSoft ) 
                               /*Move to the record having the specified 
                                 cSeek value, in selected field
                                 from nStart to nEnd with SoftSeek*/
                 
   METHOD SetData( nNum, uValue ) HIDDEN
                               /*set value into array or hash*/
   
   METHOD SetNewFilter( nType, cFilter, lRefresh )
   METHOD SetWhere( cWhere, lRefresh )   INLINE ::SetNewFilter( SET_WHERE, cWhere, lRefresh )
   METHOD SetGroup( cGroup, lRefresh )   INLINE ::SetNewFilter( SET_GROUP, cGroup, lRefresh )
   METHOD SetHaving( cHaving, lRefresh ) INLINE ::SetNewFilter( SET_HAVING, cHaving, lRefresh )
   METHOD SetOrder( cOrder, lRefresh )   INLINE ::SetNewFilter( SET_ORDER, cOrder, lRefresh )
   METHOD SetLimit( cLimit, lRefresh )   INLINE ::SetNewFilter( SET_LIMIT, cLimit, lRefresh )
   
   METHOD SetPages( nLimit )   /*Activate pagination and Set total rows by page*/
  
   METHOD Skip( nRecords )
   
   METHOD VerifyValue( nIdx, cField ) //HIDDEN
   
   METHOD Undo( cnField )

   METHOD Zap() INLINE ::Delete( .T. )
                               /*Delete all record in table*/
   
   ERROR HANDLER ONERROR()   

ENDCLASS


//Main class to manager exports
CLASS TDolphinExport

    DATA oQuery        /* Query object */
    DATA aColumns      /* Columns seelct to fill file */
    DATA aPictures     /* Columns's Picture */

    DATA cFileName     /* File name */
    DATA hFile
    DATA lAddHeader

    DATA nType         /* Export type */
    DATA bOnRow        /* codeblock to evaluate row by row */
    DATA bOnStart      /* codeblock to evaluate at the begin process */
    DATA bOnEnd        /* codeblock to evaluate at the end process */
    DATA oExport       /* Export Objet, is direftent by type */
    DATA oMain         /* Self */


    METHOD New( nType, oQuery, aColumns, aPictures  )

    METHOD Start() INLINE ::oExport:Export()
    METHOD Write( cLine, lNoCRLF )
    METHOD Close()  INLINE FClose( ::hFile )

    ERROR HANDLER ONERROR()


ENDCLASS

Autos eléctricos para todos

Cuando hablamos de convertir un vehículo a eléctrico es bueno conocer las diferentes opciones y equipamientos que existen en el mercado.

Los nuevos kit de conversión compactos con motores de flujo axial, generadores eléctricos para extender el rango de funcionamiento y la capacidad de usar un auto para alimentar herramientas eléctricas son ventajas de bajo costo que los especialistas en conversión de vehículos pueden usar.

aa Magnetic Autolibre

Nuevo Motor Axial de 50 Hp y solo 17 Kg enfriado por líquido.

Estos motores de Imanes permanentes son muy livianos y según el controlador de velocidad que se utilice se pueden alimentar con 48, 72, 96 o 120V DC. Ideales para proyectos donde sea necesario un sistema de bajo peso o un motor encapsulado. Apto para uso Marino, terrestre o aéreo.

Otro componente ahora disponible para los casos de vehículos que necesitan recorrer distancias mayores a la capacidad de las baterías instaladas es el generador extensor de rango. Los nuevos generadores a gasolina con control inteligente de carga directa y solo 21 Kg de peso

En vehículos eléctricos con capacidad de 50 a 120 Km por carga, aumentar la autonomía al doble representa una inversión de 3000 a 10.000 dólares en baterías de litio y hasta ahora no había ninguna otra solución de menor costo y fácil de instalar.

Gen 13

Foto, modelo 3 KWH.

Micro Generadores a gasolina con control inteligente (encendido y apagado automático) compatibles con cualquier carro eléctrico de 36 a 300V. El Gestor de VE en cada caso va a calcular el modelo necesario y sera quien suministre el equipo o el contacto directo para su adquisición.Y el tercer opcional de un VE convertido es la capacidad de servir como fuente temporal de energía:

Imagine que esta con su vehículo eléctrico y necesita utilizar una herramienta eléctrica o cualquier otro dispositivo pero no dispone de energía de red a su alcance, ya esta la solución.
Organización Autolibre ha diseñado un sistema de energía móvil para vehículos eléctricos (VE)  convertidos, que entrega de 110 a 240V AC para alimentar herramientas, dispositivos móviles, un campamento, etc.

Inverter power

Como ejemplo estas pueden ser las baterías de tracción del VE.

El sistema es modular y tiene una capacidad de 2000 a 8000 W de potencia y va a Bordo del vehículo.

Este modulo portable está diseñado para usarse en las conversiones de VE  y toma la energía del banco de baterías del vehículo pudiendo alimentar consumos durante dos a 10 horas, dependiendo de la capacidad del banco de baterías.

Esta solución convierte a los vehículos eléctricos en fuentes temporales de electricidad de red de onda pura (110 a 220V AC 50 a 60 H/s).  Esto es muy útil en tareas donde se necesiten herramientas eléctricas, equipos de soldadura, etc. y no hayan fuentes de energía eléctrica disponibles. La potencia se puede configurar de 1000 a 15000 W.

El funcionamiento es fácil de explicar, el sistema toma energía del banco de tracción (por ejemplo 96 V CC) y convierte esta energía en 110 o 220 V de AC de onda pura, que es apta para alimentar herramientas, electrodomésticos, PC, iluminación, etc.

La principal característica del sistema es que como usa el banco de baterías de tracción del vehículo se obtiene electricidad en forma silenciosa y sin requerir generadores de combustible.

Generador de VE

El sistema además es compatible con sistemas de energía solar que pueden estar también a bordo del vehículo o en ubicaciones fijas.

Fuente: AutoLibre

Abrir Aplicaciones Externas

2015-04-04_182346

 

2015-04-04_182326

2015-04-04_183249

 

/*
 * (c)2015 MigSoft Test Execute Functions
 *
 */

#include 'oohg.ch'

FUNCTION Main()
   Public nHdl := 0

   DEFINE WINDOW Form_1 ;
      AT 0, 0 ;
      WIDTH 600 ;
      HEIGHT 500 ;
      TITLE 'Open Applications by MigSoft' ;
      MAIN

      DEFINE STATUSBAR
         STATUSITEM 'OOHG Power !!!'
      END STATUSBAR

      @ 70, 20 BUTTON Button_1 ;
         WIDTH 180 THEMED ;
         CAPTION 'Google Chrome' ;
         ACTION AbreChrome()

      @ 100, 20 BUTTON Button_2 ;
         WIDTH 180 THEMED ;
         CAPTION 'ShellExecute' ;
         ACTION AbreProg()

      @ 130, 20 BUTTON Button_3 ;
         WIDTH 180 THEMED ;
         CAPTION 'Teclado ON' ;
         ACTION Teclado1(1)

      @ 160, 20 BUTTON Button_4 ;
         WIDTH 180 THEMED ;
         CAPTION 'Teclado OFF' ;
         ACTION Teclado1(0)

      @ 190, 20 BUTTON Button_5 ;
         WIDTH 180 THEMED ;
         CAPTION 'Calculadora ON' ;
         ACTION Calculadora(1)

      @ 220, 20 BUTTON Button_6 ;
         WIDTH 180 THEMED ;
         CAPTION 'Calculadora OFF' ;
         ACTION Calculadora(0)

      @ 250, 20 BUTTON Button_7 ;
         WIDTH 180 THEMED ;
         CAPTION 'Word' ;
         ACTION EnviaFile()

      ON KEY ESCAPE ACTION Form_1.Release()

   END WINDOW

   CENTER WINDOW Form_1
   ACTIVATE WINDOW Form_1

RETURN NIL


Function AbreChrome()

   oShell1 := CreateObject('WScript.Shell')
   oShell1:Exec ('C:\Program Files (x86)\Google\Chrome\' + ;
      'Application\chrome.exe -url http:www.mig2soft.com')

Return Nil

Function AbreProg()

   cFileName := 'C:\Program Files (x86)\Google\' + ;
                'Chrome\Application\chrome.exe'
   cParams   := '-url http:www.mig2soft.com'
   cAction   := 'open'   // 'play' , 'properties', 'PrintTo'
   ShellExecute( 0, cAction, cFileName, cParams, '', 1 )

Return Nil

Function EnviaFile()     // Change path and file
    nRes := ShellExecute( 0, 'open', ;
            'c:\Users\Usuario1\Documents\Balance de situacion.rtf')
    If nRes < 33
       MsgInfo('Error en conexión')
    Endif
Return Nil


#define WM_CLOSE                        0x0010

Function Teclado1( nOp )
   LOCAL cKeyboard := GetEnv( 'windir' ) + '\system32\osk.exe'

   If nOp = 1
      ShellExecute( 0, 'open', cKeyboard, , , 1 )
   Endif

   If nOp = 0
      //SendMessage( GetForegroundWindow(), WM_CLOSE )
      SendMessage( FindWindowEx( Nil,Nil,Nil, ;
            'On-Screen Keyboard' ) , WM_CLOSE )
      SendMessage( FindWindowEx( Nil,Nil,Nil, ;
            'Teclado en Pantalla' ), WM_CLOSE )

   Endif

Return Nil

Function Calculadora( nOp )
   If nOp = 1
      ShellExecute( 0, 'open', 'calc' )
   Endif

   If nOp = 0
      SendMessage( FindWindowEx( Nil,Nil,Nil, ;
                  'Calculator' ), WM_CLOSE )
      SendMessage( FindWindowEx( Nil,Nil,Nil, ;
                 'Calculadora' ), WM_CLOSE )
   Endif

Return Nil