Clipper On Line • Ver Tópico - *** ADOxb - BIblioteca de funções de Acesso SQL ***
Página 1 de 6

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 16 Out 2007 10:12
por rochinha
Amigos,

Eis alguns comandos existentes no arquivo .CH que deve fazer parte da chamada INCLUDE de seus .PRGs de acesso as tabelas usando ADO.

#command ADO CONNECT => ADOCONNECT( , )
#command ADO DISCONNECT => ADODISCONNECT()
#command ADO APPEND BLANK => ADOAPPEND()
#command ADO EDIT => ADOEDIT()
#command ADO COMMIT => ADOCOMMIT( )
#command ADO SKIP => ADOSKIP( 1 )
#command ADO SKIP => ADOSKIP( )
#command ADO DELETE => ADODELETE()
#command ADO REPLACE f1 WITH v1 => ADOREPLACE( f1, v1 )
#command ADO GOTOP => ADOGOTOP()
#command ADO GOBOTTOM => ADOGOBOTTOM()
#command ADO SET FILTER TO => ADOSETFILTER()
#command ADO SET FILTER TO => ADOSETFILTER( )
#command ADO SAVE < (CfILE)> => ADOSAVE( < (CfILE)> )
#command ADO EXECUTE < *Sql*> => ADOEXECUTE( < (Sql)> )
#command ADO LOCATE => ADOLOCATE( )
#command ADO REGLOCK => ADOREGLOCK()
#command ADO CLOSE => ADOCLOSE()
#command ADO CLOSE ALL => ADOCLOSEALL()
#command ADO USE => ADOUSE()
#command ADO USE < (StrDatabase)> [SHARED] => ADOUSE( < (StrDatabase)>, [< .shared.>] )
#command ADO SORT ON [< (cF)>][< (x)>]=> ADOSORT( [< (cF)>][, < (x)>] )
#command ADO SELECT < (cRecordSet)> => ADOSELECT( < (cRecordSet)> )

O uso é muito simples, bastando incluir a chamada ao arquivo no inicio de seu .PRG e construir o restante do codigo com os comandos existentes na mesma, exemplo:

ADOMDB.PRG
..
ADO APPEND BLANK
ADO REPLACE campoA WITH variavelA
ADO REPLACE campoB WITH variavelB
ADO COMMIT
..

Tenha em mente que ao colocar este cabeçalho em um .PRG os comandos devem ser apenas para uso com a biblioteca.

De forma avançada pode ser usado MySQL, MDB, MSSQL, Firebird em conjunto com tabelas .DBF de forma a importar ou exportar dados, o que será o seu uso mais frequente.

O arquivo completo encontra-se no endereço http://www.5volution.com.br/downloads/forum/adoxb.txt bastando selecionar o conteudo, copiar e salvar como adoxb.ch.

Até mais…

MensagemEnviado: 16 Out 2007 10:15
por rochinha
ADOXb - Biblioteca de acesso a diversos BDs

Estas são informações relativas a minha LIB que tem por objetivo aliviar o problema de acessar varios tipos de bases de dados diferentes. Tornando-se uma ferramenta de apoio ao programador.

A biblioteca constitue de um set de comandos e funções padronizado para facilitar a programação, feita em linguagem acessivel e com comandos fáceis de memorizar.

Nos testes efetivados até agora consegui:

- Incluir registros
- Excluir registros
- Deletar registros
- Fazer filtragem estilo SET FILTER
- Fazer buscas estilo LOCATE
- Abrir várias áreas simultaneamente estilo SELECT

Nos testes feitos com DBs já consegui acessar tabelas no MySQL, Access, XML, Firebird e irei fazer testes de acesso a tabelas em MS-SQL Express 2005.

Só para se ter uma idéia do que estou falando é que acho ser possivel abrir estes tipos de arquivos ao mesmo tempo e trabalhar com os mesmos e suas tabelas também.

Dimensionei as áreas para 50 como teste, isto quer dizer que poderemos ter 50 SELECTs abertas.

O acesso poderá ser local ou remoto dependendo do DB utilizado e que suporte TCP-IP.

Veja um exemplo de código:

Function Teste()
StrDatabase := [adomysql]
StrServer := [mysql4.shoppmarketing.com]
StrPort := 3306
StrUserID := [adomysql_user]
StrUserPWD := [adomysql_pass]
StrDriver := "MySQL ODBC 3.51 Driver"

StrConnection := "driver={" + StrDriver +"};database=" + StrDatabase + ;
";server=" + StrServer + ;
";uid=" + StrUserID + ;
";pwd=" + StrUserPWD + ;
";option=35"

MsgRun( "Conectando…" )

ADO CONNECT StrConnection

// Abre as tabelas existentes na base
ADO USE clientes
ADO USE siglas

// Verifica se ja possuem dados
ADO SELECT clientes
nRegistros := ADORecCount()
if nRegistros = 0
ADO APPEND BLANK
ADO REPLACE nome WITH "ROCHINHA"
ADO REPLACE email WITH "EMAIL@ISP.COM.BR"
ADO COMMIT
endif

ADO SELECT siglas
nRegistros := ADORecCount()
if nRegistros = 0
ADO APPEND BLANK
ADO REPLACE uf WITH "SP"
ADO REPLACE estado WITH "SAO PAULO"
ADO COMMIT
ADO APPEND BLANK
ADO REPLACE uf WITH "RJ"
ADO REPLACE estado WITH "RIO DE JANEIRO"
ADO COMMIT
endif

MsgRun( "Executando…" )
ADO SELECT clientes
ADO GOTOP

MsgRun( "Executando SET FILTER TO nome like '*tete*'…" )
ADO SET FILTER TO "nome like '*tete*'"
if ADOEof()
? 'Nada foi filtrado'
ADO SET FILTER TO
ADO GOTOP
endif
Browse( oRs )
ADO SET FILTER TO

MsgRun( "Executando LOCATE nome like 'TESTES'…" )
ADO LOCATE "nome like 'TESTES*'"
if ADOEof()
? 'Nada foi encontrado'
ADO GOTOP
endif
Browse( oRs )

ADO CLOSE
return .t.


No momento estou implementando os comandos SORT que permitirão colocar uma visualização em ordem que o usuário especificar.

Logo estarei disponibilizando esta biblioteca para testes.

Bom, até mais…

MensagemEnviado: 16 Out 2007 10:20
por rochinha
Amiguinhos,

Para iniciar o uso com as funções é necessário antes conhecer o cabeçalho que pode ajudar a COMMANDar as instruções de acesso a dados:

Codigo completo de ADOxb.CH
**************************************************************************************
*
* Cursor Location
*
* adUseServer           2 Atua no lado servidor
* adUseClient           3 Atua no lado cliente
*
* Cursor Type
*
* adOpenForwardOnly     0 O cursor so navega para frente. Bom para listar dados
* adOpenKeyset          1 Nao permite ver os registro adicionados e eliminados
* adOpenDynamic         2 Aceita todas operacoes do utilizador e dos outros
* adOpenStatic          3 Serve apenas para procurar dados ou gerar relatorios
*
* Lock Type Enum - Contantes de Seguranca
*
* adLockReadOnly        1 Apenas pode ler os registros
* adLockPessimistic     2 O fornecedor dos dados fecha o registro apos edicao
* adLockOptimistic      3 O fornecedor dos dados fecha o registro apos chamar o update
* adLockBatchOptimistic 4 O mesmo que Optmistic mas para sequencia de comandos
*
* AllowNumsEnum
*
* adIndexNullsAllow     0
* adIndexNullsDisallow  1
* adIndexNullsIgnore    2
* adIndexNullsIgnoreAny 4
*
**************************************************************************************

#command ADO CONNECT <StrDriver> [<disconected:DISCONECTED>] => ADOCONNECT( <StrDriver>, [<.disconected.>] )
#command ADO DISCONNECT             => ADODISCONNECT()
#command ADO APPEND BLANK           => ADOAPPEND()
#command ADO EDIT                   => ADOEDIT()
#command ADO COMMIT [<save:SAVE>]   => ADOCOMMIT( [<.save.>] )
#command ADO SKIP                   => ADOSKIP( 1 )
#command ADO SKIP <num>             => ADOSKIP( <num> )
#command ADO DELETE                 => ADODELETE()
#command ADO REPLACE <f1> WITH <v1> => ADOREPLACE( <(f1)>, <v1> )
#command ADO GOTOP                  => ADOGOTOP()
#command ADO GOBOTTOM               => ADOGOBOTTOM()
#command ADO SET FILTER TO          => ADOSETFILTER()
#command ADO SET FILTER TO <xpr>    => ADOSETFILTER( <xpr> )
#command ADO SAVE <(CfILE)>         => ADOSAVE( <(CfILE)> )
#command ADO EXECUTE <*Sql*>        => ADOEXECUTE( <(Sql)> )
#command ADO LOCATE <xpr>           => ADOLOCATE( <xpr> )
#command ADO REGLOCK                => ADOREGLOCK()
#command ADO CLOSE                  => ADOCLOSE()
#command ADO CLOSE ALL              => ADOCLOSEALL()
#command ADO USE                    => ADOUSE()
#command ADO USE <(StrDatabase)> [<shared:SHARED>] => ADOUSE( <(StrDatabase)>, [<.shared.>] )
#command ADO SORT ON [<(cF)>][<(x)>]=> ADOSORT( [<(cF)>][, <(x)>] )
#command ADO SELECT <(cRecordSet)>  => ADOSELECT( <(cRecordSet)> )

#xcommand ADO SQL DELETE <*cSQL*>   => ADOEXECUTE( 'DELETE '+ <(cSQL)> )
#xcommand ADO SQL INSERT <*cSQL*>   => ADOEXECUTE( 'INSERT '+ <(cSQL)> )
#xcommand ADO SQL UPDATE <*cSQL*>   => ADOEXECUTE( 'UPDATE '+ <(cSQL)> )
#xcommand ADO SQL ALTER  <*cSQL*>   => ADOEXECUTE( 'ALTER ' + <(cSQL)> )
#xcommand ADO SQL CREATE <*cSQL*>   => ADOEXECUTE( 'CREATE '+ <(cSQL)> )
#xcommand ADO SQL DROP   <*cSQL*>   => ADOEXECUTE( 'DROP '  + <(cSQL)> )
#xcommand ADO SQL RENAME <*cSQL*>   => ADOEXECUTE( 'RENAME '+ <(cSQL)> )
#xcommand ADO SQL UPDATE <*cSQL*>   => ADOEXECUTE( 'UPDATE '+ <(cSQL)> )
#xcommand ADO SQL GRANT  <*cSQL*>   => ADOEXECUTE( 'GRANT ' + <(cSQL)> )
#xcommand ADO SQL REVOKE <*cSQL*>   => ADOEXECUTE( 'REVOKE '+ <(cSQL)> )

/*---- Lock Type Enum ----*/
#define adLockReadOnly        1
#define adLockPessimistic     2
#define adLockOptimistic      3
#define adLockBatchOptimistic 4

/*---- AllowNumsEnum ----*/
#define adIndexNullsAllow     0
#define adIndexNullsDisallow  1
#define adIndexNullsIgnore    2
#define adIndexNullsIgnoreAny 4

/*---- CursorTypeEnum Values ----*/
#define adOpenForwardOnly 0
#define adOpenKeyset 1
#define adOpenDynamic 2
#define adOpenStatic 3

/*---- LockTypeEnum Values ----*/
#define adLockReadOnly 1
#define adLockPessimistic 2
#define adLockOptimistic 3
#define adLockBatchOptimistic 4

/*---- CursorLocationEnum Values ----*/
#define adUseServer 2
#define adUseClient 3

/*---- DataTypeEnum Values ----*/
#define adEmpty 0
#define adTinyInt 16
#define adSmallInt 2
#define adInteger 3
#define adBigInt 20
#define adUnsignedTinyInt 17
#define adUnsignedSmallInt 18
#define adUnsignedInt 19
#define adUnsignedBigInt 21
#define adSingle 4
#define adDouble 5
#define adCurrency 6
#define adDecimal 14
#define adNumeric 131
#define adBoolean 11
#define adError 10
#define adUserDefined 132
#define adVariant 12
#define adIDispatch 9
#define adIUnknown 13
#define adGUID 72
#define adDate 7
#define adDBDate 133
#define adDBTime 134
#define adDBTimeStamp 135
#define adBSTR 8
#define adChar 129
#define adVarChar 200
#define adLongVarChar 201
#define adWChar 130
#define adVarWChar 202
#define adLongVarWChar 203
#define adBinary 128
#define adVarBinary 204
#define adLongVarBinary 205
#define adChapter 136
#define adFileTime 64
#define adPropVariant 138
#define adVarNumeric 139
#define adArray &H2000

/*---- GetRowsOptionEnum Values ----*/
#define adGetRowsRest -1

/*---- PositionEnum Values ----*/
#define adPosUnknown -1
#define adPosBOF -2
#define adPosEOF -3

/*---- BookmarkEnum Values ----*/
#define adBookmarkCurrent 0
#define adBookmarkFirst 1
#define adBookmarkLast 2

/*---- MarshalOptionsEnum Values ----*/
#define adMarshalAll 0
#define adMarshalModifiedOnly 1

/*---- AffectEnum Values ----*/
#define adAffectCurrent 1
#define adAffectGroup 2
#define adAffectAllChapters 4

/*---- ResyncEnum Values ----*/
#define adResyncUnderlyingValues 1
#define adResyncAllValues 2

/*---- CompareEnum Values ----*/
#define adCompareLessThan 0
#define adCompareEqual 1
#define adCompareGreaterThan 2
#define adCompareNotEqual 3
#define adCompareNotComparable 4

/*---- FilterGroupEnum Values ----*/
#define adFilterNone 0
#define adFilterPendingRecords 1
#define adFilterAffectedRecords 2
#define adFilterFetchedRecords 3
#define adFilterConflictingRecords 5

/*---- SearchDirectionEnum Values ----*/
#define adSearchForward 1
#define adSearchBackward -1

/*---- PersistFormatEnum Values ----*/
#define adPersistADTG 0
#define adPersistXML 1

/*---- StringFormatEnum Values ----*/
#define adClipString 2

/*---- ConnectPromptEnum Values ----*/
#define adPromptAlways 1
#define adPromptComplete 2
#define adPromptCompleteRequired 3
#define adPromptNever 4

/*---- ConnectModeEnum Values ----*/
#define adModeUnknown 0
#define adModeRead 1
#define adModeWrite 2
#define adModeReadWrite 3
#define adModeShareDenyRead 4
#define adModeShareDenyWrite 8
#define adModeShareExclusive 12
#define adModeShareDenyNone 16

/*---- EventReasonEnum Values ----*/
#define adRsnAddNew 1
#define adRsnDelete 2
#define adRsnUpdate 3
#define adRsnUndoUpdate 4
#define adRsnUndoAddNew 5
#define adRsnUndoDelete 6
#define adRsnRequery 7
#define adRsnResynch 8
#define adRsnClose 9
#define adRsnMove 10
#define adRsnFirstChange 11
#define adRsnMoveFirst 12
#define adRsnMoveNext 13
#define adRsnMovePrevious 14
#define adRsnMoveLast 15

/*---- SchemaEnum Values ----*/
#define adSchemaProviderSpecific -1
#define adSchemaAsserts 0
#define adSchemaCatalogs 1
#define adSchemaCharacterSets 2
#define adSchemaCollations 3
#define adSchemaColumns 4
#define adSchemaCheckConstraints 5
#define adSchemaConstraintColumnUsage 6
#define adSchemaConstraintTableUsage 7
#define adSchemaKeyColumnUsage 8
#define adSchemaReferentialConstraints 9
#define adSchemaTableConstraints 10
#define adSchemaColumnsDomainUsage 11
#define adSchemaIndexes 12
#define adSchemaColumnPrivileges 13
#define adSchemaTablePrivileges 14
#define adSchemaUsagePrivileges 15
#define adSchemaProcedures 16
#define adSchemaSchemata 17
#define adSchemaSQLLanguages 18
#define adSchemaStatistics 19
#define adSchemaTables 20
#define adSchemaTranslations 21
#define adSchemaProviderTypes 22
#define adSchemaViews 23
#define adSchemaViewColumnUsage 24
#define adSchemaViewTableUsage 25
#define adSchemaProcedureParameters 26
#define adSchemaForeignKeys 27
#define adSchemaPrimaryKeys 28
#define adSchemaProcedureColumns 29
#define adSchemaDBInfoKeywords 30
#define adSchemaDBInfoLiterals 31
#define adSchemaCubes 32
#define adSchemaDimensions 33
#define adSchemaHierarchies 34
#define adSchemaLevels 35
#define adSchemaMeasures 36
#define adSchemaProperties 37
#define adSchemaMembers 38
#define adSchemaTrustees 39

/*---- FieldStatusEnum Values ----*/
#define adFieldOK 0
#define adFieldCantConvertValue 2
#define adFieldIsNull 3
#define adFieldTruncated 4
#define adFieldSignMismatch 5
#define adFieldDataOverflow 6
#define adFieldCantCreate 7
#define adFieldUnavailable 8
#define adFieldPermissionDenied 9
#define adFieldIntegrityViolation 10
#define adFieldSchemaViolation 11
#define adFieldBadStatus 12
#define adFieldDefault 13
#define adFieldIgnore 15
#define adFieldDoesNotExist 16
#define adFieldInvalidURL 17
#define adFieldResourceLocked 18
#define adFieldResourceExists 19
#define adFieldCannotComplete 20
#define adFieldVolumeNotFound 21
#define adFieldOutOfSpace 22
#define adFieldCannotDeleteSource 23
#define adFieldReadOnly 24
#define adFieldResourceOutOfScope 25
#define adFieldAlreadyExists 26
#define adFieldPendingInsert &H10000
#define adFieldPendingDelete &H20000
#define adFieldPendingChange &H40000
#define adFieldPendingUnknown &H80000
#define adFieldPendingUnknownDelete &H100000

/*---- SeekEnum Values ----*/
#define adSeekFirstEQ &H1
#define adSeekLastEQ &H2
#define adSeekAfterEQ &H4
#define adSeekAfter &H8
#define adSeekBeforeEQ &H10
#define adSeekBefore &H20

/*---- ADCPROP_UPDATECRITERIA_ENUM Values ----*/
#define adCriteriaKey 0
#define adCriteriaAllCols 1
#define adCriteriaUpdCols 2
#define adCriteriaTimeStamp 3

/*---- ADCPROP_ASYNCTHREADPRIORITY_ENUM Values ----*/
#define adPriorityLowest 1
#define adPriorityBelowNormal 2
#define adPriorityNormal 3
#define adPriorityAboveNormal 4
#define adPriorityHighest 5

/*---- ADCPROP_AUTORECALC_ENUM Values ----*/
#define adRecalcUpFront 0
#define adRecalcAlways 1

/*---- ADCPROP_UPDATERESYNC_ENUM Values ----*/

/*---- ADCPROP_UPDATERESYNC_ENUM Values ----*/

/*---- MoveRecordOptionsEnum Values ----*/
#define adMoveUnspecified -1
#define adMoveOverWrite 1
#define adMoveDontUpdateLinks 2
#define adMoveAllowEmulation 4

/*---- CopyRecordOptionsEnum Values ----*/
#define adCopyUnspecified -1
#define adCopyOverWrite 1
#define adCopyAllowEmulation 4
#define adCopyNonRecursive 2

/*---- StreamTypeEnum Values ----*/
#define adTypeBinary 1
#define adTypeText 2

/*---- LineSeparatorEnum Values ----*/
#define adLF 10
#define adCR 13
#define adCRLF -1

/*---- StreamOpenOptionsEnum Values ----*/
#define adOpenStreamUnspecified -1
#define adOpenStreamAsync 1
#define adOpenStreamFromRecord 4

/*---- StreamWriteEnum Values ----*/
#define adWriteChar 0
#define adWriteLine 1

/*---- SaveOptionsEnum Values ----*/
#define adSaveCreateNotExist 1
#define adSaveCreateOverWrite 2

/*---- FieldEnum Values ----*/
#define adDefaultStream -1
#define adRecordURL -2

/*---- StreamReadEnum Values ----*/
#define adReadAll -1
#define adReadLine -2

/*---- RecordTypeEnum Values ----*/
#define adSimpleRecord 0
#define adCollectionRecord 1
#define adStructDoc 2

MensagemEnviado: 16 Out 2007 11:28
por rochinha
Amiguinhos,

O coração deste tópico esta liberado para juntar-se aos exemplos que se seguem e vamos enriquecer este topico afim de conseguirmos tirar o maximo do conjunto de funções:

ADOxb.prg
****************************************************************************************
*
* CursorType
*
* adOpenForwardOnly     0 O cursor so navega para frente. Bom para listar dados
* adOpenKeyset          1 Nao permite ver os registro adicionados e eliminados
* adOpenDynamic         2 Aceita todas operacoes do utilizador e dos outros
* adOpenStatic          3 Serve apenas para procurar dados ou gerar relatorios
*
* LockTypeEnum - Contantes de Seguranca
*
* adLockReadOnly        1 Apenas pode ler os registros
* adLockPessimistic     2 O fornecedor dos dados fecha o registro apos edicao
* adLockOptimistic      3 O fornecedor dos dados fecha o registro apos chamar o update
* adLockBatchOptimistic 4 O mesmo que Optmistic mas para sequencia de comandos
*
* SortOrdEnum - Contantes de Ordenacao
*
* adSortAscending       1 Ordem ascendente
* adSortDescending      2 Ordem descendente
*
****************************************************************************************

#include "adoxb.ch"
#ifndef _ADO_xHarbour_
        #define _ADO_Harbour_
#endif

*
*---------------------------------------------------------
Function ADOSetRDD( cRDDName )
   public cADORDD := iif( cRDDName=NIL, "DBF", cRDDName )
   PUBLIC aRecordSet, oRecordSet, nConnection, nRecordSet, aIndexOrder, nIndexOrder, ;
          StrConnection, aADOConection, oADOConection, oADOErrDescription, oADOIndex, ;
          oADOCatalog, oADOTable, oADOStream
   nConnection        := 1
   aADOConection      := {}
   oADOConection      := Array(10)
   return cADORDD

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOConnect( StrDriver )
   //PUBLIC aRecordSet, oRecordSet, nRecordSet, aIndexOrder, nIndexOrder, StrConnection, oADOConection, oADOErrDescription, oADOIndex, oADOCatalog, oADOTable
   aRecordSet         := {}
   oRecordSet         := Array(50)
   oADOIndex          := Array(10)
   nRecordSet         := 0
   aIndexOrder        := {}
   nIndexOrder        := 1
   StrConnection      := StrDriver
   AADD( aADOConection, StrDriver ) // Controla numero de conexoes
   nConnection        := len( aADOConection )
   oADOConection[nConnection] := TOLEAUTO():New("ADODB.connection")
   oADOStream         := TOLEAUTO():New("ADODB.Stream")
   oADOErrDescription := TOLEAUTO():New("ADODB.Err")
   oADOIndex          := TOLEAUTO():New("ADOX.Index")
   oADOCatalog        := TOLEAUTO():New("ADOX.Catalog")
   oADOConection[nConnection]:CommandTimeOut    := 200
   oADOConection[nConnection]:ConnectionTimeOut := 10
   oADOConection[nConnection]:CursorLocation    := adUseClient
   oADOConection[nConnection]:Mode              := adModeShareDenyNone // adModeRead 1, adModeWrite 2, adModeReadWrite 3
   oADOConection[nConnection]:Open( StrConnection )
   return 'connected'
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADODBCREATE( cDatabase )
   oADOCreateCatalog := TOLEAUTO():New("ADOX.Catalog")
   StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + cDatabase
   oADOCreateCatalog:Create( StrConnection )
   return .t.

