При организации интеграции между конфигурациями 1С:Предприятие 8.3 и устаревшими базами на платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с трудностями при позиционировании объектов и переносе реквизитов. Типичный сценарий — получение данных (например, номеров накладных из комментариев платежных поручений) через COM-соединение и последующий поиск соответствующих документов в базе 7.7 для формирования выписок или проводок.
Разберем, почему метод НайтиПоНомеру() может возвращать ноль, как обойти это ограничение с помощью встроенного механизма запросов 1С 7.7 и как правильно организовать группировку по организациям (фирмам).
Рассмотрим типовой фрагмент кода, в котором разработчик подключается к базе 1С 8.3 через COMConnector, выбирает данные платежек и пытается спозиционировать документ в 1С 7.7:
Док = СоздатьОбъект("Документ.ПриходнаяНакладная");
Для Сч = 0 По Результат.Количество - 1 Цикл
СтрокаТЧ = Результат.Получить(Сч);
НомерПоиска = СокрЛП(СтрокаТЧ.Комментарий);
Если Док.НайтиПоНомеру(НомерПоиска) = 1 Тогда
ТЗДанных1С83.ДокСсылка = Док.ТекущийДокумент;
ТЗДанных1С83.Фирма = Док.ТекущийДокумент.Фирма;
КонецЕсли;
КонецЦикла;
Если метод Док.НайтиПоНомеру() возвращает 0, объект документа остается непозиционированным, а обращение к реквизиту Док.ТекущийДокумент возвращает пустое значение. Выделим основные технические причины такого поведения:
00000123. Если из комментария 1С 8.3 извлекается строка 123, точное строковое совпадение не сработает. Номер необходимо дополнять нулями слева до требуемой длины или использовать типовую функцию глПреобразоватьНомер().НайтиПоНомеру(Номер, Дата) в 1С 7.7 принимает вторым параметром дату. Если нумерация документа в конфигураторе настроена с периодичностью (в пределах года, месяца или квартала), а дата в метод не передана, платформа производит поиск строго в пределах периода текущей рабочей даты (РабочаяДата()). Если накладная была проведена в другом расчетном периоде, поиск вернет 0. Для сквозной нумерации или поиска в определенном интервале рекомендуется явно передавать расчетную дату.Построчный поиск через НайтиПоНомеру() в цикле работает медленно при больших объемах данных. Более надежным и производительным решением в 1С 7.7 является сбор всех номеров документов в объект СписокЗначений и выполнение единого «черного» запроса к метаданным.
Разберем по шагам реализацию данного механизма.
Подключение через 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 Тогда
СпНомеров.ДобавитьЗначение(НомерСтр);
КонецЕсли;
КонецЦикла;
Построение запроса в 1С 7.7 с отбором:
Для корректного отбора по списку в синтаксисе запросов 1С 7.7 используется оператор в. Конструкция вида Условие(НомерДок = спНомеров) является синтаксической ошибкой и приведет к пустому результату выборки.
НчП = НачГода(ВыбКонПериода);
Запрос77 = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ВыборкаПоНомерам)
|с НчП по ВыбКонПериода;
|Обрабатывать НеПомеченныеНаУдаление;
|Без итогов;
|ПриходнаяНакладная = Документ.ПриходнаяНакладная.ТекущийДокумент;
|Фирма = Документ.ПриходнаяНакладная.Фирма;
|Контрагент = Документ.ПриходнаяНакладная.Контрагент;
|Договор = Документ.ПриходнаяНакладная.Договор;
|НомерДок = Документ.ПриходнаяНакладная.НомерДок;
|СуммаДок = Документ.ПриходнаяНакладная.Сумма;
|Группировка Фирма без групп;
|Группировка ПриходнаяНакладная;
|Условие(НомерДок в СпНомеров);
|"//}}ЗАПРОС
;
Если Запрос77.Выполнить(ТекстЗапроса) = 0 Тогда
Предупреждение("Ошибка выполнения запроса по документам!");
Возврат;
КонецЕсли;
Когда требуется сгруппировать полученные документы по организациям (например, для автоматического создания трех разных документов банковской выписки под каждую фирму), в тексте запроса настраиваются многоуровневые группировки. В коде обход выполняется с указанием имени конкретной группировки в методе Группировка():
Пока Запрос77.Группировка("Фирма") = 1 Цикл
ТекущаяФирма = Запрос77.Фирма;
// Создаем документ БанковскаяВыписка для конкретной фирмы
ДокВыписка = СоздатьОбъект("Документ.БанковскаяВыписка");
ДокВыписка.Новый();
ДокВыписка.ДатаДок = ТекущаяДата();
ДокВыписка.Фирма = ТекущаяФирма;
// Вложенный цикл обхода документов накладных, относящихся к данной фирме
Пока Запрос77.Группировка("ПриходнаяНакладная") = 1 Цикл
ДокВыписка.НоваяСтрока();
ДокВыписка.Договор = Запрос77.Договор;
ДокВыписка.Контрагент = Запрос77.Контрагент;
ДокВыписка.Сумма = Запрос77.СуммаДок;
ДокВыписка.ПервичныйДокумент = Запрос77.ПриходнаяНакладная;
КонецЦикла;
// Записываем документ
// ДокВыписка.Записать();
КонецЦикла;
Подобный подход исключает ручной поиск документов по одному, обходит ограничения несовпадения форматов одиночных строк и позволяет гибко манипулировать полученными массивами данных с учетом структуры реквизитов 1С 7.7.