The way I would takle it is first I would select all of the items manually, then iterate through each item extracting the coordinates, creating a list of X coords and Y coords.
If the X or Y coord of the current item being checked doesn't exist in the list of coordinates, add that coordinate to the list. When you are done, count the items in the list.
You could use the bounding box, but I suspect that unless you used a fixed width font, the top left corner may not be uniform. If all of the items utilize the same justification location, then this should work. Of course, if the insertion points of the items are not lined up, then you will have to compare the items with a fuzz factor.
Something like this ... (quick and dirty) ... it could be made more robust by getting the font size and comparing the insertion points with a fuzz factor by percentage of height and by filtering for object type (i.e. only selecting text, mtext, blocks etc.)
The return value is a list (rows cols)
(defun countRowCol( / ent ss xcoord xlist ycoord ylist)
(setq ss (ssget)
ndx 0)
(repeat (sslength ss)
(setq ent (ssname ss ndx)
ndx (1+ ndx)
)
(setq xcoord (cadr (assoc 10 (entget ent)))
ycoord (caddr(assoc 10 (entget ent)))
)
(if (= (member xcoord xlist) nil)
(setq xlist (append xlist (list xcoord)))
)
(if (= (member ycoord ylist) nil)
(setq ylist (append ylist (list ycoord)))
)
)
(list (length ylist) (length xlist))
)