Как исправить ошибку "Недопустимое значение" при работе с ФиксированнымМассивом в 1С после обновления платформы?

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

Мы рассмотрим подробно проблему, которая возникла у пользователей 1С:Розницы (2.3.8.22) после обновления платформы до версии 8.3.20.1996. Суть ошибки заключается в появлении сообщения "Недопустимое значение" при попытке работы с коллекцией типа ФиксированныйМассив. Эта ситуация часто ставит в тупик разработчиков, поскольку она связана с изменением поведения платформы и требует глубокого понимания принципов работы с неизменяемыми коллекциями.

Проблема проявлялась в следующем контексте:


Недопустимое значение {ОбщийМодуль.ОбщегоНазначенияРТ.Модуль(1019)}:ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
{Справочник.СкидкиНаценки.Форма.ФормаЭлемента.Форма(117)}:ОбщегоНазначенияРТ.УдалитьПараметрыВыбораРасширений(Элементы.ВнешняяОбработка.ПараметрыВыбора);
по причине: Недопустимое значение

Данная ошибка возникает в процедуре УдалитьПараметрыВыбораРасширений, которая предназначена для фильтрации элементов коллекции ПараметрыВыбора. Давайте детально проанализируем исходный код этой процедуры и разберем причины возникновения ошибки.

Анализ исходной проблемы и ошибки

Рассмотрим исходный код процедуры УдалитьПараметрыВыбораРасширений, как она была представлена до исправления:


// Удаляет устаревшие параметры выбора
// Параметры:
// ПараметрыВыбора - Фиксированные массив
Процедура УдалитьПараметрыВыбораРасширений(ПараметрыВыбора) Экспорт
    Если ПараметрыВыбора.Количество > 0 Тогда
        МассивДляВнешнихОбработок = Новый Массив;
        СтрокаПоиска = НСтр("ru = ''");
        Для каждого ПараметрВыбора Из ПараметрыВыбора Цикл
            Если СтрНайти(ПараметрВыбора.Значение, СтрокаПоиска) = 0 Тогда
                МассивДляВнешнихОбработок.Добавить(ПараметрВыбора.Значение);
            КонецЕсли;
        КонецЦикла;
        ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
    КонецЕсли;
КонецПроцедуры

Давайте разберем эту процедуру по шагам и выясним, почему она начала выдавать ошибку "Недопустимое значение" после обновления платформы.

Ключевой момент в данной проблеме — это работа с объектом ФиксированныйМассив. Фиксированный массив является неизменяемым объектом. Это означает, что после его создания мы не можем добавлять в него новые элементы, удалять существующие или изменять их последовательность. Однако, в данном случае, ошибка возникает не при попытке непосредственного изменения элементов исходного ФиксированногоМассива, а на строке, где происходит переприсвоение переменной ПараметрыВыбора:

ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);

Эта строка пытается создать совершенно новый ФиксированныйМассив из временного Массива под названием МассивДляВнешнихОбработок и затем присвоить ссылку на этот новый объект переменной ПараметрыВыбора. Сама по себе такая операция переприсвоения ссылки на новый объект для переменной-параметра не является нарушением неизменяемости исходного ФиксированногоМассива. Проблема кроется глубже — в содержимом, которое мы пытались поместить в новый ФиксированныйМассив.

Проанализируем строку, отвечающую за заполнение временного массива:

МассивДляВнешнихОбработок.Добавить(ПараметрВыбора.Значение);

Здесь и кроется основная причина ошибки. Входящий параметр ПараметрыВыбора, судя по всему, является коллекцией, содержащей объекты типа ПараметрВыбора. Объект ПараметрВыбора, как правило, имеет два важных свойства: Имя и Значение. Однако в цикле мы добавляли во временный МассивДляВнешнихОбработок только свойство Значение каждого элемента.

Таким образом, после завершения цикла, МассивДляВнешнихОбработок содержал не коллекцию объектов ПараметрВыбора, а коллекцию простых значений (например, строк, чисел или ссылок). Когда из этого временного массива затем создавался новый ФиксированныйМассив, он также содержал только эти простые значения.

Конечная точка назначения этого ФиксированногоМассива — это свойство Элементы.ВнешняяОбработка.ПараметрыВыбора. Вероятнее всего, это свойство ожидает на вход коллекцию, состоящую из объектов ПараметрВыбора (т.е. объектов, которые имеют как Имя, так и Значение), а не просто список значений. Попытка присвоить этому свойству ФиксированныйМассив, элементы которого не соответствуют ожидаемому типу (т.е. вместо объектов ПараметрВыбора в нем оказались просто значения), и приводила к ошибке "Недопустимое значение".

Ужесточение контроля типов в новых версиях платформы 1С (начиная с 8.3.20.1996) сделало такие несоответствия более явными и приводило к критическим ошибкам, тогда как в более ранних версиях они могли игнорироваться или вызывать менее заметные проблемы. Платформа теперь более строго проверяет, соответствует ли тип элементов коллекции тому, что ожидается в целевом свойстве или параметре.

Пошаговое решение проблемы

Для решения возникшей проблемы нам необходимо обеспечить, чтобы новый ФиксированныйМассив, который мы создаем, содержал элементы правильного типа, соответствующие ожиданиям системы. Если исходная коллекция ПараметрыВыбора состоит из объектов типа ПараметрВыбора, то и фильтрованная коллекция должна сохранять эту структуру.

