Ошибка расчета остатков в СКД и ее программное исправление на примере Универсального отчета

04.06.12

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

В отчетах, построенных на СКД, в ряде случаев некорректно рассчитываются начальные и конечные остатки по группировкам. Проблема известная, и написано по этому поводу уже немало, но почему-то в типовом универсальном отчете по метаданным она до сих пор проявляется. Дело в том, что при программной работе с СКД разработчики отчета не учли ряд особенностей самой платформы 1С8 (причем это относится как к 8.1, так и к 8.2).
Эти особенности и методы программной работы с ними рассматриваются в данной статье.

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

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

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

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

РЕШЕНИЕ интерактивное (не подходит для Универсального отчета):

Открываем схему компоновки данных вашего отчета и смотрим в настройки полей набора данных.

Для полей начальных и конечных остатков по каждому из ресурсов необходимо заполнить роль: выбрать группу ролей "Остаток" и в ней указать значение "Нач. остаток" или "Кон. остаток" соответственно. Так (скрин2) это делается в конструкторе СКД.

Аналогичным образом необходимо проставить роль "Измерение" для всех измерений вашего набора данных.

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

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

РЕШЕНИЕ программное (на примере Универсального отчета по метаданным):

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

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

Аналогичным образом при создании полей набора данных для измерений необходимо проставить им роль "Измерение". Код будет примерно следующим: 

НовоеИзмерение = ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Измерение.Имя, Измерение.Синоним);

НовоеИзмерение.Роль.Измерение = Истина;

 

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

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

Кроме того, в отчет нигде программно не добавляются поля "Номер строки" и "Регистратор". Мне показалось это странным, т.к. в итоговом наборе данных они присутствуют.

Как выяснилось, поля "Номер строки" и "Регистратор" (Recorder) добавляет сама платформа автоматически при инициализации компоновщика настроек. Причем платформа не заполняет роли для создаваемых ею полей, а программно их заполнить не получается, что создает проблемы при дальнейшей работе с ними. Но если эти поля создать "вручную" и программно прописать им правильные роли, то платформа уже не пытается создавать их заново.

Ниже я предлагаю рецепт, который помог мне почти полностью решить эту проблему платформы и Универсального отчета по метаданным: 

Вот этот фрагмент кода модуля объекта:

/

// Добавляем поля периода

Если ИмяТаблицы = "ОстаткиИОбороты" ИЛИ ИмяТаблицы = "Обороты" Тогда

ТиповыеОтчеты.ДобавитьПоляПериодаВНаборДанных(СхемаКомпоновкиДанных.НаборыДанных[0]);

КонецЕсли;

нужно заменить на следующий:

// Добавляем поля периода

Если ИмяТаблицы = "ОстаткиИОбороты" ИЛИ ИмяТаблицы = "Обороты" Тогда

СписокПериодов = ТиповыеОтчеты.ДобавитьПоляПериодаВНаборДанных(СхемаКомпоновкиДанных.НаборыДанных[0]);

//Заполним служебные поля и проставим периоды вручную, т.к. платформа их не заполняет

Поле = ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], "НомерСтроки", "Номер строки");

Поле.Роль.НомерПериода = 1;

Поле = ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], "Регистратор", "Регистратор");

Поле.Роль.НомерПериода = 2;

сч = 3;

Для Каждого ПолеПериод Из СписокПериодов Цикл

ПолеПериод.Значение.Роль.НомерПериода = сч;

Если сч > 3 Тогда

    ПолеПериод.Значение.Роль.ТипПериода = ТипПериодаКомпоновкиДанных.Дополнительный;

КонецЕсли;

сч = сч+1;

КонецЦикла;

КонецЕсли;

 

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

UPDATE: мне подсказали в комментариях, что на диске ИТС в свое время вышла статья на эту тему. К сожалению, эта статья прошла мимо меня, но помочь мне в решении проблем с универсальным отчетом она бы смогла лишь отчасти. Увы, заморочки платформы со служебными полями СКД, такими как "Recorder", там также не описаны.

