месяца три назад делал быстрое решение (нужно было срочно), достаточно весь вывод отловить через ob_start и выдать браузеру как файл через http_header. Все прекрастно работало даже отдавались картинки и работали ссылки, поскольку Excel без проблем понимает html формат в чистом виде, и даже прожовывает css (но не все)
примерно
{php}
$out1 = ob_get_contents();
ob_end_flush();
$csv_output ='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<base href="{$smarty.server.SERVER_NAME}" />
<meta http-equiv="content-type" content="text/html; charset=cp1251" />
<meta name="author" content="" />
<style type="text/css">
table.gre_y{background:#D0D1D5;}
table.gre_y td{background:#fff;color:#000 !important;border:1px solid #000;}
table.gre_y table td{border:none;}
table.gre_y td.lt{font-weight:bold;background:#ffcc00;color:#000 !important;}
table.gre_y a{color:#000 !important;}
table.gre_y.noline{font-size:20px;}
</style>
<title></title>
</head>
<body>';
$csv_output .= $out1;
$csv_output .='</body></html>';
file_put_contents('price.xls', $csv_output);
{/php}