A new method to build rich VFP reports from HTML

Published on by Yousfi Benameur


Assume having a cursor or table contains a memo field fill with html tags (html code).
How to render a report with these html tags?

this consists using the really rendered html (as  web does) and capture the page as image with the free utility IECAPT.exe (exclusively for internet explorer).

windows gdiplus must be in system( its the case for the  windows OS).
idea consists to render the memofield as invisible page web and capture it as jpg image (can be png,bmp,gif,emf...all gdiplus supported formats).
the report prepared by the user contains an image oleboundcontrol to host the relative image rendered from the memofield(html).

adapt this oleboundcontrol in report (rightclick on+properties):
  -clip contents
  -scale contents, retain the shape
  -scale contents , retian the frame
for a better readability i used the first option but retain that the html content must fill a page only not more.can resize images programmatly but the readabilty might be affected...

the free utility IECAPT can be downloaded at:http://downloads.sourceforge.net/iecapt/IECapt-2008-06-10.zip  (54ko).unzip and put iecapt.exe in the source folder.
(web page: http://iecapt.sourceforge.net/)
usage is easy as this command line :[ IECapt url(web or disc)  output(png,jpg,bmp,gif...)]
the html builds actually the better rich contents as any application does.
note: the  rendered images are stored in a folder "images" created.once the job finish these images are erased by the code.

i added to any page the magic ie tag :<meta http-equiv="X-UA-Compatible" content="IE=11;IE=EDGE" />	
to render as well the page as last ie navigators (ie11/edge),otherwise some modern css might be not rendered.

note: can render as well Unicodes languages with inserting in memo field [html] the encoded contents (string base 64).
_cliptext=filetosr(m.htmlfilename,13)  and in the code or outputing result , restore the original unicode with
strconv(m.stringencoded,14)
that because vfp dont support unicode surface.
test : the record 2 in the data is arabic.see how i build it.

conclusion:
with these some tricks can build any composite record (any knwon language) and preview it as a native vfp report with classic toolbar and appearance (because its original vfp report embedding images).

Download the demo in the zip below and run the code yhtml_report.prg

[Post 224]


Click on code to select [then copy] -click outside to deselect


*!*	*1*
*!*	created on 28 of february 2017
*!*	this is a demo how to render memo html field to a report output
*!*	the method consists to build a temp html file for each page and capture it as a jpg image
*!*	the memo field html content are then supersteded by a jpg temporary image
*!* the code uses a 2th party utility  as iecapt.exe (must be in source folder)
*!* report must be prepared  manually before running this code (can be done programmatly using the report as table and focusing essentially on object 4 (image)). 
*!*all these are in the zip below ,run yhtml_report.prg

&&shellexecute
Declare Integer ShellExecute In SHELL32.Dll Integer nWinHandle,;
	STRING cOperation,;
	STRING cFileName,;
	STRING cParameters,;
	STRING cDirectory,;
	INTEGER nShowWindow

Set Safe Off
Local m.yrep
m.yrep=Addbs(Justpath(Sys(16,1)))
Set Defa To (yrep)
If !Directory(m.yrep+"images")
	Md (m.yrep+"images")
	else
	erase (m.yrep+"images\*.*")
Endi
Clea Resources

Close Data All
Use Locfile( m.yrep+"yfrx.dbf")
local m.xhtml
Scan
if recno()=2 or recno()=4 or recno()=9   &&unicode here : convert encoded string 13-->14
m.xhtml=strconv(html,14)
else
m.xhtml=html
endi
set memowidth to 8192

	Local m.myvar
	TEXT to m.myvar textmerge noshow
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=11;IE=EDGE" />	
<style>
body{padding:25px;}
</style>
<<m.xhtml>>
	ENDTEXT

	Local m.lcdest
	m.lcdest=Addbs(Sys(2023))+"ytemp.html"
	Strtofile(m.myvar,m.lcdest)
	Local m.ximg
	m.ximg= m.lcdest+" "+m.yrep+"images\"+Trans(Recno())+".jpg"
	= ShellExecute(0, "open","iecapt.exe"  ,m.ximg,"",0)
	Wait Window "record  "+Trans(Recno())+"/"+Trans(Reccount())+ "  rendered" Nowait
	Inke(2)
	Repl img With (m.yrep+"images\"+Trans(Recno())+".jpg")
Endscan
Wait Clea

Repo Form zreport Preview
Erase (m.yrep+"images\*.*")  &&clean--can uncomment to see temporary images created


Of course if memo html fields contain web urls internet must be connected
Of course if memo html fields contain web urls internet must be connected
Of course if memo html fields contain web urls internet must be connected
Of course if memo html fields contain web urls internet must be connected
Of course if memo html fields contain web urls internet must be connected
Of course if memo html fields contain web urls internet must be connected

Of course if memo html fields contain web urls internet must be connected

Click on code to select [then copy] -click outside to deselect


*!*	*2* created on 03 of march 2017
*!*	this use listener with output as html to build an  (html report].
*!*	it uses the table yfrx.dbf/fpt and the zreport.frx/frt in the zip above (must download it first).
*!* the images outputed in [images folder] must be present to render this html report
*!* Uncomment the last line of the yhtml_report.prg , run it: verify the 10 images are in "images "folder
*!*line to uncomment  is : [*Erase (m.yrep+"images\*.*")  &&clean--can uncomment to see temporary images created]
*!* and the run this code
*!*	the html report is viewed

Clea All
Close Data All
Set Defa To Addbs(Justpath(Sys(16,1)))

loListener = .Null.
Do (_ReportOutput) With 5, loListener
loListener.TargetFileName = 'MyReport.html'   &&html output of report
loListener.Quietmode      = .T.
Use yfrx
Local m.lcfilename
m.lcfilename="zreport.frx"    &&getfile('frx')
Report Form (m.lcfilename)   Object loListener
Use In Select("yfrx")

&&show the result
Declare Integer ShellExecute In shell32.Dll ;
	INTEGER hndWin, String cAction, String cFileName, ;
	STRING cParams, String cDir, Integer nShowWin
ShellExecute(0,"open",loListener.TargetFileName,"","",1)




I have asked Lisa Nicholls a reporting specialist how to render html tags in a vfp report (embed as memo field in a table).
she menaged no effort to find a quick magic solution described in its blog at:
http://spacefold.com/lisa/post/2017/02/27/Using-Raw-HTML-with-HTMLListener.aspx

it consists in 3 things essentially
1.download an xslt file built by Lisa specially for this purpose and  put this file in source folder or link to it with path :xsltprocessoruser-sp2Plus.xslt
2.tweaking the report properties  in TAB "others" and adding manually a new property named HTML.Raw  set to "yes" (choose add..yes/no...HTML.Raw...yes).it appears on the list.  warning this is sensitive
3.build the code as below: and the memo fields are rendered directly (without building images as previously)
  the HTML report must be the same as previous in code *2*

Note: for rendering html tags directly in  fields of vfp report :no solution until this time.
      As i said previously Bo Durban have found a solution for this (no publication how ?).
this method runs an html report  as the code *3* below.      



Click on code to select [then copy] -click outside to deselect

*3* created on 03 of march 2017 from  Lisa Nicholls support
*can visit its blog as pointed above.
*code works mandatory with :MSXML 4.0 Service Pack 3 (Microsoft XML Core Services) 
*If not installed can be downloaded at:https://www.microsoft.com/fr-fr/download/de*tails.aspx?id=15697
*(its not shipped with win OS actually).

Set Classlib To Home(1) + 'FFC\_REPORTLISTENER'
Local ox
ox=Null
ox=Createobject("htmlListener")
ox.xsltProcessorUser="xsltprocessoruser-sp2Plus.xslt"
ox.adjustXSLTParameter(0,"useTextAreaForStretchingText")  && warning:sensitive

ox.targetFilename="yrendered.html"
ox.Quietmode=.T.  &&no diaogs
use yfrx
Repo Form  zreport    Object ox
Release Classlib Home(1) + 'FFC\_REPORTLISTENER'
Use In Select("yfrx")
&&show the result
Declare Integer ShellExecute In shell32.Dll ;
	INTEGER hndWin, String cAction, String cFileName, ;
	STRING cParams, String cDir, Integer nShowWin
ShellExecute(0,"open",ox.targetFilename,"","",1)


Click on code to select [then copy] -click outside to deselect


*4* created on 03 of march 2017
*assume table have memo field fill with html tags as table yfrx.dbf(i added the meta utf-8 declaration in code)
*using the table yfrx (with some unicode records as 2,4,9)
*this code outputs the table as html report file directly without any listener intervention.it consists on sum html memo in one html file essentially.
*the output is the same as codes *2* and code *3*

Use yfrx  &&my table for report with htl memo field [html]
Local m.myvar,m.x,m.xhtml
m.x=""

Scan
m.xhtml=Iif (Inlist(Recno(),2,4,9),Strconv(html,14),html)
TEXT to m.myvar textmerge noshow
<meta http-equiv="X-UA-Compatible" content="IE=11;IE=EDGE" />
 <meta charset="UTF-8">
<style>
body{padding:50px;}
</style>
<<m.xhtml>>
<hr><br>
ENDTEXT

	m.x=m.x+m.myvar+Chr(13)
Endscan
Use In Select("yfrx")

Set Safe Off
Local m.lcdest
m.lcdest=Addbs(Sys(2023))+"ytemp.html"
Strtofile(m.x,m.lcdest)


&&show the result
Declare Integer ShellExecute In shell32.Dll ;
	INTEGER hndWin, String cAction, String cFileName, ;
	STRING cParams, String cDir, Integer nShowWin
ShellExecute(0,"open",m.lcdest,"","",1)

*Erase (m.lcdest)  &&clean temporary file

Retu


Click on code to select [then copy] -click outside to deselect


*5* created on 03 of march 2017
*!*	IECAPT is a wonderfull tool (created with C++) to download a web page as image
*!*	it uses the gdiplus of windows OS to work (mandatory)
*!*	the command line is simple:[ IECAPT  lcurl   OutputImage]
*!* i use it here to run with shellexecute API  in a dos window hidden
*!* its possible it raises some dialog errors with ceratin web protected pages (robots?)
*!* IECAPT download http://downloads.sourceforge.net/iecapt/IECapt-2008-06-10.zip
*!* http://iecapt.sourceforge.net/  (web page:http://iecapt.sourceforge.net/)
*!*	Note!: i used the api PrintWindow  to snap a web page (and gdiplusX to resize the image)  in:
*!*	http://yousfi.over-blog.com/2015/02/snap-a-web-page-as-image.html
*!*	it does same work as IECAPT but must be performed....
*!*	IECAPT can snap any web page and this is an example as the code below
*!*IECAPT.exe must be in source folder to run the code.

If !File('iecapt.exe')
	Messagebox("IECAPT.exe must be in source folder mandatory!",16+4096,'ERROR',1400)
	Return .F.
Endi

Local m.lcURL
m.lcURL=Inputbox("Type any web (or local) valid URL","","http://www.atoutfox.org/")
If Empty(m.lcURL)
	Return .F.
Endi
Local m.yrep
m.yrep=Addbs(Justpath(Sys(16,1)))
Declare Integer Sleep In kernel32 Integer
Declare Integer ShellExecute In shell32.Dll ;
	INTEGER hndWin, String cAction, String cFileName, ;
	STRING cParams, String cDir, Integer nShowWin

Local m.lcdest,m.xparam,result
m.lcdest=m.yrep+"ycapture_"+Sys(2015)+".jpg"
m.xparam= m.lcURL+"  "+m.lcdest  &&can be png,bmp,gif,emf...format
m.result	= ShellExecute(0, "open","iecapt.exe"  ,m.xparam,"",1)
Sleep(3000)  &&wait to render.
If  m.result>32
	Local oo
	Run/N explorer &lcdest
Else
	Messagebox("An error was occured!",16+4096)
Endi


A new method to build rich VFP reports from HTML

Important:All Codes above are tested on VFP9SP2 & windows 10 pro and IE11 emulation.

To be informed of the latest articles, subscribe:
Comment on this post

JenniferHsu 03/07/2017 04:07

VFP becomes a helpful Accessibility after without microsoft's support...
JenniferHsu 3.07