-
2 Attachment(s)
Charts controls with GDI+
It is a suite of user controls, to create statistical graphs. There are four controls but some have different styles, it could be said that they are the main and most used. Each user control is independent of the other, so it does not require implementing the entire suite, of course this does not make it more optimal in code reduction, but it is that habit of not depending on anything, there are many lines of code and surely there will be more of some bugs turning, for my part I think that my desire with this reached here, of course if someone finds an error or suggestion, please inform us to correct it.
In the download you will find an example of each one and a main project that includes all and some additions to simulate a Dashboard.
Attachment 178554
see more in http://leandroascierto.com/blog/charts-control-con-gdi
-
1 Attachment(s)
Re: Charts controls with GDI+
it's incredible.
I tested PerMonitorV2 at 175% Scale, The graphics are clean and Tool-tips are showing at right position (not the best position at below mouse pointer). Just the ClsResizer may have some problem.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
DaveDavis
it's incredible.
I tested PerMonitorV2 at 175% Scale, The graphics are clean and Tool-tips are showing at right position (not the best position at below mouse pointer). Just the ClsResizer may have some problem.
I don't understand your PerMonitorV2. For me the graphic is scaled like before. (comparing the graphic of your Form2 with the one of LeandroA)
-
Re: Charts controls with GDI+
very good work, it looks great.
as always very good contribution.
Greetings
-
Re: Charts controls with GDI+
You don't need ManageGDIToken function. Too bad this piece of LaVolpe's code got cargo-cult status.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
wqweto
You don't need ManageGDIToken function. Too bad this piece of LaVolpe's code got cargo-cult status.
It is already a habit, I always think about it again, perhaps as I never fail I continue to use it, in win XP it had more sense because if GDI + was not closed(Shutdown) the ide would fall, nowadays only with GdiplusStartup would be enough.
@DaveDavis DPI 175% and 225% it's a nice headache in vb
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
Krool
I don't understand your PerMonitorV2. For me the graphic is scaled like before. (comparing the graphic of your Form2 with the one of LeandroA)
Three charts at bottom are not showing entirely.
-
Re: Charts controls with GDI+
How to set different data in ucChartBar?
For example, one bar shows last year's data, and another bar shows this year's data.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
ChenLin
How to set different data in ucChartBar?
For example, one bar shows last year's data, and another bar shows this year's data.
look inside the ucCartBar folder there is an example of use, you must call the AddSerie function
-
Re: Charts controls with GDI+
Thank you LeandroA, I will continue testing.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
DaveDavis
Three charts at bottom are not showing entirely.
I did not mean that. The form (non-client) is automatically scaled by the OS. If the DPI changed the size and font and graphics needs to draw "bigger" or "smaller" as per current monitor. And that's not the case..
It would be better you do not use PerMonitorV2 and just use system DPI awareness. That's already a small challenge to properly handle that.
If you then move to another screen with DPI change let the OS bitmap stretch your Form. So it looks correctly sized though a bit blurry.. but better than nothing.
I propose you read LaVolpe tutorial: https://www.vbforums.com/showthread....eing-DPI-Aware
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
LeandroA
. . . in win XP it had more sense because if GDI + was not closed(Shutdown) the ide would fall
I'm constantly testing GDI+ code in VBIDE under XP in a VM and it never fails (GPF/AV) when gdiplus.dll is loaded only once w/ GdiplusStartup and never terminated.
I'm using something like this in user-controls Initialize event
Code:
If GetModuleHandle("gdiplus") = 0 Then
aInput(0) = 1
Call GdiplusStartup(0, aInput(0))
End If
Btw, how do you test for GDI+ leaks? I know how it can be done for GDI but for GDI+ it seems not possible, so code dealing with GDI+ handles has to be rock stable.
cheers,
</wqw>
-
Re: Charts controls with GDI+
About ucChartBar:
It would be great if the FillGradient property can set a gradient color.
If the AddSerie property does not use the current Collection, it will be more convenient to use the Recordset.
Can the LablesFormats property be set and not displayed? Now if it is not set, Labels will not be displayed at the same time.
Modify the FillOpacity attribute: avoid setting it to an invalid number exceeding 100:
Code:
Public Property Let FillOpacity(ByVal New_Value As Long)
m_FillOpacity = IIf(New_Value > 100, 100, New_Value)
PropertyChanged "FillOpacity"
Refresh
End Property
-
Re: Charts controls with GDI+
@wqweto I don't know if there is something similar in GDI +, I just beg not to forget to delete it
@chenLin I did not want to add a second color in the properties, you can change it if you wish, I will plant it in the following way, if color1 is alpha 100%, internally color2 is white alpha 100%, if color1 aplha is less than 100% color2 it is 100% transparent.
I am not very familiar with recorset, it is not much information that is loaded to a control so passing a recorset to a collection is not a lot of work, also a charts is not always used with databases
LablesFormats, I did not like what I did very much, I did not find a better way to do it without making it very extensive
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
wqweto
.....Btw, how do you test for GDI+ leaks? I know how it can be done for GDI but for GDI+ it seems not possible, so code dealing with GDI+ handles has to be rock stable.
cheers,
</wqw>
I've never had any leakage issues with GDI+. I just make sure to always dynamically delete objects & handles when done with them.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
SomeYguy
I've never had any leakage issues with GDI+. I just make sure to always dynamically delete objects & handles when done with them.
Is this machine translated? This is like advising not to worry and to always destroy GDI objects & handles and everything will be ok. Until it's not ok because for one reason or another you miss on destroying everything which is the point. . . Anyway.
Can you share with us how do you prevent leakage in GDI+? How do you detect it? Which perfmon counters do you use? Which API functions report outstanding handles or similar debug aides?
cheers,
</wqw>
-
1 Attachment(s)
Re: Charts controls with GDI+
Hello Leandro. I don't understand how in ucTreeMaps component, i can make rows of 'Buttons' with the same height and width. As I showed in the picture. Thank!
Attachment 178644
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
Visualman
Hello Leandro. I don't understand how in ucTreeMaps component, i can make rows of 'Buttons' with the same height and width. As I showed in the picture. Thank!
Attachment 178644
I do not recommend this control for that purpose, better use LabelPlus.ctl together with the ClsResizer module
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
wqweto
I'm constantly testing GDI+ code in VBIDE under XP in a VM and it never fails (GPF/AV) when gdiplus.dll is loaded only once w/ GdiplusStartup and never terminated.
Just FYI, back in the XP days (when that ManageGDIToken stuff was created), one could crash XP with GDI+ and not shutting it down. That was why the thunk was created. Since then, GDI+ has gone through some revisions and maybe the problem is no longer present? Don't know for sure. Within XP, these were the steps to cause a crash on-demand most times (others were able to reproduce this too). Otherwise, the crash was too intermittent to test. P.S. Don't ask me about the relationship between IE and VB at that time; it was just a pattern that was easy to reproduce.
Quote:
Start new project
1. On form Load, start GDI+. On Unload, stop GDI+
2. Run project
3. Click VB IDE's toolbar STOP button or execute an END statement
4. Open a new instance of Internet Explorer
5. Crash will occur within 5 seconds, if it is going to occur.
I can make some guesses though. GDI+ creates its own window (GDI+ Hook Window Class), we can find that. It is in same process as VB but in a different thread. That window hooks into GDIplus.dll possibly, or at least makes calls to it. When IDE is shut down, GDIplus may have been released (FreeLibrary) by VB. At some point that window made a call to dead code (freed memory) & crash. Maybe newer revisions increment ref count on the library & decrement when window is destroyed/process shuts down? Maybe the problem is still there, just don't know the conditions to trigger it.
One more follow-up. On Win10, I started GDI+ and did not shut it down, but closed the project in IDE. I set Spy++ on that GDI+ window. I went to work & 9+ hours later when I came home, the IDE was still alive and that GDI+ window had some system messages logged. It would appear, that somewhere along the road, that particular 'bug' in GDI+ may have been fixed; don't know when.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
DaveDavis
it's incredible.
I tested PerMonitorV2 at 175% Scale, The graphics are clean and Tool-tips are showing at right position (not the best position at below mouse pointer).
Just FYI and for any others, regarding PerMonitorV2 DPI-awareness. To properly test PerMonitorV2, one needs to change DPI while an app is running. Either change the DPI via system settings or drag to another monitor with a different DPI. When that happens, the app must rescale itself and all of its controls, while also changing control properties (as needed) for the new scale. Some controls are already DPI-aware and can change their own properties; while others/many aren't aware. Only at that point, after the scaling, can you determine how well the controls, and the app itself, are PerMonitor2 DPI-aware.
Should go without saying that PerMonitorV2 awareness requires subclassing and a lot of extra code. If interested, I have a project in the codebank to play with: https://www.vbforums.com/showthread....ness-Framework
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
wqweto
Is this machine translated? This is like advising not to worry and to always destroy GDI objects & handles and everything will be ok. Until it's not ok because for one reason or another you miss on destroying everything which is the point. . . Anyway.
Can you share with us how do you prevent leakage in GDI+? How do you detect it? Which perfmon counters do you use? Which API functions report outstanding handles or similar debug aides?
cheers,
</wqw>
Sorry so long to come back to this.
I have no concrete method of detecting leaks in GDI+, and I'm not sure that such a thing exists. When testing, I monitor memory & handle usage via Windows Task Manager and watch for excess usage and especially watch when my program terminates to make sure that used memory returns to prior values as much as possible.
I also make sure that I destroy/delete all GDI+ objects etc. directly when done with them, and at program termination if needed which is also where I shut down GDI+ for that application. My programs always start and shut down GDI+ once only. I made a simple reusable GDI+ start/shutdown module to make it simpler for my needs.
So those are the things which I do anyway, and it seems to work well so far. I'm honestly not aware of any other way.....
-
Re: Charts controls with GDI+
@LeandroA - These are excellent and very useful chart controls. Thank you very much! :)
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
SomeYguy
So those are the things which I do anyway, and it seems to work well so far. I'm honestly not aware of any other way.....
There is another way and that is the way C++ and C# wrappers are implemented. They just use RAII technique and never worry about leaking handles.
Anyway, monitoring GDI handles for GDI+ leakage makes no sense to me. Monitoring RAM usage has some merits as GDI+ allocator seems to be a "normal" one so its bitmaps are nothing more than large BLOBs in process space.
My point is that using GDI+ is *very* dangerous, even more dangerous than the notorious GDI as there is no way to catch, monitor and prevent leaks.
For instance the code in this thread has a lot of places where some leakage is suspected though just by looking at it I cannot tell if it leaks or when. For some snippets it look like it's possible to leak but whether the edge case is hit is not obvious and vice versa -- it might be leaking all the time and no one notices it.
cheers,
</wqw>
-
1 Attachment(s)
Re: Charts controls with GDI+
1. I tried to transfer the user control ucChartArea to a new project, and if property of uc is
LegendAlign = 0 - LA_TOP, then error occurs while form showing.
Attachment 180843
m_Serie is Nothing
2. The next question is how to do the reverse operation:
ucChartArea1.AddLineSeries
- delete a any of one serie? or, remove all series?
-
1 Attachment(s)
Re: Charts controls with GDI+
LeandroA - First let me say I'm very impressed with these controls! The appearance and features are just what I was looking for as I'm updating a program I wrote and wanted to replace the old chart control that came with VB6.
I'm having an issue with the Area and Pie chart controls crashing (completely closing the program without any error message). The form has three chart controls on it and updates each of them every two to five seconds or so. I have it doing a .clear before updating the data each time for each of the controls and they pretty much always crash if the mouse is moved over (or left on top of) one of the controls but will also crash when the mouse is not. I've tested removing the ShowToolTips sub and the program will run longer (without that feature) but still crashes after a while.
I've added a timer to your demo and then copied the coding from the load sub into the timer sub and added a .clear before it updates. I've set the timer to be quick so you can see how it crashes however you can change the timer it will just take longer to crash. If you run the attached demo and move your mouse around on top of the graph it should happen (try moving your mouse around in a circle over the graph while the graph keeps updating).
Any help would be greatly appreciated!
-
Re: Charts controls with GDI+
Crikey - superb gauges! I really want to do mine now in VB6.
With regard to GDI+ leaking, I'd love to see a separate thread on that. My program is leaking like a sieve with only one hole, ie. slow but sure.
-
1 Attachment(s)
Re: Charts controls with GDI+
I did some more testing and this time it did produce an error instead of crashing. Here is a picture of the error and the location of the error.Attachment 186010
-
Re: Charts controls with GDI+
I fix your problem
In user control ucPieChart, change one line in Sub Clear:
ReDim m_Item(0)
So you delete Preserve
So the hpath is 0 in item 0. So new hpath produced
And now your program run fine
Also you can comment three lines in Timer1 in form1, to use the styles without resetting each 100ms
'Me.cboLabelsPositions.ListIndex = 0
'Me.CboLegendAlign.ListIndex = 0
'Me.CboStyle.ListIndex = 0
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
georgekar
I fix your problem
In user control ucPieChart, change one line in Sub Clear:
ReDim m_Item(0)
So you delete Preserve
So the hpath is 0 in item 0. So new hpath produced
And now your program run fine
Also you can comment three lines in Timer1 in form1, to use the styles without resetting each 100ms
'Me.cboLabelsPositions.ListIndex = 0
'Me.CboLegendAlign.ListIndex = 0
'Me.CboStyle.ListIndex = 0
Indeed you did! Thank you!!!
-
Re: Charts controls with GDI+
These look super cool!
I'm trying to slowly integrate these into my app, but I can't seem to find a .Clear or .Reset in order to flush the uc back to nothing and then insert new data into it.
I'm starting with the ucChartArea control.
Thanks!
-
Re: Charts controls with GDI+
Looks like Leandro missed it for ucChartArea (though ucPieChart, ucChartBar, and ucTreeMaps all have a Clear method). You can add this to the ucChartArea class:
Code:
Public Sub Clear()
SerieCount = 0
ReDim Preserve m_Serie(0)
Me.Refresh
End Sub
-
Re: Charts controls with GDI+
Hello, I don't think I updated the file here, it was already corrected from my blog, the function would be something similar to the one that jpbro put, only that you should call .refresh if you really need it.
Code:
Public Sub Clear()
ReDim m_Serie(0)
SerieCount = 0
Set cAxisItem = New Collection
End Sub
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
LeandroA
Hello, I don't think I updated the file here, it was already corrected from my blog, the function would be something similar to the one that jpbro put, only that you should call .refresh if you really need it.
Code:
Public Sub Clear()
ReDim m_Serie(0)
SerieCount = 0
Set cAxisItem = New Collection
End Sub
Got it!
I went ahead and left the me.Refresh, as I don't when I would/wouldn't need it. My app shows the graph, then while refreshing data, creates another (new) graph for the changed data.
Can you point me to where the Latest version is kept? I have found a few more bugs, namely:
1. in Draw:
Case LA_BOTTOM, LA_TOP (I had changed mine to use LA_TOP)
With LabelsRect
If SerieCount > 0 Then 'i added this IF to make sure there is data before running the next statement
.Height = m_Serie(0).TextHeight + PT16 / 2 'm_Serie(0) doesn't exist if there's NO DATA yet!
2. in Draw:
change this:
If cAxisItem.Count Then
AxisDistance = (mWidth - mPenWidth) / (cAxisItem.Count - 1)
End If
to this, because I ran into cAxisItem.Count=1, which results in Div by Zero!
If cAxisItem.Count <> 1 Then
AxisDistance = (mWidth - mPenWidth) / (cAxisItem.Count - 1)
Else
AxisDistance = (mWidth - mPenWidth)
End If
3. in Draw, *just below* where #2 is, I inserted another IF because I ran into another Div by Zero:
after this line:
If SerieCount > 0 Then
insert this IF:
If m_Serie(0).Values.Count <> 1 Then
PtDistance = (mWidth - mPenWidth) / (m_Serie(0).Values.Count - 1) 'original line -- Div by Zero if .Count=1
4. in ShowToolTips:
after this line:
For i = 0 To SerieCount - 1
insert this line:
If i <= UBound(m_Serie) And ((mHotBar + 1) <= m_Serie(i).Values.Count) Then
I believe I had to do this because there were more Values in some of the data sets, and as I was moving the mouse over to see data points Tips, there wasn't data that far out to the left.
5. in ShowToolTips:
BEFORE this line:
sText = Left(sText, Len(sText) - 2)
add this line, so we don't end up taking LEFT with ZERO length:
If Len(sText) - 2 > 0 Then
6. in ShowToolTips:
after this line:
With RectF
add this IF to wrap .Left and .Top statements to make sure data is there, before we use it:
If UBound(m_Serie(IndexMax).PT) >= mHotBar Then
.Left = m_Serie(IndexMax).PT(mHotBar).x - SZ.Width / 2
.Top = m_Serie(IndexMax).PT(mHotBar).Y - SZ.Height - 10 * nScale - TM
End If
-
Re: Charts controls with GDI+
Hi
A little fix to ucChartArea.ctl:
Code:
Public Property Get LegendVisible() As Boolean
LegendVisible = m_LegendVisible
End Property
Public Property Let LegendVisible(ByVal New_Value As Boolean)
m_LegendVisible = New_Value
PropertyChanged "LegendVisible"
Refresh
End Property
Public Property Get AxisXVisible() As Boolean
AxisXVisible = m_AxisXVisible
End Property
Public Property Let AxisXVisible(ByVal New_Value As Boolean)
m_AxisXVisible = New_Value
PropertyChanged "AxisXVisible"
Refresh
End Property
Public Property Get AxisYVisible() As Boolean
AxisYVisible = m_AxisYVisible
End Property
Public Property Let AxisYVisible(ByVal New_Value As Boolean)
m_AxisYVisible = New_Value
PropertyChanged "AxisYVisible"
Refresh
End Property
It has all the functions ready to work but the propierties are not public so they can't be used. With that code all works ok.
-
Re: Charts controls with GDI+
with all these fixes, can the OP update the origonal zip file to include the updates. tks
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
k_zeon
with all these fixes, can the OP update the origonal zip file to include the updates. tks
Eu pagaria por esta ferramenta, gostaria muito que todos os bugs fossem resolvidos e as funcionalidades fossem ampliadas. A melhor ferramenta do mercado até agora.
Gostaria de receber atualizações também
-
Re: Charts controls with GDI+
Hello Leandro & Team,
Many thanks for these user controls and many other pieces of information you have shared over the time in this forum.
I have a challenge with the ucChartBar. I need to display departments by their initials in X-axis and the employee count in the Y-axis for both the Males and Females using the bar chart. Allow me to attach both the code and the data to be analyzed by the graph here. The issue I have is that the code stops in the function GetMax() of the ucChartBar with error "Object is no longer valid". Can you assist me go past this error and display the graph.
Below is the code
Private Sub DisplayGenderGraph()
Dim VALUEX As Collection
Dim VALUEY As Collection
Dim CustomColors As Collection
Dim i As Long, j As Long
Dim Min As Single
Dim Max As Single
Dim Palette() As String
Dim strDEPTINITIAL() As String
'Display Employee Count by Gender per Department
ucChartBar1.Clear
'determine unique departments
myString = "SELECT TOP (100) PERCENT DEPARTMENT AS DEPARTMENTQ, DEP_INITIAL " _
& "FROM DEPARTMENT " _
& "WHERE (DEPT_ACTIVE = 1) " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rsTemp.RecordCount > 0 Then
intX = rsTemp.RecordCount
strX = "'"
Set VALUEX = New Collection
For i = 0 To intX - 1
'VALUEX.Add rsTemp!DEP_INITIAL
strX = strX & rsTemp!DEP_INITIAL & "','"
If rsTemp.EOF = False Then rsTemp.MoveNext Else Exit For
Next
strX = Left(strX, Len(strX) - 2)
strDEPTINITIAL = Split(strX, ",")
For i = 0 To UBound(strDEPTINITIAL)
VALUEX.Add strDEPTINITIAL(i)
Next i
ucChartBar1.AddAxisItems VALUEX, False, 0, 1
End If
Palette = Split("&H004744E3, &H003DB0EF, &H00ABA56C, &H0048BDBF, &H004D91F4, &H007450, &H0050C187, &HC0C0FF, &HFFFFC0, &H80FFFF, &HFF8D11, &HA744E0, &H376CE6, &H40AB1A, &H7B006B, &H400000, &H404080, &H80C0FF, &HC0C0C0, &HFF00FF, &HC0FFC0, &H8080FF, &H80&", ",")
'Determine unique genders
myString = "SELECT DISTINCT GENDER AS GENDERM FROM PERSONNEL_MASTER ORDER BY GENDER"
If rs.State = adStateOpen Then rs.Close
rs.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rs.RecordCount > 0 Then
For i = 1 To rs.RecordCount
NameX = rs!GENDERM
myString = "SELECT TOP (100) PERCENT DEPARTMENT, GENDER, EMPCOUNT, PERIOD, PYEAR, DEP_INITIAL " _
& "FROM EMPLOYEE_COUNT_GENDER_TEMP " _
& "WHERE (GENDER = '" & rs!GENDERM & "') " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
Set VALUEY = New Collection
For j = 0 To intX - 1
VALUEY.Add rsTemp!EMPCOUNT
rsTemp.MoveNext
Next
ucChartBar1.AddSerie NameX, CLng(Palette(i)), VALUEY
rs.MoveNext
Next i
End If
End Sub
Below is the data (Sorry I dont know how to attach excel file here but these are 6 columns and 16 rows with data while top row is row header.
DEPARTMENT GENDER EMPCOUNT PERIOD PYEAR DEP_INITIAL
ADMINISTRATION FEMALE 20 2 2025 ADMIN
ADMINISTRATION MALE 26 2 2025 ADMIN
BREEDING FEMALE 38 2 2025 BRDNG
BREEDING MALE 8 2 2025 BRDNG
COMMERCIAL ROOTING FEMALE 99 2 2025 CMRTG
COMMERCIAL ROOTING MALE 33 2 2025 CMRTG
LOGISTICS FEMALE 108 2 2025 LGSTC
LOGISTICS MALE 75 2 2025 LGSTC
NAKURU FEMALE 1 2 2025 NKURU
NAKURU MALE 1 2 2025 NKURU
PRODUCTION EE FEMALE 120 2 2025 PRDEE
PRODUCTION EE MALE 66 2 2025 PRDEE
QUALITY CHECKERS FEMALE 35 2 2025 QLTCH
QUALITY CHECKERS MALE 6 2 2025 QLTCH
REDHILL FEMALE 1 2 2025 RDHLL
REDHILL MALE 2 2 2025 RDHLL
Attached is the error displayed and the point of error in the GetMax function.
Attachment 194515
Attachment 194514
-
Re: Charts controls with GDI+
Wrap the code in the code tags so we can read it properly, and secondly, place the images on imgur, and post the image links instead. The image function is not working on the forum.
-
Re: Charts controls with GDI+
-
Re: Charts controls with GDI+
Hello Yereverluvinuncleber ,
Thanks for the guidance.
I have a challenge with the ucChartBar. I need to display departments by their initials in X-axis and the employee count in the Y-axis for both the Males and Females using the bar chart. Allow me to attach both the code and the data to be analyzed by the graph here. The issue I have is that the code stops in the function GetMax() of the ucChartBar with error "Object is no longer valid". Can you assist me go past this error and display the graph.
Below is the code
Code:
Private Sub DisplayGenderGraph()
Dim VALUEX As Collection
Dim VALUEY As Collection
Dim CustomColors As Collection
Dim i As Long, j As Long
Dim Min As Single
Dim Max As Single
Dim Palette() As String
Dim strDEPTINITIAL() As String
'Display Employee Count by Gender per Department
ucChartBar1.Clear
'determine unique departments - This will go to X-axis
myString = "SELECT TOP (100) PERCENT DEPARTMENT AS DEPARTMENTQ, DEP_INITIAL " _
& "FROM DEPARTMENT " _
& "WHERE (DEPT_ACTIVE = 1) " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rsTemp.RecordCount > 0 Then
intX = rsTemp.RecordCount
strX = "'"
Set VALUEX = New Collection
For i = 0 To intX - 1
'VALUEX.Add rsTemp!DEP_INITIAL
strX = strX & rsTemp!DEP_INITIAL & "','"
If rsTemp.EOF = False Then rsTemp.MoveNext Else Exit For
Next
strX = Left(strX, Len(strX) - 2)
strDEPTINITIAL = Split(strX, ",")
For i = 0 To UBound(strDEPTINITIAL)
VALUEX.Add strDEPTINITIAL(i)
Next i
ucChartBar1.AddAxisItems VALUEX, False, 0, 1
End If
Palette = Split("&H004744E3, &H003DB0EF, &H00ABA56C, &H0048BDBF, &H004D91F4, &H007450, &H0050C187, &HC0C0FF, &HFFFFC0, &H80FFFF, &HFF8D11, &HA744E0, &H376CE6, &H40AB1A, &H7B006B, &H400000, &H404080, &H80C0FF, &HC0C0C0, &HFF00FF, &HC0FFC0, &H8080FF, &H80&", ",")
'Determine unique genders - This will go to Y axis and it is for both genders - First round its female then second round its male
myString = "SELECT DISTINCT GENDER AS GENDERM FROM PERSONNEL_MASTER ORDER BY GENDER"
If rs.State = adStateOpen Then rs.Close
rs.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rs.RecordCount > 0 Then
For i = 1 To rs.RecordCount
NameX = rs!GENDERM
myString = "SELECT TOP (100) PERCENT DEPARTMENT, GENDER, EMPCOUNT, PERIOD, PYEAR, DEP_INITIAL " _
& "FROM EMPLOYEE_COUNT_GENDER_TEMP " _
& "WHERE (GENDER = '" & rs!GENDERM & "') " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
Set VALUEY = New Collection
For j = 0 To intX - 1
VALUEY.Add rsTemp!EMPCOUNT
rsTemp.MoveNext
Next
ucChartBar1.AddSerie NameX, CLng(Palette(i)), VALUEY
rs.MoveNext
Next i
End If
End Sub
Error generated can be seen here: https://imgur.com/l0tiKyn
Point where error occurs in the user control code: https://imgur.com/SCMlXG9
Data to be displayed in the ucChartBar https://imgur.com/y0ehIkQ
I will really appreciate your support on this.
Regards,
Nicholas.
-
Re: Charts controls with GDI+
If you add image tags around the image links they will display inline. [ I M G ] and [ / I M G ] without the spaces, of course. You will need the full name from imgur ie. https://imgur.com/y0ehIkQ.gif
https://www.vbforums.com/images/ieimages/2025/04/1.gif
-
Re: Charts controls with GDI+
Hello Yereverluvinuncleber ,
Thanks for the guidance.
I have a challenge with the ucChartBar. I need to display departments by their initials in X-axis and the employee count in the Y-axis for both the Males and Females using the bar chart. Allow me to attach both the code and the data to be analyzed by the graph here. The issue I have is that the code stops in the function GetMax() of the ucChartBar with error "Object is no longer valid". Can you assist me go past this error and display the graph.
Below is the code
Code:
Private Sub DisplayGenderGraph()
Dim VALUEX As Collection
Dim VALUEY As Collection
Dim CustomColors As Collection
Dim i As Long, j As Long
Dim Min As Single
Dim Max As Single
Dim Palette() As String
Dim strDEPTINITIAL() As String
'Display Employee Count by Gender per Department
ucChartBar1.Clear
'determine unique departments
myString = "SELECT TOP (100) PERCENT DEPARTMENT AS DEPARTMENTQ, DEP_INITIAL " _
& "FROM DEPARTMENT " _
& "WHERE (DEPT_ACTIVE = 1) " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rsTemp.RecordCount > 0 Then
intX = rsTemp.RecordCount
strX = "'"
Set VALUEX = New Collection
For i = 0 To intX - 1
'VALUEX.Add rsTemp!DEP_INITIAL
strX = strX & rsTemp!DEP_INITIAL & "','"
If rsTemp.EOF = False Then rsTemp.MoveNext Else Exit For
Next
strX = Left(strX, Len(strX) - 2)
strDEPTINITIAL = Split(strX, ",")
For i = 0 To UBound(strDEPTINITIAL)
VALUEX.Add strDEPTINITIAL(i)
Next i
ucChartBar1.AddAxisItems VALUEX, False, 0, 1
End If
Palette = Split("&H004744E3, &H003DB0EF, &H00ABA56C, &H0048BDBF, &H004D91F4, &H007450, &H0050C187, &HC0C0FF, &HFFFFC0, &H80FFFF, &HFF8D11, &HA744E0, &H376CE6, &H40AB1A, &H7B006B, &H400000, &H404080, &H80C0FF, &HC0C0C0, &HFF00FF, &HC0FFC0, &H8080FF, &H80&", ",")
'Determine unique genders
myString = "SELECT DISTINCT GENDER AS GENDERM FROM PERSONNEL_MASTER ORDER BY GENDER"
If rs.State = adStateOpen Then rs.Close
rs.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rs.RecordCount > 0 Then
For i = 1 To rs.RecordCount
NameX = rs!GENDERM
myString = "SELECT TOP (100) PERCENT DEPARTMENT, GENDER, EMPCOUNT, PERIOD, PYEAR, DEP_INITIAL " _
& "FROM EMPLOYEE_COUNT_GENDER_TEMP " _
& "WHERE (GENDER = '" & rs!GENDERM & "') " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
Set VALUEY = New Collection
For j = 0 To intX - 1
VALUEY.Add rsTemp!EMPCOUNT
rsTemp.MoveNext
Next
ucChartBar1.AddSerie NameX, CLng(Palette(i)), VALUEY
rs.MoveNext
Next i
End If
End Sub
Error generated can be seen here:
https://imgur.com/l0tiKyn
Point where error occurs in the user control code:
https://imgur.com/SCMlXG9
Data to be displayed in the ucChartBar
https://imgur.com/y0ehIkQ
I will really appreciate your support on this. I hope I have gotten it right now
Regards,
Nicholas.
-
Re: Charts controls with GDI+
Quote:
Originally Posted by
NOkello2002
Hello Yereverluvinuncleber ,
Thanks for the guidance.
I have a challenge with the ucChartBar. I need to display departments by their initials in X-axis and the employee count in the Y-axis for both the Males and Females using the bar chart. Allow me to attach both the code and the data to be analyzed by the graph here. The issue I have is that the code stops in the function GetMax() of the ucChartBar with error "Object is no longer valid". Can you assist me go past this error and display the graph.
Below is the code
Code:
Private Sub DisplayGenderGraph()
Dim VALUEX As Collection
Dim VALUEY As Collection
Dim CustomColors As Collection
Dim i As Long, j As Long
Dim Min As Single
Dim Max As Single
Dim Palette() As String
Dim strDEPTINITIAL() As String
'Display Employee Count by Gender per Department
ucChartBar1.Clear
'determine unique departments
myString = "SELECT TOP (100) PERCENT DEPARTMENT AS DEPARTMENTQ, DEP_INITIAL " _
& "FROM DEPARTMENT " _
& "WHERE (DEPT_ACTIVE = 1) " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rsTemp.RecordCount > 0 Then
intX = rsTemp.RecordCount
strX = "'"
Set VALUEX = New Collection
For i = 0 To intX - 1
'VALUEX.Add rsTemp!DEP_INITIAL
strX = strX & rsTemp!DEP_INITIAL & "','"
If rsTemp.EOF = False Then rsTemp.MoveNext Else Exit For
Next
strX = Left(strX, Len(strX) - 2)
strDEPTINITIAL = Split(strX, ",")
For i = 0 To UBound(strDEPTINITIAL)
VALUEX.Add strDEPTINITIAL(i)
Next i
ucChartBar1.AddAxisItems VALUEX, False, 0, 1
End If
Palette = Split("&H004744E3, &H003DB0EF, &H00ABA56C, &H0048BDBF, &H004D91F4, &H007450, &H0050C187, &HC0C0FF, &HFFFFC0, &H80FFFF, &HFF8D11, &HA744E0, &H376CE6, &H40AB1A, &H7B006B, &H400000, &H404080, &H80C0FF, &HC0C0C0, &HFF00FF, &HC0FFC0, &H8080FF, &H80&", ",")
'Determine unique genders
myString = "SELECT DISTINCT GENDER AS GENDERM FROM PERSONNEL_MASTER ORDER BY GENDER"
If rs.State = adStateOpen Then rs.Close
rs.Open myString, Maincn, adOpenKeyset, adLockOptimistic
If rs.RecordCount > 0 Then
For i = 1 To rs.RecordCount
NameX = rs!GENDERM
myString = "SELECT TOP (100) PERCENT DEPARTMENT, GENDER, EMPCOUNT, PERIOD, PYEAR, DEP_INITIAL " _
& "FROM EMPLOYEE_COUNT_GENDER_TEMP " _
& "WHERE (GENDER = '" & rs!GENDERM & "') " _
& "ORDER BY DEP_INITIAL"
If rsTemp.State = adStateOpen Then rsTemp.Close
rsTemp.Open myString, Maincn, adOpenKeyset, adLockOptimistic
Set VALUEY = New Collection
For j = 0 To intX - 1
VALUEY.Add rsTemp!EMPCOUNT
rsTemp.MoveNext
Next
ucChartBar1.AddSerie NameX, CLng(Palette(i)), VALUEY
rs.MoveNext
Next i
End If
End Sub
Error generated can be seen here:
https://www.vbforums.com/images/ieimages/2025/04/1.jpg
Point where error occurs in the user control code:
https://www.vbforums.com/images/ieimages/2025/04/1.jpg
Data to be displayed in the ucChartBar
https://www.vbforums.com/images/ieimages/2025/04/1.jpg
I will really appreciate your support on this. I hope I have gotten it right now
Regards,
Nicholas.
Hi
I did some mods to the control since I also had problems with it but don't know if it would fix your problem. Please do a simpler example without using database (just adding some data manually) and I'll try to run you code with my modified control.
Regards