Link to home
Start Free TrialLog in
Avatar of Cruisin18
Cruisin18

asked on

plotting a graph

How do you plot a graph inside of a picture box, instead of using MSChart?
Avatar of GivenRandy
GivenRandy

MSChart1.EditCopy
Picture1.Picture = Clipboard.GetData
p.s., you can make the MSChart hidden, but perform all of your actions there, then do the copy-and-paste mentioned above.
Avatar of Cruisin18

ASKER

I'm stuck on the actual plotting of the points.
I have 6 values to plot in  1 graph, how do you do this with the mschart or  a picture box?
This should help get you started:

---
Dim arrPrices(1 to 10)
Dim i As Integer
For i = 1 to 10
   arrPrices(i)= i * 2
Next i
MSChart1.ChartData = arrPrices
---

Look at the online help.  You can change the style (bar, line, etc.), colors, and on and on.

This is the approach you want to take (using MSChart and copy-and-paste).  Otherwise you will be writing a LOT of code and re-inventing the wheel.
If it's not too much work, you can send me your equation and what you would like.  <GivenRandy@aol.com>
You can use putpixel API to put a pixel anywhere you want..ifits a function that returns a bunch of data..the only hard part is defining the scope (settingup the coordinates)
it setpixel or put pixel.. I always have to look it up.. be forwarned its slower than death.
I don't understand why doing a graph can be so difficult, this is what i want to do

900
800
700
600

        5      10     15   20     25      30

the user put a number between 600 - 900  into a textbox every 5 minutes (6 VALUES) and hit a button and they have their graph,
I've never done a graph before and the help menu stinks

can anyone give a hand

Thanks
There are much simpler approaches to this!

Use the .Scale property on your picture box to scale to a convenient unit.

Then use .Line to draw your grid and link your data points

You can use .CurrentX/Y to position text anywhere you want.

You can change fonts and characteristics with .Font, .FontBold, .FontItalic, etc.

No API's are needed.

You can put a dot at a data point with the .Circle command. Keep the radius small and tell it filled and you can rapidly get spots everywhere.

You can do multiple line graphs, etc. that the M$Chart control can't. Since you're using just standard controls you keep your install small and you don't have to rely on the users having Excel or somesuch installed.