Тем не менее, я нашел на Мисте ссылку на нее и рекомендую ознакомиться, ибо полезно:

статья "Типичные проблемы при расчете остатков"

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

См. также

SALE! 15%

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

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

10000 руб.

02.09.2020    159651    875    399    

862

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

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

15.05.2024    8719    implecs_team    6    

47

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

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

3 стартмани

05.02.2024    7010    56    obmailok    21    

79

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

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

1 стартмани

31.01.2024    3155    5    Yashazz    1    

34

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

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

2 стартмани

11.12.2023    10825    23    John_d    25    

124

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

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

05.12.2023    8046    PROSTO-1C    15    

68
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. indigo_ 22.01.10 10:14 Сейчас в теме
Спасибо за статью. Мне тоже довелось с этой ошибкой столкнуться, теперь уже стало понятнее, в чем проблема
2. vvr908 449 22.01.10 10:23 Сейчас в теме
(1) Да, я помню, что сильно удивился первый раз, когда мне пользователи на эту ошибку указали. Пришлось разбираться, т.к. уже было штук 30 различных сохраненных пользовательских настроек - не писать же на каждую свой отчет... ;)

Заодно вспомнил, что у меня есть материал для еще одной заметочки на тему универсального отчета, на днях напишу и выложу.
3. Danil.Potapov 517 22.01.10 18:20 Сейчас в теме
"Мне удалось найти одно ограничение, связанное с этим решением"

попробуй установить флаг у поля "регистратор" - обязательное.
Никулин Леонид; vis_tmp; +2 Ответить
4. vvr908 449 22.01.10 22:08 Сейчас в теме
(3) Я думал об этом, но не пробовал. Мне кажется, это не совсем верное решение проблемы, т.к. регистратор далеко не всегда вообще нужно выводить в отчет (как и детальные записи в принципе). Что будет выведено в отчет, если в настройках флажок "Детальные записи" снят, а поле Регистратор помечено в СКД как обязательное? Не знаю, надо будет попробовать.
5. vvr908 449 23.01.10 01:23 Сейчас в теме
(3) Попробовал сделать Регистратор обязательным полем. Сразу же полезли ошибки СКД из-за последовательности нумерации периодов. Никому этот вариант не рекомендую, не зря он казался мне подозрительным. ;) Лучше уж оставить все в исходном варианте, как в статье.
6. Danil.Potapov 517 23.01.10 13:33 Сейчас в теме
(5) Да, про обязательное поле брякнул не то. Сейчас посмотрю....
45. vis_tmp 32 08.08.17 16:31 Сейчас в теме
(3)(6)Столкнулся с ситуацией когда остатки считались неверно до тех пор, пока не поставил галочки "Обязательное" и у "Регистратор" и у "ПериодСекунда".
47. batya_sh 09.05.20 13:21 Сейчас в теме
(45) Благодарю тебя, добрый человек.
48. Akbis 55 25.05.20 01:17 Сейчас в теме
7. Dirk Diggler 27.01.10 09:10 Сейчас в теме
На каких релизах проверяли?
8. vvr908 449 27.01.10 17:42 Сейчас в теме
(7) На Бух 1.6.22.4 и ранее.
В УПП та же картина на нескольких релизах (точнее, на всех, виденных мной), точно номера не помню.

Только что проверил на платформе 8.2.10.73 в той же Бух 1.6.22.4 - глючит все так же.
9. Glafira 244 29.01.10 09:29 Сейчас в теме
В стандартных отчетах 1С:Торговли при выводе детальных записей по регистратору необходимо добавлять также поле Период для правильного расчета группировок и остатков (Период+Документ движения (регистратор)). Видимо здесь такая же ситуация.
10. vvr908 449 29.01.10 13:03 Сейчас в теме
(9) Попробовал добавить к регистратору еще поле "Период секунда" - не помогает, как и добавление любого другого поля. Ошибка остается. Стандартные отчеты УТ, очевидно, реализованы несколько иначе (скорее всего, при их создании все же использовался конструктор СКД).
11. vvr908 449 29.01.10 13:04 Сейчас в теме
Больше всего напрягает тот факт, что создаваемые самой платформой при инициализации компоновщика настроек служебные поля "Регистратор" ("Recorder") и "номер строки" потом никак нельзя изменять - к ним не удается обратиться как к обычному полю набора данных СКД.

