Formula to Evenly Distribute Guests on a Seating Plan

markmogli

New Member
Joined
Dec 20, 2019
Messages
19
Office Version
  1. 365
Platform
  1. Windows
Hello,

I have a spreadsheet where column A has the company name and column B has the total guests booked to attend the event. I need to allocate the guests to tables where the smallest can be a table of 7 and the largest can be a table of 14. I also need to allocate the party to the smallest number of tables possible.

A party of 15 guests will be seated as 1 x table of 7 and 1 x table 8.


A party of 20 guests will be seated as 2 x tables of 10.


A party of 36 guests can be seated as either

3 x tables of 12

or

1 x table of 13, 1 x table of 12 and 1 x table of 11


A party of 100 guests can be seated as:

10 tables of 10

but they could also be seated as:

6 x tables of 14 and 2 x tables of 8


I have 2,200 guests to seat and a maximum of 220 tables. I want the least possible tables and as bonus points, I only have 30 tables which will take 13 or 14 guests, the other 190 tables seat a max of 12.
 
One last update because this one was fun. Below is an updated VBA solution that gets rid of the matrix and does everything in memory. And the other is a Power Query solution.

Book1
ABC
1CustomerGuestsResult
2Company 11191x7, 8x14
3Company 291x9
4Company 3602x9, 3x14
5Company 4602x9, 3x14
6Company 5151x7, 1x8
7Company 6162x8
8Company 7121x12
9Company 8191x9, 1x10
10Company 9291x7, 1x8, 1x14
11Company 10191x9, 1x10
12Company 1191x9
13Company 12101x10
14Company 13111x11
15Company 14261x12, 1x14
16Company 15141x14
Sheet7


VBA Code:
Sub ALLOCATE()
Dim AL As Object:           Set AL = CreateObject("System.Collections.ArrayList")
Dim r As Range:             Set r = Range("A2:B" & Range("A" & Rows.Count).End(xlUp).Row)
Dim AR() As Variant:        AR = r.Value
Dim Res() As Variant:       ReDim Res(1 To UBound(AR))
Dim MinTblSize As Integer:  MinTblSize = 6
Dim MaxTblSize As Integer:  MaxTblSize = 14
Dim Total As Long, Dif As Long, MaxLarge As Long, sp As Long

For i = 1 To UBound(AR)
    Total = AR(i, 2)
    If Total < MaxTblSize Then
        AL.Add fStr(1, AR(i, 2))
    Else
        MaxLarge = Int(AR(i, 2) / MaxTblSize)
        Dif = AR(i, 2) - (MaxLarge * MaxTblSize)
        If Dif > 0 Then
            If Dif >= MinTblSize And Dif < MaxTblSize Then
                AL.Add fStr(1, Dif)
            Else
                Dif = Dif + MaxTblSize
                MaxLarge = MaxLarge - 1
                If Dif Mod 2 = 1 Then
                    sp = Int(Dif / 2)
                    AL.Add fStr(1, sp)
                    AL.Add fStr(1, sp + 1)
                Else
                    AL.Add fStr(2, Dif / 2)
                End If
            End If
            If MaxLarge > 0 Then AL.Add fStr(MaxLarge, 14)
        Else
            AL.Add fStr(MaxLarge, MaxTblSize)
        End If
    End If
    Res(i) = Join(AL.toarray, ", ")
    AL.Clear
Next i

r.Resize(r.Rows.Count, 1).Offset(, 2).Value = Application.Transpose(Res)
            
End Sub

Function fStr(num As Variant, size As Variant) As String
fStr = num & "x" & size
End Function

PQ

Book1
DEF
1CustomerGuestsFinal
2Company 11191x7, 8x14
3Company 291x9
4Company 3602x9, 3x14
5Company 4602x9, 3x14
6Company 5151x7, 1x8
7Company 6162x8
8Company 7121x12
9Company 8191x9, 1x10
10Company 9291x7, 1x8, 1x14
11Company 10191x9, 1x10
12Company 1191x9
13Company 12101x10
14Company 13111x11
15Company 14261x12, 1x14
16Company 15141x14
Sheet8


Code:
let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Customer", type text}, {"Guests", Int64.Type}}),
    Max14 = Table.AddColumn(#"Changed Type", "Max14", each Number.RoundDown([Guests]/14)),
    Total14 = Table.AddColumn(Max14, "Total14", each [Max14]*14),
    Diff = Table.AddColumn(Total14, "Diff", each if [Total14] = [Guests] then null else [Guests]-[Total14]),
    NewDiff = Table.AddColumn(Diff, "NewDiff", each if [Diff] = null then null else
if [Diff] < 6 then [Diff]+14 else [Diff]),
    New14 = Table.AddColumn(NewDiff, "New14", each if [NewDiff] = null then [Guests] else
if [Diff]=[NewDiff] then [Max14] else [Max14]-1),
    Div = Table.AddColumn(New14, "Div", each if [NewDiff] = null then null else
if [NewDiff] <=14 then [NewDiff] else [NewDiff] /2),
    Num1 = Table.AddColumn(Div, "Num1", each if Int64.From([Div])-[Div] = 0 then [Div] else Number.RoundDown([Div])),
    Num2 = Table.AddColumn(Num1, "Num2", each if [Div] = [Num1] then null else [Num1]+1),
    #"14" = Table.AddColumn(Num2, "14Count", each if [New14] = 0 then null else
if [New14] = [Total14] then "1x" & Text.From([Total14]) else if [New14] > 0 then Text.From([New14]) & "x" & "14" else null),
    R1 = Table.AddColumn(#"14", "R1", each if [Num1] = null then null else
if [NewDiff] > [Diff] and [Num2] = null then  "2x" & Text.From([Num1]) else
"1x" & Text.From([Num1])),
    R2 = Table.AddColumn(R1, "R2", each if [Diff] = null then null else "1x" & Text.From([Num2])),
    Replace = Table.ReplaceValue(R2,null,"",Replacer.ReplaceValue,{"14Count", "R1", "R2"}),
    Final = Table.AddColumn(Replace, "Final", each Text.Combine(Table.ToList(Table.SelectRows(Table.Transpose(Table.FromColumns({{[R1]},{[R2]},{[14Count]}})), each Text.Length([Column1])>0)),", ")),
    Remove = Table.RemoveColumns(Final,{"Max14", "Total14", "Diff", "NewDiff", "New14", "Div", "Num1", "Num2", "14Count", "R1", "R2"})
in
    Remove
 
Upvote 0

Excel Facts

Excel motto
Not everything I do at work revolves around Excel. Only the fun parts.
Wow, thanks for that, Irobbo314.

Is there anyway to do this without VBA / PQ, using jut formulas?
 
Upvote 0

Forum statistics

Threads
1,214,918
Messages
6,122,257
Members
449,075
Latest member
staticfluids

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top