Page 1 of 1

Drawing Graphs from file data

Posted: Tue Mar 05, 2019 10:06 am
by prof50
Hi,

I am from Melbourne, Australia.
I have many years programming in Clipper mainly for my own use - databases for personal and financial details mainly.
I have made several HMG projects successively.
Current problem is a need to make a graph of price data from a DBF file.
I have tried the Bos Tauros samples but having lots of problems with the array functions in them.

The following code is a cut-down version of original - eg, I have eliminated the pie graph option, as well as 3D option etc. to simplify it a bit. Only a sample of the original array declaration works - all other versions do not work.
The other 3 code options all give same error message "DRAW GRAPH: 'Series' / 'SerieNames' / 'Colors' arrays size mismatch." from h_GraphBitmap.prg
I have looked through the many posts re 'BT graphing' but none seem to address the simple point that I am wanting - the ability to draw a graph from a series of datapoints contained in a DBF file.

/*
MINIGUI - Harbour Win32 GUI library Demo

Author: Siri Rathinagiri <srgiri@dataone.in>

Revised by Grigory Filatov <gfilatov@inbox.ru>
*/

#include "hmg.ch"


FUNCTION Main

set font to "Arial", 9

// altd()

define window graph at 0, 0 width 1000 height 700 title 'Bos Taurus Graph' main

define label selecttype
row 10
col 45
width 115
value 'Select Graph Type'
vcenteralign .T.
end label

define combobox graphtype
row 10
col 160
width 100
items { 'Bar', 'Lines', 'Points', 'Pie' }
onchange drawgraph()
end combobox

define checkbox enable3d
row 10
col 280
width 100
caption 'Enable 3D'
onchange drawgraph()
value .F.
end checkbox

define button Button_1
row 10
col 400
caption 'Save as PNG'
action ProcSaveGraph()
end button

define image grapharea
row 50
col 50
width 800
height 600
stretch .T.
end image

end window

graph.graphtype.value := 2

graph.center
graph.activate

RETURN NIL


FUNCTION drawgraph

LOCAL nImageWidth := graph.grapharea.width
LOCAL nImageHeight := graph.grapharea.height
LOCAL aSV := {}, aSN := {}
LOCAL hBitmap
LOCAL i := 0

IF graph.graphtype.value == 0
RETURN NIL
ENDIF

#define COLOR1 { 128, 128, 255 }

/*
// Option 1 : FOR-NEXT with simple arrays
FOR i = 1 to 5
AADD( aSV, 100+5*i )
AADD( aSN, "" )
NEXT
*/


// Option 2 : array with structure as per original. This is only option that works!
aSV := { { 105, 110, 115, 120, 125 } }
aSN := { "", "", "", "", "" }


/*
// Option 3 : simple array with 'normal' declaration
aSV := { 105, 110, 115, 120, 125 }
aSN := { "", "", "", "", "" }
*/

/*
// Option 4 : desired result - load data points from a DBF
use ( "BT_TEST.DBF" ) // just a DBF with numerics in first field
DO WHILE ! EOF()
AADD( aSV := FIELDGET( 1 ) )
AADD( aSN, "" )
SKIP
ENDDO
*/

GRAPH BITMAP graph.GraphType.VALUE ;
SIZE nImageWidth, nImageHeight ;
SERIEVALUES aSV ;
SERIENAMES { "Serie 1" } ;
SERIECOLORS { COLOR1 } ;
SERIEYNAMES aSN ;
PICTURE "99,999.99" ;
TITLE "Sample Graph" ;
TITLECOLOR BLACK ;
HVALUES 5 ;
BARDEPTH 15 ;
BARWIDTH 15 ;
SEPARATION NIL ;
LEGENDWIDTH 10 ;
3DVIEW .F. ;
SHOWGRID .T. ;
SHOWXGRID .T. ;
SHOWYGRID .T. ;
SHOWVALUES .F. ;
SHOWXVALUES .T. ;
SHOWYVALUES .T. ;
SHOWLEGENDS .T. ;
NOBORDER .F. ;
STOREIN hBitmap

graph.grapharea.HBITMAP := hBitmap // Assign hBitmap to the IMAGE control

RETURN NIL



