IMPRESSÃO - Rotina extraída do MIRO, em puro clipper

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
acelconsultoria
Usuário Nível 3
Usuário Nível 3
Mensagens: 231
Registrado em: 10 Jan 2006 17:05
Localização: Itápolis-SP

IMPRESSÃO - Rotina extraída do MIRO, em puro clipper

Mensagem por acelconsultoria »

Bom pessoal... eu até acho que a grande maioria aqui já conhece o MIRO. Os sistemas gerados pelo MIRO recebem algumas funções e classes para auxiliar em procedimentos diversos. Sei que já são manjadas, mas resolvi extrair aqui a rotina de impressão, para que os interessados possam utilizar ou estudar.


Aqui, vai o arquivo MIRO.CH (necessário incluir no #include):

Código: Selecionar todos

#define DESLIGA  0
#define LIGA     1
#define CURSOR(P_CUR) (SETCURSOR( IIF( P_CUR = 0, 0, IIF( READINSERT(), 3, 1 ) ) ))
#define SOS(TEX_TO)  (SOS += TEX_TO + CHR(13) + CHR(10))
#define BEEP()         TONE( 250, 4 )
#define T_ENTER         13
#define T_ESC           27
#define T_INSERT        22
#define T_CIMA           5
#define T_BAIXO         24
#define T_ESQUERDA      19
#define T_DIREITA        4
#define T_HOME           1
#define T_END            6
#define T_PGUP          18
#define T_PGDN           3
#define T_BACKSPACE      8
#define T_CTRL_W        23
#define T_F1            28
#define T_F2            -1
#define T_F3            -2
#define T_F4            -3
#define T_F5            -4
#define T_F6            -5
#define T_F7            -6
#define T_F10           -9
#define T_CTRL_PGDN     30
#define T_CTRL_PGUP     31
#define T_DEL            7
#define T_CTRL_HOME     29
#define T_CTRL_END      23
#define T_CTRL_ESQUERDA 26
#define T_CTRL_DIREITA   2
#define T_TAB            9
#define T_SH_TAB       271
#define TB_COR_DEL      CONTECOR[ 4 ]  // Cor dos registros DELETADOS
#define TB_RODAPE       "ÄÁÄ"  // Caracteres para o rodape do TBROWSE
#define TB_SEP_LIN      " ³ "  // Separadores de coluna do TBROWSE
#define TB_SEP_CAB      "ÄÂÄ"  // Separadores do cabecalho do TBROWSE
#define TB_JANELA       "ÚÄ¿³´³ÙÄÀ³Ã³"
#define MOSTRA_PAG_1      "M"
#define CONSULTA          "C"
#define ALTERACAO         "A"
#define EXCLUSAO          "E"
#define INCLUSAO          "I"
#define SUB_MENU       1
#define MENU_PRINCIPAL 0
#define COLUNAR             1
#define COLUNAR_AUTOMATICO  2
#define FICHA               3
#define ETIQUETA            4
#define SIM  .T.
#define NAO  .F.
#define _TIPO_REL      1
#define _TITULOS       2
#define _CONTEUDO      3
#define _REDUCAO       4
#define _LIN_SUP       5
#define _LIN_INF       6
#define _COL_INI       7
#define _SEPARADOR     8
#define _TOTALIZA      9
#define _SEP_CAB      10
#define _SUB_TOT      11
#define _TIT_TOT      12
#define _TIT_SUB_TOT  13
#define _QUEBRA       14
#define _RESUMO       15
#define _LARGURA      16
#define _LINHA        17
#define _PAGINA       18
#define _BLOCO_CAB    19
#define _TIPO_SAIDA   20
#define _TIT_STOT_QUE 21
#define _FILTRO       22
#define _LARG_MEMO    23
#define _PRE_CONTEUDO 24
#define _NUM_COL_ET   25
#define _COL_DISTANC  26
#define _LIN_DISTANC  27
#define _QUANT_LIN    28
#translate relatorio:TIPO                   => ObjRelatorio\[ _TIPO_REL ]
#translate relatorio:TITULOS                => ObjRelatorio\[ _TITULOS ]
#translate relatorio:CONTEUDO               => ObjRelatorio\[ _CONTEUDO ]
#translate relatorio:REDUCAO                => ObjRelatorio\[ _REDUCAO ]
#translate relatorio:LIN_SUPERIOR           => ObjRelatorio\[ _LIN_SUP ]
#translate relatorio:LIN_INFERIOR           => ObjRelatorio\[ _LIN_INF ]
#translate relatorio:COL_INICIAL            => ObjRelatorio\[ _COL_INI ]
#translate relatorio:SEPARADOR              => ObjRelatorio\[ _SEPARADOR ]
#translate relatorio:TOTALIZA               => ObjRelatorio\[ _TOTALIZA ]
#translate relatorio:SEP_CABECALHO          => ObjRelatorio\[ _SEP_CAB ]
#translate relatorio:SUB_TOTALIZACAO        => ObjRelatorio\[ _SUB_TOT ]
#translate relatorio:TITULO_TOTAL           => ObjRelatorio\[ _TIT_TOT ]
#translate relatorio:TITULO_SUB_TOTAL       => ObjRelatorio\[ _TIT_SUB_TOT ]
#translate relatorio:TIT_SUBTOTAL_QUEBRA    => ObjRelatorio\[ _TIT_STOT_QUE ]
#translate relatorio:RESUMO                 => ObjRelatorio\[ _RESUMO ]
#translate relatorio:LARGURA                => ObjRelatorio\[ _LARGURA ]
#translate relatorio:LINHA                  => ObjRelatorio\[ _LINHA ]
#translate relatorio:PAGINA                 => ObjRelatorio\[ _PAGINA ]
#translate relatorio:SAIDA                  => ObjRelatorio\[ _TIPO_SAIDA ]
#translate relatorio:BLOCO_CABECALHO        => ObjRelatorio\[ _BLOCO_CAB ]
#translate relatorio:QUEBRA                 => ObjRelatorio\[ _QUEBRA ]
#translate relatorio:FILTRO                 => ObjRelatorio\[ _FILTRO ]
#translate relatorio:MEMO_LARGURA           => ObjRelatorio\[ _LARG_MEMO ]
#translate relatorio:PRE_CONTEUDO           => ObjRelatorio\[ _PRE_CONTEUDO ]
#translate relatorio:NUM_COLUNAS_ETQ        => ObjRelatorio\[ _NUM_COL_ET ]
#translate relatorio:COL_DISTANCIA          => ObjRelatorio\[ _COL_DISTANC ]
#translate relatorio:LIN_DISTANCIA          => ObjRelatorio\[ _LIN_DISTANC ]
#translate relatorio:QUANTIDADE_LIN         => ObjRelatorio\[ _QUANT_LIN ]
#translate relatorio:CONTEUDO()             => ObjMenu
#translate relatorio:RODA()                 => IIF( relatorio:TIPO = FICHA,;
                                       IMP_FICHA( PROCNAME(), PROCLINE() ),;
         IIF( relatorio:TIPO = ETIQUETA, IMP_ETQ( PROCNAME(), PROCLINE() ),;
                                       IMP_REL( PROCNAME(), PROCLINE() ) ) )
#translate relatorio:FILTRO( <X1> )         => ObjRelatorio\[ _FILTRO ] :=;
                                               { || <X1> }
#translate relatorio:LIMPA()             =>;
   ObjRelatorio := { 1,;      // Tipo do relatorio
                    {},;      // Titulos do relatorio
                    {},;      // Conteudo
                   NIL,;      // Reducao de caracteres
                     1,;      // Linha superior
                    61,;      // Linha inferior
                     1,;      // Coluna inicial
                     3,;      // Separador de colunas p/COLUNAR_AUTOMATICO
                    {},;      // Totalizacao
                   "-",;      // Separador de cabecalho
                   .F.,;      // Define se SUB-TOTALIZA
               "TOTAL",;      // Titulo para totalizacao
           "SUB-TOTAL",;      // Titulo para sub_total
                    {},;      // Quebras
                   NIL,;      // Resumo ( Rel. tipo balancetes )
                     0,;      // Largura -> Este dado e' de controle interno do objeto
                     0,;      // Linha -> Este dado e' de controle interno do objeto
                     1,;      // Pagina -> Este dado e' de controle interno do objeto
                   NIL,;      // Bloco de codigo para desvio do cabecalho
                   "I",;      // Tipo saida -> Este dado e' de controle interno do objeto
           "Sub-Total",;      // Titulo para sub_total de quebras
                   NIL,;      // Codigo de bloco contendo a expressao do filtro
                    75,;      // Largura dos campos tipo MEMO
                    {},;      // Pre-conteudo
                     2,;      // Numero de colunas da etiquetas
                     2,;      // Colunas entre etiquetas
                     1,;      // Linhas entre etiquetas
                     0 }      // Quantidade de linhas
#translate relatorio:ADD( <X1>, <X2>[, <X3>][, <X4>][ ,<X5>] )  =>;
           AADD( ObjRelatorio\[ _CONTEUDO ], { <X1>, { || <X2> },;
                 <"X2">[, <X3>][, <X4>][, <X5>] } )
#translate relatorio:ADDTOTAL( <X1>[, <X2>][, <X3>] )  =>;
           AADD( ObjRelatorio\[ _TOTALIZA ], { { || <X1> },;
                 <"X1">[, <X2>][, <X3>] } )
#translate relatorio:ADDQUEBRA( <X1>, <X2>[, <X3>][, <X4>] )  =>;
           AADD( ObjRelatorio\[ _QUEBRA ], { { || <X1> },;
                 <X2>[, <X3>][, <X4>] } )
#translate relatorio:ADDTITULO( <X1> )  =>;
           AADD( ObjRelatorio\[ _TITULOS ], { || <X1> } )
#translate relatorio:ADDPRECONTEUDO( <X1> )  =>;
           AADD( ObjRelatorio\[ _PRE_CONTEUDO ], { || <X1> } )
#define SALTA_PAGINA     0
#define SALTA_1_LINHA    1
#define SALTA_2_LINHAS   2
#define SALTA_3_LINHAS   3
#define TOTALIZA_QUEBRA .T.
#define _CABECALHO  1
#define _DADOS      2
#define _NOME_CAMPO 3
#define _COLUNA     4
#define _MASCARA    5
#define _TIPO_MENU     1
#define _OPCOES_MENU   2
#define _CHAMADA_MENU  3
#translate menu:LIMPA() => ObjMenu := { 0, {}, {} }
#translate menu:TIPO_MENU  =>  ObjMenu\[ _TIPO_MENU ]
#translate menu:RODA()  =>  MENU( ObjMenu, PROCNAME(), PROCLINE() )
#translate menu:ADD( <X1>, <X2>[, <X3> ] )  => ;
           AADD( ObjMenu\[ _OPCOES_MENU ], <X1> )\; AADD( ObjMenu\[ _CHAMADA_MENU ], { || <X2>[, <X3> ] } )
#translate menu:ADD( <X1> )  => ;
           AADD( ObjMenu\[ _OPCOES_MENU ], <X1> )\; AADD( ObjMenu\[ _CHAMADA_MENU ], { || NIL } )
#translate menu:CONTEUDO()  =>  ObjMenu
#define MOSTRA_BOTOES    0
#define EDITA_BOTOES     1
#define MOVIMENTA_BOTAO  2
#translate botao:LIMPA()     =>  ObjBotao := {}
#translate botao:RODA()      =>  BOTAO()
#translate botao:RODA( <X> ) =>  BOTAO( <X> )
#translate botao:MOSTRA()  =>  BOTAO( .T., .T. )
#translate botao:MOVIMENTA( <X1>, <X2>, <X3> )  =>  BOTAO( <X1>, <X2>, <X3> )
#translate botao:ADD( <X1>, <X2>, <X3> )  => ;
           AADD( ObjBotao, { <X1>, <X2>, <X3> } )
#translate botao:CONTEUDO()  =>  ObjBotao
Continua...
Adm. Maickon Sato
Consultoria e Projetos
-------------------------------------------------------
Avatar do usuário
acelconsultoria
Usuário Nível 3
Usuário Nível 3
Mensagens: 231
Registrado em: 10 Jan 2006 17:05
Localização: Itápolis-SP

