I just created a simple but configurable stacked bar graph, το cover a specific need.
The code is not very elegant but covers my need.
If it is useful to someone it can use it freely.
Best regards.
Thanos
Updated, 03/01/2019
v 1.1 :: Small changes to draw the data series, if it is desirable
Code: Select all
;##-<< Simple Stacked Bar Graph >>-#######################################################
;{
;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;# Author: Athanasios I. Douros
;# Version: 1.0, 02/01/2019
;# Changes: 1.1, 03/01/2019. Small changes to draw the data series, if it is desirable
;# Purpose: Show stacked bars
;# Restrictions: Free to use, no restrictions.
;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;}
;##-<< Simple Stacked Bar Graph >>-#######################################################
EnableExplicit
DeclareModule StackedBarChart
EnableExplicit
#STACKBAR_CHART_WIDTH = 1200
#STACKBAR_CHART_HEIGHT = 700
#DRAW_BAR_AT_POS = 150
#LEGEND_HEIGHT = 15
#BAR_HEIGHT = 65
#DISTANCE_BETWEEN_BARS = 10
#DISTANCE_BETWEEN_LABELS = 2
#AXIS_WIDTH = 100
Structure Delay
Header.s
Value_1.d
Value_2.d
Value_3.d
Value_4.d
Value_5.d
Value_6.d
Value_7.d
Value_8.d
List DataSeries.d()
EndStructure
Declare StackedBarShow(sTitle.s, List Values.Delay(), List Labels.s(), DrawDataSeries = #True)
EndDeclareModule
Module StackedBarChart
Procedure Max(Value1, Value2)
If (Value1 >= Value2)
ProcedureReturn Value1
Else
ProcedureReturn Value2
EndIf
EndProcedure
Procedure StackedBarsCalcPercentages(List Values.Delay())
Protected dSum.d
ForEach Values()
With Values()
dSum = \Value_1 +
\Value_2 +
\Value_3 +
\Value_4 +
\Value_5 +
\Value_6 +
\Value_7 +
\Value_8
\Value_1 = (\Value_1 / dSum)
\Value_2 = (\Value_2 / dSum)
\Value_3 = (\Value_3 / dSum)
\Value_4 = (\Value_4 / dSum)
\Value_5 = (\Value_5 / dSum)
\Value_6 = (\Value_6 / dSum)
\Value_7 = (\Value_7 / dSum)
\Value_8 = (\Value_8 / dSum)
;~ Fill the data for data series
AddElement(\DataSeries()): \DataSeries() = \Value_1
AddElement(\DataSeries()): \DataSeries() = \Value_2
AddElement(\DataSeries()): \DataSeries() = \Value_3
AddElement(\DataSeries()): \DataSeries() = \Value_4
AddElement(\DataSeries()): \DataSeries() = \Value_5
AddElement(\DataSeries()): \DataSeries() = \Value_6
AddElement(\DataSeries()): \DataSeries() = \Value_7
AddElement(\DataSeries()): \DataSeries() = \Value_8
EndWith
Next
EndProcedure
Procedure StackedBarsDraw(List Values.Delay(), List Labels.s(), WinHeight, Font1, Font2, Font3, DrawDataSeries)
Protected CurrBar
Protected BarLeft
Protected BarTop
Protected BarLen
Protected BarValue.d
Protected StackLen = #STACKBAR_CHART_WIDTH - 175
Protected LabelTop
Protected LabelLeft
Protected CurrVal
Protected TotalLabels
Protected sLabel.s
;~ Protected NewList BranchData.d()
Protected Dim StackBarColor(7)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~ Colors
;{
StackBarColor(00) = RGBA(102, 170, 000, 255)
StackBarColor(01) = RGBA(016, 150, 024, 255)
StackBarColor(02) = RGBA(034, 170, 153, 255)
StackBarColor(03) = RGBA(221, 068, 119, 255)
StackBarColor(04) = RGBA(255, 010, 010, 255)
StackBarColor(05) = RGBA(153, 000, 153, 255)
StackBarColor(06) = RGBA(127, 000, 000, 255)
StackBarColor(07) = RGBA(048, 048, 048, 255)
;}
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ForEach Values()
;~ ClearList(BranchData())
;~ AddElement(BranchData()): BranchData() = Values()\Value_1
;~ AddElement(BranchData()): BranchData() = Values()\Value_2
;~ AddElement(BranchData()): BranchData() = Values()\Value_3
;~ AddElement(BranchData()): BranchData() = Values()\Value_4
;~ AddElement(BranchData()): BranchData() = Values()\Value_5
;~ AddElement(BranchData()): BranchData() = Values()\Value_6
;~ AddElement(BranchData()): BranchData() = Values()\Value_7
;~ AddElement(BranchData()): BranchData() = Values()\Value_8
;~ Set the drawing font
DrawingFont(FontID(Font1))
;~ Take the values
sLabel = Values()\Header
BarLeft = #DRAW_BAR_AT_POS
BarTop = (CurrBar * #BAR_HEIGHT)
CurrVal = 0
ForEach Values()\DataSeries()
BarLen = (StackLen * Values()\DataSeries())
BarValue = (BarLen/StackLen) * 100
LabelTop = BarTop + (#BAR_HEIGHT / 2.5)
Box(BarLeft, BarTop + (CurrBar * #DISTANCE_BETWEEN_BARS) + 5, BarLen, #BAR_HEIGHT, StackBarColor(CurrVal))
DrawText(BarLeft+5, LabelTop + (CurrBar * #DISTANCE_BETWEEN_BARS) + 5, StrD(BarValue, 2) + "%", $FFFFFF)
BarLeft + BarLen
;~ Increase counter
CurrVal + 1
Next
;~ Set the label
DrawingFont(FontID(Font2))
DrawText(10, LabelTop + (CurrBar * #DISTANCE_BETWEEN_BARS), sLabel, RGBA(75, 75, 75, 75))
CurrBar + 1
Next
;~ Draw the legends
CurrBar = 0
TotalLabels = ListSize(Labels()) + #DISTANCE_BETWEEN_LABELS
BarTop = WinHeight - (TotalLabels * #LEGEND_HEIGHT)
;~ Set the drawing font
DrawingFont(FontID(Font3))
ForEach Labels()
Box(150, BarTop, 25, #LEGEND_HEIGHT, StackBarColor(CurrBar))
DrawText(180, BarTop, Labels(), RGBA(75, 75, 75, 75))
CurrBar + 1
BarTop + #LEGEND_HEIGHT + #DISTANCE_BETWEEN_LABELS
Next
;~ Draw the Data series
If (DrawDataSeries = #True)
TotalLabels = ListSize(Labels()) + #DISTANCE_BETWEEN_LABELS
LabelLeft = 375
;~ Set the drawing font
DrawingFont(FontID(Font3))
ForEach Values()
With Values()
BarTop = WinHeight - (TotalLabels * #LEGEND_HEIGHT) - 20
DrawText(LabelLeft, BarTop, \Header, RGBA(75, 75, 75, 75))
;~ Start drawing the data
BarTop = WinHeight - (TotalLabels * #LEGEND_HEIGHT)
ForEach \DataSeries()
DrawText(LabelLeft, BarTop, StrD((\DataSeries() * 100), 2) + "%", RGBA(75, 75, 75, 75))
BarTop + #LEGEND_HEIGHT + #DISTANCE_BETWEEN_LABELS
Next
EndWith
LabelLeft + #AXIS_WIDTH
Next
EndIf
EndProcedure
Procedure StackedBarShow(sTitle.s, List Values.Delay(), List Labels.s(), DrawDataSeries = #True)
Protected Event
Protected hImg1
Protected hImg2
Protected hWnd
Protected hScroll
Protected WinHeight
Protected WinWidth
Protected Font1 = LoadFont(#PB_Any, "Tahoma", 7, #PB_Font_Bold|#PB_Font_HighQuality)
Protected Font2 = LoadFont(#PB_Any, "Tahoma", 11, #PB_Font_HighQuality)
Protected Font3 = LoadFont(#PB_Any, "Tahoma", 7, #PB_Font_HighQuality)
WinHeight = ListSize(Values()) * (#BAR_HEIGHT + 5)
WinHeight + ListSize(Labels()) * (#LEGEND_HEIGHT + 5)
WinHeight * 1.05
WinHeight = Max(WinHeight, #STACKBAR_CHART_HEIGHT)
If (DrawDataSeries = #True)
WinWidth = ListSize(Values()) * (#AXIS_WIDTH * 1.30)
WinWidth = Max(WinWidth, #STACKBAR_CHART_WIDTH)
Else
WinWidth = #STACKBAR_CHART_WIDTH
EndIf
hWnd = OpenWindow(#PB_Any, 0, 0, #STACKBAR_CHART_WIDTH, #STACKBAR_CHART_HEIGHT, sTitle, #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If (hWnd)
hScroll = ScrollAreaGadget(#PB_Any, 0, 0, #STACKBAR_CHART_WIDTH, #STACKBAR_CHART_HEIGHT, WinWidth, WinHeight, 30, #PB_ScrollArea_Flat)
hImg1 = CreateImage(#PB_Any, WinWidth, WinHeight)
If (hImg1) And (StartDrawing(ImageOutput(hImg1)))
;~ If CreateImage(0, #CHART_WIDTH, #CHART_HEIGHT) And StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Transparent)
;~ Change from values to percentages
StackedBarsCalcPercentages(Values())
;~ Set white background for the whole chart
Box(0, 0, WinWidth, WinHeight, $FFFFFF)
;~ Display the stacked bars
StackedBarsDraw(Values(), Labels(), WinHeight, Font1, Font2, Font3, DrawDataSeries)
StopDrawing()
hImg2 = ImageGadget(#PB_Any, 0, 0, WinWidth, WinHeight, ImageID(hImg1))
CloseGadgetList()
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
CloseWindow(hWnd)
EndIf
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
Define NewList Labels.s()
AddElement(Labels()): Labels() = "Label 1"
AddElement(Labels()): Labels() = "Label 2"
AddElement(Labels()): Labels() = "Label 3"
AddElement(Labels()): Labels() = "Label 4"
AddElement(Labels()): Labels() = "Label 5"
AddElement(Labels()): Labels() = "Label 6"
AddElement(Labels()): Labels() = "Label 7"
AddElement(Labels()): Labels() = "Label 8"
;~ You can add as many Values() as you want
;~ Each Values() creates a new bar in chart
Define NewList Values.StackedBarChart::Delay()
AddElement(Values())
Values()\Header = "Header 001"
Values()\Value_1 = 4898600.0
Values()\Value_2 = 2811870.0
Values()\Value_3 = 2013820.0
Values()\Value_4 = 1834540.0
Values()\Value_5 = 2586490.0
Values()\Value_6 = 1134970.0
Values()\Value_7 = 1253450.0
Values()\Value_8 = 3738510.0
AddElement(Values())
Values()\Header = "Header 002"
Values()\Value_1 = 5068430.0
Values()\Value_2 = 597752.0
Values()\Value_3 = 1867140.0
Values()\Value_4 = 1338630.0
Values()\Value_5 = 422371.0
Values()\Value_6 = 351421.0
Values()\Value_7 = 307252.0
Values()\Value_8 = 10894000.0
AddElement(Values())
Values()\Header = "Header 003"
Values()\Value_1 = 1098130.0
Values()\Value_2 = 884433.0
Values()\Value_3 = 277653.0
Values()\Value_4 = 499117.0
Values()\Value_5 = 448056.0
Values()\Value_6 = 2138260.0
Values()\Value_7 = 769726.0
Values()\Value_8 = 3826260.0
AddElement(Values())
Values()\Header = "Header 004"
Values()\Value_1 = 1135720.0
Values()\Value_2 = 371530.0
Values()\Value_3 = 154354.0
Values()\Value_4 = 46228.0
Values()\Value_5 = 12444.2
Values()\Value_6 = 0.0
Values()\Value_7 = 8074.23
Values()\Value_8 = 57124.9
AddElement(Values())
Values()\Header = "Header 005"
Values()\Value_1 = 522394.0
Values()\Value_2 = 198548.0
Values()\Value_3 = 108467.0
Values()\Value_4 = 163168.0
Values()\Value_5 = 62078.0
Values()\Value_6 = 44384.9
Values()\Value_7 = 131412.0
Values()\Value_8 = 236213.0
AddElement(Values())
Values()\Header = "Header 006"
Values()\Value_1 = 522394.0
Values()\Value_2 = 198548.0
Values()\Value_3 = 108467.0
Values()\Value_4 = 663168.0
Values()\Value_5 = 62078.0
Values()\Value_6 = 44384.6
Values()\Value_7 = 131412.0
Values()\Value_8 = 236213.0
AddElement(Values())
Values()\Header = "Header 007"
Values()\Value_1 = 222394.0
Values()\Value_2 = 198548.0
Values()\Value_3 = 108467.0
Values()\Value_4 = 163168.0
Values()\Value_5 = 62078.0
Values()\Value_6 = 44385.1
Values()\Value_7 = 131412.0
Values()\Value_8 = 236213.0
;~ Show the chart
StackedBarChart::StackedBarShow("Stacked bar demo", Values.StackedBarChart::Delay(), Labels(), #True)
CompilerEndIf