# Plot Graph from Textbox

How to plot a graph from a multiple data set that was available from a textbox.  The dataset is separated by line.

I have this serial port program that read the data which is display on a text box.  The displayed data show records separated by line in a text box.  I need to use that data to plot a graph.

LVL 3
###### Who is Participating?

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Commented:
Say called picGraph
change the properties so that AutoRedraw is True
change the scalemode to pixels

2) Add some code to convert the text to values:

Dim sLines() as String
sLines = Split(text1, vbcrlf) ' split all lines into an array

' move the text array into a value array
ReDim Values(Ubound(sLines)) As Single

dim lc as long
dim MaxValue  as Single
For Lc = 0 to Ubound(sLines)
Values(lc) = csng(sLines(lc))
If Values(lc)>MaxValue Then
MaxValue = Values(lc) ' knowing the max value may be a help
End If
Next

3) Plot the points

' Uplift the max value
Maxvalue = MaxValue * 1.1

' Set some margins
TopGap = 100
BottomGap = 100
LeftGap = 100
RightGap = 100
AvailableHeight = picGraph.ScaleHeight - TopGap - BottomGap
BaseLine = AvailableHeight + TopGap
PlotWidth = (picGraph.ScaleWidth - LeftGap - RightGap)/(Ubound(values)-2)
For lc = 0 To Ubound(Values)-1
X1 = lc * PlotWidth
Y1 = BaseLine - (AvailableHeight * Values(lc)/MaxValue)
X2 = (lc+1) * PlotWidth
Y2 = BaseLine - (AvailableHeight * Values(lc+1)/MaxValue)
picGraph.Line (x1,y1)-(x2,y2), rgb(0,0,255)
Next Lc

And thats it.

I hope the above code works without too much debugging.
Declare all values as singles except those already declared
X1,x2,y1,y2 should be longs.

Hope this helps:~)

Commented:
Here is the code with a few tweaks:

Private Sub Command1_Click()
Dim sLines() As String
sLines = Split(Text1, vbCrLf) ' split all lines into an array

' move the text array into a value array
ReDim Values(UBound(sLines)) As Single

Dim lc As Long
Dim MaxValue  As Single

Do
If Len(sLines(UBound(sLines))) = 0 Then
ReDim Preserve sLines(UBound(sLines) - 1)
Else
Exit Do
End If
Loop

For lc = 0 To UBound(sLines)
Values(lc) = CSng(sLines(lc))
If Values(lc) > MaxValue Then
MaxValue = Values(lc) ' knowing the max value may be a help
End If
Next

Dim TopGap As Single
Dim BottomGap  As Single
Dim LeftGap  As Single
Dim RightGap  As Single

Dim AvailableHeight As Single
Dim BaseLine As Single
Dim PlotWidth As Single

' Uplift the max value
MaxValue = MaxValue * 1.1

Dim X1 As Long
Dim X2 As Long
Dim y1 As Long
Dim y2 As Long

' Set some margins
TopGap = 100
BottomGap = 100
LeftGap = 100
RightGap = 100
AvailableHeight = picGraph.ScaleHeight - TopGap - BottomGap
BaseLine = AvailableHeight + TopGap
PlotWidth = (picGraph.ScaleWidth - LeftGap - RightGap) / (UBound(Values))
For lc = 0 To UBound(Values) - 1
X1 = lc * PlotWidth + LeftGap
y1 = BaseLine - (AvailableHeight * Values(lc) / MaxValue)
X2 = (lc + 1) * PlotWidth + LeftGap
y2 = BaseLine - (AvailableHeight * Values(lc + 1) / MaxValue)
picGraph.Line (X1, y1)-(X2, y2), RGB(0, 0, 255)
Next lc

End Sub

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Commented:
After you print the graph you can add the following for cometic affect

' box round graph
picGraph.Line (LeftGap, TopGap)-Step(picGraph.ScaleWidth - LeftGap - RightGap, AvailableHeight), RGB(255, 0, 0), B
Dim hscale As Single