Function ADOCREATE( cTable, aFields )
   //local oADOTable := TOLEAUTO():New("ADOX.Table")
   //oADOCatalog:ActiveConnection := StrConnection
   //oADOTable:Name := cTable
   //for i = 1 to len( aFields )
   //    oADOTable:Columns:Append( aFields[i][1], GetFieldType(aFields[i][2]), aFields[i][3] )
   //next
   //oADOCatalog:Tables:Append( oADOTable )
   //oADOTable:Close()
   //oADOTable:End()
   //
   //oADOCreateCatalog := TOLEAUTO():New("ADOX.Catalog")
   //oADOCreateTable   := TOLEAUTO():New("ADOX.Table")
   //oADOCreateCatalog:Create( StrConnection )
   //oADOCreateTable:Name := cTable
   //for i = 1 to len( aFields )
   //    oADOCreateTable:Columns:Append( aFields[i][1], GetFieldType(aFields[i][2]) ) //, aFields[i][3] )
   //next
   //oADOCreateCatalog:Tables:Append( cTable )
   //return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOIndex( cTable, cIDXField, cIDXName, cIDXAscend )
   local adSortAscending := 1, adSortDescending := 2
   local oADOTable := TOLEAUTO():New("ADOX.Table")
   cIDXAscend := iif( cIDXAscend = nil, .t., cIDXAscend )
   if .not. ADOFILE( "INDEXES" )
      oADOCatalog:ActiveConnection := StrConnection
      oADOTable:Name := "INDEXES"
      oADOTable:Columns:Append( "NumField", adInteger, 20 )
      oADOTable:Columns:Append( "TextField", adVarWChar, 20 )
      oADOCatalog:Tables:Append( oADOTable )
   endif
   AADD( aIndexOrder, cTable )
   nIndexOrder        := len( aIndexOrder )
   oADOIndex[nIndexOrder] := TOLEAUTO():New("ADOX.Index")
   oADOIndex[nIndexOrder]:Name       := cIDXName
   oADOIndex[nIndexOrder]:Columns:Append( cIDXField )
   oADOIndex[nIndexOrder]:Columns( cIDXField ):SortOrder = iif( cIDXAscend, adSortAscending, adSortDescending )
   //oADOIndex[nIndexOrder]:PrimaryKey := .t.
   //oADOIndex[nIndexOrder]:Unique     := .t.
   oADOIndex[nIndexOrder]:IndexNulls := adIndexNullsAllow
   // Adciona o indice criado ao catalogo
   //oADOCatalog:Tables( cTable ) //:Indexes:Append( oADOIndex[nIndexOrder] )
   oADOTable:Indexes:Append( oADOIndex )
   oADOCatalog:Tables:Append( oADOTable )
   oADOTable:Close()
   oADOTable:End()
   return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOUse( cDatabase, lShared )
   local oError
   if cADORDD = "XML"
      cDatabase := cDatabase + ".xml"
   endif
   if cADORDD = "XLS"
      cDatabase := "[" + cDatabase + "$]"
   endif
   if cDatabase = NIL
      oRecordSet[nRecordSet]:Close()
      oRecordSet[nRecordSet]:End()
   else
      AADD( aRecordSet, cDatabase )
      cRecordSet := cDatabase
      nRecordSet := len( aRecordSet )
      oRecordSet[nRecordSet] := TOleAuto():New( "ADODB.Recordset" )
      if cADORDD = "XML"
         oRecordSet[nRecordSet]:Open( cDatabase, StrConnection, 1, 3 )
      else
         oRecordSet[nRecordSet]:CacheSize      := 50
         oRecordSet[nRecordSet]:CursorLocation := adUseClient
         if lShared = .t.
            oRecordSet[nRecordSet]:CursorType  := adOpenDynamic
            oRecordSet[nRecordSet]:LockType    := adLockOptimistic
         else
            oRecordSet[nRecordSet]:CursorType  := adOpenStatic
            oRecordSet[nRecordSet]:LockType    := adLockPessimistic
         endif
         oRecordSet[nRecordSet]:Open( "Select * from " + cDatabase, StrConnection, iif(lShared=.t.,3,1), 3 )
      endif
      ADOGOTOP() // oRecordSet[nRecordSet]:MoveFirst()
   endif
   * CursorType
   *
   * adOpenForwardOnly     0 O cursor so navega para frente. Bom para listar dados
   * adOpenKeyset          1 Nao permite ver os registro adicionados e eliminados
   * adOpenDynamic         2 Aceita todas operacoes do utilizador e dos outros
   * adOpenStatic          3 Serve apenas para procurar dados ou gerar relatorios
   *
   * LockTypeEnum - Contantes de Seguranca
   *
   * adLockReadOnly        1 Apenas pode ler os registros
   * adLockPessimistic     2 O fornecedor dos dados fecha o registro apos edicao
   * adLockOptimistic      3 O fornecedor dos dados fecha o registro apos chamar o update
   * adLockBatchOptimistic 4 O mesmo que Optmistic mas para sequencia de comandos
   return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOConnectRemote( StrDSN, StrServer )
   PUBLIC aRecordSet, oRecordSet, nRecordSet, aIndexOrder, nIndexOrder, StrConnection, oADOConection, oADOErrDescription, oADOIndex, oADOCatalog
   aRecordSet    := {}
   oRecordSet    := Array(50)
   oADOIndex     := Array(10)
   nRecordSet    := 0
   aIndexOrder   := {}
   nIndexOrder   := 1
   StrConnection := StrDriver
   oADOConection := TOLEAUTO():New("RDS.DataControl")
   oADOConection:ExecuteOptions := adcExecAsync
   oADOConection:Connect        := "DSN=" + StrDriver
   oADOConection:Server         := StrServer
   oADOConection:Refresh()
   return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
Function ADOConnected()
   if !(valtype(oADOConection[nConnection]) = "O")
      return .f. // Nao foi definido o Objecto
   endif
   if valtype(oADOConection) = "L"
      return .f. // Se ja existe a variavel mas nao foi definida como Objeto
   endif
   cADOConectionState := oADOConection[nConnection]:State
   return iif( cADOConectionState=1, .t., .f. )

*
*---------------------------------------------------------
Function MsgAlert( cMsg )
   Alert( cMsg )
   return .t.