Parte II

Mensagem por acelconsultoria »

... continuação:

Funções de auxílio a rotina:

Código: Selecionar todos


FUNCTION AJUSTE  // Conta os caracteres, para ajustar a fonte
LOCAL MAXIMO, REDUCAO, MARGEM, CONTAR, CONTADOR, NUM_FORMULARIO
PARA LARGURA, FORMULARIO
IF VALTYPE( LARGURA ) = "C"
   FORMULARIO := LARGURA
   LARGURA := 150
ENDIF
REDUCAO := ""
MAXIMO := 0
IF FORMULARIO = "80"
   NUM_FORMULARIO := 1
ELSE
   NUM_FORMULARIO := 2
ENDIF
FOR CONTAR := 1 TO LEN( IMPRESSORA )
   IF LARGURA <= IMPRESSORA[ CONTAR ][ 1 ][ NUM_FORMULARIO ]
      MAXIMO := IMPRESSORA[ CONTAR ][ 1 ][ NUM_FORMULARIO ]
      FOR CONTADOR := 1 TO LEN( IMPRESSORA[ CONTAR ][ 2 ] )
         REDUCAO += CHR( IMPRESSORA[ CONTAR ][ 2 ][ CONTADOR ] )
      NEXT
      EXIT
   ENDIF
NEXT
IF FORMULARIO = "ETIQUETA"
   FOR CONTADOR := 1 TO LEN( IMPRESSORA[ REDUCAO_ETQ ][ 2 ] )
      REDUCAO += CHR( IMPRESSORA[ REDUCAO_ETQ ][ 2 ][ CONTADOR ] )
   NEXT
   ?? REDUCAO
*   SET MARGIN TO 0
ELSE
   IF MAXIMO = 0
      @ 00, 01 SAY "SEM AJUSTE"
      RETURN .F.
   ENDIF
   MARGEM := INT( ( MAXIMO - LARGURA ) / 2 ) + relatorio:COL_INICIAL - 1
*   SET MARGIN TO MARGEM
   @ PROW(), PCOL() + 1 SAY REDUCAO
ENDIF
RETURN .T.



FUNCTION MENU_PRN // Menu de impressão
ARQ_PRN := "REPORT"
RESTSCREEN( LIN_MENU + 1, 00, 23, 79, TELA_PRI )
** FUNDO()
JANELA( 06, 21, 19, 59, TRIM( SUBS( NOME_IMP, 1, 33 ) ) )
COR( "MENU" )
@ 09, 26 CLEAR TO 13, 54
IF NUM_RELATORIO = 0
   TIPO_FORMULARIO := "0"
ELSE
   TIPO_FORMULARIO := FOR_MULARIO[ NUM_RELATORIO ]
ENDIF
WHILE .T.
   @ 06, 23 SAY PADC( TRIM( SUBS( NOME_IMP, 1, 33 ) ), 35 ) COLOR CONTECOR[ 5 ]
   botao:ADD( 15, 33, "Impressoras   " )
   botao:ADD( 17, 33, "Formulario " + IIF( TIPO_FORMULARIO = "1",;
              "132", "080" ) )
   botao:MOSTRA()
   MENU_CFG := { "     (" + CHR( 7 ) + ") Impressora",;
                 "     (" + CHR( 7 ) + ") Tela      ",;
                 "     (" + CHR( 7 ) + ") Arquivo   " }
   SETCOLOR( CONTECOR[ 2 ] + "," + CONTECOR[ 7 ] )
   KEYBOARD CHR( 32 )
   OPC_PRN := ACHOICE( 10, 28, 12, 52, MENU_CFG, .T., "FUN_CFG" )
   IF LASTKEY() = T_TAB .OR. LASTKEY() = T_SH_TAB
      botao:ADD( 15, 33, "Impressoras   " )
      botao:ADD( 17, 33, "Formulario " + IIF( TIPO_FORMULARIO = "1",;
                 "132", "080" ) )
      IF LASTKEY() = T_TAB
         OPCAO_BOTAO := 1
      ELSE
         OPCAO_BOTAO := 2
      ENDIF
      OPCAO_BOTAO := botao:RODA( OPCAO_BOTAO )
      IF OPCAO_BOTAO = 0
         LOOP
      ELSEIF OPCAO_BOTAO = 1
         KEYBOARD "I"
      ELSE
         KEYBOARD "F"
      ENDIF
      INKEY( 0 )
   ENDIF
   IF LASTKEY() = ASC( "I" ) .OR. LASTKEY() = ASC( "i" )
      botao:MOVIMENTA( 15, 33, "Impressoras   " )
      TELA_PRN := SAVESCREEN( 00, 00, 24, 79 )
      IF LEN( IMP_ARQ ) != 0
         ME_NU := {}
         FOR CONTADOR := 1 TO LEN( IMP_ARQ )
            AADD( ME_NU, " " + TRIM( IMP_ARQ[ CONTADOR ][ 1 ] ) )
         NEXT
         JANELA( 03, 08, 21, 72, "Sele‡„o de impressora" )
         botao:ADD( 19, 28, "Enter   " )
         botao:ADD( 19, 44, "Esc     " )
         botao:MOSTRA()
         COR( "MENU" )
         @ 05, 12 CLEAR TO 17, 68
         KEYBOARD CHR( T_CIMA )
         SELECAO_IMP := 1
         SELECAO_IMP := ACHOICE( 06, 13, 16, 67, ME_NU )
         IF SELECAO_IMP = 0
            botao:MOVIMENTA( 19, 44, "Esc     " )
            RESTSCREEN( 00, 00, 24, 79, TELA_PRN )
            LOOP
         ENDIF
         botao:MOVIMENTA( 19, 44, "Enter   " )
         CON_ARQ := IMP_ARQ[ SELECAO_IMP ][ 2 ]
         LER_IMP( CON_ARQ )
      ENDIF
      RESTSCREEN( 00, 00, 24, 79, TELA_PRN )
      LOOP
   ENDIF
   IF LASTKEY() = ASC( "F" ) .OR. LASTKEY() = ASC( "f" )
      botao:MOVIMENTA( 17, 33, "Formulario " +;
                       IIF( TIPO_FORMULARIO = "1", "132", "080" ) )
      TIPO_FORMULARIO := IIF( TIPO_FORMULARIO = "1", "0", "1" )
      IF NUM_RELATORIO > 0
         FOR_MULARIO[ NUM_RELATORIO ] := TIPO_FORMULARIO
      ENDIF
      LOOP
   ENDIF
   IF AT( UPPER( CHR( LASTKEY() ) ), "SCR" ) > 0
      LOOP
   ENDIF
   IF OPC_PRN = 0
      RETURN NIL
   ELSEIF OPC_PRN = 1
      TIPO_PRN := "I"
      IF !ISPRINTER()
         BEEP()
         MENSAGEM( "Impressora desligada ou desconectada", 3 )
         LOOP
      ENDIF
   ELSEIF OPC_PRN = 2
      TIPO_PRN := "T"
      EX_T := ( VAL( SUBS( TIME(), 4, 2 ) ) * 10 ) + VAL( SUBS( TIME(), 7, 2 ) )
      ARQ_PRN += "." + STRZERO( EX_T, 3 )
      SET PRINTER TO &ARQ_PRN
   ELSEIF OPC_PRN = 3
      RESTSCREEN( LIN_MENU + 1, 00, 23, 79, TELA_PRI )
      JANELA( 07, 16, 17, 62, "Saidas" )
      COR( "MENU" )
      @ 10, 20 CLEAR TO 14, 58
      @ 11, 23 SAY "Digite o nome do arquivo de saida"
      ARQ_PRN := SPACE( 20 )
      WHILE .T.
         @ 13,29 GET ARQ_PRN PICT "@!" VALID ISALPHA( ARQ_PRN )
         CURSOR( LIGA )
         READ
         CURSOR( DESLIGA )
         IF LASTKEY() = T_ESC
            RETURN NIL
         ENDIF
         IF AT(".",ARQ_PRN) != 0
            BEEP()
            MENSAGEM( "Digite o nome do arquivo sem extens„o", 3 )
            LOOP
         ENDIF
         EXIT
      ENDDO
      ARQ_PRN := ALLTRIM( ARQ_PRN ) + ".PRN"
      TIPO_PRN := "A"
      SET PRINTER TO &ARQ_PRN
   ENDIF
   MENSAGEM( "Tecle <ESC> para pausa ou interrup‡„o" )
   RETURN TIPO_PRN
ENDDO
 
FUNCTION IMP_TELA
PARA TAM_LIN
MARG_ESQ := 1
IF MARG_ESQ = NIL
   MARG_ESQ := 0
ENDIF
ARQ_PRN := "REPORT"
MARG_ESQ++
MENSAGEM( "Aguarde processamento" )
SELE 100
PUBL QUAN_REG, ULT_POS
ARQ_PRN1 := ARQ_PRN + "." + STRZERO( EX_T, 3 )
ARQ_PRN2 := ARQ_PRN + "." + STRZERO( EX_T + 100, 3 )
DBCREATE( ARQ_PRN2, { { "LI_NHA", "C", TAM_LIN + 1, 0 } } )
IF !USEREDE(ARQ_PRN2,.T.,10)
   BEEP()
   MENSAGEM( "Nao foi possivel acesso, tente novamente", 5 )
   RETURN .F.
ENDIF
APPEND FROM &ARQ_PRN1 SDF
QUAN_REG := LASTREC()
IF QUAN_REG = 0
   QUAN_REG := 1
ENDIF
GOTO TOP
JANELA( LIN_MENU + 3, 02, 21, 77 )
@ LIN_MENU + 4, 77 SAY CHR( 30 )
@ 20, 77 SAY CHR( 31 )
IF TAM_LIN < 72
   EDI_TAR := { "SUBS( LI_NHA, MARG_ESQ )" }
ELSE
   IF INT( TAM_LIN / 36 ) = TAM_LIN / 36
      NUM_COL := TAM_LIN / 36
   ELSE
      NUM_COL := INT( TAM_LIN / 36 ) + 1
   ENDIF
   X=1
   EDI_TAR := {}
   FOR CONTAR = 1 TO NUM_COL - 1
      NUM_MAT := ( CONTAR * 36 ) - 34
      AADD( EDI_TAR, "SUBS( LI_NHA, "+STR(NUM_MAT,3)+", 36 )" )
   NEXT
   NUM_MAT := ( CONTAR * 36 ) - 34
   AADD( EDI_TAR, "SUBS( LI_NHA, " + STR( NUM_MAT, 3 ) + ") + SPACE(" + STR( ( NUM_COL * 36 ) - TAM_LIN, 2 ) + ")" )
ENDIF
KEYBOARD CHR( 65 )
ULT_POS := LIN_MENU + 5
MENSAGEM( "Tecle <ESC> para sair" )
SOS_MENU := "RELATORIO"
SETCOLOR( CONTECOR[ 4 ] + "," + CONTECOR[ 7 ] )
DBEDIT( LIN_MENU + 4, 04, 20, 75, EDI_TAR, "FUN_IMP", "", "", "", "" )
SOS_MENU := " "
USE
FERASE( ARQ_PRN1 )
FERASE( ARQ_PRN2 )
RELEASE QUAN_REG, ULT_POS

FUNCTION FUN_IMP
IF LASTKEY() = T_ESC
   RETURN 0
ELSEIF LASTKEY() = T_HOME
   GOTO TOP
ELSEIF LASTKEY() = T_END
   GOTO BOTT
ENDIF
COR( "BOX DA JANELA DE DIALOGO" )
@ ULT_POS, 77 SAY " "
ULT_POS := LIN_MENU + 5 + ( ( ( RECN() * 100 ) / QUAN_REG ) /;
           ( 100 / ( 19 - ( LIN_MENU + 5 ) ) ) )
IF RECN() = 1
   ULT_POS := LIN_MENU + 5
