当前位置: 首页 > article >正文

excel VBA进行间比法设计

在品比试验大家多使用间比法试验设计,这里通过excel VBA实现间比法设计,代码如下:

Sub 生成试验设计()

Dim ws As Worksheet
Dim rng As Range, rng2 As Range, rng3 As Range
Dim cell As Range, lastcell As Range
Dim rd As String, sn As String, pl As String   'rd为是否随机排列品种顺序,sn即sheetname的简称,pl即排在sheet表中的方向的简称
Dim ck As String, var_num As Integer, pl2 As String, method As String    ' method即对照设置方法,var_num即对照间品种数量,pl2即品种在每排的排列方式
Dim row_num As Integer    '每排行数
Dim i As Integer, j As Integer, r As Integer, s As Integer, m As Integer, n As Integer, lastRow As Integer
Dim t_num As Integer, c_num As Integer, ck_num As Integer   't_num为加上对照后总的品种数,c_num为总列数
Dim arr As Variant, arr2 As Variant, rngValues As Variant, tmp As Variant
Dim arr5 As Variant, arr6 As Variant
Dim col_min As Integer, col_max As Integer, row_min As Integer, row_max As Integer

Application.ScreenUpdating = False       '刷新屏幕关闭
Application.DisplayAlerts = False        '警告提示框关闭



'获取初始设置
sn = Range("A2").Value    '新建工作表的名称
rd = Range("A5").Value   '是否随机排列品种顺序
pl = Range("A8").Value    '试验设计是横向排列还是纵向排列
row_num = Range("A11").Value    '每排行数
pl2 = Range("A14").Value    '品种在排之间的排列方式
method = Range("A17").Value  '对照的设置方法
var_num = Range("A20").Value  '对照间品种的间隔数
ck = Range("A23").Value    '设置对照名称,默认为“CK”



'获取品种名称
lastRow = Range("C10000").End(xlUp).Row    '获取品种名称列的最后一行的行号
Set rng = Range("C2:C" & lastRow)


' 将范围内的值存储在数组中
rngValues = rng.Value
ReDim arr(UBound(rngValues)) As Variant
arr = rngValues

' 随机排列数组中的元素
If rd = "是" Then
    Randomize ' 初始化随机数生成器
    For m = LBound(arr) To UBound(arr) - 1
        n = Int((UBound(arr) - m + 1) * Rnd + m)
        ' 交换元素
        tmp = arr(m, 1)
        arr(m, 1) = arr(n, 1)
        arr(n, 1) = tmp
    Next m
End If

If method = "逢X法" Then
    '确定包含对照的总品种数量
    t_num = lastRow - 1 + Int((lastRow - 1) / (var_num))

        
    '设置排区号的数组
    ReDim arr2(1 To t_num, 1 To 4) As Variant
    
    '确定排数,并将含有对照的品种名称列入新的数组中
    If t_num Mod row_num Then
        c_num = Int(t_num / row_num) + 1
        '将含有对照的品种信息列入新数组中
        r = 1
        s = 1
        For i = 1 To c_num - 1
            For j = 1 To row_num
                arr2(r, 1) = i
                arr2(r, 2) = j
                arr2(r, 3) = r
                If r Mod (var_num + 1) = 1 Then
                    arr2(r, 4) = ck
                    r = r + 1
                Else
                    arr2(r, 4) = arr(s, 1)
                    r = r + 1
                    s = s + 1
                End If
            Next
        Next
        
        For j = 1 To (t_num Mod row_num)
            arr2(r, 1) = c_num
            arr2(r, 2) = j
            arr2(r, 3) = r
            If r Mod (var_num + 1) = 1 Then
                arr2(r, 4) = ck
                r = r + 1
            Else
                arr2(r, 4) = arr(s, 1)
                r = r + 1
                s = s + 1
            End If
        Next
        
    Else
        c_num = Int(t_num / row_num)
        '将含有对照的品种信息列入新数组中
        r = 1
        s = 1
        For i = 1 To c_num
            For j = 1 To row_num
                arr2(r, 1) = i
                arr2(r, 2) = j
                arr2(r, 3) = r
                If r Mod 10 = 1 Then
                    arr2(r, 4) = ck
                    r = r + 1
                Else
                    arr2(r, 4) = arr(s, 1)
                    r = r + 1
                    s = s + 1
                End If
            Next
        Next
        
    End If

