Página 20 de 35

Meu modo de trabalho

Enviado: 16 Jul 2020 16:35
por JoséQuintas
E mais outra:

Depois.... vou alterar esse histórico.

Coisa simples: PRA QUE vincular produto + cadastro + forma de pagamento no histórico.... se agora o preco tem uma ID única?
Pois é.... 3 campos de vínculo, só porque eu não tinha criado uma identificação no DBF.
Agora que tem chave no arquivo de preços, o histórico só precisa dessa chave, e não mais de 3 campos.

Mas vou alterar isso depois, é perigoso mexer agora durante migração, agora que já comecei desse jeito.

Com MySQL, vai ser só fazer o relacionamento e atualizar, então fica pra uma versão futura, com calma.

Agora é terminar desse jeito, só falta um fonte.

Meu modo de trabalho

Enviado: 17 Jul 2020 14:35
por JoséQuintas

Código: Selecionar todos

30/12/2019  21:50               163 cthisto.dbf
30/12/2019  21:52               291 jprefcta.dbf
30/12/2019  21:50               355 ctlotes.dbf
30/12/2019  21:50               387 ctlanca.dbf
30/12/2019  21:50               483 jpcontabil.dbf
03/03/2020  02:44             2.799 jpfiscal.DBF
30/12/2019  21:50             5.335 jpempresa.dbf
13/07/2020  17:13             5.923 jpnumero.dbf
30/12/2019  21:50             6.691 ctplano.dbf
30/12/2019  21:52             7.416 jpuf.dbf
09/07/2020  21:18             8.123 jpbaccusto.DBF
13/07/2020  17:13             9.997 jpconfi.dbf
10/07/2020  14:32           119.029 jptabel.dbf
30/12/2019  21:50           301.112 jpdolar.dbf
06/07/2020  11:25           314.624 jpsenha.dbf
03/03/2020  02:33         1.254.539 jpcidade.dbf
13/07/2020  15:30        16.385.892 jpbancario.dbf
              17 arquivo(s)     18.423.159 bytes
E os DBFs estão reduzindo....

Meu modo de trabalho

Enviado: 18 Jul 2020 11:01
por JoséQuintas
Este é um daqueles complicados.
É um tbrowse, que por si só já é uma exceção.

Código: Selecionar todos

/*
PBANCOCOMPARAMES - COMPARATIVO MES A MES
1994.01 José Quintas
*/

#include "inkey.ch"
#include "josequintas.ch"

MEMVAR m_MostraDol, m_MostraTot, m_Ano, m_Mes, m_CodResumo, m_Tabela, nQtdCols

PROCEDURE pBancoComparaMes

   LOCAL m_Texto, m_TmpMes, m_TmpAno, oBrowse, nKey, mTop, mLeft, mBottom, mRight, ColPos
   LOCAL m_TmpMov, nMCol, nMRow, oTBrowse

   IF ! AbreArquivos( "jpempresa", "jptabel", "jpconfi", "jpbaccusto", "jpbancario" )
      RETURN
   ENDIF
   SELECT jpbancario
   OrdSetFocus( "bancario2" )
   SELECT jpbaccusto
   OrdSetFocus( "jpbaccusto2" )
   GOTO TOP
   m_Tabela := PegaContas( .T. )
   IF Len( m_Tabela ) == 2 // So contas de totais
      MsgWarning( "Não há dados p/ comparativo!" )
      RETURN
   ENDIF

   m_CodResumo           := 1
   m_Ano                 := Year( Date() )
   m_Mes                 := Month( Date() )
   m_mostratot           := .F.
   m_mostradol           := .F.
   mTop                  := 4
   mLeft                 := 0
   mBottom               := MaxRow() - 5
   mRight                := MaxCol() - 2

   oBrowse               := TBrowseDb( mTop, mLeft, mBottom, mRight )
   oBrowse:SkipBlock     := { | m_Regs | SkipBrow2( m_Regs ) }
   oBrowse:GoTopBlock    := { || TopBrow2() }
   oBrowse:GoBottomBlock := { || botbrow2() }
   oBrowse:HeadSep       := Chr(196)
   oBrowse:ColSep        := Chr(179)
   oBrowse:FootSep       := Chr(196)
   oBrowse:FrameColor    := SetColorTbrowseFrame()
   ColPos                := 2
   nQtdCols              := 5

   oTBrowse := { ;
      { "", { || FldBrow2( -1 ) } }, ;
      { "", { || FldBrow2( 0  ) } }, ;
      { "", { || FldBrow2( 1  ) } }, ;
      { "", { || FldBrow2( 2  ) } }, ;
      { "", { || FldBrow2( 3  ) } }, ;
      { "", { || FldBrow2( 4  ) } } }
   ToBrowse( oTBrowse, oBrowse )

   TitBrow2()

   oBrowse:right()

   DO WHILE ! oBrowse:Stable
      oBrowse:Stabilize()
   ENDDO
   DO WHILE .T.
      Mensagem( "SETAS, T Totais, ENTER Lançamentos, R Desp/Rec, ESC Sai" )
      nKey := 0
      DO WHILE nKey == 0 .AND. ! oBrowse:Stable
         oBrowse:Stabilize()
         nKey := Inkey()
      ENDDO

      IF oBrowse:stable()
         oBrowse:RefreshCurrent()
         DO WHILE ! oBrowse:Stabilize()
         ENDDO
         nKey = Inkey( INKEY_IDLE, HB_INKEY_ALL - INKEY_MOVE + HB_INKEY_GTEVENT )
         IF nKey == 0
            KEYBOARD Chr( K_ESC )
            LOOP
         ENDIF
      ENDIF
      nMRow := MROW()
      NMCol := MCOL()

      DO CASE
      CASE SetKey( nKey ) != NIL
         eval( SetKey( nKey ), procname(), procline(), readvar() )
      CASE nKey > 999
         DO CASE
         CASE mBrzMove( oBrowse, nMRow, nMCol, mTop + 1, mLeft + 1, mBottom - 1, mRight - 1 ) // Move cursor
         CASE mBrzClick( oBrowse, nMRow, nMCol ) // click no TBrowse atual
            //KEYBOARD Chr( K_ENTER )
         ENDCASE

      CASE nKey == K_ESC       ; EXIT

      CASE nKey == K_DOWN      ; oBrowse:Down()

      CASE nKey == K_UP        ; oBrowse:Up()

      CASE nKey == K_CTRL_DOWN ; oBrowse:PageDown()

      CASE nKey == K_CTRL_UP   ; oBrowse:PageUp()

      CASE nKey == K_LEFT
         IF ColPos == 2
            m_Ano := iif( m_Mes == 12, m_Ano + 1, m_Ano )
            m_Mes := iif( m_Mes == 12, 1, m_Mes + 1 )
            TitBrow2()
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ELSEIF ColPos > 1
            oBrowse:left()
            ColPos--
         ENDIF

      CASE nKey == K_RIGHT
         IF ColPos == ( nQtdCols + 1 )
            m_Ano = iif( m_Mes == 1, m_Ano - 1, m_Ano )
            m_Mes = iif( m_Mes == 1, 12, m_Mes - 1 )
            TitBrow2()
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ELSE
            oBrowse:right()
            ColPos++
         ENDIF

      CASE nKey == Asc( "R" ) .OR. nKey == Asc( "r" )
         IF Len( m_Tabela[ m_CodResumo ] ) == 10
            SELECT jpbaccusto
            SEEK m_Tabela[ m_CodResumo ]
            DO WHILE jpbaccusto->cuGrupo == m_Tabela[ m_CodResumo ] .AND. ! Eof()
               RecLock()
               REPLACE jpbaccusto->cuMostra WITH iif( jpbaccusto->cuMostra == "S", "N", "S" )
               RecUnlock()
               SKIP
            ENDDO
            m_Tabela := PegaContas()
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ENDIF

      CASE nKey == K_ENTER
         DO WHILE ! oBrowse:stabilize()
            GrafProc()
         ENDDO
         m_TmpMes := m_Mes - iif( ColPos > 1, ColPos - 2, 0 )
         m_TmpAno := m_Ano - iif( m_TmpMes < 1, 1, 0 )
         m_TmpMes := m_TmpMes + iif( m_TmpMes < 1, 12, 0 )
         WSave()
         Mensagem( "Aguarde, pesquisando movimentação..." )
         Cls()
         @ 2, 0 SAY "Desp/Rec:" + Trim( Left( m_Tabela[ m_CodResumo ], 10 ) ) + iif( Len( m_Tabela[ m_CodResumo ] ) == 10, "", ;
            ", Resumo:" + Trim( Right( m_Tabela[ m_CodResumo ], 10 ) ) ) + ", mes:" + StrZero( m_TmpMes, 2 ) + "/" + StrZero( m_TmpAno, 4 )
         @ 3, 0 SAY "BANCO EMISS __________HISTORICO__________ ___VALOR (NA DATA)__"
         m_tmpmov := {}
         SELECT jpbaccusto
         SEEK Left( m_Tabela[ m_CodResumo ], 10 )
         DO WHILE jpbaccusto->cuGrupo == Left( m_Tabela[ m_CodResumo ], 10 ) .AND. ! Eof()
            GrafProc()
            IF jpbaccusto->cuResumo != Right( m_Tabela[ m_CodResumo ], 10 ) .AND. Len( m_Tabela[ m_CodResumo ] ) > 10
               SKIP
               LOOP
            ENDIF
            SELECT jpbancario
            SEEK jpbaccusto->bcResumo + StrZero( m_TmpAno, 4 ) + StrZero( m_TmpMes, 2 )
            DO WHILE jpbancario->baResumo = jpbaccusto->cuCCusto .AND. Year( jpbancario->baDatEmi ) == m_TmpAno .AND. Month( jpbancario->baDatEmi ) == m_TmpMes .AND. ! Eof()
               GrafProc()
               m_Texto  = iif( jpbancario->baDatBan = Stod( "29991231" ), Space(5), Left( Dtoc( jpbancario->baDatBan ), 5 ) )
               m_Texto += Chr(179) + Left( Dtoc( jpbancario->baDatEmi ), 5 )
               m_Texto += Chr(179) + Left( jpbancario->baHist, 26 )
               m_Texto += Chr(179)
               m_Texto += Transform( jpbancario->bavalor, PicVal(14,2) )
               m_Texto += "<" + Chr(179)
               m_Texto += Space(14)
               m_Texto += " "
               AAdd( m_tmpmov, m_Texto )
               SKIP
            ENDDO
            SELECT jpbaccusto
            SKIP
         ENDDO
         IF Len( m_tmpmov ) > 0
            Mensagem( "Movimente com as setas, ENTER ou ESC sai" )
            achoice( 4, 0, 21, 79, m_tmpmov )
         ENDIF
         WRestore()

      CASE nKey == K_HOME
         oBrowse:GoTop()

      CASE nKey == K_END
         oBrowse:GoBottom()

      CASE Chr( nKey ) $ "Tt"
         m_mostratot = ( ! m_mostratot )
         TitBrow2()
         oBrowse:Invalidate()
         oBrowse:RefreshAll()

      CASE Chr( nKey ) $ "Dd"
         m_mostradol = ( ! m_mostradol )
         TitBrow2()
         oBrowse:Invalidate()
         oBrowse:RefreshAll()

      ENDCASE
   ENDDO

   RETURN

STATIC FUNCTION TopBrow2()

   m_CodResumo := 1

   RETURN .T.

STATIC FUNCTION botbrow2()

   m_CodResumo := Len( m_Tabela )

   RETURN .T.

STATIC FUNCTION SkipBrow2( nSkip )

   LOCAL nSkipped := 0

   IF nSkip == 0
   ELSEIF nSkip > 0 .AND. m_CodResumo < Len( m_Tabela )
      DO WHILE nSkipped < nSkip .AND. m_CodResumo < Len( m_Tabela )
         GrafProc()
         m_CodResumo++
         nSkipped++
      ENDDO
   ELSEIF nSkip < 0
      DO WHILE nSkipped > nSkip .AND. m_CodResumo > 1
         GrafProc()
         m_CodResumo--
         nSkipped--
      ENDDO
   ENDIF

   RETURN nSkipped