ENDIF
@ ULT_POS, 77 SAY CHR( 4 )
SETCOLOR( CONTECOR[ 4 ] + "," + CONTECOR[ 7 ] )
RETURN 1
... continua ...
Adm. Maickon Sato
Consultoria e Projetos
-------------------------------------------------------
Avatar do usuário
acelconsultoria
Usuário Nível 3
Usuário Nível 3
Mensagens: 231
Registrado em: 10 Jan 2006 17:05
Localização: Itápolis-SP

Parte III

Mensagem por acelconsultoria »

... continuação...


Aqui, mais umas funções auxiliares:

Código: Selecionar todos


FUNCTION IMP_REL
LOCAL SAIDA := "S", LARGURA := 0, CONTAR, TAMANHO, TIPO, RESULTADO,;
      MAS_CARA, POSICAO, CORINGA, DIFERENCA, LOCALIZA, ADD_MASCARA,;
      FIL_TRA, CONTADOR, ACAO_MEMO := 1, INICIO, MAIOR_MEMO
PARA PROGRAMA, LINHA_PROG
TO_TALIZA := {}; CO_LUNAS := {}; RE_SUMO := {}; QUE_BRAS := {}
TOTALIZADOR := {}; CAMPOS_MEMO := {}; TAM_MEMO := {}; TOT_QUEBRA := {}
FOR CONTAR := 1 TO LEN( relatorio:QUEBRA )
   AADD( TOT_QUEBRA, {} )
NEXT
IF relatorio:TIPO = COLUNAR
   ASORT( relatorio:CONTEUDO,,, { | X, Y | X[ _COLUNA ] < Y[ _COLUNA ] } )
ENDIF
POSICAO := 01
relatorio:LINHA := relatorio:LIN_SUPERIOR
MAS_CARA := IIF( relatorio:TIPO = COLUNAR, 5, 4 )
FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
   IF relatorio:TIPO = COLUNAR
      IF relatorio:CONTEUDO[ CONTAR ][ _COLUNA ] +;
         LEN( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] ) - 1 > LARGURA
         LARGURA := relatorio:CONTEUDO[ CONTAR ][ _COLUNA ] +;
                    LEN( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] ) - 1
      ENDIF
   ENDIF
   IF NUM_RELATORIO = 0
      MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
      TIPO := VALTYPE( &MACRO )
   ELSE
      TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
   ENDIF
   IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
      IF NUM_RELATORIO = 0
         MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
         TAMANHO := LEN( TRANS( &MACRO, relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ] ) )
      ELSE
         TAMANHO := LEN( TRANS( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ),;
                         relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ] ) )
      ENDIF
   ELSE
      IF TIPO = "N"
         TAMANHO := 10
      ELSEIF TIPO = "D"
         TAMANHO := 8
      ELSEIF TIPO = "L"
         TAMANHO := 3
      ELSEIF TIPO = "M"
         TAMANHO := relatorio:MEMO_LARGURA
      ELSE
         IF NUM_RELATORIO = 0
            MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
            TAMANHO := LEN( &MACRO )
         ELSE
            TAMANHO := LEN( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
         ENDIF
      ENDIF
   ENDIF
   IF relatorio:TIPO = COLUNAR
      IF relatorio:CONTEUDO[ CONTAR ][ _COLUNA ] + TAMANHO - 1 > LARGURA
         LARGURA := relatorio:CONTEUDO[ CONTAR ][ _COLUNA ] + TAMANHO - 1
      ENDIF
      AADD( CO_LUNAS, relatorio:CONTEUDO[ CONTAR ][ _COLUNA ] )
   ELSE
      IF TAMANHO < LEN( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] )
         TAMANHO := LEN( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] )
      ENDIF
      LARGURA += TAMANHO
      AADD( CO_LUNAS, POSICAO )
      POSICAO += relatorio:SEPARADOR + TAMANHO
   ENDIF
   IF relatorio:RESUMO != NIL .AND. TIPO = "N"
      DIFERENCA := 0
      CORINGA := NIL
      IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
         CORINGA := relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ]
         CORINGA := STRTRAN( CORINGA, "#", "9" )
         LOCALIZA := AT( "9", CORINGA )
         IF LOCALIZA != 0
            IF AT( ",", CORINGA ) != 0
               ADD_MASCARA := SUBS( CORINGA, LOCALIZA, AT( ",",;
                                    CORINGA ) - LOCALIZA )
               IF LEN( ADD_MASCARA ) = 1
                  ADD_MASCARA := "99"; DIFERENCA := 2
               ELSEIF LEN( ADD_MASCARA ) = 2 .OR.;
                      LEN( ADD_MASCARA ) = 3
                  ADD_MASCARA := "9,9"; DIFERENCA := 3
               ENDIF
               IF DIFERENCA != 0
                  CORINGA := STUFF( CORINGA, LOCALIZA, 0, ADD_MASCARA )
               ENDIF
            ELSE
               IF LOCALIZA != 0
                  CORINGA := STUFF( CORINGA, LOCALIZA, 0, "99" )
                  DIFERENCA := 2
               ENDIF
            ENDIF
         ENDIF
      ENDIF
      CO_LUNAS[ CONTAR ] -= DIFERENCA
      IF CORINGA != NIL
         relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ] := CORINGA
      ENDIF
      IF relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] != NIL
         relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] :=;
           SPACE( DIFERENCA ) + relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ]
      ENDIF
      AADD( RE_SUMO, { relatorio:CONTEUDO[ CONTAR ][ _DADOS ], 0 } )
   ENDIF
NEXT
IF relatorio:TIPO = COLUNAR_AUTOMATICO
   LARGURA += ( LEN( relatorio:CONTEUDO ) - 1 ) * relatorio:SEPARADOR
ENDIF
IF LEN( relatorio:TITULOS ) > 1
   IF NUM_RELATORIO = 0
      IF LEN( relatorio:TITULOS[ 1 ] ) > LEN( relatorio:TITULOS[ 2 ] )
         TAMANHO := LEN( relatorio:TITULOS[ 1 ] )
      ELSE
         TAMANHO := LEN( relatorio:TITULOS[ 2 ] )
      ENDIF
   ELSE
      IF LEN( EVAL( relatorio:TITULOS[ 1 ] ) ) > LEN( EVAL( relatorio:TITULOS[ 2 ] ) )
         TAMANHO := LEN( EVAL( relatorio:TITULOS[ 1 ] ) )
      ELSE
         TAMANHO := LEN( EVAL( relatorio:TITULOS[ 2 ] ) )
      ENDIF
   ENDIF
ELSEIF LEN( relatorio:TITULOS ) = 1
   IF NUM_RELATORIO = 0
      TAMANHO := LEN( relatorio:TITULOS[ 1 ] )
   ELSE
      TAMANHO := LEN( EVAL( relatorio:TITULOS[ 1 ] ) )
   ENDIF
ELSE
   TAMANHO := 18
ENDIF
IF TAMANHO + 17 > LARGURA; LARGURA := TAMANHO + 17; ENDIF
relatorio:LARGURA := LARGURA
FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
   IF NUM_RELATORIO = 0
       MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
      TIPO := VALTYPE( &MACRO )
   ELSE
      TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
   ENDIF
   IF TIPO = "M"
      AADD( CAMPOS_MEMO,;
            { relatorio:CONTEUDO[ CONTAR ][ _DADOS ], CO_LUNAS[ CONTAR ] } )
   ENDIF
NEXT
IF LEN( relatorio:TOTALIZA ) = 0
   FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
      IF NUM_RELATORIO = 0
         MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
         TIPO := VALTYPE( &MACRO )
      ELSE
         TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
      ENDIF
      IF TIPO = "N"
         CORINGA := {}
         AADD( CORINGA, relatorio:CONTEUDO[ CONTAR ][ _DADOS ] )
         AADD( CORINGA, relatorio:CONTEUDO[ CONTAR ][ _DADOS + 1 ] )
         AADD( CORINGA, CO_LUNAS[ CONTAR ] )
         IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
            AADD( CORINGA, relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ] )
         ENDIF
         AADD( TOTALIZADOR, CORINGA )
      ENDIF
   NEXT
ELSE
   TOTALIZADOR := relatorio:TOTALIZA
ENDIF
FOR CONTAR := 1 TO LEN( TOTALIZADOR )
   IF NUM_RELATORIO = 0
      MACRO := TOTALIZADOR[ CONTAR ][ 1 ]
      TIPO := VALTYPE( &MACRO )
   ELSE
      TIPO := VALTYPE( EVAL( TOTALIZADOR[ CONTAR ][ 1 ] ) )
   ENDIF
   IF TIPO != "N"
      SETCOLOR( "W" )
      CLS
      ?
      ? "Tentativa de totalizar campo nao numerico"
      ?
      ? "Rotina -> " + PROGRAMA
      ? "Linha --> " + ALLTRIM( STR( LINHA_PROG ) )
      ?
      QUIT
   ENDIF
   IF relatorio:TIPO = COLUNAR_AUTOMATICO
      POSICAO := ASCAN( relatorio:CONTEUDO, { | X | UPPER( X[ 3 ] ) ==;
                 UPPER( TOTALIZADOR[ CONTAR ][ 2 ] ) } )
      IF POSICAO = 0
         SETCOLOR( "W" )
         CLS
         ?
         ? "Tentativa de totalizar campo nao posicionado para impressao"
         ?
         ? "Rotina -> " + PROGRAMA
         ? "Linha --> " + ALLTRIM( STR( LINHA_PROG ) )
         ?
         QUIT
      ENDIF
      DIFERENCA := 0; CORINGA := NIL
      IF LEN( relatorio:CONTEUDO[ POSICAO ] ) = MAS_CARA
         CORINGA := relatorio:CONTEUDO[ POSICAO ][ MAS_CARA ]
         CORINGA := STRTRAN( CORINGA, "#", "9" )
         LOCALIZA := AT( "9", CORINGA )
         IF LOCALIZA != 0
            IF AT( ",", CORINGA ) != 0
               ADD_MASCARA := SUBS( CORINGA, LOCALIZA, AT( ",",;
                                    CORINGA ) - LOCALIZA )
               IF LEN( ADD_MASCARA ) = 1
                  ADD_MASCARA := "99"; DIFERENCA := 2
               ELSEIF LEN( ADD_MASCARA ) = 2 .OR.;
                      LEN( ADD_MASCARA ) = 3
                  ADD_MASCARA := "9,9"; DIFERENCA := 3
               ENDIF
               IF DIFERENCA != 0
                  CORINGA := STUFF( CORINGA, LOCALIZA, 0, ADD_MASCARA )
               ENDIF
            ELSE
               IF LOCALIZA != 0
                  CORINGA := STUFF( CORINGA, LOCALIZA, 0, "99" )
                  DIFERENCA := 2
               ENDIF
            ENDIF
         ENDIF
      ENDIF
      AADD( TOTALIZADOR[ CONTAR ], CO_LUNAS[ POSICAO ] - DIFERENCA )
      IF CORINGA != NIL
         AADD( TOTALIZADOR[ CONTAR ], CORINGA )
      ENDIF
   ENDIF
   AADD( TO_TALIZA, 0 )
   FOR CONTADOR := 1 TO LEN( relatorio:QUEBRA )
      AADD( TOT_QUEBRA[ CONTADOR ], 0 )
   NEXT
NEXT
IF LEN( TOTALIZADOR ) > 0
   relatorio:LIN_INFERIOR -= 3
ENDIF
FOR CONTAR := 1 TO LEN( relatorio:QUEBRA )
   IF NUM_RELATORIO = 0
      MACRO := relatorio:QUEBRA[ CONTAR ][ 1 ]
      AADD( QUE_BRAS, &MACRO )
   ELSE
      AADD( QUE_BRAS, EVAL( relatorio:QUEBRA[ CONTAR ][ 1 ] ) )
   ENDIF
NEXT
relatorio:SAIDA := MENU_PRN()
IF relatorio:SAIDA = NIL
   RESTSCREEN( LIN_MENU + 1, 00, 23, 79, TELA_PRI )
   relatorio:LIMPA()
   RETURN
