Solved

# plotting a graph

Posted on 2000-05-16
1,161 Views
How do you plot a graph inside of a picture box, instead of using MSChart?
0
Question by:Cruisin18
• 15
• 13
• 9
• +1

LVL 9

Expert Comment

ID: 2814356
MSChart1.EditCopy
Picture1.Picture = Clipboard.GetData
0

LVL 9

Expert Comment

ID: 2814362
p.s., you can make the MSChart hidden, but perform all of your actions there, then do the copy-and-paste mentioned above.
0

Author Comment

ID: 2814528
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?
0

LVL 9

Expert Comment

ID: 2814574
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.
0

LVL 9

Expert Comment

ID: 2814585
If it's not too much work, you can send me your equation and what you would like.  <GivenRandy@aol.com>
0

LVL 3

Expert Comment

ID: 2817425
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.
0

Author Comment

ID: 2818040
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
0

LVL 12

Expert Comment

ID: 2818146
There are much simpler approaches to this!

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

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
0

Author Comment

ID: 2818272
Yes please send me some samples, and the points are yours.

Thanks
0

LVL 3

Expert Comment

ID: 2818293
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
0

LVL 12

Expert Comment

ID: 2818387
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
0

LVL 9

Expert Comment

ID: 2818438
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!
0

Author Comment

ID: 2818492
Would about a line graph, and not a bar chart?
0

LVL 12

Expert Comment

ID: 2818533
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
0

LVL 9

Expert Comment

ID: 2818617
>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.

0

LVL 12

Expert Comment

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

M
0

Author Comment

ID: 2821003
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?
0

LVL 12

Expert Comment

ID: 2821081
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
0

LVL 9

Expert Comment

ID: 2821502
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?

0

LVL 12

Expert Comment

ID: 2821572
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
0

LVL 9

Expert Comment

ID: 2821839
>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.
0

LVL 12

Expert Comment

ID: 2821938
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
0

Author Comment

ID: 2822561

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 .
0

Author Comment

ID: 2822610
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
0

LVL 12

Expert Comment

ID: 2822638
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
0

Author Comment

ID: 2822697
Am I changing the ScaleHeight, ScaleLeft, ScaleMode, ScaleTop or ScaleWidth
Thanks
0

LVL 12

Expert Comment

ID: 2822743
None of the above. The .Scale sets all four at once.

M
0

Author Comment

ID: 2822767
Can you give me an example?
0

LVL 12

Expert Comment

ID: 2822834
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

0

Author Comment

ID: 2822862
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
0

Author Comment

ID: 2825436
Adjusted points from 30 to 50
0

Author Comment

ID: 2825437
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
0

Author Comment

ID: 2825468
GivenRandy
What is  TeeChart?
0

LVL 12

Expert Comment

ID: 2825511
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
0

LVL 9

Expert Comment

ID: 2825763
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!).
0

Author Comment

ID: 2826213

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

0

LVL 12

Expert Comment

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

M
0

Author Comment

ID: 2826596
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
0

LVL 12

Accepted Solution

mark2150 earned 50 total points
ID: 2826784
Your x scale is too small. You can either change the .scale statement or multiply the ndx-1 and ndx terms by 10x or so.

Graph1.Scale (0, 110)-(130, 0)

This gives a range in x from 0-130 and in Y from 110-0. Your loop index is from 0 to 6. This will put your graph cramped to the left edge. If you multiply the value by say 20 then your X range will be 0 - 120.

Graph1.Line ((ndx - 1) * 20, Last_Cum)-(ndx * 20, Cumulative), vbBlue

You could leave the above statement alone and change the .scale statement to (0, 110)-(7, 0) and this will do the same thing.

M
0

## Featured Post

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture. Â  There is also a companion Debug Toolbar that looks like the followinâ€¦
Enums (shorthand for â€˜enumerationsâ€™) are not often used by programmers but they can be quite valuable when they are. Â What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that containsâ€¦
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applicâ€¦
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process fromâ€¦