STATIC FUNCTION FldBrow2( nCont )

   LOCAL m_Retorno, m_TmpMes, m_TmpAno, m_Select

   m_TmpAno := iif( m_Mes - nCont <= 0, m_Ano - 1, m_Ano )
   m_TmpMes := iif( m_Mes - nCont <= 0, m_Mes - nCont + 12, m_Mes - nCont )
   m_Select := select()
   DO CASE
   CASE nCont == -1
      IF Len( m_Tabela[ m_CodResumo ] ) == 10
         m_Retorno := "->" + Left( m_Tabela[ m_CodResumo ], 10 )
      ELSE
         m_Retorno := "  " + Right( m_Tabela[ m_CodResumo ], 10 )
      ENDIF
   CASE ( m_Tabela[ m_CodResumo ] == ">ENTRADAS" .OR. m_Tabela[ m_CodResumo] == ">SAIDAS" ) .AND. ! m_MostraTot
      m_Retorno := ""
   CASE m_Tabela[ m_CodResumo ] = ">ENTRADAS"
      m_Retorno := Transform( SomaEntradas( m_TmpAno, m_TmpMes ), PicVal(14,2) )
   CASE m_Tabela[ m_CodResumo ] = ">SAIDAS"
      m_Retorno := Transform( SomaSaidas( m_TmpAno, m_TmpMes ), PicVal(14,2) )
   CASE Len(m_Tabela[ m_CodResumo ]) == 10
      m_Retorno := Transform( SomaGrupo( m_Tabela[ m_CodResumo ], m_TmpAno, m_TmpMes ), PicVal(14,2) )
   OTHERWISE
      m_Retorno := Transform( SomaResumo( Right( m_Tabela[ m_CodResumo ], 10 ), m_TmpAno, m_TmpMes ), PicVal(14,2) )
   ENDCASE
   SELECT ( m_Select )

   RETURN m_Retorno

STATIC FUNCTION TitBrow2()

   LOCAL nCont

   @ 2, 0 SAY Padc( "VALORES EM MOEDA VIGENTE", MaxCol() )
   @ 3, 1 SAY "Item"
   FOR nCont = 0 TO ( nQtdCols - 1 )
      @ 3, 16 + nCont * 20 SAY Padc( Space(3) + iif( m_Mes - nCont <= 0, ;
         StrZero( m_Mes - nCont + 12, 2 ) + "/" + StrZero( m_Ano - 1, 4 ), ;
         StrZero( m_Mes - nCont, 2 ) + "/" + StrZero( m_Ano, 4 ) ), 20 )
   NEXT

   RETURN .T.

STATIC FUNCTION SomaEntradas( m_Ano, m_Mes )

   LOCAL nTotal := 0, cResumo, nTotalTmp, nSelect := Select(), nRecNo

   SELECT jpbancario
   nRecNo := RecNo()
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      cResumo   := jpbancario->baResumo
      nTotalTmp := 0
      SEEK cResumo + StrZero( m_Ano, 4 ) + StrZero( m_Mes, 2 )
      DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == m_Ano .AND. Month( jpbancario->baDatEmi ) == m_Mes .AND. ! Eof()
         GrafProc()
         IF jpbancario->baResumo == Pad( "APLIC", 10 ) .OR. jpbancario->baResumo == Pad( "NENHUM", 10 )
            EXIT
         ENDIF
         nTotalTmp += jpbancario->baValor
         SKIP
      ENDDO
      IF nTotalTmp > 0
         nTotal += nTotalTmp
      ENDIF
      SEEK cResumo + "XXXX" SOFTSEEK
   ENDDO
   GOTO nRecNo
   SELECT ( nSelect )

   RETURN nTotal

STATIC FUNCTION SomaSaidas( nAno, nMes )

   LOCAL nTotal := 0, cResumo, nTotalTmp, nSelect := Select(), nRecNo

   SELECT jpbancario
   nRecNo := RecNo()
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      cResumo := jpbancario->baResumo
      nTotalTmp := 0
      SEEK cResumo + StrZero( nAno, 4 ) + StrZero( nMes, 2 )
      DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == nAno .AND. Month( jpbancario->baDatEmi ) == nMes .AND. ! Eof()
         GrafProc()
         IF jpbancario->baResumo == Pad( "APLIC", 10 ) .OR. jpbancario->baResumo == Pad( "NENHUM", 10 )
            EXIT
         ENDIF
         nTotalTmp += jpbancario->baValor
         SKIP
      ENDDO
      IF nTotalTmp < 0
         nTotal += nTotalTmp
      ENDIF
      SEEK cResumo + "XXXX" SOFTSEEK
   ENDDO
   GOTO nRecNo
   SELECT ( nSelect )

   RETURN nTotal

STATIC FUNCTION SomaGrupo( cGrupo, nAno, nMes )

   LOCAL nTotal := 0, nSelect := Select()

   SELECT jpbaccusto
   SEEK cGrupo
   DO WHILE jpbaccusto->cuGrupo == cGrupo .AND. ! Eof()
      GrafProc()
      nTotal += SomaResumo( jpbaccusto->cuCCusto, nAno, nMes )
      SKIP
   ENDDO
   SELECT ( nSelect )

   RETURN nTotal

STATIC FUNCTION SomaResumo( cResumo, nAno, nMes )

   LOCAL nTotal := 0, nSelect := Select()

   SELECT jpbancario
   SEEK cResumo + StrZero( nAno, 4 ) + StrZero( nMes, 2 )
   DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == nAno .AND. Month( jpbancario->baDatEmi ) == nMes .AND. ! Eof()
      GrafProc()
      nTotal += jpbancario->baValor
      SKIP
   ENDDO
   SELECT ( nSelect )

   RETURN nTotal

STATIC FUNCTION PegaContas( lPrimeiraVez )

   LOCAL mLista := {}, m_Grupo

   hb_Default( @lPrimeiraVez, .F. )
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      AAdd( mLista, jpbaccusto->cuGrupo )
      m_Grupo = jpbaccusto->cuGrupo
      DO WHILE jpbaccusto->cuGrupo == m_Grupo .AND. ! Eof()
         GrafProc()
         IF lPrimeiraVez .AND. jpbaccusto->cuMostra == "S"
            RecLock()
            REPLACE jpbaccusto->cuMostra WITH  "N"
            RecUnlock()
         ENDIF
         IF jpbaccusto->cuMostra=="S"
            AAdd( mLista, jpbaccusto->cuGrupo + jpbaccusto->cuCCusto )
         ENDIF
         SKIP
      ENDDO
   ENDDO
   AAdd( mLista, ">ENTRADAS" )
   AAdd( mLista, ">SAIDAS" )

   RETURN mLista