PROCEDURE ProcSaveGraph()

LOCAL cFileName
LOCAL hBitmap := graph.grapharea.HBITMAP // Gets the value of hBitmap from the IMAGE control

IF hBitmap <> 0 .AND. graph.GraphType.VALUE > 0

cFileName := "Graph_" + graph.GraphType.ITEM( graph.GraphType.VALUE ) + IIF( graph.Enable3D.VALUE, "3D", "2D") + ".PNG"
BT_BitmapSaveFile( hBitmap, cFileName, BT_FILEFORMAT_PNG )

MsgInfo( "Save as: " + cFileName )

ENDIF

RETURN

I would be relieved to know there is a solution to this matter.

Prof50

Re: Drawing Graphs from file data

Posted: Tue Mar 05, 2019 11:07 am
by gfilatov
Hi,

You are welcome aboard!

Please be so kind to try the following updated sample for your option 4:

Code: Select all

/*
MINIGUI - Harbour Win32 GUI library Demo

*/

#include "hmg.ch"


FUNCTION Main

set font to "Arial", 9

// altd()

define window graph at 0, 0 width 1000 height 700 title 'Bos Taurus Graph' main

define label selecttype
row 10
col 45
width 115
value 'Select Graph Type'
vcenteralign .T.
end label

define combobox graphtype
row 10
col 160
width 100
items { 'Bar', 'Lines', 'Points', 'Pie' }
onchange drawgraph()
end combobox

define checkbox enable3d
row 10
col 280
width 100
caption 'Enable 3D'
onchange drawgraph()
value .F.
end checkbox

define button Button_1
row 10
col 400
caption 'Save as PNG'
action ProcSaveGraph()
end button

define image grapharea
row 50
col 50
width 800
height 600
stretch .T.
end image

end window

graph.graphtype.value := 2

graph.center
graph.activate

RETURN NIL


FUNCTION drawgraph

LOCAL nImageWidth := graph.grapharea.width
LOCAL nImageHeight := graph.grapharea.height
LOCAL aSV := {}, aSN := {}, aTmp := {}
LOCAL hBitmap
LOCAL i := 0

IF graph.graphtype.value == 0
RETURN NIL
ENDIF

#define COLOR1 { 128, 128, 255 }

/*
// Option 1 : FOR-NEXT with simple arrays
FOR i = 1 to 5
AADD( aTmp, 100+5*i )
AADD( aSN, "" )
NEXT
AADD( aSV, aTmp )
*/

// Option 2 : array with structure as per original. This is only option that works! 
//aSV := { { 105, 110, 115, 120, 125 } } 
//aSN := { "", "", "", "", "" } 

   IF ! FILE( "BT_TEST.DBF" )
      dbCreate( "BT_TEST.DBF", { { "TEST",  "N", 10, 0 } } )
   ENDIF

   USE BT_TEST.DBF NEW
   IF LastRec() == 0
      FOR i = 1 to 5
         APPEND BLANK
         FIELDPUT( 1, 100+5*i )
      NEXT
   ENDIF

// Option 4 : desired result - load data points from a DBF
//use ( "BT_TEST.DBF" ) // just a DBF with numerics in first field
GO TOP
DO WHILE ! EOF()
AADD( aTmp, FIELDGET( 1 ) )
AADD( aSN, "" )
SKIP
ENDDO
AADD( aSV, aTmp )

USE

GRAPH BITMAP graph.GraphType.VALUE ; 
SIZE nImageWidth, nImageHeight ;
SERIEVALUES aSV ;
SERIENAMES { "Serie 1" } ; 
SERIECOLORS { COLOR1 } ; 
SERIEYNAMES aSN ;
PICTURE "99,999.99" ;
TITLE "Sample Graph" ;
TITLECOLOR BLACK ;
HVALUES 5 ;
BARDEPTH 15 ; 
BARWIDTH 15 ;
SEPARATION NIL ;
LEGENDWIDTH 30 ;
3DVIEW .F. ; 
SHOWGRID .T. ;
SHOWXGRID .T. ;
SHOWYGRID .T. ;
SHOWVALUES .F. ;
SHOWXVALUES .T. ;
SHOWYVALUES .T. ; 
SHOWLEGENDS .T. ; 
NOBORDER .F. ;
STOREIN hBitmap 