ENDIF
SET DEVI TO PRINT
WHILE !EOF()
   IF INKEY() = T_ESC
      SET DEVI TO SCREEN
      SAIDA := PERG( "Continua a impress„o ?" )
      MENSAGEM( "Tecle <ESC> para pausa ou interrup‡„o" )
      SET DEVI TO PRINT
      IF SAIDA = "N"; EXIT; ENDIF
   ENDIF
   IF relatorio:FILTRO != NIL
      IF NUM_RELATORIO = 0
         MACRO := relatorio:FILTRO
         IF !( &MACRO )
            TOTALIZE( .T. )
            EXIT
         ENDIF
      ELSE
         IF !( EVAL( relatorio:FILTRO ) )
            TOTALIZE( .T. )
            EXIT
         ENDIF
      ENDIF
   ENDIF
   IF relatorio:LINHA = relatorio:LIN_SUPERIOR
      IF relatorio:BLOCO_CABECALHO != NIL
         EVAL( relatorio:BLOCO_CABECALHO )
      ELSE
         IF relatorio:SAIDA != "T"
            IF relatorio:REDUCAO != NIL
               @ 00, 01 SAY relatorio:REDUCAO
            ENDIF
            AJUSTE( relatorio:LARGURA, IIF( TIPO_FORMULARIO = "0", "80", "132" ) )
         ENDIF
         IF LEN( relatorio:TITULOS ) > 0
            IF NUM_RELATORIO = 0
               @ relatorio:LINHA, 01 SAY relatorio:TITULOS[ 1 ]
            ELSE
               @ relatorio:LINHA, 01 SAY EVAL( relatorio:TITULOS[ 1 ] )
            ENDIF
         ENDIF
         @ relatorio:LINHA, relatorio:LARGURA - 13 SAY;
           "Pagina: " + STRZERO( relatorio:PAGINA, 4 )
         relatorio:PAGINA++
         IF LEN( relatorio:TITULOS ) > 1
            IF NUM_RELATORIO = 0
               @ ++relatorio:LINHA, 01 SAY relatorio:TITULOS[ 2 ]
            ELSE
               @ ++relatorio:LINHA, 01 SAY EVAL( relatorio:TITULOS[ 2 ] )
            ENDIF
         ENDIF
         @ relatorio:LINHA, relatorio:LARGURA - 15 SAY;
           "Data: " + DTOC( DAT_HOJE )
         FOR CONTAR := 3 TO LEN( relatorio:TITULOS )
            IF NUM_RELATORIO = 0
               IF VALTYPE( relatorio:TITULOS[ CONTAR ] ) = "A"
                  MACRO := relatorio:TITULOS[ CONTAR ][ 2 ]
                  @ ++relatorio:LINHA, 01 SAY relatorio:TITULOS[ CONTAR ][ 1 ]
                  @ relatorio:LINHA, LEN( relatorio:TITULOS[ CONTAR ][ 1 ] ) +;
                    2 SAY &MACRO
               ELSE
                  @ ++relatorio:LINHA, 01 SAY relatorio:TITULOS[ CONTAR ]
               ENDIF
            ELSE
               @ ++relatorio:LINHA, 01 SAY EVAL( relatorio:TITULOS[ CONTAR ] )
            ENDIF
         NEXT
         relatorio:LINHA++
         @ ++relatorio:LINHA, 01 SAY;
           REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
         relatorio:LINHA++
         FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
            IF relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] != NIL
               @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY;
                 relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ]
            ENDIF
         NEXT
         @ ++relatorio:LINHA, 01 SAY;
           REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
         relatorio:LINHA++
         CORINGA := .F.
         IF LEN( relatorio:QUEBRA ) > 0
            FOR CONTAR := 1 TO LEN( relatorio:QUEBRA )
               IF LEN( relatorio:QUEBRA[ CONTAR ] ) > 2
                  IF VALTYPE( relatorio:QUEBRA[ CONTAR ][ 3 ] ) = "C"
                     @ ++relatorio:LINHA, 01 SAY;
                       relatorio:QUEBRA[ CONTAR ][ 3 ]
                     @ relatorio:LINHA, LEN( relatorio:QUEBRA[ CONTAR ][ 3 ] ) + 2 SAY;
                       QUE_BRAS[ CONTAR ]
                     CORINGA := .T.
                  ENDIF
               ENDIF
            NEXT
            IF CORINGA; relatorio:LINHA += 2; ENDIF
         ENDIF
      ENDIF
   ENDIF
   IF ACAO_MEMO = 1
      TAM_MEMO := {}
      IF relatorio:RESUMO != NIL
         IF NUM_RELATORIO = 0
            MACRO := relatorio:RESUMO
            FIL_TRA := &MACRO
         ELSE
            FIL_TRA := EVAL( relatorio:RESUMO )
         ENDIF
         FOR CONTAR := 1 TO LEN( RE_SUMO )
            RE_SUMO[ CONTAR ][ 2 ] := 0
         NEXT
         MACRO := relatorio:RESUMO
         WHILE FIL_TRA = IIF( NUM_RELATORIO > 0, EVAL( relatorio:RESUMO ),;
                              &MACRO ) .AND. !EOF()
            FOR CONTAR := 1 TO LEN( relatorio:PRE_CONTEUDO )
               EVAL( relatorio:PRE_CONTEUDO[ CONTAR ] )
            NEXT
            FOR CONTAR := 1 TO LEN( RE_SUMO )
               IF NUM_RELATORIO = 0
                  MACRO := RE_SUMO[ CONTAR ][ 1 ]
                  RE_SUMO[ CONTAR ][ 2 ] += &MACRO
               ELSE
                  RE_SUMO[ CONTAR ][ 2 ] += EVAL( RE_SUMO[ CONTAR ][ 1 ] )
               ENDIF
            NEXT
            FOR CONTAR := 1 TO LEN( TOTALIZADOR )
               IF NUM_RELATORIO = 0
                  MACRO := TOTALIZADOR[ CONTAR ][ _DADOS -1 ]
                  TO_TALIZA[ CONTAR ] += &MACRO
               ELSE
                  TO_TALIZA[ CONTAR ] += EVAL( TOTALIZADOR[ CONTAR ][ _DADOS -1 ] )
               ENDIF
               FOR CONTADOR := 1 TO LEN( relatorio:QUEBRA )
                  IF NUM_RELATORIO = 0
                     MACRO := TOTALIZADOR[ CONTAR ][ _DADOS -1 ]
                     TOT_QUEBRA[ CONTADOR ][ CONTAR ] += &MACRO
                  ELSE
                     TOT_QUEBRA[ CONTADOR ][ CONTAR ] +=;
                       EVAL( TOTALIZADOR[ CONTAR ][ _DADOS -1 ] )
                  ENDIF
               NEXT
            NEXT
            IF NUM_RELATORIO = 0
               MACRO := relatorio:RESUMO
               FIL_TRA := &MACRO
            ENDIF
            SKIP
         ENDDO
         SKIP -1
         POSICAO := 1
         FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
            IF NUM_RELATORIO = 0
               MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
               RESULTADO := &MACRO
               TIPO := VALTYPE( &MACRO )
            ELSE
               RESULTADO := EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] )
               TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
            ENDIF
            IF TIPO = "N"
               RESULTADO := RE_SUMO[ POSICAO ][ 2 ]
               POSICAO++
            ENDIF
            IF TIPO = "M"
               AADD( TAM_MEMO, MLCOUNT( RESULTADO, relatorio:MEMO_LARGURA ) )
               @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY;
                 MEMOLINE( RESULTADO, relatorio:MEMO_LARGURA, 1 )
            ELSE
               IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
                  @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY;
                    RESULTADO PICT relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ]
               ELSE
                  @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY RESULTADO
               ENDIF
            ENDIF
         NEXT
      ELSE
         FOR CONTAR := 1 TO LEN( relatorio:PRE_CONTEUDO )
            EVAL( relatorio:PRE_CONTEUDO[ CONTAR ] )
         NEXT
         FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
            IF NUM_RELATORIO = 0
               MACRO := relatorio:CONTEUDO[ CONTAR ][ _DADOS ]
               RESULTADO := &MACRO
               TIPO := VALTYPE( &MACRO )
            ELSE
               RESULTADO := EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] )
               TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
            ENDIF
            IF TIPO = "M"
               AADD( TAM_MEMO, MLCOUNT( RESULTADO, relatorio:MEMO_LARGURA ) )
               @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY;
                 MEMOLINE( RESULTADO, relatorio:MEMO_LARGURA, 1 )
            ELSE
               IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
                  @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY;
                    RESULTADO PICT relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ]
               ELSE
                  @ relatorio:LINHA, CO_LUNAS[ CONTAR ] SAY;
                    RESULTADO
               ENDIF
            ENDIF
         NEXT
      ENDIF
      IF LEN( CAMPOS_MEMO ) != 0
         ACAO_MEMO++; INICIO := 2
      ENDIF
   ENDIF
   IF ACAO_MEMO = 2
      MAIOR_MEMO := 0
      FOR CONTAR := 1 TO LEN( TAM_MEMO )
         IF TAM_MEMO[ CONTAR ] > MAIOR_MEMO
            MAIOR_MEMO := TAM_MEMO[ CONTAR ]
         ENDIF
      NEXT
      FOR CONTADOR := INICIO TO MAIOR_MEMO
         relatorio:LINHA++
         FOR CONTAR := 1 TO LEN( CAMPOS_MEMO )
            IF NUM_RELATORIO = 0
               MACRO := CAMPOS_MEMO[ CONTAR ][ 1 ]
               RESULTADO := &MACRO
            ELSE
               RESULTADO := EVAL( CAMPOS_MEMO[ CONTAR ][ 1 ] )
            ENDIF
            @ relatorio:LINHA, CAMPOS_MEMO[ CONTAR ][ 2 ] SAY;
              MEMOLINE( RESULTADO, relatorio:MEMO_LARGURA, CONTADOR )
         NEXT
         IF relatorio:LINHA > relatorio:LIN_INFERIOR
            EXIT
         ENDIF
      NEXT
      IF CONTADOR < MAIOR_MEMO
         INICIO := CONTADOR + 1
      ELSE
         ACAO_MEMO := 3
      ENDIF
   ENDIF
   IF relatorio:RESUMO = NIL
      FOR CONTAR := 1 TO LEN( TOTALIZADOR )
         IF NUM_RELATORIO = 0
            MACRO := TOTALIZADOR[ CONTAR ][ _DADOS - 1 ]
            TO_TALIZA[ CONTAR ] += &MACRO
         ELSE
            TO_TALIZA[ CONTAR ] += EVAL( TOTALIZADOR[ CONTAR ][ _DADOS - 1 ] )
         ENDIF
         FOR CONTADOR := 1 TO LEN( relatorio:QUEBRA )
            IF NUM_RELATORIO = 0
               MACRO := TOTALIZADOR[ CONTAR ][ _DADOS - 1 ]
               TOT_QUEBRA[ CONTADOR ][ CONTAR ] += &MACRO
            ELSE
               TOT_QUEBRA[ CONTADOR ][ CONTAR ] +=;
                 EVAL( TOTALIZADOR[ CONTAR ][ _DADOS - 1 ] )
            ENDIF
         NEXT
      NEXT
   ENDIF
   IF LEN( CAMPOS_MEMO ) = 0
      relatorio:LINHA++
      SKIP
   ELSE
      IF ACAO_MEMO = 3
         relatorio:LINHA++
         SKIP
         ACAO_MEMO := 1
      ENDIF
   ENDIF
   FOR CONTAR := LEN( relatorio:QUEBRA ) TO 1 STEP -1
      IF NUM_RELATORIO = 0
         MACRO := relatorio:QUEBRA[ CONTAR ][ 1 ]
      ENDIF
      IF QUE_BRAS[ CONTAR ] != IIF( NUM_RELATORIO = 0, &MACRO,;
         EVAL( relatorio:QUEBRA[ CONTAR ][ 1 ] ) )
         CORINGA := .F.
         RESULTADO := ""
         IF LEN( relatorio:QUEBRA[ CONTAR ] ) = 4
            CORINGA := .T.
            RESULTADO := relatorio:QUEBRA[ CONTAR ][ 3 ]
         ELSEIF LEN( relatorio:QUEBRA[ CONTAR ] ) = 3
            IF NUM_RELATORIO = 0
               MACRO := relatorio:QUEBRA[ CONTAR ][ 1 ]
               TIPO := VALTYPE( &MACRO )
            ELSE
               TIPO := VALTYPE( EVAL( relatorio:QUEBRA[ CONTAR ][ 1 ] ) )
            ENDIF
            IF TIPO = "L"
               CORINGA := .T.
            ELSE
               RESULTADO := relatorio:QUEBRA[ CONTAR ][ 3 ]
            ENDIF
         ENDIF
         IF CORINGA = .T.
            @ relatorio:LINHA, 01 SAY REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
            @ ++relatorio:LINHA, 01 SAY relatorio:TIT_SUBTOTAL_QUEBRA
            FOR CONTADOR := 1 TO LEN( TOTALIZADOR )
               IF LEN( TOTALIZADOR[ CONTADOR ] ) = 4
                  @ relatorio:LINHA, TOTALIZADOR[ CONTADOR ][ _COLUNA - 1 ] SAY;
                    TOT_QUEBRA[ CONTAR ][ CONTADOR ];
                    PICT TOTALIZADOR[ CONTADOR ][ 4 ]
               ELSE
                  @ relatorio:LINHA, TOTALIZADOR[ CONTADOR ][ _COLUNA - 1 ] SAY;
                    TOT_QUEBRA[ CONTAR ][ CONTADOR ]
               ENDIF
               TOT_QUEBRA[ CONTAR ][ CONTADOR ] := 0
            NEXT
         ENDIF
         IF relatorio:QUEBRA[ CONTAR ][ 2 ] = SALTA_PAGINA
            relatorio:LINHA := relatorio:LIN_INFERIOR + 1
         ELSE
            relatorio:LINHA += relatorio:QUEBRA[ CONTAR ][ 2 ]
            IF LEN( TRIM( RESULTADO ) ) > 0 .AND. !EOF()
               @ ++relatorio:LINHA, 01 SAY RESULTADO
               IF NUM_RELATORIO = 0
                  MACRO := relatorio:QUEBRA[ CONTAR ][ 1 ]
                  @ relatorio:LINHA, LEN( RESULTADO ) + 2 SAY &MACRO
               ELSE
                  @ relatorio:LINHA, LEN( RESULTADO ) + 2;
                    SAY EVAL( relatorio:QUEBRA[ CONTAR ][ 1 ] )
               ENDIF
               relatorio:LINHA += 2
            ENDIF
         ENDIF
         FOR CONTADOR := CONTAR TO LEN( relatorio:QUEBRA )
            IF NUM_RELATORIO = 0
               MACRO := relatorio:QUEBRA[ CONTADOR ][ 1 ]
               QUE_BRAS[ CONTADOR ] = &MACRO
            ELSE
               QUE_BRAS[ CONTADOR ] = EVAL( relatorio:QUEBRA[ CONTADOR ][ 1 ] )
            ENDIF
            AFILL( TOT_QUEBRA[ CONTADOR ], 0 )
         NEXT
      ENDIF
   NEXT
   IF relatorio:LINHA > relatorio:LIN_INFERIOR .OR. EOF()
      TOTALIZE()
      relatorio:LINHA := relatorio:LIN_SUPERIOR
   ENDIF
