Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VFP & FoxChart

Status
Not open for further replies.

JRB-Bldr

Programmer
May 17, 2001
3,281
US
I think that I must have taken a BIG dose of STUPID this morning resulting in the following confusion.

I need to get a Line Graph onto a VFP Report (not just onto a VFP Form).
It looks like the best approach for that might be to sue FoxChart (from VFPx), but I am having some difficulty getting it started.

I have downloaded FoxChart * GDIPlusX and even used Thor (also from VFPx) to get it installed into my VFP9.
But when I try to follow the FoxCharts.PDF documentation ( [URL unfurl="true"]http://doughennig.com/papers/Pub/FoxCharts.pdf[/url] ) Our first chart directions things fall apart from there.
It says:
* Create a form
* Drop an instance of FoxCharts on it, name it oChart, and size it appropriately.
But there is no "instance of FoxCharts" to drop on to the form.
It does not even appear among the OLE objects available.

Even in the FoxCharts documentation getting its object (oFoxChart) onto the VFP Report is a requirement and if I can't find it to drop onto a Form, I am sure not to find it to drop it onto a Report - which is where I need it to eventually go.

Obviously I am missing something (or many somethings) from the initial setup.

Any suggestions/advice you might have to offer would be greatly appreciated.

Thanks
JRB-Bldr
 
It does not even appear among the OLE objects available.

But FoxChart is not an ActiveX control, so it won't appear in the list of OLE objects.

What you should have is a file named FOXCHARTS.VCX. If you add that file to your project, you should be able to drop an instance on your form simply by dragging the class from the project manager.

I know that won't help you with your ultimate goal of displaying a chart in a report, but it is a possible first step.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Your main does of STUPID is as Mike already said: It's not OLE.

There is some common denominator of Reports and FoxCharts, but it goues a long round:

First there was reportlisteners introduced in VFP9 in ffc classes, also VFP9 introduced gdiplus support ffc libaries and these two topics have an overlap in that reportlistener render methods give you a gdi plus device context you may use for rendering/drawing on reports.

FoxCharts and reportlisteners are not directly usable with each other, though, the FoxCharts mainly aim for form display of charts.

You would not be the first borrowing from gdiplusx to use it in reports, though, the foxypreviewer team also used partial code fromgdiplusx. They aboided foxypreviewer to have a total dependency of gdiplusx, so these remain separate extensions, but the nature of the reportlistener would allows gdi drawing, it's no wonder as gdi (graphics device interface) aims not only for screen graphic, still you would have a steep learning curve and lot of work to integrate these tow things with each other, I'd say. The fastest approach might really be to accept that dependency and use gdiplusx as is within reports, that would then depend on the _screen.system.drawing and other gdiplusx objects be availabel during rendering a report and that would cause some quirks, most probably with the partial involvement of the foxypreviewer with gdi+ declarations. Too complicated to go into details.

But let me get back to the point of why this all gous a longwinded way: First I came across usage of gdiplus with VFP was as I needed it to combine 4 icons each from a set of 5 to all possible 5^4 combinations as I couldn't display 4 imagees in a listbox and thus wanted to compose images on the fly when needed. Cesar Chalom could help me with his first steps into that DLL and declarations - that was long ago, when I still was around in Universalthread. It was a first core of code later evolving into gdiplusx. And that was even before that became a VFP topic in VFP7 times, IIRC. NAyway it was before codeplex became sednas home. (By the way, codeplex is shutting down and VFPX moves to guthub).

FoxCharts is based on gdiplusx and foxypreviewer as said also borrowed some declarations in it's preview related classes. The main point is gdiplusx and foxyreviewer, despite of having that overlap in the GDI+ topic, have an independent development history and also didn't merge. FoxCharts is closer coupled to gdiplusx and so the best way to get FoxCharts printed on reports would be to merge all three, but it's harder to merge 2-3 projects having a long independent history, each. The major difficuly of course is merging foxypreviewer with gdiplusx, FoxCharts already is. Your other route would need to decouple FoxCharts from gdiplusx.

One thing is clear, despite all this history of involved components, even if you'd start from scratch with VFP native classes. The reportlistener must be involved to get gdi+ drawing into your reports.

All that said: One very simple way of going about it is using FoxCharts to create a PNG or JPG and then print that the usual way, which even the legacy printing engine is capable of. Just create very high resolution images.

Bye, Olaf.

 
Mike - thanks for the reply.

OK, but I am running this as a FXP through VB.Net so I need to modify the PRG code itself.
I can do a:
SET CLASSLIB TO FoxCharts.vcx ADDITIVE​
and then
oFoxChart = CREATEOBJECT("FoxCharts")​
which should make it available to the rest of the code.

But after doing that, how would I get it so that I can 'drop' an oFoxChart object onto either a User Form or onto the Summary Band of a Report Form?

Thanks,
JRB-Bldr
 
I think I am getting close

Code:
SELECT DtlSummary

SET CLASSLIB TO ADDBS(cLibDir) + "foxcharts.vcx" ADDITIVE
oFoxChart = CREATEOBJECT("FoxCharts")
WITH oFoxChart
   * Set all the properties for the chart
   * Name of the alias that contains the needed fields that will create the chart
   .SourceAlias = 'DtlSummary'
   * Numeric, the type or chart to create.
   .ChartType  = 5  && = Lines
   * Numeric, the number of data series (lines on the graph).
   .ChartsCount = 2
   * Numeric, the depth in pixels, simulating a 3D effect (0 = plain)
   .Depth = 0
   * The name of the field containing the values to be displayed along the X-Axis.
   .FieldAxis2 = 'Time'
   * The fields for each of the data series, and their associated legends
   WITH .FIELDS(1)
      .FieldValue = 'Units'
      .Legend = 'Total Units'
   ENDWITH
   WITH .FIELDS(2)
      .FieldValue = 'Dollars'
      .Legend = 'Total Dollars'
   ENDWITH
ENDWITH

Then
Code:
[b]Embedding in a Report (FRX)
[/b]A chart created by FoxCharts can be used directly in a report by adding an image to the report and setting its properties appropriately.

Drop an "Picture/OLEBoundControl" on the report designer surface. In the Properties dialog that appears, select “Expression or variable name” for the Control Source Type. In the "Control source" TextBox, put the image object name: oFoxChart.

I'll see where that leads me.
Just in case anyone else might need something like this in the future, I'll update when its working.

Thanks,
JRB-Bldr



 
That would be much simpler than I thought. Yes, please post back when you finally made that work.

Bye, Olaf.
 
Well I got things working but it didn't come about as easy as I thought.

I must have gotten it working just about the time that atlopes posted his reply above.
And, like is shown in atlopes reference link above, I had to use the .SaveToFile() to write out an image file (I used a PNG) and then brought the resultant PNG file image into the Report Form.

So I ended up with the following in my PRG code (no VFP Form needed and no WShell) to get a 2 Line Graph:

Code:
SELECT DtlSummary  && Cursor with summarized data - 3 fields - HourRange, Units, Dollars

PUBLIC oFoxChart
cLibDir = < directory where FoxCharts.VCX 'lives' >
SET CLASSLIB TO ADDBS(cLibDir) + "foxcharts.vcx" ADDITIVE
oFoxChart = CREATEOBJECT("FoxCharts")

WITH oFoxChart
   * Set all the properties for the chart
   * Name of the alias that contains the needed fields that will create the chart
   .SourceAlias = 'DtlSummary'
   * Numeric, the type or chart to create.
   .ChartType  = 5  && = Lines
   * Numeric, the number of data series.
   .ChartsCount = 2  && Defines how many lines 
   * Numeric, the depth in pixels, simulating a 3D effect (0 = plain)
   .Depth = 0
   * The name of the field containing the values to be displayed along the X-Axis.
   .FieldAxis2 = 'HourRange'
   * The fields for each of the data series, and their associated legends
   WITH .FIELDS(1)
      .FieldValue = 'Units'
      .Legend = 'Total Units'
   ENDWITH
   WITH .FIELDS(2)
         .FieldValue = 'Dollars'
         .Legend = 'Total Dollars'
   ENDWITH
   .WIDTH=900   && Define Width of the Graph itself
   .TITLE.CAPTION = "Graph Page Title"
   .SubTitle.CAPTION = ""   *  I did not need any SubTitle
   .xAxis.CAPTION = "Hours"  * Text for X-Axis
   .yAxis.CAPTION = "Units/Dollars"  * Text for Y-Axis

   .DrawChart()
   *  Save the Result Out To a Image File (Format defined by file extension)
   [b].SaveToFile("c:\temp\temp.png",1)[/b]
ENDWITH

Still to add are RGB color definitions for each of the separate graph lines
EDIT...
As atlopes has suggested:​
.ColorType = 2 will give you random colors for the lines in the chart​
Alternatively individual line colors can be specifically defined with the RGB values such as:
.ColorType = 1 tells FoxChart to use discrete Custom colors​
Then in the individual FIELDS(n)
*.Color = RGB(90,250,50) && Green
.Color = RGB(0,0,255) && Blue
*.Color = RGB(255,20,80) && Red

Then in the VFP Report Form I dropped on a Picture Object and set it to get the resultant PNG file.

There may be another way to get this more directly onto the Report Form and maybe someone will come along and show us how (I sincerely hope so), but for now it is working.

JRB-Bldr
 
.ColorType = 2 will give you random colors for the lines in the chart if you don't want to worry too much about it.

A sidenote: the Shell object was instantiated only for testing purposes just to show the resulting chart, exactly like you referenced the resulting chart in a report. It didn't add any functionality to the FunctionPlotter class.
 
Okay,

I would have been astonished, if you could use an object on the rerpot, you could only bind to ole objects ith the olebound control and the ole object couldn't just be a variable holding n object reference, you'd first store this in a General field. Since VFP classes can't be ole classes, only olepublic com servers (which is not sufficient), that would have been astonishing.

So it is rather as I last said:
OlafDoschke said:
One very simple way of going about it is using FoxCharts to create a PNG or JPG and then print that the usual way, which even the legacy printing engine is capable of. Just create very high resolution images.

I don't know why you say it's complicated, though, it's much less work than embedding FoxCharts into foxypreviewer reportlisteners to get Foxcharts going directly on a report instead of via the detour of a picture file. Extending the reportlistener would be much harder work tham addnig a SaveToFile line of code, wouldn't it?

Bye, Olaf.
 
The only reason I say it is 'complicated' is that it involves more than is implied in the Print/Saving Charts part of:
where they say:
Add the chart to a report: drop a Picture/OLE Bound control on the report,
and show:
FoxChart_in_Report_oyqlpl.jpg


All of that certainly implies that I should have been able to use the FoxChart Object directly in the Report Form.

Regardless, hopefully this might be of benefit to someone else looking for a similar solution.

JRB-Bldr
 
What you need is an expression that resolves to a filename. Your oChart, by itself, does not do that, but the Integral() method in the FunctionPlotter that I presented returns a filename, so it can be used as an expression to represent an image in a report. You'll have to think of something like that.

I changed the FunctionPlotter a little bit just to preserve the working area when any of its methods are invoked. Apart from that, it's the same class that you can find in the Foxite post.

Demonstrating:

a) Create a report that has, in its detail band, a label, a field, and an image. The controlsource for the field is set to "expression", and the image's is set to "m.Plotter.Integral(expression, 0, 3, 0.1)".

