Categorizing group of numbers which depicts an area coverage on a grid map

Chlwls808

Board Regular
Joined
Jun 20, 2021
Messages
51
Office Version
  1. 2016
Platform
  1. Windows
Hi,

I think this is more of a VBA question than a function.

Imagine a grid system that is numbered based on rows and columns. The numbers are rows, and letters are column - sort of like an excel sheet except rows increase from bottom to top.

4A 4B 4C 4D
3A 3B 3C 3D
2A 2B 2C 2D
1A 1B 1C 1D

Now, imagine again that each grid has 9 boxes numbered from top to bottom - 3 numbers per row (something like your telephone keypad).

The following list are coordinates which covers the grid. The numbers following the letter represent the area of each grid it covers (keypad format).

4A89
4B789
4C78
3A2356
3B123456
3C1245
2C9
2D78
1C3
1D12

1629680980025.png


If the list were randomized, is there a programmatical way to distinguish the list and categorize them by their areas? Whether if it's in two separate columns or text, doesn't matter; As long as they are separated.
 
I assume that the above quotes relate to the same thing?
Can you explain and give examples, including location, of what 20-8 or 90, 91, 92, 93, 94, 95, 96, 97, 98 actually means?
The first group in the coordinates are the numbers which corresponds to each 3x3 grid on the vertical axis. And the letters corresponds to horizontal range. They represent certain area that the coordinates point to. The numbers I'm dealing with usually fit within the 90's range so I'm OK with bottom row being 90 and the top as 98. I imagined changing the hardcoded numbers in the code if I needed to represent the map to be in a range that's something else, like 20's for example. I don't know what the implications are to the Excel performance if I tried making a grid much larger than that to accommodate beyond just the 90's range so I didn't put it out there.

Example could be:
94AA235689
94AB123456789
94AC1245789
93AC123
93AD123456
93AE14578
97AF2356
97AG1245678
98AG124578

PS: One thing to note is that my whole intention was to devise a way to segregate a group of numbers like above that are in its own area (borders not touching) and not the map itself.
It certainly is not happening for me.
  • Select a single cell somewhere on the sheet
  • Ctrl+F to bring up the Find dialog
  • Find what: leave blank, make sure Options>> is expanded, click the down arrow beside Format..., if 'Clear Find Format is not greyed out then click it & then the down arrow again and choose Format..., put a tick beside merge cells, View attachment 46626, OK, Find All
  • If the sheet has merged cells you should see something like this that identifies where they are View attachment 46627
Good to know!
 
Last edited:
Upvote 0

Excel Facts

Can a formula spear through sheets?
Use =SUM(January:December!E7) to sum E7 on all of the sheets from January through December
Creating a "map" with vertical blocks numbered from 90 to 98...

MapGrid 210903.xlsm
ABCDEFGHIJKLMNOPQRSTUVWX
112
245
378
42312
556456
678
7
8
9
10
11
12
132312312
145645645
1589789789
161231231
1745645
1878
19
20
21
Map


MapGrid 210903.xlsm
ABC
194AA23568998AG12457894AA235689
294AB12345678997AF235694AB123456789
394AC124578997AG124567894AC1245789
493AC12393AC123
593AD12345693AD123456
693AE1457893AE14578
797AF2356
897AG1245678
998AG124578
List


VBA Code:
Sub FillMap2()
Dim nm As Name
Dim r1 As Range, r2 As Range
Dim i As Long, j As Long
Dim sht1 As String, sht2 As String

Application.ScreenUpdating = False
sht1 = "List"
sht2 = "Map"
For Each r1 In Sheets(sht1).Range("A1:A" & Sheets(sht1).Cells(Rows.Count, "A").End(xlUp).Row)
    For Each nm In ActiveWorkbook.Names
        If nm.RefersToRange.Parent.Name = Sheets(sht2).Name Then
            For j = 1 To Len(r1.Text)
                If Not (IsNumeric(Mid(r1.Text, j, 1))) Then Exit For
            Next j
            If Left(r1.Value, j + 1) = Mid(nm.Name, 2, j + 1) Then
                Set r2 = Range(nm).Cells(1, 1)
                i = 2
                Do Until i = Len(r1)
                    i = i + 1
                    If Mid((r1), i, 1) = 1 Then r2.Offset(0, 0) = 1
                    If Mid((r1), i, 1) = 2 Then r2.Offset(0, 1) = 2
                    If Mid((r1), i, 1) = 3 Then r2.Offset(0, 2) = 3
                    If Mid((r1), i, 1) = 4 Then r2.Offset(1, 0) = 4
                    If Mid((r1), i, 1) = 5 Then r2.Offset(1, 1) = 5
                    If Mid((r1), i, 1) = 6 Then r2.Offset(1, 2) = 6
                    If Mid((r1), i, 1) = 7 Then r2.Offset(2, 0) = 7
                    If Mid((r1), i, 1) = 8 Then r2.Offset(2, 1) = 8
                    If Mid((r1), i, 1) = 9 Then r2.Offset(2, 2) = 9
                Loop
            End If
        End If
    Next nm
