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

Программист 1С v7.7 Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При организации интеграции между конфигурациями 1С:Предприятие 8.3 и устаревшими базами на платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с трудностями при позиционировании объектов и переносе реквизитов. Типичный сценарий — получение данных (например, номеров накладных из комментариев платежных поручений) через COM-соединение и последующий поиск соответствующих документов в базе 7.7 для формирования выписок или проводок.

Разберем, почему метод НайтиПоНомеру() может возвращать ноль, как обойти это ограничение с помощью встроенного механизма запросов 1С 7.7 и как правильно организовать группировку по организациям (фирмам).

Почему метод НайтиПоНомеру возвращает 0: анализ причин

Рассмотрим типовой фрагмент кода, в котором разработчик подключается к базе 1С 8.3 через COMConnector, выбирает данные платежек и пытается спозиционировать документ в 1С 7.7:


Док = СоздатьОбъект("Документ.ПриходнаяНакладная");
Для Сч = 0 По Результат.Количество - 1 Цикл
    СтрокаТЧ = Результат.Получить(Сч);
    НомерПоиска = СокрЛП(СтрокаТЧ.Комментарий);
    
    Если Док.НайтиПоНомеру(НомерПоиска) = 1 Тогда
        ТЗДанных1С83.ДокСсылка = Док.ТекущийДокумент;
        ТЗДанных1С83.Фирма = Док.ТекущийДокумент.Фирма;
    КонецЕсли;
КонецЦикла;

Если метод Док.НайтиПоНомеру() возвращает 0, объект документа остается непозиционированным, а обращение к реквизиту Док.ТекущийДокумент возвращает пустое значение. Выделим основные технические причины такого поведения:

  1. Несоответствие длины и формата номера (ведущие нули). В метаданных 1С 7.7 номер документа имеет фиксированную длину (например, 8, 10 или 11 символов) и текстовый тип. Если документ создавался системой автоматически, номер дополняется ведущими нулями: например, 00000123. Если из комментария 1С 8.3 извлекается строка 123, точное строковое совпадение не сработает. Номер необходимо дополнять нулями слева до требуемой длины или использовать типовую функцию глПреобразоватьНомер().
  2. Периодичность нумерации документа. Метод НайтиПоНомеру(Номер, Дата) в 1С 7.7 принимает вторым параметром дату. Если нумерация документа в конфигураторе настроена с периодичностью (в пределах года, месяца или квартала), а дата в метод не передана, платформа производит поиск строго в пределах периода текущей рабочей даты (РабочаяДата()). Если накладная была проведена в другом расчетном периоде, поиск вернет 0. Для сквозной нумерации или поиска в определенном интервале рекомендуется явно передавать расчетную дату.

Альтернативное решение: использование запроса с отбором по Списку Значений

Построчный поиск через НайтиПоНомеру() в цикле работает медленно при больших объемах данных. Более надежным и производительным решением в 1С 7.7 является сбор всех номеров документов в объект СписокЗначений и выполнение единого «черного» запроса к метаданным.