g1_w7c8mp.png


b) Create an object to generate the images (I'm creating it from the command window, so it will be Public). You may consider a function, for instance, that is always in scope, when not member of a class.

Code:
m.Plotter = CREATEOBJECT("FunctionPlotter")

c) Create a cursor to hold all the expressions that I want to plot:

Code:
CREATE CURSOR Expressions (expression varchar(200))
INSERT INTO Expressions VALUES ("3*x-x^2")
INSERT INTO Expressions VALUES ("x^2*SIN(x)")
INSERT INTO Expressions VALUES ("(COS(x)^2)*x")

d) Run the report. The images are inserted in the detail band.

g2_xtmgau.png


Of course, images will be left somewhere to be erased, but that housekeeping is not a big problem, by itself.
 
Well, the text is:

Add the chart to a report: drop a Picture/OLE Bound control on the report, set Control source type to
Expression or variable name, and set Control source to a variable containing a reference to an image
for the chart (Figure 23). Note that the variable must be private or public, not local.

And "a variable containing a reference to an image for the chart", well is that and not a reference to the foxchart class.

The PDF also gives the code to define and set such a variable.
Code:
private oChart
oChart = Thisform.oChart.ChartCanvas

or alternatively
Code:
private oChart
oChart = Thisform.oChart.DrawReport()

You just have to read the text after that Figure 23 in the PDF, too. Then you know you'd need to set it this way before running REPORT FORM.

So this oChart variable is not the oChart object, but either it's ChartCanvas sub object or better yet what DrawReport() returns. The documentation could have used a different name, but it works that way. And the next picture (Fig 24 in the PDF) illustrates, what I also said: "Just create very high resolution images.", the oChart.ChartCanvas is the object on the form having screen dpi resolution image and .oChart.DrawReport() creates a much higher resolution image to be usable as controlsource in a report OLE/Picture control.

Bye, Olaf.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top