Make a copy of the target surface - ExtractSrf with Copy=Yes will do it. Hide everything else
ShrinkTrimmedSrf
Rebuild to a high point count - say 32 by maybe 256 in this case to get an even grid and evenly distributed UV
CreateUVCrv
Move all of the results to one side for convenience and make an array of circles inside the perimeter rectangle
Now, there are two possible workflows that I can see
Make a PlanarSrf from the perimeter rectangle.
Extrude the circles a short distance ,BothDirections
FlowAlongSrf the circles from the plane to the rebuilt surface
(the possible advantage is to this route is that you can use the Rigid in the Flow and get a true, un-tapered cylinder at each location)
OR
ApplyCrv the outer rectangle and the circles to the rebuilt surface
Either way, use the results to trim the orginal surface - the rebuilt one can be discarded.
And, either way, making that many holes in a surface is a good way to slow Rhino down to a crawl -
A few of each in the attached file. The rebuilt surface is in place the original hidden.
Have you tried PanelingTools? It should give you great flexibility to work with surfaces and add any cellular 2D or 3D texture or perforation. Use ptOrientToGrid, or ptPanelGridCustom, then split the surface with the populated pattern.