o tbrowse é feito encima de grupos de centro de custo e centros de custo, com/sem total geral.
Cada coluna se refere a um mês, sendo que a navegação na horizontal entre meses é infinita.
Está sendo usado um DBF pro browse, e as colunas são calculadas.

À primeira vista, seria trazer pronto do SQL, mas pra isso teria que limitar os meses das colunas.
Isso poderia ser resolvido se, ao ultrapassar a coluna, refizesse o comando SQL pra trazer todo browse.
Mesmo assim, teria o browse vertical das linhas, que pode variar.

Acho que a saída vai ser fazer um browse em array, ou em um recordset ADO, e as colunas continuarem sendo calculadas.

Numa primeira alteração, posso eliminar apenas o uso do arquivo de movimentação.
Esse arquivo representa 16MB dos 18MB que faltam pra converter.

Meu modo de trabalho

Enviado: 18 Jul 2020 11:56
por JoséQuintas
Fazer por etapa, primeiro alguns cálculos.
Este pra começar

Código: Selecionar todos

STATIC FUNCTION SomaResumo( cResumo, nAno, nMes )

   LOCAL nTotal := 0, nSelect := Select()

   SELECT jpbancario
   SEEK cResumo + StrZero( nAno, 4 ) + StrZero( nMes, 2 )
   DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == nAno .AND. Month( jpbancario->baDatEmi ) == nMes .AND. ! Eof()
      GrafProc()
      nTotal += jpbancario->baValor
      SKIP
   ENDDO
   SELECT ( nSelect )

   RETURN nTotal

Meu modo de trabalho

Enviado: 18 Jul 2020 12:42
por JoséQuintas
Lembram que comentei que a programação tende a seguir o "jeito humano"?
Então, por isso o comando SQL as vezes parece mais "humano" que o DBF, ou pelo menos mais claro.

Código: Selecionar todos

STATIC FUNCTION SomaResumo( cResumo, nAno, nMes )

   LOCAL nTotal
   LOCAL cnSQL := ADOClass():New( AppConexao() )
   
   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( BAVALOR ) AS SOMA" + ;
         " FROM JPBANCARIO" + ;
         " WHERE BARESUMO = " + StringSQL( cResumo ) + ;
         " AND YEAR( BADATEMI ) = " + NumberSQL( nAno ) + ;
         " AND MONTH( BADATEMI ) = " + NumberSQL( nMes )
      :Execute()
      nTotal := :Number( "SOMA" )
      :CloseRecordset()
   ENDWITH   

   RETURN nTotal
Some o valor, de um c.custo específico e de mes/ano específicos.

Código: Selecionar todos

STATIC FUNCTION SomaGrupo( cGrupo, nAno, nMes )

   LOCAL nTotal := 0, nSelect := Select()

   SELECT jpbaccusto
   SEEK cGrupo
   DO WHILE jpbaccusto->cuGrupo == cGrupo .AND. ! Eof()
      GrafProc()
      nTotal += SomaResumo( jpbaccusto->cuCCusto, nAno, nMes )
      SKIP
   ENDDO
   SELECT ( nSelect )

   RETURN nTotal
Esse é um grupo de centro de custo, que soma os centros de custo dele.
Faz uso da rotina anterior, mas acho que no SQL é melhor somar de uma vez, e não ficar fazendo somas menores.
No DBF faz sentido porque permite fazer uso da chave de pesquisa.

Meu modo de trabalho

Enviado: 18 Jul 2020 12:57
por JoséQuintas
Ficou igual o anterior, mas relacionado com a tabela de centro de custo, e indicando total por grupo.

Código: Selecionar todos

STATIC FUNCTION SomaGrupo( cGrupo, nAno, nMes )

   LOCAL nTotal := 0
   
   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( BAVALOR ) AS SOMA" + ;
         " FROM JPBANCARIO" + ;
         " LEFT JOIN JPBACCUSTO ON JPBACCUSTO.CCUSTO = JPBANCARIO.BARESUMO" + ;
         " WHERE YEAR( BADATEMI ) = " + NumberSQL( nAno ) + ;
         " AND MONTH( BADATEMI ) = " + NumberSQL( nMes ) + ;
         " AND JPBACCUSTO.CUGRUPO = " + StringSQL( cGrupo )
      :Execute()
      nTotal := :Number( "SOMA" )
      :CloseRecordset()
   ENDWITH
Eu deveria já ter renomeado BARESUMO pra BACCUSTO, mas ficou pra depois.
Começou assim, vai assim até terminar.

Meu modo de trabalho

Enviado: 18 Jul 2020 12:59
por JoséQuintas
Complemento: eu ia usar CC ou BC pro c.custo bancario, iniciais dos campos, mas vi que tava errando muito ao digitar CCCCUSTO por exemplo, muito C junto.
Acabei usando C.U.

Meu modo de trabalho

Enviado: 18 Jul 2020 13:37
por JoséQuintas
No final, a gente encontra destas coisas: duas rotinas iguais, a diferença é que uma soma positivos e a outra soma negativos:

Código: Selecionar todos


STATIC FUNCTION SomaEntradas( m_Ano, m_Mes )

   LOCAL nTotal := 0, cResumo, nTotalTmp, nSelect := Select(), nRecNo

   SELECT jpbancario
   nRecNo := RecNo()
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      cResumo   := jpbancario->baResumo
      nTotalTmp := 0
      SEEK cResumo + StrZero( m_Ano, 4 ) + StrZero( m_Mes, 2 )
      DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == m_Ano .AND. Month( jpbancario->baDatEmi ) == m_Mes .AND. ! Eof()
         GrafProc()
         IF jpbancario->baResumo == Pad( "APLIC", 10 ) .OR. jpbancario->baResumo == Pad( "NENHUM", 10 )
            EXIT
         ENDIF
         nTotalTmp += jpbancario->baValor
         SKIP
      ENDDO
      IF nTotalTmp > 0
         nTotal += nTotalTmp
      ENDIF
      SEEK cResumo + "XXXX" SOFTSEEK
   ENDDO
   GOTO nRecNo
   SELECT ( nSelect )

   RETURN nTotal

