Особенность встроенной функции Представление() в СКД [поход на грабли]

15.01.19

Разработка - СКД

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

Скачать исходный код

Наименование Файл Версия Размер
Отчет для демонстраций ошибки Представления()
.erf 5,79Kb
0
.erf 5,79Kb Скачать

В "1С:Бухгалтерии 8" одного из клиентов обнаружил невозможность сформировать стандартный отчет "Карточка счета" по некоторым счетам (чуть позже похожее поведение нашел еще в "Карточке субконто" и в "Отчете по проводкам"). Из-за данной периодически возникающей ошибки бухгалтера для работы стали использовать другую версию этого отчета из более ранних редакций конфигурации (когда еще до появления СКД применяли объект "Построитель отчета"). А вообще, если не считать эту тянувшуюся несколько лет ошибку, то в целом в работе системы их больше ничего не беспокоило. 

В конфигурации была включена возможность внесения изменений и моими предшественниками были выполнены некоторые доработки под процессы компании. Но, к моему удивлению, конкретно бухгалтерская отчетность не модифицировалась. Что это - "особенные" настройки? Или результат "кривого" ручного обновления? Неужели ошибка типового функционала, которую за много лет никто не обнаружил?

 

Поиск причины ошибки

Первое допущение: мои предшественники намудрили с RLS из-за чего возникла ошибка в типовом функционале. Но под полными правами проблема то же воспроизвелась - при попытке сформировать отчет получаю странную картинку с частично сформированной таблицей результата в "поломанном" оформлением и сообщение:

Отчет не сформирован!
Неверные параметры "+"


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

ПроцессорВывода.Вывести(ПроцессорКомпоновки, Истина);

Именно во время выполнения обвернутого в попытку встроенного метода платформы и генерировалось исключение про неверный параметр плюса, который далее перехватывался в блоке обработки исключения и показывался пользователю. Следовательно теперь в поисках причины заинтересовавшей меня ошибки нужно идти в описание схемы компоновки.

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

Вариант с ошибкой в запросе был маловероятным. Но я на всякий случай скопировал запрос в консоль запросов, повторил значения параметров и получил все данные периода. Включая те строки, с которыми система компоновки почему-то не смогла справится. Их анализ чуть позже подсказал причину проблемы и ее решение. Итак, поскольку с источником данных для запроса все было в порядке, то ошибку следует искать при пост-обработке в процессе вывода в макет.

Четвертой догадкой стала: проблема с формулами вычисляемых полей. В данном разделе были описано одиннадцать расчетных полей, в трех из которых содержались операции по конкатенации строк с помощью оператора "+". Это были формирование представления документа, а так же описания аналитик по Дебету и Кредиту. Выглядят они во всех типовых (и отраслевых) конфигурациях следующим образом:

 
 Представление документа
Представление(Регистратор) + &ПС + Содержание
 
Текст для аналитики Дебита
Выбор Когда ((НалоговоеНазначениеДт Есть NULL) ИЛИ ( НалоговоеНазначениеДт=Значение(Справочник.НалоговыеНазначенияАктивовИЗатрат.ПустаяСсылка))) Тогда ""
Иначе Выбор Когда Не ЗначениеЗаполнено(Представление(НалоговоеНазначениеДт)) Тогда "<...>"+ &ПС Иначе Представление(НалоговоеНазначениеДт)+ &ПС Конец
Конец
+
Выбор Когда СубконтоДт1 Есть NULL Тогда ""
Иначе Выбор Когда Не ЗначениеЗаполнено(Представление(СубконтоДт1)) Тогда "<...>"+ &ПС Иначе Представление(СубконтоДт1)+ &ПС Конец
Конец
+
Выбор Когда СубконтоДт2 Есть NULL Тогда ""
Иначе Выбор Когда Не ЗначениеЗаполнено(Представление(СубконтоДт2)) Тогда "<...>" Иначе Представление(СубконтоДт2)+ &ПС Конец
Конец
+
Выбор Когда СубконтоДт3 Есть NULL Тогда ""
Иначе Выбор Когда Не ЗначениеЗаполнено(Представление(СубконтоДт3)) Тогда "<...>" Иначе Представление(СубконтоДт3) Конец
Конец
 
 Текст для аналитики Кредита

