Este gerador de relatorios é muito pratico e com certeza muito mais facil de integrar a qualquer sistema em qualquer plataforma.
O gerador foi preparado para abrir um arquivo especifico com informações sobre o relatorio a ser impresso e imprimi-lo.
Com criatividade, o aplicativo TEST.EXE e TEST2.EXE abrem o mesmo de forma mais interativa dando margem a geração de mais relatorios.
Basta analisar o conteudo de TEST.PRG para ter noção de como integra-lo ao seu sistema.
Não me lembro de onde baixei esta perola, e não encontro indicação de seu autor, mas o cara merece um beijo na testa.
#include "fivewin.ch"
REQUEST DBFCDX
STATIC pDirectorio
STATIC pExtension
STATIC pNuevo
STATIC pRespaldo
STATIC pHistory
STATIC pOpenLast
STATIC pAutoSave
STATIC nAutoSave
STATIC pTips
STATIC pLenguage
STATIC pTabs
function main(cFileName)
pDirectorio = TraeIni("PRINCIPAL", "Directorio", ".\")
pExtension = TraeIni("PRINCIPAL", "Extension" , "frx")
pNuevo = TraeIni("PRINCIPAL", "Nuevo" , "N" )
pRespaldo = TraeIni("PRINCIPAL", "Respaldo" , "bak")
pHistory = TraeIni("PRINCIPAL", "History" , 2)
pOpenLast = TraeIni("PRINCIPAL", "OpenLast" , "S")
pAutosave = TraeIni("PRINCIPAL", "Autosave" , 120)
pTips = TraeIni("PRINCIPAL", "Tips" , "S")
pTabs = TraeIni("PRINCIPAL", "Tabs" , 4)
pLenguage = TraeIni("PRINCIPAL", "Linguagem" , "Portugues")
rddSetDefault( "DBFCDX" )
use purc1
index on purc tag purc to purc1
use
use purc2
index on purc tag purc to purc2
use
use supplier
index on supp tag supp to supplier
use
IF pOpenLast = "S" .AND. ;
EMPTY(cFileName) .AND. !EMPTY( TraeIni("PRINCIPAL","LastFile","") )
cFileName = TraeIni("PRINCIPAL","LastFile","")
ENDIF
DEFINE WINDOW oWnd FROM 1, 5 TO 20, 75 MENU BuildMenu() TITLE 'Report Test' COLOR CLR_BLACK,CLR_GRAY
ACTIVATE WINDOW oWnd MAXIMIZED
return nil
FUNCTION BuildMenu()
local oMenu
MENU oMenu
MENUITEM "Arquivos"
MENU
MENUITEM "Novo" + Chr( 9 ) + "Ctrl+N" ACTION PrgNew()
MENUITEM "Abrir" + Chr( 9 ) + "Ctrl+A" ACTION PrgOpen()
MENUITEM "Salvar" + Chr( 9 ) + "Ctrl+G" ACTION PrgSave() // WHEN oEdit != nil
MENUITEM "Salvar como..." ACTION PrgSaveAs() // WHEN oEdit != nil
SEPARATOR
MENUITEM 'Configuraçao' ACTION fRep('Set')
SEPARATOR
MENUITEM "Imprimir" ACTION fRep('Print') // WHEN oEdit != nil
SEPARATOR
MENUITEM "Sair" ACTION oWnd:End()
//MRU oMruFiles INI "hedit.ini" SECTION "MRU-Files" ;
// MESSAGE tMAbrirMru ACTION PrgOpen( cMruItem )
ENDMENU
ENDMENU
return oMenu
FUNCTION PrgNew()
LOCAL cFileName := pDirectorio + cGetNewFileName( pNuevo , pExtension )
fRep( 'New', cFileName )
return .t.
FUNCTION cGetNewFileName( cName, cExt )
LOCAL cTemp := cName + "1" + "." + cExt
LOCAL nId := 1
do while File( cTemp )
cTemp = cName + StrZero( ++nId, If( nId < 10, 1, 2 ) ) + ;
"." + cExt
enddo
return cTemp
FUNCTION PrgOpen()
LOCAL cFileName := cGetFile( "Format Report XBase (*.frx) |*.frx|", "Selecione o arquivo",,".\",, .T. )
fRep( 'Edit', cFileName )
return .t.
FUNCTION PrgSave()
return .t.
FUNCTION PrgSaveAs()
return .t.
FUNCTION fRep( cMode, cFile )
default cFile := 'po.frx'
USE report SHARED
if eof()
append blank
endif
rlock()
REPLACE mode with cMode
REPLACE path with ''
REPLACE report with cFile // 'po.frx'
unlock
waitrun( 'vfp.exe', 3 )
return .t.
FUNCTION TraeIni(cSeccion,cEntry,gDefault)
LOCAL oIni,gGet
DEFAULT gDefault := nil
INI oIni FILE "hEdit"
IF gDefault == nil
GET gGet SECTION cSeccion ENTRY cEntry OF oIni
ELSE
GET gGet SECTION cSeccion ENTRY cEntry OF oIni DEFAULT gDefault
ENDIF
ENDINI
RETURN gGet
FUNCTION DejaIni(cSeccion,cEntry,gDato)
LOCAL oIni
INI oIni FILE "hEdit"
SET SECTION cSeccion ENTRY cEntry TO gDato OF oIni
ENDINI
RETURN nil
DLL32 Function GetFullPathName( lpszFile AS LPSTR, cchPath AS DWORD,;
lpszPath AS LPSTR, @nFilePos AS PTR ) AS DWORD ;
PASCAL FROM "GetFullPathNameA" LIB "kernel32.dll"
DLL32 Function apiFindFst(lpFilename AS LPSTR, @cWin32DataInfo AS LPSTR) AS LONG PASCAL FROM "FindFirstFileA" LIB "KERNEL32.DLL"
DLL32 Function apiFindNxt(nHandle AS LONG, @cWin32DataInfo AS LPSTR) AS BOOL PASCAL FROM "FindNextFileA" LIB "KERNEL32.DLL"
DLL32 Function apiFindCls(nHandle AS LONG) AS BOOL PASCAL FROM "FindClose" LIB "KERNEL32.DLL"
DLL32 Function apiFT2DT(@lpFT AS LPSTR, @lpDATE AS LPSTR, @lpTIME AS LPSTR) AS BOOL PASCAL FROM "FileTimeToDosDateTime" LIB "KERNEL32.DLL"
DLL32 Function apiFT2LT(@lpFT AS LPSTR, @lpLT AS LPSTR) AS BOOL PASCAL FROM "FileTimeToLocalFileTime" LIB "KERNEL32.DLL"
DLL32 STATIC FUNCTION COPYFILE( cOldName AS LPSTR, cNewName AS LPSTR ) AS BOOL PASCAL FROM "CopyFileA" LIB "kernel32.dll"
O codigo do programa em Visua FoxPRO é simples, mas só servirá para visualização a não ser que voce use o Visual FoxPRO para incrementa-lo:
*** vfp report code
SET RESOURCE OFF
SET CPDIALOG OFF
SET DATE TO BRITISH
SET CENTURY ON
SET DELETE ON
SET EXACT ON
SET OPTIMIZE ON
ON SHUTDOWN QUIT
CLOSE ALL
CLEAR RESOURCES
KEYBOARD '{ctrl+f10}' CLEAR
USE report SHARED
cMode=ALLTRIM(mode)
cPath=ALLTRIM(path)
cRep =ALLTRIM(report)
USE
DO CASE
CASE cMode='Set'
* maintain your report dbf/tag/relation
USE reportDb
BROWSE
USE
CASE cMode='New'
CREATE REPORT
* 1. right click on blank scrren to get Data Environment
* 2. right click to add main dbf for this report
CASE cMode='Edit'
SET SYSMENU TO _MFILE,_MEDIT
RELEASE PAD _MFI_SAVE OF _MFILE
RELEASE PAD _MFI_SYSPRINT OF _MFILE
RELEASE PAD _MED_PSTLK OF _MEDIT
RELEASE PAD _MED_FIND OF _MEDIT
RELEASE PAD _MED_FINDA OF _MEDIT
RELEASE PAD _MED_REPL OF _MEDIT
RELEASE PAD _MED_SLCTA OF _MEDIT
RELEASE PAD _MED_INSOB OF _MEDIT
RELEASE PAD _MED_OBJ OF _MEDIT
RELEASE PAD _MED_LINK OF _MEDIT
RELEASE PAD _MED_CLEAR OF _MEDIT
RELEASE PAD _MED_PREF OF _MEDIT
RELEASE PAD _MED_SP200 OF _MEDIT
RELEASE PAD _MED_SP300 OF _MEDIT
RELEASE PAD _MED_SP400 OF _MEDIT
RELEASE PAD _MED_SP500 OF _MEDIT
SET RESOURCE ON
KEYBOARD '{ctrl+f10}' CLEAR
MODIFY REPORT &cRep
CASE cMode='Print'
DIMENSION aDbf[100],aCdx[100],aTg[100],aRela[100,100],aAlia[100,100]
nDbf=0
USE reportdb SHARED
SET FILTER TO upper(alltrim(frx))=STRTRAN(UPPER(cRep),'.FRX','')
GO TOP
nRela=(FCOUNT()-3)/2
DO WHILE !EOF()
IF !EMPTY(DBF)
nDbf=nDbf+1
aDbf[nDbf]=ALLTRIM(DBF)
aCdx[nDbf]=ALLTRIM(CDX)
aTg[nDbf]=ALLTRIM(TAG)
FOR j=1 TO nRela
cJ=PADL(INT(j),2,'0')
cFd='field'+cJ
cAl='alias'+cJ
aRela[nDbf,j]=&cFd
aAlia[nDbf,j]=&cAl
NEXT
ENDIF
SKIP
ENDDO
USE
IF nDbf<=0
RETURN .t.
ENDIF
*** set main dbf for report details band
cDetails=aDbf[nDbf]
cEx='Alias = "'+cDetails+'"'+CHR(13)+CHR(10)
cEx=cEx+'CursorSource = '+cDetails+'.dbf'+CHR(13)+CHR(10)
cEx=cEx+'Name = "cursor1"'+CHR(13)+CHR(10)
USE &cRep
LOCATE FOR objtype=26
IF FOUND()
replace expr WITH cEx
ENDIF
USE
*** open all dbfs with relations
FOR i=1 TO nDbf
cDbf=cPath+aDbf[i]
cCdx=cPath+aCdx[i]
cTag=aTg[i]
SELE 0
USE &cDbf INDEX &cCdx SHARED
SET ORDER TO TAG &cTag
FOR j=1 TO nRela
cFd=aRela[i,j]
cAl=aAlia[i,j]
IF !EMPTY(cFD)
SET RELATION TO &cFd INTO &cAl ADDITIVE
ELSE
EXIT
ENDIF
NEXT
NEXT
GO TOP
REPORT FORM &cRep TO PRINT PROMPT PREVIEW
ENDCASE
CLOSE ALL
RETURN .t.
Os arquivos REPORT.DBF e REPORTDB.DBF são usados pelo gerador para armazenar informações sobre os relatorios.
Os arquivos PURC1.DBF, PURC2.DBF e SUPPLIER possuem os dados usados na impressão dos relatorios.
Muito mais facil de integrar e muito mais fácil de trabalhar que o Cyrstal Reports, ReportManager e FastReport, pois voce pode ter dentro de sua aplicação a chamada para o desenhador de relatórios, podendo os mesmos serem alterados pelo usuário.
Restaria então acrescentar um meio, em seu sistema, de agregar em momento de execução, o novo relatório aos menus do mesmo.
Baixar
Nota 10.