Как при загрузке из DBF создать один документ в 1С и правильно заполнить его табличную часть?

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При импорте сведений из сторонних баз данных (например, файлов формата DBF, созданных в FoxPro) часто возникает ситуация, когда вместо одного итогового документа в 1С создается множество однотипных документов. Каждая строка исходного файла приводит к генерации нового объекта в системе. Разберем, как правильно переписать алгоритм обхода DBF-файла, вынести инициализацию документа за пределы цикла и корректно обработать специфические типы данных.

Причина создания лишних документов и ошибки в структуре цикла

Проанализируем типовую ошибку в логике программного кода. Если вызов метода СоздатьДокумент() и управление транзакциями (НачатьТранзакцию(), ЗафиксироватьТранзакцию()) находятся внутри основного цикла обхода строк DBF (Пока ДБФ.ВКонце = 0 Цикл), система при каждом шаге итерации формирует новую ссылку на документ и записывает её в базу данных.

Дополнительно ситуацию усугубляет фиксация транзакции по счетчику Сч % 1 = 0 внутри итератора. Это разбивает обработку одного объекта на разные транзакции базы данных, приводит к конфликту версий объекта и плодит дубли документов.

Исправление структуры кода для создания единого документа

Чтобы все строки из файла DBF попали в табличную часть одного и того же документа, рассмотрим пошаговый порядок действий:

  1. Объявляем флаг состояния документа (например, ДокументСоздан = Ложь) или инициализируем объект документа до начала основного цикла.
  2. Внутри цикла обхода файла проверяем условие: если документ ещё не создан, вызываем метод СоздатьДокумент() и устанавливаем флаг в значение Истина.
  3. На каждом шаге цикла добавляем новую строку в табличную часть Начисления созданного объекта.
  4. Записываем документ вызовом Док.Записать() только после завершения чтения всех строк из файла.
  5. Управление транзакцией (НачатьТранзакцию() и ЗафиксироватьТранзакцию()) выносим за пределы цикла или оборачиваем им весь процесс целиком.

Посмотрим на пример правильной организации структуры кода:


Док = Неопределено;
ДокументСоздан = Ложь;

ДБФ.Первая();

Попытка
    НачатьТранзакцию();
    
    Пока ДБФ.ВКонце() = 0 Цикл
        
        Если Не ДокументСоздан Тогда
            Док = Документы.НачислениеЗарплатыРаботникамОрганизаций.СоздатьДокумент();
            Док.Дата = ТекущаяДата();
            Док.ПериодНачисленияДатаОкончания = ДБФ.Dat_End;
            ДокументСоздан = Истина;
        КонецЕсли;
        
        // Определение вида расчета по шифру
        ВидОплаты = ДБФ.Shifr;
        Расчет1 = ПланыВидовРасчета.ОсновныеНачисленияОрганизаций.ПустаяСсылка();
        
        Если ВидОплаты = "001" Тогда
            Расчет1 = ПланыВидовРасчета.ОсновныеНачисленияОрганизаций.НайтиПоНаименованию("Сдельные наряды(суммой)");
        ИначеЕсли ВидОплаты = "005" Тогда
            Расчет1 = ПланыВидовРасчета.ОсновныеНачисленияОрганизаций.НайтиПоНаименованию("Сверхурочные(суммой)");
        КонецЕсли;
        
        // Добавление строки в табличную часть документа
        ТекСтрока = Док.Начисления.Добавить();
        ТекСтрока.ВидРасчета = Расчет1;
        
        Сотр1 = Справочники.СотрудникиОрганизаций.НайтиПоКоду(ДБФ.TabNom);
        Если Не Сотр1.Пустая() Тогда
            ТекСтрока.Сотрудник = Сотр1;
        КонецЕсли;
        
        ТекСтрока.Результат = ДБФ.Summa;
        ТекСтрока.ДатаНачала = ДБФ.Dat_Beg;
        ТекСтрока.ДатаНачалаСобытия = ДБФ.Dat_Beg;
        ТекСтрока.ДатаОкончания = ДБФ.Dat_End;
        
        ДБФ.Следующая();
    КонецЦикла;
    
    Если ДокументСоздан Тогда
        Док.Записать();
    КонецЕсли;
    
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    Сообщить(ОписаниеОшибки());
КонецПопытки;

Почему не записываются даты и другие реквизиты из DBF?

Выясним причину второй частой проблемы, когда при загрузке из сторонней базы данных (например, FoxPro 2.6) поля ДатаНачала или ДатаОкончания остаются пустыми в табличной части 1С.

Объект XBase в 1С привязан к структуре типов, описанной в заголовке файла DBF. Существует несколько причин несоответствия данных:

  1. Тип поля в DBF — строка (Character), а не дата (Date): В системах FoxPro даты часто хранятся как строки формата "YYYYMMDD" или "DD.MM.YYYY". При попытке записать значение типа Строка в реквизит табличной части с типом Дата, платформа 1С не вызывает ошибку, но записывает пустую дату (01.01.0001 00:00:00).
  2. Использование специализированных утилит для проверки структуры: Чтобы проверить типы полей исходного файла, рекомендуется открыть его через сторонний просмотрщик (например, DBF Viewer 2000) и изучить структуру колонок.
  3. Пустые значения в формате FoxPro: Пустая дата в DBF часто представляет собой строку из 8 пробелов.

Рассмотрим, как правильно преобразовать строковую дату из DBF в полноценный тип Дата перед заполнением реквизита 1С:


// Если дата в DBF хранится в текстовом виде "YYYYMMDD"
ЗначениеДаты = Строка(ДБФ.Dat_Beg);
Если СтрДлина(СокрЛП(ЗначениеДаты)) = 8 Тогда
    Год   = Число(Лев(ЗначениеДаты, 4));
    Месяц = Число(Сред(ЗначениеДаты, 5, 2));
    День  = Число(Прав(ЗначениеДаты, 2));
    ТекСтрока.ДатаНачала = Дата(Год, Месяц, День);
Иначе
    ТекСтрока.ДатаНачала = ДБФ.Dat_Beg; // Если тип поля в DBF изначально Date
КонецЕсли;

Таким образом, правильное проектирование цикла обхода файлов XBase и предварительная проверка типов данных через просмотрщик структуры гарантируют корректное создание единого документа и полное заполнение его табличной части.

← На главную