С представлением документа все нормально - все три операнда в данном уравнении всегда являются строками (согласно текста запроса и явно инициированного переносом строки параметра &ПС) и потому не могут быть причиной ошибки. Проверил суждение практикой и заменил формулу на пустую строку - отчет ожидаемо не сформировался до конца.

Строки с описанием аналитик тоже внешне выглядят "правильными". Конечно, смущает что при наличии проверок на заполненность и обладая знанием, что первое или второе субконто могут являются Null-ами (признак отсутствия аналитики на счете), все равно тратится время на анализ последующих субконто.  Еще бросается в глаза, что для второго субконто (как для Дебета, так и для Кредита) перенос строки добавляют лишь после имеющих значение представлений, а после строки "<...>" про перенос забыли. (Кстати, из любопытства проверил последнюю ERP - там точно так же забыт этот несчастный перенос строки. Видимо типовые бухгалтерские отчеты как написали лет 10 назад, так больше ни разу и не трогали.) Но после заполнения полей аналитик пустыми строками, отчет наконец-то успешно сформировался. Следовательно не все параметры имеют тип строки. Единственным подозреваемым остается результат функции Представление().

 

Исправление ошибки

Ошибку тут же исправил заключив результаты вызова функций Представление() в функции Строка().

Заодно не удержался от прочих исправлений - вернул потерянные переносы строк, а выводы второго и третьего субконто перенес в ветки ИНАЧЕ их предшественников.

 

Что бы я изменил в стандартных бухгалтерских отчетах?

Я сделал быстрое исправление, которое "починило отчет" и обрадовало бухгалтеров, которые теперь снова смогут пользоваться стандартной СКД-отчетностью. Но будь я разработчиком типовых, то исправление носило бы более глобальный характер.

Мне сразу не понравилась бездумная конкатенация в описании вычисляемых полей. Если учитывать каждое генерируемое представление, то получаем от 9 до 14 операций конкатенации на КАЖДУЮ выводимую строку отчета. Как я уже упоминал в другой своей статье, операции по сложению строк не являются дешевыми. По факту каждый раз в памяти создается новая строка, в которую копируются две предшественницы. Чем больше участников в операции "сложения", тем больше будет создано и затем уничтожено промежуточных строк. (Теперь вы понимаете почему квартальные и годовые отчеты нужно так долго ждать?)

Тут оптимальным решением я вижу для обслуживания отчетов создание общего модуля со включенной опцией повторно использования возвращаемых значений. В таком общем модуле требуется реализовать все требуемые функции с быстрой конкатенации требуемых представлений (на мою устаревшую статью не смотрите - сейчас для быстрого сложения строк существует функция СтрСоединить()). А в схеме компоновки можно просто вызывать эти новые функции. Думаю, что получился бы довольно приличный прирост скорости на больших объемах информации.

 

Так что же привело к ошибке?

Остался вопрос: что же было такого необычного в той строке отчета, которая "ломала" СКД?

Анализ показал, что это была корреспонденция анализируемого счета со счетом затрат будущего периода, куда было добавлено второе субконто "Период" с типом Дата. Полагаю, что данное субконто добавили мои предшественники-разработчики по просьбе бухгалтеров, которым для контроля было неудобно использовать строковые представления дат, с которыми в отличии от настоящих дат нельзя ни отборы применить, ни условным оформление воспользоваться.

Этот же факт объясняет почему экземпляр данного отчета, который успешно работает в сотнях тысяч инсталяций типовых и отраслевых решений по всему СНГ, у моих клиентов внезапно сломался. Дело в том, что разработчики типовых в плане видов характеристик ВидыСубконтоХозрасчетные стандартно разрешили только ссылочные типы и ни одного из примитивных! Если кому-то нужны даты, (видимо думали они) то пусть заводят их строковые представления в справочнике Субконто. Хотя несколько лет применения такого субконто показало, что вообще никаких негативных последствий для системы это не несет.

 