STATIC FUNCTION SomaSaidas( nAno, nMes )

   LOCAL nTotal := 0, cResumo, nTotalTmp, nSelect := Select(), nRecNo

   SELECT jpbancario
   nRecNo := RecNo()
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      cResumo := jpbancario->baResumo
      nTotalTmp := 0
      SEEK cResumo + StrZero( nAno, 4 ) + StrZero( nMes, 2 )
      DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == nAno .AND. Month( jpbancario->baDatEmi ) == nMes .AND. ! Eof()
         GrafProc()
         IF jpbancario->baResumo == Pad( "APLIC", 10 ) .OR. jpbancario->baResumo == Pad( "NENHUM", 10 )
            EXIT
         ENDIF
         nTotalTmp += jpbancario->baValor
         SKIP
      ENDDO
      IF nTotalTmp < 0
         nTotal += nTotalTmp
      ENDIF
      SEEK cResumo + "XXXX" SOFTSEEK
   ENDDO
   GOTO nRecNo
   SELECT ( nSelect )

   RETURN nTotal
Melhor até transformar em uma só, antes de converter.

Meu modo de trabalho

Enviado: 18 Jul 2020 22:48
por JoséQuintas
Só um comentário:

O Browse ficou interessante.
Neste instante, CADA célula do browse pode vir de DBF ou SQL ou Array.

Meu modo de trabalho

Enviado: 18 Jul 2020 23:39
por JoséQuintas

Código: Selecionar todos

STATIC FUNCTION SomaSaidas( nAno, nMes )

   LOCAL nTotal := 0, cResumo, nTotalTmp, nSelect := Select(), nRecNo

   SELECT jpbancario
   nRecNo := RecNo()
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      cResumo := jpbancario->baResumo
      nTotalTmp := 0
      SEEK cResumo + StrZero( nAno, 4 ) + StrZero( nMes, 2 )
      DO WHILE jpbancario->baResumo = cResumo .AND. Year( jpbancario->baDatEmi ) == nAno .AND. Month( jpbancario->baDatEmi ) == nMes .AND. ! Eof()
         GrafProc()
         IF jpbancario->baResumo == Pad( "APLIC", 10 ) .OR. jpbancario->baResumo == Pad( "NENHUM", 10 )
            EXIT
         ENDIF
         nTotalTmp += jpbancario->baValor
         SKIP
      ENDDO
      IF nTotalTmp < 0
         nTotal += nTotalTmp
      ENDIF
      SEEK cResumo + "XXXX" SOFTSEEK
   ENDDO
   GOTO nRecNo
   SELECT ( nSelect )

   RETURN nTotal
Até que ficou simples em SQL

Código: Selecionar todos

STATIC FUNCTION SomaMovimento( nAno, nMes, nTipo )

   LOCAL nTotal
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( SOMA ) AS TOTAL FROM" + ;
         " ( SELECT BARESUMO, SUM( BAVALOR ) AS SOMA" + ;
            " FROM JPBANCARIO" + ;
            " WHERE BARESUMO NOT IN ( 'APLIC', 'NENHUM' )" + ;
            " AND YEAR( BADATEMI ) = " + NumberSQL( nAno ) + ;
            " AND MONTH( BADATEMI ) = " + NumberSQL( nMes ) + ;
            " GROUP BY BARESUMO" + ;
            " HAVING SOMA " + iif( nTipo == 1, ">", "<" ) + " 0 ) AS A"
      :Execute()
      nTotal := :Number( "TOTAL" )
      :CloseRecordset()
   ENDWITH

   RETURN nTotal

Meu modo de trabalho

Enviado: 19 Jul 2020 11:58
por JoséQuintas
Realmente, esse tbrowse é daqueles, bem fora do normal.
Pra não usar mais DBF, alterei pra array multidimensional.

Alterei pra multidimensional

Código: Selecionar todos

STATIC FUNCTION PegaContas()

   LOCAL aCCustoList := {}, cGrupo
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WITH OBJECT cnSQL
      :cSQL := "SELECT CUGRUPO, CUCCUSTO FROM JPBACCUSTO ORDER BY CUGRUPO, CUCCUSTO"
      :Execute()
      DO WHILE ! :Eof()
         AAdd( aCCustoList, { :String( "CUGRUPO" ), "", .T. } )
         cGrupo = :String( "CUGRUPO" )
         DO WHILE cGrupo == :String( "CUGRUPO" ) .AND. ! Eof()
            AAdd( aCCustoList, { :String( "CUGRUPO" ), :String( "CUCCUSTO" ), .F. } )
            :MoveNext()
         ENDDO
      ENDDO
      :CloseRecordset()
   ENDWITH
   AAdd( aCCustoList, { ">ENTRADAS", "", .F. } )
   AAdd( aCCustoList, { ">SAIDAS", "", .F. } )

   RETURN aCCustoList
O detalhe é o último item da lista, .T. ou .F.
Se for .F., NÃO é pra aparecer na tela.
Então tive que criar skip/top/bottom especiais.

Código: Selecionar todos

STATIC FUNCTION TopCCusto()

   m_CodResumo := 1
   DO WHILE ! aCCustoList[ m_CodResumo, 3 ]
      m_CodResumo++
   ENDDO

   RETURN .T.

STATIC FUNCTION BottomCCusto()

   m_CodResumo := Len( aCCustoList )
   DO WHILE ! aCCustoList[ m_CodResumo, 3 ]
      m_CodResumo--
   ENDDO

   RETURN .T.

STATIC FUNCTION SkipCCusto( nSkip )

   LOCAL nSkipped := 0

   IF nSkip == 0
   ELSEIF nSkip > 0 .AND. m_CodResumo < Len( aCCustoList )
      DO WHILE nSkipped < nSkip .AND. m_CodResumo <= Len( aCCustoList )
         m_CodResumo++
         IF m_CodResumo <= Len( aCCustoList ) .AND. aCCustoList[ m_CodResumo, 3 ]
            nSkipped++
         ENDIF
      ENDDO
      IF m_CodResumo > Len( aCCustoList )
         BottomCCusto()
      ENDIF
   ELSEIF nSkip < 0
      DO WHILE nSkipped > nSkip .AND. m_CodResumo >= 1
         m_CodResumo--
         IF m_CodResumo > 0 .AND. aCCustoList[ m_CodResumo, 3 ]
            nSkipped--
         ENDIF
      ENDDO
      IF m_CodResumo < 1
         TopCCusto()
      ENDIF
   ENDIF

   RETURN nSkipped
