首页 > 其他分享 >限行列和随机加墙版_过程拆解为若干函数

限行列和随机加墙版_过程拆解为若干函数

时间:2022-11-29 09:11:15浏览次数:38  
标签:End Sub nCols vArr Long 拆解 随机 tmpSum 加墙

Public nRows As Long, nCols As Long, nLastRow As Long, tmpSum As Long, tmpRow As Long, r As Long, c As Long
Public sumRows() As Long, nRowSkipSum() As Long, nColSkipSum() As Long, nColsLast() As Long
Public bForceValue() As Boolean
Public vArr() As Variant
Public fOffset As Single

Sub 变量初始化()
    tmpSum = 0
    tmpRow = 0
    Erase vArr
    With Sheet3
        vArr = .Range("A2").CurrentRegion.Value '取数据
        nRows = UBound(vArr)
        nCols = UBound(vArr, 2)
        ReDim sumRows(3 To nRows) '以第2行为基数,计算每行的和值(不含黄色的0)
        ReDim nRowSkipSum(3 To nRows)
        ReDim nColsLast(3 To nRows) '每行最后1个列限制和非0的非固定值的列号
        ReDim nColSkipSum(2 To nCols - 1)
        ReDim nRowsLast(2 To nCols - 1)
        ReDim bForceValue(3 To nRows, 2 To nCols) '墙壁标记容器
    End With
End Sub

Sub 以第2行为基数计算每行的和值不含黄色的零()
    With Sheet3
        With .Range("A1")
            For c = 2 To nCols - 1
                For r = 3 To nRows
                    If .Offset(r - 1, c - 1).Interior.Color = vbYellow Then '背景颜色为黄色的单元格固定原值不变(跳过)
                        bForceValue(r, c) = True
                        bForceValue(r, nCols) = True
                        nRowSkipSum(r) = nRowSkipSum(r) + vArr(r, c) '每行跳过值之和
                        nColSkipSum(c) = nColSkipSum(c) + vArr(r, c) '每列跳过值之和
                    Else
                        sumRows(r) = sumRows(r) + vArr(2, c) '每行限制之和
                        If vArr(2, c) <> 0 Then nColsLast(r) = c '每行最后1个列限制和非0的非固定值的列号
                    End If
                Next
            Next
        End With
    End With
End Sub
Sub 计算行列限制和值()
    For c = 2 To nCols - 1
        tmpSum = tmpSum + vArr(2, c)
    Next
    For r = 3 To nRows
        tmpRow = tmpRow + vArr(r, nCols)
        If vArr(r, nCols) <> 0 And bForceValue(r, nCols) = False Then nLastRow = r
    Next
    If tmpRow <> tmpSum Then MsgBox "行与列限制之和不相等!": Exit Sub
    If nLastRow < 3 Then MsgBox "至少要有一行无任何固定值!": Exit Sub
    '    fOffset = 0.05! '随机值浮动百分比
End Sub
Sub 逐行生成随机数()
    fOffset = 0.015! '随机值浮动百分比
    Randomize
    For r = 3 To nRows
        If r <> nLastRow Then
            tmpSum = 0
            tmpRow = vArr(r, nCols) - nRowSkipSum(r) '该行剩余可随机值之和
            For c = 2 To nCols - 1
                If c <> nColsLast(r) And bForceValue(r, c) = False Then
                    vArr(r, c) = Int(tmpRow / sumRows(r) * vArr(2, c) * (1! + Rnd * fOffset * 2 - fOffset))
                    tmpSum = tmpSum + vArr(r, c)
                End If
            Next
            vArr(r, nColsLast(r)) = tmpRow - tmpSum '该行剩余列的值
        End If
    Next
End Sub
Sub main限行列和随机加墙版()
    Call 变量初始化
    Call 以第2行为基数计算每行的和值不含黄色的零
    Call 计算行列限制和值
    Call 逐行生成随机数
    Call 逐列生成随机数
    Call 结果输出
End Sub
Sub 逐列生成随机数()
    For c = 2 To nCols - 1
        tmpSum = 0
        For r = 3 To nRows
            If r <> nLastRow And bForceValue(r, c) = False Then tmpSum = tmpSum + vArr(r, c)
        Next
        vArr(nLastRow, c) = vArr(2, c) - nColSkipSum(c) - tmpSum '剩余列的剩余值
    Next
End Sub
Sub 结果输出()
    With Sheet3
        .Range("A1").Resize(UBound(vArr), UBound(vArr, 2)).Value = vArr
    End With
End Sub

 

标签:End,Sub,nCols,vArr,Long,拆解,随机,tmpSum,加墙
From: https://www.cnblogs.com/eyunkeji/p/16934400.html

相关文章