Вот Сергей копит в копилку (https://forum.dorex.pro/index.php?topic=191.0), а обсуждать там не разрешает. Пусть будет тема для небольшого полуфлуда - обо всём и ни о чём. Шепотом.
Не только для копилки - потому что иногда натыкаешься на какую-нибудь интересную неожиданную ерунду, забавный пустяк, а может кому пригодится.
Вот про то, что Записать недокументировано возвращает значение (https://forum.dorex.pro/index.php?topic=191.46), если применяется к элементу / документу локального контекста (а не созданному через СоздатьОбъект), оказалось интересно. Даже никогда не задумывался, что будет, если не заморачиваться с
Если Форма.ТолькоПросмотр() = 1 Тогда
Форма.КнопкаОК.Доступность(0);
КонецЕсли;
А оказалось, что ничего не будет. Если форма открыта в режиме чтения (только на просмотр), то и Записать() и #Записать будут проигнорированы. Так что использование Доступность(0) - просто способ показать пользователю, что нажимать кнопку бесполезно.
Ну и кстати #Записать и Записать() неравнозначны, вопреки тому что написано в als (там так: "данный метод отрабатывает те же действия, что и интерактивное нажатие пользователем кнопки с формулой ''#Записать''")
Записать() не вызывает ПриЗаписи() и игнорирует некоторые установки записи, типа СохранениеПериодическихРеквизитов(). Но вот ПриЗаписиПерепроводить(1) и АвтоВремя..(), а также регистрацию события в "Журнале регистрации" оба варианта отрабатывают одинаково. Ещё раз акцентирую, что Записать() - именно в локальном контексте, а не к созданному через СоздатьОбъект().
Записать() возвращает ноль не только, если форма открыта в режиме чтения, но и при нарушении уникальности кода. Правда, в этом случае всё равно выдаётся интерактивное окошко предупреждения "Код не уникальный", поэтому использовать Записать() для программной проверки возможности записи - не очень хорошо.
Написал, перечитал, задумался. Если ПриЗаписиПерепроводить(1) действует на Записать() локального контекста, то, значит я всё это время неправильно делал запись с перепроводением из формы документа:
Записать();
Если Проведен() = 1 Тогда
Провести();
КонецЕсли;В этом коде две проблемы:
1) двойное перепроведение, если ПриЗаписиПерепроводить() было установлено в единичку;
2) надо городить огород с единой транзакцией, чтобы не получилось, что реквизиты в документ записаны новые, а проведение документа, в случае неудачи, осталось по старым.
Подобную реализацию можно увидеть в процедуре ПечатьЧека() в ПКО и РКО в типовой Тис, например.
Правильный код для записи с перепроведением из модуля формы документа такой:
ЗапомнимПриЗаписиПерепроводить = ПриЗаписиПерепроводить(1);
Результат = Записать();//записывает и при необходимости перепроводит
ПриЗаписиПерепроводить(ЗапомнимПриЗаписиПерепроводить);В этом случае документ будет при необходимости перепроведён, а в случае неудачного перепроведения - запись не состоится. И, что замечательно, Записать() вернёт 0 в случае неудачного перепроводения, а не только в случае неудачной записи.
Наткнулся у себя на баг 1С, про который не слышал раньше: итог по колонке может быть у нечисловой колонки.
Воспроизведение:
- Создаем реквизит табличной части документа типа "Число" и ставим галку "Итог по колонке";
- Сохраняем конфигурацию;
- Меняем тип реквизита на какой-нибудь справочник;
- Сохраняем конфигурацию.
При втором сохранении получаем сообщение, что изменено построение итогов по колонке, в диалоговой форме реквизита галка "Итог по колонке" визуализирована сброшенной. Но - это не так: в описании структуры метаданных "ИтогПоКолонке" равен 1, а проблемный реквизит присутствует в заголовочной таблице документа DH*.DBF. То есть итоги продолжают "считаться".
Лечение: поменять что-нибудь (идентификатор) в реквизите и вернуть назад - при сохранении будет выполнена уже нормальная реструктуризация.
Код для проверки на наличие проблемных реквизитов:
Для СчДокументов = 1 По Метаданные.Документ() Цикл
МетаДок = Метаданные.Документ(СчДокументов);
Для СчРеквизитов = 1 По МетаДок.РеквизитТабличнойЧасти() Цикл
МетаРекв = МетаДок.РеквизитТабличнойЧасти(СчРеквизитов);
Если (МетаРекв.Тип <> "Число") и (МетаРекв.ИтогПоКолонке = 1) Тогда
Сообщить(МетаДок.Идентификатор + "." + МетаРекв.Идентификатор);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Мсье знает толк в извращениях!
Цитата: Злоп от 22 октября 2025, 13:46Мсье знает толк в извращениях!
Согласен. Описал так, как будто это было намеренное издевательство над конфигуратором и здравым смыслом. Но всё было наоборот, это 1С поиздевалось надо моим здравым смыслом:
Увидел опечатку в комментарии к реквизиту табличной части, ну типа "Поздразделение ЦФО" и решил поправить. При сохранении - сообщение "изменено построение итогов по колонке...". И меня стопарнуло: какой пересчет итогов, если у я лишь поменял Комментарий к реквизиту типа "Справочник.Подразделения"?!
Просто такие баги могут быть достаточно вредными, система тебе визуально показывает одно, а сама делает другое. Тратит ресурсы на сохранение и подсчет итогов, там где их отродясь не было и не будет.
Вот ещё одни вредный баг из этой же серии (показываю одно, делаю другое):
Думаю зачем мне две формы списка справочника "ФормаСпискаОсновная" и "ФормаСпискаДляВыбора"? Удаляю "ФормаСпискаДляВыбора", при этом галочка "основная форма для выбора" перескакивает на "ФормаСпискаОсновная". Сохраняюсь, всё отлично, теперь у меня единая форма для обоих режимов работы.
А вот и нет - "основная форма для выбора" не установлена и система рисует пользователям свою корявую форму "по умолчанию".
Ну а в целом изврат, правда. Просто иногда есть рабочее время и желание не работать. На днях чУдно провёл время разбираясь с багом, известным в основном, как "Перестал отображаться автор в общем журнале". Вылечить - 2 минуты, придумать отчетик, проверяющий базу на наличие проблемы - 2 часа, определить причину возникновения - 2 дня. Зато - кайф, раскрыл ещё один мало кому уже нужный секрет.
И почему перестал отображаться автор в ОЖ?
Я на ряд ошибок и граблей просто тупо не наступал. Просто потому что делал как надо, а как не надо - не делал...
Кстати, а итог-то по нечисловым колонкам считает? По идее тупо суммировать должен и варианта два: либо рухнет в ошибку, либо проссуммирует и получит 0 если содержимое чисто текстовое или какое о число если колонка содержит строковый реквизит, в котором строки типа
123
Петров.
.
А вот как суммирует если агрегатный тип - это интереснее: либо по преобразованию в текстовое представление либо тупо значение ссылки, а там вполне возможно число может быть в начале ссылки...?
Цитата: Злоп от 22 октября 2025, 17:35стати, а итог-то по нечисловым колонкам считает?
Похоже, что так же как и функция Итог() в локальном контексте документа - ставит ноль, если реквизит нечисловой, и считает сумму (кстати, независимо от галки "Итог по колонке" и длины числа). Т.е. для колонки "Мест" Число1.0 функция Итог("Мест") даст 5+5=10.
А вот .Итог() примененный к этому же документу, но полученному через СоздатьОбъект уже полезет в таблицу DH и вернет 5+5=9, либо ошибку, если галка "Итог по колонке" не установлена.
Цитата: Злоп от 22 октября 2025, 17:31...не наступал. Просто потому что делал как надо, а как не надо - не делал...
Враки. Иначе откуда бы ты узнал, как не надо ;) . Однажды наступив - долго обходишь стороной. Зачем разбираться с проблемой, если её можно обходить. Но, чтоб не получалось как в древнем баяне "Тут так принято" про обезьян, бананы и шланг с холодной водой, порой стоит вернуться и, при желании и наличии времени, разобраться: а что именно ты обходишь, надо ли это обходить, и каков радиус. Ну и интересно иногда походить по нехоженным дорожкам.
Ну и дополню: Итог() по таблице значений работает так:
Если тип значения колонки "Число" - суммирует независимо от заданной длины числа
Если тип значения не задан, то суммирует только если ВСЕ значения в колонке - явно заданные числа.
Во всех остальных случаях - ноль.
Функции - "ложные друзья программиста":
.ОбратныйПорядок() - без параметра.
Для справочника и документа - не делает ничего, постоянно наступаю на эти грабли;
Для периодического - устанавливает обратный порядок текущей (а если нет текущей - то последующей) выборки;
Для регистра - устанавливает обратный порядок последующей выборки.
ВыбратьДокументы(), ВыбратьЭлементы(), ВыбратьЗначения() - строят выборки и возвращают 0, если выборка пуста;
ВыбратьДвижения() - ничего не делает (ну только фиксирует флажки типа "ОбратныйПорядок"), всегда возвращает 1, даже если движений нет.
GComp. Может открою Америку, но как-то с легкой руки Фёдора всегда считал, что Container.Profile (https://1c.alterplast.ru/1cv7md/howto-less.html) - лишний мусор в мдшнике, ну типа формы элемента для справочников, редактируемого только "в списке".
Оказалось, что это установки по работе с таблицей из диалоговой формы отчета/обработки (ну и пароли при необходимости) и бездумно удалять их не надо.
Состав Container.Profile:
Действия - Свойства формы
MoxelName (Использовать таблицу):
Пустую - "␁Blank"
Для ввода данных - Имя таблицы
MoxelPos (Положение):
0 - во всё окно (по умолчанию)
2 - снизу
3 - сверху
4 - справа
5 - слева
MoxelNextMode (Для ввода данных - Переход по строкам):
0 - нет
1 - по строкам (по умолчанию)
2 - по столбцам
Действия - Установить пароль
UUID:
"D41D8CD98F00B204E9800998ECF8427E" - пароль не установлен
Любые другие значения - хэш пароля?
Entry (Запрашивать пароль при исполнении):
0 - не запрашивать
1 - запрашивать (по умолчанию)
Баг «Не показывается колонка общего реквизита в журналах» aka «Исчез автор в общем журнале»
Описание: В непонятное время по непонятным причинам у пользователей перестаёт отоборажаться колонка с общим реквизитом, в конфигураторе – всё чётко.
Лечение: Удалить проблемную колонку – Закрыть форму списка (ЭТО ВАЖНО) – Сохранить – Добавить колонку.
Код для проверки наличия проблемы (программно открываем и закрываем все журналы и смотрим: есть/нет?):
СписокДляПроверки = СоздатьОбъект("СписокЗначений");
Для СчЖурналов = 1 По Метаданные.Журнал() Цикл
МетаЖурнал = Метаданные.Журнал(СчЖурналов);
ИдЖурнала = МетаЖурнал.Идентификатор;
Для СчФорм = 1 По МетаЖурнал.ФормаСписка() Цикл
ИдФормы = МетаЖурнал.ФормаСписка(СчФорм).Идентификатор;
СписокДляПроверки.УдалитьВсе();
Для СчОбщихРеквизитов = 1 По Метаданные.ОбщийРеквизитДокумента() Цикл
СписокДляПроверки.ДобавитьЗначение(Метаданные.ОбщийРеквизитДокумента(СчОбщихРеквизитов).Идентификатор);
КонецЦикла;
Для СчГраф = 1 По МетаЖурнал.Графа() Цикл
СписокДляПроверки.ДобавитьЗначение(МетаЖурнал.Графа(СчГраф).Идентификатор);
КонецЦикла;
Конт = "";
ОткрытьФорму("Журнал."+ИдЖурнала+"."+ИдФормы+"#",Конт);
Если ТипЗначения(Конт) = 100 Тогда
Для Сч = 1 По СписокДляПроверки.РазмерСписка() Цикл
ИмяКолонки = СписокДляПроверки.ПолучитьЗначение(Сч);
Попытка
Конт.Форма.ПолучитьАтрибут(ИмяКолонки);
Исключение
Продолжить;
КонецПопытки;
Конт.Форма.ПолучитьАтрибут(ИмяКолонки).Видимость(1);
Конт.Активизировать(ИмяКолонки,1);
Если Конт.Форма.ТекущаяКолонка() <> ИмяКолонки Тогда
Сообщить("Проблема отображения: "+"Журнал."+ИдЖурнала+"."+ИдФормы+"."+ИмяКолонки);
КонецЕсли;
КонецЦикла;
Конт.Форма.Закрыть(0);
Конт="";
КонецЕсли;
КонецЦикла;
КонецЦикла;
Сообщить("Проверка завершена.");
Пространно: заморочка с этим глюком в том, что он появлялся как бы из ниоткуда и в неизвестный момент времени. Юзеры не знают, что в журнале должен быть этот столбец, а программист не знает, что его там не стало. Первый раз, когда столкнулся, списал на рудимент от 7.5, потому что конфа была типовая комплексная 3, в которой осталось 4 журнала, перекочевавших, видимо, через преобразование из 7.5 из первого релиза Комплексной. А недавно, с удивлением, обнаружил этот глюк в своей нетленке. Поэтому, взяв ежедневные бэкапы баз за 23 года, установил день, когда исчез столбец, и проанализировав два соседних мдшника, понял механизм возникновения глюка.
Исходная конфигурация (ИК), два параллельных прямых потомка (П1 и П2). В П1 добавляем любой объект. В П2 добавляем общий реквизит и выводим его в форму списка журнала. Загружаем в П1 через объединение конфигурации. Готово: в П1 битый журнал. В форме списка журнала в конфигураторе столбец виден, а в режиме «1С: Предприятие» не показывается.
Тестовый стенд в пустой пробной: создать документ, журнал, форму списка журнала, разделить на 2 потомка, в первом создать константу, во втором - общий реквизит документов и добавить его в форму списка журнала, накатить мдшник на первый потомок через объединение - баг проявился.
Если разложить проблемный мдшник, то в столбце в значении ИдентификаторМетаданных будет содержать мусорный id (а если «повезёт», то существующий, но от другого объекта).
С какого-то релиза разработчики о глюке узнали, но механизм его возникновения не поняли, и в момент открытия журнала стали просто делать проблемный столбец невидимым. А может и поняли, но по сумме характеристик, решили, что проще так, чем исправлять.
Возникновение глюка вполне укладывается в распространённый механизм обновления типовых, когда свои изменения (и в их числе, например, общий реквизит «Автор», которого так не хватало в типовой бухии) переносишь в новый релиз типовой через объединение, а потом накатываешь на рабочую базу.
То есть причина - в некорректной работе объедения конфигурации: когда замещаешь форму списка журнала документа, то ИдентификаторМетаданных не изменяется вслед за изменением Идентификатора исходного объекта (например, общего реквизита «Автор»), а остаётся как был в накатываемой конфигурации.
Лечение историческое: добрый Ёпрст gcompом(?) менял страждущим ИдентификаторМетаданных на правильный;
Лечение хирургическое: убрать столбец вообще: «вам это не надо»;
Лечение паллиативное: делать такие столбцы текстовыми;
Лечение правильное: в шапке. Но – зараза – если форму списка после удаления не закрыть, то столбец 1С вставит обратно проблемный - из кэша. Обо что многие и спотыкались. И это ещё одна, другая, багофича.
Вот этого не понял
ИдентификаторМетаданных не изменяется вслед за изменением Идентификатора исходного объекта (например, общего реквизита «Автор»), а остаётся как был в накатываемой конфигурации.
В П1 реквизита автор не было. В П2 - есть, общий реквизит, в П2 положили общий реквизит на журнал. Объединили с П1. Теперь в П1 столбец Автор в журнале в конфигураторе есть ИлентификаторМетаданных "автор" ?), но в базе в нем лежит кривой ид ?
Что за упомянутый "идентификатор исходного объекта"???
ИдентификаторМетаданных - это имя реквизита в конфиге или id в пользовательском режиме? Идентификатор исходного объекта - это в конфигураторе или id в пользовательском режиме?
По идее трабла не должно быть если в обновляемой конфиге (НА которую накатываем) в базе нет документов. По мере создания документов в уже обновленной базе - все должно быть ок
8000 копий для анализа и уйма времени - чтобы принести это бесполезное хрустальное знание :) Спасибо за интерес, без дураков.
Смотри, дело вообще не в данных. Дело в том, что в результате обычного объединения получается битый мдшник.
Возьми свою лучшую конфу, просто чистый мдшник, и разложи в две папки.
1) В конфе 1 добавь константу и сохрани.
2) В конфе 2 добавь общий реквизит документа и выведи его в колонку в любом журнале.
3) Накати на конфу 1 мдшник от конфы 2 стандартным объединением и сохрани.
А теперь "Джентльмены, подходим ближе: вот он есть (в конфигураторе ты колонку в журнале видишь) , а вот его нет (в режиме "1С: Предприятия" ты колонку не видишь).
Вообще у фокуса есть продолжение: если теперь удалить константу, и попробовать объединять конфигурации, то 1С будет говорить, что "Конфигурации идентичны". При этом конфа 1 будет битая (колонка пользователям не видна), а конфа 2 нормальная (колонка пользователям видна).
PS ИдентификаторМетаданных - это внутренний id реквизита в конфигураторе.
PS ИдентификаторМетаданных - это внутренний id реквизита в конфигураторе.
Лучше так:
ИдентификаторМетаданных - это внутренний id объекта метаданных в конфигурации.
ИдентификаторМетаданных не изменяется вслед за изменением Идентификатора исходного объекта (например, общего реквизита «Автор»), а остаётся как был в накатываемой конфигурации
.
Накатываемая конфигурация - п2.
Что такое Идентификатор исходного объекта? - это есть идентификатор метаданных общего реквизита "автор" в п2? В П2 все в порядке с мд, он небитый? "Идентификатормптаданных" - в твоем приложении - он где, в П1? Если он не меняется и остается как был в П2 - откуда в п1 битый мд?
Твое предложение для меня набор каких-то несвязных слов, который вообще не склеивается с описанием воспроизводства проблемы... Можешь это свое предложение перефразировать как-то по-другому, понятнее...?
Любой объект, который ты создаёшь в конфигурации получает внутренний id (идентификатор метаданных) - число от 1 и далее:
...
1 Задача
475 ОбщийРеквизитДокумента.Комментарий
66404 ОбщийРеквизитДокумента.новый1
476 ГрафаОтбора.Контрагент
471 Нумератор.АктОС1
472 Нумератор.ПриходныйОрдерМ4
58672 Нумератор.СчетаФактуры
12 Константа.ДатаРегистрации
13 Константа.НазваниеОрганизации
...
Упрощенно:
Пусть у тебя в исходной конфигурации 1000 объектов.
Когда ты создал в П1 константу (пусть "ОГРН")она получила id = 1001.
Когда ты создал в П2 общий реквизит документа (пусть "Автор") он тоже получит id = 1001
Когда ты накатываешь на П1 объединением конфигурацию П2, то id добавляемого общего реквизита уже занят (он присвоен константе ОГРН) и общий реквизит "Автор" получает новый id = 1002.
И вот тут упущение - в колонке журнала ссылка не изменяется (а должна!) и остается - id 1001. Т.е в колонке журнала вместо Автора будет выводится Константа.ОГРН. Но в качестве заплатки 1С в таком случае просто не показывает эту колонку вообще.
Ну это же проще 1 раз увидеть, чем 7 раз услышать. Поэтому
...возьми свою лучшую конфу, просто чистый мдшник, и разложи в две папки..
Или запустить код для проверки - возможно проблема обнаружится, тогда будет понятно как это выглядит.
Сразу бы так написать... ;-)
Цитата: amo|obs от 16 ноября 2025, 17:22Не добавляется в список значений значение неопределенного типа данных!
Действительно, ДобавитьЗначение и ВставитьЗначение ничего не делают с пустотой.
Но если очень хочется, то можно:
Список = СоздатьОбъект("СписокЗначений");
Список.ДобавитьЗначение("займём местчеко");
Список.УстановитьЗначение(Список.РазмерСписка,);
Сообщить(ЗначениеВСтрокуВнутр(Список));//список из одного пустого элемента
Недокументированное поведение метода СписокЗначений::Установить(<Строка>, <Знач>)
Если опустить параметр <Знач>, то:
если в списке есть элемент с представлением <Строка>, то он будет удален из списка
если в списке нет элемента с представлением <Строка>, то будет добавлено пустое значение с представлением <Строка>.
Код для иллюстрации:
Список = СоздатьОбъект("СписокЗначений");
Список.Установить("Процент",100);
Сообщить(Список.РазмерСписка()); //1 элемент - значение с представлением "Процент" - добавлено
Список.Установить("Процент");
Сообщить(Список.РазмерСписка()); //0 - значение с представлением "Процент" было найдено и удалено
Список.Установить("Процент");
Сообщить(Список.РазмерСписка()); //1 - значение с представлением "Процент" не было найдено и поэтому добавлено
СЗ неисчерпаем. Как атом.
Цитата: Харлампий Дымба от 10 декабря 2025, 15:35Но если очень хочется, то можно:
Интересно, что даст ПустоеЗначение(Список)
;-)
Фичи с СЗ - перенес в Копилку
Битый час пытался воткнуть, что сломалось в Отладчике - оказалось багофича 1с:
Отладчик не видит локальные переменные глобального модуля в глобальных процедурах и функциях, вызванных из других мест.
При попытке вычислить выражение даёт ошибку типа:
"ЛокальнаяПеременнаяГлобальногоМодуля = Ошибка в выражении!"
При этом всё нормально работает, переменная имеет значение. Но вот Отладчик её отказывается показывать.
Чтоб было понятнее - глобальный модуль такой:
Перем ЛокальнаяПеременнаяГлобальногоМодуля;
Процедура Проверка() Экспорт
ЛокальнаяПеременнаяГлобальногоМодуля = 1;
КонецПроцедуры
ЛокальнаяПеременнаяГлобальногоМодуля = 0;
Вызов из обработки такой:
Процедура Сформировать()
Проверка()
КонецПроцедуры
Похожая фишка, насколько помню, есть и объекта "Запрос", но вот на такой каприз Отладчика до сего дня не натыкался.
Ещё одна багофича 1С, связанная с функциями УчетПоКоличеству() и УчетПоВалютнойСумме() - флаги учета по "По количеству" и "По сумме" по указанному виду субконто:
КолУчетПоСубконто1...3 = СчетПоКоду("26").УчетПоКоличеству(1...3);// = 1, хотя количественного учета по аналитике сч.26 отродясь не было
ВалУчетПоСубконто1...3 = СчетПоКоду("26").УчетПоВалютнойСумме(1....3);// = 1, хотя валютного учета по аналитике сч.26 отродясь не было
Это происходит потому, что 1Ска ленится скидывать неиспользуемые флаги при редактировании метаданных (такое много где встречается и приводит к разным багам). Типа если по счету в целом нет количественного учета, то неважно состояние флагов "Учет по количеству" для всех субконто этого счета, поэтому не будем с ними ничего делать и оставим их как были. Пользователю эти флаги видны как неустановленные и недоступны для редактирования, при этом на самом деле флаги установлены. Можно в любой типовой конфе с планом счетом убедиться, что по неколичественным счетам у субконто флаг снят (т.е. "НЕТ"), но при выводе "Описания структуры метаданных" для всех субконто счета значение реквизита "УчетПоКоличеству" будет равно "ЕСТЬ". С валютой аналогично.
Так что правильное использование этих функций - с использованием атрибутов счета "Количественный" и "Валютный":
КолУчетПоСубконто1...3 = ?(Счет.Количественный = 0, 0, Счет.УчетПоКоличеству(1...3));
ВалУчетПоСубконто1....3 = ?(Счет.Валютный = 0, 0, Счет.УчетПоВалютнойСумме(1...3));
Можно было бы назвать это не багом, а особенностью - так как в описании функции именно такое поведение функций и задекларировано: "Функция возвращает значение флага ...".
Но во-первых даже в вылизанной за десятилетия ОСВ по счету в типовой бухии есть именно эта ошибка - использование функции "УчетПоКоличеству" без оглядки на сам счёт. Ошибка незначительная по последствимя - из-за неё выводятся лишние пустые секции в печатной форме, но всё же.
А во-вторых возможно, что и в других местах 1С будет смотреть на флаг по субконто, игнорируя флаг по счету.
Не знаю как лучше классифицировать этот баг 1С, долго ловил и, думаю, поймал.
При некоторых условиях использование "Окна-Закрыть все окна" приводило к появлению окошка "Ошибка при выполнении модуля! Закрыть?" и последующему падению 1С независимо от ответа пользователя.
Проблема возникает, если выполняются следующие условия:
1. Открыта форма подбора;
2. В форме подбора установлен флаг множественного выбора;
3. В форме подбора установлен флаг выбора групп и справочник многоуровневый;
4. Форма подбора находится на заднем плане относительно вызвавшой формы;
5. Пользователь выбирает пункт меню "Окна - Закрыть все окна".
Если любой из этих пунктов убрать - всё гладко.
Воспроизведение бага: в типовой пустой ТиС открыть отчет "Остатки ТМЦ", на закладке "Множественный фильтр" при выбранном фильтре "По номенклатуре" щелкнуть на кнопку добавления нескольких элементов в список - "......", ткнуть обратно в исходную форму отчета "Остатки ТМЦ". Теперь "Окна - Закрыть все окна" уронит 1С.
Можно поиграться с другими отчетами и фильтрами, чтобы увидеть разницу поведения из-за п.3.
Это не баг, а извращение ;-)
Держать форму подбора, да еще на заднем плане и при этом закрыть все окна - мусье знает толк... ;-)
Однако сколько времени потратилось чтобы воспроизвести...
Цитата: Злоп от 01 ноября 2026, 23:04мусье знает толк
Воу-воу, стопэ! :)
Абсолютно типовой сценарий обычной быстрой работы:
Открыл любой отчет, подобрал несколько групп товаров или контрагентов, сразу ткнул "Сформировать" (незакрытая форма подбора отъехала на задний план), при последующей работе понаоткрывал ещё кучу других форм - отчеты, документы и т.д. и закрыл все окна одной командой - 1С упала.
Нет, я верю, что:
1. большинство пользователей будут добавлять элементы через форму одиночного подбора - именно она откроется если ткнуть в название отбора ("По номенклатуре", например)
и
2. большинство пользователей обязательно закроют крестиком форму множественного подбора после последнего выбора
и
3. большинство пользователей будут крестиками закрывать все открытые окна, вместо того чтобы чохом закрыть.
и
именно поэтому большинство пользователей с этой ошибкой никогда не встретятся.
Но баг есть, и довольно бесячий - если использовать "Окна-Закрыть все окна" и формы подбора, то будешь натыкаться на него регулярно.
Тут, помнится, Владислав искал причины падения 1С у пользователей ни с того ни с сего - вполне себе вариант.
Еще если помните - почему UCHOICE падал с закрытием 1С при задании даты в условие отбора?
Цитата: Харлампий Дымба от 01 ноября 2026, 02:07Не знаю как лучше классифицировать этот баг 1С
Что тут не понятного?
Эта форма подбора работает в специфическом режиме. ПриЗакрытии() отрабатывает процедуру переноса ТЗ подобранного в форму из которой вызван подбор. Если открыты оба окна (и сама форма и подбор), то Окна-Закрыть все окна сначала закрывает "родительскую" форму, вызвавшую подбор, а потом саму форму подбора, которая при закрытии пытается заполнить реквизиты "родительской" формы и неожиданно "обнаруживает", что "родительская" форма уже отсутствует и система валится, пытаясь заполнить не существующий реквизит не существующей формы.
Цитата: cr от 02 ноября 2026, 09:05Что тут не понятного?
В точку. Именно так я и думал, и именно так же ошибся. Поэтому и не мог долгое время надежно воспроизвести глюк - он то появлялся, то исчезал. Так что - очень правдоподобно, но нет. Механизм проявления сложнее, поэтому и причина возникновения для меня теперь не столь очевидна.
Я же написал - для складов и фирм глюк не возникает, а для товаров и контрагентов - возникает. И ключевое различие там - п.3
Цитата: Злоп от 02 ноября 2026, 06:45почему UCHOICE падал с закрытием 1С при задании даты в условие отбора
Не увидел. Как воспроизвести? Попробовал из типовой обработку "ПодборОбъектов" (полный аналог UChoice), сделал подбор по документам с отбором по нескольким датам - всё нормально прошло.
Но вангую, что если ошибка есть, то она скорее всего связана с некорректным синтаксисом построенного запроса (там же UChoice пытается данные именно с помощью черного запроса получить. Мы разбирались здесь (https://forum.dorex.pro/index.php?topic=268.0) с подобной ерундой, возможно и с датой похожее.
Цитата: cr от 02 ноября 2026, 09:05Цитата: Харлампий Дымба от 01 ноября 2026, 02:07Не знаю как лучше классифицировать этот баг 1С
Что тут не понятного?
Эта форма подбора работает в специфическом режиме. ПриЗакрытии() отрабатывает процедуру переноса ТЗ подобранного в форму из которой вызван подбор. Если открыты оба окна (и сама форма и подбор), то Окна-Закрыть все окна сначала закрывает "родительскую" форму, вызвавшую подбор, а потом саму форму подбора, которая при закрытии пытается заполнить реквизиты "родительской" формы и неожиданно "обнаруживает", что "родительская" форма уже отсутствует и система валится, пытаясь заполнить не существующий реквизит не существующей формы.
Здесь при переносе надо видимо сделать просто проверку существования родительского контекста...
Цитата: Злоп от 02 ноября 2026, 06:45Еще если помните - почему UCHOICE падал с закрытием 1С при задании даты в условие отбора?
Не, тут падает не всегда... Как-то выборочно\специфически тоже...
Цитата: Злоп от 03 ноября 2026, 03:45надо видимо сделать просто проверку существования родительского контекста.
Да, не чего-то не получается ничего. Ну то есть интересно придумать латку, чтоб избегать такой ситуации, но пока у меня решения нет.
Кстати, выяснилась ещё одна деталь - обязательное условие:
п.6 в форме подбора должна быть процедура ПриЗакрытии()
на ней и валится. Пустая она или там есть код не важно - валится от её наличия. Если этой процедуры нет, то падения не происходит. Всё чудесатее и чудесатее.
Чё как дети?
Есть 2 способа организации подбора. Обычный и специальный.
Можно просто ОткрытьПодбор() и здесь же (в "родительской" форме) в предопределенной процедуре ОбработкаПодбора() задать действия с выбранной строкой из списка подбора. Так чаще всего и делается, при этом если режим НЕполноэкранный и сделать видимыми в окне обе формы (и "родительскую" и форму списка), видно как при выборе строки в форме подбора, она сразу "попадает" в "родительскую" форму. В каком порядке эти формы будут закрываться - по барабану.
А можно иначе. Если в форме подбора в ПриОткрытии() установить ОбработкаВыбораСтроки() в 1, ОбработкаПодбора() в "родительской" форме срабатывать не будет, зато в форме подбора начнет срабатывать предопределенная процедура ПриВыбореСтроки(), в которой и задаются действия с выбранной строкой. В этом варианте подобранные значения из формы подбора автоматически "отправляются" в "родительскую" форму из ПриЗакрытии() (- а как еще-то?). 1С валится из ПриЗакрытии() формы подбора, когда совершает там недопустимую операцию с закрытой "родительской" формой.
для начала надо выяснить валится на ПриЗакрытии() - на каком этапе? вход в процедуру успешен, валится на завершении? или как? если выяснится что вход в ПриЗакрытии успешен - то дальше можно пытаться играться с контекстом родительской формы, которую передавать через параметры при вызове подбора
Цитата: cr от 03 ноября 2026, 19:49Чё как дети?
Не, ОбработкаВыбораСтроки() тут тоже не причём.
Но и у меня чё-то поплыли все рассуждения тоже. Многоуровневость оказывается не обязательна, проблема возникает если форму подбора дернуть из родительской формы после ОткрытьПодбор() по любому поводу, а в форме подбора (обычная форма списка справочника) есть процедура ПриЗакрытии.
Стенд:
Справочник.Новый1 - все установки по умолчанию, форма списка со следующим модулем:
Процедура ПриЗакрытии() //если нет этой процедуры - ошибки не будет
//код есть или кода нет - не важно
КонецПроцедурыОтчет.Новый1 - все установки по умолчанию, модуль формы:
Процедура Сформировать()
Перем ФормаПодбора;
ОткрытьПодбор("Справочник.Новый1",,ФормаПодбора,1);//если 0 - ошибки не будет
ФормаПодбора.Сортировка("Код"); //если нет обращения к форме - ошибки не будет
КонецПроцедурыЗапускаем Отчет.Новый1, нажимаем Сформировать, выводим форму отчета на передний план, Окна-Закрыть все, падаем.
Цитата: Злоп от 03 ноября 2026, 21:57если выяснится что вход в ПриЗакрытии успешен - то дальше можно пытаться играться с контекстом родительской формы
Вход-то успешен, только вот родительской формы уже не существует, так что играться не с чем и мы в любом случае свалимся в ошибку. Есть вариант избежать, но абсолютно некрасивый.
Если в форме подбора есть ПриЗакрытии(), то после захода в неё, курсор вернется обратно в "родительскую" форму (скорее всего, на строку "родительской" формы следующую после ОткрытьПодбор(), но может, еще куда-то, ПриПовторномОткрытии(), например), а если "родительской" формы уже нет, курсору некуда вернуться и он роняет 1С.
Отладчик в руки и вперед ...
Цитата: cr от Вчера в 00:20Отладчик в руки и вперед
Сообщением выше - тестовый стенд. Там ровно 8 строчек на 2 модуля, из них только две строчки выполняют инструкцию. В какую строку нужно поставить точку останова и какой параметр отследить? Да и как это поможет?
Ежу понятно, что корень зла в том, что дочерняя форма закрывается позже родительской. Но ведь вся соль в том, что это только
одно из пяти условий. Если любое из остальных четырех не выполнено - никакой ошибки нет, дочерняя форма спокойно закрывается при несуществующей уже родительской.
Универсальная заглушка на ошибку - с помощью Formex + недокументированного КонтекстПодбора:
Процедура Глобальная_ПриЗакрытии(Конт)
Если ТипЗначения(Конт.КонтекстПодбора) = 100 Тогда // может быть стоит обернуть в Попытку
Если Конт.КонтекстПодбора.Форма.РежимВыбора() = 2 Тогда
СтатусВозврата(0);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Цитата: Харлампий Дымба от Вчера в 22:14В какую строку нужно поставить точку останова
Да, ёклмн!
Конечно в строку
еклмн=1;
в ПриЗакрытии() в форме побора.
Затем руками закрываешь форму подбора и по F8 смотришь куда она (когда не падает) пойдет после ПриЗакрытия()
В "родительской" форме тоже нужно создать всякие предопределенные процедуры с заглушками
а=1;
И тогда в том месте, куда она уходит в "родительской" форме можно поставить ловушку из переменной, объявленной в "родительской" форме:
Перем КонтекстФормы;
Процедура Сформировать()
ОткрытьПодбор(<Объект>,<ИмяФормы>,КонтекстФормы,<ФлагМножВыбора>,<ТекЗнач>):
а=1;
// ОткрытьПодбор("Справочник.Новый1",,ФормаПодбора,1);//если 0 - ошибки не будет
// ФормаПодбора.Сортировка("Код"); //если нет обращения к форме - ошибки не будет
КонецПроцедуры
Процедура ПриЗакрытии()
Если 0+ТипЗначения(КонтекстФормы) = 100 Тогда
СтатусВозврата(0);
КонецЕсли;
КонецПроцедуры
Чтобы при первой попытке Окна - закрыть все , форма подбора закрылась, а "родительская" форма осталась открытой. И ничего не упадет. Со второй попытки Окна - закрыть все, "родительская форма тоже закроется без падения.
Все пункты с условиями - в топку! Они не при делах. Все формексы, попытки-исключения и недокументированные возможности - туда же, куда и условия.
Цитата: cr от Сегодня в 00:02смотришь куда она (когда не падает) пойдет после ПриЗакрытия()
НИКУДА. Зачем 3 раза отправлять меня в Отладчик, если можно убедиться, что там нечего ловить?
Цитата: cr от Сегодня в 00:02Чтобы при первой попытке Окна - закрыть все , форма подбора закрылась, а "родительская" форма осталась открытой
Цитата: Харлампий Дымба от 03 ноября 2026, 23:40Есть вариант избежать, но абсолютно некрасивый.
Вот именно этот вариант со СтатусомВозврата(0) в ПриЗакрытии родительской формы мне и не понравился, поэтому и приводить не стал.
Не понравился по многим причинам:
Ты не закроешь родительскую форму обычным способом, если открыта дочерняя (крестиком, кнопкой Закрыть, Окна-Закрыть). Надо будет обязательно закрыть дочернюю, хотя раньше этого не требовалось - это неудобно.
То же самое касается и всех других вариантов открытия дочерней формы: в режиме одиночного подбора, без обращения к контексту дочерней формы.
Пользователь может спокойно ткнуть в несколько подборов в одном отчете в той же типовой ТиС (склад, номенклатура), а "Перем ФормаПодбора" на всех одна.
В той же типовой ТиС вызов идёт в глобальной процедуре - там ещё больше вариантов налететь на протухшую переменную.
И самое главное: этот код надо вставлять в ПриЗакрытии() во все модули, где есть ОткрытьПодбор(), а в случае типовой ТиС - всюду, где возможен вызов глРаботаСТаблицейМФ - т.е. во все отчеты.
Ну собственно первое и последнее - определяющее.
С другой стороны, использование ванильной 1С - это плюсик.
Условия возникновения глюка перечислены, заглушки придуманы.
Механизм возникновения сам больше ковырять не буду - знаний не хватает.