Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 矩阵分布_Vba_Algorithm_Excel_Matrix - Fatal编程技术网

Vba 矩阵分布

Vba 矩阵分布,vba,algorithm,excel,matrix,Vba,Algorithm,Excel,Matrix,我有一个项目列表,其中列出了需要花费的时间,这些时间在各个月内呈线性分布: Hours Aug Sep Oct Nov Dec 100 20 20 20 20 20 200 40 40 40 40 40 300 60 60 60 60 60 600 120 120 120 120 120 有些项目将在不同的月份结束,因此不应标记下个月的任何时间(必须为0): 但是,我们必须保持20%的金额比例(20%*

我有一个项目列表,其中列出了需要花费的时间,这些时间在各个月内呈线性分布:

Hours  Aug  Sep  Oct  Nov  Dec
100    20   20   20   20   20
200    40   40   40   40   40
300    60   60   60   60   60

600    120  120  120  120  120
有些项目将在不同的月份结束,因此不应标记下个月的任何时间(必须为0):

但是,我们必须保持20%的金额比例(20%*600=120。我之所以选择20%,是因为我们有5个月,但可能是不同的百分比),因此:

Hours  Aug    Sep    Oct    Nov   Dec  End
100    20     30     50     0     0    Oct
200    60     50     30     60    0    Nov
300    40     40     40     60    120  Dec

600    120    120    120    120   120
我这里有一个类似数独的问题,我需要尊重列的比例,并在每个项目上保持行的总和。我尝试了很多方法(VBA或函数)来制作这个发行版,但到目前为止我失败了。我相信以前有人遇到过这个问题,那么有没有一种方法可以通过编程来完成这个分发呢?这种发行版有什么名字吗?

我想你需要“逆向思考”。 在第n个月(12月),首先在活动项目中分配小时数。
从各自的项目中扣除这些小时,然后转到第n-1个月,等等。

我不能100%确定我是否正确回答了你的问题,但希望是的,因为这花了我很多时间。这看起来很简单,但实际上相当棘手

假设我们有一张桌子:

如果我没弄错的话,我们基本上想数一数,我们需要多少小时 已经用完了,现在我们想把剩下的分发出去 取决于未使用(空)月份

例如,在第3行(100小时),我们不想分配任何小时,因为我们已经用完了100小时中的所有100小时

在下一行(4)中,我们希望将115小时(200-85小时)分配给剩余的2个单元格=>这将使我们每月有57.5小时的轮班时间

等等

根据推测,这就是您希望算法实现的功能:

Private Sub divide_time()

Dim tbl As ListObject: Set tbl = Sheets("Sheet1").ListObjects("Table1")
Dim hour_dist() As Integer
ReDim hour_dist(1 To 3)

' first we need to learn how many hours total we have available per project
For i = 1 To 3
    With tbl.ListColumns(1)
        hour_dist(i) = .Range(i + 1) ' we store each value into an array per project
    End With
Next i

Dim current As Double
Dim sumof As Double
Dim hours_left As Double
Dim empty_counter As Integer

For i = 1 To 3

    'we reset all of the counters per row
    sumof = 0
    empty_counter = 0

    'looping through all the column values in the row
    For j = 2 To 6
        current = tbl.ListRows(1).Range(i, j)
        sumof = sumof + current ' we get a sum of the current values in the row
        If (current = 0) Then 'if there is an empty cell, we keep track of it _
        (so we know into how many cells we can still divide the remaining time)
            empty_counter = empty_counter + 1
        End If
    Next j

    ' so we get how many hours we have left for the project _
    in comparison to  how many  months are free to distribute
    hours_left = (hour_dist(i) - sumof)

    'if we also want to store the info, _ 
    'what month we ended on before we distribute the remaining hours
    If (hours_left = 0) Then
    Select Case empty_counter
        Case 0
            tbl.ListRows(1).Range(i, 7) = "Dec"
        Case 1
            tbl.ListRows(1).Range(i, 7) = "Nov"
        Case 2
            tbl.ListRows(1).Range(i, 7) = "Oct"
        Case 3
            tbl.ListRows(1).Range(i, 7) = "Sep"
        Case 4
            tbl.ListRows(1).Range(i, 7) = "Aug"
    End Select
    Else
        tbl.ListRows(1).Range(i, 7) = "Dec"
    End if

    If (empty_counter <> 0) Then '( we dont want to be dividing by 0 )
    For n = 6 To (6 - empty_counter + 1) Step -1

        'for each month we divide what we have left _
         depending on the % of the months available
        tbl.ListRows(1).Range(i, n) = (hours_left / empty_counter)

    Next n
    End If



' and we loop it for each and every row
Next i

End Sub
Private subdivide_time()
将tbl设置为列表对象:设置tbl=图纸(“图纸1”)。列表对象(“表1”)
Dim hour_dist()为整数
雷迪姆小时区(1至3)
“首先,我们需要了解每个项目的可用总小时数
对于i=1到3
带tbl.ListColumns(1)
hour_dist(i)=.Range(i+1)”我们将每个值存储到每个项目的数组中
以
接下来我
双倍微弱电流
双倍的
昏暗的时间是双倍的
将空计数器设置为整数
对于i=1到3
'我们重置每行的所有计数器
sumof=0
空计数器=0
'循环遍历行中的所有列值
对于j=2到6
当前=tbl.列表行(1).范围(i,j)
sumof=sumof+current'我们得到行中当前值的总和
如果(current=0),那么“如果有一个空单元格,我们将跟踪它_
(这样我们就知道剩下的时间还能分成多少个细胞)
空计数器=空计数器+1
如果结束
下一个j
“那么我们还有多少小时可以完成这个项目_
相比之下,有多少个月可以免费分发
剩余小时数=(小时距离(i)-总小时数)
'如果我们还想存储信息,\u
“在分配剩余时间之前,我们在哪个月结束
如果(剩余小时=0),则
选择案例空\u计数器
案例0
tbl.列表行(1).范围(i,7)=“12月”
案例1
tbl.ListRows(1).范围(i,7)=“11月”
案例2
tbl.列表行(1).范围(i,7)=“10月”
案例3
tbl.列表行(1).范围(i,7)=“九月”
案例4
tbl.列表行(1).范围(i,7)=“8月”
结束选择
其他的
tbl.列表行(1).范围(i,7)=“12月”
如果结束
如果(计数器0为空),则“(我们不希望被0除)
对于n=6至(6-空_计数器+1)步骤-1
“每个月我们把剩下的分成两半_
取决于可用月份的百分比
tbl.ListRows(1).范围(i,n)=(剩余小时数/空计数器)
下一个
如果结束
“我们为每一行循环它
接下来我
端接头
生成的表如下所示:


见下图。填写完边际和后,将此公式输入B2并填写表格的其余部分(使用ctrl+shift+enter将其作为数组公式输入):


=IF(匹配($H2,$B$1:$F$1,0)只是想澄清一下……你想把总数放在A栏,月底放在F栏,想用一种方法自动填入B栏到E栏???@Gary的学生,这是正确的!它应该尊重月底、排队时间和每个月的百分比!你搞定了!这正是我想要的,非常感谢!我会研究你想要的你这么做是为了让我能提高我的知识水平,我以前从未使用过矩阵公式。再次,非常感谢!如果我不能弄清楚的话,很抱歉。这是一个项目时数的日历,因此总时数已经设置好,需要在每个月内分配,尊重每个月确定的时数比例d项目结束。请看@jblood94的解决方案,这些矩阵公式是神奇的。您好,好吧,尽管@jblood94的解决方案很优雅,但如果您必须不均匀地分配时间(如果项目不同时开始,这看起来像是不同项目的现实场景),则该解决方案将不起作用。我尝试在代码中使用注释进行描述,因此希望您能够根据自己的需要对其进行调整。如果开始时间是静态的,那么您就可以使用jblood94的解决方案:)此时,所有项目都在同一个月开始,但您所说的是真的。我将研究您的代码和@jblood94公式,看看是否可以将它们混合在一起以获得最终解决方案。再次感谢你的帮助!
Private Sub divide_time()

Dim tbl As ListObject: Set tbl = Sheets("Sheet1").ListObjects("Table1")
Dim hour_dist() As Integer
ReDim hour_dist(1 To 3)

' first we need to learn how many hours total we have available per project
For i = 1 To 3
    With tbl.ListColumns(1)
        hour_dist(i) = .Range(i + 1) ' we store each value into an array per project
    End With
Next i

Dim current As Double
Dim sumof As Double
Dim hours_left As Double
Dim empty_counter As Integer

For i = 1 To 3

    'we reset all of the counters per row
    sumof = 0
    empty_counter = 0

    'looping through all the column values in the row
    For j = 2 To 6
        current = tbl.ListRows(1).Range(i, j)
        sumof = sumof + current ' we get a sum of the current values in the row
        If (current = 0) Then 'if there is an empty cell, we keep track of it _
        (so we know into how many cells we can still divide the remaining time)
            empty_counter = empty_counter + 1
        End If
    Next j

    ' so we get how many hours we have left for the project _
    in comparison to  how many  months are free to distribute
    hours_left = (hour_dist(i) - sumof)

    'if we also want to store the info, _ 
    'what month we ended on before we distribute the remaining hours
    If (hours_left = 0) Then
    Select Case empty_counter
        Case 0
            tbl.ListRows(1).Range(i, 7) = "Dec"
        Case 1
            tbl.ListRows(1).Range(i, 7) = "Nov"
        Case 2
            tbl.ListRows(1).Range(i, 7) = "Oct"
        Case 3
            tbl.ListRows(1).Range(i, 7) = "Sep"
        Case 4
            tbl.ListRows(1).Range(i, 7) = "Aug"
    End Select
    Else
        tbl.ListRows(1).Range(i, 7) = "Dec"
    End if

    If (empty_counter <> 0) Then '( we dont want to be dividing by 0 )
    For n = 6 To (6 - empty_counter + 1) Step -1

        'for each month we divide what we have left _
         depending on the % of the months available
        tbl.ListRows(1).Range(i, n) = (hours_left / empty_counter)

    Next n
    End If



' and we loop it for each and every row
Next i

End Sub
=IF(MATCH($H2,$B$1:$F$1,0)<COLUMNS($B$1:B$1),0,($A2-SUM(C2:$G2))/(SUM(IF(MATCH($H$2:$H$4,$B$1:$F$1,0)<COLUMNS($B$1:B$1),0,$A$2:$A$4))-SUM(IF(MATCH($H$2:$H$4,$B$1:$F$1,0)<COLUMNS($B$1:B$1),0,C$2:$G$4)))*B$5)