I'm going to admit that I wrote a program based on the individual CRM_READ_*_OW that can dynamically read all the header level data of any business transaction type based on a mapping definition of segments and fields. So using that program I have been able to extract many different types of transactions without needed to code per transaction type, but rather just add support per segment. I personally don't use CSV but use tab delimited instead, but that's besides the point. In addition I actually set the program to run in the background and e-mail out the results in order to avoid the fuss of dealing with grabbing files from the application server.
I think that CRM_ORDER_READ is probably an okay way of doing it and I would have gone down that approach if I didn't need to support potentially about 20 different transaction types. I'm sure someone has an easier less brute force approach, but for me the whole generic extract program took a week or less to build.
Take care,
Stephen