ENDDO
EJECT
SET DEVI TO SCREEN
IF relatorio:SAIDA = "A"
   SET PRINTER TO
ELSEIF relatorio:SAIDA = "T" .AND. SAIDA = "S"
   SET PRINTER TO
   IMP_TELA( relatorio:LARGURA + 1 )
ENDIF
relatorio:LIMPA()
RETURN NIL

FUNCTION TOTALIZE( TOT_OU_SUB )
IF LEN( relatorio:TOTALIZA ) = 0; RETURN NIL; ENDIF
IF TOT_OU_SUB = NIL; TOT_OU_SUB := EOF(); ENDIF
IF !TOT_OU_SUB .AND. relatorio:SUB_TOTALIZACAO = NAO
   RETURN NIL
ENDIF
IF TOT_OU_SUB .AND. relatorio:LINHA < relatorio:LIN_INFERIOR + 1
   relatorio:LINHA := relatorio:LIN_INFERIOR + 1
ENDIF
@ relatorio:LINHA, 01 SAY;
  REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
relatorio:LINHA++
IF TOT_OU_SUB
   @ relatorio:LINHA, 01 SAY relatorio:TITULO_TOTAL
ELSE
   @ relatorio:LINHA, 01 SAY relatorio:TITULO_SUB_TOTAL
ENDIF
FOR CONTAR := 1 TO LEN( TOTALIZADOR )
   IF LEN( TOTALIZADOR[ CONTAR ] ) = 4
      @ relatorio:LINHA, TOTALIZADOR[ CONTAR ][ _COLUNA - 1 ] SAY;
        TO_TALIZA[ CONTAR ] PICT TOTALIZADOR[ CONTAR ][ 4 ]
   ELSE
      @ relatorio:LINHA, TOTALIZADOR[ CONTAR ][ _COLUNA - 1 ] SAY;
        TO_TALIZA[ CONTAR ]
   ENDIF
NEXT
@ ++relatorio:LINHA, 01 SAY;
  REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
RETURN NIL

FUNCTION IMP_FICHA
LOCAL SAIDA := "S", LARGURA := 0, CONTAR, TAMANHO, TIPO, RESULTADO,;
      MAS_CARA, DIFERENCA, LOCALIZA, ADD_MASCARA, FIL_TRA, CONTADOR,;
      TAM_CAB, TAM_SALTO := 0, TAM_MEMO
PARA PROGRAMA, LINHA_PROG
CO_LUNAS := {}; LI_NHAS := {}
relatorio:LINHA := relatorio:LIN_SUPERIOR
MAS_CARA := 6
FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
   TAM_CAB := LEN( TRIM( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] ) )
   IF TAM_CAB = 0; TAM_CAB--; ENDIF
   TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
   IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
      TAMANHO := LEN( TRANS( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ),;
                 relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ] ) )
   ELSE
      IF TIPO = "N"
         TAMANHO := 10
      ELSEIF TIPO = "D"
         TAMANHO := 8
      ELSEIF TIPO = "L"
         TAMANHO := 3
      ELSEIF TIPO = "M"
         TAMANHO := relatorio:MEMO_LARGURA
      ELSE
         TAMANHO := LEN( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
      ENDIF
   ENDIF
   IF relatorio:CONTEUDO[ CONTAR ][ _COLUNA + 1 ] + TAMANHO + TAM_CAB > LARGURA
      LARGURA := relatorio:CONTEUDO[ CONTAR ][ _COLUNA + 1 ] + TAMANHO + TAM_CAB
   ENDIF
   AADD( CO_LUNAS, relatorio:CONTEUDO[ CONTAR ][ _COLUNA + 1 ] )
   AADD( LI_NHAS, relatorio:CONTEUDO[ CONTAR ][ _COLUNA ] )
NEXT
FOR CONTAR := 1 TO LEN( LI_NHAS )
   IF LI_NHAS[ CONTAR ] > TAM_SALTO
      TAM_SALTO := LI_NHAS[ CONTAR ]
   ENDIF
NEXT
IF LEN( relatorio:TITULOS ) > 1
   IF LEN( EVAL( relatorio:TITULOS[ 1 ] ) ) > LEN( EVAL( relatorio:TITULOS[ 2 ] ) )
      TAMANHO := LEN( EVAL( relatorio:TITULOS[ 1 ] ) )
   ELSE
      TAMANHO := LEN( EVAL( relatorio:TITULOS[ 2 ] ) )
   ENDIF
ELSEIF LEN( relatorio:TITULOS ) = 1
   TAMANHO := LEN( EVAL( relatorio:TITULOS[ 1 ] ) )
ELSE
   TAMANHO := 18
ENDIF
IF TAMANHO + 17 > LARGURA; LARGURA := TAMANHO + 17; ENDIF
relatorio:LARGURA := LARGURA
relatorio:SAIDA := MENU_PRN()
IF relatorio:SAIDA = NIL
   RESTSCREEN( LIN_MENU + 1, 00, 23, 79, TELA_PRI )
   relatorio:LIMPA()
   RETURN
ENDIF
SET DEVI TO PRINT
WHILE !EOF()
   IF INKEY() = T_ESC
      SET DEVI TO SCREEN
      SAIDA := PERG( "Continua a impress„o ?" )
      MENSAGEM( "Tecle <ESC> para pausa ou interrup‡„o" )
      SET DEVI TO PRINT
      IF SAIDA = "N"; EXIT; ENDIF
   ENDIF
   IF relatorio:FILTRO != NIL
      IF !( EVAL( relatorio:FILTRO ) )
         EXIT
      ENDIF
   ENDIF
   IF relatorio:LINHA = relatorio:LIN_SUPERIOR
      IF relatorio:BLOCO_CABECALHO != NIL
         EVAL( relatorio:BLOCO_CABECALHO )
      ELSE
         CAB_FICHA()
      ENDIF
   ENDIF
   FOR CONTAR := 1 TO LEN( relatorio:PRE_CONTEUDO )
      EVAL( relatorio:PRE_CONTEUDO[ CONTAR ] )
   NEXT
   FOR CONTAR := 1 TO LEN( relatorio:CONTEUDO )
      RESULTADO := EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] )
      TIPO := VALTYPE( EVAL( relatorio:CONTEUDO[ CONTAR ][ _DADOS ] ) )
      TAM_CAB := LEN( TRIM( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] ) )
      IF TAM_CAB > 0
         TAM_CAB++
         @ relatorio:LINHA + LI_NHAS[ CONTAR ], CO_LUNAS[ CONTAR ] SAY;
           TRIM( relatorio:CONTEUDO[ CONTAR ][ _CABECALHO ] )
      ENDIF
      IF TIPO = "M"
         TAM_MEMO := MLCOUNT( RESULTADO, relatorio:MEMO_LARGURA )
         FOR CONTADOR := 1 TO TAM_MEMO
            @ relatorio:LINHA + LI_NHAS[ CONTAR ], CO_LUNAS[ CONTAR ] + TAM_CAB;
              SAY MEMOLINE( RESULTADO, relatorio:MEMO_LARGURA, CONTADOR )
            relatorio:LINHA++
            IF relatorio:LINHA + LI_NHAS[ CONTAR ] > relatorio:LIN_INFERIOR
               relatorio:LINHA := relatorio:LIN_SUPERIOR
               IF relatorio:BLOCO_CABECALHO != NIL
                  EVAL( relatorio:BLOCO_CABECALHO )
               ELSE
                  CAB_FICHA()
               ENDIF
            ENDIF
         NEXT
         IF TAM_MEMO > 0; relatorio:LINHA--; ENDIF
      ELSE
         IF LEN( relatorio:CONTEUDO[ CONTAR ] ) = MAS_CARA
            @ relatorio:LINHA + LI_NHAS[ CONTAR ], CO_LUNAS[ CONTAR ] +;
              TAM_CAB SAY RESULTADO PICT relatorio:CONTEUDO[ CONTAR ][ MAS_CARA ]
         ELSE
            @ relatorio:LINHA + LI_NHAS[ CONTAR ], CO_LUNAS[ CONTAR ] +;
              TAM_CAB SAY RESULTADO
         ENDIF
      ENDIF
   NEXT
   relatorio:LINHA += TAM_SALTO
   @ ++relatorio:LINHA, 01 SAY;
     REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
   SKIP
   IF relatorio:LINHA + TAM_SALTO > relatorio:LIN_INFERIOR
      relatorio:LINHA := relatorio:LIN_SUPERIOR
   ENDIF
ENDDO
EJECT
SET DEVI TO SCREEN
IF relatorio:SAIDA = "A"
   SET PRINTER TO
ELSEIF relatorio:SAIDA = "T" .AND. SAIDA = "S"
   SET PRINTER TO
   IMP_TELA( relatorio:LARGURA + 1 )
ENDIF
relatorio:LIMPA()
RETURN NIL

FUNCTION CAB_FICHA
IF relatorio:SAIDA != "T"
   IF relatorio:REDUCAO != NIL
      @ 00, 01 SAY relatorio:REDUCAO
   ENDIF
   AJUSTE( relatorio:LARGURA, IIF( TIPO_FORMULARIO = "0", "80", "132" ) )