Next r1
Application.ScreenUpdating = True
End Sub

VBA Code:
Sub MapGroup()
Dim Group As Range, rng As Range
Dim str2 As String, str3 As String
Dim nm As Name
Dim LastRow As Long, LastCol As Long
Dim sht1 As String, sht2 As String

Application.ScreenUpdating = False
Set Group = Selection
sht1 = "List"
sht2 = "Map"
LastCol = Sheets(sht1).Cells(1, Columns.Count).End(xlToLeft).Column

''' Loop thru named ranges
For Each nm In ActiveWorkbook.Names
    str2 = ""
    If Not Intersect(Range(nm.Name), Group) Is Nothing Then
        For Each rng In Range(nm.Name)
            If Not Intersect(Range(nm.Name), rng) Is Nothing And rng <> "" Then
                str2 = str2 & rng.Value
            End If
        Next rng
        If str2 <> "" Then
            str3 = Right(nm.Name, Len(nm.Name) - 1) & str2
            LastRow = Sheets(sht1).Cells(Rows.Count, LastCol + 1).End(xlUp).Row
            If Sheets(sht1).Cells(LastRow, LastCol + 1) = "" Then
                Sheets(sht1).Cells(LastRow, LastCol + 1) = str3
            Else
                Sheets(sht1).Cells(LastRow + 1, LastCol + 1) = str3
            End If
        End If
    End If
Next nm

Sheets(sht1).Activate
Dim r1 As Range, j As Long
''' Separate alphanumeric characters into helper columns
For Each r1 In Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1))
    For j = 1 To Len(r1.Text)
        If Not (IsNumeric(Mid(r1.Text, j, 1))) Then
            r1.Offset(0, 1) = Mid(r1.Text, 1, j - 1)
            r1.Offset(0, 2) = Mid(r1.Text, j, 2)
            r1.Offset(0, 3) = Mid(r1.Text, j + 2, Len(r1.Text) - j - 1)
            Exit For
        End If
    Next j