' draw hlines
hscale = MaxValue * 0.1
Do While hscale < MaxValue
y1 = BaseLine - (AvailableHeight * hscale / MaxValue)
picGraph.Line (LeftGap + 1, y1)-(picGraph.ScaleWidth - RightGap - 1, y1), RGB(0, 255, 0)
hscale = hscale + MaxValue * 0.1
Loop
Commented:
if you want some spots.....

For lc = 0 To UBound(Values) - 1
X1 = lc * PlotWidth + LeftGap
y1 = BaseLine - (AvailableHeight * Values(lc) / MaxValue)
X2 = (lc + 1) * PlotWidth + LeftGap
y2 = BaseLine - (AvailableHeight * Values(lc + 1) / MaxValue)
picGraph.Line (X1, y1)-(X2, y2), RGB(0, 0, 255)
picGraph.Circle (X1, y1), 2, RGB(100, 100, 0) 'add this line
Next lc
picGraph.Circle (X2, y2), 2, RGB(100, 100, 0) ' and this
Author Commented:
Thanks for the code, but how can I add additional cosmetic such as the X-Bar title, Y-Bar title, plus their range.  Plus a way so I can change the default starting point instead of 0 but other number.  Currently, I saw that the graph kinda crunch small in the middle can we make it bigger?

Thanks a lot.
Commented:
Hi nchondro, I knew you would ask these questions which is why I added margins.

In the code you can see how the program scans for the highest value, you can do the same for the lowest value.

In your case you are probably doing some kind of QA on a device so you know then max and min values that you are expecting. So it would be better to set them manually.

Private Sub Command1_Click()

Dim sLines() As String
sLines = Split(Text1, vbCrLf) ' split all lines into an array

' move the text array into a value array

Dim lc As Long
Dim MaxValue  As Single
Dim MinValue As Single

Do
If Len(sLines(UBound(sLines))) = 0 Then
ReDim Preserve sLines(UBound(sLines) - 1)
Else
Exit Do
End If
Loop

ReDim Values(UBound(sLines)) As Single ' this was moved

MinValue = 9999999999#
For lc = 0 To UBound(sLines)
Values(lc) = CSng(sLines(lc))
If Values(lc) > MaxValue Then
MaxValue = Values(lc) ' knowing the max value may be a help
End If
If Values(lc) < MinValue Then
MinValue = Values(lc)
End If
Next

Dim TopGap As Single
Dim BottomGap  As Single
Dim LeftGap  As Single
Dim RightGap  As Single

Dim AvailableHeight As Single
Dim BaseLine As Single
Dim PlotWidth As Single

' Uplift the max value
MaxValue = MaxValue * 1.1

' drop then minvalue
MinValue = MinValue * 0.9

' Or set the max/min value manually
MaxValue = 100
MinValue = 50

Dim Range As Single

Range = MaxValue - MinValue

Dim X1 As Long
Dim X2 As Long
Dim y1 As Long
Dim y2 As Long

' Set some margins
TopGap = 30
BottomGap = 25
LeftGap = 35
RightGap = 10

AvailableHeight = picGraph.ScaleHeight - TopGap - BottomGap
BaseLine = AvailableHeight + TopGap
PlotWidth = (picGraph.ScaleWidth - LeftGap - RightGap) / (UBound(Values))

For lc = 0 To UBound(Values) - 1
X1 = lc * PlotWidth + LeftGap
y1 = BaseLine - (AvailableHeight * (Values(lc) - MinValue) / Range)
X2 = (lc + 1) * PlotWidth + LeftGap
y2 = BaseLine - (AvailableHeight * (Values(lc + 1) - MinValue) / Range)
picGraph.Line (X1, y1)-(X2, y2), RGB(0, 0, 255)
picGraph.Circle (X1, y1), 2, RGB(100, 100, 0) 'add this line
Next lc