ENDIF
IF LEN( relatorio:TITULOS ) > 0
   @ relatorio:LINHA, 01 SAY EVAL( relatorio:TITULOS[ 1 ] )
ENDIF
@ relatorio:LINHA, relatorio:LARGURA - 13 SAY;
  "Pagina: " + STRZERO( relatorio:PAGINA, 4 )
relatorio:PAGINA++
IF LEN( relatorio:TITULOS ) > 1
   @ ++relatorio:LINHA, 01 SAY EVAL( relatorio:TITULOS[ 2 ] )
ENDIF
@ relatorio:LINHA, relatorio:LARGURA - 15 SAY;
  "Data: " + DTOC( DAT_HOJE )
FOR CONTAR := 3 TO LEN( relatorio:TITULOS )
   @ ++relatorio:LINHA, 01 SAY EVAL( relatorio:TITULOS[ CONTAR ] )
NEXT
relatorio:LINHA++
@ ++relatorio:LINHA, 01 SAY;
  REPL( relatorio:SEP_CABECALHO, relatorio:LARGURA )
RETURN NIL


FUNCTION MENSAGEM( TEXTO, PAUSA ) // função de exibição de msgs.
STATIC ULT_MENSAGEM := ""
LOCAL ULT_CURSOR := SETCURSOR()
IF TEXTO = NIL; TEXTO := ""; ENDIF
CURSOR( DESLIGA )
@ MAXROW(), 11 SAY PADC( TEXTO, 58 ) COLOR CONTECOR[ 2 ]
IF PAUSA = NIL
   ULT_MENSAGEM := TEXTO
ELSE
   INKEY( PAUSA )
   @ MAXROW(), 11 SAY PADC( ULT_MENSAGEM, 58 ) COLOR CONTECOR[ 2 ]
ENDIF
SETCURSOR( ULT_CURSOR )
RETURN NIL
 

FUNCTION PERGUNTA( TEX_TO, RES_POSTA )  // função de pergunta pop-up
IF RES_POSTA = NIL; RES_POSTA="S"; ENDIF
PER_COR := SETCOLOR()
CURSOR( DESLIGA )
SAVE SCREEN TO PER_TELA
M->SIM_NAO := IIF( RES_POSTA ="N", 2, 1 )
M->LAR_G := LEN( TEX_TO )
IF M->LAR_G < 37
   M->LAR_G := 51
ELSE
   M->LAR_G += 14
ENDIF
COL_SUP := INT( ( 80 - M->LAR_G ) / 2 )
COL_INF := COL_SUP + LAR_G - 1
JANELA( 08, COL_SUP, 16, COL_INF )
COR( "JANELA DE DIALOGO" )
@ 11, ( 80 - LEN( TEX_TO ) ) / 2 SAY TEX_TO
botao:ADD( 13, 25, "Sim     " )
botao:ADD( 13, 42, "N„o     " )
SIM_NAO := botao:RODA()
RESTORE SCREEN FROM PER_TELA
SETCOLOR( PER_COR )
RETURN IIF( M->SIM_NAO = 1, "S", "N" )


FUNCTION BOTAO( LINHA_SUPERIOR, COLUNA_ESQUERDA, NOME_BOTAO ) // botões para operar os menus
LOCAL TIPO_OPERACAO, LARGURA_BOTAO, CONTAR, TECLA, PONTEIRO := 1
IF PCOUNT() = 0
   TIPO_OPERACAO := EDITA_BOTOES
ELSEIF PCOUNT() = 1
   TIPO_OPERACAO := EDITA_BOTOES
   PONTEIRO := LINHA_SUPERIOR
ELSEIF PCOUNT() = 2
   TIPO_OPERACAO := MOSTRA_BOTOES
ELSEIF PCOUNT() = 3
   TIPO_OPERACAO := MOVIMENTA_BOTAO
ENDIF
IF TIPO_OPERACAO = MOVIMENTA_BOTAO
   LARGURA_BOTAO := LEN( NOME_BOTAO ) + 2
   COR( "JANELA DE DIALOGO" )
   @ LINHA_SUPERIOR, COLUNA_ESQUERDA SAY " "
   @ LINHA_SUPERIOR + 1, COLUNA_ESQUERDA - 1 SAY SPACE( LARGURA_BOTAO )
   @ LINHA_SUPERIOR, COLUNA_ESQUERDA + LARGURA_BOTAO - 1 SAY " "
   COR( "BOTAO EM DESTAQUE" )
   @ LINHA_SUPERIOR, COLUNA_ESQUERDA - 1 SAY " " + NOME_BOTAO + " "
   INKEY( .2 )
   COR( "BOTOES" )
   @ LINHA_SUPERIOR, COLUNA_ESQUERDA SAY " " + NOME_BOTAO + " "
   SETCOLOR( "N/" + ALLTRIM( SUBS( CONTECOR[ 4 ], 4 ) ) )
   @ LINHA_SUPERIOR, COLUNA_ESQUERDA - 1 SAY "Ü"
   @ LINHA_SUPERIOR + 1, COLUNA_ESQUERDA - 1 SAY REPL( "ß", LARGURA_BOTAO ) + " "
   INKEY( .2 )
ENDIF
IF TIPO_OPERACAO = EDITA_BOTOES .OR. TIPO_OPERACAO = MOSTRA_BOTOES
   FOR CONTAR := 1 TO LEN( ObjBotao )
      LARGURA_BOTAO := LEN( ObjBotao[ CONTAR ][ 3 ] ) + 2
      COR( "BOTOES" )
      @ ObjBotao[ CONTAR ][ 1 ], ObjBotao[ CONTAR ][ 2 ]  SAY " " + ;
        ObjBotao[ CONTAR ][ 3 ] + " "
      SETCOLOR( "N/" + ALLTRIM( SUBS( CONTECOR[ 4 ], 4 ) ) )
      @ ObjBotao[ CONTAR ][ 1 ], ObjBotao[ CONTAR ][ 2 ] - 1 SAY "Ü"
      @ ObjBotao[ CONTAR ][ 1 ] + 1, ObjBotao[ CONTAR ][ 2 ] - 1 SAY;
        REPL( "ß", LARGURA_BOTAO ) + " "
   NEXT
ENDIF
IF TIPO_OPERACAO = EDITA_BOTOES
   TECLA := 0
   WHILE .T.
      LARGURA_BOTAO := LEN( ObjBotao[ PONTEIRO ][ 3 ] ) + 2
      COR( "BOTAO EM DESTAQUE" )
      @ ObjBotao[ PONTEIRO ][ 1 ], ObjBotao[ PONTEIRO ][ 2 ] SAY;
        " " + ObjBotao[ PONTEIRO ][ 3 ] + " "
      SETCOLOR( "N/" + ALLTRIM( SUBS( CONTECOR[ 4 ], 4 ) ) )
      @ ObjBotao[ PONTEIRO ][ 1 ], ObjBotao[ PONTEIRO ][ 2 ] - 1 SAY "Ü"
      @ ObjBotao[ PONTEIRO ][ 1 ] + 1, ObjBotao[ PONTEIRO ][ 2 ] - 1 SAY;
        REPL( "ß", LARGURA_BOTAO ) + " "
      IF TECLA = T_ENTER
         INKEY( .2 )
         botao:LIMPA()
         RETURN PONTEIRO
      ENDIF
      TECLA := INKEY( 0 )
      IF TECLA = T_ESC
         botao:LIMPA()
         RETURN 0
      ENDIF
      IF TECLA = T_F1
         HELP( "CALENDARIO", 1, "" )
      ENDIF
      COR( "BOTOES" )
      @ ObjBotao[ PONTEIRO ][ 1 ], ObjBotao[ PONTEIRO ][ 2 ] + 1 SAY;
        ObjBotao[ PONTEIRO ][ 3 ]
      FOR CONTAR = 1 TO LEN( ObjBotao )
         IF SUBS( ObjBotao[ CONTAR ][ 3 ], 1, 1 ) = UPPER( CHR( TECLA ) )
            PONTEIRO := CONTAR
            TECLA := T_ENTER
            EXIT
         ENDIF
      NEXT
      IF TECLA = T_ENTER
         LARGURA_BOTAO := LEN( ObjBotao[ PONTEIRO ][ 3 ] ) + 2
         COR( "JANELA DE DIALOGO" )
         @ ObjBotao[ PONTEIRO ][ 1 ], ObjBotao[ PONTEIRO ][ 2 ] SAY " "
         @ ObjBotao[ PONTEIRO ][ 1 ] + 1, ObjBotao[ PONTEIRO ][ 2 ] - 1 SAY;
           SPACE( LARGURA_BOTAO )
         @ ObjBotao[ PONTEIRO ][ 1 ], ObjBotao[ PONTEIRO ][ 2 ] +;
           LARGURA_BOTAO - 1 SAY " "
         COR( "BOTAO EM DESTAQUE" )
         @ ObjBotao[ PONTEIRO ][ 1 ], ObjBotao[ PONTEIRO ][ 2 ] - 1 SAY ;
           " " + ObjBotao[ PONTEIRO ][ 3 ] + " "
         INKEY( .2 )
         LOOP
      ENDIF
      IF TECLA = T_ESQUERDA .OR. TECLA = T_CIMA
         PONTEIRO--
      ELSEIF TECLA = T_DIREITA .OR. TECLA = T_BAIXO
         PONTEIRO++
      ENDIF
      PONTEIRO := IIF( PONTEIRO < 1, LEN( ObjBotao ),;
                  IIF( PONTEIRO > LEN( ObjBotao ), 1, PONTEIRO ) )
   ENDDO
ENDIF
botao:LIMPA()
RETURN NIL



FUNCTION PERG( TEX_TO, RES_POSTA ) // mensagem em forma de pergunta
LOCAL LI, SIM_NAO, CUR_PERG := SETCURSOR()
COR( "MENU" )
CURSOR( DESLIGA )
IF PCOUNT() = 1; RES_POSTA := "S"; ENDIF
SIM_NAO := IIF( RES_POSTA = "N", 2, 1 )
@ 24, 11 SAY SPACE( 58 )
LI := ( 80 - ( LEN( TEX_TO ) + 11 ) ) / 2
@ 24, LI SAY TEX_TO
LI += LEN( TEX_TO ) + 2
WHILE .T.
   @ 24, LI     PROMPT "Sim"
   @ 24, LI + 6 PROMPT "N„o"
   @ 24, LI + 4 SAY "-"
   MENU TO SIM_NAO
   IF SIM_NAO != 0
      EXIT
   ENDIF
ENDDO
SETCURSOR( CUR_PERG )
RETURN IIF( SIM_NAO = 1, "S", "N" )

FUNCTION JANELA( PJAN1, PJAN2, PJAN3, PJAN4, PJAN5 ) // desenha janelas
IF PCOUNT() != 5
   PJAN5 := ""
ENDIF
SOMBRA( PJAN1, PJAN2, PJAN3, PJAN4 )
SETCOLOR( CONTECOR[ 4 ] )
@ PJAN1, PJAN2 CLEAR TO PJAN3, PJAN4
SETCOLOR( CONTECOR[ 5 ] )
@ PJAN1, PJAN2, PJAN3, PJAN4 BOX " "
@ PJAN1, PJAN2 SAY "þ"
IF LEN( TRIM( PJAN5 ) ) > 0
   @ PJAN1, PJAN2 + ( ( ( PJAN4 + 1 - PJAN2 ) - LEN( PJAN5 ) ) / 2 ) SAY PJAN5
ENDIF


FUNCTION SOMBRA( LIN_SUP, COL_SUP, LIN_INF, COL_INF ) // gera sombras 
IF PCOUNT() = 2 .OR. PCOUNT() = 3
   C_SOM := COL_SUP; L_SOM := LIN_SUP
   LIN_SUP := VAL( SUBS( C_SOM, 1, 2 ) )
   COL_SUP := VAL( SUBS( C_SOM, 3, 2 ) )
   LIN_INF := VAL( SUBS( C_SOM, 5, 2 ) )
   COL_INF := VAL( SUBS( C_SOM, 7, 2 ) )
   COL_SOM := SUBS( C_SOM, 9 )
   LIN_SOM := L_SOM
