Clipper On Line • Ver Tópico - Meu modo de trabalho

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

 

Meu modo de trabalho

Mensagempor JoséQuintas » 18 Jul 2020 22:48

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 18 Jul 2020 23:39

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

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 11:58

Realmente, esse tbrowse é daqueles, bem fora do normal.
Pra não usar mais DBF, alterei pra array multidimensional.

Alterei pra multidimensional
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.

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 12:01

Se apertar a letra T, aparecem os totais.

      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.

      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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 12:04

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 12:10

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 15:19

Não serve de referência pra nada, porque é diferente de tudo, mas.... tá feito.

/*
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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 17:43

Cabe um comentário interessante sobre o fonte:

No geral, as modificações foram para organizar o fonte, e não para o SQL.
Os 3 módulos que pegariam do DBF, agora pegam do SQL, e até que ficaram relativamente simples.

Antes, acabava gravando no DBF, só por causa da visualização.
A gravação foi eliminada com o uso de array.
O resto passou a ser só consulta, que é o que deveria ser desde o começo.

Também poderia ser um recordset ADO local, ao invés de array.... mas assim tá bom.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 17:55

Este outro eu até já sei o que vou usar.
Este altera toda ordem do bancário, pra mostrar tudo junto e misturado, não importa a conta.
Outra gravação no DBF que não deveria existir.

Usando o resultado de outras pesquisas pela internet, vai ser substituído por um único comando SQL.

/*
PBANCOCONSOLIDA - SALDO CONSOLIDADO DAS CONTAS
1994.04 José Quintas
*/

#include "inkey.ch"

MEMVAR mRecalcAuto, m_Filtro