Особенности функции Представление()

Почему же функция Представление() не вернула строку? Без чтения документации тут некуда.

Согласно данным справочной информации эта функция существует самостоятельно в контексте (а не как метод объекта) лишь в двух местах - в языке запросов и как встроенная функция системы компоновки данных. 

Давайте освежим знания по языку запросов и посмотрим статью во встроенной документации платформы:

Функция ПРЕДСТАВЛЕНИЕ 
Данная функция предназначена для получения строкового представления значения произвольного типа.
Параметр функции – выражение любого типа.
Возвращаемое значение – представление значения, тип СТРОКА.
Результат работы функции не может быть использован внутри других функций, за исключением функции ПРЕДСТАВЛЕНИЕ.

Далее обратимся на ИТС, где поиском я нашел лишь одну релевантную статью на эту тему: Особенности работы с полем Представление и функцией Представление() языка запросов из раздела "1С:Предприятия 8. Разработка и администрирование":

Функция Представление()
Функция представление предназначена для получения текстового представления любого значения, которое может быть получено при помощи языка запросов. Функция Представление() работает как для ссылочных, так и для примитивных типов. Для ссылочных типов результат функции полностью аналогичен получению поля "Представление" от ссылки, переданной в качестве параметра функции. Для примитивных типов, результатом работы функции является строка, в которую было преобразовано значение, переданное в качестве параметра. Особенностью данной функции является то, что ее результат не может быть использован в выражении.

Таким образом в двух источниках видим практически одно и тоже, но разными словами: результат всегда строка и результат нельзя использовать в выражениях.

Теперь обратимся к реализации в функциях СКД и посмотрим статью "Функции языка выражений системы компоновки данных" из встроенной справки платформы (на ИТС аналогично):

Представление  (Resentation)
Данная функция возвращает строковое представление переданного значения не примитивного типа. Для значений примитивного типа возвращает само значение.

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

 

А нет ли ошибок еще и в платформе?

Но перепроверяя данные из документации я обнаружил, что функция Представление() имеет наглость возвращать значения разных типов даже при идентичном входном параметре. Причем такое неоднозначное поведение было зафиксировано как в версиях 8.2, так и в современных 8.3 - т.е. оно сопровождало СКД с самого начала.

Предлагаю немного попрактиковаться и создать внешний отчет, в котором будет 2 источника описанных запросами. В обоих запросах выберем предопределенные дату и число. Единственное различие будет в том, что во втором варианте мы кроме значений дополнительно запросим еще представления этих полей:

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

Теперь создадим вариант настройки с табличками отдельно по первому источнику (в котором только данные) и по второму источнику (где мы дополнительно запрашивали представления):

А теперь посмотрим результат:

Получившийся отчет для платформы 8.3 я поместил во вложение. Если (внезапно) захотите проверить на платформе 8.2, то вам необходимо переделать вычисляемые поля, так как в те времена в СКД еще не было встроенной функции ТипЗначения(). Можно или вызвать свою собственную функцию из общего модуля или не заморачиваться и вывести в отчет сам результат Представление() - результаты для двух запросов будут снова разных типов.

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

Так почему же результаты различаются? Точно не понятно, или вызов представления в запросе заполняет кеш системы компоновки некоторыми значениями, которые подхватываются одноименной функцией схемы (все таки у них одинаковая сигнатура), или это особенности анализа текста запроса (типа как с периодичностью регистров накопления, где если выбрать Авто и группировку скажем по дням, то начальное и конечное сальдо в группировках будет корректным, но если нигде ничего не меняя исправить в тексте запроса периодичность на День, то отчет сразу поломается и роли полей-остатков станут игнорироваться, они превратятся в обычные поля с обычным суммированием). В документации про такую особенность использования (и тем более про ее логику) нет ни слова. Абсолютно не понятно хотят ли разработчики оставить эту "фичу" навсегда или передумают и уберут в одном из свежих релизов. Но нам, "простым пацанам", помнить о таких особенностях точно нужно, что бы не забывать покрывать код дополнительными проверками типов - на всякий случай.