Else
    
    '常规法设置对照
    '确定单排ck数量
    If (row_num - 1) Mod (var_num + 1) Then
        ck_num = 1 + Int((row_num - 1) / (var_num + 1)) + 1
    Else
        ck_num = 1 + Int((row_num - 1) / (var_num + 1))
    End If
    '确定总排数和含对照的总品种数量
    c_num = Int((lastRow - 1) / (row_num - ck_num))
    If (lastRow - 1) Mod (row_num - ck_num) Then
        c_num = c_num + 1
        t_num = (lastRow - 1) + (c_num - 1) * ck_num
        If (lastRow - 1 - (c_num - 1) * (row_num - ck_num)) Mod var_num Then
            t_num = t_num + 1 + Int((lastRow - 1 - (c_num - 1) * (row_num - ck_num)) / var_num) + 1
        Else
            t_num = t_num + 1 + Int((lastRow - 1 - (c_num - 1) * (row_num - ck_num)) / var_num)
        End If
    Else
        c_num = c_num
        t_num = (lastRow - 1) + c_num * ck_num
    End If
        
    '设置排区号的数组
    ReDim arr2(1 To t_num, 1 To 4) As Variant
    
    '确定排数,并将含有对照的品种名称列入新的数组中
    If t_num Mod row_num Then
        c_num = Int(t_num / row_num) + 1
        '将含有对照的品种信息列入新数组中
        r = 1
        s = 1
        For i = 1 To c_num - 1
            For j = 1 To row_num
                arr2(r, 1) = i
                arr2(r, 2) = j
                arr2(r, 3) = r
                If j Mod (var_num + 1) = 1 Then
                    arr2(r, 4) = ck
                    r = r + 1
                ElseIf j = row_num Then
                    arr2(r, 4) = ck
                    r = r + 1
                Else
                    arr2(r, 4) = arr(s, 1)
                    r = r + 1
                    s = s + 1
                End If
            Next
        Next
        
        For j = 1 To (t_num Mod row_num)
                arr2(r, 1) = c_num
                arr2(r, 2) = j
                arr2(r, 3) = r
                If j Mod (var_num + 1) = 1 Then
                    arr2(r, 4) = ck
                    r = r + 1
                ElseIf j = (t_num Mod row_num) Then
                    arr2(r, 4) = ck
                    r = r + 1
                Else
                    arr2(r, 4) = arr(s, 1)
                    r = r + 1
                    s = s + 1
                End If
        Next
        
    Else
        c_num = Int(t_num / row_num)
        '将含有对照的品种信息列入新数组中
        r = 1
        s = 1
        For i = 1 To c_num
            For j = 1 To row_num
                arr2(r, 1) = i
                arr2(r, 2) = j
                arr2(r, 3) = r
                If j Mod (var_num + 1) = 1 Then
                    arr2(r, 4) = ck
                    r = r + 1
                ElseIf j = row_num Then
                    arr2(r, 4) = ck
                    r = r + 1
                Else
                    arr2(r, 4) = arr(s, 1)
                    r = r + 1
                    s = s + 1
                End If
            Next
        Next
        
    End If
    
    
End If

'对数组进行之字排列
If pl2 = "之字" Then
    arr2 = zhizi(arr2, t_num, row_num, c_num)
End If

' 新建一个工作表,用于生成带有排区号的整列数据
Set ws = ThisWorkbook.Sheets.Add
If sn <> "" Then
    ws.Name = sn      ' 将新工作表的名称设置为"新工作表"
End If

'工作表内数据录入
ws.Cells(1, 1).Value = "排号"
ws.Cells(1, 2).Value = "行号"
ws.Cells(1, 3).Value = "序号"
ws.Cells(1, 4).Value = "品种名称"

For i = 2 To t_num + 1
    For j = 1 To 4
        ws.Cells(i, j).Value = arr2(i - 1, j)
    Next
Next

'设置格式
Set rng2 = Range(ws.Cells(1, 1), ws.Cells(i - 1, j - 1))
'对单元格进行居中设置,添加边框
Call biankuang(ws, rng2)


Set rng = ws.Range("A1").CurrentRegion
col_max = WorksheetFunction.Max(ws.Range("A2:A" & (rng.Rows.Count)))
col_min = WorksheetFunction.Min(ws.Range("A2:A" & (rng.Rows.Count)))
row_max = WorksheetFunction.Max(ws.Range("B2:B" & (rng.Rows.Count)))
row_min = WorksheetFunction.Min(ws.Range("B2:B" & (rng.Rows.Count)))


'将行排号和品种名称放入数组,用于xlookup查询
ReDim arr5(1 To rng.Rows.Count - 1)
ReDim arr6(1 To rng.Rows.Count - 1)
For i = 2 To rng.Rows.Count
    arr5(i - 1) = CStr(rng(i, 1)) & " " & CStr(rng(i, 2))
    arr6(i - 1) = rng(i, 4)
Next

If pl = "纵向" Then
    '输入列号
    j = 1
    For i = col_min To col_max
        ws.Cells(1, j + 7).Value = i
        j = j + 1
    Next
    '输入行号
    j = 1
    For i = row_min To row_max
        ws.Cells(j + 1, 7).Value = i
        j = j + 1
    Next
                
    '将品种名称放入对应行排号的单元格中
    For i = 8 To col_max - col_min + 8
        For j = 2 To row_max - row_min + 2
            ws.Cells(j, i).Value = WorksheetFunction.XLookup(CStr(ws.Cells(1, i)) & " " & CStr(ws.Cells(j, 7)), arr5, arr6, "空", 0, 1)
        Next
    Next

