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