NÃO é pra aparecer na tela, mas.... depende desse valor.

Meu modo de trabalho

Enviado: 19 Jul 2020 12:01
por JoséQuintas
Se apertar a letra T, aparecem os totais.

Código: Selecionar todos

      CASE Chr( nKey ) $ "Tt"
         aCCustoList[ Len( aCCustoList ) - 1, 3 ] := ! aCCustoList[ Len( aCCustoList ) - 1, 3 ]
         aCCustoList[ Len( aCCustoList ), 3 ] := ! aCCustoList[ Len( aCCustoList ), 3 ]
         TitBrow2()
         oBrowse:Invalidate()
         oBrowse:RefreshAll()
E se teclar a letra C, aparece o detalhamento de CCusto sobre o grupo que está posicionado.

Código: Selecionar todos

      CASE nKey == Asc( "C" ) .OR. nKey == Asc( "c" )
         IF Empty( aCCustoList[ m_CodResumo, 2 ] )
            FOR EACH oElement IN aCCustoList
               IF oElement[ 1 ] == aCCustoList[ m_CodResumo, 1 ] .AND. ! Empty( oElement[ 2 ] )
                  oElement[ 3 ] := ! oElement[ 3 ]
               ENDIF
            NEXT
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ENDIF

Meu modo de trabalho

Enviado: 19 Jul 2020 12:04
por JoséQuintas
Atualizei o nome, não faz mais sentido m_CodResumo, troquei pra nIndexCCusto
nIndex, porque é a chave, e CCusto, porque se refere a Centro de Custo.

Meu modo de trabalho

Enviado: 19 Jul 2020 12:10
por JoséQuintas
o tbrowse em questão é este aqui:
banco.png
Dá pra escolher pra detalhar o grupo que quiser, tantos quantos quiser.
Na imagem, só detalhei o grupo bens.

Então, ao teclar C em "BENS", ou detalha ou esconde os Centros de Custo desse grupo.

Meu modo de trabalho

Enviado: 19 Jul 2020 15:19
por JoséQuintas
Não serve de referência pra nada, porque é diferente de tudo, mas.... tá feito.

Código: Selecionar todos

/*
PBANCOCOMPARAMES - COMPARATIVO MES A MES
1994.01 José Quintas
*/

#include "inkey.ch"
#include "josequintas.ch"
#define BA_ENTRADAS  1
#define BA_SAIDAS   -1

MEMVAR nIndexAno, nIndexMes, nIndexCCusto, aCCustoList, nQtdCols

PROCEDURE pBancoComparaMes

   LOCAL m_TmpMes, m_TmpAno, oBrowse, nKey, mTop, mLeft, mBottom, mRight, ColPos
   LOCAL nMCol, nMRow, oTBrowse, oElement

   IF ! AbreArquivos( "jpempresa", "jptabel", "jpconfi", "jpbaccusto", "jpbancario" )
      RETURN
   ENDIF
   aCCustoList := PegaContas( .T. )

   nIndexCCusto          := 1
   nIndexAno             := Year( Date() )
   nIndexMes             := Month( Date() )
   mTop                  := 4
   mLeft                 := 0
   mBottom               := MaxRow() - 5
   mRight                := MaxCol() - 2

   oBrowse               := TBrowseDb( mTop, mLeft, mBottom, mRight )
   oBrowse:SkipBlock     := { | nSkipRows | CCustoSkip( nSkipRows ) }
   oBrowse:GoTopBlock    := { || CCustoGoTop() }
   oBrowse:GoBottomBlock := { || CCustoGoBottom() }
   oBrowse:HeadSep       := Chr(196)
   oBrowse:ColSep        := Chr(179)
   oBrowse:FootSep       := Chr(196)
   oBrowse:FrameColor    := SetColorTbrowseFrame()
   ColPos                := 2
   nQtdCols              := 5

   oTBrowse := { ;
      { "", { || CCustoColuna( -1 ) } }, ;
      { "", { || CCustoColuna( 0  ) } }, ;
      { "", { || CCustoColuna( 1  ) } }, ;
      { "", { || CCustoColuna( 2  ) } }, ;
      { "", { || CCustoColuna( 3  ) } }, ;
      { "", { || CCustoColuna( 4  ) } } }
   ToBrowse( oTBrowse, oBrowse )

   CCustoTitulo()

   oBrowse:Right()

   DO WHILE .T.
      Mensagem( "SETAS, T Totais, ENTER Lançamentos, D Detalhes, ESC Sai" )
      nKey := 0
      DO WHILE nKey == 0 .AND. ! oBrowse:Stable
         oBrowse:Stabilize()
         nKey := Inkey()
      ENDDO

      IF oBrowse:Stable()
         oBrowse:RefreshCurrent()
         DO WHILE ! oBrowse:Stabilize()
         ENDDO
         nKey = Inkey( INKEY_IDLE, HB_INKEY_ALL - INKEY_MOVE + HB_INKEY_GTEVENT )
         IF nKey == 0
            KEYBOARD Chr( K_ESC )
            LOOP
         ENDIF
      ENDIF
      nMRow := MROW()
      NMCol := MCOL()

      DO CASE
      CASE SetKey( nKey ) != NIL
         eval( SetKey( nKey ), procname(), procline(), readvar() )
      CASE nKey > 999
         DO CASE
         CASE mBrzMove( oBrowse, nMRow, nMCol, mTop + 1, mLeft + 1, mBottom - 1, mRight - 1 )
         CASE mBrzClick( oBrowse, nMRow, nMCol )
         ENDCASE

      CASE nKey == K_ESC       ; EXIT
      CASE nKey == K_DOWN      ; oBrowse:Down()
      CASE nKey == K_UP        ; oBrowse:Up()
      CASE nKey == K_CTRL_DOWN ; oBrowse:PageDown()
      CASE nKey == K_CTRL_UP   ; oBrowse:PageUp()
      CASE nKey == K_HOME      ; oBrowse:GoTop()
      CASE nKey == K_END       ; oBrowse:GoBottom()

      CASE nKey == K_LEFT
         IF ColPos == 2
            nIndexAno := iif( nIndexMes == 12, nIndexAno + 1, nIndexAno )
            nIndexMes := iif( nIndexMes == 12, 1, nIndexMes + 1 )
            CCustoTitulo()
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ELSEIF ColPos > 1
            oBrowse:Left()
            ColPos--
         ENDIF

      CASE nKey == K_RIGHT
         IF ColPos == ( nQtdCols + 1 )
            nIndexAno = iif( nIndexMes == 1, nIndexAno - 1, nIndexAno )
            nIndexMes = iif( nIndexMes == 1, 12, nIndexMes - 1 )
            CCustoTitulo()
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ELSE
            oBrowse:Right()
            ColPos++
         ENDIF

      CASE nKey == Asc( "D" ) .OR. nKey == Asc( "d" )
         IF Empty( aCCustoList[ nIndexCCusto, 2 ] )
            FOR EACH oElement IN aCCustoList
               IF oElement[ 1 ] == aCCustoList[ nIndexCCusto, 1 ] .AND. ! Empty( oElement[ 2 ] )
                  oElement[ 3 ] := ! oElement[ 3 ]
               ENDIF
            NEXT
            oBrowse:Invalidate()
            oBrowse:RefreshAll()
         ENDIF

      CASE nKey == K_ENTER
         DO WHILE ! oBrowse:stabilize()
            GrafProc()
         ENDDO
         m_TmpMes := nIndexMes - iif( ColPos > 1, ColPos - 2, 0 )
         m_TmpAno := nIndexAno - iif( m_TmpMes < 1, 1, 0 )
         m_TmpMes := m_TmpMes + iif( m_TmpMes < 1, 12, 0 )
         CCustoDetalhes( aCCustoList[ nIndexCCusto, 1 ], aCCustoList[ nIndexCCusto, 2 ], m_TmpMes, m_TmpAno )

      CASE Chr( nKey ) $ "Tt"
         aCCustoList[ Len( aCCustoList ) - 1, 3 ] := ! aCCustoList[ Len( aCCustoList ) - 1, 3 ]
         aCCustoList[ Len( aCCustoList ), 3 ] := ! aCCustoList[ Len( aCCustoList ), 3 ]
         CCustoTitulo()
         oBrowse:Invalidate()
         oBrowse:RefreshAll()

      ENDCASE
   ENDDO
   CLOSE DATABASES

   RETURN