graph.grapharea.HBITMAP := hBitmap // Assign hBitmap to the IMAGE control

RETURN NIL



PROCEDURE ProcSaveGraph()

LOCAL cFileName
LOCAL hBitmap := graph.grapharea.HBITMAP // Gets the value of hBitmap from the IMAGE control

IF hBitmap <> 0 .AND. graph.GraphType.VALUE > 0

cFileName := "Graph_" + graph.GraphType.ITEM( graph.GraphType.VALUE ) + IIF( graph.Enable3D.VALUE, "3D", "2D") + ".PNG"
BT_BitmapSaveFile( hBitmap, cFileName, BT_FILEFORMAT_PNG )

MsgInfo( "Save as: " + cFileName )

ENDIF

RETURN
with a result screen below

Re: Drawing Graphs from file data

Posted: Tue Mar 05, 2019 3:54 pm
by jairpinho
prof50 wrote: Tue Mar 05, 2019 10:06 am Hi,

I am from Melbourne, Australia.
I have many years programming in Clipper mainly for my own use - databases for personal and financial details mainly.
I have made several HMG projects successively.
Current problem is a need to make a graph of price data from a DBF file.
I have tried the Bos Tauros samples but having lots of problems with the array functions in them.

The following code is a cut-down version of original - eg, I have eliminated the pie graph option, as well as 3D option etc. to simplify it a bit. Only a sample of the original array declaration works - all other versions do not work.
The other 3 code options all give same error message "DRAW GRAPH: 'Series' / 'SerieNames' / 'Colors' arrays size mismatch." from h_GraphBitmap.prg
I have looked through the many posts re 'BT graphing' but none seem to address the simple point that I am wanting - the ability to draw a graph from a series of datapoints contained in a DBF file.

/*
MINIGUI - Harbour Win32 GUI library Demo

Author: Siri Rathinagiri <srgiri@dataone.in>

Revised by Grigory Filatov <gfilatov@inbox.ru>
*/

#include "hmg.ch"


FUNCTION Main

set font to "Arial", 9

// altd()

define window graph at 0, 0 width 1000 height 700 title 'Bos Taurus Graph' main

define label selecttype
row 10
col 45
width 115
value 'Select Graph Type'
vcenteralign .T.
end label

define combobox graphtype
row 10
col 160
width 100
items { 'Bar', 'Lines', 'Points', 'Pie' }
onchange drawgraph()
end combobox

define checkbox enable3d
row 10
col 280
width 100
caption 'Enable 3D'
onchange drawgraph()
value .F.
end checkbox

define button Button_1
row 10
col 400
caption 'Save as PNG'
action ProcSaveGraph()
end button

define image grapharea
row 50
col 50
width 800
height 600
stretch .T.
end image

end window

graph.graphtype.value := 2

graph.center
graph.activate

RETURN NIL


FUNCTION drawgraph

LOCAL nImageWidth := graph.grapharea.width
LOCAL nImageHeight := graph.grapharea.height
LOCAL aSV := {}, aSN := {}
LOCAL hBitmap
LOCAL i := 0

IF graph.graphtype.value == 0
RETURN NIL
ENDIF

#define COLOR1 { 128, 128, 255 }

/*
// Option 1 : FOR-NEXT with simple arrays
FOR i = 1 to 5
AADD( aSV, 100+5*i )
AADD( aSN, "" )
NEXT
*/


// Option 2 : array with structure as per original. This is only option that works!
aSV := { { 105, 110, 115, 120, 125 } }
aSN := { "", "", "", "", "" }


/*
// Option 3 : simple array with 'normal' declaration
aSV := { 105, 110, 115, 120, 125 }
aSN := { "", "", "", "", "" }
*/

/*
// Option 4 : desired result - load data points from a DBF
use ( "BT_TEST.DBF" ) // just a DBF with numerics in first field
DO WHILE ! EOF()
AADD( aSV := FIELDGET( 1 ) )
AADD( aSN, "" )
SKIP
ENDDO
*/

