Results 1 to 22 of 22

Thread: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Just a little Demo, how to work with the new RC6.cChart-Class (requiring an RC6-version >= 6.0.3).

    This Class follows a somewhat different pattern, compared to other Chart-Controls -
    because it supports a "virtual concept" which:
    - doesn't define the Chart-behaviour (or Type) as much via Properties
    - but via OwnerDraw-Events instead

    To "catch" these Events (to draw your own "ChartType"):
    - you have to define your own Class (per ChartType)
    - and in this Class, you will receive the OwnerDraw-Events

    Example for such a UserDefined CharType-Class
    (taken from the zipped example below, responsible for rendering the chart at the right-hand-side of the following ScreenShot):
    Code:
    Option Explicit
    
    Public WithEvents Chart As cChart
    
    Private Sub Class_Initialize()
      Set Chart = New_c.Chart
    End Sub
     
    '**** Class-specific Implementation of the Chart-Events *****
    Private Sub Chart_DrawChartBackGroundAndTitle(CC As cCairoContext, ByVal Title As String)
      CC.Paint 1, Cairo.CreateSolidPatternLng(vbWhite)
      CC.SelectFont "Times New Roman", 13, &H222222, True, True
      CC.DrawText 0, 0, CC.Surface.Width, 50, Title, True, vbCenter, 3, True
    End Sub
     
    Private Sub Chart_OverrideAxisProps(Axis As cChartAxis, ByVal CurrentMin As Double, ByVal CurrentMax As Double, ByVal CurrentTickIntervals As Long)
      If Axis.Name = "X" Then Axis.TickIntervals = 10
    End Sub
    
    Private Sub Chart_DrawSingleTickForAxis(Axis As cChartAxis, CC As cCairoContext, ByVal TickValue, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long)
      Select Case UCase$(Axis.Name)
        Case "X"
          CC.DrawLine x, y, x, y + dy + 4, True, 1, vbRed, 0.5
          Axis.DrawTickText CC, x, y + 6, Format$(TickValue, "0.00")
        Case "Y"
          CC.DrawLine x - 4, y, x + dx, y, True, 1, vbBlue, 0.5
          Axis.DrawTickText CC, x - 4, y, Format$(TickValue, "0.00")
      End Select
    End Sub
     
    Private Sub Chart_DrawData(CC As cCairoContext, DataArr() As Variant, ByVal dx As Long, ByVal dy As Long)
      Dim PolyArr As cArrayList
      Set PolyArr = Chart.GetAxisScaledPolyArrXY(DataArr, Chart.AxisCol("X"), Chart.AxisCol("Y"))
     
      CC.SetLineWidth 2
      CC.PolygonPtr PolyArr.DataPtr, PolyArr.Count \ 2, False, splNormal, True, True
      CC.Stroke , Cairo.CreateSolidPatternLng(vbGreen)
    End Sub
    Here a ScreenShot:


    Here is the zipped Demo-Code, which produced the above output:
    ChartPlot.zip

    Have fun,

    Olaf
    Last edited by Schmidt; Feb 18th, 2021 at 05:49 PM.

  2. #2
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    Espaņa
    Posts
    290

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    hi olaf very good example as always.
    but I have a problem

    cChart typed not defined

    missing a class or something, I tried it with rc5 and rc6

    a greeting

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by yokesee View Post
    hi olaf very good example as always.
    but I have a problem

    cChart typed not defined

    missing a class or something, I tried it with rc5 and rc6
    Ahh, sorry - should have mentioned that the cChart-Class is a new addition
    (requiring RC6-version >= 6.0.3 - please download again from the website).

    My original plan was, to have "all the additionally planned enhancements" in the RC6 "finished by now" -
    but (as always) I'm lagging behind my own optimistic planning...

    As it is currently, I'll probably need another month or two, until the remaining RC6 enhancements will be "included, according to plan".

    HTH

    Olaf

  4. #4
    Addicted Member
    Join Date
    Jul 2016
    Posts
    220

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Hi Schmidt

    As I am stuck with RC5 due to required Windows XP compatibility, do you have any code examples showing how to draw a chart *with axes* using RC5? Alternatively, an example using some JS charting lib with RC5, as you hinted here, if such a thing is possible. DC.js looks amazing.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by OldClock View Post
    As I am stuck with RC5 due to required Windows XP compatibility, do you have any code examples showing how to draw a chart *with axes* using RC5?
    Have no problem, to post the code of the two RC6-charting-classes here, since they are "small enough" -
    and the principle was basically shown in this RC5-Demo already: https://www.vbforums.com/showthread....for-x-y-Plots)

    cChart.cls:
    Code:
    Option Explicit
    
    Public Event DrawChartBackGroundAndTitle(CC As cCairoContext, ByVal Title As String)
    Public Event DrawChartAreaRect(CC As cCairoContext, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long)
    Public Event OverrideAxisProps(Axis As cChartAxis, ByVal CurrentMin As Double, ByVal CurrentMax As Double, ByVal CurrentTickIntervals As Long)
    Public Event DrawSingleTickForAxis(Axis As cChartAxis, CC As cCairoContext, ByVal TickValue, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long)
    Public Event DrawData(CC As cCairoContext, DataArr(), ByVal dx As Long, ByVal dy As Long)
    
    Public OffsT&, OffsL&, OffsB&, OffsR& 'Offsets of the ChartArea within the Render-Surface
    Public AxisCol As New Collection, CC As cCairoContext, dx&, dy&
    
    Private Sub Class_Initialize() 'init of Default-Properties
      AddAxis "X", 0: AddAxis "Y", 1                 'add our two default-Axis-Objects
      OffsT = 60: OffsL = 50: OffsB = 50: OffsR = 30 'set the default offsets of the chart-area
    End Sub
    
    Public Function AddAxis(Name, DataColIdx) As cChartAxis
      Set AddAxis = New cChartAxis
          AddAxis.Init Name, DataColIdx
      AxisCol.Add AddAxis, Name
    End Function
    
    Public Function Render(DataArr(), WPxl, HPxl, Optional Title$) As cCairoSurface
      Set CC = Cairo.CreateSurface(WPxl, HPxl).CreateContext
      RaiseEvent DrawChartBackGroundAndTitle(CC, Title)
    
      dx = WPxl - OffsL - OffsR: dy = HPxl - OffsT - OffsB
      CC.SetLineWidth 1
      RaiseEvent DrawChartAreaRect(CC, OffsL, OffsT, dx + 1, dy + 1)
      CC.SelectFont "Arial", 9, &H222222
      
      Dim Axis As cChartAxis
      For Each Axis In AxisCol
        Axis.CalcMinMaxAndTickDist Me, DataArr, dx, dy
      Next
      
      CC.TranslateDrawings OffsL - AxisCol("X").MinPxl, (HPxl - OffsB) + AxisCol("Y").MinPxl
      CC.ScaleDrawings 1, -1
      RaiseEvent DrawData(CC, DataArr, dx, dy)
      
      Set Render = CC.Surface
    End Function
     
    Public Sub MouseCoordsToChartCoords(ByVal MouseXPxl As Long, ByVal MouseYPxl As Long, xPxlChart, yPxlChart, xDataValue, yDataValue)
      xPxlChart = MouseXPxl - OffsL
      yPxlChart = CC.Surface.Height - MouseYPxl - OffsB
      xDataValue = AxisCol("X").Min + xPxlChart / AxisCol("X").PxlScaleFac
      yDataValue = AxisCol("Y").Min + yPxlChart / AxisCol("Y").PxlScaleFac
    End Sub
    
    Public Function GetAxisScaledPolyArrXY(DataArr(), xAxis As cChartAxis, yAxis As cChartAxis) As cArrayList
      Set GetAxisScaledPolyArrXY = New cArrayList
          GetAxisScaledPolyArrXY.Init vbDouble
      Dim i As Long
      For i = 0 To UBound(DataArr, 2)
          GetAxisScaledPolyArrXY.Add DataArr(xAxis.DataColIdx, i) * xAxis.PxlScaleFac 'x-Values at even ...
          GetAxisScaledPolyArrXY.Add DataArr(yAxis.DataColIdx, i) * yAxis.PxlScaleFac 'y-Values at odd indexes
      Next
    End Function
    
    Friend Sub RaiseTickDrawingEvent(Axis As cChartAxis, ByVal TickValue, ByVal x&, ByVal y&)
      RaiseEvent DrawSingleTickForAxis(Axis, CC, TickValue, x, y, Axis.ChartDX, Axis.ChartDY)
    End Sub
    
    Friend Sub RaiseOverrideAxisPropsEvent(Axis As cChartAxis)
      RaiseEvent OverrideAxisProps(Axis, Axis.Min, Axis.Max, Axis.TickIntervals)
    End Sub
    cChartAxis.cls:
    Code:
    Option Explicit
    
    Const Eps# = 0.0000000000001
    
    Public Name$, DataColIdx&, TickIntervals&, Min#, Max#, IsNonNumeric As Boolean
    Public TickDist#, MinPxl&, MaxPxl&, TickDistPxl&, PxlScaleFac#, ChartDX&, ChartDY&
     
    Friend Sub Init(Name, DataColIdx)
      Me.Name = Name
      Me.DataColIdx = DataColIdx
    End Sub
    
    Public Sub CalcMinMaxAndTickDist(Chart As cChart, DataArr(), ByVal dx&, ByVal dy&)
      Dim MaxVal#, MinVal#, TickVal#, x#, y#
      If UBound(DataArr(), 1) >= 0 Then
        GetMinMaxFromData DataArr, MinVal, MaxVal
        
        If Abs(MaxVal - MinVal) = 0 Then
          TickDist = Eps: Min = MinVal - Eps / 2: Max = MaxVal + Eps / 2
        Else
          TickDist = 10 ^ Int(Log(Abs(MaxVal - MinVal)) / Log(10)) * Sgn(MaxVal - MinVal)
          
          CalcBounds MinVal, MaxVal, 1
          If Int((Max - Min) / TickDist) > 10 Then TickDist = CalcBounds(MinVal, MaxVal, 2)
          If Int((Max - Min) / TickDist) < 5 Then TickDist = CalcBounds(MinVal, MaxVal, 0.5)
          If Int((Max - Min) / TickDist) < 5 Then TickDist = CalcBounds(MinVal, MaxVal, 0.5)
        End If
        
        ChartDX = dx: ChartDY = dy
          
        On Error Resume Next
          TickIntervals = 1
          TickIntervals = Int((Max - Min) / TickDist)
        On Error GoTo 0
        Chart.RaiseOverrideAxisPropsEvent Me
        If TickIntervals > 0 Then TickDist = (Max - Min) / TickIntervals
     
        PxlScaleFac = IIf(Left$(UCase$(Name), 1) = "X", dx / (Max - Min), dy / (Max - Min))
        MinPxl = Min * PxlScaleFac
        MaxPxl = Max * PxlScaleFac
        TickDistPxl = TickDist * PxlScaleFac
        
        For TickVal = Min To Max + TickDist / 2 Step TickDist
          If Left$(UCase$(Name), 1) = "X" Then
            x = Chart.OffsL + (TickVal - Min) * PxlScaleFac
            If IsNonNumeric And CLng(TickVal) <= UBound(DataArr, 2) Then
              Chart.RaiseTickDrawingEvent Me, IIf(DataArr(0, TickVal), DataArr(0, TickVal), TickVal + 1), x + TickDistPxl / 2, dy
            Else
              Chart.RaiseTickDrawingEvent Me, TickVal, x, Chart.OffsT
            End If
          Else
            y = Chart.OffsT + dy - (TickVal - Min) * PxlScaleFac
            Chart.RaiseTickDrawingEvent Me, TickVal, Chart.OffsL, y
          End If
        Next
      End If
    End Sub
    
    Public Sub DrawTickText(CC As cCairoContext, ByVal x#, ByVal y#, ByVal S As String, Optional ByVal Rot90 As Boolean)
      CC.Save
        Dim dx, dy, Alignment As AlignmentConstants
        If UCase$(Name) = "X" Then
          dx = IIf(Rot90, CC.Surface.Height - y - ChartDY, TickDistPxl)
          dy = IIf(Rot90, TickDistPxl, CC.Surface.Height - y - ChartDY)
          CC.TranslateDrawings x - TickDistPxl / 2, IIf(Rot90, CC.Surface.Height, y + ChartDY)
          Alignment = IIf(Rot90, vbRightJustify, vbCenter)
        ElseIf x < ChartDX / 2 Then
          dx = x
          dy = TickDistPxl
          CC.TranslateDrawings 0, y - dy / 2
          Alignment = vbRightJustify
        Else
          dx = CC.Surface.Width - x
          dy = TickDistPxl
          CC.TranslateDrawings x, y - dy / 2
          Alignment = vbLeftJustify
        End If
        If Rot90 Then CC.RotateDrawingsDeg -90
        CC.DrawText 0, 0, dx, dy, S, True, Alignment, 2, IIf(UCase$(Name) = "X" And Not Rot90, 0, 1)
      CC.Restore
    End Sub
    
    Private Sub GetMinMaxFromData(DataArr(), Min, Max)
      If DataColIdx = 0 Then
         Select Case VarType(DataArr(0, UBound(DataArr, 2)))
           Case vbLong, vbInteger, vbByte, vbDouble, vbSingle, vbCurrency, vbDate
           Case Else: Min = 0: Max = UBound(DataArr, 2) + 1: IsNonNumeric = True: Exit Sub
         End Select
      End If
      Min = 1E+35: Max = 1E-35
      Dim i As Long
      For i = 0 To UBound(DataArr, 2)
        If Min > DataArr(DataColIdx, i) Then Min = DataArr(DataColIdx, i)
        If Max < DataArr(DataColIdx, i) Then Max = DataArr(DataColIdx, i)
      Next
    End Sub
    
    Private Function CalcBounds(MinVal As Double, MaxVal As Double, StepFac As Double) As Double
      CalcBounds = TickDist * StepFac
      Min = (Int((MinVal + Eps) / CalcBounds)) * CalcBounds
      Max = (Int((MaxVal - Eps) / CalcBounds) + 1) * CalcBounds
    End Function
    So, if you:
    - include the above two Classes with the correct names into the Project of the Demo-Zip (see the opener-posting)
    - then change the project-reference from RC6 to vbRichClient5
    - and replace all occurences of New_c.Chart with: New cChart
    ... then the Demo should work "as before" - but now in RC5-Mode instead.

    HTH

    Olaf
    Last edited by Schmidt; Aug 16th, 2021 at 09:50 AM.

  6. #6
    Addicted Member
    Join Date
    Jul 2016
    Posts
    220

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Fantastic, thank you Schmidt. The demo worked correctly following your instructions in XP using RC5.0.80.

  7. #7
    Addicted Member
    Join Date
    Jul 2016
    Posts
    220

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    I've been studying the code for days but there are a few things I'm still trying to solve and would appreciate help. Well I think I can solve the other things on my own, but this one thing I'm stuck at.

    I'm trying to be able to plot several series on one chart, each one having a unique color (pass color as parameter).

    I see you added support for axes X, Y and a second Y on the right. But what if instead of that one wants to plot several series on the same X and Y? Like in this sketch.

    Name:  chart_mockup3.png
Views: 275
Size:  25.0 KB

    The data set is a time series with several variables, each measured once a month over 24 months. I store it in a recordset, where the first column (0) represents the month number (x axis, 0-24), and the remaining columns are the measured variables (y axis).

    The best I managed to get is this. I don't think it's done properly, as I don't understand all of your code, and I don't know why the x axis goes up to 100 when it should only go up to 24 - clearly I broke something.

    Name:  screenshot_20210826_170716_a.jpg
Views: 272
Size:  22.9 KB

    Could you help?

    P.S. If I went the wrong direction, feel free to ignore my way and do it completely your way.
    Attached Files Attached Files

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by OldClock View Post
    Could you help?

    P.S. If I went the wrong direction, feel free to ignore my way and do it completely your way.
    Using your Demo-Zip above...

    1) First, restore the code-content of cChart and cChartAxis to exactly what was posted in #5.

    2) In your cTimePlot.cls, please replace:

    2.1) The AxisOverride-Event with the following:
    Code:
    Private Sub Chart_OverrideAxisProps(Axis As cChartAxis, ByVal CurrentMin As Double, ByVal CurrentMax As Double, ByVal CurrentTickIntervals As Long)
      Select Case Left$(UCase$(Axis.Name), 1)
            Case "X" 'use the defaults
    
            Case "Y" 'we cannot use the automatic here, because Axis-Y gets its values from ColIdx=1 (which has constant values of 1)
                Axis.Min = 40
                Axis.Max = 100
                Axis.TickIntervals = 6
      End Select
    End Sub
    2.2) And the DrawData-Event should be replaced with this:
    Code:
    Private Sub Chart_DrawData(CC As cCairoContext, DataArr() As Variant, ByVal dx As Long, ByVal dy As Long)
        Dim j As Long
        For j = 5 To 11
            Chart.AxisCol("Y").DataColIdx = j '<- that's the thing which was missing
            
            Dim PolyArr As cArrayList
            Set PolyArr = Chart.GetAxisScaledPolyArrXY(DataArr, Chart.AxisCol("X"), Chart.AxisCol("Y"))
    
            CC.SetLineWidth 2
            CC.PolygonPtr PolyArr.DataPtr, PolyArr.Count \ 2, False, splNone, True, True
            CC.Stroke , Cairo.CreateSolidPatternLng(QBColor(j + 3)) 'I've simply choosen QBColor, to vary the Line-Colors a bit
            
            Dim i As Long
            For i = 0 To PolyArr.Count - 1 Step 2
               'CC.DrawRegularPolygon PolyArr(i + 0), PolyArr(i + 1), 9, 6, splSmall, 2.5
               'CC.ClosePath
               CC.Ellipse PolyArr(i + 0), PolyArr(i + 1), 7, 7, False
               CC.Stroke , Cairo.CreateSolidPatternLng(vbBlack, 0.7)
            Next
        Next
    End Sub
    HTH

    Olaf

  9. #9
    Addicted Member
    Join Date
    Jul 2016
    Posts
    220

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Thank you Schmidt, that works perfectly.

  10. #10
    Addicted Member sergeos's Avatar
    Join Date
    Apr 2009
    Location
    Belarus
    Posts
    145

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    What is the RC6.cChart-Class?
    Where did we can download it?
    Ten Years After - 01 You Give Me Loving

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by sergeos View Post
    What is the RC6.cChart-Class?
    Where did we can download it?
    The RC6 (as well as the older vbRichClient5-downloads) are available on vbRichClient.com.

    Besides, the code of the cChart (along with a second companion-class), was posted in #5.

    HTH

    Olaf

  12. #12
    Addicted Member sergeos's Avatar
    Join Date
    Apr 2009
    Location
    Belarus
    Posts
    145

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Does your plotting mechanism can draw lines with different lengths and not always beginning from zero point?
    As for example it can be done by an excel.
    Ten Years After - 01 You Give Me Loving

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by sergeos View Post
    Does your plotting mechanism can draw lines with different lengths and not always beginning from zero point?
    As for example it can be done by an excel.
    Yes, because everything you Draw (Axes, Ticks, Titles), is your own responsibility ...
    done using your own code, which has to be placed within one of the Events, raised by the cChart-Class.

    That's the reason, these two Charting-Classes are that small - but they take away from you all
    the Axis- Ticks- and Scaling-calculations - feeding the Events with nicely prepared Arguments -
    to ease your efforts whilst "filling out these Events with CC.Drawing-calls"

    Post #8 (point 2.2) has an example, what kind of code is placed in the (final) cChart_DrawData-event.

    Here is the Events Signature:
    Chart_DrawData(CC As cCairoContext, DataArr() As Variant, ByVal dx As Long, ByVal dy As Long)

    - 1st argument: CC (followed by a typed dot) will pop-up all kind of drawing-methods you can use
    - 2nd argument DataArr is the same 2D-Variant-Array, you've put into the initial cChart.Render-call.
    - dx and dy specify the avalable witdth and height of the current "inner Charting-area" (inside the Axes).

    In the Demo-Examples, I've used the CC.Polygon rendering-call (a "one-liner"), to draw lines -
    but you can do "your own thing" using plain CC.MoveTo, CC.LineTo calls as well
    (leaving out as many "cells" from the Data in DataArr() as you want, whilst looping over a certain Column)

    Also "Bars instead of Lines" (vertically or horizontally) would be easily doable -
    it's entirely up to you, how you interpret (and render) the content of the DataArr() you've earlier passed in.

    Olaf

  14. #14
    New Member
    Join Date
    May 2021
    Posts
    12

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Dear Olaf, I tested your sample code and modified it to create a graph as attch. image. there is a problem when I use CC.drawtext or other related method to output a text string. the text was mirrored by horizontal line, why? please help. thanks.Attachment 182272

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by JT870 View Post
    Dear Olaf, I tested your sample code and modified it to create a graph as attch. image. there is a problem when I use CC.drawtext or other related method to output a text string. the text was mirrored by horizontal line, why? please help. thanks.Attachment 182272
    Can't see your attachment...

    But the last raised Event (Chart_DrawData), is using a "mirrored, bottom-up Coord-Sys"...
    (Cairos default CoordSys is like the one in normal VB-Drawing-Commands, "top-down").

    Please render your "free Text" either in one of the earlier Events (as e.g. Chart_DrawChartAreaRect),
    or just use the return-type of the Chart.Render-method (a cCairoSurface), to draw your text afterwards:
    Code:
      Dim Srf As cCairoSurface
      Set Srf = MyChartPlot.Chart.Render(..., ...)
      With Srf.CreateContext
         .DrawText ..., ...
      End With
      Set MyPictureBox.Picture = Srf.Picture
    HTH

    Olaf

  16. #16
    New Member
    Join Date
    May 2021
    Posts
    12

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Many thanks Olaf, It is the mirrored . bottom-up coord-sys which caused the output text string reverse sideup-down. I'm tring to find a way to relocate the text string. The follwing 2 codes should be changed.
    CC.TranslateDrawings OffsL - AxisCol("X").MinPxl, (HPxl - OffsB) + AxisCol("Y").MinPxl
    CC.ScaleDrawings 1, -1

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,611

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Quote Originally Posted by JT870 View Post
    Many thanks Olaf, It is the mirrored . bottom-up coord-sys which caused the output text string reverse sideup-down. I'm tring to find a way to relocate the text string. The follwing 2 codes should be changed.
    CC.TranslateDrawings OffsL - AxisCol("X").MinPxl, (HPxl - OffsB) + AxisCol("Y").MinPxl
    CC.ScaleDrawings 1, -1
    Well, if you want to handle everything within the Chart_DrawData-Event,
    then you should first draw all Lines and "Pointmarkers" (still using the reversed coordsys) -
    and then - before you exit the EventHandler-function - you could do:

    '... all your Line and PointData-Drawings

    CC.MatrixResetToIdentity
    '... now draw all your text, using the normal "unscaled, unflipped" coordsys
    End Sub

    For better help, you should post your current Test-Project as a Zip.

    HTH

    Olaf

  18. #18
    New Member
    Join Date
    May 2021
    Posts
    12

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Thanks. You give a good solution here and I'll try it later, well I fond another way to close the bottom-up coord sys by setting : CC.ScaleDrawings 1, 1, then using a length value (for example -30) to sub the location height of the text string. but I'm not sure if it is stable for every data case. The attach. zip is problem codes.
    Attached Files Attached Files

  19. #19
    New Member
    Join Date
    May 2021
    Posts
    12

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    The modified VBP as attch. below
    Name:  Test.jpg
