Розробка функціоналу завантаження замовлення з Excel 1С-Бітрікс
Оптові покупці працюють зі своїми прайс-листами і специфікаціями в Excel. Вони хочуть взяти готову таблицю «артикул — кількість», завантажити її на сайт і одразу отримати кошик. Без цього функціоналу менеджер витрачає годину на ручне введення, робить помилки, і клієнт іде до конкурента з зручнішим сайтом. Стандартний 1С-Бітрікс не вміє читати Excel — потрібна кастомна реалізація.
Парсинг Excel на сервері
Для читання .xlsx файлів без встановлення MS Office використовується бібліотека PhpSpreadsheet (наступник PHPExcel). Підключається через Composer:
composer require phpoffice/phpspreadsheet
AJAX-контролер обробки файлу:
public function uploadAction(): array
{
$file = $_FILES['excel_file'];
if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
return ['status' => 'error', 'message' => 'Файл не завантажено'];
}
$allowedMimes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel',
];
if (!in_array($file['type'], $allowedMimes)) {
return ['status' => 'error', 'message' => 'Невірний формат файлу'];
}
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createAutomatic(
\PhpOffice\PhpSpreadsheet\IOFactory::identify($file['tmp_name'])
);
$spreadsheet = $reader->load($file['tmp_name']);
$sheet = $spreadsheet->getActiveSheet();
$rows = $sheet->toArray();
return $this->processRows($rows);
}
Логіка розбору рядків
Формат файлу клієнта непередбачуваний: шапка може бути в першому або другому рядку, колонки — в будь-якому порядку. Реалізуємо детектор заголовків:
private function processRows(array $rows): array
{
// Шукаємо рядок-заголовок за ключовими словами
$headerRow = null;
$articleCol = null;
$quantityCol = null;
foreach ($rows as $i => $row) {
foreach ($row as $j => $cell) {
$cell = mb_strtolower(trim((string)$cell));
if (in_array($cell, ['артикул', 'арт', 'article', 'sku', 'код'])) {
$articleCol = $j;
$headerRow = $i;
}
if (in_array($cell, ['количество', 'кол-во', 'qty', 'quantity', 'кол'])) {
$quantityCol = $j;
}
}
if ($headerRow !== null) break;
}
// Якщо заголовок не знайдено — припускаємо: колонка 0 = артикул, колонка 1 = кількість
$articleCol = $articleCol ?? 0;
$quantityCol = $quantityCol ?? 1;
$dataStart = ($headerRow ?? -1) + 1;
$items = [];
for ($i = $dataStart; $i < count($rows); $i++) {
$article = trim((string)($rows[$i][$articleCol] ?? ''));
$qty = (float)str_replace(',', '.', $rows[$i][$quantityCol] ?? 1);
if ($article !== '') {
$items[] = ['article' => $article, 'quantity' => max(1, $qty)];
}
}
return $this->resolveArticles($items);
}
Резолвінг артикулів
Після парсингу отримуємо масив артикулів. Резолвимо їх пакетним SQL-запитом — швидше, ніж N окремих запитів:
private function resolveArticles(array $items): array
{
$articles = array_column($items, 'article');
// Шукаємо у властивостях торгових пропозицій
$placeholders = implode(',', array_fill(0, count($articles), '?'));
$rs = $connection->query(
"SELECT ie.ID, iep.VALUE AS ARTICLE, ie.IBLOCK_ELEMENT_ID AS PRODUCT_ID
FROM b_iblock_element ie
JOIN b_iblock_element_property iep ON iep.IBLOCK_ELEMENT_ID = ie.ID
WHERE iep.IBLOCK_PROPERTY_ID = ? AND iep.VALUE IN ($placeholders)",
array_merge([$articlePropertyId], $articles)
);
// ...
}
Превью перед додаванням до кошика
Після завантаження файлу користувач бачить таблицю з результатами:
| Артикул з файлу | Знайдений товар | К-ть | Ціна | Статус |
|---|---|---|---|---|
| ABC-123 | Болт М8×20 | 100 | 2.50 грн | Знайдено |
| XYZ-999 | — | 5 | — | Не знайдено |
| DEF-456 | Гайка М8 | 50 | 1.20 грн | Немає на складі |
Клієнт може скоригувати кількість, прибрати не знайдені позиції і натиснути «Додати до кошика». Додавання — те саме пакетне \Bitrix\Sale\Basket зі сценарію швидкого замовлення.
Шаблон для завантаження
На сторінці завантаження розміщуємо посилання на завантаження шаблону Excel — файл з правильними заголовками колонок. Генерується через PhpSpreadsheet або зберігається як статичний файл у /upload/templates/order_template.xlsx.
Кейс: дистриб'ютор будівельних матеріалів
Ситуація: 300+ корпоративних клієнтів, кожен зі своєю таблицею замовлення, менеджери витрачали 2–3 години на день на введення позицій вручну.
Реалізація:
- Детектор формату: розпізнає 7 варіантів шапок (артикул, код, SKU, арт та ін.)
- Підтримка
.xlsxі.xls(через PhpSpreadsheet) - Обмеження: максимум 1 000 рядків за завантаження, файл до 5 МБ
- Превью з можливістю редагування кількості
- Автоматичне зіставлення за
XML_ID, якщо артикул не знайдено у властивості
Результат: менеджери звільнили 2+ години на день, клієнти розміщують замовлення самостійно.
| Етап | Термін |
|---|---|
| Налаштування PhpSpreadsheet, завантаження файлу | 1 день |
| Парсер з детектором заголовків | 2 дні |
| Резолвінг артикулів, пакетний запит | 1 день |
| Превью-таблиця з редагуванням | 2 дні |
| Пакетне додавання до кошика | 1 день |
| Тестування на реальних файлах клієнтів | 1 день |
Що входить у розробку
- Завантажувач файлів
.xlsx/.xlsз валідацією формату - Парсер з автовизначенням заголовків і позицій колонок
- Пакетний резолвінг артикулів за
b_iblock_element_property - Превью результатів з можливістю коригування перед додаванням до кошика
- Пакетне додавання знайдених товарів до кошика
\Bitrix\Sale\Basket - Шаблон Excel для завантаження







