Meu modo de trabalho

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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....
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Meu modo de trabalho

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder