I would also recommend a Pipeline object for this task, not the current architecture. That will result in having three separate copies of all the data in the workstation memory:
1) The initial dw.retrieve - which invokes the stored procedure;
2) The external dw - that has all the summary data and headers too
3) The Excel spreadsheet
You might be able to free up some memory by doing a dw_1.Reset() and destroying it after doing the RowsCopy into the external dw. But a pipeline is still a better option.
-Paul-