Перенос данных со старых платформ 1С (таких как 1С:Предприятие 7.7) на современные конфигурации 1С:Предприятие 8.3 — задача, с которой регулярно сталкиваются разработчики. Для настройки правил обмена традиционно используется конфигурация «Конвертация данных 2.1». Однако в процессе выгрузки могут возникать весьма специфические ошибки компиляции, способные поставить в тупик даже опытного специалиста. Проанализируем одну из таких типовых проблем.
В этой статье мы подробно разберем ошибку компиляции при выгрузке документа ПриемНаРаботуВОрганизацию, выясним истинные причины её возникновения (которые часто остаются незамеченными на форумах) и исправим не только саму ошибку, но и критические логические дефекты в кодовой базе выгрузки.
Симптомы проблемы выглядят следующим образом. При попытке выгрузки данных система выдает ошибку:
Ошибка в обработчике события ПередОбработкойВыгрузки группы свойств... ОписаниеОшибки = Ошибка компиляции при вычислении выражения или выполнении фрагмента кода: {(1,4)}: Процедура или функция с указанным именем не определена (СоздатьОбъект)
---
Выясним, почему платформа выдает ошибку о неопределенности функции СоздатьОбъект. Эта функция является базовым методом платформы 1С 7.7 для инициализации объектов (таблиц значений, справочников, документов). В платформе 1С 8.x такого метода нет — вместо него используется оператор Новый.
Подобный сбой происходит в двух сценариях:
УниверсальныйОбменДаннымиXML пытается скомпилировать и выполнить код обработчиков непосредственно в контексте 8-ки. Встретив там чистый код 7.7, платформа 1С 8.3 закономерно выдает ошибку компиляции.Рассмотрим два основных варианта решения этой архитектурной проблемы.
---
При переносе данных из 1С 7.7 настоятельно рекомендуется отказаться от прямого COM-подключения из базы 8.3. Архитектурные различия платформ и утечки памяти при работе OLE-соединений могут приводить к зависаниям. Гораздо надежнее использовать выгрузку в промежуточный XML-файл.
Разберем по шагам, как настроить этот процесс правильно:
V77Exp.ert, поставляемая вместе с КД 2.1). Откройте её модуль и полностью замените существующий код сгенерированным текстом модуля выгрузки. Сохраните обработку.V77Exp.ert, укажите файл правил обмена и выполните выгрузку в XML-файл. При этом код отработает корректно, так как он будет выполняться в родной среде 1С 7.7.УниверсальныйОбменДаннымиXML и загрузите полученный файл данных.---
Если по каким-то причинам вам необходимо производить выгрузку именно в режиме прямого подключения из базы 1С 8.3, то писать код на «чистом» языке 7.7 в обработчиках КД нельзя. Платформа 8.3 должна обращаться к объектам 7.7 через COM-соединение.
В правилах обмена при COM-подключении доступна глобальная переменная (обычно это БазаОле или V77). Все вызовы функций создания объектов должны адресоваться к ней. Посмотрим на пример изменения синтаксиса:
// Вместо прямого создания объектов в 7.7:
// тз = СоздатьОбъект("ТаблицаЗначений");
// сп = СоздатьОбъект("Справочник.Сотрудники");
// Используем обращение через OLE-соединение:
тз = БазаОле.CreateObject("ТаблицаЗначений");
сп = БазаОле.CreateObject("Справочник.Сотрудники");
Важно: При использовании OLE-соединения вам придется переписать абсолютно весь алгоритм обработчика, поскольку методы обхода выборки (ВыбратьЭлементы(), ПолучитьЭлемент()) также должны будут вызываться через COM-объект, что существенно снижает скорость работы и усложняет отладку.
---
Даже если мы решим проблему с контекстом выполнения (запустим выгрузку локально в 1С 7.7 через V77Exp.ert), исходный код обработчика, представленный автором вопроса, содержит целый ряд грубейших синтаксических и логических ошибок платформы 7.7. Проанализируем эти ошибки и исправим их.
Посмотрим еще раз на исходный фрагмент кода:
тз=СоздатьОбъект("ТаблицаЗначений");
тз.НоваяКолонка("Сотрудник");
тз.НоваяКолонка("ДатаПриема");
// ...
Пока сп.ПолучитьЭлемент()=1 Цикл
Если Источник.Дт Тогда
Продолжить;
КонецЕсли;
тз.НоваяСтрока();
тз.Сотрудник = сп.ТекущийЭлемент();
тз.ДатаНачала = Источник.Дт; // Ошибка! Такой колонки нет в ТЗ
// ...
КонецЦикла;
КоллекцияОбъектов = тз;
Строка кода Если Источник.Дт Тогда гарантированно вызовет ошибку времени выполнения в 1С 7.7 по двум причинам:
0 (ложь) и 1 (истина). Неявное приведение типов (когда любое заполненное значение расценивается как истина) здесь не работает.Источник.Дт представляет собой тип Дата. Попытка подставить дату в условие Если... Тогда приведет к ошибке «Ожидается логическое выражение».Для проверки заполнения даты в 1С 7.7 необходимо использовать функцию ПустоеЗначение():
Если ПустоеЗначение(Источник.Дт) = 0 Тогда
// Дата заполнена, выполняем действия
КонецЕсли;
При объявлении структуры таблицы значений разработчик создает колонку с именем "ДатаПриема":
тз.НоваяКолонка("ДатаПриема");
Однако ниже по тексту при заполнении строки ТЗ значение присваивается в несуществующую колонку "ДатаНачала":
тз.ДатаНачала = Источник.Дт;
Это неминуемо приведет к падению выгрузки с ошибкой «Поле агрегатного объекта не обнаружено». Имена колонок при объявлении и при обращении должны строго совпадать.
Посмотрим на обход справочника сотрудников внутри обработчика:
сп = СоздатьОбъект("Справочник.Сотрудники");
сп.ВыбратьЭлементы();
Пока сп.ПолучитьЭлемент()=1 Цикл
// Заполнение ТЗ...
КонецЦикла;
Данный обработчик написан для ПКГС (Правила конвертации группы свойств) табличной части документа. Это означает, что данный код выполняется при выгрузке каждого отдельного документа «Приказ на прием на работу».
Если в вашей базе 1 000 документов приема на работу и 1 000 сотрудников в справочнике, то при выгрузке система выполнит 1 000 000 (один миллион!) итераций цикла, перебирая весь справочник сотрудников для каждого документа. Выгрузка базы просто зависнет.
В документе приема на работу в 1С 7.7 (например, в ЗиК 7.7) обычно фигурирует конкретный сотрудник (или список сотрудников, если это групповой приказ). Нам не нужно выбирать всех сотрудников из базы — нужно получать данные только по тем сотрудникам, которые указаны в самом документе (в объекте Источник).
---
Проанализируем структуру документа-источника. Допустим, мы выгружаем документ приема на работу, где сотрудник указан в шапке документа (реквизиты Сотрудник, Ставка, Оклад, а дата приема хранится в реквизите ДатаПриема или Дт). Нам нужно сформировать строку табличной части для приемника в 1С 8.3.
Рассмотрим правильный, чистый вариант кода для обработчика ПередОбработкойВыгрузкиГруппыСвойств табличной части РаботникиОрганизации:
// Инициализируем Таблицу Значений с правильными именами колонок
тз = СоздатьОбъект("ТаблицаЗначений");
тз.НоваяКолонка("Сотрудник");
тз.НоваяКолонка("ДатаПриема");
тз.НоваяКолонка("ПодразделениеОрганизации");
тз.НоваяКолонка("Должность");
тз.НоваяКолонка("ЗанимаемыхСтавок");
тз.НоваяКолонка("МесячнаяТарифнаяСтавка");
// Проверяем, задан ли сотрудник в документе-источнике
Если ПустоеЗначение(Источник.Сотрудник) = 0 Тогда
// Создаем ОДНУ строку в ТЗ для текущего сотрудника из документа
тз.НоваяСтрока();
тз.Сотрудник = Источник.Сотрудник;
// Безопасно определяем дату приема
Если ПустоеЗначение(Источник.Дт) = 0 Тогда
тз.ДатаПриема = Источник.Дт;
Иначе
тз.ДатаПриема = Источник.ДатаДок; // Альтернативная дата, если Дт пустая
КонецЕсли;
// Получаем периодические реквизиты сотрудника на дату приема
спСотр = Источник.Сотрудник;
тз.ПодразделениеОрганизации = спСотр.Подразделение.Получить(тз.ДатаПриема);
тз.Должность = спСотр.Должность;
Ставка = спСотр.Ставка.Получить(тз.ДатаПриема);
тз.ЗанимаемыхСтавок = ?(Ставка = 0, 1, Ставка);
тз.МесячнаяТарифнаяСтавка = спСотр.Оклад.Получить(тз.ДатаПриема);
КонецЕсли;
// Передаем заполненную таблицу в коллекцию объектов выгрузки
КоллекцияОбъектов = тз;
Проанализируем, почему этот код работает правильно и быстро:
Источник."ДатаПриема" теперь называется одинаково как при создании ТЗ, так и при её заполнении.ПустоеЗначение(Источник.Дт) гарантирует стабильную работу без вызова ошибок несоответствия типов данных.Получить() строго на дату приема сотрудника, что исключает получение неактуальных данных.Применив данные изменения и выполнив выгрузку по классической схеме через файл обмена в 1С 7.7, вы гарантированно избавитесь от ошибок компиляции и добьетесь корректного переноса кадровых документов в базу 1С 8.3.