Por si a alguien le puede ayudar o se anima a usar MyRpt. Yo no conocía la existencia de MyRpt y llegue a el buscando en el foro por tener necesidad de un diseñador de documentos decente. Lo he podido implementar en poco más de un día, así que ahí van los pasos que he seguido.
Aunque por supuesto MyRpt se puede usar tal y como lo ha dejado Carles (de nuevo gracias), yo me he encontrado con unos cuantos problemas:
1º) Agregar una cantidad impresionante de prgs a mis programas o utilizar la librería generada. La primera opción me pareció un tostón tener que meter tantos ficheros al .MAK o a Verce que utilizo habitualmente y más si lo voy a implementar en varias aplicaciones, la segunda me dio muchos problemas. Al final metí todos los prg en un solo fichero, lo he linkado en un par de aplicaciones y funciona. Se que no es muy ortodoxo, pero hasta que esté totalmente terminada y funcione sin problemas, para mi es más cómodo.
2º) En los fuente viene una clase TReport que no es la de FW, la he renombrado a TRpt (y todas las llamadas a ella)
3º) Quería dejar que el usuario pudiese configurar ciertos documentos, algo así como "Configurar factura". Tal y como venía el usuario tenía que guardar el archivo y lo podía hacer con otro nombre, además podía cambiarle el nombre a los cID de los items, con lo cual podía fastidiar todo. Le he puesto una data ::lsmartmenu, que hace que no se muestren ciertas opciones de menú, el menú flotante del botón derecho del ratón y que no permita cambiar los cID. Estoy trabajando en una data que consista en un array con los datos obligatorios y que no se puedan borrar, renombrar ni ocultar en el documento. También le he añadido data ::cnomapp para mostrar el nombre de la aplicación en ciertos mensajes.
4º) Para facilitar su uso, le he puesto parametros a la llamada a MyRpt():New()
Así, para llamar al diseño de un documento concreto., solo tengo que poner dos líneas:
orpt := MyRpt():New(diruta()+'\Factura.rpt',"Diseñador de Factura de MyApp",'MyApp', t.) //El último parametro es ::lmenusmart
orpt:Activate()
Si quiero llamar al diseño de MyRpt en modo completo:
orpt := MyRpt():New()
orpt:Activate()
5º) He añadido el siguiente código al final método Postop() de TRptForm:
if ::lactive
::oRpt:oForm:lChange := .t.
::oRpt:oInspect:lactive := .f.
::oRpt:oForm:lBuilding = .T.
oitemact := ::oControlItem
::additem(oitemact:ntop, oitemact:nleft)
::oControlItem := oitemact
::oRpt:oInspect:DeleteItem(oitemact)
::oRpt:oInspect:AddItem(oitemact)
::oRpt:oInspect:SelectItem( oItemact )
::oRpt:oForm:lBuilding = .F.
::oRpt:oInspect:lactive := .t.
endif
Esto me ha surgido porque, aunque se puede poner de fondo un EMF, yo quería que pudiese ser un JPG, más accesible al usuario final. Me daba problemas si el JPG ocupaba todo el documento o el mismo espacio que otros items. Al pulsar el botón "Traer al frente", solo traia al frente (y con mala visualización) la ventana del control, pero en el Tree de TInspector seguía colocado en el mismo sitio, con lo cual al imprimirse, si el fondo JPG era el último, solo se veía el JPG porque machacaba los demás. Estoy viendo como poder poner otros controles encima de la imagen, de momento hay que dejar un pequeño hueco para ponerlos y luego moverlos a su sitio.
6º) He añadido el siguiente código al final del método PosBottom() de TRptFrom:
if ::lactive
oitemact := ::oControlItem
::oRpt:oForm:lChange := .t.
cSection := ::oControlItem:cSection
citemsel := ::oControlItem:cID
aItems := ::oRpt:oInspect:GetItemsSection( cSection )
::oRpt:oInspect:lactive := .f.
::oRpt:oForm:lBuilding = .T.
for nI := 1 To Len( aItems )
if aitems[nI]:cID <> citemsel
oitemmove := aitems[nI]
::additem(oitemmove:ntop, oitemmove:nleft)
::oControlItem := oitemmove
::oRpt:oInspect:DeleteItem(oitemmove)
::oRpt:oInspect:AddItem(oitemmove)
endif
next nI
::oRpt:oForm:lBuilding = .F.
::oRpt:oInspect:lactive := .t.
::oRpt:oInspect:SelectItem( oItemact )
endif
Por el mismo motivo que el anterior. De momento lo tengo así, a falta de buscar otra solución más límpia.
7º) He visto algunas funciones que hacian un SetResources() a ::cDllFile y luego, en ciertas circunstancias no volvía a hacer SetResources(oldresources), con lo cual me petaba mi programa al cargar algún otro dialogo, lo he corregido.
Eso es todo de momento, para el que no lo haya usado numca, el uso para imprimir documentos es muy simple, por ejemplo para una factura:
o := MyRpt():New(diruta()+'\factura.rpt', Generador de Factura de MyApp")
oRpt := o:Run()
oRpt:bHeader := {|| Cabefact(oRpt) } //Cabefact es la cabecera de la factura que se imprimirá igual en todas las hojas, los datos serán los de la section Public y de rellenan oRpt:Data('NOMBRE',cnombre)
oList := oRpt:GetSection('CUERPO') //CUERPO es una Section declarada en el .rpt
for n = 1 to len(alineas) //alineas son las líneas de la factura, sustituirlo por un do whil o lo que utiliceis
oList:Data('CANTIDAD', trimstr(alineas[n,1])) //CANTIDAD es el cID de un TSay metido en una Section
oList:Data('DESCRIPCION', alineas[n,2] )
oList:Data('PRECIO',transform(alineas[n,3],'@E 999,999.99'))
oList:Data('IMPORTE', transform(alineas[n,4],'@E 999,999.99'))
oList:Skip()
next n
oList:end()
oRpt:End()
oRpt := nil
Bueno, perdonad por el ladrillo, se que es mejor bajar la clase tal y como la ha dejado Carles, pero si quereis descargar el prg que estoy utilizando y la dll la he dejado en:
http://www.caseinformatica.com/MyRpt/myrpt.html
Es lo único que hace falta para implementarlo, la dll que he dejado es en español, sin cambios, la clase original trae varias en distintos idiomas si lo necesitais.
Saludos