PHPExcel. Как записать содержимое xls файла в таблицу SQL

В рамках данной заметки рассматривается вариант решения такой прикладной задачи, как запись в таблицу базы данных сайта содержимого excel-файла. Данный процесс будет осуществлен с помощью библиотеки phpexcel.

Что потребуется для успешного выполнения задачи:

  1. Сервер с поддержкой php
  2. База данных MYSQL
  3. Установленная библиотека phpexcel (устанавливается, к примеру, в корень сайта)
  4. ФТП-клиент
  5. Текстовый редактор (например, Notepad++)
  6. Excel-файл, содержимое которого нужно записать в базу данных.

В рамках данного учебного примера вся работа будет происходить в одном файле. Тестовый excel-файл далее будет обозначаться под именем «test.xls».

Шаг первый. Подключение библиотеки к файлу.

В файле, созданном специально под эту задачу, example.php следует записать следующие строки:

<?php
header( 'Content-Type: text/html; charset=utf-8' );
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
require_once 'PHPExcel-1.8/Classes/PHPExcel.php';

Первые строки объявляют кодировку страницы и параметры отображения ошибок (полезная вещь при решении сложных задач). Последняя строка же, как раз подключает библиотеку PHPExcel к нашему файлу. Естественно, следует указывать реальный путь к файлу (в зависимости от того, где была размещена библиотека). Собственно, после этого шага библиотека «активирована» и можно пользоваться функциями, которые содержатся в ней.

Шаг второй. Создание таблицы базы данных.

Далее следует создать подключение к базе данных и таблицу, в которую мы будем записывать excel-файла.

Создание подключения производится следующим образом:

//Параметры подключения
$hostname = 'hostname';
$username = 'username';
$passwordname = 'passwordname';
$basename = 'basename';
// Открываем соединение с базой данных
$conn = new mysqli($hostname, $username, $passwordname, $basename) or die ('Невозможно открыть базу');
//Устанавливаем кодировку
$query = "SET NAMES 'utf8'";   
if (mysqli_query($conn,$query) === TRUE) {}

Далее создаем таблицу. Количество столбцов в данном примере будет три (Предположим, что в тестовом excel-файле три колонки, которые нужно записать в БД).

Создание таблицы происходит следующим образом:

   $sql_1 = "DROP TABLE IF EXISTS testNew";
   $result_1 = $conn->query($sql_1) or die("ERR_1 " . mysqli_error($conn)); 
   $sql_2 = "CREATE TABLE testNew(
   A_MPN varchar(64) NULL DEFAULT NULL,
   A_NAME varchar(255) NULL DEFAULT NULL,
   A_PRICE decimal(15,4) NULL DEFAULT NULL,
   PRIMARY KEY (A_MPN)
   )  ENGINE=MyISAM  DEFAULT CHARSET=utf8";
   $result_2 = $conn->query($sql_2) or die("ERR_Main_tbl " . mysqli_error($conn));
   if($result_2){};

Подготовительные работы закончены, переходим к выполнению задачи.

Шаг третий. Чтение ячеек.

Первым делом нужно подгрузить необходимый excel-файл в данный скрипт. Делается это так:

$pExcel = PHPExcel_IOFactory::load('test.xls');

Далее, если в файле несколько листов с одинаковыми данными, которые различаются по какому-либо несущественному в данной ситуации параметру (например этот файл содержит список товаров и на каждом листе представлена отдельная категория) — то нужно предварительно посчитать количество строк на каждом листе. Это можно сделать следующим образом:

// Цикл по листам Excel-файла
$i = 0;
foreach ($pExcel->getWorksheetIterator() as $worksheet) {
    // выгружаем данные из объекта в массив
    $tables[] = $worksheet->toArray();
    $i++;
}

$countRow = 0;
foreach( $tables as $table ) {
    foreach($table as $row) {
        $countRow++;
    } 
}

Следующим шагом является, собственно, чтение содержимого файла. Сначала приводится код, потом даются небольшие комментарии относительно того, что он делает.

$countProd=0;
while ($countProd<$i){
  // Данные начинаются с одиннадцатой строки
  $row = 11;
  //Для артикула
  $col3 = 3;
  //Для имени
  $col5 = 5;
  //Для цены
  $col11 = 11;
  
        $pExcel->setActiveSheetIndex($countProd);
	$aSheet = $pExcel->getActiveSheet();
	for ($row; $row <= $countRow; $row ++){
          $cell3 = $aSheet->getCellByColumnAndRow($col3, $row);
          $cell5 = $aSheet->getCellByColumnAndRow($col5, $row);
          $cell11 = $aSheet->getCellByColumnAndRow($col11, $row);

          $value3 = $cell3->getValue();
          $value5 = $cell5->getValue();
          $value11 = $cell11->getValue();
        }
$countProd++;
}

Что происходит? Первым делом, запускается цикл по листам. Известно, что данные начинаются с 11-й строки, следовательно значение переменной row едино для всех столбцов. Далее объявляются переменные с «координатами» нужной колонки, в нашем случае это третья, пятая и одиннадцатая.

Далее устанавливается активный лист, соответствующий значению переменной $countProd на данном этапе цикла (т.е., изначально, он равен 0). На следующей строке переменной $aSheet передается значение активного листа.

Цикл for запускает «обход» строк excel-файла. Циклу уже известно, что количество строк не может быть больше, чем значение переменной $countRow. Далее, с помощью метода getCellByColumnAndRow скрипт получает значение ячейки по координатам (столбец и строка) и записывает его в переменную. Далее, с помощью метода $getValue() происходит запись в переменную $value, которая будет участвовать в записи значений в БД.

Шаг четвертый. Запись содержимого.

Строго после объявления последней переменной $value должен следовать SQL запрос на запись. В рамках данного примера он будет выглядеть следующим образом:

$sql_1 = "INSERT INTO testNew( A_MPN, A_NAME, A_PRICE ) VALUES('$value3','$value5','$value11')";
	 $result_1 = $conn->query($sql_1) or die("<br>ERR_ARTICLE " . mysqli_error($conn));

Тут, думаю, всё очевидно — происходит запись текущих значений $value в БД. На вопрос «Почему это делается в общем цикле, а не происходит предварительной записи в массив?» — можно ответить так: «В рамках учебного примера это несущественно. И (!) как ни странно, данный способ реализации выигрывает в производительности на слабой машине и относительно крупном (ок. 20т строк) файле.

Шаг пятый. Последние штрихи.

В заключение, нужно сделать еще две небольшие вещи.

Во-первых, нужно почистить таблицу от пустых строк (если таковые имеются). Например так:

$sql_1 = "DELETE FROM testNew WHERE A_MPN = ''";
$result_1 = $conn->query($sql_1) or die("<br>ERR_FIN " . mysqli_error($conn));

И, во-вторых, закрыть соединение с базой:

mysqli_close($conn);

Эти строки размещаются после закрывающей скобки цикла while, что обходит листы файла для чтения данных.

На этом всё, на выходе мы имеем таблицу БД с записанными туда данными из excel-файла, которой теперь можно «манипулировать» как угодно: Записывать ли данные из данной таблицы в «рабочие» таблицы CMS, либо использовать для каких-либо других целей.