tl;dr Answer
The utility of SAS Macro, or of a text preprocessor in general,
is to support constructions that would be cumbersome to write
directly in the generated language.
Details
SAS Macro is a text preprocessor. It is similar in role to CPP within C/C++; M4 within several Unix utilities; Python- and Ruby-based template languages within HTML; etc. Text preprocessors have two main purposes:
to minimize redundant code by providing a data driven template mechanism
to transcend the limits imposed by the syntax of the generated language
Languages whose typical workflow lacks a text processor rely on string manipulation to support dynamic code generation and execution. Dynamic generation is especially difficult in Java.
Several SAS languages have a CALL EXECUTE
statement, but over time, users have preferred to use SAS Macro.
Users rely on SAS Macro in part because it is an exceptionally good text processor. Unlike most other text processors, it supports flow control, scope, function definitions, arithmetic, invoking library functions, comments, interactive input, and has (for a preprocessor, of course) an unobtrusive syntax.
Because it is perhaps too good, users have preferred SAS macro where Object-Oriented approaches (i.e., using PROC DS2, or more recently PROC GROOVY or PROC LUA) would have led to more maintainable code. New languages and new ways to access SAS are added frequently, but because SAS has so many users who have written pages linking to the old docs, sometimes PageRank can be slow to catch up. So people end up overusing Macro.
In my workflow, I search for whatever SAS language or PROC is best-suited to the task at hand, and perform the bulk of the processing in that language. However, every single day there is a use case where Macro makes things simpler than anything else. In those cases I use Macro. If you follow the principle of generated language first, Macro second, I think you'll find Macro to be an invaluable tool.