STATIC FUNCTION CCustoGoTop()

   nIndexCCusto := 1
   DO WHILE ! aCCustoList[ nIndexCCusto, 3 ]
      nIndexCCusto++
   ENDDO

   RETURN .T.

STATIC FUNCTION CCustoGoBottom()

   nIndexCCusto := Len( aCCustoList )
   DO WHILE ! aCCustoList[ nIndexCCusto, 3 ]
      nIndexCCusto--
   ENDDO

   RETURN .T.

STATIC FUNCTION CCustoSkip( nSkip )

   LOCAL nSkipped := 0

   IF nSkip == 0
   ELSEIF nSkip > 0 .AND. nIndexCCusto < Len( aCCustoList )
      DO WHILE nSkipped < nSkip .AND. nIndexCCusto <= Len( aCCustoList )
         nIndexCCusto++
         IF nIndexCCusto <= Len( aCCustoList ) .AND. aCCustoList[ nIndexCCusto, 3 ]
            nSkipped++
         ENDIF
      ENDDO
      IF nIndexCCusto > Len( aCCustoList )
         CCustoGoBottom()
      ENDIF
   ELSEIF nSkip < 0
      DO WHILE nSkipped > nSkip .AND. nIndexCCusto >= 1
         nIndexCCusto--
         IF nIndexCCusto > 0 .AND. aCCustoList[ nIndexCCusto, 3 ]
            nSkipped--
         ENDIF
      ENDDO
      IF nIndexCCusto < 1
         CCustoGoTop()
      ENDIF
   ENDIF

   RETURN nSkipped

STATIC FUNCTION CCustoColuna( nCont )

   LOCAL m_Retorno, m_TmpMes, m_TmpAno

   m_TmpAno := iif( nIndexMes - nCont <= 0, nIndexAno - 1, nIndexAno )
   m_TmpMes := iif( nIndexMes - nCont <= 0, nIndexMes - nCont + 12, nIndexMes - nCont )
   DO CASE
   CASE nCont == -1
      IF Empty( aCCustoList[ nIndexCCusto, 2 ] )
         m_Retorno := "->" + Pad( aCCustoList[ nIndexCCusto, 1 ], 10 )
      ELSE
         m_Retorno := "  " + Pad( aCCustoList[ nIndexCCusto, 2 ], 10 )
      ENDIF
   CASE ! aCCustoList[ nIndexCCusto, 3 ]
      m_Retorno := ""
   CASE aCCustoList[ nIndexCCusto, 1 ] = ">ENTRADAS"
      m_Retorno := Transform( SomaMovimento( m_TmpAno, m_TmpMes, BA_ENTRADAS ), PicVal(14,2) )
   CASE aCCustoList[ nIndexCCusto, 1 ] = ">SAIDAS"
      m_Retorno := Transform( SomaMovimento( m_TmpAno, m_TmpMes, BA_SAIDAS ), PicVal(14,2) )
   CASE Empty( aCCustoList[ nIndexCCusto, 2 ] )
      m_Retorno := Transform( SomaGrupo( aCCustoList[ nIndexCCusto, 1 ], m_TmpAno, m_TmpMes ), PicVal(14,2) )
   OTHERWISE
      m_Retorno := Transform( SomaResumo( aCCustoList[ nIndexCCusto, 2 ], m_TmpAno, m_TmpMes ), PicVal(14,2) )
   ENDCASE

   RETURN m_Retorno

