窗体 FrmEqualityPrep.frm Option Explicit Option Base 1 Private Sub Form_Load() optDataShare.Value = True cbxMethod.ListIndex = 1 lstSData.Clear End Sub Private Sub optDataInput_Click() optDataInput.Value = True Frame3.Enabled = True txtIndex.Enabled = False End Sub Private Sub optDataShare_Click() optDataShare.Value = True Frame3.Enabled = False txtIndex.Enabled = True End Sub Private Sub cbExit_Click() Unload Me End Sub ' Event Procedures for input source data: Means and GroupNames Private Sub cbAdd_Click() Dim pLine As String Dim I As Integer, St As String If Len(txtMean.Text) = 0 Then MsgBox "请先填好方差值!", vbExclamation Exit Sub End If If Not IsNumeric(txtMean.Text) Then MsgBox "方差值必须为数字!", vbExclamation Exit Sub End If pLine = Format(txtMean.Text, "0000.000 ") & _ Format(txtGName.Text, "!@@@@@@@@@@") ' ' Format is based on Charactor not on Byte! So, when mixed with ASCII and _ DBCS chars in Chinese Version, String with same lenth may have different _ width on Screen !!! I = IIf(lstSData.ListCount = 0, 0, lstSData.ListCount) lstSData.AddItem pLine, I lstSData.ListIndex = I txtMean.SetFocus End Sub Private Sub cbDelete_Click() Dim I As Integer If lstSData.ListIndex = -1 Then MsgBox "请先选好要删除的行!", vbExclamation Exit Sub End If I = lstSData.ListIndex lstSData.RemoveItem I If lstSData.ListCount > 0 Then lstSData.ListIndex = IIf(I = 0, 0, I - 1) End Sub Private Sub cbDown_Click() Dim sTemp As String Dim I As Integer I = lstSData.ListIndex If I = lstSData.ListCount - 1 Then Beep Exit Sub End If sTemp = lstSData.List(I) lstSData.RemoveItem I I=I+1 lstSData.AddItem sTemp, I lstSData.ListIndex = I End Sub Private Sub cbUP_Click() Dim sTemp As String Dim I As Integer I = lstSData.ListIndex If I = 0 Then Beep Exit Sub End If sTemp = lstSData.List(I) lstSData.RemoveItem I I=I-1 lstSData.AddItem sTemp, I lstSData.ListIndex = I End Sub Private Sub cbRun_Click() Dim sVariance() As Double Dim idFx As Integer, n As Integer Dim iMethod As Integer Dim iReturn As Integer, I As Integer, strT As String I = cbxMethod.ListIndex iMethod = cbxMethod.ItemData(I) If optDataShare.Value Then ' use Sample data for Anova analysis If Not IsNumeric(txtIndex.Text) Then MsgBox "请输入试点序号! (0 代表多点联合分析)", vbOKOnly + vbExclamation txtIndex.SetFocus Exit Sub End If iReturn = objAnova.EqualityAnova(Val(txtIndex.Text), iMethod) Else ' all data should be provided here ' Check parameters If Not IsNumeric(txtdFx.Text) Then MsgBox "请输入自由度值,它必须为数字!", vbExclamation Exit Sub Else idFx = Val(txtdFx.Text) End If If lstSData.ListCount < 2 Then MsgBox "至少要有两组方差值数据才能进同质性检验!", vbExclamation Exit Sub Else n = lstSData.ListCount ReDim sVariance(n), VarIDs(n) For I = 0 To n - 1 strT = lstSData.List(I) sVariance(I + 1) = Val(Left(strT, 10)) VarIDs(I + 1) = Trim(Mid(strT, 11)) Next End If iReturn = objAnova.EqualityWSD(sVariance, idFx, iMethod) End If If iReturn <> caiOK Then TestAnovaMain.txtMessage.Text = TestAnovaMain.txtMessage.Text & vbCrLf & Time() & _ " 同质性检验失败!" & vbCrLf & objAnova.strMessage TestAnovaMain.Show Exit Sub End If EqualityPresent TestAnovaMain.Show End Sub Public Sub EqualityPresent() Dim strT As String, strS As String Dim ctEquRpt As AnovaCom.EqualityResult ctEquRpt = objAnova.ctEqTestResult With ctEquRpt strT = vbCrLf & Time() & " 参试组样本方差间的同质性检验顺利完成。" & vbCrLf strT = strT & "方法名称:" & Format(.MethodName, "!@@@@@@@@@@@") & vbCrLf strT = strT & "参试组个数:" & Format(.Size, "000;") & " 各方差的自由度:" & Format(.dF, "000") & vbCrLf strS = IIf(.MethodName = "Cochran", "G_Max", "X_Square") strT = strT & "计算得同质性评估指数 " & strS & " = " & Format(.EvalValue, "##0.000") & vbCrLf strT = strT & "对应的临界值:α=0.05 时为" & Format(.CritVal005, "##0.000;") & " α=0.01 时为" & Format(.CritVal001, "##0.000;") & vbCrLf Select Case .Result Case 0 strS = "各参试组的样本方差间的同质性可以接受。" Case 1 strS = "各参试组的样本方差间的差异显著。 (错判概率小于 5%)" Case 2 strS = "各参试组的样本方差间的差异极显著。(错判概率小于 1%)" End Select strT = strT & "检验结论:" & strS & vbCrLf End With TestAnovaMain.txtMessage.Text = TestAnovaMain.txtMessage.Text & strT End Sub 窗体 frmGetSDataExcel.frm Option Explicit Option Base 1 Private exlApp As Excel.Application, exlWBook As Excel.Workbook Private exlRg As Excel.Range Private Const cState0 As String = "初始状态:没连结任何 Excel 工作簿文件。" Private Const cState1 As String = "连接工作簿成功;等待导入样本数据。" Private Const cState2 As String = "开始导入样本数据,请稍侯。" 'Private Const cState3 As String = "开始导入生产试验数据,请稍侯。" Private Const cState4 As String = "当前工作簿中的样本数据已成功地读入。" Private Const cStateErr As String = "操作失败!" Private Sub Form_Load() txtState = cState0 txtPathName = "" cbActions(1).Enabled = False ProgressBar1.Value = 0 cdlDialog1.Filter = "Excel Workbook (*.xls)|*.xls" Me.Height = 5790 Me.Width = 7950 End Sub Private Sub Form_Unload(Cancel As Integer) If Not exlWBook Is Nothing Then exlWBook.Close Set exlWBook = Nothing End If If Not exlApp Is Nothing Then exlApp.Quit Set exlApp = Nothing End If End Sub Private Sub cbBrows_Click() ' Get file name from the Common Dialog Box, i.e. cdlDialog1 On Error Resume Next cdlDialog1.CancelError = True cdlDialog1.ShowOpen If Err.Number = cdlCancel Then lbInit: txtPathName = "" txtState.Text = cState0 ProgressBar1.Value = 0 Exit Sub ' Cancel button is pressed End If txtPathName.Text = cdlDialog1.FileName If Len(txtState.Text) < 5 Then MsgBox "你尚未选择有效的工作簿路径名!", vbOKOnly + vbExclamation GoTo lbInit Else ProgressBar1.Value = 2 txtState.Text = cState0 End If End Sub Private Sub cbActions_Click(Index As Integer) Dim iReturn As Integer Dim bVisible As Boolean Select Case Index Case 0 If Len(txtPathName.Text) < 5 Or Right(txtPathName.Text, 3) <> "xls" Then MsgBox "请先确定 Excel 工作簿的路径名!", vbOKOnly + vbExclamation Exit Sub End If bVisible = chkVisible.Value iReturn = AccessExcelWBook(txtPathName.Text, bVisible) If iReturn = caiOK Then txtState = cState1 cbActions(1).Enabled = True ProgressBar1.Value = 30 Else txtState = cStateErr & strMessage & vbCrLf _ & "请检查后重新连结。" cbActions(1).Enabled = False ProgressBar1.Value = 0 iDState = 0 End If Case 1 txtState = cState2 iReturn = GetSampleDataExcel() If iReturn = caiOK Then txtState = cState4 TestAnovaMain!txtMessage.Text = Time() & " 样本数据收集完毕。 " & vbCrLf Else txtState = cStateErr & strMessage ProgressBar1.Value = 0 End If Case 2 Unload Me End Select End Sub Function AccessExcelWBook(strPathName As String, bVisible As Boolean) As Integer On Error GoTo errAccessExcel Set exlApp = CreateObject("Excel.Application") If bVisible Then exlApp.WindowState = xlMaximized exlApp.Visible = True Else exlApp.Visible = False End If Set exlWBook = exlApp.Workbooks.Open(strPathName, 0) ' "0",the 2nd. Para., means no link to be updated when open the workbook Set exlRg = exlWBook.Worksheets.Item(1).Range("PlotYields") AccessExcelWBook = caiOK Exit Function errAccessExcel: If Err.Number = 9 Then strMessage = "该工作簿中没按规定设立小区产量数据区域!无法获得数据。" _ & vbCrLf & "它应在第一张工作表上且定义为“PlotYields” 。" ElseIf Err.Number = 1004 Then strMessage = "找不到指定的工作簿,路径名不对!建议利用《浏览》键查找。" Else strMessage = "操作失败,未能获得小区产量数据!" End If AccessExcelWBook = caiError End Function Function GetSampleDataExcel() As Integer Dim n1 As Integer, n2 As Integer, n3 As Integer Dim vT As Variant, lOffset As Long Dim I As Integer, J As Integer, K As Integer Dim strMessage As String ' Set Dimentions of Sample Data and get IDs/Names of Sites and Varieties On Error GoTo errR n3 = exlRg.Columns.Count lOffset = exlRg.Column J = 3 + 1 - lOffset vT = exlRg.Cells(1, J).Value I=2 Do While exlRg.Cells(I, J).Value <> vT I=I+1 Loop n2 = I - 1 n1 = Int(exlRg.Rows.Count / n2) ReDim sData(n1, n2, n3), SiteIDs(n1), VarIDs(n2) ' Reading Variety Names J=J+1 For I = 1 To n2 VarIDs(I) = exlRg.Cells(I, J).Value Next ' Reading Site IDs J=J-2 For I = 1 To n1 SiteIDs(I) = exlRg.Cells(n2 * (I - 1) + 1, J).Value Next ProgressBar1.Value = 50 ' Reading Plot Yields For I = 1 To n1 For J = 1 To n2 For K = 1 To n3 sData(I, J, K) = exlRg.Cells(n2 * (I - 1) + J, K).Value If exlRg.Cells(n2 * (I - 1) + J, 4).Value <> 0.02 Then vT = exlRg.Cells(n2 * (I - 1) + J, 4).Value vT = 0.02 / vT sData(I, J, K) = sData(I, J, K) * vT End If Next K Next J Next I ProgressBar1.Value = 100 iDState = 1 GetSampleDataExcel = caiOK Exit Function errR: iDState = 0 ReDim sData(1), SiteIDs(1), VarIDs(1) strMessage = "读入样本数据时出错!" _ & " 错误代码:" & CStr(Err.Number) & vbCrLf _ & "说明:" & Err.Description GetSampleDataExcel = caiError End Function 窗体 frmMCompPrep.frm Option Explicit Option Base 1 Private Sub Form_Load() optDataShare.Value = True cbxMethod.ListIndex = 1 cbxMode.ListIndex = 1 lstSData.Clear End Sub Private Sub optDataInput_Click() optDataInput.Value = True Frame3.Enabled = True End Sub Private Sub optDataShare_Click() optDataShare.Value = True Frame3.Enabled = False End Sub Private Sub cbExit_Click() Unload Me End Sub ' Event Procedures for input source data: Means and GroupNames Private Sub cbAdd_Click() Dim pLine As String Dim I As Integer, St As String If Len(txtMean.Text) = 0 Or Len(txtGName.Text) = 0 Then MsgBox "请先填好平均值和名称两项!", vbExclamation Exit Sub End If If Not IsNumeric(txtMean.Text) Then MsgBox "平均值必须为数字!", vbExclamation Exit Sub End If ' pLine = Format(txtMean.Text, "0000.000 ") & _ Format(txtGName.Text, "!@@@@@@@@@@") ' Format is based on Charactor not on Byte! So, when mixed with ASCII and _ DBCS chars in Chinese Version, String with same lenth may have different _ width on Screen !!! I = IIf(lstSData.ListCount = 0, 0, lstSData.ListCount) lstSData.AddItem pLine, I lstSData.ListIndex = I End Sub Private Sub cbDelete_Click() Dim I As Integer If lstSData.ListIndex = -1 Then MsgBox "请先选好要删除的行!", vbExclamation Exit Sub End If I = lstSData.ListIndex lstSData.RemoveItem I If lstSData.ListCount > 0 Then lstSData.ListIndex = IIf(I = 0, 0, I - 1) End Sub Private Sub cbDown_Click() Dim sTemp As String Dim I As Integer I = lstSData.ListIndex If I = lstSData.ListCount - 1 Then Beep Exit Sub End If sTemp = lstSData.List(I) lstSData.RemoveItem I I=I+1 lstSData.AddItem sTemp, I lstSData.ListIndex = I End Sub Private Sub cbUP_Click() Dim sTemp As String Dim I As Integer I = lstSData.ListIndex If I = 0 Then Beep Exit Sub End If sTemp = lstSData.List(I) lstSData.RemoveItem I I=I-1 lstSData.AddItem sTemp, I lstSData.ListIndex = I End Sub Private Sub cbRun_Click() Dim sMeans() As Double Dim dMSx As Double, idFx As Integer, n As Integer Dim iMode As Integer, iMethod As Integer Dim iReturn As Integer, I As Integer, strT As String I = cbxMode.ListIndex iMode = cbxMode.ItemData(I) I = cbxMethod.ListIndex iMethod = cbxMethod.ItemData(I) If optDataShare.Value Then ' use Sample data for Anova analysis iReturn = objAnova.MultiCompareAnova(iMethod, iMode) Else ' all data should be provided here ' Check parameters If Not IsNumeric(txtMSx.Text) Then MsgBox "请输入均方差值,它必须为数字!", vbExclamation Exit Sub Else dMSx = Val(txtMSx.Text) End If If Not IsNumeric(txtdFx.Text) Then MsgBox "请输入自由度值,它必须为数字!", vbExclamation Exit Sub Else idFx = Val(txtdFx.Text) End If If Not IsNumeric(txtN.Text) Then MsgBox "请输入样本容量值,它必须为数字!", vbExclamation Exit Sub Else n = Val(txtN.Text) End If If lstSData.ListCount < 2 Then MsgBox "至少要有两组平均值数据才能进行多重比较!", vbExclamation Exit Sub Else iMode = lstSData.ListCount ReDim sMeans(iMode), VarIDs(iMode) For I = 0 To iMode - 1 strT = lstSData.List(I) sMeans(I + 1) = Val(Left(strT, 10)) VarIDs(I + 1) = Trim(Mid(strT, 11)) Next End If iReturn = objAnova.MultiCompareWSD(sMeans, dMSx, idFx, n, iMethod) End If If iReturn <> caiOK Then TestAnovaMain.txtMessage.Text = TestAnovaMain.txtMessage.Text & vbCrLf & Time() & _ " 多重比较失败!" & vbCrLf & objAnova.strMessage TestAnovaMain.Show Exit Sub End If MultiCompPresent TestAnovaMain.Show End Sub Public Sub MultiCompPresent() Dim strT As String Dim ctMCRpt As AnovaCom.MCReport Dim I As Integer, n As Integer n = UBound(VarIDs) strT = vbCrLf & Time() & " 完成多重比较,各品种名,平均产量,及其级别如下列:" & vbCrLf For I = 1 To n ctMCRpt = objAnova.ctMCompReport(I) With ctMCRpt strT = strT & " ▲ " & Format(.Mean, "000.00") & ", " & .Classif _ & Format(VarIDs(.Index), " !@@@@@@@@") & vbCrLf End With Next TestAnovaMain.txtMessage.Text = TestAnovaMain.txtMessage.Text & strT End Sub 窗体 frmRegressionPrep.frm Option Explicit Option Base 1 Private Sub Form_Load() optDataShare.Value = True lstSData.Clear End Sub Private Sub optDataInput_Click() optDataInput.Value = True Frame3.Enabled = True Frame2.Enabled = False End Sub Private Sub optDataShare_Click() optDataShare.Value = True Frame3.Enabled = False Frame2.Enabled = True End Sub Private Sub cbExit_Click() Unload Me End Sub ' Event Procedures for input source data: Means and GroupNames Private Sub cbAdd_Click() Dim pLine As String Dim I As Integer, St As String If Len(txtX.Text) = 0 Or Len(txtY.Text) = 0 Then MsgBox "请先填好样本 X 和 Y 的值!", vbExclamation Exit Sub End If If Not (IsNumeric(txtX.Text) And IsNumeric(txtY.Text)) Then MsgBox "X、Y 的样本值必须为数字!", vbExclamation Exit Sub End If pLine = Format(txtX.Text, "0000.000 ") & _ Format(txtY.Text, "0000.000") ' ' Format is based on Charactor not on Byte! So, when mixed with ASCII and _ DBCS chars in Chinese Version, String with same lenth may have different _ width on Screen !!! I = IIf(lstSData.ListCount = 0, 0, lstSData.ListCount) lstSData.AddItem pLine, I lstSData.ListIndex = I txtX.SetFocus End Sub Private Sub cbDelete_Click() Dim I As Integer If lstSData.ListIndex = -1 Then MsgBox "请先选好要删除的行!", vbExclamation Exit Sub End If I = lstSData.ListIndex lstSData.RemoveItem I If lstSData.ListCount > 0 Then lstSData.ListIndex = IIf(I = 0, 0, I - 1) End Sub Private Sub cbDown_Click() Dim sTemp As String Dim I As Integer I = lstSData.ListIndex If I = lstSData.ListCount - 1 Then Beep Exit Sub End If sTemp = lstSData.List(I) lstSData.RemoveItem I I=I+1 lstSData.AddItem sTemp, I lstSData.ListIndex = I End Sub Private Sub cbUP_Click() Dim sTemp As String Dim I As Integer I = lstSData.ListIndex If I = 0 Then Beep Exit Sub End If sTemp = lstSData.List(I) lstSData.RemoveItem I I=I-1 lstSData.AddItem sTemp, I lstSData.ListIndex = I End Sub Private Sub cbRun_Click() Dim sXs() As Double, sYs() As Double Dim n As Integer Dim iReturn As Integer, I As Integer, strT As String If optDataShare.Value Then ' use Sample data for Anova analysis If Not IsNumeric(txtIndex.Text) Then MsgBox "请输入所选的因子 B(品种)的序号!", vbOKOnly + vbExclamation txtIndex.SetFocus Exit Sub End If iReturn = objAnova.RegressionAnova(Val(txtIndex.Text)) Else ' all data should be provided here If lstSData.ListCount < 4 Then MsgBox "至少要有 4 组样本数据才能进回归分析!", vbExclamation Exit Sub Else n = lstSData.ListCount ReDim sXs(n), sYs(n) For I = 0 To n - 1 strT = lstSData.List(I) sXs(I + 1) = Val(Left(strT, 10)) sYs(I + 1) = Val(Trim(Mid(strT, 11))) Next End If iReturn = objAnova.RegressionWSD(sXs(), sYs(), n) End If If iReturn <> caiOK Then TestAnovaMain.txtMessage.Text = TestAnovaMain.txtMessage.Text & vbCrLf & Time() & _ " 回归分析失败!" & vbCrLf & objAnova.strMessage TestAnovaMain.Show Exit Sub End If RegressionPresent TestAnovaMain.Show End Sub Public Sub RegressionPresent() Dim strT As String, strS As String Dim ctRegRpt As AnovaCom.RegresionResult ctRegRpt = objAnova.ctRegresResult With ctRegRpt strT = vbCrLf & Time() & " 回归分析及相关性检验顺利完成。" & vbCrLf strT = strT & "样本个数:" & Format(.Size, "000;") & vbCrLf strT = strT & "计算得回归方程‘Y = kX + b’ 的系数: k =" & Format(.Slope, "#0.0000; ") _ & " b =" & Format(.Intercept, "#0.0000;") & vbCrLf strT = strT & "X 和 Y 之间的样本相关系数:" & Format(.CorCorf, "0.00000") & vbCrLf strT = strT & "判断相关性的临界值:α=0.05 时为" & Format(.CritRa005, "0.00000; ") _ & " α=0.01 时为" & Format(.CritRa001, "0.00000;") & vbCrLf Select Case .Result Case 0 strS = "随机变量 X 和 Y 相互之间的独立性可以接受。" Case 1 strS = "随机变量 X 和 Y 相互之间是相关的。 (错判概率小于 5%)" Case 2 strS = "随机变量 X 和 Y 相互之间是相关的。 (错判概率小于 1%)" End Select strT = strT & "检验结论:" & strS & vbCrLf End With TestAnovaMain.txtMessage.Text = TestAnovaMain.txtMessage.Text & strT End Sub 窗体 TestAnovaMain.frm Option Explicit Option Base 1 Private Sub Form_Load() Set objAnova = New clsStatisAnova Me.Height = 5790 Me.Width = 7950 txtMessage.Text = Time() & " 主页启动 " & vbCrLf End Sub Private Sub Form_Unload(Cancel As Integer) Set objAnova = Nothing End Sub Private Sub cbExit_Click() Unload Me End Sub Private Sub cbClean_Click() txtMessage.Text = Time() & " End Sub 擦清公告牌,删除所有历史记录。 " & vbCrLf Private Sub cbGetSData_Click() frmGetSDataExcel.Show End Sub Private Sub cbSendSData_Click() Dim iReturn As Integer iReturn = objAnova.SetSampleData(sData, 3) If iReturn = caiOK Then txtMessage.Text = txtMessage.Text & Time() & _ " 样本数据已成功地传输给统计分析部件:objAnova 。 " & vbCrLf Else txtMessage.Text = txtMessage.Text & Time() & _ " 样本数据传输失败! " & vbCrLf & objAnova.strMessage & vbCrLf End If End Sub Private Sub cbAnova2WOD_Click() Dim iReturn As Integer iReturn = objAnova.Anova2WOD(cRadomized) If iReturn <> caiOK Then txtMessage.Text = txtMessage.Text & vbCrLf & Time() & _ " 联合方差分析失败!" & vbCrLf & objAnova.strMessage Exit Sub End If If objAnova.iAnovaResultState = 22 Then Anova2Present "联合" End If End Sub Private Sub cbAnova2WSD_Click() Dim iReturn As Integer iReturn = objAnova.Anova2Wsd(sData, cRadomized) If iReturn <> caiOK Then txtMessage.Text = txtMessage.Text & vbCrLf & Time() & _ " 联合方差分析失败!" & vbCrLf & objAnova.strMessage Exit Sub End If If objAnova.iAnovaResultState = 22 Then Anova2Present "联合" End If End Sub Private Sub cbAnova2gWOD_Click() Dim iReturn As Integer iReturn = objAnova.Anova2gWOD(4) If iReturn <> caiOK Then txtMessage.Text = txtMessage.Text & vbCrLf & Time() & _ " 双因子随机区组试验方差分析失败!" & vbCrLf & objAnova.strMessage Exit Sub End If If objAnova.iAnovaResultState = 22 Then Anova2Present "双因子随机区组试验" End If End Sub Private Sub cbAnova1WOD_Click() Dim iReturn As Integer, strT As String Dim Idx As Integer Idx = 0 Do Until Idx > 0 strT = InputBox("请输入所选试点的序号:") If IsNumeric(strT) Then Idx = Val(strT) Else MsgBox "试点序号必须是正整数!", vbOKOnly + vbExclamation End If Loop iReturn = objAnova.Anova1WOD(Idx) If iReturn <> caiOK Then txtMessage.Text = txtMessage.Text & vbCrLf & Time() & _ " 单点方差分析失败!" & vbCrLf & objAnova.strMessage Exit Sub End If If objAnova.iAnovaResultState = 12 Then Anova1Present SiteIDs(Idx) End If End Sub Private Sub cbAnova1WSD_Click() Dim iReturn As Integer, strT As String Dim Idx As Integer, I As Integer, J As Integer Dim Data1() As Single, n2 As Integer, n3 As Integer Idx = 0 Do Until Idx > 0 strT = InputBox("请输入所选试点的序号:") If IsNumeric(strT) Then Idx = Val(strT) Else MsgBox "试点序号必须是正整数!", vbOKOnly + vbExclamation End If Loop n2 = UBound(sData, 2) n3 = UBound(sData, 3) ReDim Data1(n2, n3) For I = 1 To n2 For J = 1 To n3 Data1(I, J) = sData(Idx, I, J) Next J Next I iReturn = objAnova.Anova1WSD(Data1) If iReturn <> caiOK Then txtMessage.Text = txtMessage.Text & vbCrLf & Time() & _ " 单点方差分析失败!" & vbCrLf & objAnova.strMessage Exit Sub End If If objAnova.iAnovaResultState = 12 Then Anova1Present SiteIDs(Idx) End If End Sub Private Sub cbMultiCompare_Click() frmMCompPrep.Show End Sub Private Sub cbEquality_Click() frmEqualityPrep.Show End Sub Private Sub cbRegress_Click() frmRegressionPrep.Show End Sub ' Present the result of Anova2 Analysis Sub Anova2Present(strAnova2Type As String) Dim strT As String Dim ctAResult As AnovaCom.AnovaStatis ctAResult = objAnova.ctAnovaResult strT = vbCrLf & Time() & " 下列:" & vbCrLf With ctAResult 完成" & strAnova2Type & "方差分析,获得相关的统计量如 strT = strT & " ▲自由度:dFt =" & Format(.dFt, "000") & "; dFsite =" & Format(.dFa, "000") _ & "; dFv =" & Format(.dFb, "000") & "; dFsv=" & Format(.dFab, "000") & "; dFr =" & Format(.dFr, "000") _ & "; dFerr =" & Format(.dFerr, "000") & "。" & vbCrLf strT = strT & " ▲均方差:MSs =" & Format(.SSa / .dFa, "##0.000") & "; MSv =" & Format(.SSb / .dFb, "##0.000") _ & "; MSab =" & Format(.SSab / .dFab, "##0.000") & "; MSr =" & Format(.SSr / .dFr, "##0.000") _ & "; MSerr =" & Format(.SSerr / .dFerr, "##0.000") & "。" & vbCrLf _ & " ▲总平方和:SStot =" & Format(.SSt, "##0.000") & "。" & vbCrLf strT = strT & " ▲F 检验:FVv = " & Format(.FVb, "#0.000") & "; FPv =" & Format(.FPb, "0.0000") _ & "; FVsv =" & Format(.FVab, "0.000") & "; FPsv =" & Format(.FPab, "0.0000") _ & "; FVs =" & Format(.FVa, "0.000") & "; FPs =" & Format(.FPa, "0.0000") _ & "; FVr =" & Format(.FVr, "0.000") & "; FPr =" & Format(.FPr, "0.0000") & "。" & vbCrLf End With txtMessage.Text = txtMessage.Text & strT End Sub ' Present the result of Anova1 Analysis Sub Anova1Present(strSiteID As String) Dim strT As String Dim ctAResult As AnovaCom.AnovaStatis ctAResult = objAnova.ctAnovaResult strT = vbCrLf & Time() & " 完成单点方差分析,获得相关的统计量如下列:" & vbCrLf strT = strT & "试点 ID = " & strSiteID & vbCrLf With ctAResult strT = strT & " ▲自由度:dFt =" & Format(.dFt, "000") & ";" _ & "; dFv =" & Format(.dFb, "000") & "; dFr =" & Format(.dFr, "000") _ & "; dFerr =" & Format(.dFerr, "000") & "。" & vbCrLf strT = strT & " ▲均方差:MSv =" & Format(.SSb / .dFb, "##0.00") _ & "; MSr =" & Format(.SSr / .dFr, "##0.00") _ & "; MSerr =" & Format(.SSerr / .dFerr, "##0.000") & "。" & vbCrLf _ & " ▲总平方和:SStot =" & Format(.SSt, "##0.000") & "。" & vbCrLf strT = strT & " ▲F 检验:FVv = " & Format(.FVb, "#0.000") & "; FPv =" & Format(.FPb, "0.0000") _ & "; FVr =" & Format(.FVr, "0.000") & "; FPr =" & Format(.FPr, "0.0000") & "。" & vbCrLf End With txtMessage.Text = txtMessage.Text & strT End Sub 模块 AccessAnovaCom.bas Option Explicit Option Base 1 ' to store the Data of Source Samples Public sData() As Single ' an instance of class clsStaisAnova Public objAnova As clsStatisAnova ' States of sData() and other xIDs() Public iDState As Integer ' 0 -- invalid, 1 -- Valid Data of Plot Yields for a Combined Anova Analysis ' to store the Name or Code of the Test Sites and Crop Varieties Public SiteIDs() As String, VarIDs() As String Public strMessage As String ' Return Values of public methods Public Const caiOK As Integer = 0 Public Const caiCancel As Integer = -1 Public Const caiError As Integer = -2 ' for the method of Multiple Comparision Public Const cMcLSD As Integer = 1 Public Const cMcSSR As Integer = 2 ' for Design Mode about Factor A Public Const cFixed As Integer = 0 Public Const cRadomized As Integer = 1 模块 Declarations.bas Option Explicit Option Base 1 '' Define a Type for store the Statistic Values of Anova Analysis 'Public Type AnovaStatis ' ' 自由度 ' dFt As Integer ' dFa As Integer ' dFb As Integer ' dFr As Integer ' dFab As Integer ' dFerr As Integer ' Degrees of Freedom -- Total ' ...... -- Factor A, e.g. the "Test Sites" ' ' 平方和 ' SSt As Double ' Total Square Sum of (Xijk-Average(Xijk)) ' SSa As Double ' Total Squire Sum about the First Factor A, e.g. the "Test Sites" ' SSb As Double ' ...... , e.g. "Varieties" ' SSr As Double ' ...... , e.g. "Blocks" ' SSab As Double ' ...... about "Cross Effections" ' SSerr As Double ' ...... about "Experimental Error" ' GrandMean As Double ' Mean Value of all Samples ' ' F 值及对应的概率(显著性) ' FVr As Double ' F Value from Repitations inside factor A. (来自试点内区组); = (SSr/dFr)/(SSerr/dFerr) ' FVb As Double ' F Value from factor B, e.g. Varieties. (来自品种); ' ' =(SSb/dFb)/Deno, here Deno=(SSab/dFab) if in Radomized mode or =(SSerr/dFerr) if Fixed mode ' FVa As Double ' F Value from factor A, e.g. Test Sites. ( 来 自 试 点 ); =(SSa/dFa)/(SSerr/dFerr) ' FVab As Double ' F Value from the iteraction of factor A and B. (来自试点 x 品种); =(SSab/dFab)/(SSerr/dFerr) ' FPr As Double ' Corresponding significense ...... ' FPb As Double ' FPa As Double ' FPab As Double 'End Type ' '' to store the Result of Multiple Comparision for each Group that presents in MC analysis '' i.e. the whole result should be stored in an Array of this type and the groups should ordered descendly 'Public Type MCReport ' Index As Integer ' Index of the group in the original resource array ' Mean As Double ' mean value of the group ' Classif As String ' ' the classifications of the group. its size always=20, with the 1st 10 chars contain _ ' the classification for 0.05 Significance, the last 10, 0.01 Significance, e.g. " cde DE " 'End Type Public modMessage As String ' Return Values of public methods Public Const caiOK As Integer = 0 Public Const caiCancel As Integer = -1 Public Const caiError As Integer = -2 Public Const caiNo As Integer = 1 ' for the method of Multiple Comparision Public Const cMcLSD As Integer = 1 Public Const cMcSSR As Integer = 2 ' for Design Mode about Factor A Public Const cFixed As Integer = 0 Public Const cRadomized As Integer = 1 ' for method of Equality Test Public Const cDefault As Integer = 0 Public Const cEqCoch As Integer = 1 Public Const cEqBart As Integer = 2 Public Const cMaxInteger As Integer = &H7FFF Public Const cNonSense As Single = -9999 模块 StatisFormulas.bas Option Explicit Option Base 1 ' F Test: n1, n2 --- the 1st and 2nd Degree of Freedom, Fv -- the F Value ' Return the Significance corresponding to Fv Function Ftest(dF1 As Integer, dF2 As Integer, Fv As Double) As Double Dim temp As Double temp = FDistributing(dF1, dF2, Fv, 1) temp = 1 - temp If temp < 0 Then temp = 0 Ftest = temp End Function ' F Distribution Function FDistributing(n1 As Integer, n2 As Integer, f As Double, lable_g As Integer) As Double Dim X As Double, u As Double, p As Double, LU As Double Dim I As Integer, iAi As Integer, iBi As Integer, nN1 As Integer, nN2 As Integer If f = 0 Then FDistributing = 0 Exit Function End If X = n1 * f / (n2 + n1 * f) If Int(n1 / 2) = n1 / 2 Then If Int(n2 / 2) = n2 / 2 Then u = X * (1 - X) p=X iAi = 2 iBi = 2 Else u = X * Sqr(1 - X) / 2 p = 1 - Sqr(1 - X) iAi = 2 iBi = 1 End If Else If Int(n2 * 0.5) = n2 * 0.5 Then p = Sqr(X) u = p * (1 - X) / 2 iAi = 1 iBi = 2 Else u = Sqr(X * (1 - X)) / 3.1415926 p = 1 - 2 * Atn(Sqr((1 - X) / X)) / 3.1415926 iAi = 1 iBi = 1 End If End If nN1 = n1 - 2 nN2 = n2 - 2 If u = 0 Then FDistributing = IIf(lable_g, p, 0) Exit Function End If LU = Log(u) If iAi <> n1 Then For I = iAi To nN1 Step 2 p=p-2*u/I LU = LU + Log((1 + iBi / I) * X) u = Exp(LU) Next I End If If iBi <> n2 Then For I = iBi To nN2 Step 2 p=p+2*u/I LU = LU + Log((1 + n1 / I) * (1 - X)) u = Exp(LU) Next I End If FDistributing = IIf(lable_g, p, u / f) End Function ' To sort source array, i.e. "SrcArr()", an array of any type, and puts the indices of ' sorted SrcArr() into "SortedIdx()", while keeping "SrcArr()" unchanged, ' i.e. after successfully return, SrcArr(SortedIdx(i)) should be in sortrd order based on "i". ' iSize: the number of elements of both array: SrcArr() and SortedIdx(). ' bAsc: indicats the sort order. True -- Ascending; false -- Decsending ' Both Arrays should be allocated with the Base 1 Low Bound by the caller ! Sub SortArray(SrcArr() As Double, iSize As Integer, ByRef SortedIdx() As Integer, bAsc As Boolean) Dim I As Integer, iStart As Integer Dim IdxS As Integer, idxO As Integer Dim vT As Variant For I = 1 To iSize SortedIdx(I) = I Next I iStart = 1 While iStart < iSize IdxS = SortedIdx(iStart) ' Sorting, i.e. let SrcArr(idxS) always being the minmum one in a sorting pass idxO = iStart ' Ordering, i. e. let idxO always satisfies "SortedIdx(idxO) = idxS". For I = iStart + 1 To iSize If SrcArr(SortedIdx(I)) < SrcArr(IdxS) Then IdxS = SortedIdx(I) idxO = I End If Next SortedIdx(idxO) = SortedIdx(iStart) SortedIdx(iStart) = IdxS iStart = iStart + 1 ' Now, SrcArr(SortedIdx(1)), SrcArr(SortedIdx(2)),, ..., SrcArr(SortedIdx(iStart)) the ascending order. Wend ' Now, Sorting Ascendingly is completed are in idxO = iSize: I = 1 If bAsc = False Then While I < idxO vT = SortedIdx(I) SortedIdx(I) = SortedIdx(idxO) SortedIdx(idxO) = vT I=I+1 idxO = idxO - 1 Wend ' At this point, SrcArr(SortedIdx(i)) will be ordered Decendingly based on i=1, 2, 3, ... End If End Sub ' Performs the Multiple Comparesion and put the Comparision Result into cReport() in the format of "a, ab, b, bcd, ...". ' Mean() contains descendly sorted mean values of groups to be compared; iSize -- number of groups, iSize must <=20 ! ' cReport(): the allocated array of chars of size iSize*20, each of its member have been initialized to Char " ", Asc(20). ' in fact, the ith group 's result will be put into section of cReport(i*20+1)~cReport(i*20+19), the first 9 Chars is for 0.05 ' significance, and the last 9 are for 0.01 Sibnificance! ' IdxS: cReport(IdxS) will be the first place to put comparision report into ' McType=cMCLSD (=1) -- use LSD method; cMCSSR (=2) -- SSR Duncan method; ' dDev contains a constants, "LSDα" forLSD method; "Deviation" for SSR Duncan ' for SSR Duncan method, SSR will be a Array of Double with size of iSize and contains the SSR vlaues Function MultiCompReport(Mean() As Double, iSize As Integer, ByRef cReport() As Integer, IdxS As Integer, _ dDev As Double, McType As Integer, Optional SSr) As Integer Dim iB As Integer, iE As Integer, iT As Integer, I As Integer Dim Cat(9) As Integer On Error GoTo MCReportFail iE = 2: iB = 1: iT = 1 Cat(1) = 0 While (iE < iSize + 1) Select Case McType Case cMcLSD ' LSD method Do While Mean(iB) - Mean(iE) <= dDev iE = iE + 1 If iE = iSize + 1 Then Exit Do Loop Case cMcSSR ' SSR Duncan Do While Mean(iB) - Mean(iE) <= dDev * SSr(iE - iB) iE = iE + 1 If iE = iSize + 1 Then Exit Do Loop Case Else modMessage = "当前仅支持 LSD 和 SSR-Duncan 两种多重比较法,请选择 其中只一。" MultiCompReport = caiCancel Exit Function End Select If iE > Cat(iT) Then For I = iB To iE - 1 cReport(IdxS + (I - 1) * 20 + iT) = Asc("a") + iT - 1 Next iT = iT + 1 Cat(iT) = iE End If iB = iB + 1 If iB = iE Then iE = iE + 1 If iE = iSize + 1 Then cReport(IdxS + (iB - 1) * 20 + iT) = Asc("a") + iT - 1 End If End If Wend MultiCompReport = caiOK Exit Function MCReportFail: modMessage = "生成多重比较报告时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description MultiCompReport = caiError End Function 模块 StatisTables.bas Option Explicit Option Base 1 ' ******************************************************************************* ' 本模块提供对一些常用的数理统计表的查询服务。除特别说明外,数据来自: ' 《常用数理统计表》 ,中科院数学所概率统计室,科学出版社,1979 ' ******************************************************************************* ' 根据给定的自由度及α值(仅限于 0.05 及 0.01,否则返回负数)返回对应的 Tα值 ' 数据来自 P.8:7. t 分布的双侧分位数表 Function TTest(idF As Integer, dAlpha As Single) As Double Dim tValues() As Variant On Error GoTo TTestFail Select Case dAlpha Case 0.05 tValues() = Array(12.706, 4.303, 3.182, 2.776, 2.571, 2.447, 2.365, 2.306, 2.262, 2.228, 2.201, 2.179, 2.16, 2.145, 2.131, 2.12, 2.11, _ 2.101, 2.093, 2.086, 2.08, 2.074, 2.069, 2.064, 2.06, 2.056, 2.052, 2.048, 2.045, 2.042, 2.021, 2#, 1.98, 1.96) Case 0.01 tValues() = Array(63.657, 9.925, 5.841, 4.604, 4.032, 3.707, 3.499, 3.355, 3.25, 3.169, 3.106, 3.055, 3.012, 2.977, 2.947, 2.921, 2.898, _ 2.878, 2.861, 2.845, 2.831, 2.819, 2.807, 2.797, 2.787, 2.779, 2.771, 2.763, 2.756, 2.75, 2.704, 2.66, 2.617, 2.576) Case Else modMessage = "本部件当前仅支持 0.05 及 0.01 两种显著性!" TTest = caiCancel Exit Function End Select Select Case idF Case Is <= 30 TTest = tValues(idF) Case 31 To 40 TTest = tValues(31) Case 41 To 50 TTest = tValues(32) Case 61 To 120 TTest = tValues(33) Case Is > 120 TTest = tValues(34) End Select Exit Function TTestFail: modMessage = "检索多重比较 LSD t 分布值时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description TTest = caiError End Function ' 按给定的自由度(idF)、处理个数(iSize<=20)及显著水平(iSigLevel= 0.05 or 0.01)提供 SSR 值。 ' 当本函数顺利完成时(返回 CaiOK)dSSR()即含有这些 SRR 值。dSSR() 应该含有 iSize-1 个 member ' 数据源: 《农业试验统计》 ,莫惠栋,p.592 表 10 ? Function DuncanSSR(ByRef dSSR() As Double, iSize As Integer, idF As Integer, dSigLevel As Double) As Integer Dim I As Integer, iT As Integer Dim SSr() As Variant, Sz() As Variant On Error GoTo SSRFail If iSize > 20 Then ' the <SSRValue Table> avialable to me only supports the multi-Comparision of 20 treatments DuncanSSR = caiCancel Exit Function Else Sz() = Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20) End If ' Assign the SSR Values for given dFs to Array SSR(). Select Case dSigLevel Case 0.01 Select Case idF Case 1 SSr() = Array(90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#, 90#) Case 2 SSr() = Array(14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#, 14#) Case 3 SSr() = Array(8.26, 8.5, 8.6, 8.7, 8.8, 8.9, 8.9, 9#, 9#, 9#, 9.1, 9.2, 9.3, 9.3) Case 4 SSr() = Array(6.51, 6.8, 6.9, 7#, 7.1, 7.1, 7.2, 7.2, 7.3, 7.3, 7.4, 7.4, 7.5, 7.5) Case 5 SSr() = Array(5.7, 5.96, 6.11, 6.18, 6.26, 6.33, 6.4, 6.44, 6.5, 6.6, 6.6, 6.7, 6.7, 6.8) Case 6 SSr() = Array(5.24, 5.51, 5.65, 5.73, 5.81, 5.88, 5.95, 6#, 6#, 6.1, 6.2, 6.2, 6.3, 6.3) Case 7 SSr() = Array(4.95, 5.22, 5.37, 5.45, 5.53, 5.61, 5.69, 5.73, 5.8, 5.8, 5.9, 5.9, 6#, 6#) Case 8 SSr() = Array(4.74, 5#, 5.14, 5.23, 5.32, 5.4, 5.47, 5.51, 5.5, 5.6, 5.7, 5.7, 5.8, 5.8) Case 9 SSr() = Array(4.6, 4.86, 4.99, 5.08, 5.17, 5.25, 5.32, 5.36, 5.4, 5.5, 5.5, 5.6, 5.7, 5.7) Case 10 SSr() = Array(4.48, 4.73, 4.88, 4.96, 5.06, 5.13, 5.2, 5.24, 5.28, 5.36, 5.42, 5.48, 5.54, 5.55) Case 11 SSr() = Array(4.39, 4.63, 4.77, 4.86, 4.94, 5.01, 5.06, 5.12, 5.15, 5.24, 5.28, 5.34, 5.38, 5.39) Case 12 SSr() = Array(4.32, 4.55, 4.68, 4.76, 4.84, 4.92, 4.96, 5.02, 5.07, 5.13, 5.17, 5.22, 5.24, 5.26) Case 13 SSr() = Array(4.26, 4.48, 4.62, 4.69, 4.74, 4.84, 4.88, 4.94, 4.98, 5.04, 5.08, 5.13, 5.14, 5.15) Case 14 SSr() = Array(4.21, 4.42, 4.55, 4.63, 4.7, 4.78, 4.83, 4.87, 4.91, 4.96, 5#, 5.04, 5.06, 5.07) Case 15 SSr() = Array(4.17, 4.37, 4.5, 4.58, 4.64, 4.72, 4.77, 4.81, 4.84, 4.9, 4.94, 4.97, 4.99, 5#) Case 16 SSr() = Array(4.13, 4.34, 4.45, 4.54, 4.6, 4.67, 4.72, 4.76, 4.79, 4.84, 4.88, 4.91, 4.93, 4.94) Case 17 SSr() = Array(4.1, 4.3, 4.41, 4.5, 4.56, 4.63, 4.68, 4.72, 4.75, 4.8, 4.83, 4.86, 4.88, 4.89) Case 18 SSr() = Array(4.07, 4.27, 4.38, 4.46, 4.53, 4.59, 4.64, 4.68, 4.71, 4.76, 4.79, 4.82, 4.84, 4.85) Case 19 SSr() = Array(4.05, 4.24, 4.35, 4.43, 4.5, 4.56, 4.61, 4.64, 4.67, 4.72, 4.76, 4.79, 4.81, 4.82) Case 20 SSr() = Array(4.02, 4.22, 4.33, 4.4, 4.47, 4.53, 4.58, 4.61, 4.65, 4.69, 4.73, 4.76, 4.78, 4.79) Case 21, 22 SSr() = Array(3.99, 4.17, 4.28, 4.36, 4.42, 4.48, 4.53, 4.57, 4.6, 4.65, 4.68, 4.71, 4.74, 4.75) Case 23, 24 SSr() = Array(3.96, 4.14, 4.24, 4.33, 4.39, 4.44, 4.49, 4.53, 4.57, 4.62, 4.64, 4.67, 4.7, 4.72) Case 26, 26 SSr() = Array(3.93, 4.11, 4.21, 4.3, 4.36, 4.41, 4.46, 4.5, 4.53, 4.58, 4.62, 4.65, 4.67, 4.69) Case 27, 28 SSr() = Array(3.91, 4.08, 4.18, 4.28, 4.34, 4.39, 4.43, 4.47, 4.51, 4.56, 4.6, 4.62, 4.65, 4.67) Case 29, 30 SSr() = Array(3.89, 4.06, 4.16, 4.22, 4.32, 4.36, 4.41, 4.45, 4.48, 4.54, 4.58, 4.61, 4.63, 4.65) Case 31 To 40 SSr() = Array(3.82, 3.99, 4.1, 4.17, 4.24, 4.3, 4.34, 4.37, 4.41, 4.46, 4.51, 4.54, 4.57, 4.59) Case 41 To 60 SSr() = Array(3.76, 3.92, 4.03, 4.12, 4.17, 4.23, 4.27, 4.31, 4.34, 4.39, 4.44, 4.47, 4.5, 4.53) Case 60 To 100 SSr() = Array(3.71, 3.86, 3.98, 4.06, 4.11, 4.17, 4.21, 4.25, 4.29, 4.35, 4.38, 4.42, 4.45, 4.48) Case Is > 100 SSr() = Array(3.64, 3.8, 3.9, 3.98, 4.04, 4.09, 4.14, 4.17, 4.2, 4.26, 4.31, 4.34, 4.38, 4.41) End Select Case 0.05 Select Case idF Case 1 SSr() = Array(18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#, 18#) Case 2 SSr() = Array(6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09, 6.09) Case 3 SSr() = Array(4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5) Case 4 SSr() = Array(3.93, 4.01, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02, 4.02) Case 5 SSr() = Array(3.64, 3.74, 3.79, 3.83, 3.83, 3.83, 3.83, 3.83, 3.83, 3.83, 3.83, 3.83, 3.83, 3.83) Case 6 SSr() = Array(3.46, 3.58, 3.64, 3.68, 3.68, 3.68, 3.68, 3.68, 3.68, 3.68, 3.68, 3.68, 3.68, 3.68) Case 7 SSr() = Array(3.35, 3.47, 3.54, 3.58, 3.6, 3.61, 3.61, 3.61, 3.61, 3.61, 3.61, 3.61, 3.61, 3.61) Case 8 SSr() = Array(3.26, 3.39, 3.47, 3.52, 3.55, 3.56, 3.56, 3.56, 3.56, 3.56, 3.56, 3.56, 3.56, 3.56) Case 9 SSr() = Array(3.2, 3.34, 3.41, 3.47, 3.5, 3.52, 3.52, 3.52, 3.52, 3.52, 3.52, 3.52, 3.52, 3.52) Case 10 SSr() = Array(3.15, 3.3, 3.37, 3.43, 3.46, 3.47, 3.47, 3.47, 3.47, 3.47, 3.47, 3.47, 3.47, 3.48) Case 11 SSr() = Array(3.11, 3.27, 3.35, 3.39, 3.43, 3.44, 3.45, 3.46, 3.46, 3.46, 3.46, 3.46, 3.47, 3.48) Case 12 SSr() = Array(3.08, 3.23, 3.33, 3.36, 3.4, 3.42, 3.44, 3.44, 3.46, 3.46, 3.46, 3.46, 3.47, 3.48) Case 13 SSr() = Array(3.06, 3.21, 3.3, 3.35, 3.38, 3.41, 3.42, 3.44, 3.45, 3.45, 3.46, 3.46, 3.47, 3.47) Case 14 SSr() = Array(3.03, 3.18, 3.27, 3.33, 3.37, 3.39, 3.41, 3.42, 3.44, 3.45, 3.46, 3.46, 3.47, 3.47) Case 15 SSr() = Array(3.01, 3.16, 3.25, 3.31, 3.36, 3.38, 3.4, 3.42, 3.43, 3.44, 3.45, 3.46, 3.47, 3.47) Case 16 SSr() = Array(3#, 3.15, 3.23, 3.3, 3.34, 3.37, 3.39, 3.41, 3.43, 3.44, 3.45, 3.46, 3.47, 3.47) Case 17 SSr() = Array(2.98, 3.13, 3.22, 3.28, 3.33, 3.36, 3.38, 3.4, 3.42, 3.44, 3.45, 3.46, 3.47, 3.47) Case 18 SSr() = Array(2.97, 3.12, 3.21, 3.27, 3.32, 3.35, 3.37, 3.39, 3.41, 3.43, 3.45, 3.46, 3.47, 3.47) Case 19 SSr() = Array(2.96, 3.11, 3.19, 3.26, 3.31, 3.35, 3.37, 3.39, 3.41, 3.43, 3.44, 3.46, 3.47, 3.47) Case 20 SSr() = Array(2.95, 3.1, 3.18, 3.25, 3.3, 3.34, 3.36, 3.38, 3.4, 3.43, 3.44, 3.46, 3.46, 3.47) Case 21, 22 SSr() = Array(2.93, 3.08, 3.17, 3.24, 3.29, 3.32, 3.35, 3.37, 3.39, 3.42, 3.44, 3.45, 3.46, 3.47) Case 23, 24 SSr() = Array(2.92, 3.07, 3.15, 3.22, 3.28, 3.31, 3.34, 3.37, 3.38, 3.41, 3.44, 3.45, 3.46, 3.47) Case 26, 26 SSr() = Array(2.91, 3.06, 3.14, 3.21, 3.27, 3.3, 3.34, 3.36, 3.38, 3.41, 3.43, 3.45, 3.46, 3.47) Case 27, 28 SSr() = Array(2.9, 3.04, 3.13, 3.2, 3.26, 3.3, 3.33, 3.35, 3.37, 3.4, 3.43, 3.45, 3.46, 3.47) Case 29, 30 SSr() = Array(2.89, 3.04, 3.12, 3.2, 3.25, 3.29, 3.32, 3.35, 3.37, 3.4, 3.43, 3.44, 3.46, 3.47) Case 31 To 40 SSr() = Array(2.86, 3.01, 3.1, 3.17, 3.22, 3.27, 3.3, 3.33, 3.35, 3.39, 3.42, 3.44, 3.46, 3.47) Case 41 To 60 SSr() = Array(2.83, 2.98, 3.08, 3.14, 3.2, 3.24, 3.28, 3.31, 3.33, 3.37, 3.4, 3.43, 3.45, 3.47) Case 60 To 100 SSr() = Array(2.8, 2.95, 3.05, 3.12, 3.18, 3.22, 3.26, 3.29, 3.32, 3.36, 3.4, 3.42, 3.45, 3.47) Case Is > 100 SSr() = Array(2.77, 2.92, 3.02, 3.09, 3.15, 3.19, 3.23, 3.26, 3.29, 3.34, 3.38, 3.41, 3.44, 3.47) End Select Case Else modMessage = "本部件当前仅支持 0.05 及 0.01 两种显著性!" DuncanSSR = caiCancel Exit Function End Select ' Assign SSR values to dSSR() for return according to iSize iT = IIf(iSize < 10, iSize, 10) For I = 1 To iT - 1 dSSR(I) = SSr(I) ' Note! SSR(1) corresponding to Size=2, SSR(2) --- Size=3 !! Next If iSize > 10 Then ' Note: SSR(10) corresponding to Size 12, SSR(11) --- Size 14, ...... ! i.e. SSR*iT) --- Size Sz(iT) ! iT = 10 For I = 10 To iSize - 1 While Sz(iT) < I + 1 ' since SSR(i) corresponding to Size=I+1 !!! iT = iT + 1 Wend dSSR(I) = SSr(iT) Next I End If DuncanSSR = caiOK Exit Function SSRFail: modMessage = "检索多重比较 Duncan SSR 值时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description DuncanSSR = caiError End Function ' 返回“方差同质性查验的 Cochran 法(Testing the Equality of Variances according to Cochran)” 的关键值 G(iSize, idF),其中 ' iSize -- 参加检验的方差个数; idF -- 每个方差的样本自由度;dAlpha -- 显著性,必须 为 0.05 或 0.01。 ' Refer to: "Applied Stastistics (2nd. Edition)" by Lothar Sachs, P.497 Function CochranTab(iSize As Integer, idF As Integer, dAlpha) As Double Dim I As Integer Dim CochranV() As Variant, dFs() As Variant dFs() = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 36, 144, 999999) I=1 Do While (idF > dFs(I)) I=I+1 Loop Select Case dAlpha Case 0.05 Select Case iSize Case 2 CochranV() = Array(0.9985, 0.975, 0.9392, 0.9057, 0.8772, 0.8534, 0.8332, 0.8159, 0.801, 0.788, 0.7341, 0.6602, 0.5813, 0.5) Case 3 CochranV() = Array(0.9669, 0.8709, 0.7977, 0.7457, 0.7071, 0.6771, 0.653, 0.6333, 0.6167, 0.6025, 0.5466, 0.4748, 0.4031, 0.3333) Case 4 CochranV() = Array(0.9065, 0.7679, 0.6841, 0.6287, 0.5895, 0.5598, 0.5365, 0.5175, 0.5017, 0.4884, 0.4366, 0.372, 0.3093, 0.25) Case 5 CochranV() = Array(0.8412, 0.6838, 0.5981, 0.5441, 0.5065, 0.4783, 0.4564, 0.4387, 0.4241, 0.4118, 0.3645, 0.3066, 0.2513, 0.2) Case 6 CochranV() = Array(0.7808, 0.6161, 0.5321, 0.4803, 0.4447, 0.4184, 0.398, 0.3817, 0.3682, 0.3568, 0.3135, 0.2612, 0.2119, 0.1667) Case 7 CochranV() = Array(0.7271, 0.5612, 0.48, 0.4307, 0.3974, 0.3726, 0.3535, 0.3384, 0.3259, 0.3154, 0.2756, 0.2278, 0.1833, 0.1429) Case 8 CochranV() = Array(0.6798, 0.5157, 0.4377, 0.391, 0.3595, 0.3362, 0.3185, 0.3043, 0.2926, 0.2829, 0.2462, 0.2022, 0.1616, 0.125) Case 9 CochranV() = Array(0.6385, 0.4775, 0.4027, 0.3584, 0.3286, 0.3067, 0.2901, 0.2768, 0.2659, 0.2568, 0.2226, 0.182, 0.1446, 0.1111) Case 10 CochranV() = Array(0.602, 0.445, 0.3733, 0.3311, 0.3029, 0.2823, 0.2666, 0.2541, 0.2439, 0.2353, 0.2032, 0.1655, 0.1308, 0.1) Case 11, 12 CochranV() = Array(0.541, 0.3924, 0.3264, 0.288, 0.2624, 0.2439, 0.2299, 0.2187, 0.2098, 0.202, 0.1737, 0.1403, 0.11, 0.0833) Case 13 To 15 CochranV() = Array(0.4709, 0.3346, 0.2758, 0.2419, 0.2195, 0.2034, 0.1911, 0.1815, 0.1736, 0.1671, 0.1429, 0.1144, 0.0889, 0.0667) Case 16 To 20 CochranV() = Array(0.3894, 0.2705, 0.2205, 0.1921, 0.1735, 0.1602, 0.1501, 0.1422, 0.1357, 0.1303, 0.1108, 0.0879, 0.0675, 0.05) Case 21 To 24 CochranV() = Array(0.3434, 0.2354, 0.1907, 0.1656, 0.1493, 0.1374, 0.1286, 0.1216, 0.116, 0.1113, 0.0942, 0.0743, 0.0567, 0.0417) Case 25 To 30 CochranV() = Array(0.2929, 0.198, 0.1593, 0.1377, 0.1237, 0.1137, 0.1061, 0.1002, 0.0958, 0.0921, 0.0771, 0.0604, 0.0457, 0.0333) Case 31 To 40 CochranV() = Array(0.237, 0.1576, 0.1259, 0.1082, 0.0968, 0.0887, 0.0827, 0.078, 0.0745, 0.0713, 0.0595, 0.0462, 0.0347, 0.025) Case Else modMessage = "本表不支持参试组个数大于 40 的情形!" _ & vbCrLf & "(同质检验 Cochran 法一般仅应用于参试的方差数不 大于 10 的情形。 )" CochranTab = caiError Exit Function End Select Case 0.01 Select Case iSize Case 2 CochranV() = Array(0.9999, 0.995, 0.9794, 0.9586, 0.9373, 0.9172, 0.8988, 0.8823, 0.8674, 0.8539, 0.7949, 0.7067, 0.6062, 0.5) Case 3 CochranV() = Array(0.9933, 0.9423, 0.8831, 0.8335, 0.7933, 0.7606, 0.7335, 0.7107, 0.6912, 0.6743, 0.6059, 0.5153, 0.423, 0.3333) Case 4 CochranV() = Array(0.9676, 0.8643, 0.7814, 0.7212, 0.6761, 0.641, 0.6129, 0.5897, 0.5702, 0.5536, 0.4884, 0.4057, 0.3251, 0.25) Case 5 CochranV() = Array(0.9279, 0.7885, 0.6957, 0.6329, 0.5875, 0.5531, 0.5259, 0.5037, 0.4854, 0.4697, 0.4094, 0.3351, 0.2644, 0.2) Case 6 CochranV() = Array(0.8828, 0.7218, 0.6258, 0.5635, 0.5195, 0.4866, 0.4608, 0.4401, 0.4229, 0.4084, 0.3529, 0.2858, 0.2229, 0.1667) Case 7 CochranV() = Array(0.8376, 0.6644, 0.5685, 0.508, 0.4659, 0.4347, 0.4105, 0.3911, 0.3751, 0.3616, 0.3105, 0.2494, 0.1929, 0.1429) Case 8 CochranV() = Array(0.7945, 0.6152, 0.5209, 0.4627, 0.4226, 0.3932, 0.3704, 0.3522, 0.3373, 0.3248, 0.2779, 0.2214, 0.17, 0.125) Case 9 CochranV() = Array(0.7544, 0.5727, 0.481, 0.4251, 0.387, 0.3592, 0.3378, 0.3207, 0.3067, 0.295, 0.2514, 0.1992, 0.1521, 0.1111) Case 10 CochranV() = Array(0.7175, 0.5358, 0.4469, 0.3934, 0.3572, 0.3308, 0.3106, 0.2945, 0.2813, 0.2704, 0.2297, 0.1811, 0.1376, 0.1) Case 11, 12 CochranV() = Array(0.6528, 0.4751, 0.3919, 0.3428, 0.268, 0.2535, 0.2419, 0.232, 0.1961, 0.1535, 0.1157, 0.0833) Case 13 To 15 CochranV() = Array(0.5747, 0.4069, 0.3317, 0.2882, 0.2228, 0.2104, 0.2002, 0.1918, 0.1612, 0.1251, 0.0934, 0.0667) Case 16 To 20 CochranV() = Array(0.4799, 0.3297, 0.2654, 0.2288, 0.1748, 0.1646, 0.1567, 0.1501, 0.1248, 0.096, 0.0709, 0.05) Case 21 To 24 CochranV() = Array(0.4247, 0.2871, 0.2295, 0.197, 0.1495, 0.1406, 0.1338, 0.1283, 0.106, 0.081, 0.0595, 0.0417) Case 25 To 30 CochranV() = Array(0.3632, 0.2412, 0.1913, 0.1635, 0.1232, 0.1157, 0.11, 0.1054, 0.0867, 0.0658, 0.048, 0.0333) Case 31 To 40 CochranV() = Array(0.294, 0.1915, 0.1508, 0.1281, 0.0957, 0.0898, 0.0853, 0.0816, 0.0668, 0.0503, 0.0363, 0.025) Case Else 0.3099, 0.2861, 0.2593, 0.2386, 0.2048, 0.1877, 0.1759, 0.1608, 0.1454, 0.1327, 0.1135, 0.1033, modMessage = "本表不支持参试组个数大于 40 的情形!" _ & vbCrLf & "(同质检验 Cochran 法一般仅应用于参试的方差数不 大于 10 的情形。 )" CochranTab = caiError Exit Function End Select Case Else modMessage = "本部件当前仅支持 0.05 及 0.01 两种显著性!" CochranTab = caiCancel Exit Function End Select CochranTab = CochranV(I) End Function ' 根据给定的自由度 idF 及α值(仅限于 0.05 及 0.01,否则返回负数)返回对应的卡方值 X_Square ' 数据来自 P.6:5. X_Square 分布的上侧分位数表 Function XSquareTab(idF As Integer, dAlpha As Double) As Double Dim XValues() As Variant If idF > 30 Then modMessage = "本卡方表支持的最大自由度值为 30!" XSquareTab = caiError Exit Function End If Select Case dAlpha Case 0.05 XValues() = Array(3.841, 5.991, 7.815, 9.488, 11.07, 12.592, 14.067, 15.507, 16.919, 18.307, 19.675, 21.026, 22.362, 23.685, 24.996, _ 26.296, 27.587, 28.869, 30.144, 31.41, 32.671, 33.924, 35.172, 36.415, 37.652, 38.885, 40.113, 41.337, 42.557, 43.773) Case 0.01 XValues() = Array(6.635, 9.21, 11.345, 12.277, 15.068, 16.812, 18.475, 20.09, 21.666, 23.209, 24.725, 26.217, 27.688, 29.141, 30.578, _ 32#, 33.409, 34.805, 36.191, 37.566, 38.932, 40.289, 41.638, 42.98, 44.314, 45.642, 46.963, 48.278, 49.588, 50.892) Case Else modMessage = "本部件当前仅支持 0.05 及 0.01 两种显著性!" XSquareTab = caiCancel Exit Function End Select XSquareTab = XValues(idF) End Function ' 根据给定的自由度 idF 及α值(仅限于 0.05 及 0.01,否则返回负数)返回对应的 Ra 值 ' 它是检验两个统计量是否相关的临界值 ' 数据来自 P.18:12. 检验相关系数=0 的临界值 Ra 表 Function RaTab(idF As Integer, dAlpha As Double) As Double Dim I As Integer Dim RaVals() As Variant, dFs() As Variant If idF > 100 Then modMessage = "本 Ra 表支持的最大自由度值为 100!" RaTab = caiError Exit Function End If dFs() = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, _ 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100) I=1 Do While (idF > dFs(I)) I=I+1 Loop Select Case dAlpha Case 0.05 RaVals() = Array(0.99692, 0.95, 0.8783, 0.8114, 0.7545, 0.7067, 0.6664, 0.6319, 0.6021, 0.576, _ 0.5529, 0.5324, 0.5139, 0.4973, 0.4821, 0.4683, 0.4555, 0.4438, 0.4329, 0.4227, _ 0.3809, 0.3494, 0.3246, 0.3044, 0.2875, 0.2732, 0.25, 0.2319, 0.2172, 0.205, 0.1946) Case 0.01 RaVals() = Array(0.999877, 0.99, 0.95873, 0.9172, 0.8745, 0.8343, 0.7977, 0.7646, 0.7348, 0.7079, _ 0.6835, 0.6614, 0.6411, 0.6226, 0.6055, 0.5897, 0.5751, 0.5614, 0.5487, 0.5368, _ 0.4869, 0.4487, 0.4182, 0.3932, 0.3721, 0.3541, 0.3248, 0.3017, 0.283, 0.2673, 0.254) Case Else modMessage = "本部件当前仅支持 0.05 及 0.01 两种显著性!" RaTab = caiCancel Exit Function End Select RaTab = RaVals(I) End Function 类模块 clsStatisAnova.cls Option Explicit Option Base 1 ' ********************************************************************** ' 本 Class 符合 COM 设计规范,可提供方差分析服务:包括单因子、双因 ' 子 (三因子?)方差分析。原始数据(Float-32)需以多维数组的形式 ' 提供(单因子的为二维,双因子的为三维)。当原始数据不完整时, ' 相应的数组项必须赋值为 cNonSense,当前定义为 -9999 ! ' ********************************************************************** '======================================================================= ' Define two Custom Types publicly '======================================================================= ' Define a Type for store the Statistic Values of Anova Analysis Public Type AnovaStatis ' 自由度 dFt As Integer ' Degrees of Freedom -- Total dFa As Integer ' ...... -- Factor A, e.g. the "Test Sites" dFb As Integer dFr As Integer dFab As Integer dFerr As Integer ' 平方和 SSt As Double ' Total Square Sum of (Xijk-Average(Xijk)) SSa As Double ' Total Squire Sum about the First Factor A, e.g. the "Test Sites" SSb As Double ' ...... , e.g. "Varieties" SSr As Double ' ...... , e.g. "Blocks" SSab As Double ' ...... about "Cross Effections" SSerr As Double ' ...... about "Experimental Error" GrandMean As Double ' Mean Value of all Samples ' F 值及对应的概率(显著性) FVr As Double ' F Value from Repitations inside factor A. (来自试点内区组); (SSr/dFr)/(SSerr/dFerr) = FVb As Double ' F Value from factor B, e.g. Varieties. (来自品种); ' =(SSb/dFb)/Deno, here Deno=(SSab/dFab) if in Radomized mode or =(SSerr/dFerr) if Fixed mode FVa As Double =(SSa/dFa)/(SSerr/dFerr) ' F Value from factor A, e.g. Test Sites. FVab As Double ' F Value from the iteraction of factor A and B. =(SSab/dFab)/(SSerr/dFerr) FPr As Double ' Corresponding significense ...... FPb As Double FPa As Double FPab As Double End Type ( 来 自 试 点 ); (来自试点 x 品种); ' to store the Result of Multiple Comparision for each Group that presents in MC analysis ' i.e. the whole result should be stored in an Array of this type and the groups should ordered descendly Public Type MCReport Index As Integer ' the group correspondint to the IndexTh. member (Counted from 1) in the original resource array Mean As Double ' mean value of the group Classif As String ' the classifications of the group. its size always=20, with the 1st 10 chars contain _ the classification for 0.05 Significance, the last 10, 0.01 Significance, e.g. " cde DE " End Type ' to store the result of Equality Test for the Variances Public Type EqualityResult MethodName As String ' either "Cochran" or "Bartlette" Result As Integer ' < 0 -- Test Failed, means other members are meanless; >= 0 -- Test Successfully completed: ' here, 0 -- Equlity Accepted, 1 -- Equlity Rejected on 0.05 Significance, 2 -- Rejected on 0.01 Significance; Size As Integer ' Number of Variances presented in Test dF As Integer ' the Degree of Freedom of each Variance EvalValue As Double ' Evaluated Value, i.e. "G_max" for Cochran, "X_eq" for Bartlette CritVal005 As Double ' the Critical Value on 0.05 Significance found from Table: Cochran Table or X_Square Table CritVal001 As Double ' the Critical Value on 0.01 Significance found from Table: Cochran Table or X_Square Table End Type ' to store the result of Regresion Analysis Public Type RegresionResult Result As Integer ' < 0 -- Test Failed, means other members are meanless; >= 0 -Test Successfully completed: ' here, 0 -- Independency (ρ=0) Accepted, 1 -- Independency Rejected on 0.05 Significance, 2 -- Rejected on 0.01 Significance; Size As Integer ' Number of Samples, i.e. (Xi, Yi)s, presented in Test Slope As Double ' Formular: Y=k*X + b, the value of k Intercept As Double ' the value of b CorCorf As Double ' Correlative Corefficient between X and Y, evaluated from Sample Data (Xi, Yi) CritRa005 As Double ' the Critical Value on 0.05 Significance found from RA Table for Independency Test CritRa001 As Double ' the Critical Value on 0.01 Significance found from RA Table for Independency Test End Type '============================================================================== ========================================== ' current states of Anova analysis Private mAnovaResultState As Integer ' 0 -- Initial State, mAnovaResult contains no valid information ; <0 -- Error happened, analysisi failed ' 10+i -- mAnovaResult contains the results of Anova1; 20 + i -- the results of Anova2 ' here, i=1 -- .SS*s, .dF*s and correponding Array T*s() are valid, ' i=2 -- F Test finished, all members of mAnovaResult are Valid ' 本部件把 Anova2 分成两种类型: 区试(一年多点)联合方差分析; 双因子随机区组试验. 每 种 ' 类型又可对其因子选择固定/随机模式, 这些信息就存储在这里 Private mAnova2Mode As Integer ' 1 -- 联合分析, A(试点)固定; 2 -- 联合分析, A(试点)随机; ' 11 -- 随机区组, A, B 都固定; 12 -- 随机区组, A 固定, B 随机; ' 13 -- 随机区组, A 随机, B 固定; 14 -- 随机区组, A,B 都随机. Private mDataState As Integer ' =0: mData() contains no valid source data; ' >0: contains the valid Samples Data, and represents the dimention of mData() ' <0: contains the valid data to do some type of analysisi, e.g. Equality, Multiple Comparesion, etc., _ |mDim| represents the dimention of mData(). ' Note: after runing Anova1WSD(), mDataState = -3 ' Source Data for analyzing Private mData() As Single ' the result of Anova Analysis Private mAnovaResult As AnovaStatis ' The detail information that the Object want to return to the client (Caller) Private mMessage As String ' the normal Report of Anova Analysis for Crop Reginal Test Private mMCompReport() As MCReport ' mVRData() is to store the Variance of each Group that takes part in Equlity Test. ' It may also be used as 2 Dimentional (Xi, Yi) to store the Sample data for Regression Analysis ' The Data stored in original order and may not be sorted yet. Private mVRData() As Double Private mVRDataState As Integer ' =0: mVRData() contains no valid data; =1: contains Variances; ' =2 contains (Xi, Yi)s for Regression Analysis. Private mEqTestResult As EqualityResult Private mRegresResult As RegresionResult ' store some middle clclating results to be shared among methods of the class Private T1() As Double, T2() As Double, T31() As Double, X21() As Double ' Store the index of Factor A, only valid during Anova1 Analysis and its related Tests, i.e. it indicates that ' the Sample Data currently used by Anova1 are stored in mData(mIdxA, *, *) ! Private mIdxA As Integer ' ******************************************************************** ' Define properties for readonly accessing the members of the class ' ******************************************************************** Public Property Get iAnovaResultState() As Integer iAnovaResultState = mAnovaResultState End Property Public Property Get ctAnovaResult() As AnovaStatis ctAnovaResult = mAnovaResult End Property Public Property Get strMessage() As String strMessage = mMessage End Property ' ref to. "Putting Property Procedures to Work for You", a section in "Programming with Object" ' of <Programmer's Guide>, MSDN Lib, <Using Visual Basic>. Public Property Get ctMCompReport(Index As Integer) As MCReport ' Should do some check of the value of Index for reliability here ctMCompReport = mMCompReport(Index) End Property Public Property Get dVariances(Index As Integer) As Double If mVRDataState = 1 Then If Index > 0 And Index <= UBound(mVRData) Then dVariances = mVRData(Index) Else dVariances = cNonSense End If Else dVariances = cNonSense End If End Property Public Property Get ctEqTestResult() As EqualityResult ctEqTestResult = mEqTestResult End Property Public Property Get dXYSamples(I As Integer, J As Integer) As Double If mVRDataState = 2 Then If I > 0 And I < 3 And J > 0 And J <= UBound(mVRData, 2) Then dXYSamples = mVRData(I, J) Else dXYSamples = cNonSense End If Else dXYSamples = cNonSense End If End Property Public Property Get ctRegresResult() As RegresionResult ctRegresResult = mRegresResult End Property ' ******************************************************************************* ****** ' Private Routines for internal use ' ******************************************************************************* ****** ' Initialize mAnovaResult and release the momory ocupied by Dynamic Arrys and mMCCompREport Private Sub InitResults() Dim Item As Variant With mAnovaResult .dFa = 0: .dFab = 0: .dFb = 0: .dFerr = 0: .dFr = 0: .dFt = 0 .SSa = 0: .SSab = 0: .SSb = 0: .SSerr = 0: .SSr = 0: .SSt = 0 .FPa = 0: .FPab = 0: .FPb = 0: .FPr = 0: .FVa = 0: .FVab = 0: .FVb = 0: .FVr = 0 .GrandMean = 0 End With mIdxA = -1 ReDim T1(1), T2(1), T31(1), X21(1) ReDim mMCompReport(1) End Sub ' Check the Array of Sopurce Data for Anova Analysis and assign it to mData() ' Return the number of dimentions of mData() if successed Private Function CheckAnovaSourceData(ByRef sData() As Single, ByVal iDim As Integer) As Integer ' iDim -- the dimention of Source Data Dim n1 As Integer, n2 As Integer, n3 As Integer Dim I As Integer, J As Integer, k As Integer, iT As Integer Dim sT As Single On Error GoTo DataErr n1 = UBound(sData, 1) - LBound(sData, 1) + 1 If n1 < 2 Then mMessage = "因子 A 的样本数小于 2," CheckAnovaSourceData = caiCancel Exit Function End If If iDim > 1 Then n2 = UBound(sData, 2) - LBound(sData, 2) + 1 If n2 < 2 Then If iDim = 1 Then mMessage = "样本无重复,本系统暂无法分析!" Else mMessage = "因子 B 的样本数小于 2," End If CheckAnovaSourceData = caiCancel Exit Function End If End If If iDim > 2 Then n3 = UBound(sData, 3) - LBound(sData, 3) + 1 If n3 < 2 Then mMessage = "样本无重复,本系统暂无法分析!" CheckAnovaSourceData = caiCancel Exit Function End If End If Select Case iDim Case 1 ReDim mData(n1) For I = 1 To n1 sT = sData(I + LBound(sData) - 1) If sT = cNonSense Then mMessage = "所提供的原始数据不平衡或有缺值,目前版本暂不 能对此进行方差分析!" mDataState = 0 CheckAnovaSourceData = caiCancel Exit Function End If mData(I) = sT Next I iT = 1 Case 2 ReDim mData(1, n1, n2) ' Add the 1st dimention to make Anova analysis for RCB (Single Site) more consistent with the analysis for Combined (Single yera, Multiple Sites) '?1 For I = 1 To n1 For J = 1 To n2 sT = sData(I + LBound(sData, 1) - 1, J + LBound(sData, 2) - 1) If sT = cNonSense Then mMessage = "所提供的原始数据不平衡或有缺值,目前版本暂不 能对此进行方差分析!" mDataState = 0 CheckAnovaSourceData = caiCancel Exit Function End If mData(1, I, J) = sT Next J Next I iT = 3 Case 3 ReDim mData(n1, n2, n3) For I = 1 To n1 For J = 1 To n2 For k = 1 To n3 sT = sData(I + LBound(sData, 1) - 1, J + LBound(sData, 2) - 1, k + LBound(sData, 3) - 1) If sT < 0 Then mMessage = "所提供的原始数据不平衡或有缺值,目前版本 暂不能处理此类数据," mDataState = 0 CheckAnovaSourceData = caiCancel Exit Function End If mData(I, J, k) = sT Next k Next J Next I iT = 3 Case Else mMessage = "目前版仅支持三维及以下的样本数据,抱歉!" mDataState = 0 CheckAnovaSourceData = caiCancel Exit Function End Select mDataState = iT CheckAnovaSourceData = iT Exit Function DataErr: mMessage = "所提供的原始数据数组的维数不符合要求," mDataState = caiError CheckAnovaSourceData = caiError End Function ' Calclating Statistic Values needed for Anova1 Analysis ' idxA is to indicate that the source data are mData(idxA, *, *) Private Function CalcSSdFs1(idxA As Integer) As Integer Dim n2 As Integer, n3 As Integer Dim J As Integer, k As Integer Dim dCF As Double Dim dTemp As Double On Error GoTo Calc1Fail ' get the size of each dimention of the source data n2 = UBound(mData, 2) n3 = UBound(mData, 3) ' Calclating the Degrees of Feedom With mAnovaResult .dFt = n2 * n3 - 1 .dFb = n2 - 1 .dFr = n3 - 1 .dFerr = .dFt - .dFb - .dFr End With ' Calclating Sumary of Squiares ReDim T2(n2), T31(n3) dCF = 0 dTemp = 0 For J = 1 To n2 T2(J) = 0 For k = 1 To n3 dCF = dCF + mData(idxA, J, k) dTemp = dTemp + mData(idxA, J, k) * mData(idxA, J, k) T2(J) = T2(J) + mData(idxA, J, k) Next k Next J mAnovaResult.GrandMean = dCF / (n2 * n3) dCF = dCF * dCF / (n2 * n3) mAnovaResult.SSt = dTemp - dCF dTemp = 0 For J = 1 To n2 dTemp = dTemp + T2(J) * T2(J) Next J mAnovaResult.SSb = dTemp / n3 - dCF For k = 1 To n3 T31(k) = 0 For J = 1 To n2 T31(k) = T31(k) + mData(idxA, J, k) Next J Next k dTemp = 0 For k = 1 To n3 dTemp = dTemp + T31(k) * T31(k) Next k With mAnovaResult .SSr = dTemp / n2 - dCF .SSerr = .SSt - .SSb - .SSr If .SSerr = 0 Then mMessage = "计算发现来自试验误差的变异的平方和为 0!无法对该样本数据 作统计分析处理" CalcSSdFs1 = caiCancel Exit Function End If End With CalcSSdFs1 = caiOK Exit Function Calc1Fail: mMessage = "计算平方和时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description CalcSSdFs1 = caiError End Function ' Calclating Statistic Values needed for Anova2 Analysis Private Function CalcSSdFs2() As Integer Dim n1 As Integer, n2 As Integer, n3 As Integer Dim I As Integer, J As Integer, k As Integer Dim dCF As Double Dim iC As Integer, dTemp As Double On Error GoTo Calc2Fail ' get the size of each dimention of the source data n1 = UBound(mData, 1) n2 = UBound(mData, 2) n3 = UBound(mData, 3) ' Calclating the Degrees of Feedom With mAnovaResult .dFt = n1 * n2 * n3 - 1 .dFa = n1 - 1 .dFb = n2 - 1 .dFr = n1 * (n3 - 1) .dFab = (n1 - 1) * (n2 - 1) .dFerr = .dFt - .dFa - .dFb - .dFr - .dFab End With ' Calclating Sumary of Squiares ReDim T1(n1), T2(n2), T31(n3 * n1), X21(n2, n1) ' T2=? (tv=?): "T*v*", means total of all Sides and Repititions for each Variety For I = 1 To n2 T2(I) = 0 For J = 1 To n1 For k = 1 To n3 T2(I) = T2(I) + mData(J, I, k) Next k Next J Next I ' T31=? (Tkj=?): "Ta*r", means Total of all Varieties for eash Site's each Repitation iC = 0 For J = 1 To n1 For k = 1 To n3 iC = iC + 1 T31(iC) = 0 For I = 1 To n2 T31(iC) = T31(iC) + mData(J, I, k) Next I Next k Next J ' T1=? ' T1 : dCF=? (tj=?,cf=?) Ta**, means Total of all Varieties and Repititions for each Site, i.e. of all plots in each Site dCF = 0 For I = 1 To n1 T1(I) = 0 For J = 1 To n2 For k = 1 To n3 T1(I) = T1(I) + mData(I, J, k) dCF = dCF + mData(I, J, k) Next k Next J Next I mAnovaResult.GrandMean = dCF / (n1 * n2 * n3) dCF = dCF * dCF / (n1 * n2 * n3) ' SSt=? dTemp = 0 For I = 1 To n1 For J = 1 To n2 For k = 1 To n3 dTemp = dTemp + mData(I, J, k) * mData(I, J, k) Next k Next J Next I mAnovaResult.SSt = dTemp - dCF ' SSa=? (sse=?) dTemp = 0 For I = 1 To n1 dTemp = dTemp + T1(I) * T1(I) Next I mAnovaResult.SSa = dTemp / (n3 * n2) - dCF ' SSb=? (ssg=?) dTemp = 0 For I = 1 To n2 dTemp = dTemp + T2(I) * T2(I) Next I mAnovaResult.SSb = dTemp / (n3 * n1) - dCF ' SSr=? (ssre=?) dTemp = 0 If mAnova2Mode <= 10 Then ' 区试联合分析型, 计算来自试点内区组间的变异 For I = 1 To n3 * n1 dTemp = dTemp + T31(I) * T31(I) Next I dTemp = dTemp / n2 mAnovaResult.SSr = dTemp - mAnovaResult.SSa - dCF ' can be proved mathematically ! Else ' 随机区组试验, 计算来自区组间的变异(对因子 A 的不同处理水平同等对待) mAnovaResult.SSr = 0 For k = 1 To n3 dTemp = 0 For I = 0 To n1 - 1 dTemp = dTemp + T31(I * n3 + k) Next I mAnovaResult.SSr = mAnovaResult.SSr + dTemp * dTemp Next k mAnovaResult.SSr = mAnovaResult.SSr / (n1 * n2) - dCF End If ' X21(I,J)=? (x(i,j)=?) Note: the 1st Dimention is for Factor B, Varieties! For I = 1 To n2 For J = 1 To n1 X21(I, J) = 0 For k = 1 To n3 X21(I, J) = X21(I, J) + mData(J, I, k) Next k Next J Next I ' SSab=? ( ssge=?) dTemp = 0 For I = 1 To n1 For J = 1 To n2 dTemp = dTemp + X21(J, I) * X21(J, I) ' X21(J, I) = X21(J, I) / n3 ' Now, it is the Average of mData(i, j, *) Next J Next I With mAnovaResult .SSab = dTemp / n3 - .SSa - .SSb - dCF .SSerr = .SSt - .SSa - .SSb - .SSr - .SSab If .SSerr = 0 Then mMessage = "计算发现来自试验误差的变异的平方和为 0!无法对该样本数据 作统计分析处理" CalcSSdFs2 = caiCancel Exit Function End If If .SSab = 0 And (mAnova2Mode = 2 Or mAnova2Mode > 11) Then mMessage = "计算发现来自因子 A、B 间互作的变异的平方和为 0!" _ & "要对该样本数据作方差分析,只能把在 A、B 设为固定模式。 " CalcSSdFs2 = caiCancel Exit Function End If End With CalcSSdFs2 = caiOK Exit Function Calc2Fail: mMessage = "计算平方和时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description CalcSSdFs2 = caiError End Function ' Calclating F Valus and corresponding probablities/Significances for Anova1 Analysis ' Radomized mode only Private Function CalcAnova1Fs() As Integer Dim MSb As Double, MSr As Double, MSerr As Double ' Calclating MSs With mAnovaResult MSb = .SSb / .dFb MSr = .SSr / .dFr MSerr = .SSerr / .dFerr End With ' Calclating F Values and thier probablities With mAnovaResult .FVr = MSr / MSerr .FVb = MSb / MSerr .FPr = Ftest(.dFr, .dFerr, .FVr) .FPb = Ftest(.dFb, .dFerr, .FVb) End With CalcAnova1Fs = caiOK End Function ' Calclating F Valus and corresponding probablities/Significances for Anova2 Analysis Private Function CalcAnova2Fs() As Integer Dim MSa As Double, MSb As Double, MSr As Double, MSab As Double, MSerr As Double ' Calclating MSs With mAnovaResult MSa = .SSa / .dFa MSb = .SSb / .dFb MSab = .SSab / .dFab MSr = .SSr / .dFr MSerr = .SSerr / .dFerr End With ' Calclating F Values and thier probablities With mAnovaResult Select Case mAnova2Mode Case 1, 2, 11, 13 .FVa = MSa / MSerr .FPa = Ftest(.dFa, .dFerr, .FVa) Case 12, 14 .FVa = MSa / MSab .FPa = Ftest(.dFa, .dFab, .FVa) End Select Select Case mAnova2Mode Case 1, 11, 12 .FVb = MSb / MSerr .FPb = Ftest(.dFb, .dFerr, .FVb) Case 2, 13, 14 .FVb = MSb / MSab .FPb = Ftest(.dFb, .dFab, .FVb) End Select .FVr = MSr / MSerr .FVab = MSab / MSerr .FPr = Ftest(.dFr, .dFerr, .FVr) .FPab = Ftest(.dFab, .dFerr, .FVab) End With CalcAnova2Fs = caiOK End Function ' Anova1 Analysisi. idxA indicate what part of mData(), i.e. mData(idxA,*,*), should be used as the Sample Data Private Function Anova1Calc(idxA As Integer) As Integer Dim iT As Integer If mDataState <= 0 Then mMessage = "没收到有效的原始样本数据,无法进行单因子方差分析!" mAnovaResultState = 0 Anova1Calc = caiCancel Exit Function End If If idxA < 1 Or idxA > UBound(mData, 1) Then mMessage = "指定的因子 A(试点)的 Index 越界,即现有的样本数据集没有所指 定的数据!" Anova1Calc = caiCancel Exit Function End If InitResults ' Calclating SSs and dFs iT = CalcSSdFs1(idxA) If iT <> caiOK Then InitResults mAnovaResultState = IIf(iT = caiCancel, 0, caiError) Anova1Calc = iT Exit Function End If mAnovaResultState = 11 mIdxA = idxA ' Calclating F Values CalcAnova1Fs mAnovaResultState = 12 Anova1Calc = caiOK End Function ' 双因子有重复样本的方差分析计算 ' iMode: 1 -- 关于因子 A 的处理是随机的,0 -- 是固定的 Private Function Anova2Calc() As Integer Dim iT As Integer If mDataState <= 0 Then mMessage = "没收到有效的原始样本数据,无法进行单因子方差分析!" mAnovaResultState = 0 Anova2Calc = caiCancel Exit Function End If ' Calclating SSs and dFs iT = CalcSSdFs2() If iT <> caiOK Then InitResults mAnovaResultState = IIf(iT = caiCancel, 0, caiError) Anova2Calc = iT Exit Function End If mAnovaResultState = 21 mIdxA = 0 ' Calclating F Values CalcAnova2Fs mAnovaResultState = 22 Anova2Calc = caiOK End Function ' Multiple Comparison Test according to Duncan's Multiple-Range Method. ' dMean(): sorted means for each group, i.e. dMean(i) >= dMean(j), if i>j; ' iSize: the number of groups which's mean to be compared; ' dDev: = sqrt(MSx/n), n is the size of each group; MSx may be MSerr or MSab according to design mode: Fixed or Radomized ' idF: the degree of freedom of the dDev Private Function MultiCompSSR(dMean() As Double, iSize As Integer, dDev As Double, idF As Integer) As Integer Dim I As Integer, iT As Integer, iSz As Integer Dim dSSR() As Double Dim cReport() As Integer Dim strT As String On Error GoTo MCompSSRFail iSz = IIf(iSize < 20, iSize, 20) ReDim dSSR(iSz - 1), cReport(iSz * 20) For I = 1 To iSz * 20 cReport(I) = Asc(" ") Next I ' with 0.01 Significance If DuncanSSR(dSSR(), iSz, idF, 0.01) = caiError Then GoTo MCError If MultiCompReport(dMean(), iSz, cReport(), 10, dDev, cMcSSR, dSSR()) = caiError Then GoTo MCError ' cReport = UCase(cReport) '???! For I = 1 To iSz * 20 strT = Chr(cReport(I)) strT = UCase(strT) cReport(I) = Asc(strT) Next I ' with 0.05Significance If DuncanSSR(dSSR(), iSz, idF, 0.05) = caiError Then GoTo MCError If MultiCompReport(dMean(), iSz, cReport(), 0, dDev, cMcSSR, dSSR()) = caiError Then GoTo MCError ' Store the report ReDim mMCompReport(iSz) For I = 1 To iSz With mMCompReport(I) .Mean = dMean(I) .Classif = "" For iT = 1 To 20 .Classif = .Classif & Chr(cReport((I - 1) * 20 + iT)) Next iT End With Next I MultiCompSSR = caiOK Exit Function MCError: mMessage = modMessage MultiCompSSR = caiError Exit Function MCompSSRFail: mMessage = "实施多重比较 SSR 时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description MultiCompSSR = caiError End Function ' Multiple Comparison Test according to LSD Method. ' dMean(): sorted means for each group, i.e. dMean(i) >= dMean(j), if i>j; ' iSize: the number of groups which's mean to be compared; ' dDev: is the Comparision Constant "S=sqr(2*MSx/n), here MSx may be MSerr or MSab according to the design mode of the Test: Fixed or Radomized ' idF: the degree of freedom of the dMSe Private Function MultiCompLSD(dMean() As Double, iSize As Integer, dDev As Double, idF As Integer) As Integer Dim I As Integer, iT As Integer, iSz As Integer Dim cReport() As Integer Dim dLSD As Double Dim strT As String On Error GoTo MCompLSDFail iSz = IIf(iSize < 20, iSize, 20) ReDim cReport(iSz * 20) For I = 1 To iSz * 20 cReport(I) = Asc(" ") Next I ' with 0.01 Significance dLSD = TTest(idF, 0.01) dLSD = dDev * dLSD If MultiCompReport(dMean(), iSz, cReport(), 10, dLSD, cMcLSD) = caiError Then GoTo MCLSDError For I = 1 To iSz * 20 strT = Chr(cReport(I)) strT = UCase(strT) cReport(I) = Asc(strT) Next I ' with 0.05Significance dLSD = TTest(idF, 0.05) dLSD = dDev * dLSD If MultiCompReport(dMean(), iSz, cReport(), 0, dLSD, cMcLSD) = caiError Then GoTo MCLSDError ' Store the report ReDim mMCompReport(iSz) For I = 1 To iSz With mMCompReport(I) .Mean = dMean(I) .Classif = "" For iT = 1 To 20 .Classif = .Classif & Chr(cReport((I - 1) * 20 + iT)) Next iT End With Next I MultiCompLSD = caiOK Exit Function MCLSDError: mMessage = modMessage MultiCompLSD = caiError Exit Function MCompLSDFail: mMessage = "实施多重比较 LSD 时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description MultiCompLSD = caiError End Function ' Doing Equality Test according to Cochran: ' Input Parameters: MSes() -- Array of Variances sorted ascendly; ' iSize -- Number of Variances to be tested; idF -- the Degree of Freedom for each Variance ' Note: Here we assume that all Mses have the same value of the Degree of Freedom!!! ' Test result is stored to mEqTestREsult ' Return values: CaiOK -- Equality Accepted, i.e. Gmax <= Gtab005; 1 -- Equality Rejected on 0.05 Sig.; 2 -- REeected on 0.01Sig.; ' CaiCancel -- Test failed, mostly due to wrong value of input parameters, e.g. iSize > 40 Private Function EqualityCochran(MSes() As Double, iSize As Integer, idF As Integer) As Integer Dim dSum As Double, Gmax As Double, Gtab001 As Double, Gtab005 As Double Dim I As Integer Gtab005 = CochranTab(iSize, idF, 0.05) If Gtab005 < 0 Then GoTo EqCochFail Gtab001 = CochranTab(iSize, idF, 0.01) If Gtab001 < 0 Then GoTo EqCochFail dSum = 0 For I = 1 To iSize dSum = dSum + MSes(I) Next Gmax = MSes(iSize) / dSum With mEqTestResult .MethodName = "Cochran" .Size = iSize .dF = idF .EvalValue = Gmax .CritVal001 = Gtab001 .CritVal005 = Gtab005 If Gmax > Gtab001 Then .Result = 2 ElseIf Gmax > Gtab005 Then .Result = 1 Else .Result = 0 ' caiOK End If EqualityCochran = .Result End With Exit Function EqCochFail: mEqTestResult.Result = caiCancel EqualityCochran = caiCancel mMessage = modMessage End Function ' Doing Equality Test according to Bartlette: ' Input Parameters: MSes() -- Array of Variances sorted ascendly; ' iSize -- Number of Variances to be tested; idF -- the Degree of Freedom for each Variance; ' Note:In General, idF should be 4 or more, and iSize should great than 10, ' otherwise this method for Equality Test should not be used. ' However, the restrictions doesn't implemented here, it depends on the Caller to take care of them ' Test result is stored to mEqTestREsult ' Return values: CaiOK -- Equality Accepted, i.e. XsquV <= XSquT005; 1 -- Equality Rejected on 0.05 Sig.; 2 -- REeected on 0.01Sig.; ' CaiCancel -- Test failed, mostly due to wrong value of input parameters, e.g. iSize > 30, or dAlpha is other than 0.01 or 0.05 Private Function EqualityBartlette(MSes() As Double, iSize As Integer, idF As Integer) As Integer Dim XsquV As Double, XSquT005 As Double, XSquT001 As Double, dSum As Double, dSumLog As Double Dim I As Integer XSquT005 = XSquareTab(iSize - 1, 0.05) If XSquT005 < 0 Then GoTo EqBartFail XSquT001 = XSquareTab(iSize - 1, 0.01) If XSquT001 < 0 Then GoTo EqBartFail dSum = 0: dSumLog = 0 For I = 1 To iSize dSum = dSum + MSes(I) dSumLog = dSumLog + Log(MSes(I)) / Log(10#) Next XsquV = 2.3026 * iSize * idF * (Log(dSum / iSize) / Log(10#) - dSumLog / iSize) XsquV = XsquV / ((iSize + 1) / (3 * iSize * idF) + 1) With mEqTestResult .MethodName = "Bartlette" .Size = iSize .dF = idF .EvalValue = XsquV .CritVal001 = XSquT001 .CritVal005 = XSquT005 If XsquV > XSquT001 Then .Result = 2 ElseIf XsquV > XSquT005 Then .Result = 1 Else .Result = 0 ' caiOK End If EqualityBartlette = .Result End With Exit Function EqBartFail: EqualityBartlette = caiCancel mMessage = modMessage mEqTestResult.Result = caiCancel End Function ' Calclating Variances from mData() indicated by iIdx for Equality Test ' iIdx: >0 -- Sample Data Set = mData(iidxa, *, *); 0 -- Sampl Data Set = mData(*, *, *) ' The Variances calclated are stored into mVRData() Private Function CalcVariances(iIdxA As Integer) As Integer Dim n1 As Integer, n2 As Integer, n3 As Integer Dim I As Integer, J As Integer, k As Integer, dTemp As Double On Error GoTo CalaVarsFail If Abs(mDataState) < 3 Or (mDataState = -3 And iIdxA > 1) Then mMessage = "没发现指定的方差分析原始样本数据,无法进行同质性检验!" mVRDataState = 0 CalcVariances = caiCancel Exit Function End If n1 = UBound(mData, 1) n2 = UBound(mData, 2) n3 = UBound(mData, 3) Select Case iIdxA Case 1 To n1 ' With Anova1 Analysis, i.e. one Site If mAnovaResultState < 11 Or mIdxA <> iIdxA Then InitResults I = CalcSSdFs1(iIdxA) If I <> caiOK Then InitResults mAnovaResultState = IIf(I = caiCancel, 0, caiError) mVRDataState = 0 CalcVariances = I Exit Function End If mAnovaResultState = 11 mIdxA = iIdxA End If ReDim mVRData(n2) For I = 1 To n2 dTemp = 0 For J = 1 To n3 dTemp = dTemp + mData(mIdxA, I, J) * mData(mIdxA, I, J) Next J mVRData(I) = (dTemp - T2(I) * T2(I) / n3) / (n3 - 1) Next I With mEqTestResult .Size = n2 .dF = n3 - 1 End With Case 0 ' With Anova2 Analysis, i.e. Multi Sites If mAnovaResultState < 21 Then I = CalcSSdFs2() If I <> caiOK Then InitResults mAnovaResultState = IIf(I = caiCancel, 0, caiError) mVRDataState = 0 CalcVariances = I Exit Function End If mAnovaResultState = 21 mIdxA = 0 End If ReDim mVRData(n1) Dim dT2 As Double, dT3 As Double, dCF As Double For I = 1 To n1 dCF = T1(I) * T1(I) / (n2 * n3) dTemp = 0 dT2 = 0 dT3 = 0 For J = 1 To n2 For k = 1 To n3 dTemp = dTemp + mData(I, J, k) * mData(I, J, k) Next k dT2 = dT2 + X21(J, I) * X21(J, I) Next J For k = 1 To n3 dT3 = dT3 + T31((I - 1) * n3 + k) * T31((I - 1) * n3 + k) Next k dTemp = dTemp - dCF ' SST for the Site I dT2 = dT2 / n3 - dCF ' SSb for the Site dT3 = dT3 / n2 - dCF ' SSr for the Site mVRData(I) = (dTemp - dT2 - dT3) / ((n2 - 1) * (n3 - 1)) SSerr/dFerr Next I With mEqTestResult .Size = n1 .dF = (n2 - 1) * (n3 - 1) End With ' MSerr = Case Else mMessage = "指定的因子 A(试点)的 Index 越界,即现有的样本数据集没有 所指定的数据!" mVRDataState = 0 CalcVariances = caiCancel Exit Function End Select mVRDataState = 1 CalcVariances = caiOK Exit Function CalaVarsFail: mMessage = "计算方差时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description mEqTestResult.Result = caiError mVRDataState = 0 CalcVariances = caiError End Function ' 同质性检验控制程序:此时 mVRData()存放着各参试组的方差值,其自由度及参试组个数 等存放在 mEqTestResult ' iMethod -- 检验方法:0 -- 常规(参试组个数<10 时用 Cochran 法,否则用 Bartellet) ; 1 -Cochran; 2 -- Bartlette ' Return Values: <0 -- 同质性检验失败: -1, caiCancel -- 参数不合要求;-2, caiError -- 检验中 出错 ' >=0 -- 同质性检验顺利完成: 0, caiOK -- 接受同质性; 1 -- 拒绝同质性(显著性 0.05); 2 -- 拒绝同质性(显著性 0.01) Private Function EqualityTest(iMethod As Integer) As Integer Dim dStVars() As Double, iSortedIdx() As Integer Dim I As Integer, iSize As Integer, idF As Integer On Error GoTo EquTestFail ' Sort the Variances With mEqTestResult iSize = .Size idF = .dF End With ReDim dStVars(iSize), iSortedIdx(iSize) SortArray mVRData(), iSize, iSortedIdx(), True For I = 1 To iSize dStVars(I) = mVRData(iSortedIdx(I)) Next I 'ordered Acsendly Select Case iMethod Case cDefault ' 0, Nomal If iSize < 10 Then EqualityTest = EqualityCochran(dStVars(), iSize, idF) ElseIf iSize >= 10 And idF >= 4 Then EqualityTest = EqualityBartlette(dStVars(), iSize, idF) Else mMessage = "按一般规则,同质性检验当参试组个数小于 10 时采用 Cochran 法," _ & "10 个以上时采用 Bartlette 法,但后者要求参试的每个方差的 自由度应大于 3。" _ & "您选择的样本数据不符合上述要求。" & vbCrLf & vbCrLf _ & "若您坚持要求进行同质性检验,请自已确定用何种方法。" mEqTestResult.Result = caiCancel ' -1 EqualityTest = caiCancel End If Case cEqCoch ' 1, Cochraan EqualityTest = EqualityCochran(dStVars(), iSize, idF) Case cEqBart ' 2, Bartlette EqualityTest = EqualityBartlette(dStVars(), iSize, idF) Case Else mMessage = "同质性检验方法当前仅支持:0 -- 常规;1 -- Cochran;2 -Bartlette!" mEqTestResult.Result = caiCancel EqualityTest = caiCancel Exit Function End Select Exit Function EquTestFail: mMessage = "实施同质性检验时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description mEqTestResult.Result = caiError EqualityTest = caiError End Function ' Calclating Sample Data (Xi, Yi) for Regression Analysis from mData() that has contained the Sample Data for ' Anova2 (Multi Sites) Analysis. "iIndexB" indecates the level of Factor B (the Variety) to be concerned. ' Xi is the Average Value of all levels of Factor B in the ith treatment of Factor A (the Average Yield per plot of all ' Varieties in the ith Site), and will be stored to mVRData(1, i); Yi is the Average Value of the iIndexBth level of ' Factor B in the ith level of Factor A (the Average Yield per plot of the iIndexBth. Variety in the ith. Site), and ' will be stored to mVRData(2, i). Private Function RegresSDataPrepare(iIndexB) Dim n1 As Integer, n2 As Integer, n3 As Integer Dim I As Integer, J As Integer, k As Integer On Error GoTo RegDataFail ' Check if the Sample Data for Anova2 is Avialable If mDataState < 3 Then mMessage = "没发现用于 Anova2 的原始样本数据,无法进行相关性检验!" GoTo RegDataCancel End If n1 = UBound(mData, 1) n2 = UBound(mData, 2) n3 = UBound(mData, 3) If iIndexB > n2 Or iIndexB < 1 Then mMessage = "因子 B 仅有" & Str(n2) & "种不同处理水平,指定的序号无效!" GoTo RegDataCancel End If ' Check, if SSxs calclating has been done already If mAnovaResultState < 21 Then I = CalcSSdFs2() If I <> caiOK Then InitResults mAnovaResultState = IIf(I = caiCancel, 0, caiError) GoTo RegDataCancel End If mAnovaResultState = 21 mIdxA = 0 End If ' Calclating (Xi, Yi) ReDim mVRData(2, n1) J = n2 * n3 For I = 1 To n1 mVRData(1, I) = T1(I) / J mVRData(2, I) = X21(iIndexB, I) / n3 Next I mVRDataState = 2 RegresSDataPrepare = caiOK Exit Function RegDataCancel: mVRDataState = 0 RegresSDataPrepare = caiCancel Exit Function RegDataFail: mMessage = "从 Anova2 样本数据计算回归分析所需样本数据时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description mVRDataState = 0 RegresSDataPrepare = caiError End Function ' Regression Analysis, SampleData of pare of (Xi, Yi)s have been stored in mVRData(), ' and the result will be stored in mRegresResult Private Function RegressionAnaly() As Integer Dim I As Integer, iSize As Integer Dim Tx As Double, Ty As Double Dim SSxx As Double, SSyy As Double, SSxy As Double Dim Ra001 As Double, Ra005 As Double On Error GoTo RegCalcFail iSize = UBound(mVRData, 2) If iSize < 4 Then mMessage = "所提供的样本数小于 4,不宜进行回归分析!" RegressionAnaly = caiCancel End If ' Regression Calclating Tx = 0: Ty = 0: SSxx = 0: SSyy = 0: SSxy = 0 For I = 1 To iSize Tx = Tx + mVRData(1, I) Ty = Ty + mVRData(2, I) SSxx = SSxx + mVRData(1, I) * mVRData(1, I) SSyy = SSyy + mVRData(2, I) * mVRData(2, I) SSxy = SSxy + mVRData(1, I) * mVRData(2, I) Next SSxx = SSxx - Tx * Tx / iSize SSyy = SSyy - Ty * Ty / iSize SSxy = SSxy - Tx * Ty / iSize With mRegresResult .Slope = SSxy / SSxx .Intercept = (Ty - .Slope * Tx) / iSize .CorCorf = SSxy / Sqr(SSxx * SSyy) .Size = iSize End With ' Correlative Test Ra001 = RaTab(iSize - 2, 0.01) Ra005 = RaTab(iSize - 2, 0.05) If Ra001 < 0 Or Ra005 < 0 Then mRegresResult.Result = caiCancel RegressionAnaly = caiCancel ' means that Data about slope, Interception and Correlative Coefficient is Valid Exit Function End If With mRegresResult .CritRa001 = Ra001 .CritRa005 = Ra005 If .CorCorf < .CritRa005 Then .Result = 0 ElseIf .CorCorf >= .CritRa001 Then .Result = 2 Else .Result = 1 End If End With RegressionAnaly = caiOK Exit Function RegCalcFail: mMessage = "计算回归方程时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description mRegresResult.Result = caiError RegressionAnaly = caiError End Function ' *********************************************************************** ' Public Methods (i.e. the Interface of the class ' *********************************************************************** ' 设定原始样本数据,对它可进行方差分析、多重比较、及其它相关的统计检验。 ' sData() 包含原始样本数据, 应是满足右列格式的三维数组:sData(因子 A Index, 因子 B Index, 重复 Index), ' 或是满足右列格式的二维数组:sData(因子 Index, 重复 Index)。iDim -- 数组的维数 ' 注:当 sData()为二维时会产生付作用:mData()被这里的 sData()复盖,维数变为(1, n2, n3), 因而不能再为 ' 其它方差分析共享,即 Anova1WOD(), Anova2WOD()均不能利用 mData()了,需要重新 设定样本数据后才能调用。 Public Function SetSampleData(ByRef sData() As Single, iDim As Integer) As Integer Dim iT As Integer iT = CheckAnovaSourceData(sData, iDim) If iT = caiError Then mMessage = mMessage & " 不能接受该样本数据!" mAnovaResultState = 0 SetSampleData = caiError Exit Function End If SetSampleData = caiOK End Function ' 单因子有重复样本的方差分析(完全随机区组设计): ' sData() 包含原始样本数据,应是满足右列格式的二维数组:sData(因子 Index, 重复 Index) ' 此函数产生付作用:mData()被这里的 sData()复盖,维数变为(1, n2, n3),因而不能再为其 它方差分析共享 ' 即 Anova1WOD(), Anova2WOD()均不能利用 mData()了,需要重新设定样本数据后才能 调用。 Public Function Anova1WSD(ByRef sData() As Single) As Integer Dim iT As Integer iT = CheckAnovaSourceData(sData, 2) If iT < 0 Then mMessage = mMessage & " 无法完成单因子方差分析!" mAnovaResultState = IIf(iT = caiCancel, 0, caiError) Anova1WSD = iT Exit Function End If Anova1WSD = Anova1Calc(1) mDataState = -3 End Function ' 同 Anova1WSD, 只是使用已存入 mData()的样本数据,Index 指明样本数据位于 mData(Index, *, *) Public Function Anova1WOD(ByVal Index As Integer) As Integer Anova1WOD = Anova1Calc(Index) End Function ' 用于区试(一年多点), 即多个"完全随机区组设计试验"的联合方差分析 ' sData() 包含原始样本数据, 应是满足右列格式的三维数组:sData(因子 A Index, 因子 B Index, 重复 Index) ' iMode: 1 -- 关于因子 A 的处理是随机的,0 -- 是固定的 Public Function Anova2WSD(ByRef sData() As Single, ByVal iMode As Integer) As Integer Dim iT As Integer iT = CheckAnovaSourceData(sData, 3) If iT < 0 Then mMessage = mMessage & " 无法完成联合方差分析!" mAnovaResultState = IIf(iT = caiCancel, 0, caiError) Anova2WSD = iT Exit Function End If mAnova2Mode = IIf(iMode, 2, 1) Anova2WSD = Anova2Calc() End Function ' 同 Anova2WSD, 只是使用已存入 mData()的样本数据 Public Function Anova2WOD(ByVal iMode As Integer) As Integer mAnova2Mode = IIf(iMode, 2, 1) Anova2WOD = Anova2Calc() End Function ' 用于双因子随机区组试验方差分析(关于区组间的变异, 对因子 A 的不同处理水平同等对 待) ' sData() 包含原始样本数据, 应是满足右列格式的三维数组:sData(因子 A Index, 因子 B Index, 重复 Index) ' iMode: 1 -- 因子 A, B 都固定; 2 -- A 固定, B 随机; 3 -- A 随机, B 固定; 4 -- A,B 都随 机. Public Function Anova2gWSD(ByRef sData() As Single, ByVal iMode As Integer) As Integer Dim iT As Integer iT = CheckAnovaSourceData(sData, 3) If iT < 0 Then mMessage = mMessage & " 无法完成双因子随机区组试验方差分析!" mAnovaResultState = IIf(iT = caiCancel, 0, caiError) Anova2gWSD = iT Exit Function End If mAnova2Mode = iMode + 10 Anova2gWSD = Anova2Calc() End Function ' 同 Anova2gWSD, 只是使用已存入 mData()的样本数据 Public Function Anova2gWOD(ByVal iMode As Integer) As Integer mAnova2Mode = iMode + 10 Anova2gWOD = Anova2Calc() End Function ' 在方差分析的基础上对 mData()中的原始数据关于因子 B(作物品种)作多重比较。比较 的 ' 结果报告将存放在类型为 MCREport 的数组 mMCompReport()中,该数组的每一项对 应于一个组, ' 并按均值的降幂排列,其中".Index"为该组在原始数据中对应于因子 B 的 Index(序 号) 。 ' iMethod:指定多重比较方法 = cMcLSD or cMcSSR,即 1 或 2 ' iMode:指定关于因子 A 的设计模型,=cFixed or cRadomized,即 0 或 1 Public Function MultiCompareAnova(ByVal iMethod As Integer, ByVal iMode As Integer) As Integer Dim dMeans() As Double, dStMeans() As Double, iSortedIdx() As Integer Dim dMSx As Double, idFx As Integer Dim I As Integer, iSize As Integer, n3 As Integer On Error GoTo MCAnovaFail ' Set the Mean Value for each Group (the Treatment of Factor B), e.g. for each Variety If Abs(mDataState) < 3 Then mMessage = "没有用于方差分析的原始数据,无法进行多重比较!" MultiCompareAnova = caiCancel Exit Function End If iSize = UBound(mData, 2) n3 = UBound(mData, 3) ReDim dMeans(iSize), dStMeans(iSize), iSortedIdx(iSize) Select Case mAnovaResultState Case 11 To 19 ' Under Anova1 Analysis, i.e. one Site For I = 1 To iSize dMeans(I) = T2(I) / n3 Next I With mAnovaResult dMSx = .SSerr / .dFerr If iMethod = cMcSSR Then dMSx = Sqr(dMSx / n3) ElseIf iMethod = cMcLSD Then dMSx = Sqr(2 * dMSx / n3) End If idFx = .dFerr End With Case 21 To 29 ' Under Anova2 Analysis, i.e. Multi Sites For I = 1 To iSize dMeans(I) = T2(I) / ((mAnovaResult.dFa + 1) * n3) Next I With mAnovaResult If .SSab = 0 And iMode = cRadomized Then mMessage = "计算发现来自因子 A、B 间互作的变异的平方 和为 0!" _ & "要对该样本数据作多重比较,只能采用固定模式。 " MultiCompareAnova = caiCancel Exit Function End If dMSx = IIf(iMode = cFixed, .SSerr / .dFerr, .SSab / .dFab) If iMethod = cMcSSR Then dMSx = Sqr(dMSx / ((.dFa + 1) * n3)) ElseIf iMethod = cMcLSD Then dMSx = Sqr(2 * dMSx / ((.dFa + 1) * n3)) End If idFx = IIf(iMode = cFixed, .dFerr, .dFab) End With Case Else mMessage = "本函数仅在方差分析后实施多重比较,请先进行方差分析或调用 其它函数实施多重比较。" MultiCompareAnova = caiCancel Exit Function End Select ' Sorting dMeans() SortArray dMeans(), iSize, iSortedIdx(), False If iSize > 20 Then iSize = 20 ReDim mMCompReport(iSize) For I = 1 To iSize dStMeans(I) = dMeans(iSortedIdx(I)) Next I 'ordered Decsendly ' Multiple Comparision Select Case iMethod Case cMcLSD I = MultiCompLSD(dStMeans(), iSize, dMSx, idFx) Case cMcSSR I = MultiCompSSR(dStMeans(), iSize, dMSx, idFx) Case Else mMessage = "本函数仅支持两种多重比较方法:1 -- LSD;2 -- SSR Duncan" MultiCompareAnova = caiCancel End Select If I <> caiOK Then MultiCompareAnova = I Exit Function End If For I = 1 To iSize mMCompReport(I).Index = iSortedIdx(I) Next I MultiCompareAnova = caiOK Exit Function MCAnovaFail: mMessage = "实施 Anova 多重比较时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description MultiCompareAnova = caiError End Function ' 根据提供的平均值 dMeans(),及对应的 dMSx 及其自由度(idF)、平均值的样本容量(iGn)作多 重比较。比较的 ' 结果报告将存放在类型为 MCREport 的数组 mMCompReport()中,该数组的每一项对 应于一个组, ' 并按均值的降幂排列,其中".Index"为该组在原始数据中的顺序号。 ' iMethod:指定多重比较方法 = cMcLSD or cMcSSR,即 1 或 2 ' 注意:dMSx 应取合适的均方差,如在固定模式下取 MSerr,在随机模式取 MSab。 Public Function MultiCompareWSD(ByRef dMeans() As Double, ByVal dMSx As Double, ByVal idFx As Integer, _ ByVal iGn As Integer, ByVal iMethod As Integer) As Integer Dim dTMeans() As Double, dStMeans() As Double, iSortedIdx() As Integer Dim I As Integer, iSize As Integer, iB As Integer On Error GoTo MCWsdFail ' It's not sure that dMeans() will based on 1 to n subscripting, so, transforming is neccessary iB = LBound(dMeans) iSize = UBound(dMeans) - iB + 1 ReDim dTMeans(iSize), dStMeans(iSize), iSortedIdx(iSize) For I = 1 To iSize dTMeans(I) = dMeans(iB - 1 + I) Next I ' Sorting dMeans() SortArray dTMeans(), iSize, iSortedIdx(), False 'ordered Decsendly If iSize > 20 Then iSize = 20 ReDim mMCompReport(iSize) For I = 1 To iSize dStMeans(I) = dMeans(iSortedIdx(I)) Next I ' Multiple Comparision Select Case iMethod Case cMcLSD dMSx = Sqr(2 * dMSx / iGn) I = MultiCompLSD(dStMeans(), iSize, dMSx, idFx) Case cMcSSR dMSx = Sqr(dMSx / iGn) I = MultiCompSSR(dStMeans(), iSize, dMSx, idFx) Case Else mMessage = "本函数仅支持两种多重比较方法:1 -- LSD;2 -- SSR Duncan" MultiCompareWSD = caiCancel Exit Function End Select If I <> caiOK Then MultiCompareWSD = I Exit Function End If For I = 1 To iSize mMCompReport(I).Index = iSortedIdx(I) Next I MultiCompareWSD = caiOK Exit Function MCWsdFail: mMessage = "实施 Anova 多重比较时出错!错误号:" & Err.Number & vbCrLf _ & "说明:" & Err.Description MultiCompareWSD = caiError End Function ' 利用当前的 Anova 样本数据对各组数据的样本方差的同质性进行检验 ' iIdxA,用于指明样本数据: ' >0 -- mData(iIdxA, *, *),即指 Anova1(单点)数据,因子 B 的每一个处理(品种) 的样本数据构成一个组; ' =0 -- mData(*,*,*),即 Anova2(多点)数据,与因子 A 每一个处理(试点)相关的所 有样本数据 ' (包括因子 B 的各种处理)构成一个组,其方差值取该处理(试点)的 MSerr,即 Experimental Error. ' iMethod -- 检验方法:0 -- 常规(参试组个数<10 时用 Cochran 法,否则用 Bartellet) ; 1 -Cochran; 2 -- Bartlette ' Return Values: <0 -- 同质性检验失败: -1, caiCancel -- 参数不合要求;-2, caiError -- 检验中 出错 ' >=0 -- 同质性检验顺利完成: 0, caiOK -- 接受同质性; 1 -- 拒绝同质性(显著性 0.05); 2 -- 拒绝同质性(显著性 0.01) ' 当检验顺利完成时,mVRData()存放着参试的方差值(按原有的顺序), ' mEqTestResult 存放着检验结果及相关信息。调用者可通过相应的 Get Property 访问 它们。 Public Function EqualityAnova(ByVal iIdxA As Integer, ByVal iMethod As Integer) As Integer Dim I As Integer ' Calclate the Variances I = CalcVariances(iIdxA) If I <> caiOK Then EqualityAnova = I Exit Function End If EqualityAnova = EqualityTest(iMethod) End Function ' 同质性检验:dVars()存放着各参试组的方差值(按原有顺序,不必排序,亦不计其 Index 的起始值) ,idF 为其自由度 ' iMethod -- 检验方法:0 -- 常规(参试组个数<10 时用 Cochran 法,否则用 Bartellet) ; 1 -Cochran; 2 -- Bartlette ' Return Values: <0 -- 同质性检验失败: -1, caiCancel -- 参数不合要求;-2, caiError -- 检验中 出错 ' >=0 -- 同质性检验顺利完成: 0, caiOK -- 接受同质性; 1 -- 拒绝同质性(显著性 0.05); 2 -- 拒绝同质性(显著性 0.01) ' 当检验顺利完成时,mVRData()存放着参试的方差值(按原有的顺序), ' mEqTestResult 存放着检验结果及相关信息。调用者可通过相应的 Get Property 访问 它们。 Public Function EqualityWSD(ByRef dVars() As Double, ByVal idF As Integer, ByVal iMethod As Integer) As Integer Dim I As Integer, iB As Integer, iSize As Integer On Error GoTo EqWSDFail iB = LBound(dVars) iSize = UBound(dVars) - iB + 1 ReDim mVRData(iSize) For I = 0 To iSize - 1 If dVars(iB + I) >= 0 Then mVRData(I + 1) = dVars(iB + I) Else GoTo EqWSDFail End If Next I With mEqTestResult .Size = iSize .dF = idF End With mVRDataState = 1 EqualityWSD = EqualityTest(iMethod) Exit Function EqWSDFail: mMessage = "提供的含有方差值的数组出错(如方差值为负数、非一维数组等)!错误 号:" _ & Err.Number & vbCrLf & "说明:" & Err.Description mEqTestResult.Result = caiError mVRDataState = 0 EqualityWSD = caiError End Function ' 在 Anova2 分析中,对指定的因子 B 的一个处理水平(如一个品种)与它的所有处理水平 在每一个 ' 因子 A 的处理水平(试验地点)下的平均值之间作回归分析。前者作为 Y, 后者作为 X。 ' 参数 iIndexB 即为此指定的 B 的处理水平的序号(属于闭区间[1, n2],n2 为因子 B 的处理 个数) ' 即回归样本数据为:(Xi, Yi), i=1, 2, ... n1,其中 n1 为因子 A 的处理个数;Xi -- 在因子 A 的 第 i 个处理水平 ' 下关于因子 B 的所有处理的平均值(第 i 个试点中所有品种的平均产量);Yi -- 在因子 A 的第 i 个处理 ' 水平下关于因子 B 的第 iIndexB 个处理的平均值(第 i 个试点中第 iIndexB 个品种的平均 产量) ' 分析结果可访问 Property ctRegresREsult 获得,Xi -- Property dXYSamples(1, i),Yi -dXYSamples(2, i)。 ' 注:样本数据(X,Y)按因子 A 的处理水平的序号排列,并未按 Xi 值的大小排序 Public Function RegressionAnova(ByVal iIndexB As Integer) As Integer Dim I As Integer ' Prepare Sample Data for Regression Analysis I = RegresSDataPrepare(iIndexB) If I <> caiOK Then RegressionAnova = I Exit Function End If RegressionAnova = RegressionAnaly() End Function ' 按提供的样本数据进行回归分析:iSize 为样本个数,第 i 个样本为(X(i), Y(i)) ' 分析结果可访问 Property ctRegresREsult 获得 ' Public Function RegressionWSD(ByRef X() As Double, ByRef Y() As Double, ByVal iSize As Integer) As Integer Dim I As Integer, iB As Integer On Error GoTo RegWSDFail ' Prepare Sample Data for Regression Analysis iB = LBound(X) ReDim mVRData(2, iSize) For I = 1 To iSize mVRData(1, I) = X(iB - 1 + I) mVRData(2, I) = Y(iB - 1 + I) Next I RegressionWSD = RegressionAnaly() Exit Function RegWSDFail: mMessage = "所提供的用于回归分析的样本数据有问题,如样本个数与 X(), Y()的容量不 符!" RegressionWSD = caiError End Function