Я надеялся, что в новых версиях платформы что-нибудь изменится, но уже 8.2.10 вышла, а воз и ныне там.
12. madmpro 43 16.08.10 23:16 Сейчас в теме
У меня есть похожий отчет, только на основе универсального отчета, по регистрам партий (комплексная конфигурация, УПП). Проблема с выводом начальных остатков и расшифровок по документам. При выводе расшифровки строки в режиме период+регистратор и отключения детальных записей - все получается (проверено) кроме начальных остатков. Кто-нибудь поможет решать эту проблему?

http://files.mail.ru/I4ZLS2
13. e.kogan 1895 05.10.11 17:01 Сейчас в теме
К сожалению, без прописывания ролей полям остатков тоже ни фига не работает... Пришлось менять процедуру из модуля (роли для измерений и остатков):

Процедура ДобавитьПоляНабораДанных()
		
	Если ТипДанных = "РегистрыНакопления" ИЛИ ТипДанных = "РегистрыСведений" Тогда
		
		// Добавляем измерения
		Для каждого Измерение Из Метаданные[ТипДанных][ИмяОбъекта].Измерения Цикл
			// Э.
			полеизм=ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Измерение.Имя, Измерение.Синоним);
			полеизм.Роль.Измерение=Истина;
			//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Измерение.Имя, Измерение.Синоним);
			// Э.
		КонецЦикла;
		
		// Добавляем реквизиты
		Если ПустаяСтрока(ИмяТаблицы) Тогда
			Для каждого Реквизит Из Метаданные[ТипДанных][ИмяОбъекта].Реквизиты Цикл
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Реквизит.Имя, Реквизит.Синоним);
			КонецЦикла;
		КонецЕсли;
		
		// Добавляем поля периода
		//Если ИмяТаблицы = "ОстаткиИОбороты" ИЛИ ИмяТаблицы = "Обороты" Тогда
		//	ТиповыеОтчеты.ДобавитьПоляПериодаВНаборДанных(СхемаКомпоновкиДанных.НаборыДанных[0]);
		//КонецЕсли;
        // Я. http://infostart.ru/public/64376/
		Если ИмяТаблицы = "ОстаткиИОбороты" ИЛИ ИмяТаблицы = "Обороты" Тогда
			СписокПериодов = ТиповыеОтчеты.ДобавитьПоляПериодаВНаборДанных(СхемаКомпоновкиДанных.НаборыДанных[0]);
			//Заполним служебные поля и проставим периоды вручную, т.к. платформа <= 8.1.14 делает это некорректно
			Поле = ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], "НомерСтроки", "Номер строки");
			Поле.Роль.НомерПериода = 1;
			Поле = ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], "Регистратор", "Регистратор");
			Поле.Роль.НомерПериода = 2;
			сч = 3;
			Для Каждого ПолеПериод Из СписокПериодов Цикл
				ПолеПериод.Значение.Роль.НомерПериода = сч;
				Если сч > 3 Тогда
					ПолеПериод.Значение.Роль.ТипПериода = ТипПериодаКомпоновкиДанных.Дополнительный;
				КонецЕсли;
				сч = сч+1;
			КонецЦикла;
		КонецЕсли;	
		// Я.
		
		// Добавляем ресурсы
		Для каждого Ресурс Из Метаданные[ТипДанных][ИмяОбъекта].Ресурсы Цикл
			Если ИмяТаблицы = "Обороты" Тогда
				
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним);
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "Оборот");

			ИначеЕсли ИмяТаблицы = "ОстаткиИОбороты" Тогда
				
				ПапкаПолейНабораДанных = СхемаКомпоновкиДанных.НаборыДанных[0].Поля.Добавить(Тип("ПапкаПолейНабораДанныхСхемыКомпоновкиДанных"));
				ПапкаПолейНабораДанных.Заголовок   = Ресурс.Синоним;
				ПапкаПолейНабораДанных.ПутьКДанным = Ресурс.Имя;
	                                                                                         
				// Э. нач
				полерес=ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйОстаток", Ресурс.Синоним + " нач. остаток", Ресурс.Имя + "." + Ресурс.Имя + "НачальныйОстаток");
				полерес.Роль.Остаток=Истина;
				полерес.Роль.ТипОстатка=ТипОстаткаКомпоновкиДанных.НачальныйОстаток;
				полерес.Роль.ГруппаОстатка=Ресурс.Имя;
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "НачальныйОстаток");
				
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Приход", Ресурс.Синоним + " приход", Ресурс.Имя + "." + Ресурс.Имя + "Приход");
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "Приход");
				
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Расход", Ресурс.Синоним + " расход", Ресурс.Имя + "." + Ресурс.Имя + "Расход");
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "Расход");
				
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним + " оборот", Ресурс.Имя + "." + Ресурс.Имя + "Оборот");
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "Оборот");
				
				полерес=ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйОстаток", Ресурс.Синоним + " кон. остаток", Ресурс.Имя + "." + Ресурс.Имя + "КонечныйОстаток");
				полерес.Роль.Остаток=Истина;
				полерес.Роль.ГруппаОстатка=Ресурс.Имя;
				полерес.Роль.ТипОстатка=ТипОстаткаКомпоновкиДанных.КонечныйОстаток;
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "КонечныйОстаток");
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйОстаток", Ресурс.Синоним + " нач. остаток", Ресурс.Имя + "." + Ресурс.Имя + "НачальныйОстаток");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "НачальныйОстаток");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Приход", Ресурс.Синоним + " приход", Ресурс.Имя + "." + Ресурс.Имя + "Приход");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "Приход");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Расход", Ресурс.Синоним + " расход", Ресурс.Имя + "." + Ресурс.Имя + "Расход");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "Расход");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним + " оборот", Ресурс.Имя + "." + Ресурс.Имя + "Оборот");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "Оборот");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйОстаток", Ресурс.Синоним + " кон. остаток", Ресурс.Имя + "." + Ресурс.Имя + "КонечныйОстаток");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "." + Ресурс.Имя + "КонечныйОстаток");
				// Э. кон
				
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйОстаток", Ресурс.Синоним + " нач. остаток");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "НачальныйОстаток");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Приход", Ресурс.Синоним + " приход");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "Приход");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Расход", Ресурс.Синоним + " расход");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "Расход");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним + " оборот");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "Оборот");
				//
				//ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйОстаток", Ресурс.Синоним + " кон. остаток");
				//ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя + "КонечныйОстаток");
				
			ИначеЕсли ТипДанных = "РегистрыСведений" Тогда
				
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя, Ресурс.Синоним);
				
				Типы = Ресурс.Тип.Типы();
				Если Типы.Количество() = 1 И Типы[0] = Тип("Число") Тогда
					ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя);
				КонецЕсли;
				
			ИначеЕсли ИмяТаблицы = "" Тогда
				
				ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя, Ресурс.Синоним);
				ТиповыеОтчеты.ДобавитьПолеИтога(СхемаКомпоновкиДанных, Ресурс.Имя);
				
			КонецЕсли;	
		КонецЦикла;
		
	ИначеЕсли ТипДанных = "Документы" ИЛИ ТипДанных = "Справочники" Тогда
		
		Если ПустаяСтрока(ИмяТаблицы) Тогда
			ОбъектМетаданных = Метаданные[ТипДанных][ИмяОбъекта];
		Иначе
			ОбъектМетаданных = Метаданные[ТипДанных][ИмяОбъекта].ТабличныеЧасти[ИмяТаблицы];
		КонецЕсли;
		
		// Добавляем реквизиты
		Для каждого Реквизит Из ОбъектМетаданных.Реквизиты Цикл
			ТиповыеОтчеты.ДобавитьПолеНабораДанных(СхемаКомпоновкиДанных.НаборыДанных[0], Реквизит.Имя, Реквизит.Синоним);
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры
Показать
17. vvr908 449 18.02.12 18:31 Сейчас в теме
(13) e.kogan, в статье сразу предлагается прописать роли для полей остатков с помощью типовой процедуры общего модуля. ;)
Т.е. вашу конструкцию вида
полерес.Роль.Остаток=Истина;
полерес.Роль.ТипОстатка=ТипОстаткаКомпоновкиДанных.НачальныйОстаток;
полерес.Роль.ГруппаОстатка=Ресурс.Имя;