PROCEDURE pBancoConsolida

   LOCAL mDataIni, m_Saldo, m_DtBco, m_DtEmi, oTBrowse
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   m_FIltro := {} // pra usar na funcao chamada
   mRecalcAuto := .T. // necessaria ref. recalculo
   mDataIni := Ctod("") // para uso da funcao pBancoLanca
   HB_SYMBOL_UNUSED( mRecalcAuto + mDataIni )
   IF ! AbreArquivos( "jpempresa", "jptabel", "jpconfi", "jpbaccusto", "jpbancario" )
      RETURN
   ENDIF
   WITH OBJECT cnSQL
      SELECT jpbaccusto
      GOTO TOP
      SELECT jpbancario

      Mensagem( "Aguarde... Efetuando cálculos..." )
      SELECT jpbancario
      OrdSetFocus( "bancario3" )
      GOTO TOP
      m_Saldo = 0
      DO WHILE ! Eof()
         Grafproc()
         m_saldo += jpbancario->bavalor
         :QueryCreate()
         :QueryAdd( "BASALDO", m_Saldo )
         jpbancario->( :DBFQueryExecuteUpdate( "JPBANCARIO" ) )
         :QueryExecuteUpdate( "JPBANCARIO", "IDBANCARIO = " + NumberSQL( jpbancario->idBancario ) )
         SKIP
      ENDDO
      GOTO BOTTOM
      m_dtbco = Ctod("")
      m_dtemi = Ctod("")
      DO WHILE ! Bof()
         GrafProc()
         IF jpbancario->baDatBan != m_dtbco
            IF jpbancario->baImpSld != "S"
               :QueryCreate()
               :QueryAdd( "BAIMPSLD", "S" )
               jpbancario->( :DBFQueryExecuteUpdate( "JPBANCARIO" ) )
               :QueryExecuteUpdate( "JPBANCARIO", "IDBANCARIO = " + NumberSQL( jpbancario->idBancario ) )
            ENDIF
         ELSEIF jpbancario->baDatBan == Stod( "29991231" ) .AND. jpbancario->baDatEmi != m_dtemi
            IF jpbancario->baImpSld != "S"
               :QueryCreate()
               :QueryAdd( "BAIMPSLD", "S" )
               jpbancario->( :DBFQueryExecuteUpdate( "JPBANCARIO" ) )
               :QueryExecuteUpdate( "JPBANCARIO", "IDBANCARIO = " + NumberSQL( jpbancario->idBancario ) )
            ENDIF
         ELSEIF jpbancario->baImpSld == "S"
            :QueryCreate()
            :QueryAdd( "BAIMPSLD", "N" )
            jpbancario->( :DBFQueryExecuteUpdate( "JPBANCARIO" ) )
            :QueryExecuteUpdate( "JPBANCARIO", "IDBANCARIO = " + NumberSQL( jpbancario->idBancario ) )
         ENDIF
         m_dtbco = jpbancario->baDatBan
         m_dtemi = jpbancario->baDatEmi
         SKIP -1
      ENDDO
      SEEK Dtos( Date() ) SOFTSEEK
      Mensagem( "I Inclui, A Altera, E Exclui, Ctrl-L Pesquisa, ESC Sai" )
      oTBrowse := { ;
         { "BANCO",         { || iif( jpbancario->baValor == 0, Replicate( "-", 8 ), iif( jpbancario->baDatBan == Stod( "29991231" ), Space(8), Dtoc( jpbancario->baDatBan ) ) ) } }, ;
         { "EMISSÃO",       { || iif( jpbancario->baValor == 0, Replicate( "-", 8 ), iif( jpbancario->baDatEmi == Stod( "29991231" ), Space(8), Dtoc( jpbancario->baDatEmi ) ) ) } }, ;
         { "DESP/REC",      { || iif( jpbancario->baValor == 0, Replicate( "-", Len( jpbancario->baResumo ) ), jpbancario->baResumo ) } }, ;
         { "HISTÓRICO",     { || iif( jpbancario->baValor == 0, Pad( jpbancario->baConta + iif( jpbancario->baAplic == "S", "(Aplicação)", "" ), Len( jpbancario->bahist ) ), jpbancario->baHist ) } }, ;
         { "ENTRADA",       { || iif( jpbancario->baValor > 0, Transform( Abs( jpbancario->baValor ), PicVal(14,2) ), Space( Len( Transform( 0, PicVal(14,2) ) ) ) ) } }, ;
         { "SAÍDA",         { || iif( jpbancario->baValor < 0, Transform( Abs( jpbancario->baValor ), PicVal(14,2) ), Space( Len( Transform( 0, PicVal(14,2) ) ) ) ) } }, ;
         { "SALDO",         { || iif( jpbancario->baImpSld == "S", Transform( jpbancario->baSaldo, PicVal(14,2) ), Space( Len( Transform( jpbancario->baSaldo, PicVal(14,2) ) ) ) ) } }, ;
         { " ",             { || ReturnValue( " ", vSay( 2, 0, "CONTA " + jpbancario->baConta ) ) } } }
      DO WHILE .T.
         BrowseDbfRC( 4, 0, MaxRow() - 3, MaxCol(), oTBrowse, { | b, k | DigBancoLanca( b, k ) } )
         IF LastKey() == K_ESC
            EXIT
         ENDIF
      ENDDO
      OrdSetFocus( "bancario1" )
   ENDWITH
   RecalculoBancario()
   CLOSE DATABASES

   RETURN
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 19 Jul 2020 18:27

Pronto, com duas coisas novas, pra mim, do MySQL:

#include "inkey.ch"

PROCEDURE pBancoConsolida

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

   WITH OBJECT cnSQL
      :cSQL := "SET @SOMA = 0"
      :ExecuteCmd()
      :cSQL := "SELECT BADATBAN, BADATEMI, BARESUMO, BAHIST, " + ;
         " IF( BAVALOR > 0, BAVALOR, 0 ) AS ENTRADA," + ;
         " IF( BAVALOR < 0, BAVALOR, 0 ) AS SAIDA," + ;
         " @SOMA := @SOMA + BAVALOR AS SALDO" + ;
         " FROM JPBANCARIO" + ;
         " WHERE BAVALOR <> 0"  + ;
         " ORDER BY BADATBAN, BADATEMI, IDBANCARIO"
      :Execute()
      oTBrowse := { ;
         { "BANCO",     { || if( :Date( "BADATBAN" ) = Stod( "29991231" ), Space(8), Dtoc( :Date( "BADATBAN" ) ) ) } }, ;
         { "EMISSAO",   { || :Date( "BADATEMI" ) } }, ;
         { "CCUSTO",    { || :String( "BARESUMO", 10 ) } }, ;
         { "HISTORICO", { || :String( "BAHIST", 50 ) } }, ;
         { "ENTRADAS",  { || Transform( :Number( "ENTRADA" ), "@ZE 999,999,999.99" ) } }, ;
         { "SAIDAS",    { || Transform( :Number( "SAIDA" ), "@ZE 999,999,999.99" ) } }, ;
         { "SALDO",     { || Transform( :Number( "SALDO" ), "@E 999,999,999.99" ) } } }
      BrowseADO( cnSQL, oTBrowse, "BAHIST", { || "" } )
      :cSQL := "SET @SOMA = NULL"
      :ExecuteCmd()
      :CloseRecordset()
   ENDWITH
   KEYBOARD ""
   CLOSE DATABASES

   RETURN