GRAPH BITMAP graph.GraphType.VALUE ;
SIZE nImageWidth, nImageHeight ;
SERIEVALUES aSV ;
SERIENAMES { "Serie 1" } ;
SERIECOLORS { COLOR1 } ;
SERIEYNAMES aSN ;
PICTURE "99,999.99" ;
TITLE "Sample Graph" ;
TITLECOLOR BLACK ;
HVALUES 5 ;
BARDEPTH 15 ;
BARWIDTH 15 ;
SEPARATION NIL ;
LEGENDWIDTH 10 ;
3DVIEW .F. ;
SHOWGRID .T. ;
SHOWXGRID .T. ;
SHOWYGRID .T. ;
SHOWVALUES .F. ;
SHOWXVALUES .T. ;
SHOWYVALUES .T. ;
SHOWLEGENDS .T. ;
NOBORDER .F. ;
STOREIN hBitmap

graph.grapharea.HBITMAP := hBitmap // Assign hBitmap to the IMAGE control

RETURN NIL



PROCEDURE ProcSaveGraph()

LOCAL cFileName
LOCAL hBitmap := graph.grapharea.HBITMAP // Gets the value of hBitmap from the IMAGE control

IF hBitmap <> 0 .AND. graph.GraphType.VALUE > 0

cFileName := "Graph_" + graph.GraphType.ITEM( graph.GraphType.VALUE ) + IIF( graph.Enable3D.VALUE, "3D", "2D") + ".PNG"
BT_BitmapSaveFile( hBitmap, cFileName, BT_FILEFORMAT_PNG )

MsgInfo( "Save as: " + cFileName )

ENDIF

RETURN

I would be relieved to know there is a solution to this matter.

Prof50

follow one more example
Histogram.zip
(9.72 KiB) Downloaded 195 times

Re: Drawing Graphs from file data

Posted: Tue Mar 05, 2019 9:29 pm
by prof50
Thanks Grigory & Jair,

I tried Grigory's suggestion and it worked, in that it produced a graph of the points.

However the scaling of the graph is not right, in that all the values are jammed up towards the top of graph. Another problem is there is a vertical black line for every point - I do not need that vertical black line, just horizontal lines to show the Y values.

I have other business to attend to now, will try some more tomorrow. Will also look at Histogram solution, but my requirement is for a point or line solution.

Prof50

Re: Drawing Graphs from file data

Posted: Wed Mar 06, 2019 7:49 am
by gfilatov
prof50 wrote: Tue Mar 05, 2019 9:29 pm However the scaling of the graph is not right, in that all the values are jammed up towards the top of graph. Another problem is there is a vertical black line for every point - I do not need that vertical black line, just horizontal lines to show the Y values.
Hi,

Please take a look for the updated sample below:

Code: Select all

/*
MINIGUI - Harbour Win32 GUI library Demo

*/

#include "hmg.ch"

#define COLOR1 { 128, 128, 255 }


FUNCTION MAIN

   SET FONT TO "Arial", 10

   DEFINE WINDOW graph AT 0, 0 width 1000 height 700 title 'Bos Taurus Graph' MAIN

   DEFINE LABEL selecttype
      row 10
      col 45
      width 115
      VALUE 'Select Graph Type'
      vcenteralign .T.
   END LABEL

   DEFINE combobox graphtype
      row 10
      col 160
      width 100
      items { 'Bar', 'Lines', 'Points' }
      onchange drawgraph()
   end combobox

   DEFINE checkbox enable3d
      row 10
      col 280
      width 100
      CAPTION 'Enable 3D'
      onchange drawgraph()
      VALUE .F.
   end checkbox

   DEFINE BUTTON Button_1
      row 10
      col 400
      CAPTION 'Save as PNG'
      ACTION ProcSaveGraph()
   end button

   DEFINE image grapharea
      row 50
      col 50
      width 800
      height 600
      stretch .T.
   end image

   end window

   graph.graphtype.VALUE := 3

   graph.CENTER
   graph.ACTIVATE

   RETURN NIL