можно заменить на:
ТиповыеОтчеты.ЗаполнитьПолеНабораДанныхОстаток(полерес, Ресурс.Имя);

По моему опыту, этого будет вполне достаточно.
Хотя и ваш вариант, конечно, тоже будет работать.

P.S. Все обсуждаемые изменения касаются процедуры ДобавитьПоляНабораДанных() модуля объекта УниверсальныйОтчетПоМетаданным.
Все желающие "починить" универсальный отчет могут заменить код этой процедуры на код, приведенный e.kogan в (13).
20. e.kogan 1895 20.02.12 13:34 Сейчас в теме
(17) это хорошо, когда конфигурация типовая :)
21. vvr908 449 20.02.12 13:38 Сейчас в теме
(20) e.kogan, ну у вас в коде тоже без вызова типовых функций все того же общего модуля не обошлось ))
23. e.kogan 1895 20.02.12 13:47 Сейчас в теме
(21) Гм, оно у меня переопределяется :) На самом деле это форма с экспортными процедурами :) самый простой способ выдрать всё на свете из конфы.
25. vvr908 449 20.02.12 23:17 Сейчас в теме
(23) e.kogan, хитро придумано )) я, честно говоря, тупо общий модуль перетащил в свое время в самописную конфу и поудалял оттуда все лишнее.

