Задачи по обмену данными между 1С и внешними файлами, такими как Excel, являются одними из самых распространенных в практике разработчика. Рассмотрим ситуацию, когда нам необходимо дополнить существующий справочник ФизЛица новыми данными (например, идентификаторами пропусков), хранящимися в стороннем файле. Мы разберем по шагам, как организовать выбор файла, его чтение на сервере и корректную запись информации в базу данных.
Первым делом нам необходимо предоставить пользователю возможность выбрать файл на диске. В современных конфигурациях 1С на управляемых формах рекомендуется использовать асинхронные методы. Проанализируем, как реализовать диалог выбора файла, который вернет нам путь к источнику данных.
Для этого создадим команду и соответствующую процедуру. Важно помнить, что работа с файловой системой происходит на клиенте.
&НаКлиенте
Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Используем современный асинхронный подход для выбора файла
ПараметрыДиалога = Новый ПараметрыДиалогаВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ПараметрыДиалога.Заголовок = "Выберите Excel-файл для загрузки";
ПараметрыДиалога.Фильтр = "Файлы Excel (*.xlsx)|*.xlsx|Все файлы (*.*)|*.*";
ПараметрыДиалога.МножественныйВыбор = Ложь;
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
НачатьВыборФайла(ОписаниеОповещения, ПараметрыДиалога);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено Тогда
Объект.ПутьКФайлу = ВыбранныеФайлы[0];
КонецЕсли;
КонецПроцедуры
В данном коде мы используем ПараметрыДиалогаВыбораФайла и НачатьВыборФайла. Это позволяет избежать блокировки интерфейса и соответствует актуальным стандартам разработки 1С.
Поскольку сама база данных находится на сервере, а файл — на локальном компьютере пользователя, нам нужно передать данные во временное хранилище. Рассмотрим механизм чтения файла без использования COM-объектов (что позволяет обработке работать даже если на сервере не установлен Microsoft Excel).
Выясним, как прочитать данные через ТабличныйДокумент. Этот метод универсален и работает быстрее классического COM-соединения.
&НаСервере
Процедура ЗагрузитьДанныеИзExcelНаСервере(АдресВХ)
// Создаем временный файл на сервере из двоичных данных
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресВХ);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанныеФайла.Записать(ИмяВременногоФайла);
// Используем ТабличныйДокумент для чтения структуры файла
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяВременногоФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
КоличествоСтрок = ТабДок.ВысотаТаблицы;
// Предположим, что в Excel: Колонка 1 - ФИО, Колонка 2 - ТабНомер, Колонка 3 - Идентификатор
Для НомерСтроки = 2 По КоличествоСтрок Цикл // Начинаем со 2-й строки, пропуская заголовок
ТабельныйНомер = СокрЛП(ТабДок.Область(НомерСтроки, 2).Текст);
ИдентификаторПропуска = СокрЛП(ТабДок.Область(НомерСтроки, 3).Текст);
Если ПустаяСтрока(ТабельныйНомер) Тогда
Продолжить;
КонецЕсли;
ОбновитьИдентификаторФизЛица(ТабельныйНомер, ИдентификаторПропуска);
КонецЦикла;
// Удаляем временный файл после обработки
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Важный момент: использование СокрЛП() критично при чтении из Excel, так как в ячейках часто присутствуют невидимые пробелы, которые могут помешать поиску в базе данных 1С.
Теперь проанализируем ситуацию, как найти нужное физическое лицо. В учебном задании поиск удобнее всего производить по реквизиту ТабНомер. Если мы найдем элемент, нам нужно получить его Объект, изменить реквизит и записать изменения.
&НаСервере
Процедура ОбновитьИдентификаторФизЛица(ТабельныйНомер, НовыйИдентификатор)
// Ищем ссылку на элемент справочника по табельному номеру
СсылкаФизЛицо = Справочники.ФизЛица.НайтиПоРеквизиту("ТабНомер", ТабельныйНомер);
Если Не СсылкаФизЛицо.Пустая() Тогда
// Получаем объект для редактирования
ОбъектФизЛицо = СсылкаФизЛицо.ПолучитьОбъект();
// Устанавливаем новое значение реквизита
ОбъектФизЛицо.ИдентификаторПропуска = НовыйИдентификатор;
// Записываем объект в базу данных
Попытка
ОбъектФизЛицо.Записать();
Исключение
Сообщить("Не удалось записать данные для сотрудника с таб. номером " + ТабельныйНомер);
КонецПопытки;
Иначе
Сообщить("Сотрудник с табельным номером " + ТабельныйНомер + " не найден в базе.");
КонецЕсли;
КонецПроцедуры
Если в вашем файле Excel содержатся тысячи строк, поиск методом НайтиПоРеквизиту внутри цикла будет работать медленно, так как 1С будет выполнять отдельное обращение к базе на каждой итерации. Рассмотрим более профессиональный подход — использование запроса с временной таблицей.
Алгоритм будет следующим:
ТаблицуЗначений.Запрос в качестве параметра.ФизЛица.
// Пример структуры запроса для ускорения поиска
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВТ_ДанныеExcel.ТабельныйНомер КАК ТабНомер,
| ВТ_ДанныеExcel.ИдентификаторПропуска КАК НовыйИдентификатор
|ПОМЕСТИТЬ ВТ_Excel
|ИЗ
| &ТаблицаИзExcel КАК ВТ_ДанныеExcel
|;
|
|ВЫБРАТЬ
| ФизЛица.Ссылка КАК Ссылка,
| ВТ_Excel.НовыйИдентификатор КАК НовыйИдентификатор
|ИЗ
| ВТ_Excel КАК ВТ_Excel
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ФизЛица КАК ФизЛица
| ПО ВТ_Excel.ТабНомер = ФизЛица.ТабНомер";
Запрос.УстановитьПараметр("ТаблицаИзExcel", ТЗ_Данные);
РезультатЗапроса = Запрос.Выполнить();
Такой подход считается стандартом "хорошего тона" в разработке 1С, так как он минимизирует количество транзакций и нагрузку на сервер БД.
Стоит отметить, что в типовых конфигурациях (таких как ЗУП или ERP) дополнительные реквизиты часто реализуются через Библиотеку стандартных подсистем (БСП). В этом случае реквизит не является физическим полем в таблице справочника, а хранится в табличной части ДополнительныеРеквизиты.
Если ваше задание подразумевает именно такой механизм, то вместо прямой записи Объект.ИдентификаторПропуска, вам потребуется найти строку в табличной части, где Свойство равно нужному значению из Плана видов характеристик, и обновить поле Значение.
Резюмируем изученное:
НачатьВыборФайла.ПоместитьВоВременноеХранилище.ТабличныйДокумент для независимости от установленного ПО.СокрЛП перед поиском.Объект из ссылки.Следуя этой структуре, вы сможете создать надежную и быструю обработку загрузки данных, которая будет корректно работать в любой среде.