Обсуждение накопленного

Автор Харлампий Дымба, 14 октября 2025, 01:31

« назад - далее »

Харлампий Дымба

Вот Сергей копит в копилку, а обсуждать там не разрешает.  Пусть будет тема для небольшого полуфлуда - обо всём и ни о чём. Шепотом.
Не только для копилки - потому что иногда натыкаешься на какую-нибудь интересную неожиданную ерунду, забавный пустяк, а может кому пригодится.

Вот про то, что Записать недокументировано возвращает значение, если применяется к элементу / документу локального контекста (а не созданному через СоздатьОбъект), оказалось интересно. Даже никогда не задумывался, что будет, если не заморачиваться с
Если Форма.ТолькоПросмотр() = 1 Тогда
 Форма.КнопкаОК.Доступность(0);
КонецЕсли;
А оказалось, что ничего не будет. Если форма открыта в режиме чтения (только на просмотр), то и Записать() и #Записать будут проигнорированы.  Так что использование Доступность(0) - просто способ показать пользователю, что нажимать кнопку бесполезно.

Ну и кстати #Записать и Записать() неравнозначны, вопреки тому что написано в als (там так: "данный метод отрабатывает те же действия, что и интерактивное нажатие пользователем кнопки с формулой ''#Записать''")
Записать() не вызывает ПриЗаписи() и игнорирует некоторые установки записи, типа СохранениеПериодическихРеквизитов(). Но вот ПриЗаписиПерепроводить(1) и АвтоВремя..(), а также регистрацию события в "Журнале регистрации" оба варианта отрабатывают одинаково. Ещё раз акцентирую, что Записать() - именно в локальном контексте, а не к созданному через СоздатьОбъект().

Записать() возвращает ноль не только, если форма открыта в режиме чтения, но и при нарушении уникальности кода. Правда, в этом случае всё равно выдаётся интерактивное окошко предупреждения "Код не уникальный", поэтому использовать Записать() для программной проверки возможности записи - не очень хорошо.

Харлампий Дымба

Написал, перечитал, задумался. Если ПриЗаписиПерепроводить(1) действует на Записать() локального контекста, то, значит я всё это время неправильно делал запись с перепроводением из формы документа:
Записать();
Если Проведен() = 1 Тогда
 Провести();
КонецЕсли;
В этом коде две проблемы:
1) двойное перепроведение, если ПриЗаписиПерепроводить() было установлено в единичку;
2) надо городить огород с единой транзакцией, чтобы не получилось, что реквизиты в документ записаны новые, а проведение документа, в случае неудачи, осталось по старым.
Подобную реализацию можно увидеть в процедуре ПечатьЧека() в ПКО и РКО в типовой Тис, например.

Правильный код для записи с перепроведением из модуля формы документа такой:
ЗапомнимПриЗаписиПерепроводить = ПриЗаписиПерепроводить(1);
Результат = Записать();//записывает и при необходимости перепроводит
ПриЗаписиПерепроводить(ЗапомнимПриЗаписиПерепроводить);
В этом случае документ будет при необходимости перепроведён, а в случае неудачного перепроведения - запись не состоится. И, что замечательно, Записать() вернёт 0 в случае неудачного перепроводения, а не только в случае неудачной записи.

Харлампий Дымба

Наткнулся у себя на баг 1С, про который не слышал раньше: итог по колонке может быть у нечисловой колонки.
Воспроизведение:
  • Создаем реквизит табличной части документа типа "Число" и ставим галку "Итог по колонке";
  • Сохраняем конфигурацию;
  • Меняем тип реквизита на какой-нибудь справочник;
  • Сохраняем конфигурацию.
При втором сохранении получаем сообщение, что изменено построение итогов по колонке, в диалоговой форме реквизита галка "Итог по колонке" визуализирована сброшенной. Но - это не так: в описании структуры метаданных "ИтогПоКолонке" равен 1, а проблемный реквизит присутствует в заголовочной таблице документа DH*.DBF. То есть итоги продолжают "считаться".

Лечение: поменять что-нибудь (идентификатор) в реквизите и вернуть назад - при сохранении будет выполнена уже нормальная реструктуризация.