Views: 144
Size:  29.4 KB
    Name:  test2.jpg
Views: 145
Size:  33.0 KB
    Attached Files Attached Files
    Last edited by JT870; Sep 8th, 2021 at 12:21 PM.

  20. #20
    Addicted Member
    Join Date
    Jul 2016
    Posts
    220

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    Hey Schmidt, I have spent several hours troubleshooting an issue, learning things in the process, but haven't found a clean solution yet.

    1. I do a one-time conversion of many CSV files to an SQLite DB. These CSV files vary in the number of rows and columns, but all data is Numeric in SQLite affinity terms:

    Code:
    Private Function getRsFromCSVString(ByVal sCSV As String, ByVal sql As String, Optional ByVal hasHeader As Boolean) As cRecordset
        With New_c.memDb
            .Exec "CREATE VIRTUAL TABLE temp.t USING csv(header=" & IIf(hasHeader, 1, 0) & ", data='" & Replace(sCSV, "'", "''") & "')"
            Set getRsFromCSVString = .GetRs(sql)
        End With
    End Function
    The problem is that all data ends up being stored as TEXT, e.g.:

    Code:
    Debug.Print memDb.Cnn.DataBases("main").Tables(tName).SQLForCreate
    Code:
    CREATE TABLE [foo] ([Week] TEXT,[L] TEXT,[M] TEXT,[S] TEXT,[1st] TEXT,[3rd] TEXT,[5th] TEXT,[15th] TEXT,[25th] TEXT,[50th] TEXT,[75th] TEXT,[85th] TEXT,[95th] TEXT,[97th] TEXT,[99th] TEXT)
    How do I get the DB to store the data as numeric?
    The full code is here: https://www.vbforums.com/showthread....=1#post5536136

    This seems to indicate that "CREATE VIRTUAL TABLE t USING csv" will always result in TEXT affinity:
    https://sqlite.org/forum/forumpost/1d13ef71b2?raw

    2. Because SQLite ends up storing all data as TEXT, this Case always ends up in the Else condition, and never establishes the min correctly:
    Code:
         Select Case VarType(DataArr(0, UBound(DataArr, 2)))
           Case vbLong, vbInteger, vbByte, vbDouble, vbSingle, vbCurrency, vbDate
           Case Else: Min = 0: Max = UBound(DataArr, 2) + 1: IsNonNumeric = True: Exit Sub
         End Select
    If I change that to:

    Code:
            If Not IsNumeric(DataArr(0, UBound(DataArr, 2))) Then
                min = 0
                max = UBound(DataArr, 2) + 1
                isNonNumeric = True
                Exit Sub
            End If
    then the program crashes with an overflow in CalcMinMaxAndTickDist() as tickVal = 1.1E+35

    Code:
    If isNonNumeric And CLng(tickVal) <= UBound(DataArr, 2) Then
    This seems to be because this part is not behaving as it should:
    Quote Originally Posted by Schmidt View Post
    Code:
    Private Sub GetMinMaxFromData(DataArr(), Min, Max)
      If DataColIdx = 0 Then
         Select Case VarType(DataArr(0, UBound(DataArr, 2)))
           Case vbLong, vbInteger, vbByte, vbDouble, vbSingle, vbCurrency, vbDate
           Case Else: Min = 0: Max = UBound(DataArr, 2) + 1: IsNonNumeric = True: Exit Sub
         End Select
      End If
      Min = 1E+35: Max = 1E-35
      Dim i As Long
      For i = 0 To UBound(DataArr, 2)
        If Min > DataArr(DataColIdx, i) Then Min = DataArr(DataColIdx, i)
        If Max < DataArr(DataColIdx, i) Then Max = DataArr(DataColIdx, i)
      Next
    End Sub
    For instance, DataArr(dataColIdx, i) = 0. So:

    Code:
    If min > DataArr(dataColIdx, i) Then min = DataArr(dataColIdx, i)
    If 1E+35 > 0 Then min = 0
    except that the "Then" condition doesn't run! How can 1E+35 not be more than 0?

    Edit: After hours of searching I found the cause: DataArr(DataColIdx, i) is not 0, it's "0"! String.

    So this takes me back to the first question: how do I batch convert CSV files (first row is header, then numeric data, and column count varies per file) to a file-based SQLite DB so that all data is stored as Numeric?
    Or how can I make 'memDb.GetRs("SELECT * FROM foo").GetRows' return numbers as numeric type and not string? Sure I could create a new double-type array and copy data using CDBL(), but that's patching a problem and not fixing it at the source.

    Thank you
    Last edited by OldClock; Sep 20th, 2021 at 12:23 PM.

  21. #21
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,838

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    @OldClock - your question should be in it's own thread, but I think you have a couple of options:

    Use the "schema" parameter of the SQLite CSV virtual table to specify all columns as numeric. Something like this:

    Code:
    .Exec "CREATE VIRTUAL TABLE temp.t USING csv(header=" & IIf(HasHeader, 1, 0) & ", data='" & Replace(sCSV, "'", "''") & "', schema='CREATE TABLE t (Week NUMERIC, L NUMERIC, M NUMERIC, S NUMERIC, ""-3 SD"" NUMERIC, ""-2 SD"" NUMERIC, ""-1 SD"" NUMERIC, ""0 SD"" NUMERIC, ""1 SD"" NUMERIC, ""2 SD"" NUMERIC, ""3 SD"" INTEGER)')"
    OR you can cast all of your fields to NUMERIC when performing your select statement:

    Code:
    SELECT CAST(Week AS NUMERIC), CAST(L AS NUMERIC), etc...
    Olaf might have something better up his sleeve though (as he often does).

  22. #22
    Addicted Member
    Join Date
    Jul 2016
    Posts
    220

    Re: VB6 2D-ChartPlotting (using the RC6.cChart HelperClass)

    This started off as a bug report about GetMinMaxFromData until I realized what was happening regarding the data type, so I agree - admins feel free to move posts #20-#22 to e.g. https://www.vbforums.com/showthread....-file-based-DB

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width