Выборка всей базы товаров и отдача в CSV

Начнем с того, что выполнять генерацию файла будет на ajax или по прямому запросу. Более сложную логику в данном примере рассматривать не будем. Итак начнем.
Раз это ajax, то нам не понадобится вывод header.php и footer.php, но без пролога (prolog_before.php) ничего на выйдет:

define('STOP_STATISTICS', true);
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
$GLOBALS['APPLICATION']->RestartBuffer();
Собственно стандартная шапка для ajax-файла готова
Далее нам необходимо сделать выборки товаров и их ТП (торговых предложений)
$iblock_id = 1;
$arSelect = Array("IBLOCK_ID", "ID", "PROPERTY_*");  
$arFilter = Array("IBLOCK_ID"=>$iblock_id);   
$res = CIBlockElement::GetList(Array(), $arFilter, false, false, $arSelect);
while($arItem = $res->Fetch()){
	$arIds[] = $arItem['ID'];	//формируем массив ID элементов - он нам понадобится для красивой выборки ТП
	$arProduct[$arItem['ID']] = $arItem;	//формируем массив всех товаров, к нему будем прикреплять ТП
}
$res = CCatalogSKU::getOffersList(
	$arIds,	// массив ID товаров
	$iblockID = $iblock_id,	// указываете ID инфоблока только в том случае, когда ВЕСЬ массив товаров из одного инфоблока и он известен
	$skuFilter = array(),	// дополнительный фильтр предложений. по умолчанию пуст.
	$fields = array("PROPERTY_CML2_ARTICLE", "NAME"),  // массив полей предложений. даже если пуст - вернет ID и IBLOCK_ID
	$propertyFilter = array() 
);
foreach($res as $key => $arItem){
	$arProduct[$key]["OFFERS"] = $arItem;
}
Всё. На этом формирование выборки из БД основного инфоблока и его ТП завершено. Далее нам нужно просто сформировать строку для CSV, сгенерировать его, сохранить и отдать в браузер на скачивание
$str = "ID товара; ID ТП; Имя;свойство1;свойство2;\r\n";
foreach($arProduct as $sku){	//arProduct - массив товара с его свойствами
	foreach($sku['OFFERS'] as $row){	//row - массив ТП с его свойствами
		$str .= $sku['ID'].";".$row['ID'].";".$row['NAME'].";".$row['PROPERTY_КОД_СВОЙСТВА1'].";".$sku['PROPERTY_КОД_СВОЙСТВА1'].";\r\n";
	}
}

$fp = fopen('/АБСОЛЮТНЫЙ_ПУТЬ_ОТ_КОРНЯ_СЕРВЕРА/export.csv', 'w');	//открываем файл на запись. Если его нет - он будет создан
fwrite($fp, $str);	//записываем строку в дескриптор файла
fclose($fp);	//закрываем дескриптор
$file = "/АБСОЛЮТНЫЙ_ПУТЬ_ОТ_КОРНЯ_СЕРВЕРА/export.csv";
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream; charset=UTF-8');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
}
exit;
Всё. Теперь при обращении к файлу обработки по прямому адресу будет генерироваться CSV со всеми товарами и торговыми предложениями