Запуск phpExcel в Битрикс при ошибке mb_string.func_overload=2

Если в настройках сервера стоит mbstring.func_overload = 2 то phpExcel не запускается, выдавая ошибку. Наблюдал на Битриксе.

Вариант решения - запуск отдельного приложения php cli через shell_exec.

ExcelConverter - класс для запуска скрипта array_to_excel.php. Пример использования:

// $this->sheet - массив по типу [0][0] = 'Значение ячейки'
$data = serialize($this->sheet);
$converter = new ExcelConverter();
$binData = $converter
  ->write($data)
  ->toExcel()
  ->read();
services/ExcelConverter.php
<?php
class ExcelConverter {
 
  public function __construct() {
    $this->file = tempnam('/tmp', 'xls_');
  }
 
  public function __destruct() {
    if(file_exists($this->file)) unlink($this->file);
  }
 
  public function write($binaryData) {
    $handle = fopen($this->file, 'wb');
    if(!is_resource($handle)) throw new Exception("Can not create temp file", 1);
    if(fwrite($handle, $binaryData) === false) throw new Exception("Can not write temp file", 1);
    fclose($handle);
    return $this;
  }
 
  public function toExcel() {
    $cmd = '/usr/bin/php '.escapeshellcmd($_SERVER["DOCUMENT_ROOT"].'/services/array_to_excel.php '.$this->file);
    $data = shell_exec($cmd);
    if(!preg_match('~^FILE SAVED:.*~m', $data)) throw new Exception("Can not convert to Excel", 1);
    return $this;
  }
 
  public function read() {
    $handle = fopen($this->file, 'rb');
    if(!is_resource($handle)) throw new Exception("Can not open temp file", 1);
    $binaryData = fread($handle, filesize($this->file));
    fclose($handle);
    return $binaryData;
  }
 
  public function name() {
    return $this->file;
  }
 
  public function filesize() {
    return filesize($this->file);
  }
}
array_to_excel.php
<?php
 
// преобразует массив в Excel файл
 
if(php_sapi_name() !== 'cli') die('Access denied'); // только из CLI
 
class ArrayToExcel {
 
  public function __construct() {
    $dir = dirname(__DIR__);
    require_once($dir.'/PHPExcel/Classes/PHPExcel/IOFactory.php');
    require_once($dir.'/PHPExcel/Classes/PHPExcel/Writer/Excel5.php');
  }
 
  public function run() {
    $this->loadData();
    $this->fillExcel();
    $this->save();
 
  }
 
  private $data, $file;
  private function loadData() {
    global $argv;
    $this->file = $argv[1];
    if(!file_exists($this->file)) throw new Exception("No file ".$this->file, 1);
    $handle = fopen($this->file, 'rb');
    if(!is_resource($handle)) throw new Exception("Can not open temp file", 1);
    $binData = fread($handle, filesize($this->file));
    fclose($handle);
    $this->data = unserialize($binData);
    if($this->data === false || !is_array($this->data)) throw new Exception("Wrong data", 1);
  }
 
  private function fillExcel() {
    $this->xls = new PHPExcel();
    $this->xls->setActiveSheetIndex(0);
    $sheet = $this->xls->getActiveSheet();
 
    foreach($this->data as $row => $rowData) {
      foreach($rowData as $col => $data) {
        $sheet->setCellValueByColumnAndRow($col, $row + 1, (string)$data); // 1-based index
      }
    }
  }
 
  private function save() {
    $objWriter = new PHPExcel_Writer_Excel5($this->xls);
    $objWriter->save($this->file);
    echo PHP_EOL.'FILE SAVED: '.$this->file;
  }
 
 
}
 
$converter = new ArrayToExcel();
$converter->run();