This is a rudimentary (and not thoroughly checked) graphical representation of data as a boxplot. It does not check the outliers using Grubb's test however shows outliers that are farther than 1.5 IQR.
Looking for ideas on improving it. Copy and paste the code into a new module and run the macro Calculate_BoxPlot -- Join official Facebook page of this forum @ https://www.facebook.com/discussexcel FORUM RULES 1) Use concise, accurate thread titles. Poor thread titles, like Please Help, Urgent, Need Help, Formula Problem, Code Problem, and Need Advice will not get quick attention or may not be answered. 2) Don't post a question in the thread of another member. 3) Don't post questions regarding breaking or bypassing any security measure. 4) Acknowledge the responses you receive, good or bad. 5) Jobs posting is not allowed. 6) Sharing copyrighted material and their links is not allowed. NOTE : Don't ever post confidential data in a workbook. Forum owners and members are not responsible for any loss. --- You received this message because you are subscribed to the Google Groups "MS EXCEL AND VBA MACROS" group. To post to this group, send email to excel-macros@googlegroups.com. To unsubscribe from this group, send email to excel-macros+unsubscr...@googlegroups.com. Visit this group at http://groups.google.com/group/excel-macros?hl=en.
Sub Calculate_BoxPlot() Dim sLW As Single, s1Q As Single, sM As Single, s3Q As Single, sUW As Single, sPE As Single, sME As Single Dim iMinA As Integer, iMaxA As Integer 'minimum and maximum values for the graph axis Dim sMin As Single, sMax As Single, sIQR As Single, sRange As Single Dim iSht As Integer Dim sSht_n As String, sSht_o As String ' new sheet, old sheet Dim lLastRow As Long, lRowCount As Long Dim iLastCol As Integer, iColCount As Integer Dim rCell As Range, rRng As Range Dim j As Long Dim i As Integer Dim k As Long, maxK As Long 'sLW = Lower Wisker 's1Q = 1st Quartile 'sM = Median 's3Q = 3rd Quartile 'sUW = Upper Wisker 'iMinA = minimum for Axis 'iMaxA = maximum for Axis 'sMin = Minimum Value no farther than 1.5 * IQR 'sMax = Maximum Value no farther than 1.5 * IQR 'sIQR = Inter Quartile Range (3rd Quartile - 1st Quartile) 'sRange = real range = maximum value - minimum value regardless of IQR 'check if anything selected If Application.WorksheetFunction.CountA(Selection) < 5 Then MsgBox "Error! You need at least 5 rows of data plus the title of the column", vbCritical Exit Sub End If 'add Temporary Sheet sSht_o = ActiveSheet.Name iSht = Sheets.Count Sheets.Add After:=Sheets(Sheets.Count) Sheets(iSht + 1).Select sSht_n = tmpSheet Sheets(iSht + 1).Name = sSht_n 'copy data range into tmpSheet Sheets(sSht_o).Activate Selection.Copy Sheets(sSht_n).Select Range("A1").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Range("A1").Select 'check data integrity (all numbers) lLastRow = ActiveSheet.UsedRange.Rows.Count iLastCol = ActiveSheet.UsedRange.Columns.Count iColCount = iLastCol For i = 1 To iColCount Columns(i).Select Selection.End(xlDown).Select lRowCount = ActiveCell.Row For j = 2 To lRowCount If Not IsNumeric(Cells(j, i)) Then MsgBox "Error! All data (except column titles) must be numeric. You have non numeric cells", vbCritical Sheets(sSht_o).Activate Application.DisplayAlerts = False Sheets(sSht_n).Delete Application.DisplayAlerts = True Exit Sub End If Next Next 'prepare sheet for calculation Range(Cells(1, 1), Cells(1, iLastCol)).Select Selection.Copy Cells(1, iLastCol + 3).Select ActiveSheet.Paste Cells(2, iLastCol + 2) = "3rd Quartile" Cells(3, iLastCol + 2) = "Median" Cells(4, iLastCol + 2) = "1st Quartile" Cells(5, iLastCol + 2) = "Lower Wisker" Cells(6, iLastCol + 2) = "Upper Wisker" Cells(7, iLastCol + 2) = "Box Range" Cells(8, iLastCol + 2) = "Plus Error" Cells(9, iLastCol + 2) = "Minus Error" Cells(11, iLastCol + 2) = "Min Axis" Cells(12, iLastCol + 2) = "Max Axis" Cells(1, iLastCol + 2).Select For i = 1 To iColCount + 1 Columns(iLastCol + 1 + i).Select Columns(iLastCol + 1 + i).EntireColumn.AutoFit Next 'start calculation iMinA = 1 iMaxA = 0 For i = 1 To iColCount Columns(i).Select Selection.End(xlDown).Select lRowCount = ActiveCell.Row Cells(5, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=MIN(R[-3]C[-" & iLastCol + 2 & "]:R[" & lRowCount - 5 & "]C[-" & iLastCol + 2 & "])" Cells(4, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=QUARTILE.EXC(R[-2]C[-" & iLastCol + 2 & "]:R[" & lRowCount - 4 & "]C[-" & iLastCol + 2 & "],1)" Cells(3, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=MEDIAN(R[-1]C[-" & iLastCol + 2 & "]:R[" & lRowCount - 3 & "]C[-" & iLastCol + 2 & "])" Cells(2, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=QUARTILE.EXC(RC[-" & iLastCol + 2 & "]:R[" & lRowCount - 2 & "]C[-" & iLastCol + 2 & "],3)" Cells(6, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=Max(R[-4]C[-" & iLastCol + 2 & "]:R[" & lRowCount - 6 & "]C[-" & iLastCol + 2 & "])" Cells(7, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=R[-5]C-R[-3]C" Cells(8, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=R[-2]C-R[-6]C" Cells(9, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=R[-5]C-R[-4]C" Cells(11, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=ROUNDDOWN(MIN(R[-6]C:R[-6]C[2]),0)" If iMinA > iMaxA Then iMinA = ActiveCell.Value If iMinA > ActiveCell.Value Then iMinA = ActiveCell.Value Cells(12, iLastCol + 2 + i).Select ActiveCell.FormulaR1C1 = "=ROUNDUP(MAX(R[-6]C:R[-6]C[2]),0)" If iMaxA < iMinA Then iMaxA = ActiveCell.Value If iMaxA < ActiveCell.Value Then iMaxA = ActiveCell.Value Cells(1, iLastCol + 2 + i).Select Next Range(Cells(11, iLastCol + 2 + 1), Cells(12, iLastCol + 2 + iColCount)).Select Selection.Clear Cells(11, iLastCol + 3) = iMinA Cells(12, iLastCol + 3) = iMaxA Cells(1, iLastCol + 2).Select maxK = Outliers(lLastRow, iLastCol) 'plot the data ActiveSheet.Shapes.AddChart.Select ActiveSheet.Shapes("Chart 1").IncrementTop 70 ActiveChart.ChartType = xlColumnClustered ActiveChart.SetSourceData Source:=Range(sSht_n & "!$" & Chr(iLastCol + 2 + 64) & "$1:$" & Chr(iLastCol + 2 + iColCount + 64) & "$4"), PlotBy:=xlRows ActiveChart.PlotArea.Select 'ActiveChart.SetSourceData 'ActiveChart.SeriesCollection(4).Select ActiveChart.SetElement (msoElementErrorBarStandardError) ActiveChart.SeriesCollection(2).ErrorBars.Select ActiveChart.SetElement (msoElementErrorBarNone) ActiveChart.SeriesCollection(1).ErrorBars.Select ActiveChart.SeriesCollection(1).ErrorBar Direction:=xlY, Include:= _ xlPlusValues, Type:=xlStError ActiveChart.SeriesCollection(1).ErrorBar Direction:=xlY, Include:= _ xlPlusValues, Type:=xlCustom, amount:=Worksheets(sSht_n).Range(Cells(8, iLastCol + 3), Cells(8, iLastCol + 2 + iColCount)) ActiveChart.SeriesCollection(3).Select ActiveChart.SetElement (msoElementErrorBarStandardError) ActiveChart.SeriesCollection(3).ErrorBars.Select ActiveChart.SeriesCollection(3).ErrorBar Direction:=xlY, Include:= _ xlMinusValues, Type:=xlStError ActiveChart.SeriesCollection(3).ErrorBar Direction:=xlY, Include:= _ xlMinusValues, Type:=xlCustom, amount:=0, minusvalues:=Worksheets(sSht_n).Range(Cells(9, iLastCol + 3), Cells(9, iLastCol + 2 + iColCount)) ActiveChart.PlotArea.Select 'ActiveChart.SeriesCollection(1).Delete 'ActiveChart.SeriesCollection(4).Delete 'ActiveChart.SeriesCollection(1).Select ActiveChart.SeriesCollection(2).Select With Selection.Format.Fill .Visible = msoTrue .ForeColor.ObjectThemeColor = msoThemeColorBackground1 .ForeColor.TintAndShade = 0 .ForeColor.Brightness = 0 .Transparency = 0 .Solid End With ActiveChart.SeriesCollection(2).Select With Selection.Format.Fill .Visible = msoTrue .ForeColor.ObjectThemeColor = msoThemeColorBackground1 .ForeColor.TintAndShade = 0 .ForeColor.Brightness = -0.25 .Transparency = 0 .Solid End With ActiveChart.SeriesCollection(1).Select With Selection.Format.Fill .Visible = msoTrue .ForeColor.ObjectThemeColor = msoThemeColorBackground1 .ForeColor.TintAndShade = 0 .ForeColor.Brightness = 0.349999994 .Transparency = 0 .Solid End With ActiveSheet.ChartObjects("Chart 1").Activate ActiveChart.SeriesCollection(3).Select With Selection.Format.Fill .Visible = msoTrue .ForeColor.ObjectThemeColor = msoThemeColorBackground1 .ForeColor.TintAndShade = 0 .ForeColor.Brightness = 0 .Solid End With With Selection.Format.Fill .Visible = msoTrue .ForeColor.ObjectThemeColor = msoThemeColorBackground1 .ForeColor.TintAndShade = 0 .ForeColor.Brightness = 0 .Transparency = 0 .Solid End With ActiveChart.SeriesCollection(1).Select With Selection.Format.Fill .Visible = msoTrue .ForeColor.ObjectThemeColor = msoThemeColorText1 .ForeColor.TintAndShade = 0 .ForeColor.Brightness = 0.349999994 .Transparency = 0 .Solid End With Selection.Format.Line.Visible = msoFalse ActiveChart.PlotArea.Select ActiveChart.SeriesCollection(3).Select ActiveChart.ChartGroups(1).GapWidth = 264 ActiveChart.ChartGroups(1).Overlap = 100 ActiveChart.PlotArea.Select ActiveSheet.ChartObjects("Chart 1").Activate ActiveSheet.Shapes("Chart 1").ScaleWidth 1.5, msoFalse, _ msoScaleFromTopLeft ActiveSheet.Shapes("Chart 1").ScaleHeight 1.5, msoFalse, _ msoScaleFromTopLeft ActiveSheet.ChartObjects("Chart 1").Activate ActiveChart.Axes(xlValue).MajorGridlines.Select Selection.Format.Line.Visible = msoFalse ActiveChart.SetElement (msoElementLegendNone) ActiveChart.Axes(xlValue).Select ActiveChart.Axes(xlValue).MinimumScale = Cells(11, iLastCol + 3).Value ActiveChart.Axes(xlValue).MaximumScale = Cells(12, iLastCol + 3).Value 'count the max number of outliers for each column For k = 14 To maxK ActiveSheet.ChartObjects("Chart 1").Activate ActiveChart.PlotArea.Select ActiveChart.SeriesCollection.NewSeries ActiveChart.SeriesCollection(4 + k - 14).Name = "Outliers" ActiveChart.SeriesCollection(4 + k - 14).Values = sSht_n & "!$" & Chr(iLastCol + 3 + 64) & "$" & k & ":$" & Chr(iLastCol + 2 + iColCount + 64) & "$" & k ActiveChart.SeriesCollection(4 + k - 14).Select ActiveChart.SeriesCollection(4 + k - 14).ChartType = xlXYScatter ActiveChart.SeriesCollection(4 + k - 14).Select Selection.MarkerStyle = -4168 With Selection.Format.Fill .Visible = msoTrue .ForeColor.RGB = RGB(128, 128, 128) .BackColor.RGB = RGB(255, 255, 255) End With With Selection.Format.Line .Visible = msoTrue .ForeColor.RGB = RGB(255, 255, 255) .ForeColor.TintAndShade = 0 .ForeColor.Brightness = 0 End With Next Range("A1").Select End Sub Function tmpSheet() As String Dim sLetter(8) As String, sName As String Dim iLetterType As Integer Dim i As Integer sName = "" For i = 0 To 7 iLetterType = WorksheetFunction.RandBetween(1, 3) Select Case iLetterType Case 1 sLetter(i) = Chr(WorksheetFunction.RandBetween(65, 90)) Case 2 sLetter(i) = Chr(WorksheetFunction.RandBetween(97, 122)) Case 3 sLetter(i) = Chr(WorksheetFunction.RandBetween(48, 57)) End Select sName = sName & sLetter(i) Next tmpSheet = sName End Function Function Outliers(lRow As Long, iCol As Integer) As Long Dim i As Integer 'columns Dim j As Long 'rows Dim k As Long 'outlier row Dim iColCount As Integer Dim sOutlier As Single Dim sRange As Single Dim maxK As Long iColCount = iCol + 3 Cells(14, iColCount - 1) = "Outliers" maxK = 14 For j = 1 To iCol k = 14 sRange = Cells(7, j + iColCount - 1) For i = 2 To lRow If Cells(i, j) <> "" Then If Cells(i, j) < Cells(3, j + iColCount - 1) Then sOutlier = Cells(4, j + iColCount - 1) - Cells(i, j) If sOutlier > sRange * 1.5 Then Cells(k, j + iColCount - 1) = Cells(i, j) Cells(i, j) = "" k = k + 1 End If Else sOutlier = Cells(i, j) - Cells(2, j + iColCount - 1) If sOutlier > sRange * 1.5 Then Cells(k, j + iColCount - 1) = Cells(i, j) Cells(i, j) = "" k = k + 1 End If End If End If Next If maxK < k - 1 Then maxK = k - 1 Next Outliers = maxK End Function