ENDIF
IF COL_SUP < 2 .OR. LIN_INF > 22
   C_SOM := ""; L_SOM := ""
   RETURN .F.
ENDIF
IF PCOUNT() = 3
   RESTSCREEN( LIN_SUP + 1, COL_SUP - 2, LIN_INF + 1, COL_SUP - 1, COL_SOM )
   RESTSCREEN( LIN_INF + 1, COL_SUP - 2, LIN_INF + 2, COL_INF - 2, LIN_SOM )
   RETURN .F.
ENDIF
IF PCOUNT() != 2
   COL_SOM := SAVESCREEN( LIN_SUP + 1, COL_SUP - 2, LIN_INF + 1, COL_SUP - 1 )
   LIN_SOM := SAVESCREEN( LIN_INF + 1, COL_SUP - 2, LIN_INF + 2, COL_INF - 2 )
ENDIF
IF SUBS( COL_SOM, 2, 1 ) != CHR( 8 )
   C_SOM := STR( LIN_SUP, 2 ) + STR( COL_SUP, 2 ) + STR( LIN_INF, 2 ) +;
            STR( COL_INF, 2 ) + COL_SOM
   L_SOM := LIN_SOM
ENDIF
FOR I = 2 TO LEN( COL_SOM ) STEP 2
   COL_SOM := STUFF( COL_SOM, I, 1, CHR( 8 ) )
NEXT
FOR I = 2 TO LEN( LIN_SOM ) / 2 STEP 2
   LIN_SOM := STUFF( LIN_SOM, I, 1, CHR( 8 ) )
NEXT
RESTSCREEN( LIN_SUP + 1, COL_SUP - 2, LIN_INF + 1, COL_SUP - 1, COL_SOM )
RESTSCREEN( LIN_INF + 1, COL_SUP - 2, LIN_INF + 2, COL_INF - 2, LIN_SOM )
RETURN .T.

Adm. Maickon Sato
Consultoria e Projetos
-------------------------------------------------------
Avatar do usuário
acelconsultoria
Usuário Nível 3
Usuário Nível 3
Mensagens: 231
Registrado em: 10 Jan 2006 17:05
Localização: Itápolis-SP

Parte IV

Mensagem por acelconsultoria »

Aqui, algumas declarações que vc deve fazer no PRG principal:

Código: Selecionar todos


// Inicializando as classes:

ObjBotao := botao:LIMPA()
ObjRelatorio := relatorio:LIMPA()

// Configurando as cores do sistema, já que o MIRO é cheio dessas "frescuras"... rssss...

NOMECOR := { "FUNDO DA TELA",;
             "MENU",;
             "DESTAQUE DO MENU",;
             "JANELA DE DIALOGO",;
             "BOX DA JANELA DE DIALOGO",;
             "BOTOES",;
             "BOTAO EM DESTAQUE",;
             "GETS",;
             "GET EM DESTAQUE",;
             "TELA DE APRESENTACAO",;
             "CARACTERES AVULSOS",;
             "CERCADURAS",;
             "TITULO" }
CONTECOR := {}

// Definindo o arquivo de impressão padrão e carregando configurações

CON_ARQ := "EMILIA.IMP"
TIPO_FORMULARIO := "0"
MOV_LINHA := 5; MOV_COLUNA := 9
DECLARE FOR_MULARIO[ 99 ]
AFILL( FOR_MULARIO, "0" )
VAR := MEMOREAD( "MIRO.CFG" )
FOR CONTAR = 1 TO 12
   AADD( CONTECOR, SUBS( VAR, ( CONTAR * 5 ) - 4, 5 ) )
NEXT
MOV_LINHA := VAL( SUBS( VAR, 61, 2 ) )
MOV_COLUNA := VAL( SUBS( VAR, 63, 2 ) )
AADD( CONTECOR, SUBS( VAR, 72, 5 ) )
IF LEN( TRIM( SUBS( VAR, 77, 12 ) ) ) > 0
   CON_ARQ := TRIM( SUBS( VAR, 77, 12 ) )
ENDIF
FOR CONTAR := 1 TO 99
   FOR_MULARIO[ CONTAR ] := SUBS( VAR, 88 + CONTAR, 1 )
NEXT
REDUCAO_ETQ := 1
IMPRESSORA := {}
IMP_ARQ := {}
NOME_IMP := ""
CONTADOR := ADIR( "*.IMP" )
IF CONTADOR != 0
   DECLARE ARQS_IMP[ CONTADOR ]
   ADIR( "*.IMP", ARQS_IMP )
   FOR CONTADOR := 1 TO LEN( ARQS_IMP )
      VAR := TRIM( MEMOLINE( MEMOREAD( ARQS_IMP[ CONTADOR ] ), 80, 1 ) )
      AADD( IMP_ARQ, { VAR, ARQS_IMP[ CONTADOR ] } )
   NEXT
ENDIF
LER_IMP( CON_ARQ )

Aqui, o conteúdo dos arquivos auxiliares:

Arquivo: MIRO.CFG

Código: Selecionar todos

09/0700/0315/0100/0715/0111/0314/0303/0015/0414/0000/0700/07 5 9FF   1A14/01EMILIA.IMP  000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Conteúdo dos arquivos .IMP, de impressão:

Código: Selecionar todos

Arquivo EPSON.IMP:

Epson FX-1170
080,132 [027,080,018]
097,160 [027,077,018]
137,226 [027,080,015]
160,264 [027,077,015]


Arquivo EMILIA.IMP

Emilia PC
080,132 [030,048]
088,145 [030,049]
100,165 [030,050]
114,188 [030,051]
133,219 [030,052]
160,264 [030,053]


Arquivo DeskJet.IMP

DeskJet HP-600S
080,132 [027,080,108]
097,160 [027,038,107,050,083]
137,226 [027,040,115,052,083]
160,264 [027,040,115,052,083]

OBS: Esses arquivos devem ser gerados e estarem na pasta principal do sistema.
Adm. Maickon Sato
Consultoria e Projetos
-------------------------------------------------------
Avatar do usuário
acelconsultoria
Usuário Nível 3
Usuário Nível 3
Mensagens: 231
Registrado em: 10 Jan 2006 17:05
Localização: Itápolis-SP

Parte V

Mensagem por acelconsultoria »

Enfim, depois de milhares de linhas de código, a simplicidade de gerar os relatórios:


Exemplo de como imprimir um simples relatório resumido de clientes:

Código: Selecionar todos

#include "MIRO.CH"

MENSAGEM( "Aguarde abertura de arquivos" )

USE CLIENTES INDEX CLI001

MENSAGEM( "Tecle <ESC> para retornar" )

SET ORDER TO 1
DBGOTOP()

NUM_RELATORIO := 1
relatorio:TIPO := COLUNAR
relatorio:ADDTITULO( "JAGUAR SEGUROS LTDA." )
relatorio:ADDTITULO( "Relatorio de Clientes" )
relatorio:LIN_SUPERIOR := 1
relatorio:LIN_INFERIOR := 61
relatorio:COL_INICIAL := 0
relatorio:ADD( "Codigo", CLIENTES->CODIGO, 1, "@E 9999999" )
relatorio:ADD( "Nome/Razão Social", CLIENTES->RAZAO, 10, "@!" )
relatorio:ADD( "Telefone", CLIENTES->FONE, 46, "@!" )
relatorio:RODA()
DBCLOSEALL()
 
RETURN .T.

Aqui, vc apenas indica o banco de dados, e através do objeto "relatorio", vc define o que quer imprimir:

Sintaxe:
relatorio:ADD([cabecalho],[campo],[coluna],[máscara])

Sei que dá um trabalhão pra enfiar aquele monte de funções dentro do programa, mas confesso que me quebrou um galhão.

Vou mandar mais alguns exemplos:

Como imprimir um relatório no formato de ficha, com todos os dados dos clientes:

Código: Selecionar todos

#include "MIRO.CH"

MENSAGEM( "Aguarde abertura de arquivos" )

USE CLIENTES INDEX CLI001

MENSAGEM( "Tecle <ESC> para retornar" )

SET ORDER TO 1
DBGOTOP()

NUM_RELATORIO := 1
relatorio:TIPO := FICHA //** Aqui eu defino que o relatório será em formato de ficha
relatorio:ADDTITULO( "JAGUAR SEGUROS LTDA." )
relatorio:ADDTITULO( "Relatorio Geral de Clientes" )
relatorio:LIN_SUPERIOR := 1
relatorio:LIN_INFERIOR := 61
relatorio:COL_INICIAL := 0
relatorio:ADD( "Codigo:", CLIENTES->CODIGO, 1, 1, "@E 99999" )
relatorio:ADD( "Pessoa Fisica ou Juridica:", CLIENTES->FIJU, 1, 17 )
relatorio:ADD( "Nome/Razao Social:", CLIENTES->RAZAO, 2, 1 )
relatorio:ADD( "Nome Fantasia/Apelido:", CLIENTES->FANTASIA, 3, 1 )
relatorio:ADD( "CPF/CNPJ:", CLIENTES->CNPJ, 4, 1 )
relatorio:ADD( "RG/Inscr.:", CLIENTES->INSC, 4, 51 )
relatorio:ADD( "Fone:", CLIENTES->FONE, 5, 1 )
relatorio:ADD( "Fax:", CLIENTES->FAX, 5, 57 )
relatorio:ADD( "Celular:", CLIENTES->CELULAR, 6, 1 )
relatorio:ADD( "Contato:", CLIENTES->CONTATO, 6, 41 )
relatorio:ADD( "Endereco:", CLIENTES->ENDERECO, 7, 1 )
relatorio:ADD( "Bairro:", CLIENTES->BAIRRO, 8, 1 )
relatorio:ADD( "CEP:", CLIENTES->CEP, 8, 45 )
relatorio:ADD( "Cidade:", CLIENTES->CIDADE, 9, 1 )
relatorio:ADD( "Estado:", CLIENTES->ESTADO, 9, 42 )
relatorio:ADD( "Trab:", CLIENTES->TLOCAL, 10, 3 )
relatorio:ADD( "e-Mail:", CLIENTES->EMAIL, 11, 1 )
relatorio:ADD( "Obs:", CLIENTES->OBS, 12, 4 )
relatorio:ADD( "Data:", CLIENTES->DATACAD, 13, 3 )
relatorio:ADD( "Bloqueado (S/N)?", CLIENTES->CHAVE, 13, 33 )
relatorio:RODA()
DBCLOSEALL()
RETURN .T.

A única diferença de sintaxe do formato COLUNAR para o FORMATO ficha, é que vc tem que definir tbem, além da coluna, a linha em que o CAMPO deverá ser impresso.

Sintaxe:
relatorio:ADD([cabecalho],[campo],[linha],[coluna],[máscara])
Adm. Maickon Sato
Consultoria e Projetos
-------------------------------------------------------
Avatar do usuário
acelconsultoria
Usuário Nível 3
Usuário Nível 3
Mensagens: 231
Registrado em: 10 Jan 2006 17:05
Localização: Itápolis-SP

Parte VI

Mensagem por acelconsultoria »

Exemplo de como imprimir um relatório de recebimento diário, com totalização:

Código: Selecionar todos

#include "MIRO.CH" 

MENSAGEM( "Aguarde abertura de arquivos" ) 
USE RECEBER INDEX REC001 
MENSAGEM( "Tecle <ESC> para retornar" ) 
SET ORDER TO 1
SET FILTER TO DATAREC = DATE() // Aqui tá o filtro
DBGOTOP() 
IF DATAREC != DATE() // Aqui o acerto do filtro
   SKIP
ENDIF