СКД Представление Карточка счета

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    124820    682    389    

732

Генератор схемы компоновки данных (СКД), написание кода схемы программно

Инструментарий разработчика СКД Платформа 1С v8.3 Конфигурации 1cv8 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

По выбранной схеме компоновки данных генерирует программный код, который генерирует СКД, аналогичную исходной схеме. Есть дополнительные инструменты для просмотра дерева схемы, сравнение исходной схемы и полученной по коду, а также сравнение изменений в сгенерированном коде для исходной схемы и для измененной.

3 стартмани

05.02.2024    4368    30    obmailok    19    

69

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2145    2    Yashazz    0    

31

СКД на JavaScript в 1С

СКД WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Долгое время поддерживаю web-портал, в котором появилась необходимость создавать отчеты. Просмотрев различные фреймворки на js, я решил сделать свое решение, которое позволяло бы быстро разрабатывать и добавлять новые отчеты на web-портал.

2 стартмани

11.12.2023    8370    20    John_d    25    

123

Использование менеджера временных таблиц в СКД

СКД Платформа 1С v8.3 Система компоновки данных Конфигурации 1cv8 Бесплатно (free)

Рассмотрим еще не получивший широкого распространения способ работы с внешними данным в СКД. В процессе обсуждения работы с СКД выяснилось, что многие не знакомы со способом помещения туда временной таблицы, полученной предварительно. Статья будет полезна разработчикам, знакомым с программным созданием СКД.

05.12.2023    4919    PROSTO-1C    13    

63

Модель СКД

Инструментарий разработчика СКД Платформа 1С v8.3 Система компоновки данных Абонемент ($m)

DSL для работы с СКД.

1 стартмани

15.11.2023    6009    15    kalyaka    5    

87

Пользовательские настройки отчетов 1С. Часть 1. Простые и расширенные настройки

СКД Инструкции пользователю Платформа 1С v8.3 Конфигурации 1cv8 1С:Бухгалтерия 3.0 Россия Бесплатно (free)

Простые приемы работы с отчетами на СКД. Что нужно знать пользователю про настройку отчетов, чтобы использовать их на полную катушку.

18.09.2023    7323    accounting_cons    7    

29

Разрыв страницы в СКД. Легко!

СКД Платформа 1С v8.3 Система компоновки данных Бесплатно (free)

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

01.09.2023    4762    KVIKS    15    

80
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Vladimir Litvinenko 2872 15.01.19 13:33 Сейчас в теме
Тут оптимальным решением я вижу для обслуживания отчетов создание общего модуля со включенной опцией повторно использования возвращаемых значений. В таком общем модуле требуется реализовать все требуемые функции с быстрой конкатенации требуемых представлений (на мою устаревшую статью не смотрите - сейчас для быстрого сложения строк существует функция СтрСоединить()). А в схеме компоновки можно просто вызывать эти новые функции. Думаю, что получился бы довольно приличный прирост скорости на больших объемах информации.


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


Этот же факт объясняет почему экземпляр данного отчета, который успешно работает в сотнях тысяч инсталяций типовых и отраслевых решений по всему СНГ, у моих клиентов внезапно сломался. Дело в том, что разработчики типовых в плане видов характеристик ВидыСубконтоХозрасчетные стандартно разрешили только ссылочные типы и ни одного из примитивных! Если кому-то нужны даты, (видимо думали они) то пусть заводят их строковые представления в справочнике Субконто. Хотя несколько лет применения такого субконто показало, что вообще никаких негативных последствий для системы это не несет.


Ох. Просто загляните в структуру индексов таблиц, относящихся к регистру бухгалтерии. Этим включением примитивного типа ваши предшественники индексы раздули. В частных случаях (небольшие базы, низкая интенсивность ввода данных, база только на SQL) это терпимо. В общем случае - неприемлемо.

