← Назад к вопросам
Обработка загрузки остатков из Excel
2.0 Middle🔥 151 комментариев
#Интеграции и обмены#Стандарты разработки
Условие
Создайте обработку загрузки начальных остатков из Excel-файла.
Структура Excel-файла:
| Номенклатура | Склад | Количество |
|---|---|---|
| Товар 1 | Осн. | 100 |
| Товар 2 | Осн. | 50 |
Требования:
- Выбор файла через диалог
- Проверка существования номенклатуры и склада
- Создание документа ввода начальных остатков
- Вывод протокола загрузки (успешно/ошибки)
Обработка ошибок
- Если номенклатура не найдена — записать в протокол
- Если склад не найден — записать в протокол
- После загрузки показать итоги: загружено X строк, ошибок Y
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Обработка загрузки начальных остатков из Excel
Рассмотрим реализацию обработки для импорта начальных остатков товаров из Excel-файла с валидацией данных.
Архитектура решения
Основные этапы:
- Выбор файла Excel пользователем
- Чтение и парсирование данных из файла
- Валидация (проверка существования номенклатуры и складов)
- Создание документа "ВводОстатков" или "ПриходТоваров"
- Логирование результатов загрузки
Структура Excel-файла
Требуемая структура:
Строка 1 (заголовок): Номенклатура | Склад | Количество | Цена (опционально)
Данные:
- Товар 1 | Основной | 100 | 500
- Товар 2 | Филиал | 50 | 1000
Реализация обработки
Форма обработки (управляемая форма):
// Процедура инициализации формы
Процедура ПриОткрытии(Отмена)
// Инициализация таблицы результатов
Протокол = ЭтаФорма.ОбъектДанных.Протокол;
Протокол.Очистить();
// Установка параметров по умолчанию
ЭтаФорма.ОбъектДанных.СтатусЗагрузки = "Ожидание файла";
КонецПроцедуры
// Команда выбора файла
Процедура ВыбратьФайл(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.ПолноеИмяФайла = "";
Диалог.Filter = "Excel файлы (*.xlsx; *.xls)|*.xlsx;*.xls";
Диалог.Заголовок = "Выбор файла с остатками";
Если Диалог.Выбрать() Тогда
ПолныйПутьФайла = Диалог.ПолноеИмяФайла;
ОбработатьФайл(ПолныйПутьФайла);
КонецЕсли;
КонецПроцедуры
// Основная процедура обработки файла
Процедура ОбработатьФайл(ПолныйПутьФайла)
Попытка
// Проверка существования файла
Если НЕ Новый Файл(ПолныйПутьФайла).Существует() Тогда
ВызватьОшибку("Файл не найден: " + ПолныйПутьФайла);
КонецЕсли;
// Считываем Excel файл
ЭксельТаблица = ПрочитатьExcel(ПолныйПутьФайла);
// Валидируем и создаём документ
РезультатЗагрузки = ВалидироватьИЗагрузить(ЭксельТаблица);
// Выводим итоги
ВывестиИтоги(РезультатЗагрузки);
Исключение
Сообщение("Ошибка при загрузке файла: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Чтение Excel файла
// Функция для чтения Excel-файла
Функция ПрочитатьExcel(ПолныйПутьФайла)
// Используем OLE Automation для Excel
Excel = Новый COMОбъект("Excel.Application");
Excel.Visible = Ложь;
ТаблицаДанных = Новый ТаблицаЗначений();
Попытка
// Открываем рабочую книгу
Книга = Excel.Workbooks.Open(ПолныйПутьФайла, Ложь, Истина);
Лист = Книга.Worksheets(1);
// Читаем заголовки из первой строки
ЧислоСтолбцов = 3; // Номенклатура, Склад, Количество
ТаблицаДанных.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
ТаблицаДанных.Колонки.Добавить("Склад", Новый ОписаниеТипов("Строка"));
ТаблицаДанных.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
ТаблицаДанных.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
// Читаем данные со второй строки (пропускаем заголовок)
НомерСтроки = 2;
Пока ЗначениеЗаполнено(Лист.Cells(НомерСтроки, 1).Value) Цикл
НоваяСтрока = ТаблицаДанных.Добавить();
НоваяСтрока.Номенклатура = Лист.Cells(НомерСтроки, 1).Value;
НоваяСтрока.Склад = Лист.Cells(НомерСтроки, 2).Value;
НоваяСтрока.Количество = Число(Лист.Cells(НомерСтроки, 3).Value);
// Цена опциональна (может быть в 4-м столбце)
ЗначениеЦены = Лист.Cells(НомерСтроки, 4).Value;
Если ЗначениеЗаполнено(ЗначениеЦены) Тогда
НоваяСтрока.Цена = Число(ЗначениеЦены);
КонецЕсли;
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
Книга.Close(Ложь);
Исключение
ВызватьОшибку("Ошибка при чтении Excel: " + ОписаниеОшибки());
Наконец
Excel.Quit();
КонецПопытки;
Возврат ТаблицаДанных;
КонецФункции
Валидация и загрузка
// Функция для валидации и загрузки данных
Функция ВалидироватьИЗагрузить(ТаблицаDанных)
РезультатЗагрузки = Новый Структура();
РезультатЗагрузки.Вставить("ВсегоСтрок", ТаблицаDанных.Количество());
РезультатЗагрузки.Вставить("УспешноЗагружено", 0);
РезультатЗагрузки.Вставить("Ошибок", 0);
РезультатЗагрузки.Вставить("Протокол", Новый ТаблицаЗначений());
// Инициализируем протокол ошибок
Протокол = РезультатЗагрузки.Протокол;
Протокол.Колонки.Добавить("СтрокаФайла", Новый ОписаниеТипов("Число"));
Протокол.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
Протокол.Колонки.Добавить("Статус", Новый ОписаниеТипов("Строка"));
Протокол.Колонки.Добавить("Описание", Новый ОписаниеТипов("Строка"));
// Создаём документ-заголовок
Документ = Documents.ПриходТоваров.CreateDocument();
Документ.Дата = ТекущаяДата();
Документ.Организация = ПолучитьОрганизацию();
// Проходим по каждой строке
НомерСтроки = 2; // Нумерация начинается с 2 (в Excel с учётом заголовка)
Для Каждого СтрокаДанных Из ТаблицаDанных Цикл
ОшибкиСтроки = ПроверитьСтрок(СтрокаДанных, НомерСтроки);
Если ОшибкиСтроки.Количество() = 0 Тогда
// Стрка валидна — добавляем в документ
НоваяСтрока = Документ.Товары.Добавить();
НоваяСтрока.Номенклатура = НайтиНоменклатуру(СтрокаДанных.Номенклатура);
НоваяСтрока.Склад = НайтиСклад(СтрокаДанных.Склад);
НоваяСтрока.Количество = СтрокаДанных.Количество;
НоваяСтрока.Цена = ?(ЗначениеЗаполнено(СтрокаДанных.Цена), СтрокаДанных.Цена, 0);
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
РезультатЗагрузки.УспешноЗагружено = РезультатЗагрузки.УспешноЗагружено + 1;
Иначе
// Есть ошибки — записываем в протокол
Для Каждого Ошибка Из ОшибкиСтроки Цикл
СтрокаПротокола = Протокол.Добавить();
СтрокаПротокола.СтрокаФайла = НомерСтроки;
СтрокаПротокола.Номенклатура = СтрокаДанных.Номенклатура;
СтрокаПротокола.Статус = "Ошибка";
СтрокаПротокола.Описание = Ошибка;
КонецЦикла;
РезультатЗагрузки.Ошибок = РезультатЗагрузки.Ошибок + 1;
КонецЕсли;
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
// Сохраняем документ
Если РезультатЗагрузки.УспешноЗагружено > 0 Тогда
Документ.Записать(РежимЗаписиДокумента.Проведение);
РезультатЗагрузки.Вставить("НомерДокумента", Документ.Номер);
КонецЕсли;
Возврат РезультатЗагрузки;
КонецФункции
Проверка строки
// Функция для проверки одной строки данных
Функция ПроверитьСтрок(СтрокаДанных, НомерСтроки)
Ошибки = Новый Массив();
// Проверка номенклатуры
Если НЕ ЗначениеЗаполнено(СтрокаДанных.Номенклатура) Тогда
Ошибки.Добавить("Номенклатура не указана");
Иначе
Номенклатура = НайтиНоменклатуру(СтрокаДанных.Номенклатура);
Если НЕ ЗначениеЗаполнено(Номенклатура) Тогда
Ошибки.Добавить("Номенклатура не найдена: " + СтрокаДанных.Номенклатура);
КонецЕсли;
КонецЕсли;
// Проверка склада
Если НЕ ЗначениеЗаполнено(СтрокаДанных.Склад) Тогда
Ошибки.Добавить("Склад не указан");
Иначе
Склад = НайтиСклад(СтрокаДанных.Склад);
Если НЕ ЗначениеЗаполнено(Склад) Тогда
Ошибки.Добавить("Склад не найден: " + СтрокаДанных.Склад);
КонецЕсли;
КонецЕсли;
// Проверка количества
Если СтрокаДанных.Количество <= 0 Тогда
Ошибки.Добавить("Количество должно быть больше нуля");
КонецЕсли;
Возврат Ошибки;
КонецФункции
// Поиск номенклатуры по наименованию
Функция НайтиНоменклатуру(Наименование)
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование = @Наименование
| И Номенклатура.ПометкаУдаления = Ложь";
Запрос.УстановитьПараметр("Наименование", Наименование);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
// Поиск склада по наименованию
Функция НайтиСклад(Наименование)
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| Склады.Ссылка
|ИЗ
| Справочник.Склады КАК Склады
|ГДЕ
| Склады.Наименование = @Наименование
| И Склады.ПометкаУдаления = Ложь";
Запрос.УстановитьПараметр("Наименование", Наименование);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Вывод итогов
// Процедура вывода результатов загрузки
Процедура ВывестиИтоги(РезультатЗагрузки)
ТекстИтогов = "";
ТекстИтогов = ТекстИтогов + "ИТОГИ ЗАГРУЗКИ ОСТАТКОВ" + Символы.ПС + Символы.ПС;
ТекстИтогов = ТекстИтогов + "Всего строк: " + РезультатЗагрузки.ВсегоСтрок + Символы.ПС;
ТекстИтогов = ТекстИтогов + "Успешно загружено: " + РезультатЗагрузки.УспешноЗагружено + Символы.ПС;
ТекстИтогов = ТекстИтогов + "Ошибок: " + РезультатЗагрузки.Ошибок + Символы.ПС + Символы.ПС;
Если РезультатЗагрузки.УспешноЗагружено > 0 Тогда
ТекстИтогов = ТекстИтогов + "Документ создан: " + РезультатЗагрузки.НомерДокумента + Символы.ПС;
КонецЕсли;
Если РезультатЗагрузки.Ошибок > 0 Тогда
ТекстИтогов = ТекстИтогов + Символы.ПС + "ОШИБКИ:" + Символы.ПС;
Для Каждого СтрокаОшибки Из РезультатЗагрузки.Протокол Цикл
ТекстИтогов = ТекстИтогов + "Строка " + СтрокаОшибки.СтрокаФайла + ": " + СтрокаОшибки.Описание + Символы.ПС;
КонецЦикла;
КонецЕсли;
// Выводим информацию в форму
ЭтаФорма.ОбъектДанных.ТекстРезультата = ТекстИтогов;
ЭтаФорма.ОбъектДанных.СтатусЗагрузки = "Загрузка завершена";
КонецПроцедуры
Ключевые особенности реализации
1. Использование OLE Automation:
- Позволяет читать Excel с сохранением форматирования
- Работает с .xlsx и .xls форматами
2. Валидация данных:
- Проверка существования справочников
- Проверка заполненности обязательных полей
- Собираются все ошибки перед сохранением
3. Эффективность:
- Документ создаётся один раз
- Все строки добавляются в оперативную память
- Логирование проводится в таблице формы
4. Пользовательский опыт:
- Подробный протокол ошибок
- Четкие итоги загрузки
- Понятные сообщения об ошибках
Эта реализация обеспечивает надёжный и удобный импорт начальных остатков из Excel-файла с полной валидацией и отчётностью.