Код для проверки на наличие проблемных реквизитов:
Для СчДокументов = 1 По Метаданные.Документ() Цикл
    МетаДок = Метаданные.Документ(СчДокументов);
    Для СчРеквизитов = 1 По МетаДок.РеквизитТабличнойЧасти() Цикл
        МетаРекв = МетаДок.РеквизитТабличнойЧасти(СчРеквизитов);
        Если (МетаРекв.Тип <> "Число") и (МетаРекв.ИтогПоКолонке = 1) Тогда
            Сообщить(МетаДок.Идентификатор + "." + МетаРекв.Идентификатор);
        КонецЕсли;
    КонецЦикла;
КонецЦикла;
   

Злоп

Мсье знает толк в извращениях!

Харлампий Дымба

Цитата: Злоп от Вчера в 13:46Мсье знает толк в извращениях!
Согласен. Описал так, как будто это было намеренное издевательство над конфигуратором и здравым смыслом. Но всё было наоборот, это 1С поиздевалось надо моим здравым смыслом:
Увидел опечатку в комментарии к реквизиту табличной части, ну типа "Поздразделение ЦФО" и решил поправить. При сохранении - сообщение "изменено построение итогов по колонке...". И меня стопарнуло: какой пересчет итогов, если у я лишь поменял Комментарий к реквизиту типа "Справочник.Подразделения"?!
Просто такие баги могут быть достаточно вредными, система тебе визуально показывает одно, а сама делает другое. Тратит ресурсы на сохранение и подсчет итогов, там где их отродясь не было и не будет.

Вот ещё одни вредный баг из этой же серии (показываю одно, делаю другое):
Думаю зачем мне две формы списка справочника "ФормаСпискаОсновная" и "ФормаСпискаДляВыбора"? Удаляю "ФормаСпискаДляВыбора", при этом галочка "основная форма для выбора" перескакивает на "ФормаСпискаОсновная". Сохраняюсь, всё отлично, теперь у меня единая форма для обоих режимов работы.
А вот и нет - "основная форма для выбора" не установлена и система рисует пользователям свою корявую форму "по умолчанию".

Ну а в целом изврат, правда. Просто иногда есть рабочее время и желание не работать. На днях чУдно провёл время разбираясь с багом, известным в основном, как "Перестал отображаться автор в общем журнале". Вылечить - 2 минуты, придумать отчетик, проверяющий базу на наличие проблемы - 2 часа, определить причину возникновения - 2 дня. Зато - кайф, раскрыл ещё один мало кому уже нужный секрет.

Злоп

И почему перестал отображаться автор в ОЖ?

Злоп

Я на ряд ошибок и граблей просто тупо не наступал. Просто потому что делал как надо, а как не надо - не делал...

Злоп

Кстати, а итог-то по нечисловым колонкам считает? По идее тупо суммировать должен и варианта два: либо рухнет в ошибку, либо проссуммирует и получит 0 если содержимое чисто текстовое или какое о число если колонка содержит строковый реквизит, в котором строки типа
123
Петров.
.
А вот как суммирует если агрегатный тип - это интереснее: либо по преобразованию в текстовое представление либо тупо значение ссылки, а там вполне возможно число может быть в начале ссылки...?

Харлампий Дымба

Цитата: Злоп от Вчера в 17:35стати, а итог-то по нечисловым колонкам считает?
Похоже, что так же как и функция Итог() в локальном контексте документа - ставит ноль, если реквизит нечисловой, и считает сумму (кстати, независимо от галки "Итог по колонке" и длины числа). Т.е. для колонки "Мест" Число1.0 функция Итог("Мест") даст 5+5=10.
А вот .Итог() примененный к этому же документу, но полученному через СоздатьОбъект уже полезет в таблицу DH и вернет 5+5=9, либо ошибку, если галка "Итог по колонке" не установлена.

Цитата: Злоп от Вчера в 17:31...не наступал. Просто потому что делал как надо, а как не надо - не делал...
Враки. Иначе откуда бы ты узнал, как не надо ;) . Однажды наступив - долго обходишь стороной. Зачем разбираться с проблемой, если её можно обходить. Но, чтоб не получалось как в древнем баяне "Тут так принято" про обезьян, бананы и шланг с холодной водой, порой стоит вернуться и, при желании и наличии времени, разобраться: а что именно ты обходишь, надо ли это обходить, и каков радиус. Ну и интересно иногда походить по нехоженным дорожкам.


Харлампий Дымба

Ну и дополню: Итог() по таблице значений работает так:
Если тип значения колонки "Число" - суммирует независимо от заданной длины числа
Если тип значения не задан, то суммирует только если ВСЕ значения в колонке - явно заданные числа.
Во всех остальных случаях - ноль.