Debra uses some dynamic range names to make her life a little easier.
Here's her code:
Option Explicit
Sub FilterCities()
Dim c As Range
Dim ws As Worksheet
'Add the heading to the criteria area
' and cities extract area
Sheets("CITIES").Range("A1").Value = _
Sheets("MAIN").Range("A1").Value
Sheets("CITIES").Range("D1").Value = _
Sheets("MAIN").Range("A1").Value
'rebuild the CityList
Sheets("MAIN").Columns("A:A").AdvancedFilter _
Action:=xlFilterCopy, _
CopyToRange:=Sheets("CITIES").Range("A1"), _
Unique:=True
Sheets("CITIES").Range("A1").CurrentRegion.Sort _
Key1:=Sheets("CITIES").Range("A2"), Order1:=xlAscending, _
Header:=xlGuess, OrderCustom:=1, _
MatchCase:=False, Orientation:=xlTopToBottom
'Add the heading to the criteria area
Sheets("CITIES").Range("D1").Value = _
Sheets("MAIN").Range("A1").Value
'check for individual City worksheets
For Each c In Range("CityList")
If WksExists(c.Value) = False Then
Set ws = Sheets.Add
ws.Name = c.Value
ws.Move After:=Sheets(Sheets.Count)
Else
Worksheets(c.Value).Cells.Clear
End If
'change the criteria in the Criteria range
Sheets("CITIES").Range("D2").Value = c.Value
'transfer data to individual City worksheets
Sheets("MAIN").Range("Database").AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=Sheets("CITIES").Range("D1

2"), _
CopyToRange:=Sheets(c.Value).Range("A1"), _
Unique:=False
Next
MsgBox "Data has been sent"
End Sub
Function WksExists(wksName As String) As Boolean
On Error Resume Next
WksExists = CBool(Len(Worksheets(wksName).Name) > 0)
End Function
=======
She has these two lines:
Dim c As Range
....
For Each c In Range("CityList")
And citylist is defined as:
=OFFSET(CITIES!$A$2,0,0,COUNTA(CITIES!$A:$A)-1,1)
This means that it's in the Cities worksheet starting at A2 and going down the
column for as many entries as there are there (but subtracts one for the
header).
Since this is a dynamic range, if you have 12 city names, or 122 city names, the
range will always include all the data.
On a test worksheet, try creating a range in A1:a99, then make a name like
Debra's =offset() formula. Just use the name of that worksheet in place of
cities.
Now hit F5 (edit|goto) and type in Citylist. You'll see all the cells
selected. Now delete a few rows from the bottom (don't leave gaps). Then
edit|goto and type citylist. You'll see that range contracted to just what was
left.
Debra has some nice notes about these dynamic ranges at:
http://www.contextures.com/xlNames01.html#Dynamic
You might be able to see it better.
It turns out that she uses that range to grab each unique value in your original
list. So after you create the name (and match it up in the code), you should be
ok.
And she does something with the name DataBase, too.
=OFFSET(MAIN!$A$1,0,0,COUNTA(MAIN!$A:$A),COUNTA(MAIN!$1:$1))
This one counts the number of columns used (don't leave gaps) and the number of
rows used (no gaps here either).
Then when she shows each value in that cityrange, she can copy it to either a
new workbook (or an existing workbook that's been cleared of all data).
This portion either creates a new worksheet or clears out the existing sheet:
If WksExists(c.Value) = False Then
Set ws = Sheets.Add
ws.Name = c.Value
ws.Move After:=Sheets(Sheets.Count)
Else
Worksheets(c.Value).Cells.Clear
End If
Since you want to keep rows 1:16, you could modify that Else portion like:
Worksheets(c.Value).Cells.Clear
becomes
worksheets(c.value).rows("17:65536").clear
later on, you can paste into A17:
Sheets("MAIN").Range("Database").AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=Sheets("CITIES").Range("D1

2"), _
CopyToRange:=Sheets(c.Value).Range("A1"), _
Unique:=False
becomes:
Sheets("MAIN").Range("Database").AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=Sheets("CITIES").Range("D1

2"), _
CopyToRange:=Sheets(c.Value).Range("A17"), _
Unique:=False
(A1 changed to A17.)
I'm not sure what criteria to be filtered is A6:d6. I'm guessing that you meant
A6 down (headers in A1:A5?).
Then you'll have to adjust your range name:
=OFFSET(MAIN!$a$5,0,0,COUNTA(MAIN!$A:$A)-5,COUNTA(MAIN!$1:$1))
(A5 to include the header & -5 only if A1:a5 (5 cells) have something in
them--you'll have to adjust that -5 to match your data.)
But since you're changing your headers, you have to change your advanced filter
to match up:
Sheets("CITIES").Range("A1").Value = _
Sheets("MAIN").Range("A5").Value
Sheets("CITIES").Range("D1").Value = _
Sheets("MAIN").Range("A5").Value
(It moves the headers into the right spots.)
I didn't test this, but it might be closer--I tried to include all those notes.
After writing most of this, I figured you could have the code define the
citylist name each time it runs--if you define it, that's fine, but the code
ignores your work--actually it destroys it!
So (if this works (haha!)), then all you have to do is define that Database name
correctly--remember no gaps in your rows or columns!
Option Explicit
Sub FilterCities()
Dim c As Range
Dim ws As Worksheet
Dim cityListRange As Range
Sheets("CITIES").Range("A1").Value = _
Sheets("MAIN").Range("A5").Value
Sheets("CITIES").Range("D1").Value = _
Sheets("MAIN").Range("A5").Value
'rebuild the CityList
With Sheets("Main")
.Range("a5:a" & .Cells(.Rows.Count, "A").End(xlUp).Row).AdvancedFilter _
Action:=xlFilterCopy, _
CopyToRange:=Sheets("CITIES").Range("A1"), _
Unique:=True
End With
Set cityListRange = Sheets("CITIES").Range("A1").CurrentRegion
With cityListRange
.Sort Key1:=.Cells(1), Order1:=xlAscending, _
Header:=xlYes, OrderCustom:=1, _
MatchCase:=False, Orientation:=xlTopToBottom
.Resize(.Rows.Count - 1, 1).Offset(1, 0).Name = "CityList"
End With
'Add the heading to the criteria area
Sheets("CITIES").Range("D1").Value = _
Sheets("MAIN").Range("A5").Value
'check for individual City worksheets
For Each c In Range("CityList")
If WksExists(c.Value) = False Then
Set ws = Sheets.Add
ws.Name = c.Value
ws.Move After:=Sheets(Sheets.Count)
Worksheets("main").Rows("1:16").Copy _
Destination:=ws.Range("a1")
Else
Worksheets(c.Value).Rows("17:65536").Clear
End If
'change the criteria in the Criteria range
Sheets("CITIES").Range("D2").Value = c.Value
'transfer data to individual City worksheets
Sheets("MAIN").Range("Database").AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=Sheets("CITIES").Range("D1

2"), _
CopyToRange:=Sheets(c.Value).Range("A17"), _
Unique:=False
Next
MsgBox "Data has been sent"
End Sub
Function WksExists(wksName As String) As Boolean
On Error Resume Next
WksExists = CBool(Len(Worksheets(wksName).Name) > 0)
End Function