FUNCTION drawgraph

   LOCAL nImageWidth := graph.grapharea.width
   LOCAL nImageHeight := graph.grapharea.height
   LOCAL aSV := {}, aSN := {}, aTmp := {}
   LOCAL hBitmap
   LOCAL i := 0

   IF graph.graphtype.VALUE == 0
      RETURN NIL
   ENDIF

   IF ! File( "BT_TEST.DBF" )
      dbCreate( "BT_TEST.DBF", { { "TEST", "N", 10, 0 } } )
   ENDIF

   USE BT_TEST.DBF NEW
   IF LastRec() == 0
      FOR i = 1 TO 5
         APPEND BLANK
         FieldPut( 1, 100 + 5 * i )
      NEXT
   ENDIF

   // load data points from a DBF
   // just a DBF with numerics in first field
   GO TOP
   DO WHILE ! Eof()
      AAdd( aTmp, FieldGet( 1 ) )
      AAdd( aSN, "" )
      SKIP
   ENDDO
   AAdd( aSV, aTmp )

   USE

   GRAPH BITMAP graph.GraphType.VALUE ;
      SIZE nImageWidth, nImageHeight ;
      SERIEVALUES aSV ;
      SERIENAMES { "Serie 1" } ;
      SERIECOLORS { COLOR1 } ;
      SERIEYNAMES aSN ;
      PICTURE "99,999,999" ;
      TITLE "Sample Graph" ;
      TITLECOLOR BLACK ;
      HVALUES 25 ;
      BARDEPTH 15 ;
      BARWIDTH 15 ;
      SEPARATION NIL ;
      LEGENDWIDTH 40 ;
      3DVIEW graph.enable3d.VALUE ;
      SHOWGRID .F. ;
      SHOWXGRID .T. ;
      SHOWYGRID .F. ;
      SHOWVALUES .T. ;
      SHOWXVALUES .T. ;
      SHOWYVALUES .F. ;
      SHOWLEGENDS .T. ;
      NOBORDER .F. ;
      STOREIN hBitmap

   graph.grapharea.HBITMAP := hBitmap // Assign hBitmap to the IMAGE control

   RETURN NIL


PROCEDURE ProcSaveGraph()

   LOCAL cFileName
   LOCAL hBitmap := graph.grapharea.HBITMAP // Gets the value of hBitmap from the IMAGE control

   IF hBitmap <> 0 .AND. graph.GraphType.VALUE > 0

      cFileName := "Graph_" + graph.GraphType.ITEM( graph.GraphType.VALUE ) + iif( graph.Enable3D.VALUE, "3D", "2D" ) + ".PNG"
      BT_BitmapSaveFile( hBitmap, cFileName, BT_FILEFORMAT_PNG )

      MsgInfo( "Save as: " + cFileName )

   ENDIF

   RETURN
Result:

Re: Drawing Graphs from file data

Posted: Wed Mar 06, 2019 8:48 pm
by prof50
X-Values no longer displayed.

Thanks to Grigory for that.

Now I will work on the scaling problem - perhaps over the coming weekend?

Re: Drawing Graphs from file data

Posted: Wed Mar 06, 2019 9:38 pm
by prof50
All,

To solve the scaling problem I need to step through the file h_Graphbitmap.prg using the Debugger.
I have copied that file into my working directory but when I run the Debugger it does not appear.

Anyone?

Re: Drawing Graphs from file data

Posted: Thu Mar 07, 2019 9:10 am
by mol
if you need to debug h_Graphbitmap.prg, you should compile it with -d option.
It's a piece of whole library, so you should use your own local copy of this file.

Re: Drawing Graphs from file data

Posted: Thu Mar 07, 2019 5:59 pm
by prof50
I have copied the h_Graphbitmap.prg file into my working directory, and in both my demoX.prg and h_Graphbitmap.prg files I have added the line altd(). Also changed the h_Graphbitmap.prg file in the \Source direectory to altd().

My compile.bat file reads:
call ..\..\..\batch\compile.bat demoX /d /l BosTaurus /lg miniprint2 %1 %2 %3 %4 %5 %6 %7 %8 %9

When I compile & run it I can only see the code in demoX.prg
The last two lines of code I see are:
graph.center
graph.activate
<< then it displays the graph >>
without showing me steps through h_Graphbitmap.prg file.

I have solved a similar scaling problem some time ago, would like to tackle this one.