You can code your rendering routine to be passed an object. This allows you to use the same routine for on screen display and for final printing (printing is something that the M$Chart control *DOESN'T* do!). You'll have to put a little conditional logic around certain device specific statements (you can't .CLS the printer nor can you .EndDoc a picturebox) but overall 95% of your plot routine can be shared.

I can send samples if you want.

M
Yes please send me some samples, and the points are yours.

Thanks
Mark2150 has a good point.
I belive setpixel would be too small anyway.  I like his idea.  That shouldnt be hard at all good luck
Here's a plot routine that does logrithmic barcharts:

Plot is the Picture Box
PO is the legend string array
Results is the data array

I've got lots more plot routines if you need something specific let me know

M

Public Sub render()
Plot.ScaleWidth = 45
Plot.ScaleHeight = pocount + 2
Plot.ScaleLeft = -10
Plot.ScaleTop = -1
Plot.ForeColor = vbBlack
Plot.BackColor = vbWhite
Plot.FontSize = 8
Plot.Cls
Plot.Line (0, 0)-(0, pocount)
Plot.Line (10, 0)-(10, pocount), vbYellow
Plot.Line (17, 0)-(17, pocount), vbRed
Plot.Line (20, 0)-(20, pocount)
Plot.Line (30, 0)-(30, pocount)
Plot.Line (0, 0)-(30, 0)
Plot.Line (0, pocount)-(30, pocount)
'
text = "1"
Plot.CurrentY = -1
Plot.CurrentX = 0 - ((TextWidth(text) / TwipsPerInch) * 10) / 2
Plot.Print text
'
text = "10"
Plot.CurrentY = -1
Plot.CurrentX = 10 - ((TextWidth(text) / TwipsPerInch) * 10) / 2
Plot.Print text
'
text = "100"
Plot.CurrentY = -1
Plot.CurrentX = 20 - ((TextWidth(text) / TwipsPerInch) * 10) / 2
Plot.Print text
'
text = "1000"
Plot.CurrentY = -1
Plot.CurrentX = 30 - ((TextWidth(text) / TwipsPerInch) * 10) / 2
Plot.Print text
'
For Index = 1 To ubound(po)
    Plot.Line (0, Index - 0.5)-(30, Index - 0.5)
    legend = po(Index)
    Plot.CurrentY = Index - 0.75
    Plot.CurrentX = 0 - (TextWidth(legend) / TwipsPerInch) * 10
    Plot.Print legend
    Plot.CurrentX = 31
    Plot.CurrentY = Index - 0.75
    Plot.Print results(Index)
    depth = Log10(results(Index))
    Color = vbGreen
    If depth > 10 Then Color = vbYellow
    If depth > 17 Then Color = vbRed
    Plot.Line (0, Index - 0.75)-(depth, Index - 0.25), Color, BF
Next Index
End Sub

Static Function Log10(x)
    If x > 0 Then
        Log10 = 10 * (Log(x) / Log(10#))
    Else
        Log10 = 0
    End If
End Function
Good luck.  I was going to finish it for you, but looks like you prefer the other solution.

Mark, it is a hassle that the MSChart doesn't do printing.  I showed a way around it, but it is not clean.

Have fun!
Would about a line graph, and not a bar chart?
You use lines running from datapoint N to N+1 instead of a bar.

Here is excerpt of code that draws lines:
'
' Begin rendering
'
Graph1.Cls
Graph1.DrawWidth = 2
Graph1.Line (0, 0)-(LastDay + 1, max), vbBlack, B     'Draw border
Graph1.Line (0, Val(Goal.Text))-(LastDay + 1, Val(Goal.Text)), vbBlack 'Draw cumulative goal line
Graph1.Line (0, 0)-(LastDay, Val(Goal.Text)), vbBlue        'Draw cum trend line
'
Cumulative = 0
  Last_Cum = 0
For ndx = 1 To Day(Now)
    Cumulative = Cumulative + spd(ndx)
    Graph1.Line (ndx - 1, Last_Cum)-(ndx, Cumulative), vbRed    'Draw cumulative line
    Last_Cum = Cumulative
    '
Next ndx
Graph1.DrawWidth = 1

This uses a data array called spd.

M
>Would about a line graph, and not a
>bar chart?

:)  That's the nice thing about controls like MSChart.  Change one line and you switch between lines, bars, etc.

Yeah, but using my methods I can plot both lines and bars and circles and ... all on *ONE* plot!

M
M
I am getting errors ; (type mismatch)

How do I do this with 6 values being entered to be graphed

 how do i code these lines for the  6 values.

Graph1.Line (0, Val(Goal.Text))-(LastDay + 1, Val(Goal.Text)), vbBlack 'Draw cumulative goal


   Graph1.Line (ndx - 1, Last_Cum)-(ndx, Cumulative), vbRed    'Draw cumulative line

and am I doing this in a picture box  and calling it graph1 and putting a line in  the picture box and   naming it line?
The GOAL.TEXT is a single horizontal line showing the sales goal for the month.

The picture box is named Graph1, but the lines are *NOT* separate graphic symbols but commands to the picture box to draw a line. I think if you get rid of the "Line" object the type mismatch errors may clear.

You iterate thru the last_cum/cumulative set connecting the two points. Think about it. Each line segment in a graph starts where the previous one ends. Thus you use each data point twice. Once as the right end point and again as the left end point of the next datum.

This is core loop:

Cumulative = 0
Last_Cum = 0
  For ndx = 1 To Day(Now)
  Cumulative = Cumulative + spd(ndx)
  Graph1.Line (ndx - 1, Last_Cum)-(ndx, Cumulative), vbRed    'Draw cumulative line
  Last_Cum = Cumulative
  '
Next ndx

DAY(NOW) is just the count of the number of points in the SPD() data array.

This is drawing a cumulative graph. It's counting total sales for the month to date. If you want to draw the instantaneous values change:

  Cumulative = Cumulative + spd(ndx)

to:

  Cumulative = spd(ndx)

M
Mark wrote:

>Yeah, but using my methods I can plot
>both lines and bars and circles
>and ... all on *ONE* plot!

True.  Which is why we use controls like TeeChart that do all the basics and all the stuff you mention, plus a ton of other things.  Why re-invent the wheel if it's not necessary?

Why pay for a control and bloat your install?

I make *strange* charts that no-one else has even thought of!

For example one client was collecting profile information. We developed what we called the "string of pearls" graph. Imagine a polar plot like a radar display with 10 spokes and 10 concentric rings. The data was from 100 "on a scale of 1 to 10 ..." type questions in ten categories (each representing a spoke. To show the relative distribution of the answers we placed a circle (pearl) at the intersection of each spoke and ring. The diameter of the circle indicated the relative %age of the answers that were given that value. The color of the circle changed to indicate if it was within the mean or above/below the sigma. We also had lines for the mean and the +- sigma's. Show me a 3rd party control that can plot *that*.

If you learn how to draw you can create most anything you can imagine. You don't have to keep learning the limits of different controls. For me I can set up and plot data quickly because I already know how to do it.

M
>Why pay for a control and bloat your install?

Why pay -- reduce development time and leverage off other people's talent (hmmm, isn't that why EE is here, too?).

Bloat install -- hardly at all.  Maybe you haven't tried using some of these (GOOD) third-party controls.  If probably added less space than your code would -- seriously!

This isn't a contest -- almost all software design is a trade-off of some kind or other.

>I make *strange* charts that no-one >else has even thought of!

So do we.  You would be amazed at what modern controls can do.

>If you learn how to draw you can
>create most anything you can imagine.

One of the first things I did learn was how to draw (programmatically).  Again, why re-invent the wheel if it's not necessary?  With that kind of attitude, why do you use VB at all?  Seems like you would want to write in C++ or maybe even Assembler.
Oh I agree. Sometimes a 3rd party control is what is needed. But overall I like to keep things simple and not have to be dependent on other vendors. Graphing is simple enough to code that I don't feel the need to buy plot controls.

Yes, I do write in .ASM. In fact I've coded more .ASM than I've done VB and I've done a *LOT* of VB! (grin)

I onetime wrote a complete image processing/form layout language in .ASM. 23Kb and capable of capturing, enhancing, and printing images.

Talk about leveraging other peoples work. I'd developed a nice app that used the M$Chart control. Spent quite a bit of time getting it just right. Then I said "Now to print this masterpiece" and I discovered that M$Chart doesn't print. @!#$%^. Schedule deadline was approaching and now I have to rewrite from scratch because printing was a requirement. Ok, so now my three days of fiddling and learning the control is a total waste. I've got no time to surf the web and D/L an eval copy of a control and then learn how to program with that control and maybe find another *killer* problem like the M$Charts inability to print. I've got to ship on Monday and it's Friday and I can't ship the eval copy as it won't deploy unlicensed and I'm not going to spend $395 for a license for a control I don't even know will do everything I want, not to mention that there is no way I can get the license disk in time to make my shipment dead line...

To me it's wasteful to use a control that duplicates what I can code in a dozen lines. With my code based solution I don't have to be dependent on others. You ever have a product that's selling that uses some 3rd party control/equipment and have *them* go under? Then what do you do? You've based your product around theirs and theirs is no longer available. Now what? No. I prefer to go with my own coding where ever possible. Your shop, your rules.

Bottom line is whatever works is right. You want 3rd party controls, fine. Me, I get good results with my methods. Not issue of right or wrong.

M


is  GOAL.TEXT a textbox?
the line does not have a text property.
What am I missing

when I put a textbox named goal on the  form the program ran but no graph .
I noticed a little red line at the top corner of the right hand side of the picture box, so how do I set the points on the side to be labeled from 900-100
 and the bottom to be labeled from 0-30.
and the points to turn out correct.
Thanks
Yes, goal.text is a text box containing the limit line for the graph. That little red line is the goal.

You need to change the .scale property to your range. This example was running from zero to around 1400.

M
Am I changing the ScaleHeight, ScaleLeft, ScaleMode, ScaleTop or ScaleWidth
Thanks
None of the above. The .Scale sets all four at once.

M
Can you give me an example?
sure:

max = int(Val(Goal.Text) * 1.1)   'Set top of graph at goal line plus space for legend
'
' LASTDAY is number of data points to be plotted.
'
' Bring us up to full size
'
 Me.Width = Screen.Width
Me.Height = Screen.Height
Me.Show
Me.Refresh
'
' Graph1 is cumulative for month
'
   Graph1.Visible = False
Graph1.AutoRedraw = True
    Graph1.Height = 480 * Screen.TwipsPerPixelY
     Graph1.Width = 640 * Screen.TwipsPerPixelX
'
' The above sets the size of the .BMP file we're going to create from this with .SavePicture at the end
'
Graph1.BackColor = vbWhite
Graph1.Scale (-1, max * 1.1)-(LastDay + 2, -(max * 0.1))    'A little larger than plot area
Graph1.Visible = True


I will get back to you tomorrow, because it's time for me to leave work, and I am totally fed up of this graph.
Later
Adjusted points from 30 to 50
I am finally getting something, but is there a way to make the 6 points scatter across the size of the picturebox, it seems like the 1st point goes up and the second point is right next to it and all points are being plotted in an inch of space instead of 5 inches, so basically how do I set up the point on the bottom for the 1st plot to be at 5 minutes and the 2nd to be at point 10 minutes and so on up to 30 minutes across the bottom?

I am increasing the amount of points.

Thanks
GivenRandy
What is  TeeChart?
Change the Y scale.

Try the first example I gave. I know you don't want a barchart, but if you play with that one you'll get a feel for how to control things.

M
TeeChart is a commercial component that originated with Borland Builder (C++) but can be used with Visual Basic without any problems.  I think it cost something like $250, so I doubt that you want to do that.  It was well worth the cost for us ($250 is 2 hours worth of work for us -- you can probably appreciate the time savings!).

mark2150

give my code a try , it does 2 separate graphs, what am i doing wrong?


Private Sub Graph1_Click()
 Dim I
 
Graph1.Cls
Graph1.AutoRedraw = True
Graph1.BackColor = vbWhite
Graph1.Visible = True
Graph1.Scale (0, 110)-(130, 0) ' Set custom coordinate system.
  For I = 100 To 10 Step -10
        Graph1.Line (0, I)-(2, I)  ' Draw scale marks every 10 units.
        CurrentY = (CurrentY + 5000) '+ (Graph1.ScaleWidth - 9) ' Move cursor position.
     Print I ' Print scale mark value on left.
        Graph1.Line (ScaleWidth - 2, I)-(ScaleWidth, I)

       CurrentY = CurrentY + 5000   ' Move cursor position.
       CurrentX = Graph1.ScaleWidth - 9
     Print I ' Print scale mark value on right.
   Next I
   
 
   
   'last day changed to 6
 
                                   
Graph1.Line (10, 0)-(20, spd(0)), vbBlue
Graph1.Line (20, 0)-(30, spd(1)), vbBlue
Graph1.Line (30, 0)-(40, spd(2)), vbBlue
Graph1.Line (40, 0)-(50, spd(3)), vbBlue
Graph1.Line (50, 0)-(60, spd(4)), vbBlue
Graph1.Line (60, 0)-(70, spd(5)), vbBlue
Graph1.Line (70,0)-(80, spd(6)), vbBlue
Cumulative = 0
  Last_Cum = 0
 For ndx = 0 To 6 ' Step 10 'Day(Now)
 Cumulative = spd(ndx) 'cumulative + spd(ndx)
 Graph1.Line (ndx - 1, Last_Cum)-(ndx, Cumulative), vbBlue    'Draw cumulative line
    Last_Cum = Cumulative
   
 Next ndx
 
End Sub



The loop does one graph. the block of .line statements does another.

M
How do I change the following to expand across 5 inches instead of 1 inch, I need a longer graph.

For ndx = 0 To 6 ' Step 10 'Day(Now)
                     Cumulative = spd(ndx) 'cumulative + spd(ndx)
                     Graph1.Line (ndx - 1, Last_Cum)-(ndx, Cumulative), vbBlue    'Draw cumulative line
                        Last_Cum = Cumulative
                       
                     Next ndx
ASKER CERTIFIED SOLUTION
Avatar of mark2150
mark2150

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial