em minha xeretagem usando a MRBoleto, consegui criar um executável que roda em linha de comando recebendo dados via arquivos .INI.
Bastará à aqueles que não conseguirem compilá-lo(por enquanto) preencher o arquivo .INI e executar o DemoUm.exe
Para não chocar os sources com o original usei outros nomes.
Compilei usando a versão Borland de binários do Harbour build harbour-3.2-17431.
O .BAT deve apontar somente para a pasta onde estiver o Harbour:
DemoUm.bat
@ECHO OFF
SET hbversao=harbour-3.2-17431
SET HBDIR=
SET HBDIR=%caminho%\%hbversao%
SET pathOLD=%PATH%
SET path=%PATH%;%HBDIR%\BIN
SET BCDIR=d:\develop\bcc55
HARBOUR -build
DEL DemoUm.Exe
HBMK2 DemoUm.hbp
DemoUm.exe
SET PATH=%pathOLD%
.HBP Modificado para compilar somente o exemplo:
DemoUm.hbp
-w3
-es2
-gtwvg
-gui
hbhpdf.hbc
hbzebra.hbc
-oDemoUm.exe
DemoUm.prg
MRboleto.prg
Codigo fonte resumido:
DemoUm.prg
#include "inkey.ch"
#include "hbgtinfo.ch"
Procedure Main
Local oBoleto, oIni
Local cFilePdf := 'DemoUm.PDF'
F_Set_Desktop()
oBoleto := MR_Boleto():New( cFilePdf )
oIni = TIniFile():New( "DemoUm.ini" )
oBoleto:Banco________ := oIni:ReadString( "MRBOLETO", "Banco________", "001" )
oBoleto:Banco_Agencia := oIni:ReadString( "MRBOLETO", "Banco_Agencia", "3482" )
oBoleto:Banco_Ag_Dv__ := oIni:ReadString( "MRBOLETO", "Banco_Ag_Dv__", "07" )
oBoleto:Banco_Ag_Un_A := oIni:ReadString( "MRBOLETO", "Banco_Ag_Un_A", "" )
oBoleto:Conta________ := oIni:ReadString( "MRBOLETO", "Conta________", "90090" )
oBoleto:Conta_DV_____ := oIni:ReadString( "MRBOLETO", "Conta_DV_____", "7" )
oBoleto:Conta_OP_____ := oIni:ReadString( "MRBOLETO", "Conta_OP_____", "" )
oBoleto:Carteira_____ := oIni:ReadString( "MRBOLETO", "Carteira_____", "18" )
oBoleto:Carteira_Tipo := oIni:ReadString( "MRBOLETO", "Carteira_Tipo", "" )
oBoleto:NossoNumero__ := oIni:ReadString( "MRBOLETO", "NossoNumero__", "62160101" )
oBoleto:Doc_Origem___ := oIni:ReadString( "MRBOLETO", "Doc_Origem___", "NFe" )
oBoleto:Prefixo______ := oIni:ReadString( "MRBOLETO", "Prefixo______", "153454" )
oBoleto:Prefixo_DV___ := oIni:ReadString( "MRBOLETO", "Prefixo_DV___", "9" )
oBoleto:Doc_Numero___ := oIni:ReadString( "MRBOLETO", "Doc_Numero___", "00001234" )
oBoleto:Doc_Aceite___ := oIni:ReadString( "MRBOLETO", "Doc_Aceite___", "N" )
oBoleto:Doc_Especie__ := oIni:ReadString( "MRBOLETO", "Doc_Especie__", "R$" )
oBoleto:Doc_Data_____ := oIni:ReadDate( "MRBOLETO", "Doc_Data_____", date() )
oBoleto:Vencimento___ := oIni:ReadDate( "MRBOLETO", "Vencimento___", date()+29 )
oBoleto:Valor________ := oIni:ReadNumber( "MRBOLETO", "Valor________", ( 13.37 * 1 ) )
oBoleto:Multa_Auto___ := oIni:ReadNumber( "MRBOLETO", "Multa_Auto___", 2 )
oBoleto:Juros_Mes____ := oIni:ReadNumber( "MRBOLETO", "Juros_Mes____", 2 )
oBoleto:Numero_Vias__ := oIni:ReadNumber( "MRBOLETO", "Numero_Vias__", 2 )
oBoleto:Local_Pagamen := oIni:ReadString( "MRBOLETO", "Local_Pagamen", "Pague em qualquer banco até o limite da data de vencimento" )
oBoleto:Instrucoes___ := StringToArray( oIni:ReadString( "MRBOLETO", "Instrucoes___", "Desconto de 5% se pago até o dia "+Transf( Date()+10, "@E 999" )+"|Não receber após 30 dias da data de vencimento" ), "|" )
oBoleto:Demonstrativo := StringToArray( oIni:ReadString( "MRBOLETO", "Demonstrativo", "Vetor: pode a exemplo ser utilizado para se demonstrar o rateio de despesas para condominios||Utiliza Fonte com espaçamento de tamanho fixo ( Courier ), o que permite geração de demostrativos financeiros flexiveis.||O limite é sua criatividade :)||Exiba detalhes importantes para o usuario||Valores em cobrança||Contratos||Informações úteis||Etc..." ), "|" )
oBoleto:Cedente______ := StringToArray( oIni:ReadString( "MRBOLETO", "Cedente______", "Cedente: CNPJ|Cedente: Nome|Cedente: Endereço ( Opcional )" ), "|" )
oBoleto:Sacado_______ := StringToArray( oIni:ReadString( "MRBOLETO", "Sacado_______", "Sacado: CNPJ|Sacado: Nome|Sacado: Endereço Completo" ), "|" )
oBoleto:Avalista_____ := StringToArray( oIni:ReadString( "MRBOLETO", "Avalista_____", "Avalista: CNPJ|Avalista: Nome|Avalista: Endereço ( Opcional )" ), "|" )
oBoleto:AddPage()
oBoleto:Finish()
IF FILE( cFilePdf )
hb_Run("Explorer.exe " + cFilePdf )
ELSE
ALERT( 'ERRO NA GERACAO DO ARQUIVO...;;' + cFilePdf )
ENDIF
Return
//*----------------------------------------------------------------------------*
// F_Set_Desktop()
//*----------------------------------------------------------------------------*
PROCEDURE F_Set_Desktop()
REQUEST HB_LANG_PT
REQUEST HB_CODEPAGE_PT850
REQUEST HB_GT_WVG_DEFAULT
REQUEST HB_GT_WVT
REQUEST HB_GT_WIN
*---------------------------------------------------------------------------*
* ANO COM 04 DIGITOS
*---------------------------------------------------------------------------*
SET CENTURY ON
*---------------------------------------------------------------------------*
* DATAS: -50 DATA ATUAL + 50
*---------------------------------------------------------------------------*
SET EPOCH TO YEAR( DATE() ) - 50
SETMODE( 33, 112 )
SetColor( 'N/W' )
CLS
hb_langSelect( hb_UserLang(), "PT850" ) // .OR. HB_LANGSELECT( 'pt-BR', "PT850" )
hb_cdpSelect( "PT850" )
Set ( _SET_SCOREBOARD, .F. )
Set ( _SET_EVENTMASK, INKEY_ALL - INKEY_MOVE + HB_INKEY_GTEVENT )
*---------------------------------------------------------------------------*
// CONFIGURAÇÕES REGIONAIS / VIDEO
*---------------------------------------------------------------------------*
hb_gtInfo( HB_GTI_CLIPBOARDDATA )
hb_gtInfo( HB_GTI_SELECTCOPY, .T. )
hb_gtInfo( HB_GTI_MOUSESTATUS, 1 )
hb_gtInfo( HB_GTI_MAXIMIZED, .F. )
hb_gtInfo( HB_GTI_CLOSABLE, .T. )
hb_gtInfo( HB_GTI_ISGRAPHIC, .T. )
hb_gtInfo( HB_GTI_STDERRCON, .T. )
RETURN
Function Random( nMaximo )
static nRandom
local nTemporal
nMaximo = if( nMaximo == NIL, 65535, nMaximo )
if nRandom == NIL
nRandom = seconds()
endif
nTemporal = ( nRandom * seconds() ) % ( nMaximo + 1 )
nTemporal = if( nTemporal < 1, 1, nTemporal )
nRandom = nTemporal + seconds()
RETURN int( nTemporal )
function StringToArray( cString, cSeparator )
LOCAL nPos
LOCAL aString := {}
cSeparator := iif(cSeparator=nil,";",cSeparator)
cString := ALLTRIM( cString ) + cSeparator
DO WHILE .T.
nPos := AT( cSeparator, cString )
IF nPos = 0
EXIT
ENDIF
AADD( aString, SUBSTR( cString, 1, nPos-1 ) )
cString := SUBSTR( cString, nPos+1 )
ENDDO
RETURN ( aString )
function fun()
return .t.
#include "inifiles.prg"
Exemplo do .INI que sua aplicação deverá gerar e passar para o DemoUm.exe:
DemoUm.ini
[MRBOLETO]
Banco________=001
Banco_Agencia=3482
Banco_Ag_Dv__=07
Banco_Ag_Un_A=
Conta________=90090
Conta_DV_____=7
Conta_OP_____=
Carteira_____=18
Carteira_Tipo=
NossoNumero__=62160101
Doc_Origem___=NFe
Prefixo______=153454
Prefixo_DV___=9
Doc_Numero___=00001234
Doc_Aceite___=N
Doc_Especie__=R$
Doc_Data_____=20121127
Vencimento___=20121226
Valor________=13.37
Multa_Auto___=2
Juros_Mes____=2
Numero_Vias__=2
Local_Pagamen=Pague em qualquer banco até o limite da data de vencimento
Instrucoes___=Desconto de 5% se pago até o dia 07/12/2012|Não receber após 30 dias da data de vencimento
Demonstrativo=Vetor: pode a exemplo ser utilizado para se demonstrar o rateio de despesas para condominios||Utiliza Fonte com espaçamento de tamanho fixo ( Courier ), o que permite geração de demostrativos financeiros flexiveis.||O limite é sua criatividade :)||Exiba detalhes importantes para o usuario||Valores em cobrança||Contratos||Informações úteis||Etc...
Cedente______=Cedente: CNPJ|Cedente: Nome|Cedente: Endereço ( Opcional )
Sacado_______=Sacado: CNPJ|Sacado: Nome|Sacado: Endereço Completo
Avalista_____=Avalista: CNPJ|Avalista: Nome|Avalista: Endereço ( Opcional )
Vejam nas ultimas linhas que existe um caracter separador de parágrafos, "|" que será traduzido pela função StringToArray() para um elemento de um vetor.
Arquivo necessário para dar a característica de leitura de arquivo de parâmetros:
inifiles.prg
//
// $Id: inifiles.prg,v 1.1 2007/08/02 00:51:33 masturm Exp $
//
#define CRLF (Chr(13) + Chr(10))
function TIniFile()
static oClass
if oClass == nil
oClass := HBClass():New( 'TINIFILE' ) // starts a new class definition
oClass:AddData( 'FileName' ) // define this class objects datas
oClass:AddData( 'Contents' )
oClass:AddMethod( 'New', @New() ) // define this class objects methods
oClass:AddMethod( 'ReadString', @ReadString() )
oClass:AddMethod( 'WriteString', @WriteString() )
oClass:AddMethod( 'ReadNumber', @ReadNumber() )
oClass:AddMethod( 'WriteNumber', @WriteNumber() )
oClass:AddMethod( 'ReadDate', @ReadDate() )
oClass:AddMethod( 'WriteDate', @WriteDate() )
oClass:AddMethod( 'ReadBool', @ReadBool() )
oClass:AddMethod( 'WriteBool', @WriteBool() )
oClass:AddMethod( 'ReadSection', @ReadSection() )
oClass:AddMethod( 'ReadSections', @ReadSections() )
oClass:AddMethod( 'DeleteKey', @DeleteKey() )
oClass:AddMethod( 'EraseSection', @EraseSection() )
oClass:AddMethod( 'UpdateFile', @UpdateFile() )
oClass:Create() // builds this class
endif
return oClass:Instance() // builds an object of this class
static function New(cFileName)
local Self := QSelf()
local Done, hFile, cFile, cLine, cIdent, nPos
local CurrArray
if empty(cFileName)
// raise an error?
outerr('No filename passed to TIniFile():New()')
return nil
else
::FileName := cFilename
::Contents := {}
CurrArray := ::Contents
if File(cFileName)
hFile := fopen(cFilename, 0)
else
hFile := fcreate(cFilename)
endif
cLine := ''
Done := .f.
while !Done
cFile := space(256)
Done := (fread(hFile, @cFile, 256) <= 0)
cFile := strtran(cFile, chr(10), '') // so we can just search for CHR(13)
// prepend last read
cFile := cLine + cFile
while !empty(cFile)
if (nPos := at(chr(13), cFile)) > 0
cLine := left(cFile, nPos - 1)
cFile := substr(cFile, nPos + 1)
if !empty(cLine)
if Left(cLine, 1) == '[' // new section
if (nPos := At(']', cLine)) > 1
cLine := substr(cLine, 2, nPos - 2);
else
cLine := substr(cLine, 2)
endif
AAdd(::Contents, { cLine, { /* this will be CurrArray */ } } )
CurrArray := ::Contents[Len(::Contents)][2]
elseif Left(cLine, 1) == ';' // preserve comments
AAdd( CurrArray, { NIL, cLine } )
else
if (nPos := At('=', cLine)) > 0
cIdent := Left(cLine, nPos - 1)
cLine := SubStr(cLine, nPos + 1)
AAdd( CurrArray, { cIdent, cLine } )
else
AAdd( CurrArray, { cLine, '' } )
endif
endif
cLine := '' // to stop prepend later on
endif
else
cLine := cFile
cFile := ''
endif
end
end
fclose(hFile)
endif
return Self
static function ReadString(cSection, cIdent, cDefault)
local Self := QSelf()
local cResult := cDefault
local i, j, cFind
if Empty(cSection)
cFind := lower(cIdent)
j := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cFind .and. ValType(x[2]) == 'C'} )
if j > 0
cResult := ::Contents[j][2]
endif
else
cFind := lower(cSection)
i := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cFind} )
if i > 0
cFind := lower(cIdent)
j := AScan( ::Contents[i][2], {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cFind} )
if j > 0
cResult := ::Contents[i][2][j][2]
endif
endif
endif
return cResult
static procedure WriteString(cSection, cIdent, cString)
local Self := QSelf()
local i, j, cFind
if Empty(cIdent)
outerr('Must specify an identifier')
elseif Empty(cSection)
cFind := lower(cIdent)
j := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cFind .and. ValType(x[2]) == 'C'} )
if j > 0
::Contents[j][2] := cString
else
AAdd(::Contents, nil)
AIns(::Contents, 1)
::Contents[1] := {cIdent, cString}
endif
else
cFind := lower(cSection)
if (i := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cFind .and. ValType(x[2]) == 'A'})) > 0
cFind := lower(cIdent)
j := AScan( ::Contents[i][2], {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cFind} )
if j > 0
::Contents[i][2][j][2] := cString
else
AAdd( ::Contents[i][2], {cIdent, cString} )
endif
else
AAdd( ::Contents, {cSection, {{cIdent, cString}}} )
endif
endif
return
static function ReadNumber(cSection, cIdent, nDefault)
local Self := QSelf()
return Val( ::ReadString(cSection, cIdent, str(nDefault)) )
static procedure WriteNumber(cSection, cIdent, nNumber)
local Self := QSelf()
::WriteString( cSection, cIdent, alltrim(str(nNumber)) )
return
static function ReadDate(cSection, cIdent, dDefault)
local Self := QSelf()
return SToD( ::ReadString(cSection, cIdent, DToS(dDefault)) )
static procedure WriteDate(cSection, cIdent, dDate)
local Self := QSelf()
::WriteString( cSection, cIdent, DToS(dDate) )
return
static function ReadBool(cSection, cIdent, lDefault)
local Self := QSelf()
local cDefault := Iif( lDefault, '.t.', '.f.' )
return ::ReadString(cSection, cIdent, cDefault) == '.t.'
static procedure WriteBool(cSection, cIdent, lBool)
local Self := QSelf()
::WriteString( cSection, cIdent, Iif(lBool, '.t.', '.f.') )
return
static procedure DeleteKey(cSection, cIdent)
local Self := QSelf()
local i, j
cSection := lower(cSection)
i := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cSection} )
if i > 0
cIdent := lower(cIdent)
j := AScan( ::Contents[i][2], {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cIdent} )
ADel( ::Contents[i][2], j )
ASize( ::Contents[i][2], Len(::Contents[i][2]) - 1 )
endif
return
static procedure EraseSection(cSection)
local Self := QSelf()
local i
if Empty(cSection)
while (i := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. ValType(x[2]) == 'C'})) > 0
ADel( ::Contents, i )
ASize( ::Contents, len(::Contents) - 1 )
end
else
cSection := lower(cSection)
if (i := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. lower(x[1]) == cSection .and. ValType(x[2]) == 'A'})) > 0
ADel( ::Contents, i )
ASize( ::Contents, Len(::Contents) - 1 )
endif
endif
return
static function ReadSection(cSection)
local Self := QSelf()
local i, j, aSection := {}
if Empty(cSection)
for i := 1 to len(::Contents)
if valtype(::Contents[i][1]) == 'C' .and. valtype(::Contents[i][2]) == 'C'
aadd(aSection, ::Contents[i][1])
endif
next
else
cSection := lower(cSection)
if (i := AScan( ::Contents, {|x| valtype(x[1]) == 'C' .and. x[1] == cSection .and. ValType(x[2]) == 'A'})) > 0
for j := 1 to Len(::Contents[i][2])
if ::Contents[i][2][j][1] <> NIL
AAdd(aSection, ::Contents[i][2][j][1])
endif
next
endif
endif
return aSection
static function ReadSections()
local Self := QSelf()
local i, aSections := {}
for i := 1 to Len(::Contents)
if ValType(::Contents[i][2]) == 'A'
AAdd(aSections, ::Contents[i][1])
endif
next
return aSections
static procedure UpdateFile()
local Self := QSelf()
local i, j, hFile
hFile := fcreate(::Filename)
for i := 1 to Len(::Contents)
if ::Contents[i][1] == NIL
fwrite(hFile, ::Contents[i][2] + Chr(13) + Chr(10))
elseif ValType(::Contents[i][2]) == 'A'
fwrite(hFile, '[' + ::Contents[i][1] + ']' + Chr(13) + Chr(10))
for j := 1 to Len(::Contents[i][2])
if ::Contents[i][2][j][1] == NIL
fwrite(hFile, ::Contents[i][2][j][2] + Chr(13) + Chr(10))
else
fwrite(hFile, ::Contents[i][2][j][1] + '=' + ::Contents[i][2][j][2] + Chr(13) + Chr(10))
endif
next
fwrite(hFile, Chr(13) + Chr(10))
elseif ValType(::Contents[i][2]) == 'C'
fwrite(hFile, ::Contents[i][1] + '=' + ::Contents[i][2] + Chr(13) + Chr(10))
endif
next
fclose(hFile)
return
.CH necessário ao Harbour pois não estava no conjunto:
harupdf.ch
Dentro do download abaixo.
.CH necessário ao Harbour pois não estava no conjunto:
hbzebra.ch
Dentro do download abaixo.
Resumindo, o aplicativo não fica muito pequeno, mas já é uma mão na roda para quem ainda não trocou o Harbour somente pela característica de um projeto.
Ás vezes ficamos sem aproveitar muitos projetos devida a grande dificuldade de adaptá-los às várias versões de uso.
Faça o download
Extras:
hbZebra.lib
HaruPDF.rar