Solved

# Plot Graph from Textbox

Posted on 2003-12-11
532 Views
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.

0
Question by:nchondro
• 7
• 2

LVL 17

Expert Comment

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:~)

0

LVL 17

Accepted Solution

inthedark earned 500 total points
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
0

LVL 17

Assisted Solution

inthedark earned 500 total points
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
0

LVL 17

Assisted Solution

inthedark earned 500 total points
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
0

LVL 3

Author Comment

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

LVL 17

Assisted Solution

inthedark earned 500 total points
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

0

LVL 17

Assisted Solution

inthedark earned 500 total points

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

LVL 17

Assisted Solution

inthedark earned 500 total points
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.
0

LVL 3

Author Comment

Thanks a lot for the help. You've been very helpful  You're the best.  :)
0

## Featured Post

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
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 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…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…