picGraph.Circle (X2, y2), 2, RGB(100, 100, 0) ' and this
' box round graph
picGraph.Line (LeftGap, TopGap)-Step(picGraph.ScaleWidth - LeftGap - RightGap, AvailableHeight), RGB(255, 0, 0), B
Dim hscale As Single

' draw hlines

Dim ScaleIncrement As Single

ScaleIncrement = MaxValue * 0.1

' or set a manual increment
ScaleIncrement = 10

hscale = MinValue + ScaleIncrement
picGraph.ForeColor = RGB(0, 0, 0)
Dim sText As String
For hscale = MinValue To MaxValue Step ScaleIncrement

y1 = BaseLine - (AvailableHeight * (hscale - MinValue) / Range)

' minvalue is the bottom of the graph
' maxvalue is the top og graph
' so we don't need mim & max just the lines between

If hscale > MinValue And hscale < MaxValue Then
picGraph.Line (LeftGap + 1, y1)-(picGraph.ScaleWidth - RightGap - 1, y1), RGB(0, 255, 0)
End If

sText = CStr(hscale)
picGraph.CurrentY = y1 - (picGraph.TextHeight(sText) * 0.5)
picGraph.CurrentX = LeftGap - picGraph.TextWidth(sText) - 2 ' reduce by a small gap
picGraph.Print sText;
Next

' Now do a title
sText = "Time vs Value"
picGraph.CurrentX = (picGraph.ScaleWidth * 0.5) - (picGraph.TextWidth(sText) * 0.5)
picGraph.CurrentY = 2
picGraph.Print sText;

' x Comment
sText = "Time"
picGraph.CurrentX = (picGraph.ScaleWidth * 0.5) - (picGraph.TextWidth(sText) * 0.5)
picGraph.CurrentY = picGraph.ScaleHeight - picGraph.TextHeight(sText)
picGraph.Print sText;

' y Comment
sText = "Values"
Dim ypos As Long

ypos = picGraph.ScaleHeight * 0.5 - (picGraph.TextHeight(sText) * Len(sText) * 0.5)
For lc = 1 To Len(sText)
picGraph.CurrentX = 2
picGraph.CurrentY = ypos
picGraph.Print Mid(sText, lc, 1);
ypos = ypos + picGraph.TextHeight(Mid(sText, lc, 1))
Next

End Sub

Commented:

' Now do a title
dim StoreSize as single

storesize=picGraph.font.size

picGraph.Font.Size = 18 ' increate font size
sText = "Time vs Value"
Dim lx As Long
Dim ly As Long
lx = (picGraph.ScaleWidth * 0.5) - (picGraph.TextWidth(sText) * 0.5) + 2
ly = 2
picGraph.ForeColor = RGB(5, 5, 10)
picGraph.CurrentX = lx + 2 ' movedown a bit
picGraph.CurrentY = ly + 2
picGraph.Print sText;

picGraph.ForeColor = RGB(0, 0, 255)
picGraph.CurrentX = lx
picGraph.CurrentY = ly
picGraph.Print sText;

picGraph.font.size = storesize
Commented:
Autoscaling.......

If you don't know what type of data you are getting then after you calculate min/max values you can autoscale like this:

sText = CStr(MinValue)
If Len(sText) > 1 Then
sText = Left(sText, 1) + String(Len(sText) - 1, "0")
MinValue = Val(sText)
End If

sText = CStr(MaxValue)
If Len(sText) > 1 Then
sText = CStr(Val(Left(sText, 1)) + 1) + String(Len(sText) - 1, "0")
MaxValue = Val(sText)
End If

Range = MaxValue - MinValue
ScaleIncrement = Int(Range / 10) ' /5 for smaller graphs or /20 for very large graphs

Another tip, if your device provides small decimal values then convert all of the points by dividing them by the minimum value. The graph should look the same.
Author Commented:
Thanks a lot for the help. You've been very helpful  You're the best.  :)
###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.