excel 将列表中的值求和到一定的数量,并创建最少数量的“集合”

xuo3flqw  于 2023-05-01  发布在  其他
关注(0)|答案(2)|浏览(121)

我有一个列表,其中的值大小可变,各个值的范围从1到33。(这是基于卡车中的托盘数量。)
我想选择该范围,并让VBA代码决定将值相加为33(永远不会超过33)的最佳方法,并使用这些值创建一个数组,然后移动到下一个“集合”,并将下一个添加到33的值放入新数组中。我知道如何长期地做(感谢Stack Overflow用户),但这不是最有效的选择。
假设我有一个包含5个值的列表:
10
15
8
22
19
这将创建3个“集”:
25
30
19
如果5个值的顺序更改为:
19
22
15
10
8
这将创建4个“集”:
19
22
15
18
我找到了一种方法来定义代码应该创建的卡车的最佳数量的变量,但是对于第二个列表,如果代码长期遍历该列表,则会导致错误。
有没有可能创建一个代码,它会查看一组值,并决定最有效的组合最接近33的值的方法。

  1. Sub test()
  2. Dim ref, b As Range
  3. Dim volume, i As Integer
  4. Dim test1(), check, total As Double
  5. Dim c As Long
  6. Set ref = Selection
  7. volume = ref.Cells.Count
  8. c = ref.Column
  9. ReDim test1(1 To volume)
  10. 'this creates a total of all the values i select
  11. For Each b In ref
  12. total = total + b
  13. Next b
  14. 'this determines when to round up or down
  15. check = total / 33 - Application.WorksheetFunction.RoundDown(total / 33, 0)
  16. If check < 0.6 Then
  17. total = Application.WorksheetFunction.RoundDown(total / 33, 0)
  18. Else
  19. total = Application.WorksheetFunction.RoundUp(total / 33, 0)
  20. End If
  21. 'this creates an array with all the values
  22. i = 1
  23. Do Until i = volume + 1
  24. test1(i) = Cells(i, c).Value
  25. i = i + 1
  26. Loop
  27. 'this is just a way for me to check and verify my current part of the code
  28. MsgBox (Round(test1(8), 2))
  29. MsgBox (total)
  30. End Sub
moiiocjp

moiiocjp1#

您可以根据自己的意愿更改单元格结果位置。我在即时窗口中显示结果。

  1. Sub test()
  2. Dim CellsCount As Integer
  3. CellsCount = Selection.Cells.Count
  4. Dim i, j As Long
  5. Dim x, y As Long
  6. Dim SumLoop As Long
  7. SumLoop = 0
  8. x = 1
  9. y = 1
  10. For i = x To CellsCount
  11. Do
  12. For j = y To CellsCount
  13. SumLoop = SumLoop + Selection.Cells(j).Value
  14. If SumLoop < 33 Then
  15. Debug.Print SumLoop
  16. y = j + 1
  17. If y = CellsCount + 1 Then Exit Sub
  18. Else
  19. SumLoop = 0
  20. x = j
  21. y = j
  22. Exit For
  23. End If
  24. Next
  25. Loop While SumLoop < 33
  26. Next
  27. End Sub
展开查看全部
ifsvaxew

ifsvaxew2#

这是一个直接的蛮力,检查每一个组合,如果你的集合变得太大,这将慢下来,但它是〈1秒的一组1000。
我把数值输入A列。输出您所需的最低数量的卡车。
你可能可以通过使用类型或类来减少变量的数量,但希望保持相对简单。

  1. Dim i As Long
  2. Dim lr As Long
  3. Dim limit As Long
  4. Dim count As Long
  5. Dim sets As Long
  6. Dim best As Long
  7. Dim start As Long
  8. Dim addset As Boolean
  9. Dim loopcounter As Long
  10. limit = 33
  11. With Sheets("Sheet1")
  12. lr = .Cells(.Rows.count, 1).End(xlUp).Row
  13. Dim arr() As Long
  14. ReDim arr(0 To lr - 2)
  15. For i = 2 To lr
  16. arr(i - 2) = .Cells(i, 1).Value 'Load array
  17. Next i
  18. start = 0
  19. i = start
  20. Do
  21. If count + arr(i) <= limit Then
  22. count = count + arr(i)
  23. addset = False 'Just for tracking the final set
  24. Else
  25. addset = True
  26. sets = sets + 1
  27. count = arr(i)
  28. End If
  29. i = i + 1
  30. If i > UBound(arr) Then
  31. i = 0 'reset index
  32. End If
  33. loopcounter = loopcounter + 1 'tracking items in set
  34. If loopcounter > UBound(arr) Then
  35. If addset = False Then
  36. sets = sets + 1 'adding final set if not already added
  37. End If
  38. Debug.Print start, sets
  39. If best > sets Or best = 0 Then
  40. best = sets 'Get the lowest value
  41. End If
  42. 'resetting values
  43. loopcounter = 0
  44. sets = 0
  45. start = start + 1
  46. i = start
  47. If start > UBound(arr) Then
  48. Exit Do
  49. End If
  50. End If
  51. Loop
  52. End With
  53. Debug.Print best
展开查看全部

相关问题