При автоматизации обмена данными часто возникает задача импорта информации из внешних файлов формата DBF в систему 1С:Предприятие 7.7. Типичная ситуация: в файле содержится список операций, где несколько строк относятся к одному и тому же документу (например, разные услуги в одной накладной). Если просто перебирать строки в цикле и на каждой итерации вызывать метод Новый(), система создаст множество отдельных документов вместо одного многострочного.
В этой статье мы разберем, как правильно построить алгоритм загрузки, чтобы сгруппировать строки по номеру документа, а также рассмотрим важные технические нюансы, которые обеспечат надежность и скорость работы вашей обработки.
Проанализируем типичную ошибку начинающих разработчиков. Когда мы пишем цикл Пока Файл.ВКонце() = 0, внутри которого сразу стоит создание документа, мы получаем ровно столько документов, сколько строк в файле. Чтобы этого избежать, нам необходимо реализовать механизм отслеживания «смены ключа» (в данном случае — номера документа).
Рассмотрим правильный алгоритм действий:
Посмотрим на пример кода, который реализует эту логику:
Перем ТекНомерДок;
ТекНомерДок = "";
ДБ = СоздатьОбъект("XBase");
ДБ.ОткрытьФайл(ПутьКФайлу);
ДБ.Первая();
Пока ДБ.ВКонце() = 0 Цикл
// Проверяем, изменился ли номер документа в файле
Если СокрЛП(ДБ.Номер) <> ТекНомерДок Тогда
// Если это не первая итерация, записываем предыдущий созданный документ
Если ТекНомерДок <> "" Тогда
Док.Записать();
КонецЕсли;
// Создаем новый документ
Док = СоздатьОбъект("Документ.Реализация");
Док.Новый();
Док.НомерДок = СокрЛП(ДБ.Номер);
ТекНомерДок = СокрЛП(ДБ.Номер);
КонецЕсли;
// В любом случае добавляем строку в текущий (только что созданный или уже открытый) документ
Док.НоваяСтрока();
Док.Услуга = ДБ.Инфо; // Здесь должна быть логика поиска элемента справочника
ДБ.Следующая();
КонецЦикла;
// Важно: записываем самый последний документ, так как цикл закончился
Если ТекНомерДок <> "" Тогда
Док.Записать();
КонецЕсли;
ДБ.ЗакрытьФайл();
Проанализируем критическое условие работы вышеуказанного кода: данный алгоритм будет работать корректно только в том случае, если строки в DBF-файле отсортированы по номеру документа. Если данные в файле перемешаны (например: сначала идет строка документа №1, потом №2, а затем снова №1), программа создаст два разных документа с номером №1.
Чтобы исключить эту проблему, мы рекомендуем использовать индексацию внутри 1С. Выясним, как это сделать программно:
ДБ = СоздатьОбъект("XBase");
ДБ.ОткрытьФайл(ПутьКФайлу);
// Создаем временный индекс по полю номера документа (ND)
ДБ.СоздатьИндексныйФайл("temp.cdx");
ДБ.ДобавитьИндекс("IDX_NUM", "ND", 0, 0, "");
ДБ.ТекущийИндекс("IDX_NUM");
// Теперь строки будут читаться строго по порядку номеров
В DBF-файлах информация обычно хранится в виде строк или чисел (названия товаров, коды контрагентов). В документе 1С 7.7 в реквизитах табличной части должны храниться ссылки на объекты справочников. Рассмотрим, как правильно организовать поиск:
При заполнении строки документа обязательно используйте методы НайтиПоНаименованию() или НайтиПоКоду(). Также следует предусмотреть обработку ситуации, когда элемент не найден в базе данных.
СпрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
// ... внутри цикла загрузки строк ...
Если СпрНоменклатура.НайтиПоНаименованию(СокрЛП(ДБ.Услуга), 0, 1) = 1 Тогда
Док.Номенклатура = СпрНоменклатура.ТекущийЭлемент();
Иначе
Сообщить("Внимание: Услуга " + ДБ.Услуга + " не найдена в справочнике!");
КонецЕсли;
Запись каждого документа в 1С 7.7 — это операция, требующая обращения к базе данных и блокировки таблиц. Если в вашем DBF-файле содержатся тысячи строк, загрузка может затянуться на длительное время. Разберем, как ускорить этот процесс с помощью транзакций.
Использование методов НачатьТранзакцию() и ЗафиксироватьТранзакцию() позволяет объединить запись всех созданных документов в одну операцию на уровне СУБД, что ускоряет процесс в несколько раз.
НачатьТранзакцию();
Пока ДБ.ВКонце() = 0 Цикл
// Логика создания и заполнения документов...
КонецЦикла;
ЗафиксироватьТранзакцию();
Важно: При использовании транзакций помните о возможности переполнения лога транзакций в SQL-версии или риске потери данных при сбое питания, если транзакция слишком объемная. Рекомендуется фиксировать транзакцию каждые 100-500 документов.
При чтении данных из XBase важно учитывать специфику типов 1С 7.7, чтобы избежать ошибок исполнения:
СокрЛП() при чтении текстовых данных.Число().Дата(Стр), предварительно убедившись в формате строки (ДД.ММ.ГГ или ГГГГММДД).На практике часто случается, что один и тот же файл загружают дважды. Чтобы не создавать дубли документов, перед выполнением команды Док.Новый() целесообразно проверить, не существует ли уже в базе документ с таким номером за указанную дату.
Для этого можно использовать объект типа Документ и метод НайтиПоНомеру(). Если документ найден, вы можете либо пропустить его создание, либо очистить существующий документ методом УдалитьСтроки() и заполнить его заново актуальными данными из файла.
Подводя итог, можно сказать, что корректная загрузка из DBF требует не только знания синтаксиса цикла, но и понимания структуры данных, механизмов индексации и контроля целостности базы данных 1С.