De novidade, criar uma variável no início e apagar no final.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 20 Jul 2020 14:12

Tem uma coisa que tive que retirar no browse anterior.... mas acho que tem solução.

Mostrar o saldo apenas no último lançamento do dia.

Vai ser um comando "diferente", mas acho que dá.
Um comando parecido, uma coluna S/N, mudou a data, altera pra S
O detalhe é que isso precisa ser em ordem decrescente de data, e o browse precisa em ordem crescente.

Pensei numa possibilidade, que parece maluca, mas é relativamente simples:

SELECT ..... ORDER BY ASC // este aqui só altera ordem
FROM
( SELECT ... ORDER BY DESC ) // este aqui altera mostrar s/n
FROM
( SELECT ... ORDER BY ASC ) // este aqui calcula saldo


Pego em ordem crescente pra fazer a conta do saldo
Depois em decrescente, pra colocar esse Sim ou Não quando alterar data
Depois novamente em crescente pra ficar na ordem da tela

Pra otimizar, e usar menos memória do servidor, TALVEZ fazer os selects só da parte que interessa, e no final relacionar e trazer o histórico.
TALVEZ, sei lá se isso ajuda ou atrapalha o servidor.

Talvez esteja na hora de usar alguma ferramenta que analise os processos do servidor.
Nenhum problema até agora, mas.... como eu digo sempre, melhor ver isso quando está tudo tranquilo, do que quando estiver com problema.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor Vlademiro » 20 Jul 2020 21:38

Você poderia criar views para as consultas mais complexas, aí não precisaria escrever sempre selects mais complexos no seu código. Só precisa de um sistema de trabalho para gravar essas views (uma espécie de dicionário). As view não poupam recursos, porque o select continua sendo o mesmo, mas facilita para você.
Avatar de usuário

Vlademiro
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 647
Data de registro: 11 Jul 2005 02:46
Curtiu: 12 vezes
Mens.Curtidas: 43 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 20 Jul 2020 22:41

Vlademiro escreveu:Você poderia criar views para as consultas mais complexas


Por enquanto ainda evitando isso, até porque ainda não me senti seguro com o backup do MySQL contendo VIEW.
Achei que no backup o view fica esquisito, diferente do comando usado pra criação.
Tô mais pra gravar o comando numa tabela normal do que num view.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14276
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor Vlademiro » 20 Jul 2020 23:16

Pense na view como uma espécie de variável. O backup de uma view é só o seu comando de criação Create view ... Ela faz parte da estrutura do banco, não dos dados.
Avatar de usuário

Vlademiro
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 647
Data de registro: 11 Jul 2005 02:46
Curtiu: 12 vezes
Mens.Curtidas: 43 vezes

Meu modo de trabalho

Mensagempor Vlademiro » 20 Jul 2020 23:25

O único problema grave que um banco de dados pode apresentar, na minha opinião, é ele ficar lento devido a triggers e store procedures que vc cria. A gente vai se empolgando e começa a passar toda a lógica de negócios para o banco. Se isso não for bem feito, o banco fica lento. Os especialistas, não eu, recomendam não abusar desse recurso. Quanto a view ela é uma forma de tornar o comando select mais fácil para vc manter no futuro. Se vc mecher em alguma tabela, mudar o nome dos campos, a view correspondente vai parar de funcionar. Outro cuidado é não criar selects muito complexos para não deixar o banco lento. As vezes se for um relatório de fim de mês compensa, mas para uso diário não. Para isso existem ferramentas que analisam o desempenho do select ente ajudam a encontrar bgargalos.
Avatar de usuário

Vlademiro
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 647
Data de registro: 11 Jul 2005 02:46
Curtiu: 12 vezes
Mens.Curtidas: 43 vezes

Anterior Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 2 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro