PHP - PHPSpreadsheet выходит из памяти или вызывает слишком много вложенных функций
Я пытаюсь проанализировать не очень большой файл XLS/CSV, используя PHPSpreadsheet.
Файл имеет только 1745 строк и 11 столбцов. Размер файла составляет 317 КБ в формате XLS или 157 в формате CSV. Дело в том, что PHP выдает мне эти ошибки (первая с использованием XLS, вторая с использованием CSV):
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 6 bytes) in C:\wamp64\www\test\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Cell\Coordinate.php on line 34
Fatal error: Maximum function nesting level of '256' reached, aborting! in C:\wamp64\www\test\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Reader\Csv.php on line 239
Я пытался дать PHP больше памяти или установить xdebug.max_nesting_level, но скрипт тоже не работает. Как я могу это исправить? Существует ли другая библиотека для чтения из файла электронной таблицы, который использует меньше памяти?
Код, который я написал, просто циклически переходит между первым и третьим столбцами, первый - это категория, третий - это подкатегория, которую я должен связать с категорией в базе данных SQL.
Может быть, код просто не эффективен? Я не понимаю, как PHP может выйти из памяти, используя только файл 157 КБ.
Это код, который я использую:
$inputFileName = 'C:\wamp64\www\test\documents\fileToParse.xls';
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($inputFileName);
$worksheet = $spreadsheet->getActiveSheet();
$highestRow = $worksheet->getHighestRow();
$values = array();
for ($rowCategory = 1; $rowCategory <= $highestRow; $rowCategory++) {
if (!is_null($worksheet->getCellByColumnAndRow(1, $rowCategory))) {
$rowSubCategory = $rowCategory + 1;
for (; is_null($worksheet->getCellByColumnAndRow(1, $rowSubCategory)->getValue()); $rowSubCategory++) {
$idSubCategory = $worksheet->getCellByColumnAndRow(3, $rowSubCategory)->getValue();
if (!is_null($idSubCategory)) {
var_dump($idSubCategory);
array_push($values, $idSubCategory);
}
}
$rowCategory = $rowSubCategory - 1;
}
}
var_dump($values);
Спасибо за помощь!
РЕДАКТИРОВАТЬ:
По запросу это часть CSV (три категории):
A1,Lastre standard,,,,,,,,,
,,HABITO,Habito,,,,,,,
,,,,HFV13300,"HABITO FORTE 13 VAPOR MM 1200X3000X12,5 MQ 3,60",01-Mar-16,MQ,€ 20.84,40,12.504
,,,,HPPV13300,"LASTRA HABITO VAPOR ACTIV AIR SP. 12,5 MM 1200X3000 MQ 3,60",16-Sep-18,MQ,€ 13.50,40,8.1
,,NETTI,Prezzi netti,,,,,,,
,,,,HF13200,"HABITO FORTE 13 MM 1200X2000X12,5 MQ 2,4",01-May-16,MQ,€ 6.20,,6.2
,,,,HF13280,"HABITO FORTE 13 MM 1200X2800X12,5 MQ 3,36",01-May-16,MQ,€ 6.20,,6.2
,,,,HF13300,"HABITO FORTE 13 MM 1200X3000X12,5 MQ 3,60",01-May-16,MQ,€ 6.20,,6.2
,,,,HSBA13200,"HABITO SILENCE ACTIV AIR SP. 12,50+2 MM 1200X2000 MQ 2,40",01-Mar-15,MQ,€ 12.00,,12
,,RB10,Lastre normali sp. 10 mm,,,,,,,
,,,,BA10200,"LASTRA STANDARD RB 10 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 4.44,64,1.5988
,,,,BA10250,"LASTRA STANDARD RB 10 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 4.44,64,1.5988
,,,,BA10300,"LASTRA STANDARD RB 10 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 4.44,64,1.5988
,,,,FBA10200,"LASTRA GYPSOTECH BA 10 MM 1200X2000 MQ 2,40",01-Jun-17,MQ,€ 4.44,64,1.5988
,,,,FBA10300,"LASTRA FASSA GYPSOTECH BA 10 MM 1200X3000 MQ 3,60",01-Jun-17,MQ,€ 4.44,64,1.5988
,,RB13,"Lastre normali sp. 12,5 mm",,,,,,,
,,,,BA13200,"LASTRA STANDARD RB 13 MM 1200x2000 MQ 2,40",01-Nov-13,MQ,€ 4.82,"66,20",1.6275
,,,,BA13250,"LASTRA STANDARD RB 13 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 4.82,"66,20",1.6275
,,,,BA13300,"LASTRA STANDARD RB 13 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 4.82,"66,20",1.6275
,,,,LBA13280PLUS,"LASTRA SINIAT PREGYPLAC STANDARD PLUS BA 13 MM 1200x2800 MQ 3,36",01-Jun-17,MQ,€ 4.82,"66,20",1.6275
,,RB15,Lastre normali RB 15,,,,,,,
,,,,BA15200,"LASTRA RIGIPS RB 15 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 5.70,58,2.3936
,,,,BA15250,"LASTRA RB 15 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 5.70,58,2.3936
,,,,BA15300,"LASTRA RIGIPS RB 15 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 5.70,58,2.3936
,,,,FBA15200,"LASTRA FASSA GYPSOTECH STANDARD BA 15 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 5.70,58,2.3936
,,,,FBA15250,"LASTRA FASSA GYPSOTECH STANDARD BA 15 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 5.70,58,2.3936
,,,,FBA15300,"LASTRA FASSA GYPSOTECH STANDARD BA 15 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 5.70,58,2.3936
,,RB18,Lastre normali sp. 18 mm,,,,,,,
,,,,BA18300,"LASTRA RIGIPS RB 18 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 7.52,40,4.5114
A2,Lastre speciali,,,,,,,,,
,,GKF,Antifuoco Knuaf sp. 13 mm,,,,,,,
,,,,GKF13200,"LASTRA KANUF ANTIFUOCO GKF 13MM DIM. 1200X2000 MQ 2,40",01-Jun-17,MQ,€ 5.96,,5.959
,,,,GKF13300,"LASTRA KNAUF ANTIFUOCO GKF 13MM DIM. 1200X3000 MQ 3,60",01-Jun-17,MQ,€ 5.96,,5.959
,,MQ,Lastre classe M0,,,,,,,
,,,,LBA13300MQ,"LASTRA SINIAT PREGYPLAC M0 BA13 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 17.14,66,5.8273
,,,,LFEU13250MQ,"LASTRA SINIAT PREGYFEU M0 ANTIFUOCO BA 13 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 19.68,66,6.6902
,,,,LFEU25250MQ,"LASTRA SINIAT PREGYFEU M0 ANTIFUOCO BD 25 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 43.29,66,14.7169
,,,,LPPF13250MQ,"LASTRA SINIAT PREGYFLAM M0 ANTIFUOCO BA 13 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 19.68,66,6.6902
,,,,LPPF15250MQ,"LASTRA SINIAT PREGYFLAM M0 ANTIFUOCO BA 15 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 22.21,66,7.5528
,,,,LPPF15300MQ,"LASTRA SINIAT PREGYFEU M0 ANTIFUOCO BA 15 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 26.47,66,8.9991
,,PHD13,Lastre alta densità' PHD BA 13,,,,,,,
,,,,DURAGYP13200,"GYPROC DURAGYP ACTIV'AIR SP. 13 MM 1200X2000 MQ 2,4",01-Jun-17,MQ,€ 3.60,,3.6
,,,,DURAGYP13300,"GYPROC DURAGYP ACTIV'AIR SP. 13 MM 1200X3000 MQ 3,6",01-Jun-17,MQ,€ 3.60,,3.6
,,,,DURAGYPA113300,"GYPROC DURAGYP A1 ACTIV'AIR SP. 13 MM 1200X3000 MQ 3,6",01-Jun-17,MQ,€ 17.22,40,10.3332
,,,,LLADURA13280,"LASTRA PREGYLADURA SP. 12,5 MM 1200X2800 MQ 3,36",01-Jun-17,MQ,€ 14.33,40,8.5986
,,,,LLADURA15280,"LASTRA PREGYLADURA SP. 15 MM 1200X2800 MQ 3,36",01-Jun-17,MQ,€ 16.62,40,9.9714
,,PPF13,"Lastre antincendio sp. 12,5 mm",,,,,,,
,,,,PPF13200,"LASTRA RIGIPS ANTIFUOCO RF 13 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 5.96,58,2.5028
,,,,PPF13250,"LASTRA RIGIPS ANTIFUOCO RF 13 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 5.96,58,2.5028
,,,,PPF13300,"LASTRA RIGIPS ANTIFUOCO RF13 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 5.96,58,2.5028
,,PPF15,Lastre antincendio sp. 15 mm,,,,,,,
,,,,GPPF20200,"LASTRA GYPROC FIRELINE SP. 20 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 9.60,58,4.0316
,,,,PPF15200,"LASTRA RIGIPS ANTIFUOCO RF 15 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 7.10,58,2.9833
,,,,PPF15250,"LASTRA RIGIPS ANTIFUOCO RF 15 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 7.10,58,2.9833
,,,,PPF15300,"LASTRA RIGIPS ANTIFUOCO RF 15 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 7.10,58,2.9833
,,PPV13,Lastre con barriera vapore,,,,,,,
,,,,GPPM13300BV,"LASTRA IDROREPELLENTE 13+BARR. VAPORE 1200X3000 MQ 3,60",01-Jun-17,MQ,€ 11.66,40,6.9948
,,RB13SPE,Lastre Speciali,,,,,,,
,,,,LBA1390180,"LASTRA PREGYKIT BA 13 MM 900x1800 MQ 1,62",01-Jun-17,MQ,€ 5.14,20,4.1104
,,RB6,Lastre x elementi curvi,,,,,,,
,,,,BA6300,"LASTRA PER ELEMENTI CURVI RB6 MM1200x3000 MQ 3,60",01-Jun-17,MQ,€ 9.12,40,5.4726
,,,,BA690300,"LASTRA PER ELEMENTI CURVI RB6 MM 900x3000 MQ 2,70",01-Jan-14,MQ,€ 8.77,40,5.262
,,,,GBA690300,"LASTRA RIGIPS PER ELEMENTI CURVI RB6 MM 900x3000 MQ 2,70",01-Jan-14,MQ,€ 8.77,40,5.262
,,RBI13,Lastre idrorepellenti,,,,,,,
,,,,PPM13200,"LASTRA IDROREPELLENTE RBI13 MM 1200x2000 MQ 2,40",01-Jun-17,MQ,€ 7.64,"66,20",2.5837
,,,,PPM13250,"LASTRA IDROREPELLENTE RBI13 MM 1200x2500 MQ 3,00",01-Jun-17,MQ,€ 7.64,"66,20",2.5837
,,,,PPM13300,"LASTRA IDROREPELLENTE RBI 13 MM 1200x3000 MQ 3,60",01-Jun-17,MQ,€ 7.64,"66,20",2.5837
,,ST,Collanti,,,,,,,
,,,,HABITOPREMIUM5,HABITO PREMIUM SACCO 5 KG,01-Jun-17,SA,€ 5.58,,5.5755
,,UNIP,Lastre fibrocemento,,,,,,,
,,,,VIDIWALL13200,"LASTRA VIDIWALL SP. 12,5 MM 1200X2000 MQ 2,40 4 SK",01-Jun-17,MQ,€ 13.26,30,9.282
,,,,VIDIWALL13300,"LASTRA KNAUF VIDIWALL SP. 12,5 MM 1200X3000 MQ 3,60",01-Jun-17,MQ,€ 13.26,30,9.282
1 ответ
Это довольно понятный фрагмент кода с использованием встроенного в PHP fgetcsv()
функция:
$values = [];
$fh = fopen($inputFileName, "r");
while ($row = fgetcsv($fh)) {
if (!empty($row[0])) {
$cat = $row[0];
} elseif (!empty($row[2])) {
$values[$cat][] = $row[2];
}
}
fclose($fh);
print_r($values);
Выход:
Array
(
[A1] => Array
(
[0] => HABITO
[1] => NETTI
[2] => RB10
[3] => RB13
[4] => RB15
[5] => RB18
)
[A2] => Array
(
[0] => GKF
[1] => MQ
[2] => PHD13
[3] => PPF13
[4] => PPF15
[5] => PPV13
[6] => RB13SPE
[7] => RB6
[8] => RBI13
[9] => ST
[10] => UNIP
)
)