*
*---------------------------------------------------------
Function ADOSetDriver( StrDatabase, StrSenha, StrUsuario, StrServer, StrPort )
   public cADORDD := iif( cRDDName=NIL, "DBASE", cRDDName )
   StrConnection := ""
   StrDriver     := ADORDDDefault()
   if StrDriver = "DBASE"
      StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";Extended Properties=dBASE IV;"
   endif
   if StrDriver = "ACCESS" // ADOMDB
      StrConnection := "Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";"
   endif
   if StrDriver = "FIREBIRD" // ADOGDB
      StrConnection := "DRIVER=Firebird/InterBase(r) driver; UID="+StrSenha+"; PWD="+StrUsuario+"; DBNAME="+StrDatabase
   endif
   if StrDriver = "MYSQL" // ADOMySQL
      StrConnection := "driver={MySQL ODBC 3.51 Driver};database=" + StrDatabase + ;
                       ";server=" + StrServer + ;
                       ";uid=" + StrUsuario + ;
                       ";pwd=" + StrSenha + ;
                       ";option=35"
   endif
   if StrDriver = "PARADOX" // ADOPX
      StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";Extended Properties=Paradox 5.x;"
   endif
   if StrDriver = "SQL"
      StrConnection := "Provider=MSDASQL;Data Source=SQLExpress;User ID=Administrador;Password=konectiva;"
   endif
    if ADORDDDefault() = "XMLDB" // ADOXML
       StrConnection := "Provider=MSPersist"
    endif
    if ADORDDDefault() = "XML" // ADOXML
       StrConnection := "Provider=MSDAOSP;Data Source=MSXML2.DSOControl.2.6"
    endif
   if StrDriver = "XLS" // ADOXLS
      StrConnection := [Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\adoxls.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1"]
   endif
   if StrDriver = "REMOTE" // ADORDS
      StrConnection := "Provider=MS Remote;Remote Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";Remote Server=" + StrServer
   endif
   return StrConnection

*
*---------------------------------------------------------
Function ADORDDDefault(qADORDD)
   default cADORDD := "Nenhum RDD especificado."
   //if (qADORDD = nil)
   //   cADORDD := qADORDD
   //endif
   return cADORDD

*
*---------------------------------------------------------
Function ADOFile( cFile )
   if cADORDD = "XML" .or. cADORDD = "XLS"
      return file( cFile )
   else
      oADOCatalog := oADOConection[nConnection]:OpenSchema(adSchemaTables)
      do while .not. oADOCatalog:EOF()
         if upper(alltrim(oADOCatalog:Fields( "TABLE_NAME" ):Value)) = upper(alltrim(cFile))
            return .t.
         endif
         oADOCatalog:MoveNext()
      enddo
   endif
   return .f.

*
*---------------------------------------------------------
Function ADOAlias()
   if nRecordSet < 1
      return ""
   else
      return aRecordSet[nRecordSet]
   endif

*
*---------------------------------------------------------
Function ADOFCount()
   if nRecordSet < 1
      return ""
   else
      return aRecordSet[nRecordSet]:Fields:Count()
   endif

*
*---------------------------------------------------------
Function ADOBEGINTRANSACTION()
   oADOConection[nConnection]:BeginTrans()
   return .t.

*
*---------------------------------------------------------
Function ADOCOMMITTRANSACTION()
   oADOConection[nConnection]:CommitTrans()
   return .t.

*
*---------------------------------------------------------
Function GetFieldType(FieldType)
   do Case
      Case FieldType = "C"
           return adVarWChar
      Case FieldType = "N"
           return adInteger
      Case FieldType = "M"
           return adText
      Case FieldType = "L"
           return adBoolean
      Case FieldType = "D"
           return adDate
   Endcase

*
*---------------------------------------------------------
Function ADOSetOrder( nIDXOrder )
   oRecordSet[nRecordSet]:Index = oADOIndex[nIDXOrder]:Name
   return .t.

*
*---------------------------------------------------------
Function ADODISConnect()
   oADOConection[nConnection]:Close()
   oADOErrDescription:Close()
   oADOIndex:Close()
   oADOCatalog:Close()
   oADOConection[nConnection]:End()
   oADOErrDescription:End()
   oADOIndex:End()
   oADOCatalog:End()
   return .t.

*
*---------------------------------------------------------
Function ADOAppend()
   oRecordSet[nRecordSet]:AddNew()
   return .t.

*
*---------------------------------------------------------
Function ADOEdit()
   oRecordSet[nRecordSet]:Edit()
   return .t.

*
*---------------------------------------------------------
Function ADOCommit( lSave )
   lSave := iif( lSave = nil, .f., lSave )
   oRecordSet[nRecordSet]:Update()
   if lSave
      oRecordSet[nRecordSet]:Save( alltrim(aRecordSet[nRecordSet]), adPersistXML )
   endif
   marca := oRecordSet[nRecordSet]:BookMark
   oRecordSet[nRecordSet]:Requery()
   oRecordSet[nRecordSet]:BookMark = marca
   return .t.

*
*---------------------------------------------------------
Function ADORequery()
   oRecordSet[nRecordSet]:Requery()
   return .t.

*
*---------------------------------------------------------
Function ADOReSync()
   oRecordSet[nRecordSet]:ReSync()
   return .t.

*
*---------------------------------------------------------
Function ADOUpdateBatch()
   oRecordSet[nRecordSet]:UpdateBatch()
   return .t.

*
*---------------------------------------------------------
Function ADOCommitAll()
   for i = 1 to len(aRecordSet)
       oRecordSet[nRecordSet]:Update()
   next
   return .t.

*
*---------------------------------------------------------
Function ADOSave( cfile )
   oRecordSet[nRecordSet]:Save( cFile, adPersistXML )
   return .t.

*
*---------------------------------------------------------
Function ADOReglock()
   //oRecordSet[nRecordSet]:CursorLocation := 2
   //oRecordSet[nRecordSet]:CursorType     := 0
   //oRecordSet[nRecordSet]:LockType       := 3
   return .t.

*
*---------------------------------------------------------
Function ADOSkip( nSkip )
   LOCAL nRec := oRecordSet[nRecordSet]:AbsolutePosition()
   oRecordSet[nRecordSet]:Move( iif( nSkip = nil, 1, nSkip ) )
   IF oRecordSet[nRecordSet]:EOF(); oRecordSet[nRecordSet]:MoveLast() ; ENDIF
   IF oRecordSet[nRecordSet]:BOF(); oRecordSet[nRecordSet]:MoveFirst(); ENDIF
   return oRecordSet[nRecordSet]:AbsolutePosition() - nRec

*
*---------------------------------------------------------
Function ADODelete()
   oRecordSet[nRecordSet]:Delete()
   oRecordSet[nRecordSet]:Move( -1 )
   if cADORDD = "XML" // ".XML" $ upper(aRecordSet[nRecordSet])
      oRecordSet[nRecordSet]:Save( alltrim(aRecordSet[nRecordSet]), adPersistXML )
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOGoTo( nRec )
   //oRecordSet[nRecordSet]:BookMark :=  nRec
   return .t.

*
*---------------------------------------------------------
Function ADOGoTop()
   if .not. ADOBof()
      if ADORecCount() > 0
         oRecordSet[nRecordSet]:MoveFirst()
      endif
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOGoBottom()
   if .not. ADOEof()
      if ADORecCount() > 0
         oRecordSet[nRecordSet]:MoveLast()
      endif
   endif
   return .t.

*
*---------------------------------------------------------
Function ADORecno()
   if nRecordSet < 0
      return 0
   else
      return oRecordSet[nRecordSet]:AbsolutePosition()
   endif

*
*---------------------------------------------------------
Function ADORecCount()
   if nRecordSet < 1
      return 0
   else
      nRecord := oRecordSet[nRecordSet]:AbsolutePosition()
      nRecord := iif(nRecord=nil,-1,nRecord)
      if nRecord < 1 //.or. .not. ( oRecordSet[nRecordSet]:EOF() = oRecordSet[nRecordSet]:BOF() )
         return 0
      else
         return oRecordSet[nRecordSet]:RecordCount()
      endif
   endif

*
*---------------------------------------------------------
Function ADOSetFilter( xpr )
   if xpr = NIL
      oRecordSet[nRecordSet]:Filter := 0
   else
      oRecordSet[nRecordSet]:Filter := xpr
   endif
   return .t.

*
*---------------------------------------------------------
Function ADODeleted( criterio )
   if oRecordSet[nRecordSet]:Status = adRecDeleted
      return .t.
   endif
   return .f.

*
*---------------------------------------------------------
Function ADOClose()
   _RecordSet := len( aRecordSet )
   ADEL( aRecordSet, nRecordSet )
   ASIZE( aRecordSet, _RecordSet-1 )
   oRecordSet[nRecordSet]:End()
   return .t.

*
*---------------------------------------------------------
Function ADOCloseAll()
   for i = 1 to len(aRecordSet)
       oRecordSet[nRecordSet]:End()
   next
   aRecordSet := {}
   nRecordSet := 0
   return .t.

*
*---------------------------------------------------------
Function ADOExecute( cSql )
   aADODefines := {}
   AADD( aADODefines, { "VOID("   , "0(" } )
   AADD( aADODefines, { "BYTE("   , "1(" } )
   AADD( aADODefines, { "CHAR("   , "2(" } )
   AADD( aADODefines, { "WORD("   , "3(" } )
   AADD( aADODefines, { "INT("    , "7(" } )
   AADD( aADODefines, { "BOOLEAN(", "5(" } )
   AADD( aADODefines, { "HDC("    , "6(" } )
   AADD( aADODefines, { "LONG("   , "7(" } )
   AADD( aADODefines, { "STRING(" , "8(" } )
   AADD( aADODefines, { "LPSTR("  , "9(" } )
   AADD( aADODefines, { "PTR("    ,"10(" } )
   AADD( aADODefines, { "DOUBLE(" ,"11(" } )
   AADD( aADODefines, { "DWORD("  ,"12(" } )
   for i = 1 to len( aADODefines )
       cSql := StrTran( cSql, aADODefines[i][2], aADODefines[i][1] )
   next
   //adolog( cSql )
   oADOConection[nConnection]:Execute( cSql )
   return .t.

Function ADOInsertInto( cSql )
   cSql := StrTran( cSql, '"', "'" )
   cSql := "INSERT INTO " + cSql
//? cSql
   oADOConection[nConnection]:Execute( cSql )
   return .t.

*
*---------------------------------------------------------
Function ADOBOF()
   return iif( ADORecCount() > 0, oRecordSet[nRecordSet]:Bof, .t. )

*
*---------------------------------------------------------
Function ADOEOF()
   return iif( ADORecCount() > 0, oRecordSet[nRecordSet]:Eof, .t. )

*
*---------------------------------------------------------
Function ADOFOUND()
   return !oRecordSet[nRecordSet]:Eof

*
*---------------------------------------------------------
Function ADOFind( criterio )
   ADOLocate( criterio )
   return .t.

*
*---------------------------------------------------------
Function ADOLocate( criterio )
   local _nBookMark := oRecordSet[nRecordSet]:Bookmark
   oRecordSet[nRecordSet]:MoveFirst()
   oRecordSet[nRecordSet]:Find( criterio )
   if oRecordSet[nRecordSet]:Eof()
      oRecordSet[nRecordSet]:BookMark := _nBookmark
      return .f.
   else
      return .t.
   endif

*
*---------------------------------------------------------
Function ADOSort( cField, nModo )
   if valtype(cField)='N'
      cField := oRecordSet[nRecordSet]:Fields( cStrField ):Name
   endi
   if cField = Nil
      Return upper(oRecordSet[nRecordSet]:Sort)
   else
      oRecordSet[nRecordSet]:Sort := cField + iif( nModo = NIL, " ASC", " DESC" )
      oRecordSet[nRecordSet]:MoveFirst()
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOFiles( cTable )
   return iif(oRecordSet[nRecordSet]:Table(cTable)==cTable,.t.,.f.)

*
*---------------------------------------------------------
Function ADOAREAS()
   return nRecordSet

*
*---------------------------------------------------------
Function ADOSelect( cRecordSet )
   if cRecordSet = nil
   else
      if cADORDD = "XLS"
         cRecordSet := "[" + cRecordSet + "$]"
      endif
      nRecordSet := ASCAN( aRecordSet, cRecordSet ) 
      nRecordSet := iif( nRecordSet = 0, 1, nRecordSet )
   endif
   //ADOGotop()
   return nRecordSet

*
*---------------------------------------------------------
Function ADOLOG( cMensagem )
   local nHandle
   if .not. file( "ADOERRO.TXT" )
      nHandle := fcreate("ADOERRO.TXT",0)
   else
      nHandle := fopen("ADOERRO.TXT",1)
      length  := fseek(nHandle,0,2)
      fseek(nHandle,length)
   endif
   fwrite(nHandle, cMensagem )
   fclose(nHandle)
   return NIL

*
*---------------------------------------------------------
Function ADOReplace( cCampo, xDado )
   LOCAL uVal,xValor,nTipo,cType,nLong,cQuery,lRepassa := .f., lBlob := .f.,;
         StrFileName
   uVal  := oRecordSet[nRecordSet]:Fields( cCampo ):Value
   nTipo := oRecordSet[nRecordSet]:Fields( cCampo ):Type
   cType := TypeDat(nTipo,cCampo)
   nLong := oRecordSet[nRecordSet]:Fields( cCampo ):DefinedSize
   if ! Empty( xDado )
      if ValType( xDado ) = 'D'
         if nTipo=  7 .or. nTipo=133 .or. nTipo=135
            if empty( xDado )
               xDado := date()
            endif
            lRepassa := .t.
         endif
      endif
      if ValType( xDado ) = 'N'
         if nTipo=17 .or. nTipo= 14 .or. nTipo=  5 .or. nTipo=  3 .or. nTipo=131 .or. nTipo=  2 .or. nTipo=  6 .or. ;
            nTipo= 4 .or. nTipo=020 .or. nTipo=018 .or. nTipo=019 .or. nTipo= 21 .or. nTipo=138 .or. nTipo=139
            lRepassa := .t.
         endif
      endif
      if ValType( xDado ) = 'C'
         if nTipo=202 .or. nTipo=130 .or. nTipo=200 .or. nTipo=201 .or. nTipo=129 .or. nTipo= 72
            xDado := substr( xDado, 1, nLong )
            lRepassa := .t.
         endif
         if nTipo=201 .or. nTipo=203 .or. nTipo=205 .or. nTipo=128
            StrFileName := Alltrim(StrZero(Random(99999999),8))+".APL"
            MemoWrit( StrFileName, xDado )
            lRepassa := .t.
            lBlob    := .t.
         endif
      endif
      if ValType( xDado ) = 'L'
         if nTipo= 11 .or. nTipo= 16
            lRepassa := .t.
         endif
      endif
      if ValType( xDado ) = 'M' .or. ValType( xDado ) = 'I'
         if nTipo=201 .or. nTipo=203 .or. nTipo=205 .or. nTipo=128
            lRepassa := .t.
            lBlob    := .t.
         endif
      endif
      if lRepassa
         if lBlob // adolog( ccampo+"-"+ctype+"-"+strzero(ntipo,3)+"-"+ValType( xDado ) )
            oADOStream:Type := 1 // adTypeBinary
            oADOStream:Open()
            oADOStream:LoadFromFile( StrFileName )
            oRecordSet[nRecordSet]:Fields( cCampo ):Value := oADOStream:Read()
            oADOStream:Close()
         else
            oRecordSet[nRecordSet]:Fields( cCampo ):Value := xDado
         endif
      endif
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOField( cStrField )
   LOCAL uVal,nTipo,cType,nLong,xValor:=nil,StrFileName
   if valtype(cStrField)='C'
      cStrField := upper(alltrim(cStrField))
   endif
   if nRecordSet > 0
      uVal  := oRecordSet[nRecordSet]:Fields( cStrField ):Value
      nTipo := oRecordSet[nRecordSet]:Fields( cStrField ):Type
      cType := TypeDat(nTipo,cStrField)
      nLong := oRecordSet[nRecordSet]:Fields( cStrField ):DefinedSize
      do case
         case cType='C'; xValor:=if(empty(uVal),spac(nLong),uVal+spac(nLong-len(uVal)))
         case cType='D'; xValor:=if(empty(uVal),ctod('')                    ,uVal)
         case cType='N'; xValor:=if(empty(uVal),0                           ,uVal)
         case cType='L'; xValor:=if(empty(uVal),.f.                         ,uVal)
         case cType='M' .or. cType='I'
              StrFileName := Alltrim(StrZero(Random(99999999),8))+".APL"
              oADOStream:Type := 1 // adTypeBinary
              oADOStream:Open()
              oADOStream:Write( oRecordSet[nRecordSet]:Fields( cStrField ) )
              oADOStream:LoadFromFile( oRecordSet[nRecordSet]:Fields( StrFileName ), 2 ) // adSaveCreateOverWrite
              oADOStream:Close()
              xValor := MemoRead( StrFileName )
         otherwise     ; xValor:=         uVal
      endcase
   endif
   RETURN xValor

*
*---------------------------------------------------------
Function ADOFieldBlank( cStrField )
   LOCAL uVal,nTipo,cType,nLong,xValor:=nil
   if valtype(cStrField)='C'
      cStrField := upper(alltrim(cStrField))
   endif
   if nRecordSet > 0
      uVal  := oRecordSet[nRecordSet]:Fields( cStrField ):Value
      nTipo := oRecordSet[nRecordSet]:Fields( cStrField ):Type
      cType := TypeDat(nTipo,cStrField)
      nLong := oRecordSet[nRecordSet]:Fields( cStrField ):DefinedSize
      do case
         case cType='C'; xValor:=space(nLong)
         case cType='D'; xValor:=ctod('  /  /  ')
         case cType='N'; xValor:=0
         case cType='L'; xValor:=.f.
         otherwise     ; xValor:=''
      endcase
   endif
   RETURN xValor

*
*---------------------------------------------------------
Function TypeDat(nTipo,cField)
   do case
      case nTipo=8.or.nTipo=12.or.nTipo=72.or.nTipo=129.or.nTipo=130.or.(nTipo>=200.and.nTipo<=203)
           // adBSTR             8
           // adGUID             72
           // adChar             129
           // adWChar            130
           // adVarChar          200
           // adLongVarChar      201
           // adVarWChar         202
           // adLongVarWChar     203
           return 'C'

      case nTipo= 17.or.nTipo= 16.or.nTipo= 14.or.nTipo=  5.or.nTipo=  3.or.nTipo=131.or.nTipo= 2 .or.nTipo=  6.or.;
           nTipo=  4.or.nTipo=020.or.nTipo=018.or.nTipo=019.or.nTipo= 21.or.nTipo=138.or.nTipo=139
           // adSmallInt         2
           // adInteger          3
           // adSingle           4
           // adDouble           5
           // adCurrency         6
           // adDecimal          14
           // adTinyInt          16
           // adUnsignedTinyInt  17
           // adUnsignedSmallInt 18
           // adUnsignedInt      19
           // adBigInt           20
           // adUnsignedBigInt   21
           // adNumeric          131
           // adPropVariant      138
           // adVarNumeric       139
           return 'N' // Numerico

      case nTipo=  7.or.nTipo=64.or.nTipo=133.or.nTipo=134.or.nTipo=135
           // adDate             7
           // adFileTime         64
           // adDBDate           133
           // adDBTime           134
           // adDBTimeStamp      135
           return 'D' // Data

      case nTipo= 11
           // adBoolean          11
           return 'L' // Logico

      case nTipo=203.or.nTipo=128
           // adLongVarWChar     203
           // adPropVariant      138
           return 'M' // Memo

      case nTipo=128.or.nTipo=204.or.nTipo=205
           // adBinary           128
           // adVarBinary        204
           // adLongVarBinary    205
           return 'I' // Imagem

   otherwise
      alert('Tipo de dado invalido: Campo '+cField+' Type='+str(nTipo))
   endcase
   return 'U'

*
*---------------------------------------------------------
Function isRSEmpty()
   return ((oRecordSet[nRecordSet]:BOF()=.t.) .and. (oRecordSet[nRecordSet]:EOF()=.t.))

*
*---------------------------------------------------------
Function ADOGetSQL( sqlFileName )
   sqlFileName = sqlFileName + ".SQL"
   if file(sqlFileName)
      cSql := MemoRead( sqlFileName )
      oADOConection:Execute( cSql )
   endif
   return nil

*
*---------------------------------------------------------
Function ADOUseRemote( cDatabase, lShared )
   local oError
   if cDatabase = NIL
      oRecordSet[nRecordSet]:Close()
   else
      AADD( aRecordSet, cDatabase )
      cRecordSet := cDatabase
      nRecordSet := len( aRecordSet )
      oRecordSet[nRecordSet] := oADOConection
      if cADORDD = "XML" // ".XML" $ upper(cDatabase)
         oRecordSet[nRecordSet]:Open( cDatabase, StrConnection, 1, 3 )
      else
         oRecordSet[nRecordSet]:CacheSize      := 50
         oRecordSet[nRecordSet]:CursorLocation := adUseClient
         if lShared = .t.
            oRecordSet[nRecordSet]:CursorType  := 1 // adOpenKeySet
            oRecordSet[nRecordSet]:LockType    := adLockBatchOptimistic
         else
            oRecordSet[nRecordSet]:CursorType  := adOpenStatic
            oRecordSet[nRecordSet]:LockType    := adLockPessimistic
         endif
         oRecordSet[nRecordSet]:Sql( "Select * from " + cDatabase, StrConnection )
      endif
      oRecordSet[nRecordSet]:MoveFirst()
   endif
   return .t.

function Random( nMaximo )
   static nRandom
   local nTemporal
   nMaximo = if( nMaximo == NIL, 65535, nMaximo )
   if nRandom == NIL
      nRandom = seconds()
   endif
   nTemporal = ( nRandom * seconds() ) % ( nMaximo + 1 )
   nRandom = nTemporal + seconds()
   RETURN int( nTemporal )

MensagemEnviado: 16 Out 2007 11:40
por rochinha
Amiguinhos

Neste codigo exemplo voces encontrarão toda formatação necessária para manipulação de arquivos e a forma como os COMMANDos e funções da ADOxb trabalham:

Este exemplo leva em consideração o uso de xBrowse do Fivewin mas o codigo é de facil entendimento e pode muito bem ser portado para o modo texto ou usado com xHarbour. No arquivo ADOxb.CH voce encontra SET para modificação para uso do acesso via OLE nativo xHarbour.

No exemplo estou acessando diretamente um .MDB e para tal é necessário criar um .MDB vazio no Access. Deixe que o aplicativo crie sozinho as tabelas e acrescente alguns registros.

Codigo CUSTOMER.PRG modificado:
#include "FiveWin.ch"
#include "Splitter.ch"

#include "adoxb.ch"

static oWnd, oClients, oClient, oName
static cName
static oSplit

//----------------------------------------------------------------------------//
function CUSTOMER(cTitle)
    public oMenu, user_nivel := 5
    default cTitle := "coloque um nome"

    // Necessária para criar objetos e variaveis visiveis o tempo todo
    ADOSetRDD( "ACCESS" )

    if ADORDDDefault() = "ACCESS" // ADOMDB
       StrDatabase   := ".\adomdb.mdb"
       StrConnection := "Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";"
    endif
    if ADORDDDefault() = "FIREBIRD" // ADOGDB
       StrDatabase   := ".\adogdb.gdb"
       StrConnection := "DRIVER=Firebird/InterBase(r) driver; UID=sysdba; PWD=masterkey; DBNAME="+StrDatabase
    endif
    if ADORDDDefault() = "MYSQL" // ADOMySQL
       StrDatabase   := [adomysql]
       StrServer     := [127.0.0.1]
       StrPort       := 3306
       StrUserID     := [root]
       StrUserPWD    := []
       StrDriver     := "MySQL ODBC 3.51 Driver"
       StrConnection := "driver={" + StrDriver +"};database=" + StrDatabase + ;
                        ";server=" + StrServer + ;
                        ";uid=" + StrUserID + ;
                        ";pwd=" + StrUserPWD + ;
                        ";option=35"
    endif
    if ADORDDDefault() = "PARADOX" // ADOPX
       StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\;Extended Properties=Paradox 5.x;"
    endif
    if ADORDDDefault() = "XML" // ADOXML
       StrConnection := "Provider=MSPersist"
    endif
    if ADORDDDefault() = "REMOTE" // ADORDS
       StrConnection := "Provider=MS Remote;Remote Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/Inetpub/wwwroot/scripts/ASP/UAPortal/ua_portal.mdb;Remote Server=http://localhost/uaportal/"
    endif

    MsgRun( "Conectando via "+ADORDDDefault()+"..." )

    ADO CONNECT StrConnection

    // Cria tabelas se nao existirem
    if ADOFile( "clientes" )
    else 
       MsgRun( "Criando tabela CLIENTES..." )
       ADO EXECUTE "DROP TABLE clientes"
       ADO EXECUTE "CREATE TABLE clientes (nome char(45), email char(45), unique(nome))"
    endif
    if ADOFile( "siglas" )
    else
       MsgRun( "Criando tabela SIGLAS..." )
       ADO EXECUTE "DROP TABLE siglas"
       ADO EXECUTE "CREATE TABLE siglas (uf char(2), estado char(20), unique(uf))"
    endif

    // Abre as tabelas
    ADO USE clientes
    ADO USE siglas

    // Verifica se ja possuem dados
    ADO SELECT clientes
    nRegistros := ADORecCount()
    if nRegistros = 0
       ADO APPEND BLANK
       ADO REPLACE nome        WITH "JOSE CARLOS DA ROCHA"
       ADO REPLACE email       WITH "IROCHINHA@ITELEFONICA.COM.BR"
       ADO COMMIT
    endif

    ADO SELECT siglas
    nRegistros := ADORecCount()
    if nRegistros = 0
       ADO APPEND BLANK
       ADO REPLACE uf          WITH "SP"
       ADO REPLACE estado      WITH "SAO PAULO"
       ADO COMMIT
       ADO APPEND BLANK
       ADO REPLACE uf          WITH "RJ"
       ADO REPLACE estado      WITH "RIO DE JANEIRO"
       ADO COMMIT
    endif

    ADO CLOSE ALL

    SET _3DLOOK ON
    DEFINE WINDOW oWnd TITLE cTitle MDI MENU BuildMenu()           
                DEFINE BUTTONBAR OF oWnd
               SET MESSAGE OF oWnd TO cTitle CENTERED
    ACTIVATE WINDOW oWnd VALID MsgYesNo( "Tem certeza?" )
    return nil

//----------------------------------------------------------------------------//
function BuildMenu()
   local oMenu
   MENU oMenu
      MENUITEM "&Cadastros"
      MENU
         MENUITEM "&Clientes..." ACTION  Clientes() MESSAGE "Cadastro de Clientes"
         SEPARATOR
         MENUITEM "&Sair"        ACTION oWnd:End()  MESSAGE "Termina Aplicativo"
      ENDMENU
      oMenu:AddMdi()              // Add standard MDI menu options
   ENDMENU
   return oMenu

//----------------------------------------------------------------------------//
function Clientes(bPrc, bAdc, bAlt, bExc, bImp, bSai)
    LOCAL oIco, oBar, oGet
    LOCAL cTitle := "Manutencao de Clientes"
    LOCAL oDlg, oBrw, nRec
    LOCAL aData := {}
    LOCAL nFor
    LOCAL oLbx, cItem
    LOCAL btnPrc, btnAdc, btnAlt, btnExc, btnImp, btnsai
    DEFAULT bPrc    := { || RecPrc( oLbx ) },;
            bAdc    := { || RecInc( oLbx ) },;
            bAlt    := { || RecAlt( oLbx ) },;
            bExc    := { || RecExc( oLbx ) },;
            bImp    := { || RecImp( oLbx ) },;
            bSai    := { || oDlg2:End() }
    if oClients != nil
       return nil
    endif
    DEFINE WINDOW oClients TITLE cTitle MDICHILD ICON oIco
    DEFINE BUTTONBAR oBar OF oClients
    DEFINE BUTTON OF oBar ACTION RecAlt(oLbx)
    nSplitH := 400
    ADO USE clientes
    //ADO SORT ON nome
    //? "Areas    : " + str( ADOAREAS() ),;
    //  "Tabela   : " + ADOALIAS(),;
    //  "Registros: " + str( ADORECCOUNT() )
    @ 0,0 LISTBOX oLbx FIELDS ADOField( "nome" ), ADOField( "email" ) ;
         HEADERS "Nome","email" ;
         FIELDSIZES 350,250 ;
         PIXEL SIZE 1000,1000 OF oClients
    oLbx:cAlias         := "ARRAY" // ADO devolve tabelas em arrays
    oLbx:bLogicLen   := { || ADORecCount() }
    oLbx:bGoTop      := { || ADOGotop() }
    oLbx:bGoBottom := { || ADOGoBottom() }
    oLbx:bSkip         := { | nSkip | ADOSkip( nSkip ) }
    oLbx:bRClicked   := {| nRow, nCol | RecMenu( nRow, nCol, oLbx ) }
    oLbx:bLDblClick  := {| nRow, nCol | RecAlt(oLbx) }
    oLbx:nStyle        := 1
    oLbx:nLineStyle  := 3
    // -> Estilo FLAT
    oLbx:nHeaderStyle  := 2
    oLbx:nHeaderHeight := 20
    oLbx:nLineHeight   := 15
    oLbx:nStyle        := nOr( WS_CHILD, WS_VSCROLL, WS_HSCROLL, WS_VISIBLE, WS_TABSTOP )

    oClients:SetControl( oLbx )
    ACTIVATE WINDOW oClients MAXIMIZED VALID( oClients := nil, ADOCLOSEALL(), .t. )

return nil

//----------------------------------------------------------------------------//
function RecMenu( nRow, nCol, oLbx )
   local oPopup
   MENU oPopup POPUP
        MENUITEM "&Incluir novo registro"  RESOURCE "bmp_binoculo" ACTION RecInc( oLbx )
        MENUITEM "&Alterar registro atual" RESOURCE ""             ACTION RecAlt( oLbx )
        MENUITEM "&Excluir registro atual" RESOURCE ""             ACTION RecExc( oLbx )
        SEPARATOR
        MENUITEM "&Procurar registro"      RESOURCE ""             ACTION RecPrc( oLbx )
        SEPARATOR
        MENUITEM "&Imprimir Listagem"      RESOURCE ""             ACTION RecImp( oLbx )
   ENDMENU
   ACTIVATE POPUP oPopup AT nRow, nCol OF oLbx
   return nil

//----------------------------------------------------------------------------//
function GenReport()
   local oWnd, oIco
   DEFINE ICON oIco FILENAME "..\icons\print.ico"
   DEFINE WINDOW oWnd MDICHILD TITLE "Clients report" ;
      VSCROLL HSCROLL ICON oIco
   ACTIVATE WINDOW oWnd
   return nil

//----------------------------------------------------------------------------//
function Show2Client()
   local oIco
   if oClient != nil
      return nil
   endif
   DEFINE ICON oIco FILENAME "..\icons\Person.ico"
   DEFINE DIALOG oClient RESOURCE "Client" ;
      ICON oIco
   REDEFINE SAY ID 3 OF oClient   // To get the proper color
   REDEFINE SAY ID 4 OF oClient
   REDEFINE SAY ID 5 OF oClient
   REDEFINE GET oName VAR cName ID ID_NAME OF oClient
   REDEFINE BUTTON ID ID_NEXT OF oClient ACTION GoNext()
   SELECT Sales     // We select Sales to properly initialize the Browse
   REDEFINE LISTBOX FIELDS ID ID_SALES OF oClient
   ACTIVATE DIALOG oClient CENTERED NOWAIT ;
      VALID ( oClient := nil, .t. )           // Destroy the object
   SELECT Clients
   return nil

//----------------------------------------------------------------------------//
function ChangeClient()
   if oClient != nil
      cName = AllTrim( Clients->Last ) + ", " + Clients->First
      oName:Refresh()
   endif
   return nil

//----------------------------------------------------------------------------//
function GoNext()
   if oClients != nil
      oClients:oControl:GoDown()
   else
      SKIP
      if EoF()
         GO BOTTOM
      endif
   endif
   ChangeClient()
   return nil

FUNCTION CLEARCHR( CICCGC )
   CICCGC = STRTRAN(CICCGC, '>', '')
   CICCGC = STRTRAN(CICCGC, '<', '')
   CICCGC = STRTRAN(CICCGC, '.', '')
   CICCGC = STRTRAN(CICCGC, '-', '')
   CICCGC = STRTRAN(CICCGC, '(', '')
   CICCGC = STRTRAN(CICCGC, ')', '')
   CICCGC = STRTRAN(CICCGC, '=', '')
   CICCGC = STRTRAN(CICCGC, '+', '')
   CICCGC = STRTRAN(CICCGC, '\', '')
   CICCGC = STRTRAN(CICCGC, '/', '')
   CICCGC = STRTRAN(CICCGC, '*', '')
   CICCGC = STRTRAN(CICCGC, ['], '')
   CICCGC = ALLTRIM(CICCGC)
   RETURN CICCGC

function fun( oque )
  msgstop( oque )
  return .t.
function tgsetmode( oque )
  return .t.
function tooltip( oque )
  return .t.
FUNCTION NewCapFirst
parameter string
declare excesao[7]
excesao[1] = " Do "
excesao[2] = " Dos "
excesao[3] = " Da "
excesao[4] = " Das "
excesao[5] = " De "
excesao[6] = " E "
excesao[7] = " Del "
novotexto = space(1)+lower(string)
fim = len(string)
for i = 1 to fim
   if substr(novotexto,i,1) = " "
      novotexto = stuff(novotexto,i+1,1,upper(substr(novotexto,i+1,1)))
   endif
next
tamanho = len(excesao)
for i = 1 to tamanho
   if excesao[i]$novotexto   && tamanho
      novotexto = stuff(novotexto,AT(excesao[i],novotexto),;
      len(excesao[i]),lower(excesao[i]))
   endif
next
RETURN(ltrim(novotexto))

//-----------------------------------------------------------
static function  RecPrc(oLbx)
    Local odlg1
    Local cCodigo:=0
    Local cSair:=" "
    Local sql
    DEFINE DIALOG oDlg1 From 0,0 To 160,250  PIXEL;
           TITLE " Procura na Tabela em Access "
    DEFINE FONT oFont NAME "FIXEDSYS" SIZE 10, -10    && Use a Nonproportional font
    SET FONT OF oDlg1 TO oFont                         && so characters line up in Says
    @ 02,05 say "Codigo : " OF oDlg1
    @ 02.2,10 get cCodigo   OF oDlg1 picture "9999" size 20,10
    @ 02.7 , 10 button "Procurar"  of oDlg1 size 40,12 action (cSair:="*",oDlg1:End())
    ACTIVATE DIALOG oDlg1 centered
    if cSair="*"
       //locate for (odbf:cAlias)->field_0001 = cCodigo
       criterio = "idpessoa Like '" + cCodigo + "%'"
       //oRs:MoveFirst()
       //oRs:Find criterio, 0, adSearchFoward
       if eof()
          msgAlert("NÆo encontrado !!!")
          go top
       endif
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function  RecInc(oLbx)
    LOCAL odlg3
    LOCAL cNome     := space(40)
    LOCAL cTelefone := space(14)
    LOCAL cEmail    := space(40)
    LOCAL cSair     := " "
    DEFINE DIALOG oDlg3 From 0,0 To 230,500 PIXEL TITLE " Inclusao na Tabela em Access "
           DEFINE FONT oFont NAME "FIXEDSYS" SIZE 10, -10    && Use a Nonproportional font
           SET FONT OF oDlg3 TO oFont                         && so characters line up in Says
           @ 02,05 say "Nome_____: " OF oDlg3
           @ 04,05 say "Email____: " OF oDlg3
           //
           @ 02.2,10 get cNome     OF oDlg3 picture "@!" size 150,10
           @ 04.4,10 get cEmail    OF oDlg3 picture "@!" size 150,10
           //
           @ 04.7 , 15 button "Salvar"   of oDlg3 size 40,12 action (cSair:="*",oDlg3:End())
    ACTIVATE DIALOG oDlg3 centered
    if cSair="*"
       ADO APPEND BLANK
       ADO REPLACE nome        WITH alltrim( cNome )
       ADO REPLACE email       WITH alltrim( cEmail )
       ADO COMMIT
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function  RecAlt(oLbx)
    LOCAL odlg3
    LOCAL nRegistro := ADORecno()
    //LOCAL cNome     := PadR( ADOField( "nome" ), 40 )
    //LOCAL cEmail    := PadR( ADOField( "email" ), 40 )
    LOCAL cNome     := ADOField( "nome" )
    LOCAL cEmail    := ADOField( "email" )
    LOCAL cSair     := " "
    DEFINE DIALOG oDlg3 From 0,0 To 230,500 PIXEL TITLE " Inclusao na Tabela em Access "
           DEFINE FONT oFont NAME "FIXEDSYS" SIZE 10, -10    && Use a Nonproportional font
           SET FONT OF oDlg3 TO oFont                        && so characters line up in Says
           //
           @ 02,05 say "Nome_____: " OF oDlg3
           @ 04,05 say "Email____: " OF oDlg3
           //
           @ 02.2,10 get cNome     OF oDlg3 picture "@!" size 150,10
           @ 04.4,10 get cEmail    OF oDlg3 picture "@!" size 150,10
           //
           @ 04.7 , 15 button "Salvar"   of oDlg3 size 40,12 action (cSair:="*",oDlg3:End())
    ACTIVATE DIALOG oDlg3 centered
    if cSair="*"
       ADO REPLACE nome       WITH alltrim( cNome )
       ADO REPLACE email      WITH alltrim( cEmail )
       ADO COMMIT
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function  RecExc(oLbx)
    if MsgYesNo( "Excluir este Registro ?", "Por Favor, confirme" )
       ADO DELETE
       //ADO SKIP
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function RecImp( oLbx )
/*
    local oRpt
    local n
    local cAlias := If( oLbx != nil, oLbx:cAlias, Alias() )
    REPORT oRpt TITLE "Relatorio: " + cAlias ;
           HEADER "Data: " + DToC( Date() ) + ", Hora: " + Time() ;
           FOOTER "Pagina: " + Str( oRpt:nPage, 3 ) ;
           PREVIEW
           if Empty( oRpt ) .or. oRpt:oDevice:hDC == 0
              return nil
           endif
           for n = 1 to FCount()
               oRpt:AddColumn( TrColumn():New( { FInfo1( cAlias, n ) },,;
                     { FInfo2( cAlias, n ) },,,,,,,,,, oRpt ) )
           next
    ENDREPORT
    ACTIVATE REPORT oRpt
    GO TOP
*/
    return nil

//--------------------------------------------
static function FInfo1( cAlias, n )
return { || ( cAlias )->( FieldName( n ) ) }

//-----------------------------------------------------------
static function FInfo2( cAlias, n )
return { || ( cAlias )->( FieldGet( n ) ) }

Function DbfDbt()
Return Nil

#include "adoxb.prg"

MensagemEnviado: 16 Out 2007 12:30
por rochinha
Amiguinhos

Com o exemplo anterior o uso com tabelas em um .MDB ficam mais faceis de manipular, mas é logico que ninguem esta interessado em usar com Access inclusive pelo fato do mesmo não possuir umas ferramentas de manipulação pequenas e rapidas como os famosos DBUs, mas nada invibializa este método de uso com tabelas vinculadas ao .MDB.

Mas vejamos o que seria necessário para o caso de se usar MySQL:

- Instalar o MySQL. Sugiro a versão 4, não importando que a 5 é atual, bla, bla, bla pois os testes que fiz foi usando esta versão.
- Instalar o MyODBC. Sugiro o 3.51.

Para efeitos de aprendizado estas versões estão de bom tamanho.

No CUSTOMER.PRG basta modificar a linha a seguir:

    ...
    ADOSetRDD( "MYSQL" )
    ...


No caso do .MDB eu sugeri que fosse criado o mesmo via Access e no caso do MySQL será necessário criar a pasta ADOMYSQL na pasta DATA no diretório MySQL e as tabelas serão criadas normalmente.

MensagemEnviado: 16 Out 2007 15:52
por rochinha
Amiguinhos

.MDB e MySQL são opções muito boas de se usar inclusive pelo fato dos mesmos terem facilidades de manipulação via ASP e PHP, ou seja, se voce tem um site que possui este tipo de database como suporte, então a sua manipulação ficará mais facil usando ADOxb.

No caso do MySQL eu integrei ao meu sistema o método de acesso remoto aos meus sites podendo incluir, visualizar e exluir registros de forma transparente.

Mas outro database que faz a cabeça de todo mundo é o firebird e porque não poder manipula-lo também?

Com Firebird o database reside em um arquivo .GDB e para manipula-los é necessário instalar algumas ferramentas:

- Instalar o servidor Firebird. Sugiro a versão 1.5.3.4870-0-Win32.
- Instalar o Firebird ODBC. Sugiro o Firebird_ODBC_1.2.0.69-Win32.exe.

Estas versões são as que usei como testes.

No CUSTOMER.PRG basta modificar a linha a seguir:

    ...
    ADOSetRDD( "FIREBIRD" )
    ...

MensagemEnviado: 16 Out 2007 16:00
por rochinha
Amiguinhos

Alguns downloads interessantes de suporte ao topico:

ADOMDB.EXE-Exemplo de acesso via ACCESS.
ADOGDB.EXE-Exemplo de acesso via FIREBIRD.
ADOMYSQL.EXE-Exemplo de acesso via MySQL.

Servidores e drivers ODBC:

Firebird-1.5.3.4870-0-Win32.exe
Firebird_ODBC_1.2.0.69-Win32.exe
MySQL 3
MyODBC-standard-3.51.9-win.msi

MensagemEnviado: 17 Out 2007 00:25
por Dudu_XBase
:{ Rochinha vou fazer uns teste essa semana e te retornarei o sucesso do mesmo.

MensagemEnviado: 17 Out 2007 08:28
por janio
rochinha escreveu:* adUseServer 2 Atua no lado servidor
* adUseClient 3 Atua no lado cliente


Rochinha,

Há um ano atrás quando decidi portar meu sistema para MySql (hoje utilizo com sucesso o Mediator), nas muitas andanças pela internet atrás de literatura sobre o tema, via muito essa expressão: "FAZER UMA CONSULTA AO LADO DO SERVIDOR". Nunca entendi o que isso significa.

O que isso quer dizer??

Jânio

MensagemEnviado: 17 Out 2007 10:37
por rochinha
Amiguinho

Consulta no lado cliente ou consulta no lado servidor é o que chamamos de direcionamento do processamento e neste caso voce define de qual lado estara o cursor que permitirá andar pelos registros consultados.

O cursor é o que entendemos como a linha que se encontra na posição do registro atual sendo apresentado, de um modo mais didático, quando estamos dentro de um dBEdit com vários registros, para sabermos em que registro estamos o dBEdit o mostra com cor diferente, isto é uma representação de cursor.

Quando você faz uma consulta, a mesma retorna vários registros, por exemplo SELECT * FROM clientes gera uma lista com vários registros de sua tabela(recordset) e posiciona o cursor no primeiro registro.

O cursor pode ser usado tanto no lado do cliente como no lado do servidor a diferença será a velocidade de resposta dos movimentos e posicionamentos.

O cursor no lado cliente tem sua manipulação interna pelo driver ODBC, ADO, OLEDB ou modulo cliente de seu Database Server e o processamento de seus resultados é feito localmente.

O cursor no lado servidor tem sua manipulação feita pelo Database Server processamento de seus resultados é feito remotamente.

Quando se manipula dados de forma on-line, se voce deseja apenas executar rotinas de filtragens e calculos, use o cursor ou direcione o pedido para o lado servidor.

Quando se manipula dados de forma on-line, se voce deseja executar rotinas de cadastro e manipulação dos dados do registro direcione o pedido para o lado cliente, pois ao executar os comandos finalizadores como Update o lado cliente se encarregará de executar o comando do lado servidor.

Em suma o processamento do lado cliente diminui a carga no servidor (banco de dados), ou seja, é muito mais rápido de se trabalhar pois deixa o servidor (banco de dados) livre.

MensagemEnviado: 07 Nov 2007 17:42
por RamonXHB
Rochinha, seria possível o uso dos providers oledb-adodb em vez de usar drives odbc para o acesso aos BD´s ???

Eu uso com firebird com o ibprovider que se encontra em
http://www.ibprovider.com/eng/trial.html na opção IBProvider Free Edition
Vem com manual, exemplos, e etc....
já testei firebird com odbc, e usando com driver oledb, fica mais rapido...
a mesma coisa ocorre com o mysql, usando o driver oledb MYOLEDB que tem no sourceforge...
Foquei meu desenvolvimento em cima do firebird, por ser realmente de livre uso, diferente do mysql, que tem uma licença meio obscura...

Estou desenvolvendo meu sistema todo em cima de queries sql, mas achei sua sistemática muito interessante, facilitando o uso por parte do pessoal que usa DBF...

Vou testar seus comandos sem o uso do drive odbc, depois reporto pra vc o que ocorrer...

MensagemEnviado: 08 Nov 2007 07:47
por rochinha
Amiguinho

Voce poderá usar as duas maneiras de se conectar ao database, seja por ODBC, usando um DNS ou OLEDB.

Nos dois casos o database deve possuir drivers para este tipo de trabalho e para tanto voce necessitará fazer a conexão usando a string de chamada compativel com o driver que voce quer usar.

Veja em http://www.connectionstrings.com/ qual a mais adequada.

MensagemEnviado: 08 Nov 2007 18:25
por ciacpd
Olá Rochinha,

Tem como abrir arquivo informando um select ao invés do nome da tabela?

Exemplos:

ADO USE MimTable SQL `Select cod_cid, nom_cid from cidades where estado="SP"`

Str_Select := ´Select cod_cid, nom_cid from cidades where estado="SP"`
ADO USE MimTable SQL Str_Select

MensagemEnviado: 09 Nov 2007 03:23
por rochinha
Amiguinho

Voce poderá usar o comando ADO EXECUTE:

...
ADO EXECUTE ´Select cod_cid,nom_cid from cidades where estado="SP"´
...

MensagemEnviado: 14 Nov 2007 14:27
por FARLEY RIBEIRO
Caro Rochinha...

Desculpe a ignorância mas não sei pq não estou conseguindo ...

Exibe a mensagem "Nenhum RDD especificado"

Criei um bd de dados no access "siac.mdb" (codigo (integer), descricao char(40)

Salvei o arquivo adoxb.ch, adoxb.prg e customer.prg com o código abaixo

#include "FiveWin.ch"
#include "Splitter.ch"
#include "adoxb.ch"

//----------------------------------------------------------------------------//
function main()

// Necessária para criar objetos e variaveis visiveis o tempo todo

ADOSetRDD( "ACCESS" ) // << ---------- definindo o RDD

if ADORDDDefault() = "ACCESS" // ADOMDB
   StrDatabase := ".\siac.mdb"
   StrConnection := "Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";"
endif

MsgRun( "Conectando via "+ADORDDDefault()+"..." )

ADO CONNECT StrConnection

// Abre as tabelas
ADO USE clientes

// Verifica se ja possuem dados
ADO SELECT clientes
nRegistros := ADORecCount()
if nRegistros = 0
   ADO APPEND BLANK
   ADO REPLACE codigo WITH "0001"
   ADO REPLACE nome   WITH "JOSE CARLOS DA ROCHA"
   ADO COMMIT
endif

ADO CLOSE ALL

return nil

#include "adoxb.prg"


Veja o arquivo fonte completo aqui...
http://www.badongo.com/pt/file/5136629

O que está acontecendo?

Grato

Farley

MensagemEnviado: 14 Nov 2007 23:09
por rochinha
Amiguinho

Fiz testes com seu exemplo e notei que o erro ocorre pois sua ADOXB.CH e ADOXB.PRG estão desatualizadas em relação ao codigo completo que esta postado no inicio do tópico.

Recorte os codigos e salve-os novamente e recompile.

O unico erro que voce deverá ter depois é a falta de criação da tabela CLIENTES.

Entenda que um .MDB não é uma tabela como um .DBF é na verdade um container de tabelas e dentro deles deverão existir as tabelas clientes e siglas para teste.

Reveja o tópico desde o inicio e veja os exemplos que te mostram com clareza o porque da criação das mesmas.

MensagemEnviado: 05 Dez 2007 23:52
por clodoaldomonteiro
Rochinha!
Todas as bases de dados que vc mencionou tem que usar um sistema gerenciador de base de dados, não teria nenhum substituto do DBF com gerenciamento interno, pelo prórpio aplicativo?

Pois o bom do clipper era poder fazer tudo no sistema mesmo, sem sistema por fora, ´mas fica aquela coisa que DBF não é seguro.

Sou novato com o xharbour e ainda tenho muitas dúvidas.

Grato pela atenção.

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 12 Jun 2008 15:47
por gvc
[clodoaldomonteiro]
O que acontece é que o clipper administrar arquivos de dados que na verdade são arquivos textos com dados formatados.
Qdo vc esta trabalhando com um SGDB como MySQL/Oracle, o SGDB esta trabalhando na máquina o tempo todo. O seu sistema manda requisição de dados e o SGDB processa o pedido e dispõe os dados para o sistema. Por isso a sua consulta retorna um ponteiro com o resultado.
O mesmo vale para o ADS. Fica uma parte rodando no servidor. O seu sistema roda o RDD ADS fazendo a comunicação com o ADS do servidor. Este administra os arquivos, mesmo estes sendo DBF. O ADS abre os arquivos solicitados como exclusivos para ele trabalhar. Assim vc não consegue abrir um DBF já aberto pelo ADS senão usar o gerenciador do mesmo.
Existem muitos softwares administradores. Aqui o pessoal usou o Toad a algum tempo (tem uma versão gratuita agora). Agora estão usando o PLSQL Developer. Os dois são muito bons mesmo.

Espero ter ajudado. Boa sorte.

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 12 Jun 2008 16:57
por rochinha
Amiguinho Clodoaldo,

Quando o DBF foi concebido para ser usado com o dBase(nem me lembro se dBase II) possuia manipulacao compartilhada, com dBase III em diante sim, as redes existentes eram gerenciadas por Novell, Lantastic, etc, todas rodando sob um sistema operacional monousuario o qual não sofria interferencias de outros programas pois na memoria só existiam drivers, o aplicativo e os DBFs. As redes eram mais seguras e os dados também por serem centralizadas num servidor que só executava o modulo central da rede.

Mesmo assim ainda existia o vilão da corrupçao, geralmente causada por quedas de força, ja que no-breaks pessoais ainda iriam aparecer.

Com o uso de redes ponto-a-ponto, começamos a ter os tão conhecidos problemas de travamentos, corrupçao, etc, causados pelas redes. Depois as redes se tornaram mais heterogeneas, com versões diferentes de Windows, falhas dos drivers controladores, perdas de conexão momentaneas em momentos criticos, etc.

Os SGDBs de hoje trabalham da mesma forma que as redes trabalhavam antes, centralizando o processo.

O dBase quando aberto pela rede é praticamente esticado do servidor para os terminal, pense em um chiclete, estique-o de sua boca com uma mão e depois com a outra mão puxe outra ponta, continue puxando ate uma parte romper.

Esta analogia é praticamente uma digitalizaçao de uma quebra que causa uma perda de dados ou corrupção.

O dBase foi concebido para armazenar dados e na época, como existia o pensamento de que memória e poder de processamento não cresceriam ou chegariam ao ano 2000, ninguém se preocupou em aprofundar tais recursos mas como sua vida foi se prolongando, foram aparecendo melhorias e ferramentas mais afinadas como Summer, Clipper 5 e seus RDDs até chegarmos ao que vemos hoje com Leto e outras alternativas de suporte a vida do DBF.

Se iremos continuar usando ainda pelos proximos 10 anos?

Digo que provavelmente sim, pois o tempo voa e os arranjos feitos sobre os RDDs poderão proporcionar o uso de todo o tipo de arquivo de dados, inclusive o vovo DBF.

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 12 Jun 2008 18:07
por gvc
[mestre Rochinha]
O nome original era Vulcan -Planeta natal do Sr. Spoke, Jornada nas Estrelas.
Para vender, a Aston & Tate mudou o nome para DBase II. Era em assembler e rodava em CP/M.

possuia manipulacao compartilhada
- ??? Juro que não entendi. Antes do DBase III Plus, não dava para compartilhar arquivos. E eu juro que não consegui compartilhar mesmo com ele.

Na verdade, os No-Break já existiam, só que o preço era assustador. Funcionavam com baterias externas, normalmente as de carro. Tb existiam/existem os gerados.

A primeira rede que eu "coloquei a mão" foi uma Novell Lite. Seu executável tinha que ter atributo R/O. Apesar de falarem bem da Lantastic, eu nunca consegui trabalhar com ela. Tinha uma outra que trabalhava com 8 bits e ligava só duas máquinas. O cara que eu ví usando deixava mais desligado do que ligado. Era uma bomba.

Qto ao tempo de vida, é difícil prever qualquer coisa, mas temos muitos sistemas legados e alguns clientes não querem invertir em um SGDB. Existem alguns SGDB gratuitos, mas ainda tem que investir em uma máquina só para ele. Não é aconselhavel rodar o banco em uma máquina que esta sendo usada para trabalho normal. O usuário faz algo, trava a máquina e o banco fica travado para todos os usuários.

Juro que dá para ficar a noite e a madrugada toda falando sobre isso (no bar, é claro), mas vamos manter os "pés no chão".

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 14 Jul 2008 18:38
por gilsonpaulo
Caro rochinha, ao tentar compilar o codigo que o nosso amigo Farley Ribeiro postou ocorre o seguinte erro.
Tem alguma ideia do que poder ser, sendo que atualizei a adoxb.ch e adoxb.prg e customer.prg

MAKE Version 5.2 Copyright (c) 1987, 2000 Borland
HARBOUR customer.prg -oobj\customer.c -n -m -b -iC:\xharbour\INCLUDE;C:\FWH\INCLUDE;C:\xharbour\include;C:\borland\bcc55\include
xHarbour Compiler build 1.1.0 (SimpLex)
Copyright 1999-2007, http://www.xharbour.org http://www.harbour-project.org/
Compiling 'customer.prg'...

100

100

100

200

300

400

500

600

700

800

900

1000

100

200

100

200

100

200

300

400

500

600

700

800

900

1000

1100

1200

1300

1400

1500

adoxb.ch(52) Error E0017 Ambiguous match pattern in #translate/#command

100

200

300

100

200

300

400

adoxb.ch(52) Error E0017 Ambiguous match pattern in #translate/#command

100

200

300

100

200

300

400

500

600

700

800

2 errors

No code generated

** error 1 ** deleting obj\customer.c

Para efeito de duvidar segue o adoxb.prg:
**************************************************************************************
*
* Cursor Location
*
* adUseServer           2 Atua no lado servidor
* adUseClient           3 Atua no lado cliente
*
* Cursor Type
*
* adOpenForwardOnly     0 O cursor so navega para frente. Bom para listar dados
* adOpenKeyset          1 Nao permite ver os registro adicionados e eliminados
* adOpenDynamic         2 Aceita todas operacoes do utilizador e dos outros
* adOpenStatic          3 Serve apenas para procurar dados ou gerar relatorios
*
* Lock Type Enum - Contantes de Seguranca
*
* adLockReadOnly        1 Apenas pode ler os registros
* adLockPessimistic     2 O fornecedor dos dados fecha o registro apos edicao
* adLockOptimistic      3 O fornecedor dos dados fecha o registro apos chamar o update
* adLockBatchOptimistic 4 O mesmo que Optmistic mas para sequencia de comandos
*
* AllowNumsEnum
*
* adIndexNullsAllow     0
* adIndexNullsDisallow  1
* adIndexNullsIgnore    2
* adIndexNullsIgnoreAny 4
*
**************************************************************************************

#command ADO CONNECT <StrDriver> [<disconected:DISCONECTED>] => ADOCONNECT( <StrDriver>, [<.disconected.>] )
#command ADO DISCONNECT             => ADODISCONNECT()
#command ADO APPEND BLANK           => ADOAPPEND()
#command ADO EDIT                   => ADOEDIT()
#command ADO COMMIT [<save:SAVE>]   => ADOCOMMIT( [<.save.>] )
#command ADO SKIP                   => ADOSKIP( 1 )
#command ADO SKIP <num>             => ADOSKIP( <num> )
#command ADO DELETE                 => ADODELETE()
#command ADO REPLACE <f1> WITH <v1> => ADOREPLACE( <(f1)>, <v1> )
#command ADO GOTOP                  => ADOGOTOP()
#command ADO GOBOTTOM               => ADOGOBOTTOM()
#command ADO SET FILTER TO          => ADOSETFILTER()
#command ADO SET FILTER TO <xpr>    => ADOSETFILTER( <xpr> )
#command ADO SAVE <(CfILE)>         => ADOSAVE( <(CfILE)> )
#command ADO EXECUTE <*Sql*>        => ADOEXECUTE( <(Sql)> )
#command ADO LOCATE <xpr>           => ADOLOCATE( <xpr> )
#command ADO REGLOCK                => ADOREGLOCK()
#command ADO CLOSE                  => ADOCLOSE()
#command ADO CLOSE ALL              => ADOCLOSEALL()
#command ADO USE                    => ADOUSE()
#command ADO USE <(StrDatabase)> [<shared:SHARED>] => ADOUSE( <(StrDatabase)>, [<.shared.>] )
#command ADO SORT ON [<(cF)>][<(x)>]=> ADOSORT( [<(cF)>][, <(x)>] )
#command ADO SELECT <(cRecordSet)>  => ADOSELECT( <(cRecordSet)> )

#xcommand ADO SQL DELETE <*cSQL*>   => ADOEXECUTE( 'DELETE '+ <(cSQL)> )
#xcommand ADO SQL INSERT <*cSQL*>   => ADOEXECUTE( 'INSERT '+ <(cSQL)> )
#xcommand ADO SQL UPDATE <*cSQL*>   => ADOEXECUTE( 'UPDATE '+ <(cSQL)> )
#xcommand ADO SQL ALTER  <*cSQL*>   => ADOEXECUTE( 'ALTER ' + <(cSQL)> )
#xcommand ADO SQL CREATE <*cSQL*>   => ADOEXECUTE( 'CREATE '+ <(cSQL)> )
#xcommand ADO SQL DROP   <*cSQL*>   => ADOEXECUTE( 'DROP '  + <(cSQL)> )
#xcommand ADO SQL RENAME <*cSQL*>   => ADOEXECUTE( 'RENAME '+ <(cSQL)> )
#xcommand ADO SQL UPDATE <*cSQL*>   => ADOEXECUTE( 'UPDATE '+ <(cSQL)> )
#xcommand ADO SQL GRANT  <*cSQL*>   => ADOEXECUTE( 'GRANT ' + <(cSQL)> )
#xcommand ADO SQL REVOKE <*cSQL*>   => ADOEXECUTE( 'REVOKE '+ <(cSQL)> )

/*---- Lock Type Enum ----*/
#define adLockReadOnly        1
#define adLockPessimistic     2
#define adLockOptimistic      3
#define adLockBatchOptimistic 4

/*---- AllowNumsEnum ----*/
#define adIndexNullsAllow     0
#define adIndexNullsDisallow  1
#define adIndexNullsIgnore    2
#define adIndexNullsIgnoreAny 4

/*---- CursorTypeEnum Values ----*/
#define adOpenForwardOnly 0
#define adOpenKeyset 1
#define adOpenDynamic 2
#define adOpenStatic 3

/*---- LockTypeEnum Values ----*/
#define adLockReadOnly 1
#define adLockPessimistic 2
#define adLockOptimistic 3
#define adLockBatchOptimistic 4

/*---- CursorLocationEnum Values ----*/
#define adUseServer 2
#define adUseClient 3

/*---- DataTypeEnum Values ----*/
#define adEmpty 0
#define adTinyInt 16
#define adSmallInt 2
#define adInteger 3
#define adBigInt 20
#define adUnsignedTinyInt 17
#define adUnsignedSmallInt 18
#define adUnsignedInt 19
#define adUnsignedBigInt 21
#define adSingle 4
#define adDouble 5
#define adCurrency 6
#define adDecimal 14
#define adNumeric 131
#define adBoolean 11
#define adError 10
#define adUserDefined 132
#define adVariant 12
#define adIDispatch 9
#define adIUnknown 13
#define adGUID 72
#define adDate 7
#define adDBDate 133
#define adDBTime 134
#define adDBTimeStamp 135
#define adBSTR 8
#define adChar 129
#define adVarChar 200
#define adLongVarChar 201
#define adWChar 130
#define adVarWChar 202
#define adLongVarWChar 203
#define adBinary 128
#define adVarBinary 204
#define adLongVarBinary 205
#define adChapter 136
#define adFileTime 64
#define adPropVariant 138
#define adVarNumeric 139
#define adArray &H2000

/*---- GetRowsOptionEnum Values ----*/
#define adGetRowsRest -1

/*---- PositionEnum Values ----*/
#define adPosUnknown -1
#define adPosBOF -2
#define adPosEOF -3

/*---- BookmarkEnum Values ----*/
#define adBookmarkCurrent 0
#define adBookmarkFirst 1
#define adBookmarkLast 2

/*---- MarshalOptionsEnum Values ----*/
#define adMarshalAll 0
#define adMarshalModifiedOnly 1

/*---- AffectEnum Values ----*/
#define adAffectCurrent 1
#define adAffectGroup 2
#define adAffectAllChapters 4

/*---- ResyncEnum Values ----*/
#define adResyncUnderlyingValues 1
#define adResyncAllValues 2

/*---- CompareEnum Values ----*/
#define adCompareLessThan 0
#define adCompareEqual 1
#define adCompareGreaterThan 2
#define adCompareNotEqual 3
#define adCompareNotComparable 4

/*---- FilterGroupEnum Values ----*/
#define adFilterNone 0
#define adFilterPendingRecords 1
#define adFilterAffectedRecords 2
#define adFilterFetchedRecords 3
#define adFilterConflictingRecords 5

/*---- SearchDirectionEnum Values ----*/
#define adSearchForward 1
#define adSearchBackward -1

/*---- PersistFormatEnum Values ----*/
#define adPersistADTG 0
#define adPersistXML 1

/*---- StringFormatEnum Values ----*/
#define adClipString 2

/*---- ConnectPromptEnum Values ----*/
#define adPromptAlways 1
#define adPromptComplete 2
#define adPromptCompleteRequired 3
#define adPromptNever 4

/*---- ConnectModeEnum Values ----*/
#define adModeUnknown 0
#define adModeRead 1
#define adModeWrite 2
#define adModeReadWrite 3
#define adModeShareDenyRead 4
#define adModeShareDenyWrite 8
#define adModeShareExclusive 12
#define adModeShareDenyNone 16

/*---- EventReasonEnum Values ----*/
#define adRsnAddNew 1
#define adRsnDelete 2
#define adRsnUpdate 3
#define adRsnUndoUpdate 4
#define adRsnUndoAddNew 5
#define adRsnUndoDelete 6
#define adRsnRequery 7
#define adRsnResynch 8
#define adRsnClose 9
#define adRsnMove 10
#define adRsnFirstChange 11
#define adRsnMoveFirst 12
#define adRsnMoveNext 13
#define adRsnMovePrevious 14
#define adRsnMoveLast 15

/*---- SchemaEnum Values ----*/
#define adSchemaProviderSpecific -1
#define adSchemaAsserts 0
#define adSchemaCatalogs 1
#define adSchemaCharacterSets 2
#define adSchemaCollations 3
#define adSchemaColumns 4
#define adSchemaCheckConstraints 5
#define adSchemaConstraintColumnUsage 6
#define adSchemaConstraintTableUsage 7
#define adSchemaKeyColumnUsage 8
#define adSchemaReferentialConstraints 9
#define adSchemaTableConstraints 10
#define adSchemaColumnsDomainUsage 11
#define adSchemaIndexes 12
#define adSchemaColumnPrivileges 13
#define adSchemaTablePrivileges 14
#define adSchemaUsagePrivileges 15
#define adSchemaProcedures 16
#define adSchemaSchemata 17
#define adSchemaSQLLanguages 18
#define adSchemaStatistics 19
#define adSchemaTables 20
#define adSchemaTranslations 21
#define adSchemaProviderTypes 22
#define adSchemaViews 23
#define adSchemaViewColumnUsage 24
#define adSchemaViewTableUsage 25
#define adSchemaProcedureParameters 26
#define adSchemaForeignKeys 27
#define adSchemaPrimaryKeys 28
#define adSchemaProcedureColumns 29
#define adSchemaDBInfoKeywords 30
#define adSchemaDBInfoLiterals 31
#define adSchemaCubes 32
#define adSchemaDimensions 33
#define adSchemaHierarchies 34
#define adSchemaLevels 35
#define adSchemaMeasures 36
#define adSchemaProperties 37
#define adSchemaMembers 38
#define adSchemaTrustees 39

/*---- FieldStatusEnum Values ----*/
#define adFieldOK 0
#define adFieldCantConvertValue 2
#define adFieldIsNull 3
#define adFieldTruncated 4
#define adFieldSignMismatch 5
#define adFieldDataOverflow 6
#define adFieldCantCreate 7
#define adFieldUnavailable 8
#define adFieldPermissionDenied 9
#define adFieldIntegrityViolation 10
#define adFieldSchemaViolation 11
#define adFieldBadStatus 12
#define adFieldDefault 13
#define adFieldIgnore 15
#define adFieldDoesNotExist 16
#define adFieldInvalidURL 17
#define adFieldResourceLocked 18
#define adFieldResourceExists 19
#define adFieldCannotComplete 20
#define adFieldVolumeNotFound 21
#define adFieldOutOfSpace 22
#define adFieldCannotDeleteSource 23
#define adFieldReadOnly 24
#define adFieldResourceOutOfScope 25
#define adFieldAlreadyExists 26
#define adFieldPendingInsert &H10000
#define adFieldPendingDelete &H20000
#define adFieldPendingChange &H40000
#define adFieldPendingUnknown &H80000
#define adFieldPendingUnknownDelete &H100000

/*---- SeekEnum Values ----*/
#define adSeekFirstEQ &H1
#define adSeekLastEQ &H2
#define adSeekAfterEQ &H4
#define adSeekAfter &H8
#define adSeekBeforeEQ &H10
#define adSeekBefore &H20

/*---- ADCPROP_UPDATECRITERIA_ENUM Values ----*/
#define adCriteriaKey 0
#define adCriteriaAllCols 1
#define adCriteriaUpdCols 2
#define adCriteriaTimeStamp 3

/*---- ADCPROP_ASYNCTHREADPRIORITY_ENUM Values ----*/
#define adPriorityLowest 1
#define adPriorityBelowNormal 2
#define adPriorityNormal 3
#define adPriorityAboveNormal 4
#define adPriorityHighest 5

/*---- ADCPROP_AUTORECALC_ENUM Values ----*/
#define adRecalcUpFront 0
#define adRecalcAlways 1

/*---- ADCPROP_UPDATERESYNC_ENUM Values ----*/

/*---- ADCPROP_UPDATERESYNC_ENUM Values ----*/

/*---- MoveRecordOptionsEnum Values ----*/
#define adMoveUnspecified -1
#define adMoveOverWrite 1
#define adMoveDontUpdateLinks 2
#define adMoveAllowEmulation 4

/*---- CopyRecordOptionsEnum Values ----*/
#define adCopyUnspecified -1
#define adCopyOverWrite 1
#define adCopyAllowEmulation 4
#define adCopyNonRecursive 2

/*---- StreamTypeEnum Values ----*/
#define adTypeBinary 1
#define adTypeText 2

/*---- LineSeparatorEnum Values ----*/
#define adLF 10
#define adCR 13
#define adCRLF -1

/*---- StreamOpenOptionsEnum Values ----*/
#define adOpenStreamUnspecified -1
#define adOpenStreamAsync 1
#define adOpenStreamFromRecord 4

/*---- StreamWriteEnum Values ----*/
#define adWriteChar 0
#define adWriteLine 1

/*---- SaveOptionsEnum Values ----*/
#define adSaveCreateNotExist 1
#define adSaveCreateOverWrite 2

/*---- FieldEnum Values ----*/
#define adDefaultStream -1
#define adRecordURL -2

/*---- StreamReadEnum Values ----*/
#define adReadAll -1
#define adReadLine -2

/*---- RecordTypeEnum Values ----*/
#define adSimpleRecord 0
#define adCollectionRecord 1
#define adStructDoc 2


Adoxb.prg
****************************************************************************************
*
* CursorType
*
* adOpenForwardOnly     0 O cursor so navega para frente. Bom para listar dados
* adOpenKeyset          1 Nao permite ver os registro adicionados e eliminados
* adOpenDynamic         2 Aceita todas operacoes do utilizador e dos outros
* adOpenStatic          3 Serve apenas para procurar dados ou gerar relatorios
*
* LockTypeEnum - Contantes de Seguranca
*
* adLockReadOnly        1 Apenas pode ler os registros
* adLockPessimistic     2 O fornecedor dos dados fecha o registro apos edicao
* adLockOptimistic      3 O fornecedor dos dados fecha o registro apos chamar o update
* adLockBatchOptimistic 4 O mesmo que Optmistic mas para sequencia de comandos
*
* SortOrdEnum - Contantes de Ordenacao
*
* adSortAscending       1 Ordem ascendente
* adSortDescending      2 Ordem descendente
*
****************************************************************************************

#include "adoxb.ch"
#ifndef _ADO_xHarbour_
        #define _ADO_Harbour_
#endif

*
*---------------------------------------------------------
Function ADOSetRDD( cRDDName )
   public cADORDD := iif( cRDDName=NIL, "DBF", cRDDName )
   PUBLIC aRecordSet, oRecordSet, nConnection, nRecordSet, aIndexOrder, nIndexOrder, ;
          StrConnection, aADOConection, oADOConection, oADOErrDescription, oADOIndex, ;
          oADOCatalog, oADOTable, oADOStream
   nConnection        := 1
   aADOConection      := {}
   oADOConection      := Array(10)
   return cADORDD

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOConnect( StrDriver )
   //PUBLIC aRecordSet, oRecordSet, nRecordSet, aIndexOrder, nIndexOrder, StrConnection, oADOConection, oADOErrDescription, oADOIndex, oADOCatalog, oADOTable
   aRecordSet         := {}
   oRecordSet         := Array(50)
   oADOIndex          := Array(10)
   nRecordSet         := 0
   aIndexOrder        := {}
   nIndexOrder        := 1
   StrConnection      := StrDriver
   AADD( aADOConection, StrDriver ) // Controla numero de conexoes
   nConnection        := len( aADOConection )
   oADOConection[nConnection] := TOLEAUTO():New("ADODB.connection")
   oADOStream         := TOLEAUTO():New("ADODB.Stream")
   oADOErrDescription := TOLEAUTO():New("ADODB.Err")
   oADOIndex          := TOLEAUTO():New("ADOX.Index")
   oADOCatalog        := TOLEAUTO():New("ADOX.Catalog")
   oADOConection[nConnection]:CommandTimeOut    := 200
   oADOConection[nConnection]:ConnectionTimeOut := 10
   oADOConection[nConnection]:CursorLocation    := adUseClient
   oADOConection[nConnection]:Mode              := adModeShareDenyNone // adModeRead 1, adModeWrite 2, adModeReadWrite 3
   oADOConection[nConnection]:Open( StrConnection )
   return 'connected'
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADODBCREATE( cDatabase )
   oADOCreateCatalog := TOLEAUTO():New("ADOX.Catalog")
   StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + cDatabase
   oADOCreateCatalog:Create( StrConnection )
   return .t.

Function ADOCREATE( cTable, aFields )
   //local oADOTable := TOLEAUTO():New("ADOX.Table")
   //oADOCatalog:ActiveConnection := StrConnection
   //oADOTable:Name := cTable
   //for i = 1 to len( aFields )
   //    oADOTable:Columns:Append( aFields[i][1], GetFieldType(aFields[i][2]), aFields[i][3] )
   //next
   //oADOCatalog:Tables:Append( oADOTable )
   //oADOTable:Close()
   //oADOTable:End()
   //
   //oADOCreateCatalog := TOLEAUTO():New("ADOX.Catalog")
   //oADOCreateTable   := TOLEAUTO():New("ADOX.Table")
   //oADOCreateCatalog:Create( StrConnection )
   //oADOCreateTable:Name := cTable
   //for i = 1 to len( aFields )
   //    oADOCreateTable:Columns:Append( aFields[i][1], GetFieldType(aFields[i][2]) ) //, aFields[i][3] )
   //next
   //oADOCreateCatalog:Tables:Append( cTable )
   //return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOIndex( cTable, cIDXField, cIDXName, cIDXAscend )
   local adSortAscending := 1, adSortDescending := 2
   local oADOTable := TOLEAUTO():New("ADOX.Table")
   cIDXAscend := iif( cIDXAscend = nil, .t., cIDXAscend )
   if .not. ADOFILE( "INDEXES" )
      oADOCatalog:ActiveConnection := StrConnection
      oADOTable:Name := "INDEXES"
      oADOTable:Columns:Append( "NumField", adInteger, 20 )
      oADOTable:Columns:Append( "TextField", adVarWChar, 20 )
      oADOCatalog:Tables:Append( oADOTable )
   endif
   AADD( aIndexOrder, cTable )
   nIndexOrder        := len( aIndexOrder )
   oADOIndex[nIndexOrder] := TOLEAUTO():New("ADOX.Index")
   oADOIndex[nIndexOrder]:Name       := cIDXName
   oADOIndex[nIndexOrder]:Columns:Append( cIDXField )
   oADOIndex[nIndexOrder]:Columns( cIDXField ):SortOrder = iif( cIDXAscend, adSortAscending, adSortDescending )
   //oADOIndex[nIndexOrder]:PrimaryKey := .t.
   //oADOIndex[nIndexOrder]:Unique     := .t.
   oADOIndex[nIndexOrder]:IndexNulls := adIndexNullsAllow
   // Adciona o indice criado ao catalogo
   //oADOCatalog:Tables( cTable ) //:Indexes:Append( oADOIndex[nIndexOrder] )
   oADOTable:Indexes:Append( oADOIndex )
   oADOCatalog:Tables:Append( oADOTable )
   oADOTable:Close()
   oADOTable:End()
   return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOUse( cDatabase, lShared )
   local oError
   if cADORDD = "XML"
      cDatabase := cDatabase + ".xml"
   endif
   if cADORDD = "XLS"
      cDatabase := "[" + cDatabase + "$]"
   endif
   if cDatabase = NIL
      oRecordSet[nRecordSet]:Close()
      oRecordSet[nRecordSet]:End()
   else
      AADD( aRecordSet, cDatabase )
      cRecordSet := cDatabase
      nRecordSet := len( aRecordSet )
      oRecordSet[nRecordSet] := TOleAuto():New( "ADODB.Recordset" )
      if cADORDD = "XML"
         oRecordSet[nRecordSet]:Open( cDatabase, StrConnection, 1, 3 )
      else
         oRecordSet[nRecordSet]:CacheSize      := 50
         oRecordSet[nRecordSet]:CursorLocation := adUseClient
         if lShared = .t.
            oRecordSet[nRecordSet]:CursorType  := adOpenDynamic
            oRecordSet[nRecordSet]:LockType    := adLockOptimistic
         else
            oRecordSet[nRecordSet]:CursorType  := adOpenStatic
            oRecordSet[nRecordSet]:LockType    := adLockPessimistic
         endif
         oRecordSet[nRecordSet]:Open( "Select * from " + cDatabase, StrConnection, iif(lShared=.t.,3,1), 3 )
      endif
      ADOGOTOP() // oRecordSet[nRecordSet]:MoveFirst()
   endif
   * CursorType
   *
   * adOpenForwardOnly     0 O cursor so navega para frente. Bom para listar dados
   * adOpenKeyset          1 Nao permite ver os registro adicionados e eliminados
   * adOpenDynamic         2 Aceita todas operacoes do utilizador e dos outros
   * adOpenStatic          3 Serve apenas para procurar dados ou gerar relatorios
   *
   * LockTypeEnum - Contantes de Seguranca
   *
   * adLockReadOnly        1 Apenas pode ler os registros
   * adLockPessimistic     2 O fornecedor dos dados fecha o registro apos edicao
   * adLockOptimistic      3 O fornecedor dos dados fecha o registro apos chamar o update
   * adLockBatchOptimistic 4 O mesmo que Optmistic mas para sequencia de comandos
   return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
#ifdef _ADO_Harbour_
Function ADOConnectRemote( StrDSN, StrServer )
   PUBLIC aRecordSet, oRecordSet, nRecordSet, aIndexOrder, nIndexOrder, StrConnection, oADOConection, oADOErrDescription, oADOIndex, oADOCatalog
   aRecordSet    := {}
   oRecordSet    := Array(50)
   oADOIndex     := Array(10)
   nRecordSet    := 0
   aIndexOrder   := {}
   nIndexOrder   := 1
   StrConnection := StrDriver
   oADOConection := TOLEAUTO():New("RDS.DataControl")
   oADOConection:ExecuteOptions := adcExecAsync
   oADOConection:Connect        := "DSN=" + StrDriver
   oADOConection:Server         := StrServer
   oADOConection:Refresh()
   return .t.
   #endif _ADO_Harbour_

*
*---------------------------------------------------------
Function ADOConnected()
   if !(valtype(oADOConection[nConnection]) = "O")
      return .f. // Nao foi definido o Objecto
   endif
   if valtype(oADOConection) = "L"
      return .f. // Se ja existe a variavel mas nao foi definida como Objeto
   endif
   cADOConectionState := oADOConection[nConnection]:State
   return iif( cADOConectionState=1, .t., .f. )

*
*---------------------------------------------------------
Function MsgAlert( cMsg )
   Alert( cMsg )
   return .t.

*
*---------------------------------------------------------
Function ADOSetDriver( StrDatabase, StrSenha, StrUsuario, StrServer, StrPort )
   public cADORDD := iif( cRDDName=NIL, "DBASE", cRDDName )
   StrConnection := ""
   StrDriver     := ADORDDDefault()
   if StrDriver = "DBASE"
      StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";Extended Properties=dBASE IV;"
   endif
   if StrDriver = "ACCESS" // ADOMDB
      StrConnection := "Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";"
   endif
   if StrDriver = "FIREBIRD" // ADOGDB
      StrConnection := "DRIVER=Firebird/InterBase(r) driver; UID="+StrSenha+"; PWD="+StrUsuario+"; DBNAME="+StrDatabase
   endif
   if StrDriver = "MYSQL" // ADOMySQL
      StrConnection := "driver={MySQL ODBC 3.51 Driver};database=" + StrDatabase + ;
                       ";server=" + StrServer + ;
                       ";uid=" + StrUsuario + ;
                       ";pwd=" + StrSenha + ;
                       ";option=35"
   endif
   if StrDriver = "PARADOX" // ADOPX
      StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";Extended Properties=Paradox 5.x;"
   endif
   if StrDriver = "SQL"
      StrConnection := "Provider=MSDASQL;Data Source=SQLExpress;User ID=Administrador;Password=konectiva;"
   endif
    if ADORDDDefault() = "XMLDB" // ADOXML
       StrConnection := "Provider=MSPersist"
    endif
    if ADORDDDefault() = "XML" // ADOXML
       StrConnection := "Provider=MSDAOSP;Data Source=MSXML2.DSOControl.2.6"
    endif
   if StrDriver = "XLS" // ADOXLS
      StrConnection := [Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\adoxls.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1"]
   endif
   if StrDriver = "REMOTE" // ADORDS
      StrConnection := "Provider=MS Remote;Remote Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";Remote Server=" + StrServer
   endif
   return StrConnection

*
*---------------------------------------------------------
Function ADORDDDefault(qADORDD)
   default cADORDD := "Nenhum RDD especificado."
   //if (qADORDD = nil)
   //   cADORDD := qADORDD
   //endif
   return cADORDD

*
*---------------------------------------------------------
Function ADOFile( cFile )
   if cADORDD = "XML" .or. cADORDD = "XLS"
      return file( cFile )
   else
      oADOCatalog := oADOConection[nConnection]:OpenSchema(adSchemaTables)
      do while .not. oADOCatalog:EOF()
         if upper(alltrim(oADOCatalog:Fields( "TABLE_NAME" ):Value)) = upper(alltrim(cFile))
            return .t.
         endif
         oADOCatalog:MoveNext()
      enddo
   endif
   return .f.

*
*---------------------------------------------------------
Function ADOAlias()
   if nRecordSet < 1
      return ""
   else
      return aRecordSet[nRecordSet]
   endif

*
*---------------------------------------------------------
Function ADOFCount()
   if nRecordSet < 1
      return ""
   else
      return aRecordSet[nRecordSet]:Fields:Count()
   endif

*
*---------------------------------------------------------
Function ADOBEGINTRANSACTION()
   oADOConection[nConnection]:BeginTrans()
   return .t.

*
*---------------------------------------------------------
Function ADOCOMMITTRANSACTION()
   oADOConection[nConnection]:CommitTrans()
   return .t.

*
*---------------------------------------------------------
Function GetFieldType(FieldType)
   do Case
      Case FieldType = "C"
           return adVarWChar
      Case FieldType = "N"
           return adInteger
      Case FieldType = "M"
           return adText
      Case FieldType = "L"
           return adBoolean
      Case FieldType = "D"
           return adDate
   Endcase

*
*---------------------------------------------------------
Function ADOSetOrder( nIDXOrder )
   oRecordSet[nRecordSet]:Index = oADOIndex[nIDXOrder]:Name
   return .t.

*
*---------------------------------------------------------
Function ADODISConnect()
   oADOConection[nConnection]:Close()
   oADOErrDescription:Close()
   oADOIndex:Close()
   oADOCatalog:Close()
   oADOConection[nConnection]:End()
   oADOErrDescription:End()
   oADOIndex:End()
   oADOCatalog:End()
   return .t.

*
*---------------------------------------------------------
Function ADOAppend()
   oRecordSet[nRecordSet]:AddNew()
   return .t.

*
*---------------------------------------------------------
Function ADOEdit()
   oRecordSet[nRecordSet]:Edit()
   return .t.

*
*---------------------------------------------------------
Function ADOCommit( lSave )
   lSave := iif( lSave = nil, .f., lSave )
   oRecordSet[nRecordSet]:Update()
   if lSave
      oRecordSet[nRecordSet]:Save( alltrim(aRecordSet[nRecordSet]), adPersistXML )
   endif
   marca := oRecordSet[nRecordSet]:BookMark
   oRecordSet[nRecordSet]:Requery()
   oRecordSet[nRecordSet]:BookMark = marca
   return .t.

*
*---------------------------------------------------------
Function ADORequery()
   oRecordSet[nRecordSet]:Requery()
   return .t.

*
*---------------------------------------------------------
Function ADOReSync()
   oRecordSet[nRecordSet]:ReSync()
   return .t.

*
*---------------------------------------------------------
Function ADOUpdateBatch()
   oRecordSet[nRecordSet]:UpdateBatch()
   return .t.

*
*---------------------------------------------------------
Function ADOCommitAll()
   for i = 1 to len(aRecordSet)
       oRecordSet[nRecordSet]:Update()
   next
   return .t.

*
*---------------------------------------------------------
Function ADOSave( cfile )
   oRecordSet[nRecordSet]:Save( cFile, adPersistXML )
   return .t.

*
*---------------------------------------------------------
Function ADOReglock()
   //oRecordSet[nRecordSet]:CursorLocation := 2
   //oRecordSet[nRecordSet]:CursorType     := 0
   //oRecordSet[nRecordSet]:LockType       := 3
   return .t.

*
*---------------------------------------------------------
Function ADOSkip( nSkip )
   LOCAL nRec := oRecordSet[nRecordSet]:AbsolutePosition()
   oRecordSet[nRecordSet]:Move( iif( nSkip = nil, 1, nSkip ) )
   IF oRecordSet[nRecordSet]:EOF(); oRecordSet[nRecordSet]:MoveLast() ; ENDIF
   IF oRecordSet[nRecordSet]:BOF(); oRecordSet[nRecordSet]:MoveFirst(); ENDIF
   return oRecordSet[nRecordSet]:AbsolutePosition() - nRec

*
*---------------------------------------------------------
Function ADODelete()
   oRecordSet[nRecordSet]:Delete()
   oRecordSet[nRecordSet]:Move( -1 )
   if cADORDD = "XML" // ".XML" $ upper(aRecordSet[nRecordSet])
      oRecordSet[nRecordSet]:Save( alltrim(aRecordSet[nRecordSet]), adPersistXML )
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOGoTo( nRec )
   //oRecordSet[nRecordSet]:BookMark :=  nRec
   return .t.

*
*---------------------------------------------------------
Function ADOGoTop()
   if .not. ADOBof()
      if ADORecCount() > 0
         oRecordSet[nRecordSet]:MoveFirst()
      endif
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOGoBottom()
   if .not. ADOEof()
      if ADORecCount() > 0
         oRecordSet[nRecordSet]:MoveLast()
      endif
   endif
   return .t.

*
*---------------------------------------------------------
Function ADORecno()
   if nRecordSet < 0
      return 0
   else
      return oRecordSet[nRecordSet]:AbsolutePosition()
   endif

*
*---------------------------------------------------------
Function ADORecCount()
   if nRecordSet < 1
      return 0
   else
      nRecord := oRecordSet[nRecordSet]:AbsolutePosition()
      nRecord := iif(nRecord=nil,-1,nRecord)
      if nRecord < 1 //.or. .not. ( oRecordSet[nRecordSet]:EOF() = oRecordSet[nRecordSet]:BOF() )
         return 0
      else
         return oRecordSet[nRecordSet]:RecordCount()
      endif
   endif

*
*---------------------------------------------------------
Function ADOSetFilter( xpr )
   if xpr = NIL
      oRecordSet[nRecordSet]:Filter := 0
   else
      oRecordSet[nRecordSet]:Filter := xpr
   endif
   return .t.

*
*---------------------------------------------------------
Function ADODeleted( criterio )
   if oRecordSet[nRecordSet]:Status = adRecDeleted
      return .t.
   endif
   return .f.

*
*---------------------------------------------------------
Function ADOClose()
   _RecordSet := len( aRecordSet )
   ADEL( aRecordSet, nRecordSet )
   ASIZE( aRecordSet, _RecordSet-1 )
   oRecordSet[nRecordSet]:End()
   return .t.

*
*---------------------------------------------------------
Function ADOCloseAll()
   for i = 1 to len(aRecordSet)
       oRecordSet[nRecordSet]:End()
   next
   aRecordSet := {}
   nRecordSet := 0
   return .t.

*
*---------------------------------------------------------
Function ADOExecute( cSql )
   aADODefines := {}
   AADD( aADODefines, { "VOID("   , "0(" } )
   AADD( aADODefines, { "BYTE("   , "1(" } )
   AADD( aADODefines, { "CHAR("   , "2(" } )
   AADD( aADODefines, { "WORD("   , "3(" } )
   AADD( aADODefines, { "INT("    , "7(" } )
   AADD( aADODefines, { "BOOLEAN(", "5(" } )
   AADD( aADODefines, { "HDC("    , "6(" } )
   AADD( aADODefines, { "LONG("   , "7(" } )
   AADD( aADODefines, { "STRING(" , "8(" } )
   AADD( aADODefines, { "LPSTR("  , "9(" } )
   AADD( aADODefines, { "PTR("    ,"10(" } )
   AADD( aADODefines, { "DOUBLE(" ,"11(" } )
   AADD( aADODefines, { "DWORD("  ,"12(" } )
   for i = 1 to len( aADODefines )
       cSql := StrTran( cSql, aADODefines[i][2], aADODefines[i][1] )
   next
   //adolog( cSql )
   oADOConection[nConnection]:Execute( cSql )
   return .t.

Function ADOInsertInto( cSql )
   cSql := StrTran( cSql, '"', "'" )
   cSql := "INSERT INTO " + cSql
//? cSql
   oADOConection[nConnection]:Execute( cSql )
   return .t.

*
*---------------------------------------------------------
Function ADOBOF()
   return iif( ADORecCount() > 0, oRecordSet[nRecordSet]:Bof, .t. )

*
*---------------------------------------------------------
Function ADOEOF()
   return iif( ADORecCount() > 0, oRecordSet[nRecordSet]:Eof, .t. )

*
*---------------------------------------------------------
Function ADOFOUND()
   return !oRecordSet[nRecordSet]:Eof

*
*---------------------------------------------------------
Function ADOFind( criterio )
   ADOLocate( criterio )
   return .t.

*
*---------------------------------------------------------
Function ADOLocate( criterio )
   local _nBookMark := oRecordSet[nRecordSet]:Bookmark
   oRecordSet[nRecordSet]:MoveFirst()
   oRecordSet[nRecordSet]:Find( criterio )
   if oRecordSet[nRecordSet]:Eof()
      oRecordSet[nRecordSet]:BookMark := _nBookmark
      return .f.
   else
      return .t.
   endif

*
*---------------------------------------------------------
Function ADOSort( cField, nModo )
   if valtype(cField)='N'
      cField := oRecordSet[nRecordSet]:Fields( cStrField ):Name
   endi
   if cField = Nil
      Return upper(oRecordSet[nRecordSet]:Sort)
   else
      oRecordSet[nRecordSet]:Sort := cField + iif( nModo = NIL, " ASC", " DESC" )
      oRecordSet[nRecordSet]:MoveFirst()
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOFiles( cTable )
   return iif(oRecordSet[nRecordSet]:Table(cTable)==cTable,.t.,.f.)

*
*---------------------------------------------------------
Function ADOAREAS()
   return nRecordSet

*
*---------------------------------------------------------
Function ADOSelect( cRecordSet )
   if cRecordSet = nil
   else
      if cADORDD = "XLS"
         cRecordSet := "[" + cRecordSet + "$]"
      endif
      nRecordSet := ASCAN( aRecordSet, cRecordSet )
      nRecordSet := iif( nRecordSet = 0, 1, nRecordSet )
   endif
   //ADOGotop()
   return nRecordSet

*
*---------------------------------------------------------
Function ADOLOG( cMensagem )
   local nHandle
   if .not. file( "ADOERRO.TXT" )
      nHandle := fcreate("ADOERRO.TXT",0)
   else
      nHandle := fopen("ADOERRO.TXT",1)
      length  := fseek(nHandle,0,2)
      fseek(nHandle,length)
   endif
   fwrite(nHandle, cMensagem )
   fclose(nHandle)
   return NIL

*
*---------------------------------------------------------
Function ADOReplace( cCampo, xDado )
   LOCAL uVal,xValor,nTipo,cType,nLong,cQuery,lRepassa := .f., lBlob := .f.,;
         StrFileName
   uVal  := oRecordSet[nRecordSet]:Fields( cCampo ):Value
   nTipo := oRecordSet[nRecordSet]:Fields( cCampo ):Type
   cType := TypeDat(nTipo,cCampo)
   nLong := oRecordSet[nRecordSet]:Fields( cCampo ):DefinedSize
   if ! Empty( xDado )
      if ValType( xDado ) = 'D'
         if nTipo=  7 .or. nTipo=133 .or. nTipo=135
            if empty( xDado )
               xDado := date()
            endif
            lRepassa := .t.
         endif
      endif
      if ValType( xDado ) = 'N'
         if nTipo=17 .or. nTipo= 14 .or. nTipo=  5 .or. nTipo=  3 .or. nTipo=131 .or. nTipo=  2 .or. nTipo=  6 .or. ;
            nTipo= 4 .or. nTipo=020 .or. nTipo=018 .or. nTipo=019 .or. nTipo= 21 .or. nTipo=138 .or. nTipo=139
            lRepassa := .t.
         endif
      endif
      if ValType( xDado ) = 'C'
         if nTipo=202 .or. nTipo=130 .or. nTipo=200 .or. nTipo=201 .or. nTipo=129 .or. nTipo= 72
            xDado := substr( xDado, 1, nLong )
            lRepassa := .t.
         endif
         if nTipo=201 .or. nTipo=203 .or. nTipo=205 .or. nTipo=128
            StrFileName := Alltrim(StrZero(Random(99999999),8))+".APL"
            MemoWrit( StrFileName, xDado )
            lRepassa := .t.
            lBlob    := .t.
         endif
      endif
      if ValType( xDado ) = 'L'
         if nTipo= 11 .or. nTipo= 16
            lRepassa := .t.
         endif
      endif
      if ValType( xDado ) = 'M' .or. ValType( xDado ) = 'I'
         if nTipo=201 .or. nTipo=203 .or. nTipo=205 .or. nTipo=128
            lRepassa := .t.
            lBlob    := .t.
         endif
      endif
      if lRepassa
         if lBlob // adolog( ccampo+"-"+ctype+"-"+strzero(ntipo,3)+"-"+ValType( xDado ) )
            oADOStream:Type := 1 // adTypeBinary
            oADOStream:Open()
            oADOStream:LoadFromFile( StrFileName )
            oRecordSet[nRecordSet]:Fields( cCampo ):Value := oADOStream:Read()
            oADOStream:Close()
         else
            oRecordSet[nRecordSet]:Fields( cCampo ):Value := xDado
         endif
      endif
   endif
   return .t.

*
*---------------------------------------------------------
Function ADOField( cStrField )
   LOCAL uVal,nTipo,cType,nLong,xValor:=nil,StrFileName
   if valtype(cStrField)='C'
      cStrField := upper(alltrim(cStrField))
   endif
   if nRecordSet > 0
      uVal  := oRecordSet[nRecordSet]:Fields( cStrField ):Value
      nTipo := oRecordSet[nRecordSet]:Fields( cStrField ):Type
      cType := TypeDat(nTipo,cStrField)
      nLong := oRecordSet[nRecordSet]:Fields( cStrField ):DefinedSize
      do case
         case cType='C'; xValor:=if(empty(uVal),spac(nLong),uVal+spac(nLong-len(uVal)))
         case cType='D'; xValor:=if(empty(uVal),ctod('')                    ,uVal)
         case cType='N'; xValor:=if(empty(uVal),0                           ,uVal)
         case cType='L'; xValor:=if(empty(uVal),.f.                         ,uVal)
         case cType='M' .or. cType='I'
              StrFileName := Alltrim(StrZero(Random(99999999),8))+".APL"
              oADOStream:Type := 1 // adTypeBinary
              oADOStream:Open()
              oADOStream:Write( oRecordSet[nRecordSet]:Fields( cStrField ) )
              oADOStream:LoadFromFile( oRecordSet[nRecordSet]:Fields( StrFileName ), 2 ) // adSaveCreateOverWrite
              oADOStream:Close()
              xValor := MemoRead( StrFileName )
         otherwise     ; xValor:=         uVal
      endcase
   endif
   RETURN xValor

*
*---------------------------------------------------------
Function ADOFieldBlank( cStrField )
   LOCAL uVal,nTipo,cType,nLong,xValor:=nil
   if valtype(cStrField)='C'
      cStrField := upper(alltrim(cStrField))
   endif
   if nRecordSet > 0
      uVal  := oRecordSet[nRecordSet]:Fields( cStrField ):Value
      nTipo := oRecordSet[nRecordSet]:Fields( cStrField ):Type
      cType := TypeDat(nTipo,cStrField)
      nLong := oRecordSet[nRecordSet]:Fields( cStrField ):DefinedSize
      do case
         case cType='C'; xValor:=space(nLong)
         case cType='D'; xValor:=ctod('  /  /  ')
         case cType='N'; xValor:=0
         case cType='L'; xValor:=.f.
         otherwise     ; xValor:=''
      endcase
   endif
   RETURN xValor

*
*---------------------------------------------------------
Function TypeDat(nTipo,cField)
   do case
      case nTipo=8.or.nTipo=12.or.nTipo=72.or.nTipo=129.or.nTipo=130.or.(nTipo>=200.and.nTipo<=203)
           // adBSTR             8
           // adGUID             72
           // adChar             129
           // adWChar            130
           // adVarChar          200
           // adLongVarChar      201
           // adVarWChar         202
           // adLongVarWChar     203
           return 'C'

      case nTipo= 17.or.nTipo= 16.or.nTipo= 14.or.nTipo=  5.or.nTipo=  3.or.nTipo=131.or.nTipo= 2 .or.nTipo=  6.or.;
           nTipo=  4.or.nTipo=020.or.nTipo=018.or.nTipo=019.or.nTipo= 21.or.nTipo=138.or.nTipo=139
           // adSmallInt         2
           // adInteger          3
           // adSingle           4
           // adDouble           5
           // adCurrency         6
           // adDecimal          14
           // adTinyInt          16
           // adUnsignedTinyInt  17
           // adUnsignedSmallInt 18
           // adUnsignedInt      19
           // adBigInt           20
           // adUnsignedBigInt   21
           // adNumeric          131
           // adPropVariant      138
           // adVarNumeric       139
           return 'N' // Numerico

      case nTipo=  7.or.nTipo=64.or.nTipo=133.or.nTipo=134.or.nTipo=135
           // adDate             7
           // adFileTime         64
           // adDBDate           133
           // adDBTime           134
           // adDBTimeStamp      135
           return 'D' // Data

      case nTipo= 11
           // adBoolean          11
           return 'L' // Logico

      case nTipo=203.or.nTipo=128
           // adLongVarWChar     203
           // adPropVariant      138
           return 'M' // Memo

      case nTipo=128.or.nTipo=204.or.nTipo=205
           // adBinary           128
           // adVarBinary        204
           // adLongVarBinary    205
           return 'I' // Imagem

   otherwise
      alert('Tipo de dado invalido: Campo '+cField+' Type='+str(nTipo))
   endcase
   return 'U'

*
*---------------------------------------------------------
Function isRSEmpty()
   return ((oRecordSet[nRecordSet]:BOF()=.t.) .and. (oRecordSet[nRecordSet]:EOF()=.t.))

*
*---------------------------------------------------------
Function ADOGetSQL( sqlFileName )
   sqlFileName = sqlFileName + ".SQL"
   if file(sqlFileName)
      cSql := MemoRead( sqlFileName )
      oADOConection:Execute( cSql )
   endif
   return nil

*
*---------------------------------------------------------
Function ADOUseRemote( cDatabase, lShared )
   local oError
   if cDatabase = NIL
      oRecordSet[nRecordSet]:Close()
   else
      AADD( aRecordSet, cDatabase )
      cRecordSet := cDatabase
      nRecordSet := len( aRecordSet )
      oRecordSet[nRecordSet] := oADOConection
      if cADORDD = "XML" // ".XML" $ upper(cDatabase)
         oRecordSet[nRecordSet]:Open( cDatabase, StrConnection, 1, 3 )
      else
         oRecordSet[nRecordSet]:CacheSize      := 50
         oRecordSet[nRecordSet]:CursorLocation := adUseClient
         if lShared = .t.
            oRecordSet[nRecordSet]:CursorType  := 1 // adOpenKeySet
            oRecordSet[nRecordSet]:LockType    := adLockBatchOptimistic
         else
            oRecordSet[nRecordSet]:CursorType  := adOpenStatic
            oRecordSet[nRecordSet]:LockType    := adLockPessimistic
         endif
         oRecordSet[nRecordSet]:Sql( "Select * from " + cDatabase, StrConnection )
      endif
      oRecordSet[nRecordSet]:MoveFirst()
   endif
   return .t.

function Random( nMaximo )
   static nRandom
   local nTemporal
   nMaximo = if( nMaximo == NIL, 65535, nMaximo )
   if nRandom == NIL
      nRandom = seconds()
   endif
   nTemporal = ( nRandom * seconds() ) % ( nMaximo + 1 )
   nRandom = nTemporal + seconds()
   RETURN int( nTemporal )


Customer.prg
#include "FiveWin.ch"
#include "Splitter.ch"

#include "adoxb.ch"

static oWnd, oClients, oClient, oName
static cName
static oSplit

//----------------------------------------------------------------------------//
function CUSTOMER(cTitle)
    public oMenu, user_nivel := 5
    default cTitle := "coloque um nome"

    // Necessária para criar objetos e variaveis visiveis o tempo todo
    ADOSetRDD( "ACCESS" )

    if ADORDDDefault() = "ACCESS" // ADOMDB
       StrDatabase   := ".\adomdb.mdb"
       StrConnection := "Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";"
    endif
    if ADORDDDefault() = "FIREBIRD" // ADOGDB
       StrDatabase   := ".\adogdb.gdb"
       StrConnection := "DRIVER=Firebird/InterBase(r) driver; UID=sysdba; PWD=masterkey; DBNAME="+StrDatabase
    endif
    if ADORDDDefault() = "MYSQL" // ADOMySQL
       StrDatabase   := [adomysql]
       StrServer     := [127.0.0.1]
       StrPort       := 3306
       StrUserID     := [root]
       StrUserPWD    := []
       StrDriver     := "MySQL ODBC 3.51 Driver"
       StrConnection := "driver={" + StrDriver +"};database=" + StrDatabase + ;
                        ";server=" + StrServer + ;
                        ";uid=" + StrUserID + ;
                        ";pwd=" + StrUserPWD + ;
                        ";option=35"
    endif
    if ADORDDDefault() = "PARADOX" // ADOPX
       StrConnection := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\;Extended Properties=Paradox 5.x;"
    endif
    if ADORDDDefault() = "XML" // ADOXML
       StrConnection := "Provider=MSPersist"
    endif
    if ADORDDDefault() = "REMOTE" // ADORDS
       StrConnection := "Provider=MS Remote;Remote Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/Inetpub/wwwroot/scripts/ASP/UAPortal/ua_portal.mdb;Remote Server=http://localhost/uaportal/"
    endif

    MsgRun( "Conectando via "+ADORDDDefault()+"..." )

    ADO CONNECT StrConnection

    // Cria tabelas se nao existirem
    if ADOFile( "clientes" )
    else
       MsgRun( "Criando tabela CLIENTES..." )
       ADO EXECUTE "DROP TABLE clientes"
       ADO EXECUTE "CREATE TABLE clientes (nome char(45), email char(45), unique(nome))"
    endif
    if ADOFile( "siglas" )
    else
       MsgRun( "Criando tabela SIGLAS..." )
       ADO EXECUTE "DROP TABLE siglas"
       ADO EXECUTE "CREATE TABLE siglas (uf char(2), estado char(20), unique(uf))"
    endif

    // Abre as tabelas
    ADO USE clientes
    ADO USE siglas

    // Verifica se ja possuem dados
    ADO SELECT clientes
    nRegistros := ADORecCount()
    if nRegistros = 0
       ADO APPEND BLANK
       ADO REPLACE nome        WITH "JOSE CARLOS DA ROCHA"
       ADO REPLACE email       WITH "IROCHINHA@ITELEFONICA.COM.BR"
       ADO COMMIT
    endif

    ADO SELECT siglas
    nRegistros := ADORecCount()
    if nRegistros = 0
       ADO APPEND BLANK
       ADO REPLACE uf          WITH "SP"
       ADO REPLACE estado      WITH "SAO PAULO"
       ADO COMMIT
       ADO APPEND BLANK
       ADO REPLACE uf          WITH "RJ"
       ADO REPLACE estado      WITH "RIO DE JANEIRO"
       ADO COMMIT
    endif

    ADO CLOSE ALL

    SET _3DLOOK ON
    DEFINE WINDOW oWnd TITLE cTitle MDI MENU BuildMenu()           
                DEFINE BUTTONBAR OF oWnd
               SET MESSAGE OF oWnd TO cTitle CENTERED
    ACTIVATE WINDOW oWnd VALID MsgYesNo( "Tem certeza?" )
    return nil

//----------------------------------------------------------------------------//
function BuildMenu()
   local oMenu
   MENU oMenu
      MENUITEM "&Cadastros"
      MENU
         MENUITEM "&Clientes..." ACTION  Clientes() MESSAGE "Cadastro de Clientes"
         SEPARATOR
         MENUITEM "&Sair"        ACTION oWnd:End()  MESSAGE "Termina Aplicativo"
      ENDMENU
      oMenu:AddMdi()              // Add standard MDI menu options
   ENDMENU
   return oMenu

//----------------------------------------------------------------------------//
function Clientes(bPrc, bAdc, bAlt, bExc, bImp, bSai)
    LOCAL oIco, oBar, oGet
    LOCAL cTitle := "Manutencao de Clientes"
    LOCAL oDlg, oBrw, nRec
    LOCAL aData := {}
    LOCAL nFor
    LOCAL oLbx, cItem
    LOCAL btnPrc, btnAdc, btnAlt, btnExc, btnImp, btnsai
    DEFAULT bPrc    := { || RecPrc( oLbx ) },;
            bAdc    := { || RecInc( oLbx ) },;
            bAlt    := { || RecAlt( oLbx ) },;
            bExc    := { || RecExc( oLbx ) },;
            bImp    := { || RecImp( oLbx ) },;
            bSai    := { || oDlg2:End() }
    if oClients != nil
       return nil
    endif
    DEFINE WINDOW oClients TITLE cTitle MDICHILD ICON oIco
    DEFINE BUTTONBAR oBar OF oClients
    DEFINE BUTTON OF oBar ACTION RecAlt(oLbx)
    nSplitH := 400
    ADO USE clientes
    //ADO SORT ON nome
    //? "Areas    : " + str( ADOAREAS() ),;
    //  "Tabela   : " + ADOALIAS(),;
    //  "Registros: " + str( ADORECCOUNT() )
    @ 0,0 LISTBOX oLbx FIELDS ADOField( "nome" ), ADOField( "email" ) ;
         HEADERS "Nome","email" ;
         FIELDSIZES 350,250 ;
         PIXEL SIZE 1000,1000 OF oClients
    oLbx:cAlias         := "ARRAY" // ADO devolve tabelas em arrays
    oLbx:bLogicLen   := { || ADORecCount() }
    oLbx:bGoTop      := { || ADOGotop() }
    oLbx:bGoBottom := { || ADOGoBottom() }
    oLbx:bSkip         := { | nSkip | ADOSkip( nSkip ) }
    oLbx:bRClicked   := {| nRow, nCol | RecMenu( nRow, nCol, oLbx ) }
    oLbx:bLDblClick  := {| nRow, nCol | RecAlt(oLbx) }
    oLbx:nStyle        := 1
    oLbx:nLineStyle  := 3
    // -> Estilo FLAT
    oLbx:nHeaderStyle  := 2
    oLbx:nHeaderHeight := 20
    oLbx:nLineHeight   := 15
    oLbx:nStyle        := nOr( WS_CHILD, WS_VSCROLL, WS_HSCROLL, WS_VISIBLE, WS_TABSTOP )

    oClients:SetControl( oLbx )
    ACTIVATE WINDOW oClients MAXIMIZED VALID( oClients := nil, ADOCLOSEALL(), .t. )

return nil

//----------------------------------------------------------------------------//
function RecMenu( nRow, nCol, oLbx )
   local oPopup
   MENU oPopup POPUP
        MENUITEM "&Incluir novo registro"  RESOURCE "bmp_binoculo" ACTION RecInc( oLbx )
        MENUITEM "&Alterar registro atual" RESOURCE ""             ACTION RecAlt( oLbx )
        MENUITEM "&Excluir registro atual" RESOURCE ""             ACTION RecExc( oLbx )
        SEPARATOR
        MENUITEM "&Procurar registro"      RESOURCE ""             ACTION RecPrc( oLbx )
        SEPARATOR
        MENUITEM "&Imprimir Listagem"      RESOURCE ""             ACTION RecImp( oLbx )
   ENDMENU
   ACTIVATE POPUP oPopup AT nRow, nCol OF oLbx
   return nil

//----------------------------------------------------------------------------//
function GenReport()
   local oWnd, oIco
   DEFINE ICON oIco FILENAME "..\icons\print.ico"
   DEFINE WINDOW oWnd MDICHILD TITLE "Clients report" ;
      VSCROLL HSCROLL ICON oIco
   ACTIVATE WINDOW oWnd
   return nil

//----------------------------------------------------------------------------//
function Show2Client()
   local oIco
   if oClient != nil
      return nil
   endif
   DEFINE ICON oIco FILENAME "..\icons\Person.ico"
   DEFINE DIALOG oClient RESOURCE "Client" ;
      ICON oIco
   REDEFINE SAY ID 3 OF oClient   // To get the proper color
   REDEFINE SAY ID 4 OF oClient
   REDEFINE SAY ID 5 OF oClient
   REDEFINE GET oName VAR cName ID ID_NAME OF oClient
   REDEFINE BUTTON ID ID_NEXT OF oClient ACTION GoNext()
   SELECT Sales     // We select Sales to properly initialize the Browse
   REDEFINE LISTBOX FIELDS ID ID_SALES OF oClient
   ACTIVATE DIALOG oClient CENTERED NOWAIT ;
      VALID ( oClient := nil, .t. )           // Destroy the object
   SELECT Clients
   return nil

//----------------------------------------------------------------------------//
function ChangeClient()
   if oClient != nil
      cName = AllTrim( Clients->Last ) + ", " + Clients->First
      oName:Refresh()
   endif
   return nil

//----------------------------------------------------------------------------//
function GoNext()
   if oClients != nil
      oClients:oControl:GoDown()
   else
      SKIP
      if EoF()
         GO BOTTOM
      endif
   endif
   ChangeClient()
   return nil

FUNCTION CLEARCHR( CICCGC )
   CICCGC = STRTRAN(CICCGC, '>', '')
   CICCGC = STRTRAN(CICCGC, '<', '')
   CICCGC = STRTRAN(CICCGC, '.', '')
   CICCGC = STRTRAN(CICCGC, '-', '')
   CICCGC = STRTRAN(CICCGC, '(', '')
   CICCGC = STRTRAN(CICCGC, ')', '')
   CICCGC = STRTRAN(CICCGC, '=', '')
   CICCGC = STRTRAN(CICCGC, '+', '')
   CICCGC = STRTRAN(CICCGC, '\', '')
   CICCGC = STRTRAN(CICCGC, '/', '')
   CICCGC = STRTRAN(CICCGC, '*', '')
   CICCGC = STRTRAN(CICCGC, ['], '')
   CICCGC = ALLTRIM(CICCGC)
   RETURN CICCGC

function fun( oque )
  msgstop( oque )
  return .t.
function tgsetmode( oque )
  return .t.
function tooltip( oque )
  return .t.
FUNCTION NewCapFirst
parameter string
declare excesao[7]
excesao[1] = " Do "
excesao[2] = " Dos "
excesao[3] = " Da "
excesao[4] = " Das "
excesao[5] = " De "
excesao[6] = " E "
excesao[7] = " Del "
novotexto = space(1)+lower(string)
fim = len(string)
for i = 1 to fim
   if substr(novotexto,i,1) = " "
      novotexto = stuff(novotexto,i+1,1,upper(substr(novotexto,i+1,1)))
   endif
next
tamanho = len(excesao)
for i = 1 to tamanho
   if excesao[i]$novotexto   && tamanho
      novotexto = stuff(novotexto,AT(excesao[i],novotexto),;
      len(excesao[i]),lower(excesao[i]))
   endif
next
RETURN(ltrim(novotexto))

//-----------------------------------------------------------
static function  RecPrc(oLbx)
    Local odlg1
    Local cCodigo:=0
    Local cSair:=" "
    Local sql
    DEFINE DIALOG oDlg1 From 0,0 To 160,250  PIXEL;
           TITLE " Procura na Tabela em Access "
    DEFINE FONT oFont NAME "FIXEDSYS" SIZE 10, -10    && Use a Nonproportional font
    SET FONT OF oDlg1 TO oFont                         && so characters line up in Says
    @ 02,05 say "Codigo : " OF oDlg1
    @ 02.2,10 get cCodigo   OF oDlg1 picture "9999" size 20,10
    @ 02.7 , 10 button "Procurar"  of oDlg1 size 40,12 action (cSair:="*",oDlg1:End())
    ACTIVATE DIALOG oDlg1 centered
    if cSair="*"
       //locate for (odbf:cAlias)->field_0001 = cCodigo
       criterio = "idpessoa Like '" + cCodigo + "%'"
       //oRs:MoveFirst()
       //oRs:Find criterio, 0, adSearchFoward
       if eof()
          msgAlert("NÆo encontrado !!!")
          go top
       endif
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function  RecInc(oLbx)
    LOCAL odlg3
    LOCAL cNome     := space(40)
    LOCAL cTelefone := space(14)
    LOCAL cEmail    := space(40)
    LOCAL cSair     := " "
    DEFINE DIALOG oDlg3 From 0,0 To 230,500 PIXEL TITLE " Inclusao na Tabela em Access "
           DEFINE FONT oFont NAME "FIXEDSYS" SIZE 10, -10    && Use a Nonproportional font
           SET FONT OF oDlg3 TO oFont                         && so characters line up in Says
           @ 02,05 say "Nome_____: " OF oDlg3
           @ 04,05 say "Email____: " OF oDlg3
           //
           @ 02.2,10 get cNome     OF oDlg3 picture "@!" size 150,10
           @ 04.4,10 get cEmail    OF oDlg3 picture "@!" size 150,10
           //
           @ 04.7 , 15 button "Salvar"   of oDlg3 size 40,12 action (cSair:="*",oDlg3:End())
    ACTIVATE DIALOG oDlg3 centered
    if cSair="*"
       ADO APPEND BLANK
       ADO REPLACE nome        WITH alltrim( cNome )
       ADO REPLACE email       WITH alltrim( cEmail )
       ADO COMMIT
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function  RecAlt(oLbx)
    LOCAL odlg3
    LOCAL nRegistro := ADORecno()
    //LOCAL cNome     := PadR( ADOField( "nome" ), 40 )
    //LOCAL cEmail    := PadR( ADOField( "email" ), 40 )
    LOCAL cNome     := ADOField( "nome" )
    LOCAL cEmail    := ADOField( "email" )
    LOCAL cSair     := " "
    DEFINE DIALOG oDlg3 From 0,0 To 230,500 PIXEL TITLE " Inclusao na Tabela em Access "
           DEFINE FONT oFont NAME "FIXEDSYS" SIZE 10, -10    && Use a Nonproportional font
           SET FONT OF oDlg3 TO oFont                        && so characters line up in Says
           //
           @ 02,05 say "Nome_____: " OF oDlg3
           @ 04,05 say "Email____: " OF oDlg3
           //
           @ 02.2,10 get cNome     OF oDlg3 picture "@!" size 150,10
           @ 04.4,10 get cEmail    OF oDlg3 picture "@!" size 150,10
           //
           @ 04.7 , 15 button "Salvar"   of oDlg3 size 40,12 action (cSair:="*",oDlg3:End())
    ACTIVATE DIALOG oDlg3 centered
    if cSair="*"
       ADO REPLACE nome       WITH alltrim( cNome )
       ADO REPLACE email      WITH alltrim( cEmail )
       ADO COMMIT
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function  RecExc(oLbx)
    if MsgYesNo( "Excluir este Registro ?", "Por Favor, confirme" )
       ADO DELETE
       //ADO SKIP
       oLbx:Refresh()
    endif
    return nil

//-----------------------------------------------------------
static function RecImp( oLbx )
/*
    local oRpt
    local n
    local cAlias := If( oLbx != nil, oLbx:cAlias, Alias() )
    REPORT oRpt TITLE "Relatorio: " + cAlias ;
           HEADER "Data: " + DToC( Date() ) + ", Hora: " + Time() ;
           FOOTER "Pagina: " + Str( oRpt:nPage, 3 ) ;
           PREVIEW
           if Empty( oRpt ) .or. oRpt:oDevice:hDC == 0
              return nil
           endif
           for n = 1 to FCount()
               oRpt:AddColumn( TrColumn():New( { FInfo1( cAlias, n ) },,;
                     { FInfo2( cAlias, n ) },,,,,,,,,, oRpt ) )
           next
    ENDREPORT
    ACTIVATE REPORT oRpt
    GO TOP
*/
    return nil

//--------------------------------------------
static function FInfo1( cAlias, n )
return { || ( cAlias )->( FieldName( n ) ) }

//-----------------------------------------------------------
static function FInfo2( cAlias, n )
return { || ( cAlias )->( FieldGet( n ) ) }

Function DbfDbt()
Return Nil

#include "adoxb.prg"

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 14 Ago 2008 09:39
por asimoes
Olá Rochinha,

Existe algum exemplo executando uma stored procedure do oracle?
Nós estamos querendo sair do clipper para o xharbour, estamos usando o oraclip, conhece?
O problema é achar exemplos de execução de storeds procedures, mais uma pergunta o SQLRDD comercial tem este recurso?

[]´s

Alexandre

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 05 Out 2010 08:32
por gilsonpaulo
Amigo Rochinha, estou tentando usar a adoxb mas estou com pequenos erros.:

----------------------------- xHarbour Error Log ------------------------------

Date...............: 10/05/10
Time...............: 08:19:22

Application name...: C:\Sist\OS\OS.EXE
Workstation name...: GS01
Available memory...: 128288
Current disk.......: C
Current directory..: Sist\OS
Free disk space....: 63575773184

Operating system...: Windows XP Professional 5.01.2600 Service Pack 3
xHarbour version...: xHarbour build 1.2.1 Intl. (SimpLex) (Rev. 6740)
xHarbour built on..: Oct  3 2010 10:18:27
C/C++ compiler.....: Borland C++ 5.5.1 (32 bit)
Multi Threading....: NO
VM Optimization....: 2

Current Area ......:1

-------------------------- Environmental Information --------------------------

SET ALTERNATE......: OFF
SET ALTFILE........:
SET AUTOPEN........: ON
SET AUTORDER.......: 0
SET AUTOSHARE......: 0
SET BACKGROUNDTASKS: OFF
SET BACKGROUNDTICK.: 1000
SET BELL...........: OFF
SET BLINK..........: .T.
SET CANCEL.........: ON
SET CENTURY........: OFF
SET COLOR..........: W/N,N/W,N/N,N/N,N/W
SET CONFIRM........: OFF
SET CONSOLE........: ON
SET COUNT..........: 0
SET CURSOR.........: 1
SET DATE FORMAT....: MM/DD/YY
SET DBFLOCKSCHEME..: 0
SET DEBUG..........: OFF
SET DECIMALS.......: 2
SET DEFAULT........:
SET DEFEXTENSIONS..: ON
SET DELETED........: OFF
SET DELIMCHARS.....: ::
SET DELIMETERS.....: OFF
SET DEVICE.........: SCREEN
SET DIRCASE........: 0
SET DIRSEPARATOR...: \
SET EOL............: 13
SET EPOCH..........: 1900
SET ERRORLOG.......: ERROR.LOG,.F.
SET ERRORLOOP......: 8
SET ESCAPE.........: ON
SET EVENTMASK......: 128
SET EXACT..........: OFF
SET EXCLUSIVE......: ON
SET EXIT...........: OFF
SET EXTRA..........: OFF
SET EXTRAFILE......:
SET FILECASE.......: 0
SET FIXED..........: OFF
SET FORCEOPT.......: OFF
SET HARDCOMMIT.....: ON
SET IDLEREPEAT.....: ON
SET INSERT.........: OFF
SET INTENSITY......: ON
SET LANGUAGE.......: EN
SET MARGIN.........: 0
SET MBLOCKSIZE.....: 0
SET MCENTER........: OFF
SET MESSAGE........: 0
SET MFILEEXT.......:
SET OPTIMIZE.......: ON
SET OUTPUTSAFETY...: ON
SET PATH...........:
SET PRINTER........: OFF
SET PRINTERJOB.....:
SET PRINTFILE......: PRN
SET SCOREBOARD.....: ON
SET SCROLLBREAK....: ON
SET SOFTSEEK.......: OFF
SET STRICTREAD.....: OFF
SET TRACE..........: ON
SET TRACEFILE......: TRACE.LOG
SET TRACESTACK.....: 2
SET TRIMFILENAME...: .F.
SET TYPEAHEAD......: 50
SET UNIQUE.........: OFF
SET VIDEOMODE......: 0
SET WRAP...........: OFF

---------------------------Detailed Work Area Items----------------------------

-------------------- Internal Error Handling Information  ---------------------

Subsystem Call ....: TOleAuto
System Code .......: 65535
Default Status ....: .F.
Description .......:
Operation .........: TOLEAUTO:NEW
Arguments .........:  [ 1] = Type: C Val: ADODB.Err
Involved File .....:
Dos Error Code ....: 0

Trace Through:
----------------
TOLEAUTO:NEW          :     334 in Module: source\rtl\win32ole.prg
TOLEAUTO:NEW          :     346 in Module: source\rtl\win32ole.prg
ADOCONNECT            :      57 in Module: C:\Sist\OS\ADOXB.PRG
MAIN                  :      26 in Module: C:\Sist\OS\GB.000

############################## Video Screen Dump ##############################

+--------------------------------------------------------------------------------+
|                                                                                |
|Error TOleAuto/65535  : TOLEAUTO:NEW Arguments: ( [ 1] = Type: C Val: ADODB.Err)|
|                                                                                |
|                                                                                |
|Error at ...: TOLEAUTO:NEW(334) in Module: source\rtl\win32ole.prg              |
|Called from : TOLEAUTO:NEW(346) in Module: source\rtl\win32ole.prg              |
|Called from : ADOCONNECT(57) in Module: C:\Sist\OS\ADOXB.PRG                    |
|Called from : MAIN(26) in Module: C:\Sist\OS\GB.000                             |


Segue o fonte do prg

#include "adoxb.ch"

request HB_GT_WIN

Function Main()

ADOSetRDD( "mysql" )
     
ADORDDDefault("mysql")

StrDatabase := [gs]
StrServer := [192.168.0.100]
StrPort := 3306
StrUserID := [root]
StrUserPWD := []
StrDriver := "MySQL ODBC 3.51 Driver"

StrConnection := "driver={" + StrDriver +"};database=" + StrDatabase + ;
                     ";server=" + StrServer + ;
                     ";uid=" + StrUserID + ;
                     ";pwd=" + StrUserPWD + ;
                     ";option=35"

ADO CONNECT StrConnection

ADO USE CLIENTE
ADO SELECT CLIENTE
browse()
ADO APPEND BLANK
ADO REPLACE CODIGO WITH 00000001
ADO REPLACE NOME WITH "GILSON PAULO SCHUCK"
ADO COMMIT
ADO USE
return nil


Desde ja agradeço qualquer ajuda.

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 09 Nov 2010 11:31
por rochinha
Amiguinho,

Pelo que pude reparar a linha referida tenta vincular um recurso ADO que pode não ser acessado em sua instalação de S.O. ou o conjunto de bibliotecas OLE não compatibilizem-se.

Voce usa xHarbour, troque o TOLEAUTO() por CREATEOBJECT() e verifique se as bibliotecas de acesso OLE estão sendo bem empregadas na compilação.

Desabilite a linha 57 no ADOxB.PRG.

Verifique também se o driver ODBC compativel com o seu MySQL esteja instalado.

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 04 Abr 2011 17:10
por pauloa1
Olá Rochinha!

Uso xHarbou 1.21 + wvw+hwgui+dbfcdx

Quero mudar de dbf para firebird.

Li todo o seu post, minha dúvida é:

O pessoal em geral usam sqlrdd(pago) para migrar dbf para BD.

Com essas funções que vc criou ao meu ver ficou parecido um sqlrdd , certo?

Em termos de velocidade os dois seriam parecidos?

Ou mesmo com essas funções ainda tem muita diferença que compense eu pagar por um sqlrdd?

Paulo

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 04 Abr 2011 21:35
por rochinha
Amiguinho,

A biblioteca apresentada tem o intuito de mostrar a manipulação da API fornecida pelo ADO.

Se bem que quando esbocei a mesma nem sequer existia o RDD para ADO.

O RDD existente hoje para ADO e SQL estão muito maduros e mais estáveis. Sugiro que faça uso deles nas versões 2.0 e posteriores do Harbour.

Com pouquissimas linhas voce conseguira manipular bases relacionais e/ou DBFs via comandos SQL.

Acho uma boa voce usar comandos SQL para acesso a DBFs para que vá aprendendo a manipular esta forma de obtenção de dados.

Nunca coloquei em testes o fator velocidade, ainda uso esta biblioteca em meu sistema para acesso a dados remotos, pois ainda uso a versão .45 do Harbour.

Sugiro antes de voce implantar acesso nativo SQL em seu aplicativo que produza em separado um pequeno aplicativo que manipule estes comandos, como append, update, where, delete, join, etc.

Veja também que enganei o compilador usando xcommand bem parecidos com os comandos nativos para DBF de forma a facilitar a programação.

Boa sorte

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 04 Abr 2011 22:53
por pauloa1
Obrigado pela Resposta Rochinha.

Não entendi direito, existe o rddsql e um rdd para ADO. Isso ou estou falando bobagem?

Como faço para usar comandos sql via dbf?

Paulo

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 05 Abr 2011 01:02
por rochinha
Amiguinho,

Existem sim, todos estes RDD, que beleza é o mundo Harbour.

Re: *** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 05 Abr 2011 09:48
por pauloa1
Que blz!
Onde encontro esse rdd para Ado?
Ele tem no xHarbour.gov?

Paulo

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 25 Mar 2013 20:32
por Mário Isa
Rochinha,,
essa .lib AdoxB vc ainda usa ?
Tem alguma atualização ?

Me pareceu ser bem fácil de usar para adaptar num programa xBase.

Mário

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 26 Mar 2013 00:19
por rochinha
Amiguinho,

Sim, ainda uso, ela faz ponte para que eu possa acessar arquivos MDB ou MySQL. Para efeito de integração.

Quando digo integração é relacionado a transferencia de/para aplicativos como FlexPDV, Salc, DJPDV, etc.

Ainda uso ela porque queria usar adordd, mas uns testes feitos recentemente ainda encontrei bugs.

Planejo usar algo como NetIO pois obtive exito em implementar e vi a facilidade de uso.

Se voce pretende fazer um uso esporádico para transição de dados, integração é uma boa saida, mas para produção voce poderá encontrar um probleminha mais afrente mais relativo ao próprio ADO. Não me lembro onde esbarrei em algo que não me permitiu usá-lo em produção.

Assim como voce, as vezes fazemos algumas apostas, mas muitas delas nos fazem ficar com uma ou outra ferramenta que depois podem nos deixar na mão com falta de atualizações ou não-compatibilidades com o compilador que usamos.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 26 Mar 2013 07:45
por Mário Isa
Quando você diz:
Planejo usar algo como NetIO


é porque pretende utilizar .dbf's ?

Para utilizar o NETIO é preciso atualizar a rede do cliente e instalar o protocolo NETIO ou ele já vem instalado? Pelo menos no meu w-7 só tem os TCP-IP......

(A)

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 26 Mar 2013 15:57
por rochinha
Amiguinho,

Quando você diz:
Planejo usar algo como NetIO


é porque pretende utilizar .dbf's ?


Exatamente. Pois pelo visto a modificação de uma plicação, hoje rodando normalmente com RDDCDX, precisaria somente das linhas iniciais com direcionamento por IP. Assim como RDDLeto.

Caso houvesse algum problema a facilidade de retorno ao padrão normal de acesso via RDDCDX poderia ser retomado mantendo o funcionamento da empresa sem transtornos do suporte.

O acesso via NetIO é identico ao RDD Leto, ou seja, voce sobe um pequeno servidorzinho e a partir de bibliotecas próprias o acesso é feito de forma transparente.

Voce terá um executável servidor chamado hbNetIO.exe. Voce executa ele numa pasta e dentro desta pasta voce cria uma pasta chamada dados e coloca nela todos os .DBFs que deseja acessar.

Voce linka as bibliotecas do RDD ao seu sistema e acrescenta umas linhas onde você informa o IP da máquina estará executando o hbNetIO.exe e então pode usar comandos use, etc.

Lembro-lhe que ainda não uso em produção, fiz um teste para entender o funcionamento e como faria a minha integração.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 26 Mar 2013 19:27
por Mário Isa
Veja o teste com o NETIO que fiz em:
http://www.pctoledo.com.br/forum/viewto ... 614#p81606

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 18 Mai 2013 06:18
por lucasdebeltran
Caro Mestre,

Por favor, indique onde eu poderia baixar a última versão do ADOXB?.

Muito grato. Saudações

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 18 Mai 2013 20:31
por rochinha
Amiguinhos,

Os links ainda são os mesmos do inicio das postagens.

Caso eu verifique algumas modificações coloco on-line.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 19 Mai 2013 10:46
por lucasdebeltran
Mestre,

Muito obrigado pela sua resposta. No entanto, os links não funcionam http://www.5volution.com.br/downloads/forum/adoxb.txt.

Além disso, por faxor existe uma versão mais recente?. O código-fonte do fórum não funciona corretamente com as versões mais recentes do Porto e xHarbour, especialmente CloseAll, FILTER, ETC, produzindo erros RTE.

Muito obrigado pelo seu tempo e ajuda e atenção.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 03 Jun 2013 08:45
por lucasdebeltran
Any news?

Obrigado

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 03 Jun 2013 18:02
por rochinha
Amiguinho,

Baixe o .TXT do link anterior.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 01 Jul 2013 10:56
por rochinha
Amiguinhos,

Ultima versão atualizada do ADOxB.prg.

Nesta versão inclusive é possivel abrir uma tabela, exemplo Access, e importá-la para .XMLDB(padrão de .XML onde os campos são agregados)

Download

Exemplo:
   ...
   ADOSetRDD( "ACCESS" )

   StrDataDir    := "C:\SISTEMA"
   StrDatabase   := StrDataDir+"\contato.mdb"

   StrConnection := "Provider= MicroSoft.Jet.OLEDB.4.0;Data Source="+StrDatabase+";"

   ADO CONNECT StrConnection
   oRs     := oRecordSet

   // Seleciona as tabelas e salva
   ADO USE tbNomes // Somente o nome da tabela no database
   ADO SAVE tbNomes.xml // Nome e extensão do resultado
   ...

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 28 Jul 2013 17:00
por rochinha
Amiguinhos,

Atualizei alguns dos links que postei aqui com base nos arquivos contidos em minhas pastas de trabalho.

De quebra coloquei o ADOExplorer

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 27 Nov 2013 20:39
por Hasse
Boa noite Rochinha.

Copiei o Adoxb.prg e Adoxb.ch acima.

Há algum documento que explique o funcionamento, uso e aplicação de cada função, #comand e #define constantes dos 2 arquivos ?

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 27 Nov 2013 22:03
por JoséQuintas
Vi nos posts que avisaram que o Harbour já tem isso pronto.
Mas só pra lembrar e exemplificar:

USE test00 VIA "ADORDD" TABLE "ACCOUNTS" MYSQL ;
      FROM "www.freesql.org" USER "myuser" PASSWORD "mypass"
   LOCATE FOR "City LIKE 'Chi*'"
   DO WHILE ! Eof()
      ? test00->First, test00->City
      CONTINUE
   ENDDO
   USE

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 28 Nov 2013 23:53
por rochinha
Amiguinhos,

Hasse

Boa noite Rochinha.

Copiei o Adoxb.prg e Adoxb.ch acima.

Há algum documento que explique o funcionamento, uso e aplicação de cada função, #comand e #define constantes dos 2 arquivos ?


Os exemplos contidos nos primeiros posts do tópico apresentam a forma de uso. Não documentei a biblioteca.

Quintas

Voce chegou a fazer uns testes pesados usando o ADORDD do Harbour? Eu fiz uma implementação usando ADORDD como ponte para manipular .MDB de outros aplicativos afim de integrar ao meu sistema e me sai melhor usando o ADOxB. Não lembro os problemas, mas em alguns casos não era lidos os dados de alguns campos e aconteciam erros que não deveria acontecer.

Aminha melhor saida foi usando a ADOxB, transformando os dados de tabelas em XML e fazendo o transporte.

Assim que retomar os testes, posto os resultados e quais os problemas encontrados.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 29 Nov 2013 10:46
por Hasse
Bom dia Rochinha.

Estou tentando entender e digerir todas estas informações contidas neste tópico, mas tenho dificuldades para entender determinadas colocações. Se o amigo puder me orientar, ficarei muito grato.

Acho uma boa voce usar comandos SQL para acesso a DBFs para que vá aprendendo a manipular esta forma de obtenção de dados.

Isto quer dizer que se pode usar o ADO para cessar DBF's ?

Desta forma eu poderia testar o aplicativo usando DBF's e depois portá-los para o Oracle ? Eu não tenho o Oracle instalado em meu Desktop.
Se isto for possível realmente, por favor, como devo proceder ?

Isto me interessa de imediato, pois estou tendo enormes dificuldades com um interfaceamento do meu cliente com um Oracle externo (o meu cliente é fornecedor de comercial do cliente possuidor do Oracle versão 10g).

Outro detalhe amigo, todos os links que apontam para o FiveWin (5Evolution) estão quebrados.

Os meus agradecimentos antecipados.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 29 Nov 2013 12:17
por rochinha
Amiguinho,

Isto quer dizer que se pode usar o ADO para cessar DBF's ?


Com certeza que sim, voce apenas terá de fazer a conecção/conexão e usar o comando EXECUTE onde passará a sentença SQL.

Outro detalhe amigo, todos os links que apontam para o FiveWin (5Evolution) estão quebrados.


Estou resolvendo isto(mudança de endereço, montagem do escritório) e em breve o site estará de volta.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 29 Nov 2013 13:06
por Hasse
Boa tarde Rochinha.

E, de que forma eu posso simular um Banco Oracle, sem ter o Oracle disponível ?

Bastaria criar os DBF's com os mesmos campos do Banco Oracle ? (pelo menos aquelas Tabelas e Campos aos quais tenho acesso)

Acredito que neste caso eu teria diferenças no que toca aos inter-relacionamentos internos do Banco, mas para testar as rotinas de select, leitura e gravação (update) acredito que seria viável. Estou correto ?

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 29 Nov 2013 13:31
por rochinha
Amiguinho,

SQL é uma linguagem única e duvido que de banco para banco exista diferenças gritantes, portanto não há o que temer.

Para testar o uso de um Oracle voce pode optar por baixar e instalar Oracle Database 11g Express Edition

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 31 Mar 2014 19:13
por ALMMa
Pessoal,

Sou novo por aqui.

Temos uma grande mudança pela frente em nosso sistema, atualmente em xHarbour.
Basicamente, precisamos remover toda a casca dele e integrar com um aplicativo em .NET, mantendo parte das funções e eliminando outras.

Então, resolvemos dar uma testada no SQLRDD mas os exemplos não compilaram.
Daí vimos o ADOxb e resolvemos testar também, já que tem a vantagem de gerar comandos na mão e ter maior controle...

Baixamos o CH e o PRG mais novos e copiamos um código de testes.

Quase tudo funciona... só que na hora do
ADO CLOSE
dá o seguinte erro:
Error ADODB.Recordset/6 DISP_E_UNKNOWNNAME: END
Arguments: ()

O log gerado aponta pra ADOXB.PRG (511), onde tem:
oRecordSet[nRecordSet]:End()


A conexão é feita, os registros são filtrados e/ou alterados, tudo parece funcionar.
Mas na hora de fechar, dá erro.

Basicamente, a mesma coisa acontece se usar um
ADO CLOSE ALL


Alguma ideia?

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 31 Mar 2014 22:48
por rochinha
Amiguinho,

Nas funções ADOUse() e ADOCloseAll() as linhas onde existam este comando poderão ser suprimidas sem problemas ao conjunto.

Nos objetos Record e RecordSet não reparei a inexistencia do método End(). Mas não me ocorreram erros até agora.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 26 Dez 2014 18:41
por Hasse
Boa noite Rochinha.

Estou desenvolvendo um aplicativo que exporta dados de um DBF para GDB do Firebird.

Na fase de testes já estou exportando dados de forma correta.

O problema é quando tento usar o comando ADO EXECUTE "DROP TABLE Estoque" para zerar a tabela de destino antes do início da exportação.

Abaixo o ErrorLog do erro:
Descrição do erro .............: [ODBC Firebird Driver][Firebird]unsuccessful metadata update object ESTOQUE is in use (0x80004005)
Nome do arquivo ...............: Microsoft OLE DB Provider for ODBC Drivers
Objeto do Erro ................: EXECUTE
Área - Select() ...............: 1
TraceLog do Erro:
TOLEAUTO:EXECUTE.Linha: 0 Módulo:
ADOEXECUTE.......Linha: 551 Módulo: FireFio.prg
MAIN.............Linha: 46 Módulo: FireFio.prg


O mesmo acontece com outros usos da comando ADO EXECUTE.

Esta é a linha onde ocorre o erro:
 oADOConection[nConnect]:Execute( cSql )

Abaixo como uso comando ADO EXECUTE:
ADO EXECUTE "DROP TABLE Estoque"

Abaixo o valor de cSql listado pelo ErroLog:
Tamanho Variável Tipo Valor
--------------------------------------------
18 Bytes -> cSQL Tipo C => DROP TABLE Estoque


Qual é o meu erro ?

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 26 Dez 2014 23:56
por rochinha
Amiguinho,

Coloque um trecho maior de código. Somente a linha que ocorre o erro não é o bastante para entender o porque.

Pela tradução visual da mensagem, indica que você está tentando deletar uma tabela que esta em uso.

Para deletar a tabela, apenas faça a conexão com o banco de dados e não selecione a tabela.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 27 Dez 2014 08:25
por Hasse
Bom dia Rochinha.

Segue o fonte completo.

No final do .prg já estão comentadas mais 2 linhas do comando ADO EXECUTE, que também não funcionam.

Quanto às 2 linhas seguintes, eu já li em teus comentários anteriores, que não funcionam. OK.

#include "adoXb.ch" ------->>> esta linha já existe no ado.ch. Ela pode ser retirada daqui ?

No Anexo também segue o arquivo do ErrorLog completo.

FireFio.prg
**
#include "adoXb.ch"
#include "AdoXb.prg"
*
#Include 'Inkey.ch'
#Include 'i_keybd.ch'
#include "MiniGUI.ch"
#include "ado.ch"
#include "set.ch"
#include "common.ch"
#include "directry.ch"
#include "fileio.ch"
#include "hbcompat.ch"
#include "hbwin.ch"
*
*STATIC oWnd, oClients, oClient, oName
*STATIC cName
*STATIC oSplit
*
REQUEST HB_GT_WIN_DEFAULT                                                 && Janela DOS - Temporário para testes.
*
*==================================================================================================
FUNCTION Main()
   *
   LOCAL oError       := ErrorBlock( { | oError | MyErrorFunc( oError ) } )
   *
   PUBLIC oMenu, user_nivel := 5
   PUBLIC StrDatabas := "C:\Teste\Exemplo.gdb"
   PUBLIC StrConnect := "DRIVER=Firebird/InterBase(r) driver; UID=sysdba; PWD=masterkey; DBNAME="+StrDatabas
   *
   // Necessária para criar objetos e variaveis visiveis o tempo todo
   ADOSetRDD( "FIREBIRD" )                // ADOGDB
   ADORDDDefault( "FIREBIRD" )            // ADOGDB
   cADORDD := "FIREBIRD"
   *
   ADO CONNECT StrConnect
   *
   ADO USE Estoque
   *
   ADO SELECT Estoque
   ADO GOBOTTOM
   *
   ADO EXECUTE "DROP TABLE Estoque"
   *
   SELE 1
   c_Estoque := 'D:\Dev\Clipper\Datafio\Estoque'
   USE ( c_Estoque )
   *
   Clear
   *
   WHILE Estoque->( ! EOF() )
      *
      @ 08,00 say Estoque->( Recno() )
      *
      IF Estoque->FG = "1"
         *
         c_Referen  := Estoque->CODIGO
         c_Descric  := Estoque->DESCRICAO
         n_Quantid  := Estoque->QUANT
         *     
         @ 10,10 say n_Reg
         @ 11,10 say c_Referen
         @ 12,10 say c_Descric
         *
         nRegistros := ADORecCount()
         n_Reg      := nRegistros + 01
         c_Registro := StrZero( n_Reg, 10 )
         c_Codigo   := StrZero( n_Reg, 05 )
         *
         ADO APPEND BLANK
         ADO REPLACE REGISTRO          WITH c_Registro                     && 10
         ADO REPLACE CODIGO            WITH c_Codigo                       && 5
         ADO REPLACE REFERENCIA        WITH c_Referen                      && 14
         ADO REPLACE DESCRICAO         WITH c_Descric                      && 45
         ADO REPLACE QTD_ATUAL         WITH n_Quantid                      && Double
         ADO COMMIT
         *   
      ENDIF
      *
      Estoque->( DBSkip() )
      *
   ENDDO
   *
*   c_Str := 'Select REGISTRO, REFERENCIA, QTD_ATUAL from ESTOQUE'
*   ADO EXECUTE ( c_Str )
   *
*  ADO CLOSE ALL
*  ADO CLOSE
   *
RETURN( nil )


Outra dúvida:
Como se faz leitura de valores da Tabela com o ADO ?

Abaixo o arquivo do ErrorLog.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 27 Dez 2014 15:31
por Hasse
Boa tarde Rochinha.

O DROP funcionou da forma como você postou. Antes de selecionar a tabela.

Mas, eu troquei alhos por bugalhos.

O DROP ele deleta a Tabela do Banco de Dados. Na realidade eu quero é zerar a Tabela, ou seja, o equivalente ao ZAP do DBF. Como se faz ?

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 29 Dez 2014 09:35
por rochinha
Amiguinhos,

#include "adoXb.ch" ------->>> esta linha já existe no ado.ch. Ela pode ser retirada daqui ?


Este .CH possui INCLUDEs expecificos para uso da biblioteca. Verifique e compare, o que for duplicado elimine.

Quanto a ZAPear uma tabela SQL é o seguinte. Por padrão usamos DROP e depois CREATE para recriar a tabela.

Verifique na biblioteca se eu acrescentei algum comando que simule o ZAP, senão, continue usando o feijão-com-arroz.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 29 Dez 2014 14:59
por Hasse
Boa tarde Rochinha.

Pesquisei no ADOxB.PRG e não tem ZAP nem DROP.
E como seria este feijão-com-arroz ?. Eu ainda não consegui zerar uma tabela via *.PRG.

No ADOxB.ch tem os comandos abaixo:
#xcommand ADO SQL CREATE <*cSQL*> => ADOEXECUTE( 'CREATE '+ <(cSQL)> )
#xcommand ADO SQL DROP <*cSQL*> => ADOEXECUTE( 'DROP ' + <(cSQL)> )

1)-Na função Function ADODBCREATE( cDatabase ), qual é a estrutura de cDatabase ? Semelhante ao usado para criar DBF ?

2)-Na função Function ADOSetOrder( nIDXOrder ), a variável nIDXOrder é o nome da coluna da tabela ?

3)-Qual a utilidade das funções abaixo:
Function ADORequery()
Function ADOReSync()
Function ADOUpdateBatch()
Function ADOSave( cfile )

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 30 Dez 2014 16:16
por rochinha
Amiguinhos,

O feijão-com-arroz é a forma básica mesmo, DROP e depois CREATE. Mas no caso de apenas eliminar os registros voce irá usar a sentença DELETE FROM.

Neste exemplo você ve o feijão-com-arroz:
#include "adoxb.ch"

function CUSTOMER(cTitle)

    // Necessária para criar objetos e variaveis visiveis o tempo todo
    ADOSetRDD( "ACCESS" )

    if ADORDDDefault() = "FIREBIRD" // ADOGDB
       StrDatabase   := ".\adogdb.gdb"
       StrConnection := "DRIVER=Firebird/InterBase(r) driver; UID=sysdba; PWD=masterkey; DBNAME="+StrDatabase
    endif

    MsgRun( "Conectando via "+ADORDDDefault()+"..." )

    ADO CONNECT StrConnection

    // Cria tabelas se nao existirem
    if ADOFile( "clientes" )
    else 
       MsgRun( "Criando tabela CLIENTES..." )
       ADO EXECUTE "DROP TABLE clientes"
       ADO EXECUTE "CREATE TABLE clientes (nome char(45), email char(45), unique(nome))"
    endif

    // Abre as tabelas
    ADO USE clientes

    // Verifica se ja possuem dados
    ADO SELECT clientes
    nRegistros := ADORecCount()
    if nRegistros = 0
       ADO APPEND BLANK
       ADO REPLACE nome      WITH "JOSE CARLOS DA ROCHA"
       ADO REPLACE email       WITH "IROCHINHA@ITELEFONICA.COM.BR"
       ADO COMMIT
    endif

    ADO CLOSE ALL

    return nil


Perceba que DROP/CREATE recriam a estrutura vazia, mas você pode usar o comando DELETE passando a ele sentenças SQL diversas:
...
   // ADO DELETE SuaSentenca
   ADO DELETE from tabela
...


Ou:
...
   // ADO DELETE SuaSentenca
   ADO DELETE * from tabela
...


Neste comando voce diz: "delete de...", "delete dentro...", "delete em...". Então voce estará limpando a tabela de seu conteúdo e não da estrutura.

Quanto a utilidade das funções, em outro build da biblioteca, colocarei no código os comentários sobre cada uma.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 07 Jan 2015 18:20
por Hasse
Boa tarde.

Estou batalhando uma forma trabalhar com o ADO, e preciso de ajuda.
Vejam o código abaixo, onde ocorre um erro na linha 25 - Variável NOME não existe.:
   StrConnect := "DRIVER=Firebird/InterBase(r) driver; UID=sysdba; PWD=masterkey; DBNAME=C:\Teste\Small.gdb"

   ADO CONNECT StrConnect

   ADO USE CliFor
   ? "ADOAreas:=>", Str( ADOAreas(), 04 ), "= ADOAlias:=>", ADOAlias()
   *
   oRecordSet := TOLEAUTO():New("ADODB.RecordSet")

   c_SeleStr := "select  NOME, ENDERE, CIDADE, ESTADO from CliFor"

   WITH Object oRecordSet
      *
      :cursorType       := adOpenDynamic //                                     // adOpenForwardOnly // adOpenForward // adOpenStatic //
      :activeConnection := oADOConection[nConnection]
      :cursorLocation   := adUseClient
      :maxRecords       := 100000
      :cacheSize        := 100
      :source           := c_SeleStr
      *
      :open()
      *
      IF ! :Eof()
         *
         ? NOME, ENDERE, CIDADE, ESTADO       && <<<======= LINHA DO ERRO.
         *
         :MoveNext()
         *
      ENDIF
      *
   END WITH

Evidente que estou cometendo um erro, e aceito sugestões para alterações profundas.

Num segundo momento quero sofisticar o Select para um formato semelhante ao abaixo:
c_SeleStr := "select  NOME c_Nome, ENDERE c_Ender, COMPLE c_Bairro, CGC c_CgcCpf, CIDADE c_Cidade, ESTADO c_Est, CEP c_Cep, FONE c_Fones, where c_Nome like '*Maria*' order by c_Nome"

Num terceiro momento preciso gravar dados na tabela.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 07 Jan 2015 18:43
por ANDRIL
Hasse escreveu:? NOME, ENDERE, CIDADE, ESTADO && <<<======= LINHA DO ERRO.

Não tenho nenhum conhecimento sobre o ADO, mas não seria o caso de tratar o objeto oRecordSet, onde os dados devem estar. Achei estranho voce acessar direto os campos, porem, se isso for possível, talvez haja um problema com a area em aberto que não contém estes campos citados no erro.

Boa sorte.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 07 Jan 2015 20:30
por rochinha
Amiguinhos,

Hasse, volte ao inicio da discussão e veja minha quinta postagem onde apresento um código de exemplo( CUSTOMER.PRG ).

Para manipular campos usando ADOxB voce deve usar a função ADOField():
...
?  ADOField( "NomeDoCampo" ), ...
...

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 08 Jan 2015 16:27
por Hasse
Boa tarde Rochinha.
Creia-me, antes de colocar a minha postagem anterior, fiz tantos testes com os co0mandos ADO que já nem sei mais quantos,
e sempre tem algum detalhe que não funciona.
Abaixo segue a parte inicial do código. Vejamos:
**
#include "adoXb.ch"
#include "AdoXb.prg"
*
#Include 'Inkey.ch'
#Include 'i_keybd.ch'
#include "MiniGUI.ch"
#include "ado.ch"
#include "set.ch"
#include "common.ch"
#include "directry.ch"
#include "fileio.ch"
#include "hbcompat.ch"
#include "hbwin.ch"
*
*STATIC oWnd, oClients, oClient, oName
*STATIC cName
*STATIC oSplit
*
REQUEST HB_GT_WIN_DEFAULT                                                 && Janela DOS - Temporário para testes.
*
*
*==================================================================================================
FUNCTION Main()
   *
   LOCAL oError       := ErrorBlock( { | oError | MyErrorFunc( oError ) } )
   *
   REQUEST HB_LANG_PT
   REQUEST HB_CODEPAGE_PT850
   HB_LANGSELECT("PT")
   HB_CDPSELECT( "PT850" ) //pt850
   *
   SET DATE TO BRIT
   SET CENTURY ON
   *
   Clear
   *
   PUBLIC StrDatabas := "C:\Teste\Small_ajustado.gdb"
   PUBLIC StrConnect := "DRIVER=Firebird/InterBase(r) driver; UID=sysdba; PWD=masterkey; DBNAME="+StrDatabas
   *
   // Necessária para criar objetos e variaveis visíveis o tempo todo
   ADOSetRDD( "ACCESS" )
   *
   ADOSetRDD( "FIREBIRD" )                // ADOGDB
   ADORDDDefault( "FIREBIRD" )            // ADOGDB
   cADORDD := "FIREBIRD"
   *
   SET_CORES()
   *
   Clear
   *
   ADO CONNECT StrConnect
   *
   ? "Is ADOConnected:>   "
   ?? ADOConnected()
   *
   ADO USE CliFor
   ? "ADOAreas:=>", Str( ADOAreas(), 04 ), "=           ADOAlias:=>", ADOAlias()
   
   WAIT
/*
Resposta do print acima:
Is ADOConnected:>   .T.
ADOAreas:=>    1 =           ADOAlias:=> CliFor
Press any key to continue...
*/

Então o sistema está conectado ao GDB e a tabela CLIFOR aberta. Esta tabela tem mais de 50 campos, mas para efeito de testes
vamos acessar somente as 3 primeiras colunas (com LEFT para caber na tela).
Como já relatado anteriormente,o ADOEof() não funciona. Entra em loop infinito quando chega no último registro.
WHILE ! ADOEof()
? Alltrim( Str( ADORecno() ) ),Left( ADOFIELD("NOME"), 20 ), Left( ADOFIELD( "CIDADE" ), 15 ), ADOFIELD( "CGC" )
ADOSkip()
ENDDO

Desativei essa rotina acima e estou usando a seguinte, que é uma gambiarra mas que, para os propósitos atuais funciona bem.
WHILE .T.
   ? Alltrim( Str( ADORecno() ) ),Left( ADOFIELD("NOME"), 20 ), Left( ADOFIELD( "CIDADE" ), 15 ), ADOFIELD( "CGC" )
   IF ADORecno() = ADORecCount()
      EXIT
   ENDIF
  ADOSKIP()
ENDDO
RETURN( NIL )

Usando esta rotina de listagem acima, irei anexar alguma funções descritas no ADOxb.prg e relatar as dificuldades que encontrei.

   ADOLocate( 'NOME = "Maria"' )
   ?  ADOFound(), "-", ADORecno(), "-", ADOField( 'NOME' ), ADOField( "CGC" )
   ADOLocate( 'NOME = "Maria*"' )
   ?  ADOFound(), "-", ADORecno(), "-", ADOField( 'NOME' ), ADOField( "CGC" )
   ADOFind( "NOME = 'Maria'" )
   ?  ADOFound(), "-", ADORecno(), "-", ADOField( 'NOME' ), ADOField( "CGC" )
   ADOFind( "NOME = 'Maria*'" )
   ?  ADOFound(), "-", ADORecno(), "-", ADOField( 'NOME' ), ADOField( "CGC" )
   ADOFind( "NOME like 'Adriane Maria'" )
   ?  ADOFound(), "-", ADORecno(), "-", ADOField( 'NOME' ), ADOField( "CGC" )
   wait
   WHILE .T.
      ? Alltrim( Str( ADORecno() ) ),Left( ADOFIELD("NOME"), 20 ), Left( ADOFIELD( "CIDADE" ), 15 ), ADOFIELD( "CGC" )
      IF ADORecno() = ADORecCount()
         EXIT
      ENDIF
      ADOSKIP()
      IF ADORecno() = 10
         WAIT
      ENDIF
   ENDDO

Veja o print gerado até no WAIT da linha 11:
.T. - 1 - Adalzira Muller Hefter 969.985.049-34
.T. - 1 - Adalzira Muller Hefter 969.985.049-34
.T. - 1 - Adalzira Muller Hefter 969.985.049-34
.T. - 1 - Adalzira Muller Hefter 969.985.049-34
.T. - 1 - Adalzira Muller Hefter 969.985.049-34
Press any key to continue...

Em todos os casos o ADOFound() informa que encontrou o alvo, pois tem mais de 20 Maria cadastradas, mas o apontador não foi deslocado para lá, e desta forma sempre o primeiro registro da tabela é apresentado.

O loop de listagem seguinte inicia no primeiro registro também.

Tenho mais uma dezena de dificuldades, mas acredito que uma vez solucionados e apontados os meus erros, os demais também serão corrigidos.

Me perdoe o tamanho desta mensagem, mas foi a única maneira de apresentar o problema todo. Caso haja necessidade posso enviar o arquivo GDB.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 22 Ago 2015 10:25
por Hasse
Bom dia Rochinha.

Mais uma vez necessito dos teus conhecimentos e gentileza.

Numa conexão com o ACCESS, via ADO, tenho como retorno um objeto tipo "oRecordSet".

Há alguma forma de conectar este objeto ao BROWSE ou GRID diretamente ?

Testei fazer o trabalho em 2 passos e funcionou, ou seja, ler o BD do ACCESS, arquivar os dados em ARRAY e em seguida conectar ao GRID, mas esta solução não satisfaz aos meus propósitos, já que não haverá atualização automática dos dados.

Caso esta conexão não seja possível, você tem alguma sugestão de uso de outra opção ?

Li no Fórum, que colegas elogiam muito o SQLMIX. Ele permite esta conexão direta ?

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 22 Ago 2015 11:32
por JoséQuintas
Num resumo:
A vantagem do SQL é trazer tudo pronto, menos consultas ao servidor/banco de dados.
O que está querendo é consultar o tempo todo, justamente o contrário do SQL.

É como querer um carro pra andar a pé, fica complicado até sugerir alguma coisa.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 22 Ago 2015 12:14
por rochinha
Amiguinhos,

Hasse, diferentemente do DBF que atua de forma mais automatica você deverá criar esta automatização.

Os recordsets são snapshots, fotografias de um trecho do banco de dados parecido com nossos dbfs temporários, mas no caso de um DBF temporário o que acontece no principal não aparece nele até que seja recriado, ou seja, limpa e appendado os dados refeitos.

Já os recordsets possuem esta característica idêntica, mas o motor se encarrega disto, mas o usuário precisa disparar a ação, através de comandos REQUERY.

Os recordsets trabalham de dois modos de atualização, sendo imediata ou por lote, resta estudar sobre o assunto.

Portanto esta ação de REQUERY precisa ser automatizada em sua aplicação..

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 23 Ago 2015 09:51
por Hasse
Bom dia Quintas e Rochinha.

Humm !!!! Alguns conhecimentos a mais.... Obrigado.

Realmente deu para entender. Terei que decidir se continuo com a ideia de implementar um BROWSE ou GRID.

No caso do REQUERY, como se automatiza este procedimento ?
Quais os passos e procedimentos ?
A Tabela disponibiliza uma flag que indicaria ao meu BROWSE ou GRID que os dados precisam ser atualizados ?

Caso este procedimento NÃO se mostre razoavelmente exequível, prático e confiável, terei que abandonar a ideia de BROWSE ou GRID.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 24 Ago 2015 08:40
por rochinha
Amiguinhos,

Hasse, o método REQUERY faz parte da classe RECORDSET, portanto se você criou um recordset de nome oRecordset bastará comandar oRecordset:Requery()

Você pode acrescentar uma ação ou botão para acionar este recurso ou colocár uma chamada após algum comando como Append ou Update.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 24 Ago 2015 09:12
por Hasse
Ok. Muito bom mesmo.

Assim bem fácil implementar a atualização.

Obrigado.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 24 Ago 2015 14:51
por JoséQuintas
Tem que lembrar o seguinte também:
O usuário consulta na tela... fica lá parado.
Se outro alterar, a tela não é atualizada automaticamente, nem mesmo se usar DBF.

Em que momento atualizar o browse/grid?
Talvez tenha atualização de tela que acostumamos com DBF, e só por isso queremos igual.
Se pensar direito, é até normal que o usuário tenha que refazer a pesquisa.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 24 Ago 2015 16:44
por Hasse
Valeu a lembrança Quintas.
Este teu procedimento é que faz com que este Fórum seja tão bom.
Nota-se que há pessoas que procuram dar do seu melhor. E isto é impagável.

Na realidade estou bem familiarizado com este detalhe. Eu uso o TBrowse() (ainda em modo console) e programei um refresh dos dados a cada 5 segundos.

Também estou ciente que, quando um determinado terminal abre uma tela de edição de dados e quando há alguma alteração na base de dados ela não será atualizada na tela de edição, mesmo que o TBrowse() já tenha se atualizado.

A grande maioria das telas de edição no universo dos meus clientes, quando há alguma edição, ela é feita a partir de um determinado terminal, justamente para evitar problemas.

Entretanto, há DUAS telas de edição críticas. Nestas, assim que a tela de edição é aberta, eu bloqueio o registro e assim evita-se que haja alguma alteração que fuja do controle. Esta tela de edição, caso ela fique inativa por 15 segundo será fechada automaticamente, e assim liberando o bloqueio do registro.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 17 Out 2015 13:54
por rochinha
Amiguinhos,

Em resumo o computador somente computa, o usuario somente usa, ou seja, os dois so fazem o que o programador estipulou. Ao automatizar damos vida propria ao computador liberando a produtividade do usuario.

Hasse,
1-Voce esta usando ADO em producao(interrogacao)
2-Voce se baseou no ADOxB(interrogacao)

No caso uma tela, com um browse principal e outro browse(ex: clientes(principal) e venda(sub-browse)) como voce esta vinculando os registros do sub-browse com o browse, tipo o que fazemos com set filter, set relation ou set scope(interrogacao)

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 17 Out 2015 14:58
por Hasse
Boa tarde caro Rochinha.

Na realidade a minha aplicação não tão complicada assim.

Uso relacionamento de dados, mas é somente para a obtenção de dados de 2 tabelas diferentes, mas que não são enviadas para o TBrowse().

Uso algo semelhante conforme a figura Anexa, onde a coluna bem à direita, dentro de um retângulo vertical, lista os códigos dos exames requisitados para o paciente, neste caso, ROLAND KLUG. Os dados da Requisição do ROLAND KLUG estão num TBROWSE. O arquivo das Requisições estão relacionadas (SET RELATION) com o arquivo de Exames, mas a impressão dos respectivos códigos na tela é feito por um FOR/NEXT, já que ali não há edição. O resultado é muito rápido. A construção da tela é tão rápida que não se percebe. Este aplicativo está rodando em monitor. Neste caso não posso usar o SET FILTER porque a base de dados é muito grande. O arquivo de Requisições tem em torno de 960.000 registros, e o de Exames tem ao redor de 6.000.000 de registros (são 6 minhões mesmo !!!).

Em relação ao ADO. Uso o ADOxB para abrir e ler um Banco Oracle e inserir os dados lidos no arquivo de Requisições e Exames, sem qualquer edição manual. Este aplicativo roda em modo gráfico, mas é uma telazinha muito pequena, de 3 linhas e umas 25/30 colunas. A edição, caso haja necessidade é feita no TBrowse() de Requisições.

Espero que a minha explanação tenha sido clara suficiente.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 17 Out 2015 18:24
por rochinha
Amiguinhos,

Hasse,
Espero que a minha explanação tenha sido clara suficiente.


Com certeza foi sim. Obrigado.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 09 Jun 2016 12:46
por Kapiaba
Bom dia Rochinha, links estão quebrados, preciso do Firbird para ODBC, para abrir um banco do Firebird. .GBD.

Obg. abs.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 09 Jun 2016 20:30
por Hasse
Este link funciona. Acabei de testar.

Você precisa do ODBC para Firebird. Há 2 versões: para 32 e para 64 bit.

http://www.firebirdsql.org/en/odbc-driver/

Se você tiver dificuldades com a configuração do ODBC, eu tenho um passo-a-passo para ODBC for Oracle. Claro que deve haver algumas diferenças, mas por analogia creio que você poderá ter sucesso.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 31 Mar 2022 09:42
por sasquast
Pessoal, tudo bem ?

Estou chegando agora em 2022 para ler esse tópico e a maioria dos links infelizmente estão quebrados. É possível alguém subir um pacote com programa exemplo com conexão com o MySQL que o Sr Rochinha subiu no oitavo post desse tópico ? Uso xHarbour.

Obrigado.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 31 Mar 2022 11:07
por alxsts
Olá!

Veja Tutorial de ADO. Utilize a busca do Fórum. Tem bastante material disponível...

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 31 Mar 2022 12:00
por sasquast
Muito obrigado.

Irei seguir a partir daí.

*** ADOxb - BIblioteca de funções de Acesso SQL ***

MensagemEnviado: 06 Jun 2022 11:14
por rochinha
Amiguinhos,

alxsts e sasquat deêm uma olhada no meu espaço no 4shared https://www.4shared.com/account/home.jsp#dir=hevAdQKs