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.  

Please help ASAP.  THank you.

LVL 3
nchondroAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

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.

inthedarkCommented:
1)  Add a picture box to your form
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:~)


inthedarkCommented:
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

Your issues matter to us.

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

Start your 7-day free trial
inthedarkCommented:
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
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

inthedarkCommented:
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
nchondroAuthor 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.
inthedarkCommented:
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




inthedarkCommented:
You can also add affects like text shadow

' 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
inthedarkCommented:
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.
nchondroAuthor 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.