Next r1
''' Sort the list
Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 3)).Offset(0, 1).Sort _
    key1:=Cells(1, LastCol + 2), order1:=xlDescending, _
    key2:=Cells(1, LastCol + 3), order2:=xlAscending, Header:=xlNo
Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1)).Offset(0, 4).FormulaR1C1 = "=CONCATENATE(RC[-3],RC[-2],RC[-1])"
Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1)).Offset(0, 4).Value = Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1)).Offset(0, 4).Value
Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1)).Value = Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1)).Offset(0, 4).Value
Sheets("List").Range(Cells(1, LastCol + 1), Cells(LastRow + 1, LastCol + 1)).Resize(, 4).Offset(0, 1).Delete
Application.ScreenUpdating = True

End Sub

The code has been revised to accommodate 1 or 2 digit prefixes.

Curious... how do you solve this now? Do you reference a map?
 
Upvote 0
Solution
The code has been revised to accommodate 1 or 2 digit prefixes.

Curious... how do you solve this now? Do you reference a map?
Hey @tonyyy , Thanks for the update. I got a fresh sheet and executed the FillMap2 but nothing happens in the Map sheet. Do I need to name the ranges accordingly first?
 
Upvote 0
Hey @tonyyy , Thanks for the update. I got a fresh sheet and executed the FillMap2 but nothing happens in the Map sheet. Do I need to name the ranges accordingly first?
@tonyyy disregard. That was it!

Curious... how do you solve this now? Do you reference a map?
There's nothing to solve. I'm able to separate the list by its areas which was what I was looking for. The coordinates are already referenced to a given area; there needed to be a way to isolate them somehow.

Thanks a bunch! I'm still baffled how generous you guys are here. I really hope this thread helps out someone else in the future!
 
Upvote 0
@tonyyy I'm not sure if you ever come across this issue but I when I copy a worksheet from another workbook and put it alongside List and Map, I notice this error pops out at me each time I execute FillMap2 again. I also tried adding a new worksheet to an existing workbook that I already use and named it List and Map, and they produce the same issue. The only time when I can get this work without any error is when I build from scratch a complete new worksheet by itself.

VBA Code:
Runtime error 1004: Application or object-defined error.

Debug:

1631314708295.png


I looked up some sources on the possible causes and they mention the following.. but I'm not sure if any of the FillMap2 code pertains to them or not.
 
Upvote 0
I imagined changing the hardcoded numbers in the code if I needed to represent the map to be in a range that's something else, like 20's for example.
OK, given that, here is my attempt (not greatly tested) for filling and mapping without named ranges.
Still assuming that we can have a blank row 1 and column A (hidden if you want)
Also assuming column CB is blank

VBA Code:
Sub FillAndMapLarge_v2()
  Dim d As Object, dGr As Object
  Dim itms As Variant
  Dim r As Range, c As Range
  Dim i As Long, j As Long, k As Long, Grp As Long, fr As Long, NumDigits As Long
  Dim adr As String, pref As String
  
  Const RowRange As String = "90-98" '<- Set your prefix row range here
  
  fr = Split(RowRange, "-")(0)
  
  'Fill
  Application.ScreenUpdating = False
  Range("B2:CA28").ClearContents
  NumDigits = Len(CStr(fr))
  For Each r In Range("CC2", Range("CC" & Rows.Count).End(xlUp))
    With Cells(29 - 3 * (Left(r.Value, NumDigits) - fr + 1), 3 * (Asc(Mid(r.Value, NumDigits + 2, 1)) - 64) - 1).Resize(3, 3)
      For i = NumDigits + 3 To Len(r.Value)
        .Cells(Mid(r.Value, i, 1)) = Mid(r.Value, i, 1)
      Next i
    End With
  Next r
  
  'Map
  Set d = CreateObject("Scripting.Dictionary")
  Set dGr = CreateObject("Scripting.Dictionary")
  
  For i = 2 To 28
    For j = 2 To 79
      If Not IsEmpty(Cells(i, j).Value) Then
        Set c = Cells(i, j)
        adr = c.Address(0, 0)
        pref = (fr + 8 - Int((c.Row - 2) / 3)) & "A" & Chr(Int((c.Column - 2) / 3) + 65) & "*"
        If d.exists(c.Offset(, -1).Address(0, 0)) Then
          d(adr) = d(c.Offset(, -1).Address(0, 0))
        Else
          k = 0
          Do Until IsEmpty(c.Offset(, k).Value)
            If d.exists(c.Offset(-1, k).Address(0, 0)) Then
              d(adr) = d(c.Offset(-1, k).Address(0, 0))
              Exit Do
            End If
            k = k + 1
          Loop
        End If
        If Not d.exists(adr) Then
          Grp = Grp + 1
          d(adr) = "Group " & Grp
        End If
        
        'Check column CC values & allocate to group
        For Each r In Range("CC1", Range("CC" & Rows.Count).End(xlUp))
          If r.Value Like pref & c.Value & "*" Then
            dGr(d(adr)) = dGr(d(adr)) & " " & r.Value
            Exit For
          End If
        Next r
      End If
    Next j
  Next i

  'Check column CC values & allocate to group
  For Each r In Range("CC1", Range("CC" & Rows.Count).End(xlUp))
    If r.Value Like pref & c.Value & "*" Then
      dGr(d(adr)) = dGr(d(adr)) & " " & r.Value
      Exit For
    End If
  Next r
  
  'Enter results in columns CE onwards
  Range("CE2").CurrentRegion.ClearContents
  For Grp = 1 To dGr.Count
    Range("CD2").Offset(, Grp).Value = dGr.Keys()(Grp - 1)
    itms = Split(Mid(dGr.Items()(Grp - 1), 2))
    With Range("CD2").Offset(1, Grp).Resize(UBound(itms) + 1)
      .Value = Application.Transpose(itms)
      .Resize(.Rows.Count + 1).RemoveDuplicates Columns:=1, Header:=xlNo
    End With
  Next Grp
  Application.ScreenUpdating = True
End Sub

Results using your sample values from post #31

Chlwls808_tonyyy.xlsm
ABCDEFGHIJKLMNOPQRSTUVWXYZAAABBYBZCACBCCCDCECF
1
21294AA235689Group 1Group 2
34594AB12345678998AG12457894AA235689
47894AC124578997AF235694AB123456789
5231293AC12397AG124567894AC1245789
65645693AD12345693AC123
77893AE1457893AD123456
897AF235693AE14578
997AG1245678
1098AG124578
11
12
13
142312312
155645645
1689789789
171231231
1845645
1978
20
21
22
23
24
25
26
27
28
Large (2)



And a couple of other examples with RowRange set to "1-9"

Chlwls808_tonyyy.xlsm
ABCDEFGHIJKLMCBCCCDCECF
1
29AA89Group 1Group 2
39AB7899AA897AC1256
4897896AD19AB7897AD47
536AC238AB3696AC23
668AB3696AD1
797AC1256
8127AD47
9564
107
11231
12
13
Large (3)


Chlwls808_tonyyy.xlsm
ABCDEFGHIJKLMCBCCCDCECF
1
29AA89Group 1
39AB7899AA89
4897896AD19AB789
536AC238AB369
668AB3698AC7
7977AC12567AC1256
8127AD477AD47
95648AC76AC23
1076AD1
11231
12
13
Large (3)
 
Upvote 0
@Peter_SSs Wow, caps off to you. This works perfectly.

So far all the data I've used has passed!

Thank you so much.
 
Upvote 0
You're welcome. Glad it works for you. Thanks for the confirmation. :)
 
Upvote 0

Forum statistics

Threads
1,215,004
Messages
6,122,656
Members
449,091
Latest member
peppernaut

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