STATIC FUNCTION CCustoTitulo()

   LOCAL nCont

   @ 2, 0 SAY Padc( "VALORES EM MOEDA VIGENTE", MaxCol() )
   @ 3, 1 SAY "Item"
   FOR nCont = 0 TO ( nQtdCols - 1 )
      @ 3, 16 + nCont * 20 SAY Padc( Space(3) + iif( nIndexMes - nCont <= 0, ;
         StrZero( nIndexMes - nCont + 12, 2 ) + "/" + StrZero( nIndexAno - 1, 4 ), ;
         StrZero( nIndexMes - nCont, 2 ) + "/" + StrZero( nIndexAno, 4 ) ), 20 )
   NEXT

   RETURN .T.

STATIC FUNCTION SomaMovimento( nAno, nMes, nTipo )

   LOCAL nTotal
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( SOMA ) AS TOTAL FROM" + ;
         " ( SELECT BARESUMO, SUM( BAVALOR ) AS SOMA" + ;
         " FROM JPBANCARIO" + ;
         " WHERE BARESUMO NOT IN ( 'APLIC', 'NENHUM' )" + ;
         " AND Year( BADATEMI ) = " + NumberSQL( nAno ) + ;
         " AND Month( BADATEMI ) = " + NumberSQL( nMes ) + ;
         " GROUP BY BARESUMO" + ;
         " HAVING SOMA " + iif( nTipo == 1, ">", "<" ) + " 0 ) AS A"
      :Execute()
      nTotal := :Number( "TOTAL" )
      :CloseRecordset()
   ENDWITH

   RETURN nTotal

STATIC FUNCTION SomaGrupo( cGrupo, nAno, nMes )

   LOCAL nTotal
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( BAVALOR ) AS SOMA" + ;
         " FROM JPBANCARIO" + ;
         " LEFT JOIN JPBACCUSTO ON JPBACCUSTO.CUCCUSTO = JPBANCARIO.BARESUMO" + ;
         " WHERE Year( BADATEMI ) = " + NumberSQL( nAno ) + ;
         " AND Month( BADATEMI ) = " + NumberSQL( nMes ) + ;
         " AND JPBACCUSTO.CUGRUPO = " + StringSQL( cGrupo )
      :Execute()
      nTotal := :Number( "SOMA" )
      :CloseRecordset()
   ENDWITH

   RETURN nTotal

STATIC FUNCTION SomaResumo( cResumo, nAno, nMes )

   LOCAL nTotal
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( BAVALOR ) AS SOMA" + ;
         " FROM JPBANCARIO" + ;
         " WHERE BARESUMO = " + StringSQL( cResumo ) + ;
         " AND Year( BADATEMI ) = " + NumberSQL( nAno ) + ;
         " AND Month( BADATEMI ) = " + NumberSQL( nMes )
      :Execute()
      nTotal := :Number( "SOMA" )
      :CloseRecordset()
   ENDWITH

   RETURN nTotal

STATIC FUNCTION PegaContas()

   LOCAL aCCustoList := {}, cGrupo
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WITH OBJECT cnSQL
      :cSQL := "SELECT CUGRUPO, CUCCUSTO FROM JPBACCUSTO ORDER BY CUGRUPO, CUCCUSTO"
      :Execute()
      DO WHILE ! :Eof()
         AAdd( aCCustoList, { :String( "CUGRUPO" ), "", .T. } )
         cGrupo = :String( "CUGRUPO" )
         DO WHILE cGrupo == :String( "CUGRUPO" ) .AND. ! Eof()
            AAdd( aCCustoList, { :String( "CUGRUPO" ), :String( "CUCCUSTO" ), .F. } )
            :MoveNext()
         ENDDO
      ENDDO
      :CloseRecordset()
   ENDWITH
   AAdd( aCCustoList, { ">ENTRADAS", "", .F. } )
   AAdd( aCCustoList, { ">SAIDAS", "", .F. } )

   RETURN aCCustoList

STATIC FUNCTION CCustoDetalhes( cGrupo, cCCusto, nMes, nAno )

   LOCAL oTBrowse
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   WSave()
   Mensagem( "Aguarde, pesquisando movimentação..." )
   Cls()
   @ 2, 0 SAY "Grupo:" + cGrupo + iif( Empty( cCCusto ), "", ", CCusto:" + cCCusto ) + ;
      ", mes:" + StrZero( nMes, 2 ) + "/" + StrZero( nAno, 4 )
   WITH OBJECT cnSQL
      :cSQL := "SELECT JPBACCUSTO.CUGRUPO, IDBANCARIO, BACONTA, BARESUMO," + ;
         " BADATBAN, BADATEMI, BAHIST, BAVALOR" + ;
         " FROM JPBANCARIO" + ;
         " LEFT JOIN JPBACCUSTO ON JPBACCUSTO.CUCCUSTO = JPBANCARIO.BARESUMO" + ;
         " WHERE Year( BADATEMI ) = " + NumberSQL( nAno ) + ;
         " AND Month( BADATEMI ) = " + NumberSQL( nMes ) + ;
         " AND JPBACCUSTO.CUGRUPO = " + StringSQL( cGrupo )
      IF ! Empty( cCCusto )
         :cSQL += " AND BARESUMO = " + StringSQL( cCCusto )
      ENDIF
      :cSQL += " ORDER BY BACONTA, BADATBAN, BADATEMI, IDBANCARIO"
      :Execute()
      oTBrowse := { ;
         { "BANCO",     { || iif( :Date( "BADATBAN" ) == Stod( "29991231" ), Space(8), :Date( "BADATBAN" ) ) } }, ;
         { "EMISSAO",   { || :Date( "BADATEMI" ) } }, ;
         { "HISTORICO", { || :String( "BAHIST", 50 ) } }, ;
         { "VALOR",     { || Transform( :Number( "BAVALOR" ), PicVal(14,2) ) } } }
      BrowseADO( cnSQL, oTBrowse, "BAHIST", { || "" } )
      :CloseRecordset()
   ENDWITH
   KEYBOARD ""
   WRestore()

   RETURN NIL

Aproveitei pra usar nomes melhores, dividir melhor, etc. etc.
Até eliminei o uso de variáveis PRIVATE, mas voltei atrás.
Também pensei em deixar as variáveis numa classe, pra simplificar, mas... dá no mesmo de variável PRIVATE, então ficou assim.