Não testei.
Chamei o recordset de oTemporario, assim acho que fica mais claro que seria algo similar a um arquivo temporário.
#include "inkey.ch"
STATIC oConexao
PROCEDURE Main
ConfiguraConexao()
oConexao:Open()
SET CENTURY ON
SET DATE BRITISH
SET EPOCH TO 2001
SET DELETE ON
SET MESSAGE TO 24 CENTER
SetMode( 25, 80 )
SET COLOR TO W/N,W/GR+,,,G+/N
CLS
TelaInicial()
@ 02,01 TO 02,80
@ 23,01 TO 23,80
@ 01,01 SAY space(80) COLOR "W/B"
@ 01,01 SAY "LOTES - Aprendizado Harbour e xHarbour" COLOR "W/B"
@ 01,70 SAY date() COLOR "W/B"
memoria = memory()
@ 03,54 SAY memory() pict "9,999,999,999"
@ 03,68 SAY "Kb Mem¢ria"
dc = " "
// OPERACAO
do while .t.
wlote = space(07)
westado = space(02)
wdt_entrada = datavol4(space(08))
wdias = 0
wdt_saida = datavol4(space(08))
wqtde = 0
wvlr_unit = 0
wvlr_total = 0
Msg( "Informe o LOTE [branco] finaliza" )
@ 09,34 SAY "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"
@ 10,34 SAY "³ Lote....: °°°°°° ? Pesquisa ³"
@ 11,34 SAY "³ ³"
@ 12,34 SAY "³ Estado..: °° °°°°°°°°°°°°°°°°°°° ³"
@ 13,34 SAY "³ ³"
@ 14,34 SAY "³ Entrada Dias Devolu‡„o ³"
@ 15,34 SAY "³ ÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄ ³"
@ 16,34 SAY "³ °°/°°/°°°° + °°°° = °°/°°/°°°° ³"
@ 17,34 SAY "³ ³"
@ 18,34 SAY "³ Qtde Unit rio Valor Total ³"
@ 19,34 SAY "³ ÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ ³"
@ 20,34 SAY "³ °°°°°°°°° x °°°°°.°°° = °°°°°°°°°.°° ³"
@ 21,34 SAY "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"
@ 22,34 SAY " "
@ 10,46 get wlote pict "@!"
read
if Empty( wlote ) .OR. LastKey() == K_ESC
clear
EXIT
endif
if wlote = "?"
consulta()
loop
endif
// consulta
oTemporario := oConexao:Execute( "SELECT * FROM LOTES WHERE LOTE=" + Ltrim( Str( wLote ) ) )
IF oTemporario:RecordCount() != 0
westado = oTemporario:Fields( "ESTADO" ):Value
wdt_entrada = datavol4( oTemporario:Fields( "DT_ENTRADA" ):Value )
wdias = oTemporario:Fields( "DIAS" ):Value
wdt_saida = datavol4( oTemporario:Fields( "DT_SAIDA" ):Value )
wqtde = oTemporario:Fields( "QTDE" ):Value
wvlr_unit = oTemporario:Fields( "VLR_UNIT" ):Value
wvlr_total = oTemporario:Fields( "VLR_TOTAL" ):Value
@ 12,46 GET westado
@ 16,36 GET wdt_entrada
@ 16,52 GET wdias pict "9999"
@ 16,60 GET wdt_saida
@ 20,36 GET wqtde pict "9,999.999"
@ 20,48 GET wvlr_unit pict "9,999.999"
@ 20,60 GET wvlr_total pict "9,999,999.99"
CLEAR GETS
EstadoOk( wEstado ) // mesma da validação
Msg( "Registro existente. Deseja Alterar, Excluir ou Voltar ? ... A/E/V ..." )
@ 24,73 get dc pict "!" valid dc $ "AEV"
read
if upper(dc) = "V" .OR. LastKey() == K_ESC
loop
elseif upper(dc) = "A"
woquefazer = "ALT"
elseif upper(dc) = "E"
woquefazer = "EXC"
endif
else
woquefazer = "INC"
endif
oTemporario:Close()
// exclusao
if woquefazer = "EXC"
IF MsgSimNao( "Confirma a exclus„o do Lote " + rtrim(wlote) + " ? ... S/N ..." )
oTemporario := oConexao:Execute( "SELECT COUNT(*) AS QTD FROM LOTES WHERE LOTE=" + Ltrim( Str( wLote ) ) )
IF oTemporario:Fields( "QTD" ):Value == 0
alert ( "Erro - chamar CPD - registro n„o existe mais" )
else
oConexao:Execute( "DELETE FROM LOTES WHERE LOTE=" + Ltrim( Str( wLote ) ) )
endif
oTemporario:Close()
endif
loop
endif
// inclusao e alteracao
if woquefazer = "INC"
@ 22,35 SAY "Registro Novo" COLOR "GR+/N"
elseif woquefazer = "ALT"
@ 22,35 SAY "Edição de Registro" COLOR "GR+/N"
endif
@ 12, 46 GET wEstado PICTURE "@!" VALID EstadoOk( wEstado ) MESSAGE "Informe o ESTADO, ESC abandona"
@ 16, 36 GET wDt_Entrada VALID Dtos( wDt_Entrada ) >= "20150101" .AND. wDt_Entrada <= Date() MESSAGE "Informe a Data de Entrada, ESC abandona"
@ 16, 52 GET wDias PICTURE "9999" VALID wDias > 0 MESSAGE "Informe a qtde. de dias, ESC abandona"
@ 16, 60 GET wDt_Saida WHEN ( wDt_Saida := wDt_Entrada + wDias, .F. )
@ 20, 36 get wqtde PICTURE "9,999.999" valid wqtde >= 0 MESSAGE "Informe a Quantidade, ESC abandona"
@ 20, 48 get wvlr_unit PICTURE "9,999.999" valid wvlr_unit >= 0 MESSAGE "Informe o valor unitário, ESC abandona"
@ 20, 60 GET wVlr_Total PICTURE "9,999,999.99" WHEN ( wVlr_Total := wQtde * wVlr_Unit, .F. )
READ
Inkey(3)
if LastKey() != K_ESC
if woquefazer = "INC"
oConexao:Execute( "INSERT INTO LOTES ( LOTE ) VALUES ( " + Ltrim( Str( wLote ) ) )
endif
oConexao:Execute( [UPDATE LOTES SET ] + ;
[ESTADO='] + wEstado + [', ] + ;
[DT_ENTRADA='] + Dtos( wDt_Entrada ) + [', ] + ;
[DIAS=] + Ltrim( Str( wDias ) ) + [, ] + ;
[DT_SAIDA="] + Dtos( wDt_Saida ) + [", ] + ;
[QTDE=] + Ltrim( Str( wQtde ) ) + [, ] + ;
[VLR_UNIT=] + Ltrim( Str( wVlr_Unit ) ) + [, ] + ;
[VLR_TOTAL=] + Ltrim( Str( wVlr_Total ) ) + [ ) ] + ;
[WHERE LOTE=] + Ltrim( Str( wLote ) ) )
endif
enddo
oConexao:Close()
RETURN
FUNCTION Msg( cTexto )
@ 24,01 SAY space(80)
IF cTexto != NIL
@ 24,03 SAY cTexto COLOR "GR+/N"
ENDIF
RETURN NIL
FUNCTION MsgPausa( cTexto )
Msg( cTexto )
inkey(0)
Msg()
RETURN NIL
FUNCTION MsgSimNao( cTexto )
Msg( cTexto )
@ Row(), Col() + 2 GET cResposta PICTURE "!" VALID cResposta $ "SN"
READ
Msg()
RETURN cResposta
FUNCTION datavol4( wdv_Data )
//set century on
w_data_dv = ctod(subst(wdv_data,7,2)+"/"+subst(wdv_data,5,2)+"/"+subst(wdv_data,1,4))
return w_data_dv
STATIC FUNCTION TelaInicial()
@ 07,59 SAY "CLIPPER BASICO"
@ 03,01 SAY "PROC01 Clipper ³"
@ 04,01 SAY " ³"
@ 05,01 SAY "PROC11 Harbour Local DBF ³"
@ 06,01 SAY "PROC12 Harbour Remoto DBF ³"
@ 07,01 SAY "PROC13 Harbour Remoto MYSQL ³"
@ 08,01 SAY " ³"
@ 09,01 SAY "PROC21 xHarbour Local DBF ³"
@ 10,01 SAY "PROC22 xHarbour Remoto DBF ³"
@ 11,01 SAY "PROC23 xHarbour Remoto MYSQL ³"
@ 12,01 SAY "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"
@ 16,01 SAY "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"
@ 17,01 SAY "- Testando os campos b sicos ³"
@ 18,01 SAY "- C lculo de Data + Dias ³"
@ 19,01 SAY "- Inclus„o/Altera‡„o/Exclus„o³"
@ 20,01 SAY "- Uso DbEdit para Consulta ³"
@ 21,01 SAY "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"
RETURN NIL
STATIC FUNCTION EstadoOk( cEstado )
LOCAL oTemporario, lOk := .T.
oTemporario := oConexao:Execute( [SELECT * FROM ESTADO WHERE ESTADO='] + cEstado + ['] )
IF oTemporario:RecordCount() == 0
Alert ( "Estado não encontrado" )
lOK := .F.
ELSE
@ 12,49 SAY oTemporario:Fields( "ESTADO" ):Value COLOR "G+/N"
ENDIF
oTemporario:Close()
RETURN lOk
STATIC FUNCTION ConfiguraConexao()
oConexao := win_OleCreateObject( "ADODB.Connection" )
oConexao:ConnectionString := "Driver={MySQL ODBC 3.51 Driver};Server=NomeServidor;" + ;
"Option=131072;Stmt=;Database=NomeBanco;User ID=NomeUsuario;Password=Senha;Collation=latin1;"
oConexao:CursorLocation := 3 // local recordset
oConexao:CommandTimeOut := 120 // seconds
oConexao:ConnectionTimeOut := 120 // seconds
RETURN NIL
Considerações:
oTemporario:Fields( "NOME" ):Value
Isso equivale a pegar o conteúdo do campo chamado NOME
oTemporario:RecordCount()
O próprio nome já diz. Contador de registros. Quantos registros foram retornados.
Uma diferença no ADO é que não se pode testar EOF em arquivo vazio., dá erro. A saÃda é usar o RecordCount()
oTemporario:Close()
Seria o equivalente a apagar o temporário. Na prática não existe nada em disco.
oTemporario := oConexao:Execute( ... )
Vai executar o comando na conexão. O retorno vai ser o equivalente a um arquivo temporário contendo registros ou não.
oConexao:Open()
Abre a conexão, é por essa conexão que o terminal conversa com o servidor, e vice-versa.
oConexao:Close()
Encerra a conexão.
INSERT INTO LOTES ( CAMPO ) VALUES ( VALOR )
Inclui um registro na tabela LOTES, gravando no CAMPO o VALOR.
UPDATE LOTES SET CAMPO=VALOR WHERE LOTE=x
Atualiza no arquivo LOTES, aonde o LOTE for número x, alterando o CAMPO para VALOR
DELETE FROM LOTES WHERE LOTE=x
Apaga do arquivo LOTES, aonde o LOTE for número x
De resto, no SQL string é entre aspas simples, e número é direto o número.
Por isso no comando SQL tem que acrescentar aspas, ou transformar o número em string pra ter a linha de comando.
No meu caso, preferi usar funções pra esse tipo de coisa.
Exemplo: StringSql( campo )
FUNCTION StringSql( cCampo )
RETURN ['] + cCampo + [']
Além de evitar erro nos abrir/fechar aspas, já coloco tratamento de alguns caracteres especiais.
No browse, teria que fazer uma conversão total de oTemporario pra DBF.
dbCreate( "TEMP", ...estrutura )
USE TEMP
oTemporario := oConexao:Execute( "SELECT * FROM LOTES" )
IF oTemporario:RecordCount() > 0
DO WHILE .NOT. oTemporario:Eof()
APPEND BLANK
REPLACE temp->Lote WITH oTemporario:Fields( "LOTE" ):Value, ;
temp->Dt_Entrada WITH oTemporario:Fields( "DT_ENTRADA" ):Value, ;
...
oTemporario:MoveNext()
ENDDO
ENDIF
oTemporario:Close()
oTemporario:MoveNext() é o equivalente de SKIP.
No momento com ADO estou usando esse esquema, estilo arquivo temporário, e convertendo se necessário.
Ah sim... a compilação do fonte final em Harbour:
hbmk2 lote01 c_lote hbwin.hbc
O outro fonte c_Lote:
Teria que ter a rotina acima, e o restante fica igual, mas tendo que criar os Ãndices também como temporários.
A diferença é não ter que salvar/retornar área em uso, porque não existe.
Pra arquivos gigantes, o ideal seria primeiro pedir algum tipo de filtro, para só depois mostrar para o usuário.
O que mudaria pro temporário, seria sua criação mais rápida, com menos registros.
oTemporario := "SELECT * FROM LOTES WHERE DT_ENTRADA >= '20150101' AND DT_ENTRADA <= '20150131'"