NUM_RELATORIO := 1 
relatorio:TIPO := COLUNAR 
relatorio:ADDTITULO( "JAGUAR SEGUROS LTDA." ) 
relatorio:ADDTITULO( "Relatorio de Recebimento do dia" ) 
relatorio:LIN_SUPERIOR := 1 
relatorio:LIN_INFERIOR := 61 
relatorio:COL_INICIAL := 0 
relatorio:ADD( "Cliente", RECEBER->CLIENTE, 1, "@!" ) 
relatorio:ADD( "Pedido", RECEBER->DOCUMENTO, 36, "@!" ) 
relatorio:ADD( "Valor", RECEBER->VALOR, 60, "@E 999,999,999.99" ) 
relatorio:ADDTOTAL( RECEBER->VALOR, 60, "@E 999,999,999.99")
relatorio:RODA() 
SELE RECEBER
SET FILTER TO
DBCLOSEALL() 
RETURN .T. 
Pronto !!! Apenas coloquei para o objeto relatorio apurar o total no final da impressão, através do comando ADDTOTAL.


Vou postar um exemplo agora, onde faço a impressão de despesas, separadas por grupo de contas (Plano de Contas), onde faço a quebra por cada grupo saltando duas linhas por quebra, apurando o sub-total e o total geral no final. Também, vou adicionar uma função, para retornar no relatório a forma como foi feita o pagamento:

Código: Selecionar todos


#include "MIRO.CH" 

MENSAGEM( "Aguarde abertura de arquivos" ) 
USE DESPESAS INDEX DESP001 
MENSAGEM( "Tecle <ESC> para retornar" ) 
SET ORDER TO 1
SET FILTER TO DATA = DATE() // Aqui tá o filtro
DBGOTOP() 
IF DATA != DATE() // Aqui o acerto do filtro
   SKIP
ENDIF

NUM_RELATORIO := 1 
relatorio:TIPO := COLUNAR 
relatorio:ADDTITULO( "JAGUAR SEGUROS LTDA." ) 
relatorio:ADDTITULO( "Relatorio de Despesas do Dia" ) 
relatorio:LIN_SUPERIOR := 1 
relatorio:LIN_INFERIOR := 61 
relatorio:COL_INICIAL := 0 
relatorio:ADD( "Descricao", DESPESAS->DESCRICAO, 1, "@!" ) 
relatorio:ADD( "Forma pgto.", FORM_PAG(), 36, "@!" ) 
relatorio:ADD( "Valor", DESPESAS->VALOR, 60, "@E 999,999,999.99" ) 
relatorio:ADDQUEBRA(  DESPESAS->GRU_CONTA, SALTA_2_LINHAS, "Grupo de Conta:", TOTALIZA_QUEBRA )
relatorio:ADDTOTAL( DESPESAS->VALOR, 60, "@E 999,999,999.99")
relatorio:RODA() 
SELE DESPESAS
SET FILTER TO
DBCLOSEALL() 
RETURN .T. 

FUNCTION FORM_PAG()
IF DESPESAS->FORMA = 1
   RETURN "DINHEIRO"
ELSEIF DESPESAS->FORMA = 2
   RETURN "CHEQUE"
ELSE
   RETURN "BOLETO"
ENDIF


OBS.: É importante lembrar que, nesse relatório, a chave do índice é o grupo de contas (GRU_CONTA).


Para todo relatório, o sistema perguntará sempre ao usuário se deseja imprimir em impressora (LPT1), na tela ou para arquivo.

Bom, sei que ficou meio extenso isso aqui... mas vale lembrar que isso foi apenas extraído do MIRO. Postei aqui para constar no fórum, para os curiosos e para os estudiosos.

Abraços a todos !!![/code]
Adm. Maickon Sato
Consultoria e Projetos
-------------------------------------------------------
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Mensagem por Pablo César »

Maickon, ficaram faltando algumas funções ainda no seu post. Quando intentei compilar deu falta de:

LER_IMP
IMP_ETQ
COR
BEEP
CURSOR
USEREDE
HELP

Digo isto por se alguém deseja compilá-lo e testar. Maikon você viu esta mensagem minha https://pctoledo.org/forum/viewto ... 6572#36572 que fala de incorporar o recurso de GERADOR DE RELATORIOS do Miro como mostra na tela abaixo:

http://fotos.terra.com.br/foto.cgi/J7c: ... f/MIRO.jpg

Acho que seria uma boa, não ?
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4664
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Mensagem por rochinha »

Amiguinho

Por muito tempo também usei este recurso e adaptei uma função que me auxiliava na impressão em impressoras for Windows.

Consistia basicamente em trocar o seguinte bloco de codigo pela chamada a minha função seletora DEVICEPRINTER():

Código: Selecionar todos

...
ENDDO 
EJECT 
SET DEVI TO SCREEN 
IF relatorio:SAIDA = "A" 
   SET PRINTER TO 
ELSEIF relatorio:SAIDA = "T" .AND. SAIDA = "S" 
   SET PRINTER TO 
   IMP_TELA( relatorio:LARGURA + 1 ) 
ENDIF 
relatorio:LIMPA() 
RETURN NIL 
...
Conforme o trecho de codigo abaixo era possivel também imprimir usando meu PrinterSpool, PageScript, html, xml e xls

Código: Selecionar todos

FUNCTION DEVICEPRINTER( TAM_ANHO )
SET DEVI TO SCREEN
IF     M->TIPO_PRN = "I"
       SET PRINTER TO
ELSEIF M->TIPO_PRN = "R"
       SET PRINTER TO
       SET PRINTER OFF
       SAVE SCREEN TO L_P_T
       //SET DEVICE TO PRINT
       IF FILE(SUBSTR(ARQ_PRN,1,8)+".$TX")
          MENSAGEM("Enviando arquivo pela porta "+ALLTRIM(M->PARALELA)+"...",5)
          //__Run( "TYPE "+SUBSTR(ARQ_PRN,1,8)+".$TX > "+M->PARALELA )
          __Run( "COPY "+SUBSTR(ARQ_PRN,1,8)+".$TX "+M->PARALELA )
       ELSE
          MENSAGEM("Nao foi criado nenhum arquivo...",5)
       ENDIF
       REST SCREEN FROM L_P_T
ELSEIF M->TIPO_PRN = "A"
       SET PRINTER TO
ELSEIF M->TIPO_PRN = "T" .AND. M->SAI_DA="S"
       SET PRINTER TO
       IMP_TELA( TAM_ANHO )
ELSEIF M->TIPO_PRN = "S"
       SET PRINTER TO
       SET PRINTER TO NULL
       SET PRINTER OFF
       MENSAGEM('Gerando, aguarde...',1)
       __ClearFile( ARQ_PRN+'.PRN', A_10CPI  )
       __ClearFile( ARQ_PRN+'.PRN', A_12CPI  )
       __ClearFile( ARQ_PRN+'.PRN', ItalOn   )
       __ClearFile( ARQ_PRN+'.PRN', ItalOff  )
       __ClearFile( ARQ_PRN+'.PRN', CondOn   )
       __ClearFile( ARQ_PRN+'.PRN', CondOff  )
       __ClearFile( ARQ_PRN+'.PRN', NegrOn   )
       __ClearFile( ARQ_PRN+'.PRN', NegrOff  )
       __ClearFile( ARQ_PRN+'.PRN', BoletoOn )
       __ClearFile( ARQ_PRN+'.PRN', BoletoOff)
       __CopyFile( '.\' + ALLTRIM(ARQ_PRN)+'.PRN', 'C:\CLEVER\FWSERVER\' + ALLTRIM(ARQ_PRN)+'.PRN' )
       fRename( 'C:\CLEVER\FWSERVER\' + ALLTRIM(ARQ_PRN)+'.PRN' , ;
                'C:\CLEVER\FWSERVER\' + ALLTRIM(ARQ_PRN)+'.SPL' )
ELSEIF M->TIPO_PRN = "G"
       SET PRINTER TO
       ULT_DBF  := SELECT()
       ARQ_PRN1 := SUBSTR(ARQ_PRN,1,AT('.',ARQ_PRN)-1)
       ARQ_PRN2 := ARQ_PRN1 + ".$AQ"
       DBCREATE( ARQ_PRN2, { { "LI_NHA", "C", 200, 0 } } )
       USE &ARQ_PRN2 EXCLUSIVE NEW // VIA "DBFNTX"
       APPEND FROM &ARQ_PRN SDF
       GO TOP
       MENSAGEM('Gerando... aguarde',5)
       PSClever( "SPOOL" )
       nRow := 0
       GO TOP
       DO WHILE .NOT. EOF()
          PSTextOut( nRow, 0, LI_NHA )
          nRow := nRow + 1
          IF nRow > 65
             PSNewPage()
             nRow := 0
          ENDIF
          SKIP
       ENDDO
       USE
       SELECT( ULT_DBF )
       PSClever()
ELSEIF M->TIPO_PRN = "H"
       SET PRINTER TO
       ARQ_PRN1 := SUBSTR(ARQ_PRN,1,AT('.',ARQ_PRN)-1)
       ARQ_PRN2 := ARQ_PRN + ".$AQ"
       DBCREATE( ARQ_PRN2, { { "LI_NHA", "C", 200, 0 } } )
       USE &ARQ_PRN2 EXCLUSIVE NEW // VIA "DBFNTX"
       APPEND FROM &ARQ_PRN SDF
       //
       // -> Definicao do BROWSE
       OB_COLUN := {}
       OBJETO := TBROWSEDB( 0, 0, 0, 0 )
       //
       // -> Separador do cabecalho
       OBJETO:HEADSEP := TB_SEP_CAB
       //
       // -> Separador de colunas
       OBJETO:COLSEP := TB_SEP_LIN
       //
       // -> Cor do browse     (1)                   (2)                   (3)
       OBJETO:COLORSPEC := CONTECOR[ 2 ] + "," + CONTECOR[ 3 ] + "," + TB_COR_DEL
       OB_COLUNA := "LI_NHA"
       //
       // -> Adicionando as colunas ao browse
       OBJETO:ADDCOLUMN( TBCOLUMNNEW( NewCapFirst( OB_COLUNA ), FIELDBLOCK( OB_COLUNA ) ) )
       MENSAGEM('Gerando... aguarde')
       DO WHILE ( !OBJETO:STABILIZE() )
          TB2Html( OBJETO, ARQ_PRN1+".htm", 'RELATORIO' )
          //TB2Xml( OBJETO, m->cNome, m->cHeader )
          //TB2Xls( OBJETO, m->cNome, m->cHeader )
       ENDDO
ENDIF
RETURN .t.
Na época em que usei este código USB era somente um tipo de conexão existente nos Apples. Portanto para imprimir em qualquer impressora sem frescura bastará modificar o pequeno trecho logo abaixo como segue:

Código: Selecionar todos

...
...
ENDDO 
EJECT 
SET DEVI TO SCREEN 
IF relatorio:SAIDA = "A" 
   SET PRINTER TO 
   //
   __Run( "COPY "+SUBSTR(ARQ_PRN,1,8)+".$TX "+M->PARALELA )
   //
ELSEIF relatorio:SAIDA = "T" .AND. SAIDA = "S" 
   SET PRINTER TO 
   IMP_TELA( relatorio:LARGURA + 1 ) 
ENDIF 
relatorio:LIMPA() 
RETURN NIL 
...
Onde:
ARQ_PRN - É o nome do arquivo temporário criado pelo gerador do Miro.
M->PARALELA - É a variavel que deverá conter o nome da impressora, podendo ser LPT! ou \\Servidor\Impressora, etc.

Pode ser inserido qualquer utilitário de auxilio a impressão conhecido, como wordpad, prwin, wapi, etc.
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.

@braços : ? )

A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Mensagem por Pablo César »

Ahhh Rochinha, você sempre nos engrandece com as suas contribuições. Eu também ja faço algo así (chamo de sistema híbrido), a minha atual tentativa é usar o Crytal Reports e estou fazendo testes. Porém a versão que conseguí (9.22) não tem opção de gerar arquivo .EXE o que viabilizaria o uso com meus aplicativos feito em Clipper. No entanto, assim como você apontou, também terei as duas modalidades de impressão (a GRÁFICA e a modo TEXTO), não descartando nunca o modo TEXTO, ora seja para visualizar em tela os relatórios ou para impressão em impressoras matriciais (padrão EPSON ou até aquela JATO-TINTA/LASER que aceitam os comandos de impressão ESC), pois elas são mais rápidas tanto na compisição do relatório como na impressão em matriciais.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Responder