Разберем шаги, которые мы предпримем для исправления кода:

  1. Создаем временный изменяемый массив. Мы по-прежнему будем использовать обычный объект Массив (Новый Массив) для промежуточного хранения отфильтрованных элементов. Это необходимо, так как Массив, в отличие от ФиксированногоМассива, позволяет нам свободно добавлять и удалять элементы.
  2. Корректно заполняем временный массив. Это ключевой шаг. Вместо того чтобы добавлять в МассивДляВнешнихОбработок только свойство Значение каждого элемента, мы будем добавлять весь объект ПараметрВыбора целиком. Это гарантирует, что каждый элемент в нашем временном массиве будет иметь структуру ПараметрВыбора (свойства Имя и Значение), что соответствует ожидаемому типу данных.
  3. Создаем новый ФиксированныйМассив. После того как временный МассивДляВнешнихОбработок будет правильно заполнен корректными объектами ПараметрВыбора, мы создадим из него новый ФиксированныйМассив, используя конструктор Новый ФиксированныйМассив(МассивДляВнешнихОбработок). Этот новый фиксированный массив будет полностью корректным по структуре и типу элементов.
  4. Присваиваем новый ФиксированныйМассив переменной-параметру. Строка ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок); останется без изменений. Теперь она будет работать корректно, поскольку новый ФиксированныйМассив содержит ожидаемые типы данных, и платформа не будет считать его "Недопустимым значением" при последующей передаче.

Пример исправленного кода

Вот как выглядит исправленная процедура, основанная на решении, предложенном на форуме. Для модификации типового кода без снятия конфигурации с поддержки, мы используем механизм расширений и соответствующие директивы компиляции:


&ИзменениеИКонтроль("УдалитьПараметрыВыбораРасширений")
Процедура ИСП32_УдалитьПараметрыВыбораРасширений(ПараметрыВыбора)
    Если ПараметрыВыбора.Количество > 0 Тогда
        МассивДляВнешнихОбработок = Новый Массив;
        СтрокаПоиска = НСтр("ru = ''");
        Для каждого ПараметрВыбора Из ПараметрыВыбора Цикл
            Если СтрНайти(ПараметрВыбора.Значение, СтрокаПоиска) = 0 Тогда
                #Удаление
                МассивДляВнешнихОбработок.Добавить(ПараметрВыбора.Значение);
                #КонецУдаления
                #Вставка
                МассивДляВнешнихОбработок.Добавить(ПараметрВыбора);
                #КонецВставки
            КонецЕсли;
        КонецЦикла;
        ПараметрыВыбора = Новый ФиксированныйМассив(МассивДляВнешнихОбработок);
    КонецЕсли;
КонецПроцедуры

Как мы видим в исправленном коде, единственное, но критически важное изменение произошло в строке добавления элемента во временный массив:

МассивДляВнешнихОбработок.Добавить(ПараметрВыбора);

Теперь мы добавляем весь объект ПараметрВыбора, а не только его свойство Значение. Это позволяет сохранить исходную структуру и тип элементов, что устраняет ошибку "Недопустимое значение" при создании нового ФиксированногоМассива и его последующем использовании.

Дополнительные рекомендации при работе с ФиксированнымМассивом

Работа с ФиксированнымМассивом в 1С требует особого внимания из-за его неизменяемой природы. Всегда держите в уме следующие принципы и рекомендации:

  1. Помните о неизменяемости: ФиксированныйМассив нельзя изменить после создания. Если вам необходимо получить измененный набор элементов, вы всегда должны создавать новый ФиксированныйМассив.
  2. Используйте временные изменяемые коллекции: Для операций фильтрации, сортировки, добавления или удаления элементов, всегда сначала перенесите данные в обычный Массив (или Соответствие, Структуру и т.д.), выполните необходимые манипуляции, а затем создайте новый ФиксированныйМассив из полученного результата.
  3. Соблюдайте тип элементов: Это было основной причиной ошибки в нашем случае. При создании нового ФиксированногоМассива из временной коллекции убедитесь, что элементы этой коллекции имеют тот тип и структуру, которые ожидаются в месте использования ФиксированногоМассива. Если ожидаются объекты определенного типа (например, ПараметрВыбора), то и в новый ФиксированныйМассив должны попасть именно эти объекты, а не только их отдельные свойства.
  4. Осознавайте контекст использования: В управляемых формах, особенно при работе с динамическими списками, параметрами выбора или свойствами элементов форм, платформа может предъявлять строгие требования к типу и структуре передаваемых коллекций. Несоответствие может приводить к ошибкам "Недопустимое значение" или "Поле объекта не обнаружено".
  5. Тестируйте после обновлений: Как показывает данный случай, обновления платформы могут ужесточать контроль типов и изменять поведение некоторых механизмов. Всегда проводите тщательное тестирование доработок и расширений после каждого обновления платформы.
  6. Используйте расширения для доработок: Модификация типового функционала через расширения является предпочтительным способом. Это позволяет сохранить конфигурацию на поддержке и упрощает процесс обновления. Директивы &ИзменениеИКонтроль, #Удаление, #КонецУдаления, #Вставка, #КонецВставки являются мощным инструментом для точечного изменения кода.

Таким образом, понимание принципов работы ФиксированногоМассива, а также строгое соблюдение типов данных и структуры элементов при его формировании, являются фундаментальными для предотвращения подобных ошибок и обеспечения стабильной работы ваших решений на платформе 1С:Предприятие.

← На главную