Одно отличие тут может стать заметным - если общий модуль может быть серверным, то форма - нет.
14. vvr908 449 14.02.12 00:38 Сейчас в теме
Недавно мне понадобилась эта статья, когда мы стали пытаться анализировать полученную из другой базы через COM-соединение таблицу остатков и оборотов с детальными записями. В исходной базе остатки считались корректно, но после выгрузки результата запроса в таблицу значений и обработки этой таблицы в другой БД настройки пришлось прописывать вручную - тут и вспомнилось про эту статью.

Выяснилось, что если содержимое строки таблицы значений содержит движения накопления по ресурсам вида "нач.остаток/приход/расход/кон.остаток", то для корректного расчета остатков по группировкам средствами СКД необходимо выполнить настройки, аналогичные описываемым в статье.
В исходной таблице значений обязательно должно быть поле периода (дата движения или период из р/н). Если его там нет - добавляем. Затем в настройках СКД нужно присвоить этому полю роль "Период, 1", и далее заполнить роли для полей остатков и измерений, как описано в статье.
При этом желательно все измерения сделать обязательными, а поля необязательных измерений убрать вообще, т.к. группировка по "необязательным" измерениям мешает корректному расчету остатков.
Конечно, результат получится далеко не столь гибким, как мы привыкли видеть в отчетах на СКД. Но он хотя бы будет верным!
15. Boroda 90 16.02.12 21:02 Сейчас в теме
Отличная статья, очень полезные комментарии, хорошо её дополняющие. Спасибо.
16. vvr908 449 16.02.12 22:58 Сейчас в теме
(15) Boroda, спасибо за столь положительный отзыв!
Как раз после того, как написал последний комментарий, я еще раз все перечитал и решил полностью переработать текст статьи.
Теперь статья не только про универсальный отчет, которым далеко не все пользуются, но главным образом про нюансы настройки СКД.
Я не претендую на особое знание глубинных механизмов СКД, но делюсь тем, что удалось накопать мне самому и вместе с коллегами.
18. romansun 194 18.02.12 20:09 Сейчас в теме
на мисте есть обсуждение этой темы... ссылку, к сожалению, не дам... гуглите

