Как исправить ошибку «Переменная не определена (Документы)» и организовать загрузку из DBF при переносе обработки из ЗУП 2.5 в ЗУП 3.1?

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

При переносе внешних обработок и алгоритмов из конфигурации «Зарплата и управление персоналом» редакции 2.5 в современную редакцию 3.1 разработчики часто сталкиваются с ситуацией, когда привычный код перестает компилироваться и выдает ошибки синтаксиса вида «Переменная не определена (Документы)» или «Переменная не определена (Справочники)». Проанализируем, почему возникает эта проблема, чем отличается работа кода в управляемом приложении и как правильно переписать алгоритм загрузки данных из внешнего DBF-файла.

Выясним причину возникновения ошибки

В конфигурациях на обычных формах (таких как ЗУП 2.5) весь код по умолчанию выполнялся на клиенте с полным доступом к объектной модели базы данных. В современной платформе 1С:Предприятие 8.3 при использовании тонкого клиента и управляемых форм (ЗУП 3.1) применяется четкое разделение на клиентский и серверный контексты.

На стороне тонкого клиента (в процедурах с директивой компиляции &НаКлиенте) недоступны менеджеры прикладных объектов:

  1. Документы
  2. Справочники
  3. ПланыВидовРасчета
  4. РегистрыСведений и другие глобальные коллекции манипулирования данными.

Попытка обратиться к ним на клиенте прямо приводит к ошибке компиляции. Любые действия по созданию, изменению, поиску и записи документов или справочников должны выполняться исключительно на стороне сервера в процедурах с директивой компиляции &НаСервере или &НаСервереБезКонтекста.

Архитектурные подходы к переработке алгоритма

Рассмотрим два основных способа решения этой задачи при переносе обработки на управляемые формы.

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

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


&НаСервере
Процедура СозданиеДокументаНачисления(ДанныеДокумента)
    Док = Документы.НачислениеЗаработнойПлаты.СоздатьДокумент();
    ЗаполнитьЗначенияСвойств(Док, ДанныеДокумента);
    Док.Записать();
КонецПроцедуры

&НаКлиенте
Процедура ИмпортДанныхДляНачисления()
    ДанныеДокумента = Новый Структура;
    ДанныеДокумента.Вставить("Комментарий", "Импорт документа");
    
    // Подготовка структуры на клиенте...
    
    СозданиеДокументаНачисления(ДанныеДокумента);
КонецПроцедуры

Способ 2. Выполнение полного цикла обработки на сервере.
В этом случае открытие файла DBF, чтение строк, поиск элементов в справочниках и создание документа выполняются целиком в серверной процедуре. Этот вариант проще в переносе, однако требует учесть нюансы работы с файловой системой на сервере.

Особенности работы с DBF-файлами в клиент-серверном режиме

При использовании объекта XBase на стороне сервера важно учитывать следующую специфику:

  1. Доступность сетевого пути. Сервер 1С выполняется под собственной служебной учетной записью операционной системы. Если сетевой ресурс (например, \\Server\ZAR_PLAT\ZARVAL\Sd_Nar.DBF) недоступен учетной записи службы 1CV8 Service, открыть файл на сервере не удастся.
  2. Передача файла через временное хранилище. Методически наиболее корректным решением является считывание файла в объект ДвоичныеДанные на клиенте, помещение его во временное хранилище через ПоместитьВоВременноеХранилище() и дальнейшая распаковка во временный файл сервера с помощью ПолучитьИмяВременногоФайла("dbf").

Реализация серверного обработчика загрузки

Рассмотрим готовый пример серверной процедуры Команда2, в которой выполняется чтение файла DBF, поиск видов расчета и сотрудников, а также наполнение табличной части документа начисления.