Else
    '输入行号
    j = 1
    For i = row_min To row_max
        ws.Cells(1, j + 7).Value = i
        j = j + 1
    Next
    '输入列号
    j = 1
    For i = col_min To col_max
        ws.Cells(j + 1, 7).Value = i
        j = j + 1
    Next
                
    '将品种名称放入对应行排号的单元格中
    For i = 8 To row_max - row_min + 8
        For j = 2 To col_max - col_min + 2
            ws.Cells(j, i).Value = WorksheetFunction.XLookup(CStr(ws.Cells(j, 7)) & " " & CStr(ws.Cells(1, i)), arr5, arr6, "空", 0, 1)
        Next
    Next
    
End If





Application.ScreenUpdating = True       '刷新屏幕开启
Application.DisplayAlerts = True        '警告提示框开启

End Sub


Sub biankuang(ws As Worksheet, rng As Range)
    '边框和居中设置子程序
    '对单元格进行居中设置
    ws.Cells(1, 1).CurrentRegion().HorizontalAlignment = xlCenter
    ws.Cells(1, 1).VerticalAlignment = xlCenter
    '对田间种植区域添加边框
    With rng.Borders
        .LineStyle = xlContinuous
        .Weight = xlThin
        .Color = RGB(0, 0, 0) ' 黑色
    End With
End Sub

Function zhizi(arr As Variant, t_num As Integer, row_num As Integer, c_num As Integer)
    'zhizi即“之字”,之字排列函数
    Dim arr3 As Variant
    Dim i_z As Integer, j_z As Integer
    
    ReDim arr3(1 To t_num, 1 To 4) As Variant
    For i_z = 1 To t_num
        If arr(i_z, 1) Mod 2 Then
            arr3(i_z, 1) = arr(i_z, 1)
            arr3(i_z, 2) = arr(i_z, 2)
            arr3(i_z, 3) = arr(i_z, 3)
            arr3(i_z, 4) = arr(i_z, 4)
        Else
            arr3(i_z, 1) = arr(i_z, 1)
            arr3(i_z, 2) = arr(row_num - arr(i_z, 2) + 1, 2)
            arr3(i_z, 3) = arr(i_z, 3)
            arr3(i_z, 4) = arr(i_z, 4)
        End If
    Next
    zhizi = arr3
End Function

设置界面如下:

参数说明:

1、是否随机排列:是对上图右侧品种顺序是否进行随机排列,如果选择将将随机排列,如果选择否,将按照给定的顺序排列

2、表格中的排列方向:若选择横向,则以行为排;若选择纵向,则以列为排

3、每排的行数:这里的行数是指田间的小区数。

4、排列方式:分为顺序排列和“之字”型配列。

5、对照设置:逢X法,即在1的位置放置对照,后面每间隔固定长度设置一个对照;常规法,即在一排的首尾设置对照,并且在一排内间隔固定长度设置一个对照

6、对照间隔数:即两个对照品种之间间隔的小区数量。

7、对照名称:默认为CK,也可以设置为具体的名称。

图1:不随机排列,排列方向横向,每排11行,之字排列,常规法设置对照

图2:不随机排列,排列方向横向,每排10行,之字排列,逢X法设置对照

图3:不随机排列,纵向,每排15行,之字排列,逢X法

图4:随机,纵向,顺序排列,每排11行,常规法设置对照,对照间隔为4行


http://www.kler.cn/a/319588.html

相关文章:

  • C++ 并发专题 - 自旋锁的实现(Spinlock)
  • sol机器人pump机器人如何实现盈利的?什么是Pump 扫链机器人?
  • 继承和多态(上)
  • [代码随想录Day10打卡] 理论基础 232.用栈实现队列 225. 用队列实现栈 20. 有效的括号 1047. 删除字符串中的所有相邻重复项
  • 【深圳大学】数据结构A+攻略(计软版)
  • 计算机毕业设计必看必学35755flask旅游景区热度可视化平台原创定制程序,java、PHP、python、小程序、文案全套、毕设成品等
  • 运行python程序
  • 初识前端监控
  • C++如何进阶? -- 整理一些学习资料
  • 基于stm32物联网身体健康检测系统
  • LeetCode 909. 蛇梯棋
  • nlohmann json:读写json文件
  • c++优先级队列自定义排序实现方式
  • SDK3(note上)
  • NLP 文本分类任务核心梳理
  • Selenium点击元素的方法
  • 【深入学习Redis丨第六篇】Redis哨兵模式与操作详解
  • 电脑自带dll修复在哪里,dll丢失的6种解决方法总结
  • 免费与付费代理IP工具的优缺点分析
  • 遗忘的数学(拉格朗日乘子法、牛顿法)
  • (16)docker自动镜像打包脚本
  • 【Power Query】追加查询(动态列,动态路径)
  • 微软宣布弃用WSUS,企业用户尽早准备替换方案
  • [RabbitMQ] RabbitMQ介绍,安装与快速上手
  • 虚拟机开启网络代理设置,利用主机代理访问国外资源
  • Vue3:toRaw与markRaw