The reason I think DSLs are good but macros are bad is because DSLs make you think long and hard about the costs of implementing a new language. You have to pay for it up-front by writing a compiler and hooking it into your build system, even if you have help from the host language's libraries, and then you'll end up with something that's clearly a separate language and must be documented and learned separately. That cost makes it clear that creating a DSL is not something to do lightly, and you need a problem domain where there really are much higher-level abstractions that can't be captured by an existing programming language.
The problem with macros is that you can create a new language construct with a half dozen or so lines of code, use it in a few hundred places in the codebase, and now your maintainers have a few hundred problems.
Is it just that, when a maintainer sees a function call it's easier to guess what it does, then when they see the use of a macro?
This does not refute your point at all -- that macros can be very helpful when implementing DSLs -- just wanted to point out that macros are not a requirement for doing so.
Also, a DSL expressed using first-class entities will fit into and integrate with its host language more nicely.
The reason is because I've come to understand that social factors trump technical factors nearly every time. The hardest part of writing a software system is almost never solving engineering challenges or writing code, it's communicating the solution to everyone who will have to touch it. Over a software system's lifetime, you will have to read code much more often than you will have to write code. Macros make writing code really easy and communicating everything about what it does, how it does it, and what invariants need to hold for it really hard. That's usually a poor trade-off for anything non-trivial.