假设您有一个包含三列数据的工作表。

|第一列按顺序排列字母表中的每个字母。第二列包含许多与字母表中的字母相关的事件。第三列包含与小时数相关的小时数。

如果您想根据第三列(小时)尽可能均匀地将字母组合成四组,该怎么办?

例如,如果字母表中每个字母的所有小时总和为4,000小时,那么您想提出一种组合,该组合将字母表分开,以便四个组中的每个组每个组大约有1,000小时。

这实际上是离散数学领域中的一个众所周知的问题。已经开发了多种算法来提供解决方案,并且存在某些编程语言(例如LISP)

这极大地有助于创建可以“搜索”最佳解决方案的树结构。

但是,在这种情况下,最好使用一种简单的方法,即使用宏。假设您的数据在A到C列中。以下宏将分析您指定的范围,并返回满足您要求的值的组合。

Function DoDist(sRaw As Range, _   iTCol As Integer, _   iBuckets As Integer, _   iWanted As Integer, _   iRetCol As Integer) As String

Dim lGTotal As Long     Dim lPerBucket As Long     Dim lCells() As Long     Dim sRet() As String     Dim lBk() As Long     Dim sBk() As String     Dim lTemp As Long     Dim sTemp As String     Dim J As Integer     Dim K As Integer     Dim L As Integer

Application.Volatile     ReDim lCells(sRaw.Rows.Count)

ReDim sRet(sRaw.Rows.Count)

ReDim lBk(iBuckets)

ReDim sBk(iBuckets)



lGTotal = 0     For J = 1 To sRaw.Rows.Count         lCells(J) = sRaw(J, iTCol)

lGTotal = lGTotal + lCells(J)

sRet(J) = sRaw(J, iRetCol)

Next J

For J = 1 To sRaw.Rows.Count - 1         For K = J + 1 To sRaw.Rows.Count             If lCells(J) < lCells(K) Then                 lTemp = lCells(J)

lCells(J) = lCells(K)

lCells(K) = lTemp                 sTemp = sRet(J)

sRet(J) = sRet(K)

sRet(K) = sTemp             End If         Next K     Next J

lPerBucket = lGTotal / iBuckets     For J = 1 To sRaw.Rows.Count         L = iBuckets         For K = iBuckets To 1 Step -1             If lBk(K) <= lBk(L) Then L = K         Next K         lBk(L) = lBk(L) + lCells(J)

sBk(L) = sBk(L) & sRet(J) & ", "

Next J

For J = 1 To iBuckets         If Right(sBk(J), 2) = ", " Then             sBk(J) = Left(sBk(J), Len(sBk(J)) - 2)

End If         sBk(J) = sBk(J) & " (" & lBk(J) & ")"

Next J

DoDist = sBk(iWanted)

End Function

请注意,此函数传递了五个参数。第一个是您要求值的范围,第二个是该范围内的列偏移量,应合计,第三个是要在评估中使用的“存储桶”数,第四个是要计算的值。您要返回的存储桶,第五个是包含要返回的值的列(在指定范围内)的偏移量。

宏所做的是获取要总计的列中的所有值,然后以降序对其进行排序。这些值从最大到最小然后分布在许多“桶”中

|您指定应该有。该数字总是添加到包含最小总数的存储桶中。该函数返回的字符串表示返回值(由第五个参数指定的列的每个单元格中的任何值)和存储桶的总数。

例如,如果您要评估范围A1:C:26,则希望分布基于范围第三列(C列)中的值,您希望分析中有四个存储桶,想要返回第三个存储桶,并且想要让该函数返回范围A列中的内容,那么您将使用以下代码来调用该函数:

=DoDist(A1:C26,3,4,3,1)

注意:

如果您想知道如何使用此页面(或_ExcelTips_网站上的任何其他页面)中描述的宏,我准备了一个特殊页面,其中包含有用的信息。

_ExcelTips_是您进行经济高效的Microsoft Excel培训的来源。

本技巧(12234)适用于Microsoft Excel 2007、2010、2013和2016。您可以在此处为Excel的较旧菜单界面找到此技巧的版本:

链接:/ excel-Determining_Combinations_to_Make_a_Total [确定要合计的组合]。