В процессе разработки на платформе 1С:Предприятие 8.3 начинающие программисты часто сталкиваются с ситуацией, когда переменная, созданная в одной процедуре, оказывается «невидимой» для другой. Это классическая проблема области видимости (контекста) переменных. В данной статье мы подробно разберем, почему возникает ошибка Переменная не определена, и научимся правильно организовывать хранение данных в управляемых формах.
Проанализируем исходный код, который вызвал затруднения. В первой процедуре ДобавитьЧисло создается массив: МассивЧисел = Новый Массив. Основная ошибка заключается в том, что эта переменная является локальной. Рассмотрим подробнее, что это значит: локальная переменная живет только до тех пор, пока выполняется процедура. Как только программа доходит до строки КонецПроцедуры, массив удаляется из оперативной памяти компьютера.
Когда мы нажимаем кнопку «Показать» и вызываем процедуру ПоказатьМассив, система пытается найти переменную МассивЧисел, но ее больше не существует. Именно в этот момент 1С выдает ошибку компиляции или выполнения. Кроме того, в исходном коде была еще одна логическая ошибка: при каждом нажатии кнопки «Добавить» массив создавался заново (строка МассивЧисел = Новый Массив), что приводило к потере всех ранее введенных данных.
Самый надежный и правильный способ сохранить данные между вызовами различных процедур в управляемом приложении — это создание Реквизита формы. Реквизиты формы — это специальные переменные, которые живут всё то время, пока открыто окно вашей обработки или документа. Они доступны во всех процедурах модуля формы (и на клиенте, и на сервере).
Разберем по шагам, как это реализовать:
МассивДанных.Произвольный (так как стандартного типа «Массив» в списке выбора реквизитов нет, мы будем инициализировать его программно).Теперь проанализируем, как изменится наш код. Нам нужно инициализировать массив при открытии формы и затем обращаться к нему через объект формы. Рассмотрим пример реализации:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализируем массив один раз при открытии формы
МассивДанных = Новый Массив;
КонецПроцедуры
&НаКлиенте
Процедура ДобавитьЧисло(Команда)
// Проверяем заполнение поля ввода
Если ПустаяСтрока(Объект.ПолеВвода) Тогда
Возврат;
КонецЕсли;
// Преобразуем введенное значение в число
Попытка
Значение = Число(Объект.ПолеВвода);
// Добавляем в массив, который хранится в реквизите формы
МассивДанных.Добавить(Значение);
// Очищаем поле для нового ввода
Объект.ПолеВвода = 0;
Исключение
Сообщить("Введите корректное число!");
КонецПопытки;
КонецПроцедуры
Существует альтернативный вариант — объявить переменную в самом начале модуля формы. Рассмотрим этот метод. Если мы напишем Перем МассивЧисел; вне процедур, эта переменная станет доступна всем процедурам данного модуля.
Важный нюанс: В управляемых формах 1С 8.3 существует разделение на клиентский и серверный контекст. Если вы объявите переменную с директивой &НаКлиенте, она будет видна только в клиентских процедурах. Если управление передастся на сервер, данные этой переменной не будут доступны. Именно поэтому использование реквизитов формы (Решение №1) считается более профессиональным и универсальным подходом.
Посмотрим на пример использования ключевого слова Перем:
&НаКлиенте
Перем МассивЧисел;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
МассивЧисел = Новый Массив;
КонецПроцедуры
&НаКлиенте
Процедура ДобавитьЧисло(Команда)
// МассивЧисел теперь виден в этой процедуре
МассивЧисел.Добавить(Число(ПолеВвода));
КонецПроцедуры
В исходном вопросе автор использовал несуществующий метод СтрокаСоединить. В современном 1С для этих целей предусмотрена мощная глобальная функция СтрСоединить. Проанализируем, как правильно вывести содержимое массива в одну строку с разделителями.
Рассмотрим обновленную процедуру «Показать»:
&НаКлиенте
Процедура ПоказатьМассив(Команда)
// Проверяем, есть ли данные в массиве
Если МассивДанных.Количество() = 0 Тогда
Сообщить("Массив пуст!");
Возврат;
КонецЕсли;
// Преобразуем массив в строку с разделителем "запятая"
ТекстСообщения = СтрСоединить(МассивДанных, ", ");
Сообщить("Содержимое массива: " + ТекстСообщения);
КонецПроцедуры
Проанализируем ситуацию, когда пользователь вводит текст вместо цифр. Использование функции Число() без проверки может привести к аварийному завершению программы. Рекомендуется использовать конструкцию Попытка ... Исключение, как показано в примере выше, либо заранее настроить ПолеВвода на работу только с числовым типом данных в свойствах элемента формы.
Для полной очистки данных мы используем метод объекта Массив — Очистить(). Посмотрим, как это выглядит в коде:
&НаКлиенте
Процедура ОчиститьМассив(Команда)
МассивДанных.Очистить();
Сообщить("Массив успешно очищен");
КонецПроцедуры
Для успешного решения задачи ввода и вывода массива мы должны помнить три правила:
Массив или СписокЗначений) один раз, например, при создании формы на сервере или при первом открытии.Соблюдение этих принципов позволит вам избежать ошибок Переменная не определена и создавать надежные алгоритмы обработки данных в среде 1С.