Jump to content
Fivewin Brasil

Ariston Santos

Membros
  • Posts

    500
  • Joined

  • Last visited

  • Days Won

    11

Posts posted by Ariston Santos

  1.  

    3 horas atrás, edutraini disse:

    bom dia a todos

    Fiz o teste com a rotina do Ariston e funcionou perfeitamente

    O unico problema nesse momento esta relacionado aos campos memo

    Alguns registro deram erro na hora de migrar para tabela

    Percebi que nesse registro foram gravados caracteres estranhos, provavelmente o usuario digitou ou colou da internet algum texto 

    Usando o slqexpress em cima do windows ele nao da erro mas usando o mariadb em um servidor linux ele nao vai

    Provavelmente terei que jogar somente a estrutura do arquivo para o banco de dados e depois na hora de importar os dados tentar tratar esses campos tirando esses caracteres

    Sera que é isso mesmo

    Obrigado a todos

    Edu

    A rotinha não é minha. Parece que é de Jmsilva

    Uma sugestão é modificar a função Any2SqlStr(uVal), inserindo uma função que remova os caracteres especiais dos campos memo  nesta linha:

    ELSEIF VALTYPE(uVal) = "M" ; Dados := "'"+STRTRAN(ALLTRIM(uVal), "'", "")+"'"

    Remova tudo que não for letras e números, inclusive CR e LF. Deixe apenas caracteres normais.

  2. Tive o mesmo erro. Depois de alguns ajustes, ficou assim:

    Procedure BkpNuvem()
       Local aFiles,cFile,cTable,nTime,oErr,aDBF,nI
       
       oSql := SR_GetConnection()
       cDBN := UPPER( SR_GetConnectionInfo(, SQL_DBMS_NAME ) )
       SR_End()
       CLOSE ALL
    
       Set AutOpen OFF
       aDBF := Directory(cPasta+"\*.dbf")
    
       aFiles :={}
       For nI:=1 TO Len(aDBF)
          AAdd(aFiles,Trim(aDBF[nI,1]))
       Next
       
       nTot := Len(aFiles)
       nReg := 0
       nMtr := 0
       cSay := "Salvando backup em nuvem. Aguarde..."
    
       DEFINE DIALOG oDmeter FROM 0,0 TO 6, 35 TITLE "Verificação de dados" STYLE DS_MODALFRAME
       @05,05 SAY oSay PROMPT cSay PIXEL SIZE 130, 10 OF oDmeter UPDATE
       @15,05 METER oMeter VAR nMtr TOTAL nTot SIZE 130, 12 OF oDmeter UPDATE PIXEL
       ACTIVATE DIALOG oDmeter CENTER NOWAIT VALID (!GetKeyState( VK_ESCAPE ) .AND. !GetKeyState( VK_MENU ))
       SysRefresh()
    
       nTime:=Seconds()
       For Each cFile IN aFiles
          cTable := Lower(cFileNoExt(cFile))
          cSay := "Salvando backup de "+cTable+"..."
          oDmeter:Update()
          Try
             USE &(cTable) EXCLUSIVE NEW VIA "DBFCDX" // DBUseArea(.T.,"DBFCDX",cFile,"TEMP",.F.)
             If LastRec() > 0
                FastTurbo("bkp_"+cTable)
             Endif
             DBCloseArea()
          Catch oErr
             XBrowser oErr title cFile
             DBCloseArea()
          End
          nReg ++
          oMeter:Set(nReg)
          oMeter:Refresh()
       Next
       
       nReg := nTot
       oMeter:Set(nReg)
       oMeter:Refresh()
       SysWait(0.25)
       oDmeter:End()
    
       MsgStop("Backup em nuvem concluído em "+SecToTime(Seconds()-nTime)+"h.", "Informação do sistema")
       * AbreDados()
    Return
    
    **=====================================================================
    Static Function FastTurbo(cTable)
       Local aStru := DBStruct()
       Local cSql
       n_Conn := nConection(2)
       IF n_Conn = 0 ; RETURN NIL ; ENDIF
       If Sr_ExistTable(cTable)
          Sr_DropTable(cTable)
       Endif
       cComm := XB2SqlStr(aStru, cTable)
       nErr := SR_GetConnection():Execute( cComm )
       DBGoTop()
       Do While !Eof()
          cSql := SqlInsert(cTable, aStru)
          SR_GetConnection():Execute(cSql)
          DBSkip()
       Enddo
       Sr_GetConnection():Commit()
    Return nil
    
    **=====================================================================
    Static Function SqlInsert(cTable,aStru)
       Local nI,uVal,aCampos:={},cSql
    
       For nI:=1 To Len(aStru)
          uVal := FieldGet(nI)
          uVal := Any2SqlStr(uVal)
          AAdd(aCampos,{aStru[nI,1],uVal})
       Next
       //Define os campos
       cSql := "Insert Into "+cTable+" ("+aCampos[1,1]
       For nI:=2 To Len(aCampos)
          cSql += ","+aCampos[nI,1]
       Next
       //define os dados
       cSql += ") Values ("+aCampos[1,2]
       For nI:=2 To Len(aCampos)
          cSql += ","+aCampos[nI,2]
       Next
       cSql+=");"
    Return cSql
    
    FUNCTION XB2SqlStr(aStr, cDBase)
       LOCAL cStrct
       cStrct := "CREATE TABLE `"+LOWER(cDBase)+"` ("
       FOR nF := 1 TO LEN(aStr)
       	 IF LOWER(aStr[nF,1]) !=  "sr_recno"
    	       IF nF > 1 ; cStrct += ", " ; ENDIF // Mais de um campo
    	       cStrct += "`"+LOWER(aStr[nF,1])+"` "+SetFType(aStr[nF,2],aStr[nF,3],aStr[nF,4])
           ENDIF
       NEXT
       IF LEN(aStr) > 0 ; cStrct += ", " ; ENDIF // Já acrescentado algum campo
       cStrct += "`sr_recno` BIGINT (15) NOT NULL UNIQUE AUTO_INCREMENT)" // Sempre criar o 'sr_recno' no final, para compatibilizar com SQLRDD
    RETURN( cStrct )
    
    STATIC FUNCTION SetFType(cTipo,nSize,nDeci)
       LOCAL cFType
       IF cTipo = "C"
          IF nSize <= 255
             cFType := "char("+ALLTRIM(STR(nSize))+")"
          ELSE
             cFType := "mediumblob"
          ENDIF
       ELSEIF cTipo = "M" ; cFType := "mediumblob"
       ELSEIF cTipo = "N" ; cFType := "double("+ALLTRIM(STR(nSize))+","+ALLTRIM(STR(nDeci))+")"
       ELSEIF cTipo = "L" ; cFType := "tinyint(4)"
       ELSEIF cTipo = "D" ; cFType := "date"
       ENDIF
    RETURN(cFType)
    
    STATIC FUNCTION Any2SqlStr(uVal)
       LOCAL Dados := ""
       IF VALTYPE(uVal) = "C" ; Dados := "'"+STRTRAN(ALLTRIM(uVal), "'", "")+"'"
       ELSEIF VALTYPE(uVal) = "M" ; Dados := "'"+STRTRAN(ALLTRIM(uVal), "'", "")+"'"
       ELSEIF VALTYPE(uVal) = "D" ; Dados := "'"+SR_dtosdot(uVal)+"'"
       ELSEIF VALTYPE(uVal) = "N" ; Dados := ALLTRIM(STR(uVal))
       ELSEIF VALTYPE(uVal) = "L" ; Dados := "'"+IIF(uVal = .T., "1", "0")+"'"
       ENDIF
    RETURN(Dados)

    Mas ainda deu um erro no meio do upload de uma das tabelas. Ainda vou verificar ou que houve.

  3. Acredito que via arquivo de lotes você consiga.

    Segue uma ideia que pode ser executada pelo seu programa:

    if file("c:\sistema\aco32_novo.exe")
       IF MsgNoYes("Existe uma nova versão do sistem. Gostaria de atualizar agora?", "Nova versão")
          cAtuInf := "@ECHO OFF"+CRLF+;
                     "COLOR F1"+CRLF+;
                	  'TASKKILL /IM aco32.exe /F'+CRLF+;
                	  'TIMEOUT /T 2 /NOBREAK'+CRLF+; // Esperar 2 segundos ignorando pressionamento de teclas
                	  'DEL aco32.exe'+CRLF+;
                	  'REN aco32_novo.exe aco32.exe'+CRLF+;
                     "START aco32.exe"+CRLF+;
                     "EXIT"
          if file(".\updaco32.bat") ; ferase(".\updaco32.bat") ; endif
          arq2 := fcreate(".\updaco32.bat")
          fwrite(arq2, cAtuInf)
          fclose(arq2)
          WAITRUN( GetEnv( 'ComSpec' )+' /C START .\updaco32.bat"', 0 )
          SysWait(10) // Precisa disso, senão o programa prossegue com a execução
       ENDIF
    ENDIF

     

  4. Em 20/11/2021 at 18:51, kapiaba disse:

    Jesus Ariston, qual o intuito disso? abs.

    É José Ariston :D

    O intuito dessa função é me informar se o EXE está aberto no PC local e/ou no servidor.
    Isso me ajuda em algumas decisões, tipo:
    Posso atualizar o programa?
    Posso reiniciar o servidor?

  5. 9 horas atrás, Ladinilson disse:

    Teu café parece ser o mesmo que o meu mano kkk

    O mesmo que o nosso. :D

     

    Só para complicar mais um pouco...

     

       // Para avisar ao servidor que aqui o aplicativo está aberto
       cLocal := gete('CLIENTNAME') ; cPref := "CLI:"
       if empty( cLocal )
          cLocal := gete('COMPUTERNAME') ; cPref := "PC:"
       endif
       if empty( cLocal )
          cLocal := gete('USERNAME') ; cPref := "USR:"
       endif
       cApelid := Alltrim(cFileNoExt(HB_ARGV(0)))+"_"+cLocal
       
       cFiSrv := cPasta+"\"+ALLTRIM(cApelid)+".tmp" //
       cFoldr := STRTRAN(UPPER(cPasta), "\DADOS", "\FOTOS")
       cFlXml := STRTRAN(UPPER(cPasta), "\DADOS", "\BKPXML")
       cFlRes := STRTRAN(UPPER(cPasta), "\DADOS", "\resp_nfe")
       cFiLoc := CurDrive()+":\"+CurDir()+"\"+ALLTRIM(cApelid)+".tmp"
       if file(cFiSrv)
          fErase(cFiSrv) // Tenta eliminar o arquivo de controle no servidor.
          if fError() <> 0 // Não excluiu. Sistema já aberto no servidor.
    	      fErase(cFiLoc) // Tenta eliminar o arquivo de controle localmente.
    	      if file(cFiLoc) // Não excluiu. Sistema já aberto aqui também.
                IF ! lReOpen
                   GeneralUnlock() // Remover o bloqueio geral, só para garantir.
    	      	   SysRefresh() ; MsgWait("Sistema já aberto!","Atenção!...", 1)
    	      	ELSE
                   IF MsgNoYes("Sistema já aberto. Gostaria de reinicializar?","Sistema já aberto")
                      cAtuInf := "@ECHO OFF"+CRLF+;
                                 "COLOR F1"+CRLF+;
                            	  'TASKKILL /IM '+Alltrim(cFileNoExt(HB_ARGV(0)))+'.EXE /F /FI "USERNAME eq '+gete('USERNAME')+'"'+CRLF+;
                            	  'TIMEOUT /T 2 /NOBREAK'+CRLF+; // Esperar 2 segundos ignorando pressionamento de teclas
                                 "START "+Alltrim(cFileNoExt(HB_ARGV(0)))+".EXE"+CRLF+;
                                 "EXIT"
                      if file(".\reabrir.bat") ; ferase(".\reabrir.bat") ; endif
                      arq2 := fcreate(".\reabrir.bat")
                      fwrite(arq2, cAtuInf)
                      fclose(arq2)
                      GeneralUnlock() // Remover o bloqueio geral, só para garantir.
                      WAITRUN( GetEnv( 'ComSpec' )+' /C START .\reabrir.bat"', 0 )
                      SysWait(10) // Precisa disso, senão o programa prossegue com a execução
                   ENDIF
    	      	ENDIF
    		      SETFOREGROUNDWINDOW( FINDWINDOW( 0, cFileNoExt(HB_ARGV(0))+" - Gestao Comercial" ) ) // Para evitar erro de codepage, deixar sem acento o titulo da janela principal
    		      PostQuitMessage( 0 )
    		      QUIT
    		   ENDIF
    	   ENDIF
       ENDIF
       SRFhnd := fCreate(cFiSrv) // Cria o arquivo de controle no servidor
       SRFhnd := fOpen(cFiSrv,1) // Abre travando o arquivo de controle no servidor
       LOChnd := fCreate(cFiLoc) // Cria o arquivo de controle localmente
       LOChnd := fOpen(cFiLoc,1) // Abre travando o arquivo de controle localmente

     

  6. Até onde sei, tem que informar as tags do grupo Rastro

    <NFe>
      <infNFe versao="4.00" Id="NFe...">
        ...
        <det nItem="1">
          <prod>
            ...
            <rastro>
              <nLote>ABC123</nLote>
              <qLote>12.345</qLote>
              <dFab>2017-01-01</dFab>
              <dVal>2017-12-31</dVal>
              <cAgreg>123 </cAgreg>
            </rastro>
            ...
          </prod>
          ...
        </det>
        ...
      </infNFe>
    <Nfe>

     

  7. Mais perguntas :)

    • Não precisa de um DBAPPEND no dbf? É sempre apenas um registro, apenas incrementando SEQ->REQUISICAO+1?
    • xNewSequencial já vem incrementado?
    • SEQ->( DbSkip(0)  ) é realmente necessário?

  8. Um exemplo de SELECT com paginação para SQLRDD, especificamente na função GetVndList(...)

    /******************************************************************************
    * Nome do PRG: cadvendas  (Criada em 11/05/2020) - ARSOFT INFROMÁTICA         *
    * Função.....: Módulo para consulta de vendas no BD remoto (online)           *
    * Autor......: Ariston Santos                                                 *
    * Site.......: http://www.arsoft-ap.com.br                                    *
    * Contato....: ariston.ap@hotmail.com; suporte@arsoft-ap.com.br               *
    ******************************************************************************/
    
    #include "FiveWin.ch"
    #include "xbrowse.ch"
    #include "vlib.ch"
    
    *--- (SqlRDD includes ) ---*
    #include "sqlrdd.ch"
    #include "firebird.ch"
    
    STATIC aVndInf, aOcpItn, aVndNul, aVndColWd, aVndSavWd, aNfColWd2, aNfSavW2, cQPesq, cCPesq
    STATIC cVndQry, cVndQpg, cVndQrc, cVndSkp, cVndLsk
    STATIC xVa01, xItn02, xItn03, xItn04, xItn05, xItn06, xItn07, xItn08, xItn09, xItn10, xItn11, xItn12, xItn13, xItn14, xItn15, xItn16, xItn17, xItn18, xItn19, xItn20,;
           xItn21, xItn22, xItn23, xItn24, xItn25, xItn26, xItn27, xItn28, xItn29, xItn30, xItn31, xItn32, xItn33, xItn34, xItn35, xItn36, xItn37, xItn38, xItn39, xItn40,;
           xItn41, xItn42, xItn43, xItn44, xItn45, xItn46, xItn47, xItn48, xItn49, xItn50, xItn51, xItn52, xItn53, xItn54, xItn55, xItn56, xItn57, xItn58, xItn59, xItn60, xItn61
    
    FUNCTION CtrlVendas()
       n_Conn := nConection(.F., .F.)
       IF n_Conn <= 0 ; RETURN NIL ; ENDIF
    
       aVndNul := {}
       aVndInf := {}
    
       aLetra := {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}
    
       cCPesq := SPACE(50)
       cQPesq := "Nome cliente"
       aQPesq := {"Nome cliente", "Fantasia", "CPF/CNPJ", "Nome vendedor", "Data venda", "Data entrega", "Código venda", "Cód. cliente", "Cód. vendedor"}
       cVndQrc := 0
       cVndQpg := 0
       cVndLsk := 0
       cVndSkp := 0
       
       GetVndList(0,"*","",NIL,NIL,.f.,"New")
       IF LenArray(aVndInf,30) > 0
          aOcpItn := OrdGetItms(aVndInf[1,1], aVndInf[1,2])
       ELSE
          aOcpItn := OrdGetItms(0, "")
       ENDIF
    
       DEFINE FONT oDFont NAME "TAHOMA" SIZE 0, -13
       DEFINE FONT oFBold NAME "Verdana" SIZE 0, -14 BOLD
       DEFINE FONT oXBfon NAME "Arial Narrow" SIZE 0,-15
    
       XBrNumFormat( 'E', .t. )
    
       SysRefresh()
       DEFINE DIALOG oCadDlg FROM 0, 0 TO 35, 100 TITLE "Consulta de venda online"
       oCadDlg:lHelpIcon := .f.
    
       @02,005 SAY oSayPsq PROMPT "Procurar por:" OF oCadDlg SIZE 70,10 PIXEL
       @12,005 COMBOBOX oCBox VAR cQPesq ITEMS aQPesq SIZE 70, 50 PIXEL OF oCadDlg
    
       @02,080 SAY "Procurar (Asterisco '*' para mostrar todos os registros)" OF oCadDlg SIZE 310,10 PIXEL
       @12,080 GET oGetPsq VAR cCPesq OF oCadDlg SIZE 310,12 PIXEL UPDATE VALID GetVndList(1,@cCPesq,"",oXbVnd,oCadDlg,.t.,"New")
    
       @25,05 TABS oPTabs PROMPTS "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z" OF oCadDlg ;
              PIXEL SIZE 385.00, 20.00 ACTION (cCPesq := aLetra[oPTabs:nOption], GetVndList(2,@cCPesq,"",oXbVnd,oCadDlg,.f.,"New"), EVAL({||oXbItn:bChange}), IIF(LEN(aVndInf)=0,(aOcpItn := OrdGetItms(0, ""),oXbItn:SetArray(aOcpItn), oXbItn:MakeTotals(), oXbItn:Refresh()),NIL)) // TABS provide nOption automatically
              oPTabs:cToolTip := "Filtar apelido ou nome que inicie por esta letra"
    
       aVndColWd := array(61) // Qtd de colunas
                    * 7,  8, 25,  16,  17, 24,  29, 30, 31, 32, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,  50, 51,  52;
       aVndColWd := {60, 30, 70, 250, 150, 80, 120, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 150, 25, 150}
       @33,05 GROUP oGrp PROMPT "" OF oCadDlg SIZE 385, 125
       @33,05 XBROWSE oXbVnd OF oCadDlg SIZE 284, 125 PIXEL ARRAY aVndInf ;
              COLUMNS "", 8, 25, 16, 17, 25, 29, 30, 31, 32, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52;
              HEADERS "Data", "Hora", "Doc. cliente", "Nome/Razão social do cliente", "Fantasia/Local de trabalho do cliente", "CPF/CNPJ", "Operação", "Vlr. Itens", "Desconto itens", "Desconto final", "Acréscimo %", "Mão de obra R$", "Couvert R$", "Meio Pg 01", "Meio Pg 02", "Meio Pg 03", "Meio Pg 04", "Meio Pg 05", "Meio Pg 06", "Meio Pg 07", "Meio Pg 08", "Meio Pg 09", "Meio Pg 10", "Meio Pg 11", "Operador", "Cód. vendedor", "Nome vendedor";
              COLSIZES aVndColWd ;
              ON CHANGE (aOcpItn := OrdGetItms(aVndInf[oXbVnd:nArrayAt,1], aVndInf[oXbVnd:nArrayAt,2]), oXbItn:SetArray(aOcpItn), oXbItn:MakeTotals(), oXbItn:Refresh()) ;
              ON DBLCLICK EditVnd(.f., oXbVnd) ;
              COLORS CLR_BLACK, nRGB(240,248,255) ;
              LINES CELL UPDATE
       AEval( oXbVnd:aCols, { |o| o:nHeadStrAlign := AL_LEFT } )
       oXbVnd:lRecordSelector := .F.
       oXbVnd:lColDividerComplete := .T.
       oXbVnd:lKineticBrw := .f.
       oXbVnd:SetFont(oXBfon)
       oXbVnd:bClrSelFocus := {|| { CLR_WHITE, CLR_HBLUE }} // Seleção com foco
       oXbVnd:bClrSel      := {|| { CLR_BLACK, CLR_GRAY }} // Seleção sem foco
       oXbVnd:bClrStd      := {|| If( LenArray(aVndInf,1) > 0 .AND. MOD(oXbVnd:nArrayAt, 2) = 0, ; // Cores diferentes em itens bloqueados
                                    { CLR_BLACK, CLR_HCYAN },;
                                    { CLR_BLACK, nRGB(240,248,255) } ) }
    
       IF LEN(aVndInf) > 0
          WITH OBJECT oXbVnd
             :aCols[1]:bStrData := {||DTOC(aVndInf[oXbVnd:nArrayAt,7])}
          END
       ENDIF
    
       oXbVnd:CreateFromCode()
       aVndSavWd := oXbVnd:nWidth
    
       * XBROWSE dos itens
       aNfColWd2 := {110, 320, 75, 75, 75, 75, 75, 75, 75}
       @163,05 GROUP oGrp02 PROMPT "" OF oCadDlg SIZE 385, 70
       @163,05 XBROWSE oXbItn ARRAY aOcpItn OF oCadDlg ;
               HEADERS "Código", "Descrição", "Quantidade", "Pr. s/desc", "Pr c/desc.", "Vlr. Total", "Nr. lote", "Fabricação", "Validade";
               COLUMNS {1,2,3,4,5,6,7,8,9} ;
               COLSIZES aNfColWd2 ;
               COLORS CLR_BLACK, nRGB(240,248,255) ;
               SIZE 385, 70 PIXEL LINES CELL UPDATE
    
               oXbItn:bClrSelFocus := {|| { CLR_WHITE, CLR_HBLUE }} // Seleção com foco
               oXbItn:bClrSel      := {|| { CLR_BLACK, CLR_HGRAY }} // Seleção sem foco
               oXbItn:bClrStd      := {|| If( MOD(oXbItn:nArrayAt, 2) = 0,  {CLR_BLACK, CLR_HCYAN}, {CLR_BLACK, nRGB(240,248,255)} ) }
               oXbItn:lRecordSelector := .F.
               oXbItn:lColDividerComplete := .T.
               oXbItn:lKineticBrw := .f.
               AEval( oXbItn:aCols, { |o| o:nHeadStrAlign := AL_LEFT } )
               oXbItn:SetFont(oXBfon)
               oXbItn:CreateFromCode()
               aNfSavW2 := oXbItn:nWidth
               oXbItn:lFooter := .t.
               oXbItn:aCols[5]:cFooter := "TOTAL >>"
               oXbItn:aCols[6]:nFooterType := AGGR_TOTAL
               oXbItn:nStretchCol  := STRETCHCOL_WIDEST
               oXbItn:ColStretch()
    
    
       nCol := 55
       @242, (8+(nCol*1)-55) SBUTTON oSbt1 PROMPT "" OF oCadDlg SIZE 50, 18 PIXEL NOBORDER XP ACTION NIL WHEN .F. // EditVnd(.t., oXbVnd)
       @242, (8+(nCol*2)-55) SBUTTON oSbt2 PROMPT "" OF oCadDlg SIZE 50, 18 PIXEL NOBORDER XP ACTION NIL WHEN .F. // EditVnd(.f., oXbVnd)
       @242, (8+(nCol*3)-55) SBUTTON oSbt4 PROMPT "" OF oCadDlg SIZE 50, 18 PIXEL NOBORDER XP ACTION NIL WHEN .F. // DeleVnd(oXbVnd)
       @242, (8+(nCol*4)-55) SBUTTON oSbt3 PROMPT "Relatório" OF oCadDlg FILENAME ".\FIGURAS\print.BMP" SIZE 50, 18 PIXEL NOBORDER XP ACTION ImprVnd(oXbVnd)
    
       @242, 230 SBUTTON oSbPg1 PROMPT " " OF oCadDlg ACTION GetVndList(4,"<","",oXbVnd,oCadDlg,.f.,"New") FILENAME ".\figuras\pgup.bmp"   SIZE 18, 18 PIXEL NOBORDER XP TOOLTIP "Mostrar registros da primeira página"
       @242, 250 SBUTTON oSbPg2 PROMPT " " OF oCadDlg ACTION GetVndList(4,"-","",oXbVnd,oCadDlg,.f.,"New") FILENAME ".\figuras\skip-1.bmp" SIZE 18, 18 PIXEL NOBORDER XP TOOLTIP "Mostrar registros da página anterior"
       @242, 290 SBUTTON oSbPg3 PROMPT " " OF oCadDlg ACTION GetVndList(4,"+","",oXbVnd,oCadDlg,.f.,"New") FILENAME ".\figuras\skip.bmp"   SIZE 18, 18 PIXEL NOBORDER XP TOOLTIP "Mostrar registros da página seguinte"
       @242, 310 SBUTTON oSbPg4 PROMPT " " OF oCadDlg ACTION GetVndList(4,">","",oXbVnd,oCadDlg,.f.,"New") FILENAME ".\figuras\pgdn.bmp"   SIZE 18, 18 PIXEL NOBORDER XP TOOLTIP "Mostrar registros da última página"
       @248, 270 SAY oXbPag PROMPT ALLTRIM(STR(cVndQpg))+"/"+ALLTRIM(STR( INT(cVndQrc/50)+IIF(MOD(cVndQrc,50) > 0,1,0) )) OF oCadDlg SIZE 18,10 PIXEL UPDATE CENTER
    
       @242, (8+(nCol*7)-55) SBUTTON oSbt5 PROMPT "Retornar" OF oCadDlg ACTION oCadDlg:End() FILENAME ".\FIGURAS\btnsair.BMP" SIZE 50, 18 PIXEL NOBORDER XP TOOLTIP "Retornar para a tela principal"
    
       oCadDlg:SetFont(oDFont)
       ACTIVATE DIALOG oCadDlg ;
             ON INIT (oGrp:Hide(), oCadDlg:MISetSize(.F.), oCadDlg:Move(0, 0), VndLbxRsiz(oXbVnd, oXbItn, oGrp, oGrp02),;
                      cCPesq:= "*", GetVndList(1,@cCPesq,"",oXbVnd,oCadDlg,.f.,"New"), oXbVnd:Refresh(), xFocus(oGetPsq))
    
       RELEASE FONT oDFont, oFBold, oXBfon
    RETURN NIL
    
    STATIC FUNCTION VndLbxRsiz(oXbVnd, oXbItn, oGrp, oGrp02)
       oGrp:Show() ; WndSetSize(oXbVnd:hWnd, oGrp:nWidth, oGrp:nHeight, .t.) ; oGrp:Hide()
       nFactor := (oXbVnd:nWidth - aVndSavWd)
       nPorcen := 100 - ((100 / nFactor) * (aVndSavWd + (if( oXbVnd:lRecordSelector,80,0) + if( oXbVnd:lVScroll,50,0))))
       AEVAL( oXbVnd:aCols, {|o, nI| o:nWidth := aVndColWd[ nI ] + ((aVndColWd[ nI ] / 100) * nPorcen)} )
       oXbVnd:Refresh()
       
       oGrp02:Show() ; WndSetSize(oXbItn:hWnd, oGrp02:nWidth, oGrp02:nHeight, .t.) ; oGrp02:Hide()
       nFactor := (oXbItn:nWidth - aNfSavW2)
       nPorcen := 100 - ((100 / nFactor) * (aNfSavW2 + (if( oXbItn:lRecordSelector,80,0) + if( oXbItn:lVScroll,50,0))))
       AEVAL( oXbItn:aCols, {|o, nI| o:nWidth := aNfColWd2[ nI ] + ((aNfColWd2[ nI ] / 100) * nPorcen)} )
       oXbItn:Refresh()
    RETURN NIL
    
    STATIC FUNCTION EditVnd(lIsNew, oXbVnd)
       LOCAL lVndOk := .F., nAt :=  oXbVnd:nArrayAt
       if ! lIsNew
          IF LEN(aVndInf) = 0
          	SysRefresh() ; MsgAlert("Favor selecionar um registro válido","Aviso")
          	RETURN NIL
          ENDIF
          IF aVndInf[nAt,1] = 0
          	SysRefresh() ; MsgAlert("Favor selecionar um registro válido","Aviso")
          	RETURN NIL
       	endif
       ENDIF
    
       xItn01 := 0 // Código
       xItn02 := SPACE(15) // ID Unico
       xItn03 := SPACE(10) // Ref. Orçamento
       xItn04 := 0 // Ref. NF-e
       xItn05 := 0 // Ref. NFC-e
       xItn06 := SPACE(6) // Ref. SAT
       xItn07 := CTOD(" ") // Data venda
       xItn08 := SPACE(5) // Hora venda
       xItn09 := CTOD(" ") // Data entrega
       xItn10 := SPACE(5) // Hora entrega
       xItn11 := .F. // Cencelada?
       xItn12 := SPACE(10) // Dt. cancelamento
       xItn13 := SPACE(95) // Motivo cancelamento
       xItn14 := 0.00 // CFOP 1º item
       xItn15 := 0 // Cód. cliente
       xItn16 := SPACE(50) // Nome cliente
       xItn17 := SPACE(50) // Fantasia
       xItn18 := SPACE(10) // End. CEP
       xItn19 := SPACE(50) // End. Rua
       xItn20 := SPACE(15) // End. número
       xItn21 := SPACE(30) // End. bairro
       xItn22 := SPACE(30) // End. cidade
       xItn23 := SPACE(255) // Perímetro
       xItn24 := SPACE(50) // Telefone
       xItn25 := SPACE(20) // CPF/CNPJ
       xItn26 := SPACE(20) // RG/IE
       xItn27 := CTOD(" ") // Dt.Nascimento
       xItn28 := SPACE(50) // Autorizado
       xItn29 := SPACE(15) // Operação
       xItn30 := 0.000 // Vlr. Itens
       xItn31 := 0.00 // Desconto itens
       xItn32 := 0.000 // Desconto final
       xItn33 := 0.00 // Acréscimo %
       xItn34 := 0.00 // Mão de obra R$
       xItn35 := 0.00 // Couvert R$
       xItn36 := 0 // Qt. pessoas
       xItn37 := SPACE(11) // Valor pago
       xItn38 := 0.000 // Meio Pg 01
       xItn39 := 0.000 // Meio Pg 02
       xItn40 := 0.000 // Meio Pg 03
       xItn41 := 0.000 // Meio Pg 04
       xItn42 := 0.000 // Meio Pg 05
       xItn43 := 0.000 // Meio Pg 06
       xItn44 := 0.000 // Meio Pg 07
       xItn45 := 0.000 // Meio Pg 08
       xItn46 := 0.000 // Meio Pg 09
       xItn47 := 0.000 // Meio Pg 10
       xItn48 := 0.00 // Meio Pg 11
       xItn49 := SPACE(80) // Inf. Pg. Cartão
       xItn50 := SPACE(43) // Operador
       xItn51 := 0 // Cód. vendedor
       xItn52 := SPACE(30) // Nome vendedor
       xItn53 := 0 // Cód. Vd. Rateio
       xItn54 := SPACE(40) // Nome Vd. Rateio
       xItn55 := 0.00 // Valor Rateio
       xItn56 := SPACE(255) // Veículo - Inf.
       xItn57 := SPACE(30) // Veículo - KM
       xItn58 := SPACE(20) // Veículo - Modelo
       xItn59 := SPACE(8) // Veículo - Placa
       xItn60 := .F. // Venda futura?
       xItn61 := SPACE(30) // Observações
    
       n_Conn := nConection(.F., .F.)
       IF n_Conn <= 0 ; RETURN NIL ; ENDIF
    
       IF ! lIsNew
          xItn01 := aVndInf[nAt,01] // Código
          xItn02 := aVndInf[nAt,02] // ID Unico
          xItn03 := aVndInf[nAt,03] // Ref. Orçamento
          xItn04 := aVndInf[nAt,04] // Ref. NF-e
          xItn05 := aVndInf[nAt,05] // Ref. NFC-e
          xItn06 := aVndInf[nAt,06] // Ref. SAT
          xItn07 := FBToDate(aVndInf[nAt,07]) // Data venda
          xItn08 := aVndInf[nAt,08] // Hora venda
          xItn09 := FBToDate(aVndInf[nAt,09]) // Data entrega
          xItn10 := aVndInf[nAt,10] // Hora entrega
          xItn11 := aVndInf[nAt,11] // Cencelada?
          xItn12 := aVndInf[nAt,12] // Dt. cancelamento
          xItn13 := aVndInf[nAt,13] // Motivo cancelamento
          xItn14 := aVndInf[nAt,14] // CFOP 1º item
          xItn15 := aVndInf[nAt,15] // Cód. cliente
          xItn16 := aVndInf[nAt,16] // Nome cliente
          xItn17 := aVndInf[nAt,17] // Fantasia
          xItn18 := aVndInf[nAt,18] // End. CEP
          xItn19 := aVndInf[nAt,19] // End. Rua
          xItn20 := aVndInf[nAt,20] // End. número
          xItn21 := aVndInf[nAt,21] // End. bairro
          xItn22 := aVndInf[nAt,22] // End. cidade
          xItn23 := aVndInf[nAt,23] // Perímetro
          xItn24 := aVndInf[nAt,24] // Telefone
          xItn25 := aVndInf[nAt,25] // CPF/CNPJ
          xItn26 := aVndInf[nAt,26] // RG/IE
          xItn27 := FBToDate(aVndInf[nAt,27]) // Dt.Nascimento
          xItn28 := aVndInf[nAt,28] // Autorizado
          xItn29 := aVndInf[nAt,29] // Operação
          xItn30 := aVndInf[nAt,30] // Vlr. Itens
          xItn31 := aVndInf[nAt,31] // Desconto itens
          xItn32 := aVndInf[nAt,32] // Desconto final
          xItn33 := aVndInf[nAt,33] // Acréscimo %
          xItn34 := aVndInf[nAt,34] // Mão de obra R$
          xItn35 := aVndInf[nAt,35] // Couvert R$
          xItn36 := aVndInf[nAt,36] // Qt. pessoas
          xItn37 := aVndInf[nAt,37] // Valor pago
          xItn38 := aVndInf[nAt,38] // Meio Pg 01
          xItn39 := aVndInf[nAt,39] // Meio Pg 02
          xItn40 := aVndInf[nAt,40] // Meio Pg 03
          xItn41 := aVndInf[nAt,41] // Meio Pg 04
          xItn42 := aVndInf[nAt,42] // Meio Pg 05
          xItn43 := aVndInf[nAt,43] // Meio Pg 06
          xItn44 := aVndInf[nAt,44] // Meio Pg 07
          xItn45 := aVndInf[nAt,45] // Meio Pg 08
          xItn46 := aVndInf[nAt,46] // Meio Pg 09
          xItn47 := aVndInf[nAt,47] // Meio Pg 10
          xItn48 := aVndInf[nAt,48] // Meio Pg 11
          xItn49 := aVndInf[nAt,49] // Inf. Pg. Cartão
          xItn50 := aVndInf[nAt,50] // Operador
          xItn51 := aVndInf[nAt,51] // Cód. vendedor
          xItn52 := aVndInf[nAt,52] // Nome vendedor
          xItn53 := aVndInf[nAt,53] // Cód. Vd. Rateio
          xItn54 := aVndInf[nAt,54] // Nome Vd. Rateio
          xItn55 := aVndInf[nAt,55] // Valor Rateio
          xItn56 := aVndInf[nAt,56] // Veículo - Inf.
          xItn57 := aVndInf[nAt,57] // Veículo - KM
          xItn58 := aVndInf[nAt,58] // Veículo - Modelo
          xItn59 := aVndInf[nAt,59] // Veículo - Placa
          xItn60 := aVndInf[nAt,60] // Venda futura?
          xItn61 := aVndInf[nAt,61] // Observações
       ENDIF
    
       n_Color := nRGB(192,217,217)
       DEFINE BRUSH oDlBru COLOR n_Color
       DEFINE FONT oDlFnt NAME "Arial Narrow" SIZE 0, -15
       SysRefresh()
       DEFINE DIALOG oCadVnd RESOURCE "CAD_VENDA" TITLE "Consulta de venda online" TRANSPARENT BRUSH oDlBru
       oCadVnd:SetFont(oDlFnt)
       REDEFINE GET oCt03 VAR xItn03 ID 101 OF oCadVnd
       REDEFINE GET oCt04 VAR xItn04 PICTURE "9999999999" ID 102 OF oCadVnd
       REDEFINE GET oCt05 VAR xItn05 PICTURE "9999999999" ID 103 OF oCadVnd
       REDEFINE GET oCt06 VAR xItn06 ID 104 OF oCadVnd
       REDEFINE GET oCt07 VAR xItn07 ID 105 OF oCadVnd
       REDEFINE GET oCt08 VAR xItn08 ID 106 OF oCadVnd
       REDEFINE GET oCt09 VAR xItn09 ID 107 OF oCadVnd
       REDEFINE GET oCt10 VAR xItn10 ID 108 OF oCadVnd
       REDEFINE GET oCt11 VAR xItn11 ID 109 OF oCadVnd
       REDEFINE GET oCt12 VAR xItn12 ID 110 OF oCadVnd
       REDEFINE GET oCt13 VAR xItn13 ID 111 OF oCadVnd
       REDEFINE GET oCt14 VAR xItn14 PICTURE "@E 99999999.99" ID 112 OF oCadVnd
       REDEFINE GET oCt15 VAR xItn15 PICTURE "9999999999" ID 113 OF oCadVnd
       REDEFINE GET oCt16 VAR xItn16 ID 114 OF oCadVnd
       REDEFINE GET oCt17 VAR xItn17 ID 115 OF oCadVnd
       REDEFINE GET oCt18 VAR xItn18 ID 116 OF oCadVnd
       REDEFINE GET oCt19 VAR xItn19 ID 117 OF oCadVnd
       REDEFINE GET oCt20 VAR xItn20 ID 118 OF oCadVnd
       REDEFINE GET oCt21 VAR xItn21 ID 119 OF oCadVnd
       REDEFINE GET oCt22 VAR xItn22 ID 120 OF oCadVnd
       REDEFINE GET oCt23 VAR xItn23 ID 121 OF oCadVnd
       REDEFINE GET oCt24 VAR xItn24 ID 122 OF oCadVnd
       REDEFINE GET oCt25 VAR xItn25 ID 123 OF oCadVnd
       REDEFINE GET oCt26 VAR xItn26 ID 124 OF oCadVnd
       REDEFINE GET oCt27 VAR xItn27 ID 125 OF oCadVnd
       REDEFINE GET oCt28 VAR xItn28 ID 126 OF oCadVnd
       REDEFINE GET oCt29 VAR xItn29 ID 127 OF oCadVnd
       REDEFINE GET oCt30 VAR xItn30 PICTURE "@E 9999999999999.999" ID 128 OF oCadVnd
       REDEFINE GET oCt31 VAR xItn31 PICTURE "@E 99999999.99" ID 129 OF oCadVnd
       REDEFINE GET oCt32 VAR xItn32 PICTURE "@E 99999999.999" ID 130 OF oCadVnd
       REDEFINE GET oCt33 VAR xItn33 PICTURE "@E 9999.99" ID 131 OF oCadVnd
       REDEFINE GET oCt34 VAR xItn34 PICTURE "@E 99999999.99" ID 132 OF oCadVnd
       REDEFINE GET oCt35 VAR xItn35 PICTURE "@E 99999999.99" ID 133 OF oCadVnd
       REDEFINE GET oCt36 VAR xItn36 PICTURE "999" ID 134 OF oCadVnd
       REDEFINE GET oCt37 VAR xItn37 ID 135 OF oCadVnd
       REDEFINE GET oCt38 VAR xItn38 PICTURE "@E 99999999.999" ID 136 OF oCadVnd
       REDEFINE GET oCt39 VAR xItn39 PICTURE "@E 99999999.999" ID 137 OF oCadVnd
       REDEFINE GET oCt40 VAR xItn40 PICTURE "@E 99999999.999" ID 138 OF oCadVnd
       REDEFINE GET oCt41 VAR xItn41 PICTURE "@E 99999999.999" ID 139 OF oCadVnd
       REDEFINE GET oCt42 VAR xItn42 PICTURE "@E 99999999.999" ID 140 OF oCadVnd
       REDEFINE GET oCt43 VAR xItn43 PICTURE "@E 99999999.999" ID 141 OF oCadVnd
       REDEFINE GET oCt44 VAR xItn44 PICTURE "@E 99999999.999" ID 142 OF oCadVnd
       REDEFINE GET oCt45 VAR xItn45 PICTURE "@E 99999999.999" ID 143 OF oCadVnd
       REDEFINE GET oCt46 VAR xItn46 PICTURE "@E 99999999.999" ID 144 OF oCadVnd
       REDEFINE GET oCt47 VAR xItn47 PICTURE "@E 99999999.999" ID 145 OF oCadVnd
       REDEFINE GET oCt48 VAR xItn48 PICTURE "@E 99999999.99" ID 146 OF oCadVnd
       REDEFINE GET oCt49 VAR xItn49 ID 147 OF oCadVnd
       REDEFINE GET oCt50 VAR xItn50 ID 148 OF oCadVnd
       REDEFINE GET oCt51 VAR xItn51 PICTURE "999" ID 149 OF oCadVnd
       REDEFINE GET oCt52 VAR xItn52 ID 150 OF oCadVnd
       REDEFINE GET oCt53 VAR xItn53 PICTURE "999" ID 151 OF oCadVnd
       REDEFINE GET oCt54 VAR xItn54 ID 152 OF oCadVnd
       REDEFINE GET oCt55 VAR xItn55 PICTURE "@E 99999999.99" ID 153 OF oCadVnd
       REDEFINE GET oCt56 VAR xItn56 ID 154 OF oCadVnd
       REDEFINE GET oCt57 VAR xItn57 ID 155 OF oCadVnd
       REDEFINE GET oCt58 VAR xItn58 ID 156 OF oCadVnd
       REDEFINE GET oCt59 VAR xItn59 ID 157 OF oCadVnd
       REDEFINE GET oCt60 VAR xItn60 ID 158 OF oCadVnd
       REDEFINE GET oCt61 VAR xItn61 ID 159 OF oCadVnd
       REDEFINE SBUTTON oBt1 PROMPT "Salvar"                          ID 201 OF oCadVnd RESOURCE "BTYESOK"                       NOBORDER XP ACTION (lVndOk := .T., oCadVnd:End())
       REDEFINE SBUTTON oBt2 PROMPT IIF(lIsNew,"Cancelar","Retornar") ID 202 OF oCadVnd RESOURCE IIF(lIsNew,"BTN_CAN","BTN_SAI") NOBORDER XP ACTION (lVndOk := .F., oCadVnd:End())
       ACTIVATE DIALOG oCadVnd CENTERED
       DeleteObject(oDlFnt)
       DeleteObject(oDlBru)
    
       IF ! lVndOk ; RETURN NIL ; ENDIF
    
       IF lIsNew
          n_Conn := nConection(.F., .F.)
          IF n_Conn <= 0 ; RETURN NIL ; ENDIF
          xItn02 := GeraIdUnico()
          cQury := "INSERT INTO vendas_info "+;
                   "(codigo, idunic, orcnum, nfenum, nfcnum, satnum, dtoper, horaop, dtentr, hoentr, opcanc, dtcanc, cancpq, cfoini, codcli, nomcli, fancli, ruacep, ruacli, ruanro, bairro, cidade, ruaper, fone01, doccpf, doc_rg, nascli, cliaut, operac, titens, descit, descfi, acresc, acres1, acres2, qtpess, vrpago, pgto01, pgto02, pgto03, pgto04, pgto05, pgto06, pgto07, pgto08, pgto09, pgto10, pgto11, cartao, operad, vddcod, vddnom, nvdrat, cvdrat, vlrrat, carinf, car_km, carmod, carpla, futura, observ)"+;
                   " VALUES ("+;
                     "(SELECT coalesce(MAX(codigo), 0)+1 AS ULTCOD FROM vendas_info), "+;
                     "'"+xItn02+"', "+;
                     "'"+ALLTRIM(xItn03)+"', "+;
                     ALLTRIM(STR(xItn04))+", "+;
                     ALLTRIM(STR(xItn05))+", "+;
                     "'"+ALLTRIM(xItn06)+"', "+;
                     "'"+SQLDTOC(xItn07)+"', "+;
                     "'"+ALLTRIM(xItn08)+"', "+;
                     "'"+SQLDTOC(xItn09)+"', "+;
                     "'"+ALLTRIM(xItn10)+"', "+;
                     IIF(!xItn11,"0","1")+", "+;
                     "'"+ALLTRIM(xItn12)+"', "+;
                     "'"+ALLTRIM(xItn13)+"', "+;
                     ALLTRIM(STR(xItn14))+", "+;
                     ALLTRIM(STR(xItn15))+", "+;
                     "'"+ALLTRIM(xItn16)+"', "+;
                     "'"+ALLTRIM(xItn17)+"', "+;
                     "'"+ALLTRIM(xItn18)+"', "+;
                     "'"+ALLTRIM(xItn19)+"', "+;
                     "'"+ALLTRIM(xItn20)+"', "+;
                     "'"+ALLTRIM(xItn21)+"', "+;
                     "'"+ALLTRIM(xItn22)+"', "+;
                     "'"+ALLTRIM(xItn23)+"', "+;
                     "'"+ALLTRIM(xItn24)+"', "+;
                     "'"+ALLTRIM(xItn25)+"', "+;
                     "'"+ALLTRIM(xItn26)+"', "+;
                     "'"+SQLDTOC(xItn27)+"', "+;
                     "'"+ALLTRIM(xItn28)+"', "+;
                     "'"+ALLTRIM(xItn29)+"', "+;
                     ALLTRIM(STR(xItn30))+", "+;
                     ALLTRIM(STR(xItn31))+", "+;
                     ALLTRIM(STR(xItn32))+", "+;
                     ALLTRIM(STR(xItn33))+", "+;
                     ALLTRIM(STR(xItn34))+", "+;
                     ALLTRIM(STR(xItn35))+", "+;
                     ALLTRIM(STR(xItn36))+", "+;
                     "'"+ALLTRIM(xItn37)+"', "+;
                     ALLTRIM(STR(xItn38))+", "+;
                     ALLTRIM(STR(xItn39))+", "+;
                     ALLTRIM(STR(xItn40))+", "+;
                     ALLTRIM(STR(xItn41))+", "+;
                     ALLTRIM(STR(xItn42))+", "+;
                     ALLTRIM(STR(xItn43))+", "+;
                     ALLTRIM(STR(xItn44))+", "+;
                     ALLTRIM(STR(xItn45))+", "+;
                     ALLTRIM(STR(xItn46))+", "+;
                     ALLTRIM(STR(xItn47))+", "+;
                     ALLTRIM(STR(xItn48))+", "+;
                     "'"+ALLTRIM(xItn49)+"', "+;
                     "'"+ALLTRIM(xItn50)+"', "+;
                     ALLTRIM(STR(xItn51))+", "+;
                     "'"+ALLTRIM(xItn52)+"', "+;
                     ALLTRIM(STR(xItn53))+", "+;
                     "'"+ALLTRIM(xItn54)+"', "+;
                     ALLTRIM(STR(xItn55))+", "+;
                     "'"+ALLTRIM(xItn56)+"', "+;
                     "'"+ALLTRIM(xItn57)+"', "+;
                     "'"+ALLTRIM(xItn58)+"', "+;
                     "'"+ALLTRIM(xItn59)+"', "+;
                     IIF(!xItn60,"0","1")+", "+;
                     "'"+ALLTRIM(xItn61)+"'"+")"
          TRY
             oSql := SR_GetConnection()
             nErr := oSql:Execute(cQury)
             oSql:Commit()
             cSeek := xItn02 // Usar ID Unico
             GetVndList(3,@cSeek,"",oXbVnd,oCadDlg,.F.,"Add")
          CATCH oErr
             SysRefresh(); MsgAlert("Erro ao tentar salvar os dados."+CRLF+CRLF+"Erro: "+oErr:Description,"Erro")
          END
       ELSE
          cQury := "UPDATE vendas_info SET"+;
                   " idunic = '"+ALLTRIM(xItn02)+"',"+;
                   " orcnum = '"+ALLTRIM(xItn03)+"',"+;
                   " nfenum = "+ALLTRIM(STR(xItn04))+","+;
                   " nfcnum = "+ALLTRIM(STR(xItn05))+","+;
                   " satnum = '"+ALLTRIM(xItn06)+"',"+;
                   " dtoper = '"+SQLDTOC(xItn07)+"',"+;
                   " horaop = '"+ALLTRIM(xItn08)+"',"+;
                   " dtentr = '"+SQLDTOC(xItn09)+"',"+;
                   " hoentr = '"+ALLTRIM(xItn10)+"',"+;
                   " opcanc = "+IIF(!xItn11,"0","1")+","+;
                   " dtcanc = '"+ALLTRIM(xItn12)+"',"+;
                   " cancpq = '"+ALLTRIM(xItn13)+"',"+;
                   " cfoini = "+ALLTRIM(STR(xItn14))+","+;
                   " codcli = "+ALLTRIM(STR(xItn15))+","+;
                   " nomcli = '"+ALLTRIM(xItn16)+"',"+;
                   " fancli = '"+ALLTRIM(xItn17)+"',"+;
                   " ruacep = '"+ALLTRIM(xItn18)+"',"+;
                   " ruacli = '"+ALLTRIM(xItn19)+"',"+;
                   " ruanro = '"+ALLTRIM(xItn20)+"',"+;
                   " bairro = '"+ALLTRIM(xItn21)+"',"+;
                   " cidade = '"+ALLTRIM(xItn22)+"',"+;
                   " ruaper = '"+ALLTRIM(xItn23)+"',"+;
                   " fone01 = '"+ALLTRIM(xItn24)+"',"+;
                   " doccpf = '"+ALLTRIM(xItn25)+"',"+;
                   " doc_rg = '"+ALLTRIM(xItn26)+"',"+;
                   " nascli = '"+SQLDTOC(xItn27)+"',"+;
                   " cliaut = '"+ALLTRIM(xItn28)+"',"+;
                   " operac = '"+ALLTRIM(xItn29)+"',"+;
                   " titens = "+ALLTRIM(STR(xItn30))+","+;
                   " descit = "+ALLTRIM(STR(xItn31))+","+;
                   " descfi = "+ALLTRIM(STR(xItn32))+","+;
                   " acresc = "+ALLTRIM(STR(xItn33))+","+;
                   " acres1 = "+ALLTRIM(STR(xItn34))+","+;
                   " acres2 = "+ALLTRIM(STR(xItn35))+","+;
                   " qtpess = "+ALLTRIM(STR(xItn36))+","+;
                   " vrpago = '"+ALLTRIM(xItn37)+"',"+;
                   " pgto01 = "+ALLTRIM(STR(xItn38))+","+;
                   " pgto02 = "+ALLTRIM(STR(xItn39))+","+;
                   " pgto03 = "+ALLTRIM(STR(xItn40))+","+;
                   " pgto04 = "+ALLTRIM(STR(xItn41))+","+;
                   " pgto05 = "+ALLTRIM(STR(xItn42))+","+;
                   " pgto06 = "+ALLTRIM(STR(xItn43))+","+;
                   " pgto07 = "+ALLTRIM(STR(xItn44))+","+;
                   " pgto08 = "+ALLTRIM(STR(xItn45))+","+;
                   " pgto09 = "+ALLTRIM(STR(xItn46))+","+;
                   " pgto10 = "+ALLTRIM(STR(xItn47))+","+;
                   " pgto11 = "+ALLTRIM(STR(xItn48))+","+;
                   " cartao = '"+ALLTRIM(xItn49)+"',"+;
                   " operad = '"+ALLTRIM(xItn50)+"',"+;
                   " vddcod = "+ALLTRIM(STR(xItn51))+","+;
                   " vddnom = '"+ALLTRIM(xItn52)+"',"+;
                   " nvdrat = "+ALLTRIM(STR(xItn53))+","+;
                   " cvdrat = '"+ALLTRIM(xItn54)+"',"+;
                   " vlrrat = "+ALLTRIM(STR(xItn55))+","+;
                   " carinf = '"+ALLTRIM(xItn56)+"',"+;
                   " car_km = '"+ALLTRIM(xItn57)+"',"+;
                   " carmod = '"+ALLTRIM(xItn58)+"',"+;
                   " carpla = '"+ALLTRIM(xItn59)+"',"+;
                   " futura = "+IIF(!xItn60,"0","1")+","+;
                   " observ = '"+ALLTRIM(xItn61)+"'"+;
                   " WHERE codigo = "+ALLTRIM(STR(xItn01))
          TRY
             n_Conn := nConection(.F., .F.)
             IF n_Conn <= 0 ; BREAK ; ENDIF
             oSql := SR_GetConnection()
             nErr := oSql:Execute(cQury)
             oSql:Commit()
             cSeek := xItn02 // Usar ID Unico
             GetVndList(3,@cSeek,"",oXbVnd,oCadDlg,.F.,"Upd")
          CATCH oErr
             SysRefresh() ; MsgAlert("Erro ao tentar salvar os dados."+CRLF+CRLF+"Erro: "+oErr:Description,"Erro")
          END
       ENDIF
    RETURN lVndOk
    
    STATIC FUNCTION DeleVnd(oXbVnd)
       LOCAL lSave := .F., nAt := oXbVnd:nArrayAt
       IF LEN(aVndInf) = 0
       	SysRefresh() ; MsgAlert("Favor selecionar um registro válido","Aviso")
       	RETURN NIL
       ENDIF
       IF aVndInf[nAt,1] = 0
       	SysRefresh() ; MsgAlert("Favor selecionar um registro válido","Aviso")
       	RETURN NIL
       ENDIF
       IF ! MsgNoYes("Confirma a exclusão do registro selecionado?", "Favor confirmar a exclusção!")
       	RETURN NIL
       ENDIF
       TRY
          n_Conn := nConection(.F., .F.)
          IF n_Conn <= 0 ; BREAK ; ENDIF
          oSql := SR_GetConnection()
          nErr := oSql:Execute("DELETE FROM vendas_info WHERE codigo = "+ALLTRIM(STR(aVndInf[nAt,01])))
          oSql:Commit()
          MyADel(aVndInf, nAt)
          oXbVnd:SetArray(aVndInf)
          oXbVnd:nArrayAt := nAt - 1 ; oXbVnd:Refresh()
          SysRefresh() ; MsgInfo("Registro excluído com êxito.", "Informação")
       CATCH oErr
          SysRefresh() ; MsgAlert("Erro ao tentar salvar os dados."+CRLF+CRLF+"Erro: "+oErr:Description,"Erro")
       END
    RETURN NIL
    
    STATIC FUNCTION GetVndList(nQue,cPesq,cUniq,oBrw,oCadDlg,lAvisa,cAcao)
       LOCAL aRcrds := {}, nRAt := 0
       IF oBrw <> NIL ; nRAt := oBrw:nArrayAt ; ENDIF
       IF EMPTY(cPesq) ; RETURN .T. ; ENDIF
    
       n_Conn := nConection(.F., .F.)
       IF n_Conn <= 0 ; RETURN .F. ; ENDIF
    
       cQryTt := ""
       cWhere := ""
       cOrder := ""
    
       IF nQue < 4
          cVndQry := "SELECT"+;
                       " codigo,"+; // 01-Código
                       " idunic,"+; // 02-ID Unico
                       " orcnum,"+; // 03-Ref. Orçamento
                       " nfenum,"+; // 04-Ref. NF-e
                       " nfcnum,"+; // 05-Ref. NFC-e
                       " satnum,"+; // 06-Ref. SAT
                       " dtoper,"+; // 07-Data venda
                       " horaop,"+; // 08-Hora venda
                       " dtentr,"+; // 09-Data entrega
                       " hoentr,"+; // 10-Hora entrega
                       " opcanc,"+; // 11-Cencelada?
                       " dtcanc,"+; // 12-Dt. cancelamento
                       " cancpq,"+; // 13-Motivo cancelamento
                       " cfoini,"+; // 14-CFOP 1º item
                       " codcli,"+; // 15-Cód. cliente
                       " nomcli,"+; // 16-Nome cliente
                       " fancli,"+; // 17-Fantasia
                       " ruacep,"+; // 18-End. CEP
                       " ruacli,"+; // 19-End. Rua
                       " ruanro,"+; // 20-End. número
                       " bairro,"+; // 21-End. bairro
                       " cidade,"+; // 22-End. cidade
                       " ruaper,"+; // 23-Perímetro
                       " fone01,"+; // 24-Telefone
                       " doccpf,"+; // 25-CPF/CNPJ
                       " doc_rg,"+; // 26-RG/IE
                       " nascli,"+; // 27-Dt.Nascimento
                       " cliaut,"+; // 28-Autorizado
                       " operac,"+; // 29-Operação
                       " titens,"+; // 30-Vlr. Itens
                       " descit,"+; // 31-Desconto itens
                       " descfi,"+; // 32-Desconto final
                       " acresc,"+; // 33-Acréscimo %
                       " acres1,"+; // 34-Mão de obra R$
                       " acres2,"+; // 35-Couvert R$
                       " qtpess,"+; // 36-Qt. pessoas
                       " vrpago,"+; // 37-Valor pago
                       " pgto01,"+; // 38-Meio Pg 01
                       " pgto02,"+; // 39-Meio Pg 02
                       " pgto03,"+; // 40-Meio Pg 03
                       " pgto04,"+; // 41-Meio Pg 04
                       " pgto05,"+; // 42-Meio Pg 05
                       " pgto06,"+; // 43-Meio Pg 06
                       " pgto07,"+; // 44-Meio Pg 07
                       " pgto08,"+; // 45-Meio Pg 08
                       " pgto09,"+; // 46-Meio Pg 09
                       " pgto10,"+; // 47-Meio Pg 10
                       " pgto11,"+; // 48-Meio Pg 11
                       " cartao,"+; // 49-Inf. Pg. Cartão
                       " operad,"+; // 50-Operador
                       " vddcod,"+; // 51-Cód. vendedor
                       " vddnom,"+; // 52-Nome vendedor
                       " nvdrat,"+; // 53-Cód. Vd. Rateio
                       " cvdrat,"+; // 54-Nome Vd. Rateio
                       " vlrrat,"+; // 55-Valor Rateio
                       " carinf,"+; // 56-Veículo - Inf.
                       " car_km,"+; // 57-Veículo - KM
                       " carmod,"+; // 58-Veículo - Modelo
                       " carpla,"+; // 59-Veículo - Placa
                       " futura,"+; // 60-Venda futura?
                       " observ"+;  // 61-Observações
                       " FROM vendas_info"
          cWhere := ""
          cOrder := ""
       	IF nQue = 1
             IF ALLTRIM(cPesq) == "*"
                cWhere := " WHERE codigo > 0"
                cOrder := " ORDER BY nomcli"
             ELSE
                IF ALLTRIM(cQPesq) = "Código venda" // "Nome cliente", "Fantasia", "CPF/CNPJ", "Nome vendedor", "Data venda", "Data entrega", "Código venda", "Cód. cliente", "Cód. vendedor"
                   cWhere := " WHERE codigo = "+ALLTRIM(cPesq)
                   cOrder := " ORDER BY codigo"
                ENDIF
                IF ALLTRIM(cQPesq) = "Data venda"
                   cWhere := " WHERE dtoper = '"+SR_dtosdot(CTOD(cPesq))+"'"
                   cOrder := " ORDER BY dtoper"
                ENDIF
                IF ALLTRIM(cQPesq) = "Data entrega"
                   cWhere := " WHERE dtentr = '"+SR_dtosdot(CTOD(cPesq))+"'"
                   cOrder := " ORDER BY dtentr"
                ENDIF
                IF ALLTRIM(cQPesq) = "Cód. cliente"
                   cWhere := " WHERE codcli = "+ALLTRIM(cPesq)
                   cOrder := " ORDER BY codcli"
                ENDIF
                IF ALLTRIM(cQPesq) = "Nome cliente"
                   cWhere := " WHERE nomcli LIKE '%"+UPPER(ALLTRIM(cPesq))+"%'"
                   cOrder := " ORDER BY nomcli"
                ENDIF
                IF ALLTRIM(cQPesq) = "Fantasia"
                   cWhere := " WHERE fancli LIKE '%"+UPPER(ALLTRIM(cPesq))+"%'"
                   cOrder := " ORDER BY fancli"
                ENDIF
                IF ALLTRIM(cQPesq) = "CPF/CNPJ"
                   cWhere := " WHERE doccpf = '"+UPPER(ALLTRIM(cPesq))+"'"
                   cOrder := " ORDER BY doccpf"
                ENDIF
                IF ALLTRIM(cQPesq) = "Cód. vendedor"
                   cWhere := " WHERE vddcod = "+ALLTRIM(cPesq)
                   cOrder := " ORDER BY vddcod"
                ENDIF
                IF ALLTRIM(cQPesq) = "Nome vendedor"
                   cWhere := " WHERE vddnom LIKE '%"+UPPER(ALLTRIM(cPesq))+"%'"
                   cOrder := " ORDER BY vddnom"
                ENDIF
             ENDIF
          ELSEIF nQue = 2
             cWhere := " WHERE nomcli LIKE '"+ALLTRIM(cPesq)+"%'"
             cOrder := " ORDER BY nomcli"
          ELSEIF nQue = 3
             cWhere := " WHERE idunic = '"+ALLTRIM(cPesq)+"'"
             cOrder := ""
          ELSE
             cWhere := " WHERE codigo > 0"
             cOrder := " ORDER BY nomcli"
          ENDIF
          IF nQue > 0
             cLimit := " LIMIT "+ALLTRIM(STR(cVndSkp))+", 50"
          ELSE
             cLimit := " LIMIT 1" // Get only 1 record, to be cleaned.
          ENDIF
          cVndQry += cWhere + cOrder + cLimit
          cQryTt := "SELECT COUNT(*) FROM vendas_info" + cWhere
       ELSE
          IF cPesq = "+"
             IF (cVndSkp + 50) < cVndQrc
                cVndSkp += 50 ; cVndQpg ++
                cVndQry := STRTRAN(cVndQry, "LIMIT "+ALLTRIM(STR(cVndLsk)), "LIMIT "+ALLTRIM(STR(cVndSkp)))
                cVndLsk := cVndSkp
             ELSE
                RETURN .T.
             ENDIF
          ENDIF
          IF cPesq = "-"
             IF (cVndSkp - 50) > -1
                cVndSkp -= 50 ; cVndQpg --
                cVndQry := STRTRAN(cVndQry, "LIMIT "+ALLTRIM(STR(cVndLsk)), "LIMIT "+ALLTRIM(STR(cVndSkp)))
                cVndLsk := cVndSkp
             ELSE
                RETURN .T.
             ENDIF
          ENDIF
          IF cPesq = ">"
             IF (cVndSkp + 50) < cVndQrc
                cVndSkp := (INT(cVndQrc/50)*50) ; cVndQpg := INT(cVndQrc/50)+IIF(MOD(cVndQrc,50) > 0, 1, 0)
                cVndQry := STRTRAN(cVndQry, "LIMIT "+ALLTRIM(STR(cVndLsk)), "LIMIT "+ALLTRIM(STR(cVndSkp)))
                cVndLsk := cVndSkp
             ELSE
                RETURN .T.
             ENDIF
          ENDIF
          IF cPesq = "<"
             IF (cVndSkp - 50) > -1
                cVndSkp := 0 ; cVndQpg := 1
                cVndQry := STRTRAN(cVndQry, "LIMIT "+ALLTRIM(STR(cVndLsk)), "LIMIT "+ALLTRIM(STR(cVndSkp)))
                cVndLsk := cVndSkp
             ELSE
                RETURN .T.
             ENDIF
          ENDIF
       ENDIF
    
       l_Err := .F.
       aVndInf := {}
       IF ! EMPTY(cQryTt)
          aTtRec := SQLArray(cQryTt, @l_Err)
          IF LEN(aTtRec) > 0 ; cVndQpg := 1; cVndQrc := aTtRec[1,1] ; ENDIF
       ENDIF
    
       l_Err := .F.
       aRcrds := SQLArray(cVndQry, @l_Err)
    
       IF LEN(aRcrds) = 0
          IF oBrw <> NIL ; aVndInf := aVndNul ; oBrw:SetArray(aVndInf) ; oBrw:Refresh() ; ENDIF
          IF lAvisa ; SysRefresh() ; MsgAlert("Informação não encontrada", "Aviso") ; ENDIF
       ELSE
          if nQue = 0 // Pegar apenas registro em branco.
       	   aInfo := aRcrds[1]
       	   for nCl := 1 TO LEN(aInfo)
       			xInv := aInfo[nCl]
       			if ValType(xInv) = 'C' ; xInv := SPACE(LEN(xInv)) ; ENDIF
       			if ValType(xInv) = 'M' ; xInv := SPACE(10) ; ENDIF
       			if ValType(xInv) = 'N' ; xInv := 0 ; ENDIF
       			if ValType(xInv) = 'D' ; xInv := CTOD(" ") ; ENDIF
       			if ValType(xInv) = 'L' ; xInv := .F. ; ENDIF
       			aRcrds[1,nCl] := xInv
       		next
       		aVndNul := aRcrds
       	endif
          IF cAcao = "New"
             aVndInf := aRcrds
          ELSEIF cAcao = "Add"
             AADD(aVndInf, aRcrds[1])
          ELSEIF cAcao = "Upd"
             aVndInf[nRAt] := aRcrds[1]
          ENDIF
       ENDIF
       cPesq := SPACE(50)
       cUniq := SPACE(15)
       IF oBrw <> NIL
          IF cAcao = "Add" .OR. cAcao = "New"
             oBrw:SetArray(aVndInf)
             oBrw:GoTop()
          ELSEIF cAcao = "Upd"
             oBrw:nArrayAt := nRAt
          ENDIF
          oBrw:Refresh()
       ENDIF
       if oCadDlg <> nil ; oCadDlg:Update() ; endif
    RETURN .F.
    
    FUNCTION OrdGetItms(nPedId, cUnqId)
       LOCAL a_Itens := {}, a_Array := {}
       IF nPedId = 0
          AADD(a_Itens, {"", "", 0, 0.00, 0.00, 0.00, "", CTOD(" "), CTOD(" ")})
          RETURN a_Itens
       ENDIF
       cItnsQry := "SELECT"+;
                    " idumov,"+; // 01-ID unico mov
                    " codmov,"+; // 02-Cód. movimento
                    " idloja,"+; // 03-ID da loja
                    " codprd,"+; // 04-Cód. produto
                    " descri,"+; // 05-Descrição
                    " medlin,"+; // 06-Med. linear
                    " medidx,"+; // 07-Medida X
                    " medidy,"+; // 08-Medida Y
                    " quanti,"+; // 09-Quantidade
                    " prcomp,"+; // 10-Preço compra
                    " vrunit,"+; // 11-Pr. s/ desconto
                    " prdesc,"+; // 12-Pr. c/ desconto
                    " vrbrut,"+; // 13-Pr. Total
                    " lotenr,"+; // 14-Nr. do lote
                    " fabric,"+; // 15-Dt. fabricação
                    " valida,"+; // 16-Dt. validade
                    " tabpre"+;  // 17-Tabela preço
                    " FROM vendas_itens WHERE codmov = "+ALLTRIM(str(nPedId))+" AND idumov = '"+cUnqId+"'"
       l_Err := .F.
       a_Array := SQLArray(cItnsQry, @l_Err)
       IF LEN(a_Array) = 0
          AADD(a_Itens, {"", "", 0, 0.00, 0.00, 0.00, "", CTOD(" "), CTOD(" ")})
       ELSE
          FOR nItn := 1 TO LEN(a_Array)
             AADD(a_Itens, {a_Array[nItn,04],; // 01-Código do produto
                            a_Array[nItn,05],; // 02-Descrição
                            a_Array[nItn,09],; // 03-Quantidade
                            a_Array[nItn,11],; // 04-Preço sem desconto
                            a_Array[nItn,12],; // 05-Preço com desconto
                            a_Array[nItn,13],; // 06-Valor total do item
                            a_Array[nItn,14],; // 07-Nr. do lote
                            a_Array[nItn,15],; // 08-Data de fabricação
                            a_Array[nItn,16]}) // 09-Data de validade
          NEXT
       ENDIF
    RETURN a_Itens
    
    STATIC FUNCTION ImprVnd(oXbVnd)
       LOCAL lConf:=.F., l_Err := .F., aVdInfo := {}
       
       n_Conn := nConection(.F., .F.)
       IF n_Conn <= 0 ; RETURN .F. ; ENDIF
    
       aLojas := {}
       SqlArr := "SELECT "+;
                    "NICK01, "+; // 01-Nome da Loja 1
                    "NICK02, "+; // 02-Nome da Loja 2
                    "NICK03, "+; // 03-Nome da Loja 3
                    "NICK04, "+; // 04-Nome da Loja 4
                    "NICK05, "+; // 05-Nome da Loja 5
                    "NICK06, "+; // 06-Nome da Loja 6
                    "NICK07, "+; // 07-Nome da Loja 7
                    "NICK08, "+; // 08-Nome da Loja 8
                    "NICK09, "+; // 09-Nome da Loja 9
                    "NICK10, "+; // 10-Nome da Loja 10
                    "USAR01, "+; // 11-Usar a Loja 1 no relatório
                    "USAR02, "+; // 12-Usar a Loja 2 no relatório
                    "USAR03, "+; // 13-Usar a Loja 3 no relatório
                    "USAR04, "+; // 14-Usar a Loja 4 no relatório
                    "USAR05, "+; // 15-Usar a Loja 5 no relatório
                    "USAR06, "+; // 16-Usar a Loja 6 no relatório
                    "USAR07, "+; // 17-Usar a Loja 7 no relatório
                    "USAR08, "+; // 18-Usar a Loja 8 no relatório
                    "USAR09, "+; // 19-Usar a Loja 9 no relatório
                    "USAR10 "+;  // 20-Usar a Loja 10 no relatório
                       "FROM config_bd LIMIT 0, 1"
       aLojas := SQLArray(SqlArr)
    
       aTrnTo := {{0,""}}
       IF LEN(aLojas) > 0
          IF aLojas[1,11] ; AADD(aTrnTo, {01, aLojas[1,01]}) ; ENDIF
          IF aLojas[1,12] ; AADD(aTrnTo, {02, aLojas[1,02]}) ; ENDIF
          IF aLojas[1,13] ; AADD(aTrnTo, {03, aLojas[1,03]}) ; ENDIF
          IF aLojas[1,14] ; AADD(aTrnTo, {04, aLojas[1,04]}) ; ENDIF
          IF aLojas[1,15] ; AADD(aTrnTo, {05, aLojas[1,05]}) ; ENDIF
          IF aLojas[1,16] ; AADD(aTrnTo, {06, aLojas[1,06]}) ; ENDIF
          IF aLojas[1,17] ; AADD(aTrnTo, {07, aLojas[1,07]}) ; ENDIF
          IF aLojas[1,18] ; AADD(aTrnTo, {08, aLojas[1,08]}) ; ENDIF
          IF aLojas[1,19] ; AADD(aTrnTo, {09, aLojas[1,09]}) ; ENDIF
          IF aLojas[1,20] ; AADD(aTrnTo, {10, aLojas[1,10]}) ; ENDIF
       ENDIF
    
       dIni := CTOD("01"+SUBSTR(DTOC(DATE()),3,8))
       dFim := DATE()
       nCli := SPACE(14)
       cCli := ""
       nVdd := SPACE(3)
       cVdd := ""
       cLoja := ""
    
       DEFINE DIALOG oDRvd RESOURCE "REL_VENDAS"
       REDEFINE GET oCt41 VAR dIni ID 41 OF oDRvd BITMAP ".\figuras\editar.bmp" ACTION RMMDT(oCt41, @dIni)
       REDEFINE GET oCt42 VAR dFim ID 42 OF oDRvd BITMAP ".\figuras\editar.bmp" ACTION RMMDT(oCt41, @dFim)
       REDEFINE GET oCt43 VAR nCli PICTURE "99999999999999" ID 43 OF oDRvd UPDATE VALID ObterClie(@nCli, @cCli, oDRvd)
       REDEFINE GET oCt44 VAR cCli ID 44 OF oDRvd MEMO UPDATE
       REDEFINE GET oCt45 VAR nVdd PICTURE "999" ID 45 OF oDRvd UPDATE VALID SeekOper(@nVdd, @cVdd, oDRvd)
       REDEFINE GET oCt46 VAR cVdd ID 46 OF oDRvd MEMO READONLY UPDATE
       REDEFINE COMBOBOX oId47 VAR cLoja ITEMS ArrTranspose(aTrnTo)[2] ID 47 OF oDRvd
       REDEFINE SBUTTON oSb31 PROMPT "Confirmar" ID 31 OF oDRvd RESOURCE "btn_prt" NOBORDER XP ACTION (lConf := .T., oDRvd:End())
       REDEFINE SBUTTON oSb32 PROMPT "Cancelar"  ID 32 OF oDRvd RESOURCE "btn_ret" NOBORDER XP ACTION (lConf := .F., oDRvd:End())
       ACTIVATE DIALOG oDRvd CENTERED
       
       if ! lConf ; RETURN NIL ; ENDIF
    
       IF (EMPTY(dIni) .OR. EMPTY(dFim)) .OR. (dIni > dFim)
          SysRefresh() ; MsgAlert("Período incorreto", "Aviso")
          RETURN NIL
       ENDIF
       
       cTitlo := "PERÍODO: "+DTOC(dIni)+" A "+DTOC(dFim)
       cWhere := "vendas_info.DTOPER >= '"+SR_dtosdot(dIni)+"' AND vendas_info.DTOPER <= '"+SR_dtosdot(dFim)+"'"
    	IF VAL(nCli) > 0
          IF ! EMPTY(cWhere) ; cWhere += " AND " ; ENDIF
          cWhere += "vendas_info.DOCCPF = '"+ALLTRIM(nCli)+"'"
          IF ! EMPTY(cTitlo) ; cTitlo += "; " ; ENDIF
          cTitlo += "CLIENTE: "+ALLTRIM(cCli)
       ELSE
          IF !EMPTY(cCli)
             IF ! EMPTY(cWhere) ; cWhere += " AND " ; ENDIF
             cWhere += "vendas_info.NOMCLI LIKE '%"+ALLTRIM(cCli)+"%'"
             IF ! EMPTY(cTitlo) ; cTitlo += "; " ; ENDIF
             cTitlo += "CLIENTE: "+ALLTRIM(cCli)
          ENDIF
    	ENDIF
    	IF VAL(nVdd) > 0
          IF ! EMPTY(cWhere) ; cWhere += " AND " ; ENDIF
          cWhere += "vendas_info.VDDCOD = "+ALLTRIM(nVdd)
          IF ! EMPTY(cTitlo) ; cTitlo += "; " ; ENDIF
          cTitlo += "VENDEDOR: "+ALLTRIM(cVdd)
    	ENDIF
    	IF !EMPTY(cLoja)
          nScn := ASCAN(aTrnTo, {|CEL|CEL[2]=cLoja})
          nLoj := IIF(nScn > 0, aTrnTo[nScn,1], 0)
          IF nLoj > 0
             IF ! EMPTY(cWhere) ; cWhere += " AND " ; ENDIF
             cWhere += "vendas_info.IDLOJA = "+ALLTRIM(STR(nLoj))
             IF ! EMPTY(cTitlo) ; cTitlo += "; " ; ENDIF
             cTitlo += "LJ: "+ALLTRIM(cLoja)
          ENDIF
    	ENDIF
    
       SqlArr := "SELECT vendas_info.CODIGO, "+;  // 01 - VND-Código do Movimento / Comanda / Mesa
                        "vendas_info.IDUNIC, "+;  // 02 - VND-ID único (Salvo em vendas, itens e contas relacionadas)
                        "vendas_info.IDLOJA, "+;  // 03 - VND-ID da loja
                        "vendas_info.ORCNUM, "+;  // 04 - VND-Número Orçamento / Comanda / Espera - Convertida para venda
                        "vendas_info.NFENUM, "+;  // 05 - VND-Nº da NF ou NF-e (NFC-e fica no ITEM99)
                        "vendas_info.NFCNUM, "+;  // 06 - VND-Número da NFC-e (NF-e no ITEM55, CF/CFE no ITEM19)
                        "vendas_info.SATNUM, "+;  // 07 - VND-Número do CFE/MFE/COO (SAT@MFE / ECF)
                        "vendas_info.OPERAC, "+;  // 08 - VND-Tipo de movimento (VENDA A VISTA / VENDA A PRAZO)
                        "vendas_info.CODCLI, "+;  // 09 - VND-Código do cliente
                        "vendas_info.NOMCLI, "+;  // 10 - VND-Nome do cliente / Razão social
                        "vendas_info.FANCLI, "+;  // 11 - VND-Nome de Fantasia
                        "vendas_info.RUACEP, "+;  // 12 - VND-CEP do cliente
                        "vendas_info.RUACLI, "+;  // 13 - VND-Endereço
                        "vendas_info.RUANRO, "+;  // 14 - VND-Nº de endereço do cliente
                        "vendas_info.BAIRRO, "+;  // 15 - VND-Bairro
                        "vendas_info.CIDADE, "+;  // 16 - VND-Cidade-UF
                        "vendas_info.RUAPER, "+;  // 17 - VND-Perímetro do endereço do cliente
                        "vendas_info.FONE01, "+;  // 18 - VND-Telefone
                        "vendas_info.DOCCPF, "+;  // 19 - VND-CPF/CNPJ
                        "vendas_info.DOC_RG, "+;  // 20 - VND-RG/IE
                        "vendas_info.DTOPER, "+;  // 21 - VND-Data da venda
                        "vendas_info.HORAOP, "+;  // 22 - VND-Hora da venda
                        "vendas_info.TITENS, "+;  // 23 - VND-Valor total dos itens. O tamanho na NF-e é 15,2
                        "vendas_info.DESCIT, "+;  // 24 - VND-Total descontos só nos itens - P/Controle de pontuação.
                        "vendas_info.DESCFI, "+;  // 25 - VND-Descontos (apenas os concedidos no fechamento)
                        "vendas_info.ACRESC, "+;  // 26 - VND-Acréscimo %
                        "vendas_info.ACRES1, "+;  // 27 - VND-Valor Mão-de-obra / Serviço / Couvert artístico
                        "vendas_info.ACRES2, "+;  // 28 - VND-Valor do Couvert por pessoa (Restaurante) (ITEN - com N mesmo - evitar conflito com DBF antigo).
                        "vendas_info.QTPESS, "+;  // 29 - VND-Quantidade de pessoas (Couvert é cobrado individualmente - multiplicar)
                        "vendas_info.VRPAGO, "+;  // 30 - VND-Valor pago Em dinheiro, sem tirar o troco, c/ 3 decimais
                        "vendas_info.PGTO01, "+;  // 31 - VND-Forma de pgto 1 - Dinheiro
                        "vendas_info.PGTO02, "+;  // 32 - VND-Forma de pgto 2 - Cheque 1
                        "vendas_info.PGTO03, "+;  // 33 - VND-Forma de pgto 3 - Cheque 2
                        "vendas_info.PGTO04, "+;  // 34 - VND-Forma de pgto 4 - Cartão 1
                        "vendas_info.PGTO05, "+;  // 35 - VND-Forma de pgto 5 - Cartão 2
                        "vendas_info.PGTO06, "+;  // 36 - VND-Forma de pgto 6 - Cartão 3
                        "vendas_info.PGTO07, "+;  // 37 - VND-Forma de pgto 7 - Cartão 4
                        "vendas_info.PGTO08, "+;  // 38 - VND-Forma de pgto 8 - Outros 1
                        "vendas_info.PGTO09, "+;  // 39 - VND-Forma de pgto 9 - Outros 2
                        "vendas_info.PGTO10, "+;  // 40 - VND-Forma de pgto 10- Outros 3
                        "vendas_info.PGTO11, "+;  // 41 - VND-Forma de pgto 11- Carta de crédito
                        "vendas_info.CARTAO, "+;  // 42 - VND-Parcelas/Bandeiras dos cartões crédito: Ex: 111222333444|B1|B2|B3|B4 (onde 111=Cartão 1 em NNN vezes|B1=Bandeira do cartão 1)
                        "vendas_info.OPERAD, "+;  // 43 - VND-Operador/Caixa/Lubrificador/Montador [000CCCCCCCCCCC...]
                        "vendas_info.VDDCOD, "+;  // 44 - VND-Código do vendedor
                        "vendas_info.VDDNOM, "+;  // 45 - VND-Nome do vendedor
                        "vendas_info.CARINF, "+;  // 46 - VND-Anotações sobre o carro
                        "vendas_info.CAR_KM, "+;  // 47 - VND-A=Km atual, R=A rodar, T=Km p/ troca. [AAAAAAAAAARRRRRRRRRRTTTTTTTTTT]
                        "vendas_info.CARMOD, "+;  // 48 - VND-Veículo do cliente
                        "vendas_info.CARPLA, "+;  // 49 - VND-Placa do veículo do cliente
                        "vendas_info.OBSERV, "+;  // 50 - VND-Observação. Ex: RECEBER NA ENTREGA
                        "vendas_itens.IDUMOV, "+; // 51 - ITN-ID único do movimento
                        "vendas_itens.CODMOV, "+; // 52 - ITN-Código do movimento
                        "vendas_itens.CODPRD, "+; // 53 - ITN-Código do produto
                        "vendas_itens.DESCRI, "+; // 54 - ITN-Descrição do produto
                        "vendas_itens.MEDLIN, "+; // 55 - ITN-Medida por metragem linear? >> ((Metros * Pr.Metro)*Qtd) = Total
                        "vendas_itens.MEDIDX, "+; // 56 - ITN-Medida X / Metros
                        "vendas_itens.MEDIDY, "+; // 57 - ITN-Medida Y / Pr.Metro
                        "vendas_itens.QUANTI, "+; // 58 - ITN-Quantidade
                        "vendas_itens.PRCOMP, "+; // 59 - ITN-Preço de compra
                        "vendas_itens.VRUNIT, "+; // 60 - ITN-Preço sem desconto - Compatível com NF-e 2.0
                        "vendas_itens.PRDESC, "+; // 61 - ITN-Preço com desconto - Compatível com NF-e 2.0
                        "vendas_itens.VRBRUT, "+; // 62 - ITN-Total com desconto. O tamanho na NF-e é 15,2
                        "vendas_itens.LOTENR, "+; // 63 - ITN-Número do lote
                        "vendas_itens.FABRIC, "+; // 64 - ITN-Fabricação
                        "vendas_itens.VALIDA, "+; // 65 - ITN-Validade
                        "vendas_itens.TABPRE"  +; // 66 - ITN-Tabela utilizada
                " FROM vendas_itens"+;
     				" LEFT JOIN vendas_info ON vendas_itens.IDUMOV=vendas_info.IDUNIC"+; // Undestanding JOINs: http://www.sitepoint.com/understanding-sql-joins-mysql-database/
     				" WHERE ("+cWhere+")"+; // WHERE clause mas be placed ahead of JOIN.
    				" ORDER BY vendas_info.IDUNIC"
    
       aVdInfo := SQLArray(SqlArr, @l_Err)
       * XBrowse(aVdInfo, "Movimentos obtidos")
    
       IF LEN(aVdInfo) = 0
          SysRefresh() ; MsgAlert("Sem movimentação no período requisitado.", "Aviso")
          RETURN NIL
       ENDIF
    
       PRINTER oPrn TO SelectedPrn() NAME "Movimentos" PREVIEW
       oPrn:SetPortrait()
       DEFINE FONT oFont NAME "Courier New"  SIZE 0, -8  OF oPrn
       DEFINE FONT oFon1 NAME "Arial Narrow" SIZE 0, -10 OF oPrn
       DEFINE FONT oFon2 NAME "Arial"        SIZE 0, -14 OF oPrn BOLD
       DEFINE FONT oFon3 NAME "Arial"        SIZE 0, -12 OF oPrn
       DEFINE FONT oFon4 NAME "Arial Narrow" SIZE 0, -8  OF oPrn BOLD
       DEFINE PEN oPen COLOR CLR_BLACK WIDTH (oFont:nHeight/10)
    
       nRow  := 03
       nPag  := 01
       mLarg := oFont:nHeight
       nTab  := oPrn:nHorzRes() / 20
       nSpc  := (oPrn:nHorzRes()-(2*nTab)) / 90
       nCls  := {nTab+(nSpc*00),; // 1Cód Movimento
                 nTab+(nSpc*10),; // 2-Cliente
                 nTab+(nSpc*48),; // 3-Valor
                 nTab+(nSpc*56),; // 4-Desconto
                 nTab+(nSpc*64),; // 5-Liquido
                 nTab+(nSpc*66),; // 6-Vendedor/Operador
                 nTab+(nSpc*80),; // 7-F.Pg
                 nTab+(nSpc*90) } // 8-Data
    
       oPrn:StartPage()
    
       oPrn:Box(03*mLarg, nTab, 11*mLarg, oPrn:nHorzRes()-nTab, oPen )
       oPrn:SayBitmap((4 * mLarg ), nTab+nSpc, ".\figuras\logomarc.bmp", 28*nSpc, 6*mLarg)
       nRow  := 4
       oPrn:Say(nRow*mLarg, nTab+(nSpc*30), "RAZÃO SOCIAL DA EMPRESA", oFon2 )
       nRow+=2
       oPrn:Say(nRow*mLarg, nTab+(nSpc*30), "ENDEREÇO DO ESTABELECIMENTO, N. 0 - BAIRRO", oFont )
       nRow++
       oPrn:Say(nRow*mLarg, nTab+(nSpc*30), "CIDADE - UF", oFont )
       oPrn:Say(nRow*mLarg, oPrn:nHorzRes()-(1.2*nTab), DTOC(DATE()), oFont,,,,1)
       nRow++
       oPrn:Say(nRow*mLarg, nTab+(nSpc*30), "TELEFONE", oFont )
       oPrn:Say(nRow*mLarg, oPrn:nHorzRes()-(1.2*nTab), LEFT(TIME(),5)+"h", oFont,,,,1)
    
       nRow += 4
       oPrn:Say(nRow*mLarg, nTab+(nSpc*45), "RELATÓRIO DE VENDAS - "+cTitlo, oFon4,,,,2)
       nRow++
    
       cIdUnq := aVdInfo[1,2]
       nItnVd := 1
       nTotVd := 0
       FOR nVn := 1 TO LEN(aVdInfo)
          IF cIdUnq <> aVdInfo[nVn,2] // Já é outra venda
             cIdUnq := aVdInfo[nVn,2]
             nItnVd := 1
          ENDIF
          IF nItnVd = 1 // Primeiro item da venda. Informações gerais.
             // Definir a principal forma de pagamento
             cFpg := ""
             IF aVdInfo[nVn,31] > 0 ; cFpg := "DIN" ; ENDIF // 1-Dinheiro
             IF aVdInfo[nVn,32] > 0 ; cFpg := "CHE" ; ENDIF // 2-Cheque
             IF aVdInfo[nVn,33] > 0 ; cFpg := "PRE" ; ENDIF // 3-Cheque pre
             IF aVdInfo[nVn,34] > 0 ; cFpg := "CRD" ; ENDIF // 4-Crd 1
             IF aVdInfo[nVn,35] > 0 ; cFpg := "CRD" ; ENDIF // 5-Crd 2
             IF aVdInfo[nVn,36] > 0 ; cFpg := "CRD" ; ENDIF // 6-Crd 3
             IF aVdInfo[nVn,37] > 0 ; cFpg := "CRD" ; ENDIF // 7-Crd 4
             IF aVdInfo[nVn,38] > 0 ; cFpg := "DEP" ; ENDIF // 8-Outros
             IF aVdInfo[nVn,39] > 0 ; cFpg := "CON" ; ENDIF // 9-Outros
             IF aVdInfo[nVn,40] > 0 ; cFpg := "OUT" ; ENDIF // 10-Outros
             // Imprimir informações gerais da venda
             FOR Y := 0 TO 89
                 oPrn:Say(nRow*mLarg, nTab+(nSpc*Y), "-", oFont)
             NEXT
             nRow++
             oPrn:Say(nRow*mLarg, nCls[1], "COD.MOV.", oFon4 )
             oPrn:Say(nRow*mLarg, nCls[2], "CLIENTE", oFon4 )
             oPrn:Say(nRow*mLarg, nCls[3], "VALOR", oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[4], "DESC.", oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[5], "LIQUIDO", oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[6], "VENDEDOR", oFon4)
             oPrn:Say(nRow*mLarg, nCls[7], "F.PG", oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[8], "DATA", oFon4,,,,1)
             nRow++
             oPrn:Say(nRow*mLarg, nCls[1], ALLTRIM(STR(aVdInfo[nVn,1])), oFon4 )
             oPrn:Say(nRow*mLarg, nCls[2], ALLTRIM(STR(aVdInfo[nVn,9]))+"-"+ALLTRIM(aVdInfo[nVn,10]), oFon4 )
             oPrn:Say(nRow*mLarg, nCls[3], ALLTRIM(TRANS(aVdInfo[nVn,23], "@E 999,999,999.9999")), oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[4], ALLTRIM(TRANS(aVdInfo[nVn,25], "@E 999,999,999.99")), oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[5], ALLTRIM(TRANS(aVdInfo[nVn,23]-aVdInfo[nVn,25], "@E 999,999,999,999.99")), oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[6], ALLTRIM(STR(aVdInfo[nVn,44]))+"-"+ALLTRIM(aVdInfo[nVn,45]), oFon4 )
             oPrn:Say(nRow*mLarg, nCls[7], cFpg, oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[8], DTOC(aVdInfo[nVn,21])+" "+aVdInfo[nVn,22] , oFon4,,,,1)
             nTotVd += (aVdInfo[nVn,23]-aVdInfo[nVn,25])
             nRow += 1.5
             oPrn:Say(nRow*mLarg, nCls[1], "PRODUTO", oFon4 )
             oPrn:Say(nRow*mLarg, nCls[2], "DESCRIÇÃO", oFon4 )
             oPrn:Say(nRow*mLarg, nCls[3], "QTD", oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[4], "P.UNIT", oFon4,,,,1)
             oPrn:Say(nRow*mLarg, nCls[5], "TOTAL", oFon4,,,,1)
             nScn := ASCAN(aTrnTo, {|CEL|CEL[1]=aVdInfo[nVn,3]})
             IF nScn > 0
                oPrn:Say(nRow*mLarg, nCls[8], "LJ: "+ALLTRIM(aTrnTo[nScn,2]), oFon4,,,,1)
             ENDIF
             nRow++
          ENDIF
          
          // Imprimir itens da venda
          oPrn:Say(nRow*mLarg, nCls[1], ALLTRIM(STR(VAL(aVdInfo[nVn,53]))), oFon1 )
          oPrn:Say(nRow*mLarg, nCls[2], aVdInfo[nVn,54], oFon1 )
          oPrn:Say(nRow*mLarg, nCls[3], ALLTRIM(TRANS(aVdInfo[nVn,58], IIF(INT(aVdInfo[nVn,58]) <> aVdInfo[nVn,58], "@E 999,999,999.999", "999999999"))), oFon1,,,,1)
          oPrn:Say(nRow*mLarg, nCls[4], ALLTRIM(TRANS(aVdInfo[nVn,61], "@E 999,999,999.9999")), oFon1,,,,1)
          oPrn:Say(nRow*mLarg, nCls[5], ALLTRIM(TRANS(aVdInfo[nVn,62], "@E 999,999,999,999.99")), oFon1,,,,1)
          nRow++
    
          IF (nRow*mLarg) >= ( oPrn:nVertRes()-(10*mLarg) )
             oPrn:Say(oPrn:nVertRes()-(4*mLarg), nTab+(nSpc*45), "PAGINA: "+ALLTRIM(STR(nPag)), oFont,,,,2)
             oPrn:EndPage()
             oPrn:StartPage()
             nPag ++
             nRow := 3
             oPrn:Line(nRow*mLarg,nTab, nRow*mLarg,oPrn:nHorzRes()-nTab, oPen )
             oPrn:Say(nRow*mLarg, nTab+(nSpc*45), "RELATÓRIO DE VENDAS", oFon3,,,,2)
             nRow += 2
             oPrn:Line(nRow*mLarg,nTab, nRow*mLarg,oPrn:nHorzRes()-nTab, oPen )
             nRow++
          ENDIF
          nItnVd ++
       NEXT
    
       nRow += 1.25
       oPrn:Line(nRow*mLarg,nTab, nRow*mLarg,oPrn:nHorzRes()-nTab, oPen )
       nRow += 0.25
    
       oPrn:Say(nRow*mLarg, nCls[3], "VALOR TOTAL DAS VENDAS:", oFon2,,,,1)
       oPrn:Say(nRow*mLarg, nCls[5], ALLTRIM(TRANS(nTotVd, "@E 999,999,999,999.99")), oFon2,,,,1)
    
       oPrn:EndPage()
       oPrn:Preview()
    
       RELEASE FONT oFont, oFon1, oFon2, oFon3, oFon4
    
    RETURN NIL

     

  9. Tenho esta para o leitor Hamster, da Nitgen.

    (2) Leitor Biométrico Hamster Dx - Nitgen - Fingkey | Mercado Livre

     

    /******************************************************************************
    * Nome do PRG: caddigit.prg                                                   *
    * Função.....: Modulo para captura e cadastro da digital (Hamster / Nitgen)   *
    * Autor......: Ariston Santos (Pode contar código de colaboradores)           *
    * Site.......: www.arsoft-ap.com.br                                           *
    * Contato....: ariston.ap@bol.com.br - MSN: arsoft-ap@hotmail.com             *
    ******************************************************************************/
    
    #include "FiveWin.ch"
    
    STATIC cTemplate, oDbrw, aDedo, vDedo
    
    FUNCTION ObterBiometria(nQue)
       LOCAL aDedos := {}, l_Err:=.F., cSql
       DEFAULT nQue := 1
       IF nQue = 1 // Armeiros
          cSql := "SELECT codigo,"+;    // 01
                        " idarmeiro,"+; // 02
                        " digital"      // 03
          cSql += " FROM sgarma_bio_armei WHERE idarmeiro > 0"
       ELSEIF nQue = 2 // Armeiros
          cSql := "SELECT codigo,"+;    // 01
                        " idmilitar,"+; // 02
                        " digital"      // 03
          cSql += " FROM sgarma_bio_milit WHERE idmilitar > 0"
       ELSE
          SysRefresh() ; MsgAlert("Opção não programada.", "Atenção")
          RETURN ""
       ENDIF
       aDedos := SQLArray(cSql, @l_Err, .F.)
       if l_Err ; RETURN "" ; endif
       IF LEN(aDedos) == 0
          SysRefresh() ; MsgAlert("Nenhuma digital de armeiro foi cadastrada ainda. Cadastre as digitais para habilitar o login protegido e biometria.", "Atenção")
          RETURN ""
       ENDIF
    RETURN TestaDedo(aDedos)
    
    FUNCTION TestaDedo(aDedos)
       LOCAL nId := "", lOerr := .T.
       CursorWait()
       TRY
          objNBioBSP := CreateObject('NBioBSPCOM.NBioBSP')
          objDevice := objNBioBSP:Device
          objExtraction := objNBioBSP:Extraction
          objMatching := objNBioBSP:Matching
          objExtraction:WindowStyle := 0
          objDevice:Open(255)
          objExtraction:DefaultTimeout := 15000 // Aguardar 15 segundos // SECS("02:00:00") * 1000 // Duas horas convertidas para milliseconds
          objExtraction:Capture()
          if objExtraction:ErrorCode <> 0
             IF objExtraction:ErrorCode = 261 // Leitor não conectado
                SysRefresh() ; MsgAlert("Falha na comunicação com o leitor biométrico. Verifique se está conectado.", ValToPrg(objExtraction:ErrorCode)+": "+objExtraction:ErrorDescription)
             ELSEIF objExtraction:ErrorCode = 516 // Tempo esgotado
                SysRefresh() ; MsgAlert("Falha na captura ou Tempo esgotado: 15 segundos.", ValToPrg(objExtraction:ErrorCode)+": "+objExtraction:ErrorDescription)
             ELSE
                SysRefresh() ; MsgAlert("Ocorreu este erro: : "+objExtraction:ErrorDescription,"Aviso")
             ENDIF
             lOerr := .F. // Não mostrar oErr description
             BREAK
          endif
          cTempl := objExtraction:TextEncodeFIR()
          IF LEN(aDedos) > 0
             FOR nDedo := 1 TO LEN(aDedos)
                objMatching:VerifyMatch(cTempl, aDedos[nDedo,3])
                if objMatching:ErrorCode <> 0
                   CursorArrow()
                   SysRefresh() ; MsgAlert("Ocorreu este erro: : "+ValToPrg(objMatching:ErrorCode)+": "+objMatching:ErrorDescription,"Aviso")
                   lOerr := .F. // Não mostrar oErr description
                   EXIT
                else
                   if objMatching:MatchingResult = 1
                      nId := ALLTRIM(STR(aDedos[nDedo,2])) // Atribuido a nOper
                      EXIT
                   endif
                endif
             NEXT
          ENDIF
          objDevice:Close(255)
       CATCH oErr
          CursorArrow()
          if lOerr
             SysRefresh() ; MsgAlert( "Não foi possível conectar-se ao leitor biométrioco."+CRLF+"Err: "+oErr:Description, "Aviso")
          endif
       END
       CursorArrow()
    RETURN( nId )
    
    FUNCTION LerBiometria()
       LOCAL digital:= "", lOerr := .T.
       CursorWait()
       TRY
          objNBioBSP := CreateObject('NBioBSPCOM.NBioBSP')
          objDevice := objNBioBSP:Device
          objExtraction := objNBioBSP:Extraction
          objMatching := objNBioBSP:Matching
          objExtraction:WindowStyle := 0
          objDevice:Open(255)
          objExtraction:DefaultTimeout := 15000 // Aguardar 15 segundos // SECS("02:00:00") * 1000 // Duas horas convertidas para milliseconds
          objExtraction:Capture()
          if objExtraction:ErrorCode <> 0
             IF objExtraction:ErrorCode = 261 // Leitor não conectado
                SysRefresh() ; MsgAlert("Falha na comunicação com o leitor biométrico. Verifique se está conectado.", ValToPrg(objExtraction:ErrorCode)+": "+objExtraction:ErrorDescription)
             ELSEIF objExtraction:ErrorCode = 516 // Tempo esgotado
                SysRefresh() ; MsgAlert("Falha na captura ou Tempo esgotado: 15 segundos.", ValToPrg(objExtraction:ErrorCode)+": "+objExtraction:ErrorDescription)
             ELSE
                SysRefresh() ; MsgAlert("Ocorreu este erro: "+objExtraction:ErrorDescription, "Aviso")
             ENDIF
             lOerr := .F. // Não mostrar oErr description
             BREAK
          endif
          digital:= objExtraction:TextEncodeFIR()
          objDevice:Close(255)
          CursorArrow()
       CATCH oErr
          CursorArrow()
          if lOerr
             SysRefresh() ; MsgAlert( "Não foi possível conectar-se ao leitor biométrioco."+CRLF+"Err: "+oErr:Description, "Aviso")
          endif
       END
       CursorArrow()
    RETURN( digital )
    

     

  10. Ah, tá.

    Eu também trabalho assim. Continuo usando arquivo temporário local, em dbf, apenas para não prejudicar desempenho (velocidade).

    Depois salvo tudo no BD remoto, da mesma forma que Rogerio Figueira.

    Quanto se há vantagem em usar SQLRDD, até o momento a única que encontrei foi a possiblidade de usar Firebird que, para rede local, atualmente está melhor que o MySQL e MariaDB no quesito "salvar em várias tabelas com uma única query". Se alguém tiver uma solução para isso em MySQL e MariaDB com SQLRDD, aceito códigos de exemplo. :D

  11. Eu uso e também tive problema com Sr_ChangeStruct(), por isso criei minha própria função. Segue. Espero que ajude.

       aStr:={}
       AADD(aStr,{"CODIGO",    "C", 13,  0}) // Código do item
       AADD(aStr,{"DESCRI",    "C",120,  0}) // Descrição do item (No SISCOM só pega 60 caracteres)
       AADD(aStr,{"DTEXCL",    "D", 08,  0}) // Data da exclusão - Para determinar quando eliminar deste bd, ex: 7 dias após a exclusão.
       l_Reindex := .F.
       IF ! SR_ExistTable( "itensdel_bd" )
          TRY
             cComm := XB2SqlStr(aStr, "itensdel_bd")
             nErr := oSql:Execute( cComm )
          CATCH oErr
             SysRefresh()
             MsgAlert("Erro ao tentar criar a tabela itensdel_bd."+CRLF+CRLF+;
                      "Favor verificar as configurações de banco de dados.","Erro")
             IF FileWrite(ErroFile(), oErr:Description)
                WAITRUN( GetEnv( "ComSpec" )+" /C NOTEPAD .\errorlog\erro.txt", 0)
             ENDIF
             PostQuitMessage( 0 )
             __QUIT()
          END
       else
          ChkStruct("itensdel_bd", "", "", aStr, oSql, nErr, nPos)
       ENDIF
    
    
    STATIC FUNCTION XB2SqlStr(aStr, cDBase)
       LOCAL cStrct
       cStrct := "CREATE TABLE `"+LOWER(cDBase)+"` ("
       FOR nF := 1 TO LEN(aStr)
       	 IF LOWER(aStr[nF,1]) !=  "sr_recno"
    	       IF nF > 1 ; cStrct += ", " ; ENDIF // Mais de um campo
    	       cStrct += "`"+LOWER(aStr[nF,1])+"` "+SetFType(aStr[nF,2],aStr[nF,3],aStr[nF,4])
           ENDIF
       NEXT
       IF LEN(aStr) > 0 ; cStrct += ", " ; ENDIF // Já acrescentado algum campo
       cStrct += "`sr_recno` BIGINT (15) NOT NULL UNIQUE AUTO_INCREMENT)" // Sempre criar o 'sr_recno' no final, para compatibilizar com SQLRDD
    RETURN( cStrct )
    
    STATIC FUNCTION SetFType(cTipo,nSize,nDeci)
       LOCAL cFType
       IF cTipo = "C" ; cFType := "char("+ALLTRIM(STR(nSize))+")"
       ELSEIF cTipo = "M" ; cFType := "mediumblob"
       ELSEIF cTipo = "N" ; cFType := "double("+ALLTRIM(STR(nSize))+","+ALLTRIM(STR(nDeci))+")"
       ELSEIF cTipo = "L" ; cFType := "tinyint(4)"
       ELSEIF cTipo = "D" ; cFType := "date"
       ENDIF
    RETURN(cFType)
    
    STATIC FUNCTION ChkStruct(cTable, cUniq, cAuto, aStrct, oSql, nErr, nPos)
       LOCAL lChangd, cComm, aNewStr, aOldStr, aChange, aImport, cImport, aArray := {}, cTmpTable := cTable+"_old"
       IF ! l_CkStr ; RETURN .F. ; ENDIF // Não deve verificar a estrutura dos dados. Apenas criar as novas tabelas
       cDBName := UPPER( SR_GetConnectionInfo(, SQL_DBMS_NAME ) )
       IF ! ("FIREBIRD" $ cDBName) // Não estou conectado ao Firebird. Firebird não aceita RENAME TABLE - http://www.firebirdfaq.org/faq363/
          aNewStr := aStrct
          nScan := ASCAN(aNewStr, {|nC|nC[1]="sr_recno"})
          IF nScan = 0
       	   AADD(aNewStr, {"sr_recno", "N", 15, 0}) // SQLRDD acrescenta este campo ao criar a tabela
          ENDIF
    
          cSay := "Verificando a tabela '"+cTable+"'"
          oSay:SetText(cSay) ; oSay:Refresh()
    
          IF ! l_CkStr ; RETURN .F.; ENDIF
    
          // Obter a estrutura da tabela atual.
          nLenTb := 0
          STORE 0 TO nErr, nPos
          TRY
             cComm := "SELECT * FROM "+cTable+" LIMIT 1"
             oSql := SR_GetConnection()
             nErr := oSql:execute( cComm )
             oSql:iniFields(.f.)
             aOldStr := oSql:aFields // Para pegar a estrutura
             nLenTb := LEN(aArray)
             * MyXBrowse(aOldStr, "Estrutura atual")
          CATCH
             SysRefresh() ; MsgAlert("Não foi possível testar a tabela '"+cTable+"'", +ProcName()+"("+AllTrim(Str(ProcLine()))+")")
             RETURN .F.
          END TRY
    
          // Comparar com a estrutura de aStrct
          lChangd := .F.
          aChange := {}
          aImport := {}
          cImport := ""
          TRY
             FOR nX := 1 TO LEN(aNewStr) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum.
                 cFild:=Lower(aNewStr[nX,1])
                 cType:=aNewStr[nX,2]
                 cSize:=STRZERO(aNewStr[nX,3], 4)
                 cDeci:=STRZERO(aNewStr[nX,4], 3)
                 nElem := ASCAN(aOldStr, {|aNro| Lower(aNro[1]) == cFild})
                 IF nElem > 0
                 	 if cFild != "sr_recno" // Não considerar erro de estrutura deste
       	             IF cType != aOldStr[nElem,2] .OR. ;
       	                cSize != STRZERO(aOldStr[nElem,3], 4) .OR. ;
       	                cDeci != STRZERO(aOldStr[nElem,4], 3)
       	                lChangd := .T. // Mudou o tamanho de um campo
       	                aadd(aChange, {cFild, "Modificou a estrutura"})
       	             ENDIF
                    endif
                 ELSE
                    lChangd := .T. // Foi removido algum campo
                    aadd(aChange, {cFild, "Campo acrescentado"})
                 ENDIF
             NEXT
             FOR nX := 1 TO LEN(aOldStr) // Verifica se foi excluindo algum compo
                 cFild := Lower(aOldStr[nX,1])
                 nElem := ASCAN(aNewStr, {|aNro| Lower(aNro[1]) == cFild})
                 IF nElem = 0
                    lChangd := .T. // Algum campo foi removido
                    aadd(aChange, {cFild, "Campo removido"})
                 ELSE
                    AADD(aImport, cFild) // Para pegar só os campos que existem nas duas tabelas.
                 ENDIF
             NEXT
             IF lChangd
                // Determinar quais campos serão importados da tabela temporária
                FOR nX := 1 TO LEN(aImport)
                    IF Lower(aImport[nX]) != "sr_recno" // Apenas um teste
                       IF ! EMPTY(cImport) ; cImport += ", " ; ENDIF
                       cImport += aImport[nX] // Pegar só os campos que existem nas duas tabelas.
                    ENDIF
                NEXT
             ENDIF
          CATCH
             SysRefresh() ; MsgAlert("Não foi possível testar a tabela '"+cTable+"'", +ProcName()+"("+AllTrim(Str(ProcLine()))+")")
             RETURN .F.
          END TRY
    
          IF ! lChangd ; RETURN .F. ; ENDIF
    
          IF SR_ExistTable( cTmpTable )
             cComm := "DROP TABLE "+cTmpTable
             TRY
                nErr := oSql:Execute( cComm )
                if nErr == 0
                   SysRefresh() ; MsgAlert("Executou "+cComm, "Ok")
                else
                   MsgAlert("Não foi preciso executar "+cComm, "Retorno: "+cValToChar(nErr))
                endif
             CATCH
                SysRefresh() ; MsgAlert("Não foi possível excluir a tabela '"+cTmpTable+"'", "Erro...")
                RETURN .F.
             END TRY
          ENDIF
    
          cComm := "ALTER TABLE "+cTable+" RENAME "+cTmpTable
          nErr := oSql:Execute( cComm )
    
          l_Err := .F.
       	TRY
             cComm := XB2SqlStr(aStrct, cTable)
             nErr := oSql:Execute( cComm )
          CATCH oErr
       	   l_Err := .T.
          END TRY
          IF l_Err
       	   cComm := "ALTER TABLE "+cTmpTable+" RENAME "+cTable
       	   nErr := oSql:Execute( cComm )
             MsgAlert("Erro ao tentar criar a nova a tabela: Executado RollBack '"+cTable+"'.","Erro") ; SysWait(1)
             RETURN .F.
          ENDIF
          IF ! EMPTY(cUniq)
             TRY
                cSql := "ALTER TABLE "+cTable+" ADD UNIQUE ("+cUniq+")"
                nErr := oSql:Execute(cSql)
             CATCH
             END TRY
          ENDIF
          IF ! EMPTY(cAuto)
             TRY
                cSql := "ALTER TABLE "+cTable+" MODIFY "+cAuto+" int NOT NULL AUTO_INCREMENT"
                nErr := oSql:Execute(cSql)
             CATCH
             END TRY
          ENDIF
          // Importar dados da tabela temporária
          IF ! empty(cImport)
             cComm := "INSERT INTO "+cTable+" ("+cImport+") SELECT "+cImport+" FROM "+cTmpTable
             nErr := oSql:Execute( cComm )
             IF nErr != 0
                MsgAlert("Erro ao tentar recuperar os dados da tabela '"+cTmpTable+"'.","Erro") ; SysWait(0.5)
             ENDIF
          ENDIF
          // Excluir a tabela temporária
          cComm := "DROP TABLE "+cTmpTable
          nErr := oSql:Execute( cComm )
       ELSE // Estou usando Firebird, que não aceita RENAME TABLE - http://www.firebirdfaq.org/faq363/
          USE &(cTable) EXCLUSIVE VIA "SQLRDD"
          a_Str := dbStruct()
          lChangd := .F.
          IF LEN(a_Str) != LEN(aStrct)
             lChangd := .T. // Campos foram removidos ou acrescentados
          ELSE
             FOR nRow := 1 TO LEN(a_Str) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum.
                 cFld := Lower(a_Str[nRow,1])
                 cTyp := a_Str[nRow,2]
                 cSze := STRZERO(a_Str[nRow,3], 4)
                 nDec := ALLTRIM(STR(a_Str[nRow,4]))
                 nElem := ASCAN(aStrct, {|aNro| UPPER(ALLTRIM(aNro[1])) == UPPER(ALLTRIM(cFld))})
                 IF nElem > 0
                 	 IF UPPER(cFld) != "SR_RECNO" // Não considerar erro de estrutura deste
       	             IF cTyp != aStrct[nElem,2] .OR. ;
       	                nDec != ALLTRIM(STR(aStrct[nElem,4])) // Não verificar nSize em campos numéricos no Firebird. Tamanho fixo: 19
       	                lChangd := .T. // Mudou a estrutura
       	             ENDIF
       	             IF cTyp == "C" .AND. cTyp == aStrct[nElem,2]
                          IF cSze <> STRZERO(aStrct[nElem,3], 4) // Considerar tamanho em campos tipo caractere
          	                lChangd := .T. // Mudou a estrutura
       	                ENDIF
       	             ENDIF
                    ENDIF
                 ELSE
                    lChangd := .T. // Campo renomeado, ou houve exclusão de um e inclusão de outro.
                 ENDIF
             NEXT
          ENDIF
          IF lChangd
             IF ! SR_ChangeStruct(cTable, aStrct) // Via SR_ChangeStruct(), indexes are automatically dropped if columns change
                lChangd := .F.
                SysRefresh() ; MsgAlert("Houve um erro ao tentar modificar a estrutura de "+cTable,"Aviso")
             ENDIF
          ENDIF
          dbCloseArea()
       ENDIF
    RETURN( .t. )
    
    *----------( Compara dois arrays e retorna .T. se houver diferença )----------*
    
    FUNCTION ArrayCheck(aArr1, aArr2)
       LOCAL cArr1 := "", cArr2 := "", cNew := "", cOld := ""
       LOCAL _lDif := .F.; _aAdd := {}; _aDif := {}; _aDel := {}
       FOR n1 := 1 TO LEN(aArr1)
           aLin := aArr1[n1]
           cNew := ""
           cOld := ""
           if ! empty(cNew) ; cNew += CRLF ; ENDIF
           FOR nL := 1 TO LEN(aLin)
               cArr1 += ALLTRIM(CStr(aLin[nL]))
               cNew += ALLTRIM(CStr(aLin[nL]))
           NEXT
           n_Id := aArr1[n1,1]
           aOld := {}
           nScn := ASCAN(aArr2,{|nCel|nCel[1]==n_Id})
           IF nScn > 0 // Se achar, verificar se houve modificação
              aOld := aArr2[nScn]
              if ! empty(cOld) ; cOld += CRLF ; ENDIF
              FOR nL := 1 TO LEN(aOld)
                  cOld += ALLTRIM(CStr(aOld[nL]))
              NEXT
           ELSE // Senão, foi excluído
              AADD(_aDel, aLin) // Gerar linha com o registro excluido
           ENDIF
           IF cNew != cOld
              AADD(_aDif, aLin) // Gerar linha com o registro modificado
           ENDIF
       NEXT
       FOR n2 := 1 TO LEN(aArr2) // Processar anteriores só para determinar se houve exclusão.
           aLin := aArr2[n2]
           FOR nL := 1 TO LEN(aLin)
               cArr2 += ALLTRIM(CStr(aLin[nL]))
           NEXT
           n_Id := aArr2[n2,1]
           nScn := ASCAN(aArr1,{|nCel|nCel[1]==n_Id})
           IF nScn = 0 // Se não achar, foi acrescentado
              AADD(_aAdd, aLin)
           ENDIF
       NEXT
       IF LEN(_aAdd) > 0 .OR. LEN(_aDif) > 0 .OR. LEN(_aDel) > 0
          _lDif := .T.
       ENDIF
       IF _lDif
          cInfo := "Houve alteração de item"
          IF LEN(_aDif) > 0
             cInfo += CRLF+CRLF+"Item diferente: "+CRLF
             FOR nL := 1 TO LEN(_aDif)
                 aLin := _aDif[nL]
                 FOR nC := 1 TO LEN(aLin)
                     cInfo += ALLTRIM(CStr(aLin[nC]))
                 NEXT
                 cInfo += CRLF
             NEXT
          ENDIF
    
          IF LEN(_aAdd) > 0
             cInfo += CRLF+CRLF+"Item novo: "+CRLF
             FOR nL := 1 TO LEN(_aAdd)
                 aLin := _aAdd[nL]
                 FOR nC := 1 TO LEN(aLin)
                     cInfo += ALLTRIM(CStr(aLin[nC]))
                 NEXT
                 cInfo += CRLF
             NEXT
          ENDIF
    
          IF LEN(_aDel) > 0
             cInfo += CRLF+CRLF+"Item excluido: "+CRLF
             FOR nL := 1 TO LEN(_aDel)
                 aLin := _aDel[nL]
                 FOR nC := 1 TO LEN(aLin)
                     cInfo += ALLTRIM(CStr(aLin[nC]))
                 NEXT
                 cInfo += CRLF
             NEXT
          ENDIF
       ENDIF
    RETURN _lDif

     

  12. Kapiaba, eu ainda não tentei. Por isso não sei lhe informar. Mas pelo que testarem, parece que não baixa xmls de emissão própria.

    Oribeiro, no forum do ACBr o pessoal deu uma dica que uso e sempre deu certo. Antes de enviar o XML para a sefaz, crie backup do xmls assinado, não autorizada. Se der bronca de retorno do Webservice, pelo ACBrMonitor tem a função de consultar enviando o backup para assinar. Com isso você resolve o problema de falha de retorno do webservice.

  13. Eu ainda não testei baixar XMLs de emissão própria. Mas creio que a baixa é apenas dos enviados para o cliente, não dos emitidos por ele.

    Sim. Requer instalar o ACBrMonitor.

    Por favor, pessoal. Se conseguirem melhorar esse código, compartilhem.

    Todo list:

    • Baixa em massa, últimos 3 meses;

    • Converter para ACBrLib (dll).

×
×
  • Create New...