Ho grandi fogli di lavoro Excel che voglio essere in grado di leggere in MySQL usando PHPExcel.Come leggere fogli di lavoro di grandi dimensioni da file Excel di grandi dimensioni (27 MB +) con PHPExcel?
Sto usando il recent patch che consente di leggere nei fogli di lavoro senza aprire l'intero file. In questo modo posso leggere un foglio di lavoro alla volta.
Tuttavia, un file di Excel ha una larghezza di 27 MB. Posso leggere con successo nel primo foglio di lavoro poiché è piccolo, ma il secondo foglio di lavoro è così grande che il processo cron che ha avviato il processo alle 22:00 non è stato completato alle 8:00, il foglio di lavoro è troppo grande.
C'è un modo per leggere in un foglio di lavoro riga per riga, ad es. qualcosa di simile:
$inputFileType = 'Excel2007';
$inputFileName = 'big_file.xlsx';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$worksheetNames = $objReader->listWorksheetNames($inputFileName);
foreach ($worksheetNames as $sheetName) {
//BELOW IS "WISH CODE":
foreach($row = 1; $row <=$max_rows; $row+= 100) {
$dataset = $objReader->getWorksheetWithRows($row, $row+100);
save_dataset_to_database($dataset);
}
}
Addendum
@ Marco, ho usato il codice che avete inviato per creare il seguente esempio:
function readRowsFromWorksheet() {
$file_name = htmlentities($_POST['file_name']);
$file_type = htmlentities($_POST['file_type']);
echo 'Read rows from worksheet:<br />';
debug_log('----------start');
$objReader = PHPExcel_IOFactory::createReader($file_type);
$chunkSize = 20;
$chunkFilter = new ChunkReadFilter();
$objReader->setReadFilter($chunkFilter);
for ($startRow = 2; $startRow <= 240; $startRow += $chunkSize) {
$chunkFilter->setRows($startRow, $chunkSize);
$objPHPExcel = $objReader->load('data/' . $file_name);
debug_log('reading chunk starting at row '.$startRow);
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null, true, true, true);
var_dump($sheetData);
echo '<hr />';
}
debug_log('end');
}
Come mostra il file di log, si corre bene su un piccolo file 8K Excel, ma quando lo eseguo su un file Excel 3 MB, non viene mai superato l'abete st pezzo, c'è un modo per ottimizzare il codice per le prestazioni, in caso contrario non sembra non è abbastanza performante per ottenere pezzi di un file di grandi dimensioni di Excel:
2011-01-12 11:07:15: ----------start
2011-01-12 11:07:15: reading chunk starting at row 2
2011-01-12 11:07:15: reading chunk starting at row 22
2011-01-12 11:07:15: reading chunk starting at row 42
2011-01-12 11:07:15: reading chunk starting at row 62
2011-01-12 11:07:15: reading chunk starting at row 82
2011-01-12 11:07:15: reading chunk starting at row 102
2011-01-12 11:07:15: reading chunk starting at row 122
2011-01-12 11:07:15: reading chunk starting at row 142
2011-01-12 11:07:15: reading chunk starting at row 162
2011-01-12 11:07:15: reading chunk starting at row 182
2011-01-12 11:07:15: reading chunk starting at row 202
2011-01-12 11:07:15: reading chunk starting at row 222
2011-01-12 11:07:15: end
2011-01-12 11:07:52: ----------start
2011-01-12 11:08:01: reading chunk starting at row 2
(...at 11:18, CPU usage at 93% still running...)
Addendum 2
Quando io commento:
//$sheetData = $objPHPExcel->getActiveSheet()->toArray(null, true, true, true);
//var_dump($sheetData);
Poi si analizza ad una velocità accettabile (circa 2 righe al secondo), è comunque necessario aumentare le prestazioni di toArray()
?
2011-01-12 11:40:51: ----------start
2011-01-12 11:40:59: reading chunk starting at row 2
2011-01-12 11:41:07: reading chunk starting at row 22
2011-01-12 11:41:14: reading chunk starting at row 42
2011-01-12 11:41:22: reading chunk starting at row 62
2011-01-12 11:41:29: reading chunk starting at row 82
2011-01-12 11:41:37: reading chunk starting at row 102
2011-01-12 11:41:45: reading chunk starting at row 122
2011-01-12 11:41:52: reading chunk starting at row 142
2011-01-12 11:42:00: reading chunk starting at row 162
2011-01-12 11:42:07: reading chunk starting at row 182
2011-01-12 11:42:15: reading chunk starting at row 202
2011-01-12 11:42:22: reading chunk starting at row 222
2011-01-12 11:42:22: end
Addendum 3
Questo sembra funzionare in modo adeguato, per esempio, almeno sul file 3 MB:
for ($startRow = 2; $startRow <= 240; $startRow += $chunkSize) {
echo 'Loading WorkSheet using configurable filter for headings row 1 and for rows ', $startRow, ' to ', ($startRow + $chunkSize - 1), '<br />';
$chunkFilter->setRows($startRow, $chunkSize);
$objPHPExcel = $objReader->load('data/' . $file_name);
debug_log('reading chunk starting at row ' . $startRow);
foreach ($objPHPExcel->getActiveSheet()->getRowIterator() as $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(false);
echo '<tr>';
foreach ($cellIterator as $cell) {
if (!is_null($cell)) {
//$value = $cell->getCalculatedValue();
$rawValue = $cell->getValue();
debug_log($rawValue);
}
}
}
}
La var_dump di $ sheetData era solo nella mia frammento di codice per dimostrare come funziona il chunking, probabilmente non qualcosa che ci serve in un utilizzo "mondo reale". Il metodo rangeToArray() che sto attualmente aggiungendo alla classe del foglio di lavoro sarebbe anche più efficiente del metodo toArray() se fosse necessario eseguire un dump dei dati del foglio di lavoro. –
@Edward Tanguay ciao, hai trovato qualche soluzione/alternativa per questo? Sto avendo lo stesso problema –
Un'alternativa a PHPExcel è la libreria open source [Spout] (https://github.com/box/spout). Supporta la lettura e la scrittura di file enormi e non richiede più di 10 MB di memoria. Ed è super veloce! – Adrien