В индекс по таблице итогов с Субконто3 минимум 3 новых поля добавилось. А в той же типовой ERP там и без этого уже 14 полей. После добавления хотя бы одного примитивного типа будет 17. Как думаете, к чему это приводит? )) А еще есть более терпимые к этому индексы по итогам по Субконто2 и Субконто1.

https://its.1c.ru/db/v8std#content:2149184377:hdoc

Хотелось бы промолчать, зная какая "благодарная" реакция бывает на отсылки к документации, которую увы опытные программисты игнорируют. Или читают только когда приспичит и без этого уже никак. Но всё же надо уменьшать количество вредных советов. Потом приходится делать круглые глаза когда видишь такое в базах и исправлять уже поздно. Ведь учёт давно ведётся и "наш прошлый программист нам так удобно сделал, так удобно" ))


Само исследование хорошее. Только синонимы полей бы поправить. Очень сложно глазами сопоставлять вывод отчетов, приведенных в конце, и исходные данные.
kwazi; Dementor; +2
5. Dementor 1019 15.01.19 18:22 Сейчас в теме
(1) спасибо за комментарий. В текущей версии статьи редактировать скриншоты отчета уже не буду. Но на будущее учту.
Про особенность индексов по "не ссылочному" я читал, но этот клиент с его бухгалтерией не из категории "биг дата".

Очень осторожно следует это делать, без глубокого анализа на базах разного объема нельзя так с горяча поступать. Не забывайте, что повторное использование возвращаемых значений не бесплатно. Системе придется долгое время хранить соответствие входящих параметров и результирующих строк, вплоть до 20 минут. Строки судя по всему получаются не короткими. Самое замечательное что хранение возможно произойдет и на клиенте и на сервере. Не зря для таких функций разрешены только параметры примитивных типов и сохраненные значения периодически удаляются из кэша.


Обычно в бухгалтерских "простынях" сотни и даже тысячи повторов одинаковой аналитики в проводках. Интуиция подсказывает, что если не тратить время на их конкатенацию, а потратить немного оперативки, то быстродействие будет очевидным. Но утверждать без эксперимента не могу. Нужно будет в свободное время попробовать.
Vladimir Litvinenko; +1
2. lvictor58 135 15.01.19 14:17 Сейчас в теме
Я всегда при слиянии строк в самом начале добавляю ""+ что далее система воспринимает как контртекцию а не арифметическое сложение.

Кстати конструкция Сообщить(""+ОписаниеОшибки()) работает корректнее той, что указана в типовом функционале Сообщить(ОписаниеОшибки())
+
3. lunjio 66 15.01.19 14:30 Сейчас в теме
Тут больше претензий к функции ТипЗначения, во втором варианте она должна вернуть для обоих типов строку, т.к Представление() возвращает строку, но видать СКД умничает и берет уже рассчитанные типы для данных полей, попробуйте в запросе местами поменять и скажите результат, тоесть со стороками представление наверх, а вниз без, спасибо.
+
4. acanta 15.01.19 14:32 Сейчас в теме
Спасибо за статью и комментарии. Представление в запросах и в целом функции СКД тема очень интересная.
На мой взгляд мы имеем вместо алгоритмического кода, трансформируемого платформой на файловый, SQL, Postgre, IBM и Oracle принципиально разные варианты и подходы приспособления низкоуровневого программирования 1с8 к особенностям хранения и обработки данных в каждой из используемых СУБД.
Встречала настоятельные рекомендации переходить к изучению программы 1с 8 после глубокого практического изучения каждого из языков (SQL, Postgre, IBM и Oracle), что без участия в реальных коммерческих проектах (без 1С) на базе именно этих продуктов невозможно. Но даже поверхностное изучение этих СУБД в вузах и техникумах создает достаточную базу для понимания допустимых типов переменных в каждой из СУБД.
Dementor; +1
6. jaroslav.h 180 06.05.20 15:19 Сейчас в теме
Дякую, з економили мені багато часу на аналізи.
Dementor; +1
Оставьте свое сообщение