на ИТС есть статья, полностью и на примерах раскрывающая тему ролей в СКД. В указанном обсуждении на мисте есть ссылки на скрины статьи ИТС :)


что интересно, в обычных запросах с итогами остатки считаются верно самой 1С на уровне платформы. И вот эту "верность" срубить весьма непросто.. )) Даже при скидывании выборки во временную таблицу 1С всё равно "помнит" остаточные поля и верно считает остатки (т.е. арифметически - неверно). Отбить память об остатках получается только при втором или третьем перескидывании во временную таблицу...

а в СКД получается, наоборот, механизмы запросных итогов они видимо отключили, как и сами итоги, поэтому приходится принудительно распределять роли полей для корректного расчета остатков.
19. vvr908 449 18.02.12 21:06 Сейчас в теме
(18) romansun, спасибо за наводку, надо будет поискать :)
Только статья-то исходно была написана 2 года назад, когда еще никакой информации толком не было...

UPD: вот, нашел на мисте кое-что с ИТС: статья "Типичные проблемы при расчете остатков"
romansun; +1 Ответить
24. romansun 194 20.02.12 22:45 Сейчас в теме
(19)

дадада.. :) она самая

и что меня убивает лично во всей этой ситуации - что такая, действительно, важная вещь, как "Роли" в библии СКД от Хрусталёвой (библии, ибо больше нигде консолидированно инфы по СКД толком нет) описана в виде одной странички с общим смыслом: "а еще в СКД есть роли, они нужны... нужны, т.к. помогают при расчете остатков и других клевых штук.. больше я вам ничего не скажу,... как-то так"
22. e.kogan 1895 20.02.12 13:47 Сейчас в теме
*упс, дважды отправилось
26. vvr908 449 05.06.12 01:18 Сейчас в теме
Был приятно удивлен появлением ссылки на статью на главной странице в рубрике "Выбор экспертов".
Хоть статья уже и не новая, я все же надеюсь, что она окажется познавательной в том числе и для тех, кто перейдет по ссылке из чистого любопытства. Для меня в свое время и сами-то роли в СКД были довольно загадочным явлением, а уж о таком странном поведении платформы я и вовсе не подозревал.
27. Пацталоцци 119 11.06.12 19:20 Сейчас в теме
Самое удивительное и смешное во всей этой истории - это постоянные разговоры восьмёрочников о том, что восьмёрка якобы на порядок круче и эффективнее чем 7.7.
Да это же стыд и срам.
Это называется прогрессивная платформа!
Для написания обычного отчёта на СКД приходится залезать в дебри такого извращённого бреда, в который любой обкуренный шаман с бубном побрезгует соваться.
asdPerepel; olbu; kentavr27; +3 Ответить
31. vvr908 449 12.06.12 18:25 Сейчас в теме
(27) Пацталоцци, в любом случае, в статье идет речь об ошибке, которая проявляется в довольно специфичных условиях. Обычно для разработки простого отчета на СКД никаких сакральных знаний не требуется, достаточно просто написать запрос.
32. nafa 661 13.06.12 21:22 Сейчас в теме
(31) Ничего себе специфические условия - поле остатка в запросе. В Бухгалтерии таких вобще-то процентов 90.

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

Дополнение

