При разработке обработок загрузки данных из внешних файлов (в частности, формата DBF) в документы начисления зарплаты часто возникает ситуация: реквизиты вида расчета и суммы заполняются корректно, а колонка Сотрудник остается пустой или сбрасывается в неопределенное значение. Рассмотрим подробнее основные причины возникновения этой проблемы и разберем практические способы ее решения.
Проанализировав логику работы обработок чтения DBF-файлов и поиска элементов в справочниках 1С, можно выделить три ключевые ошибки:
TABNOM) часто хранится как числовое значение (например, 10004). В справочнике Сотрудники 1С код обычно имеет строковый тип с лидирующими нулями (например, "0000010004") или содержит префиксы организации. Прямой метод НайтиПоКоду(ДБФ.TABNOM) в этом случае возвращает пустую ссылку.Начисления, а ссылка на сотрудника — в новую строку табличной части Удержания.ДБФ.Следующая() внутри одного цикла приводит к пропуску строк файла и некорректному считыванию значений.Если в справочнике сотрудников используется стандартная нумерация с лидирующими нулями, разберем, как привести числовое значение из DBF к строковому формату нужной длины. Для этого применим функцию Формат() и обратимся к метаданным справочника:
ДлинаКода = Метаданные.Справочники.Сотрудники.ДлинаКода;
ТабельныйНомер = Формат(ДБФ.TABNOM, "ЧЦ=" + ДлинаКода + "; ЧВН=; ЧГ=0");
Сотр1 = Справочники.Сотрудники.НайтиПоКоду(ТабельныйНомер);
Если Не Сотр1.Пустая() Тогда
ТекСтрока.Сотрудник = Сотр1;
КонецЕсли;
Параметр ЧВН= отвечает за вывод незначащих нулей, а ЧГ=0 отключает группировку тысяч, что позволяет получить точное соответствие коду 1С.
Вызов метода НайтиПоКоду() на каждой итерации обхода DBF-файла существенно замедляет работу системы. Наиболее эффективным решением является предварительная выборка всех действующих сотрудников запросом, с последующим поиском в памяти по очищенному числовому коду.
Рассмотрим пошагово реализацию этого алгоритма:
Шаг 1. Сформируем запрос и заполним дополнительную колонку с числовым представлением кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сотрудники.Код КАК Код,
| Сотрудники.Ссылка КАК Сотрудник,
| 0 КАК КодЧислом
|ИЗ
| Справочник.Сотрудники КАК Сотрудники
|ГДЕ
| НЕ Сотрудники.ПометкаУдаления
| И НЕ Сотрудники.ВАрхиве";
ТаблицаСотрудников = Запрос.Выполнить().Выгрузить();
// Приводим строковые коды к числу для сопоставления с DBF
Для Каждого СтрокаТЗ Из ТаблицаСотрудников Цикл
Попытка
СтрокаТЗ.КодЧислом = Число(СтрокаТЗ.Код);
Исключение
// Если код содержит буквы или спецсимволы, оставляем 0
СтрокаТЗ.КодЧислом = 0;
КонецПопытки;
КонецЦикла;
Шаг 2. Реализуем цикл чтения DBF и заполнения документа:
ДБФ = Новый XBase;
ДБФ.Кодировка = КодировкаXBase.OEM;
ДБФ.ОткрытьФайл(ПутьКФайлу);
Если Не ДБФ.Открыта() Тогда
Сообщить("Не удалось открыть файл DBF!");
Возврат;
КонецЕсли;
Док = Документы.НачислениеЗарплаты.СоздатьДокумент();
Док.Дата = ТекущаяДата();
ДБФ.Первая();
Пока ДБФ.ВКонце() = 0 Цикл
// Создаем строку в табличной части Начисления
ТекСтрока = Док.Начисления.Добавить();
ТекСтрока.Результат = ДБФ.Summa;
// Ищем сотрудника в ранее подготовленной таблице значений по числовому коду
СтрокаНайдена = ТаблицаСотрудников.Найти(ДБФ.TABNOM, "КодЧислом");
Если СтрокаНайдена <> Неопределено Тогда
ТекСтрока.Сотрудник = СтрокаНайдена.Сотрудник;
КонецЕсли;
ДБФ.Следующая();
КонецЦикла;
Док.Записать();
ДБФ.ЗакрытьФайл();
Выясним еще несколько важных нюансов, которые необходимо учитывать при программном создании документов начисления зарплаты:
Организация, ПериодРегистрации (или МесяцНачисления) и Подразделение. Без них при проведении документа возникнут ошибки записи движений.Сотрудник заполняется в той же строке табличной части, куда записывается вид расчета и сумма начисления.ДБФ.ЗакрытьФайл() по завершении загрузки, чтобы избежать блокировки файла на сервере.