Разберем по шагам реализацию данного механизма.

  1. Подключение через COM и получение данных из 1С 8.3:

    Инициализируем COM-соединение, формируем запрос к базе «восьмерки» и переносим номера документов в список значений 7.7. Обратите внимание: для добавления элементов в СписокЗначений используется метод ДобавитьЗначение(), а не Установить() (который служит для работы по ключам).

    
    Коннектор = СоздатьОбъект("V83.COMConnector");
    v8 = Коннектор.Connect("File=""" + ПутьКБазе + """;Usr=""" + СокрЛП(Логин) + """;Pwd=""" + СокрЛП(Пароль) + """;");
    
    Запрос8 = v8.NewObject("Запрос");
    Запрос8.Текст = 
    "ВЫБРАТЬ
    |   ПлатежноеПоручение.Комментарий КАК НомерНакладной
    |ИЗ
    |   Документ.ПлатежноеПоручение КАК ПлатежноеПоручение
    |ГДЕ
    |   ПлатежноеПоручение.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
    |   И ПлатежноеПоручение.Организация.ИНН = &Организация
    |   И ПлатежноеПоручение.Проведен = ИСТИНА";
    
    Запрос8.УстановитьПараметр("ДатаНачала", ВыбНачПериода);
    Запрос8.УстановитьПараметр("ДатаОкончания", ВыбКонПериода);
    Запрос8.УстановитьПараметр("Организация", Организация.ИНН);
    
    Результат8 = Запрос8.Выполнить().Выгрузить();
    
    СпНомеров = СоздатьОбъект("СписокЗначений");
    Для Сч = 0 По Результат8.Количество() - 1 Цикл
        СтрокаТЧ = Результат8.Получить(Сч);
        НомерСтр = СокрЛП(Строка(СтрокаТЧ.НомерНакладной));
        Если ПустаяСтрока(НомерСтр) = 0 Тогда
            СпНомеров.ДобавитьЗначение(НомерСтр);
        КонецЕсли;
    КонецЦикла;
    
  2. Построение запроса в 1С 7.7 с отбором:

    Для корректного отбора по списку в синтаксисе запросов 1С 7.7 используется оператор в. Конструкция вида Условие(НомерДок = спНомеров) является синтаксической ошибкой и приведет к пустому результату выборки.

    
    НчП = НачГода(ВыбКонПериода);
    Запрос77 = СоздатьОбъект("Запрос");
    ТекстЗапроса = 
    "//{{ЗАПРОС(ВыборкаПоНомерам)
    |с НчП по ВыбКонПериода;
    |Обрабатывать НеПомеченныеНаУдаление;
    |Без итогов;
    |ПриходнаяНакладная = Документ.ПриходнаяНакладная.ТекущийДокумент;
    |Фирма              = Документ.ПриходнаяНакладная.Фирма;
    |Контрагент         = Документ.ПриходнаяНакладная.Контрагент;
    |Договор            = Документ.ПриходнаяНакладная.Договор;
    |НомерДок           = Документ.ПриходнаяНакладная.НомерДок;
    |СуммаДок           = Документ.ПриходнаяНакладная.Сумма;
    |Группировка Фирма без групп;
    |Группировка ПриходнаяНакладная;
    |Условие(НомерДок в СпНомеров);
    |"//}}ЗАПРОС
    ;
    
    Если Запрос77.Выполнить(ТекстЗапроса) = 0 Тогда
        Предупреждение("Ошибка выполнения запроса по документам!");
        Возврат;
    КонецЕсли;
    

Обход результатов запроса и разделение документов по организациям

Когда требуется сгруппировать полученные документы по организациям (например, для автоматического создания трех разных документов банковской выписки под каждую фирму), в тексте запроса настраиваются многоуровневые группировки. В коде обход выполняется с указанием имени конкретной группировки в методе Группировка():


Пока Запрос77.Группировка("Фирма") = 1 Цикл
    ТекущаяФирма = Запрос77.Фирма;
    
    // Создаем документ БанковскаяВыписка для конкретной фирмы
    ДокВыписка = СоздатьОбъект("Документ.БанковскаяВыписка");
    ДокВыписка.Новый();
    ДокВыписка.ДатаДок = ТекущаяДата();
    ДокВыписка.Фирма   = ТекущаяФирма;
    
    // Вложенный цикл обхода документов накладных, относящихся к данной фирме
    Пока Запрос77.Группировка("ПриходнаяНакладная") = 1 Цикл
        ДокВыписка.НоваяСтрока();
        ДокВыписка.Договор     = Запрос77.Договор;
        ДокВыписка.Контрагент  = Запрос77.Контрагент;
        ДокВыписка.Сумма       = Запрос77.СуммаДок;
        ДокВыписка.ПервичныйДокумент = Запрос77.ПриходнаяНакладная;
    КонецЦикла;
    
    // Записываем документ
    // ДокВыписка.Записать();
КонецЦикла;

Подобный подход исключает ручной поиск документов по одному, обходит ограничения несовпадения форматов одиночных строк и позволяет гибко манипулировать полученными массивами данных с учетом структуры реквизитов 1С 7.7.

← На главную