Пришлось и все измерения обязательными сделать (т.к. иначе отсутствие/наличие одного из измерений в запросе влияло на остаток :( ) зато теперь работает как часы.
shima; MikaGI; opkc; +3 Ответить
33. vvr908 449 14.06.12 10:34 Сейчас в теме
(32) nafa, обычно поля остатка правильно распознаются конструктором СКД и роли им прописываются без участия программиста. Конечно, можно заполнять схему компоновки программно, а не интерактивно. В этом случае роли приходится прописывать вручную, но это все же довольно специфичная ситуация.
34. nafa 661 14.06.12 11:29 Сейчас в теме
(33)
Поля остатка то распознаются, но почему без этих галок то в самом примитивном отчете по регистру (простой запрос типа выбрать измерение1, измерение2, начальный остаток, приход, расход, конечный остаток, период, регистратор из регистр.ххх.ОстаткиИОбороты(,, Регистратор,)) итог по полям остатка при наличии в выбранных пользователем группировках периода/регистратора и их отсутствии оказывается совершенно разный, а с галками одинаковый.
(Отчет создан без единой ручной правки, только эти галки)
35. vvr908 449 14.06.12 16:21 Сейчас в теме
(34) nafa, да, насчет этих галок вообще вопрос интересный.
А если пользователь, к примеру, будет группировать отчет по периоду, но с заранее неизвестной периодичностью (неделя или месяц)? Делать оба поля ПериодНеделя и ПериодМесяц обязательными? Как на это отреагирует СКД? Надо будет проэкспериментировать и дополнить статью результатами эксперимента...
36. nafa 661 14.06.12 23:44 Сейчас в теме
(35)
Есть есть обязательные группировки Регистратор и Период, то пруппировки ПериодМесяц и ПериодНеделя обязательными делать не надо, и так работает. Кроме того в статье по ссылке выше написано что нельзя одновременно использовать неделю и более крупные периоды - можно, но просто надо понимать что в этом случае неделя которая находится на пересечении месяцев разделится на два кусочка.
40. opkc 25.02.15 13:17 Сейчас в теме
(32) nafa, спасибо тебе, мил человек! перерыл пол-интернета, но только в твоём комментарии нашёл истину: "Пришлось сделать обязательным 2 поля: период и регистратор."
41. garaevilnur 4 27.05.16 15:55 Сейчас в теме
(32) nafa, спасибо! Присоединяюсь "обязательно"!
28. Пацталоцци 119 11.06.12 19:23 Сейчас в теме
Вы хоть сами понимаете, что вместо нормальной и стабильной программерской работы, занимаетесь совершенно ненормальным "научным тыком" ???
asdPerepel; +1 Ответить
29. Пацталоцци 119 11.06.12 19:30 Сейчас в теме
Для странного, алогичного поведения платформы вы ищете странные, алогичные методы багофиксинга.
И я бы ещё понял, если бы выгода от использования СКД была настолько существенна, что перекрывала бы эти затраты времени и рассудка.
Но ведь этого не происходит.
Насколько я понимаю, основным плюсом СКД декларировалась очень высокая скорость разработки отчётов и, как следствие, экономия времени программиста?
Ну и?
Много времени сэкономили, бегая с бубном вокруг сабжа?
30. vvr908 449 12.06.12 18:21 Сейчас в теме
(29) Пацталоцци, я не вполне понимаю - какие есть альтернативы? Забить на СКД и перевести всех клиентов обратно на 7.7?
Мы работаем с теми механизмами, какие есть, а претензии имеет смысл адресовать не сюда, а к 1С.
37. Makushimo 160 13.09.13 06:31 Сейчас в теме
Полезная статья.
Спасибо автор.
38. Al777 24.07.14 09:18 Сейчас в теме
Поставил обязательными поля Период и Регистратор. Остатки теперь выводит правильно, но по периодам перестал отчёт работать. В чём может быть причина?
39. olbu 22.08.14 14:49 Сейчас в теме
Потратил полдня на это, нигде не видел, что периодичность виртуальной таблицы должна быть "Авто". У меня было "Регистратор" - ничего не получалось, пока не поменял на "Авто"...
42. bashhhh 26 13.01.17 14:40 Сейчас в теме
Спасибо. Статья помогла разобраться в проблеме!
43. maxchaos 22 17.03.17 12:58 Сейчас в теме
Автор, исправьте ссылку на Мисту в конце публикации, а то открывается не то!
44. vis_tmp 32 08.08.17 07:40 Сейчас в теме
46. AndroidRu 4 09.08.17 14:18 Сейчас в теме
Исправил все как в этой статье. Остатки считает правильно, но выводит как то странно.
2-мя строчками. В 1 строчке в полях начального и конечного остатка суммы начального остатка, а во второй строчке суммы конечного остатка. Подскажите, пожалуйста, кто сталкивался с таким? Заранее благодарен.
Оставьте свое сообщение