&НаСервере
Процедура Команда2(Команда)
    Перем ТипРасчета;
    
    ДБФ = Новый XBase;
    ДБФ.Кодировка = КодировкаXBase.OEM;
    ДБФ.ОткрытьФайл("\\Server\ZAR_PLAT\ZARVAL\Sd_Nar.DBF");
    
    Если Не ДБФ.Открыта() Тогда
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось открыть файл базы данных DBF!");
        Возврат;
    КонецЕсли;
    
    ДБФ.Индексы.Добавить("Shifr", "Shifr", Ложь, Ложь);
    ДБФ.СоздатьИндексныйФайл("i_Sd_Nar.cdx");
    
    Сотр = Справочники.Сотрудники;
    СпрВидРасчета = ПланыВидовРасчета.Начисления;
    
    Док = Документы.НачислениеЗаработнойПлаты.СоздатьДокумент();
    Док.Дата = ТекущаяДата();
    
    ДБФ.Первая();
    Пока НЕ ДБФ.ВКонце() Цикл
        ВидОплаты = ДБФ.Shifr;
        
        Расчет1 = Неопределено;
        Если ДБФ.Shifr = "001" Тогда
            Шифр001 = СпрВидРасчета.НайтиПоНаименованию("Сдельные наряды(суммой)", Истина);
            Если Не Шифр001.Пустая() Тогда
                Расчет1 = Шифр001;
            КонецЕсли;
        ИначеЕсли ДБФ.Shifr = "005" Тогда
            Шифр005 = СпрВидРасчета.НайтиПоНаименованию("Сверхурочные(суммой)", Истина);
            Если Не Шифр005.Пустая() Тогда
                Расчет1 = Шифр005;
            КонецЕсли;
        ИначеЕсли ДБФ.Shifr = "050" Тогда
            Шифр050 = СпрВидРасчета.НайтиПоНаименованию("Премия месячная(суммой)", Истина);
            Если Не Шифр050.Пустая() Тогда
                Расчет1 = Шифр050;
            КонецЕсли;
        КонецЕсли;
        
        КолСтрок = 0;
        Пока (НЕ ДБФ.ВКонце()) И (ВидОплаты = ДБФ.Shifr) Цикл
            ТекСтрока = Док.Начисления.Добавить();
            КолСтрок = КолСтрок + 1;
            
            ТекСтрока.ВидРасчета = Расчет1;
            
            Сотр1 = Сотр.НайтиПоКоду(ДБФ.TabNom);
            Если Не Сотр1.Пустая() Тогда
                ТекСтрока.Сотрудник = Сотр1;
            КонецЕсли;
            
            ТекСтрока.Результат = ДБФ.Summa;
            ТекСтрока.ДатаНачала = ДБФ.Dat_Beg;
            ТекСтрока.ДатаОкончания = ДБФ.Dat_End;
            
            ДБФ.Следующая();
        КонецЦикла;
        
    КонецЦикла;
    
    ДБФ.ЗакрытьФайл();
    
    Попытка
        Док.Записать(РежимЗаписиДокумента.Запись);
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Документ успешно создан и записан!");
    Исключение
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка при записи документа: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Замена устаревших методов и функций информирования

При переносе кода на сервер обратите внимание на вызовы интерактивных функций:

  1. Модальные вызовы и диалоговые окна (Предупреждение(), Вопрос()) **недопустимы** в серверном коде. Их нужно выносить на клиент либо отключать.
  2. Для отправки сообщений пользователю из серверного контекста рекомендуется использовать методы Библиотеки Стандартных Подсистем (БСП), например: ОбщегоНазначенияКлиентСервер.СообщитьПользователю(). Обычный метод Сообщить() на сервере также работает, однако функции БСП обеспечивают корректную привязку сообщений к элементам формы.
  3. Убедитесь, что имена метаданных соответствуют целевой конфигурации: в ЗУП 3.1 планом видов расчета является ПланыВидовРасчета.Начисления, а основным документом расчета зарплаты за месяц — Документы.НачислениеЗаработнойПлаты (или специализированные документы выработки, такие как Документы.СдельныйНаряд).
← На главную