1с посчитать сумму в динамическом списке
Многие задаются вопросами расчета итогов динамических списков в управляемых формах. Здесь мы не будем претендовать на академичность, оставим споры, что мол это не нужно, что это все равно что считать бородатых мужиков на движущемся эскалаторе, что это дополнительная нагрузка. Все это понимают, Кто не понимает - поймет на практике. Поэтому основываемся на. "снегопад, снегопад, если женщина просит. " или "..а мня плевать - мне очень хочется.." Я попытался решить практические проблемы при расчете и выводе итогов. В приложении примеры расчета итогов в иерархическом справочнике и журнале документов.
Рассмотрим на примере неких колонок Поступило и Списано в динамическом списке
1. Размещаем реквизиты итогов
На форму добавляем числовые реквизиты ИтогиПоступилоПодвал и ИтогиСписноПодвал и назначаем их в подвал таблицы к полям Поступило и Списано в качестве ПутьКДаннымПодвала
2. Отлавливаем изменения на клиенте
Т.к. не существует событий, связанных с изменение отбора и с поиском в динамическом списке, попробуем реализовать свою систему слежения. Для отслеживания изменений в отборе периодически нужно контролировать пользовательские настройки компоновщика списка, период списка (для журналов и документов), а так же использовать событие ПриСменеТекущегоРодителя ддля иерархического справочника.
Пока нерешенной проблемой остается изменение поиска. Стоит заметить, что если поиск выполняется средствами СУБД (не через индекс полнотекстового поиска), то настройки компоновки содержат отбор, соответствующий поиску. Поэтому, если использоватья явный вызов расчета на сервере, то итоги будут рассчитаны с учетом поиска. Но вот отследить на клиенте когда нужно вызвать сервер при поиске пока у меня не получилось.
Добавляем на форме строковый реквизит НастройкаСписка, который и будет нашим флагом. Запускаем обработчик ожидания и следим за изменениями. Если что-то поменялось - обращаемся на сервер за расчетом итогов
3. Расчитываем реквизиты итогов на сервере
Тут нужно сказать спасибо разработчикам за предоставленные фунуции для динамических списков ПолучитьИсполняемуюСхемуКомпоновкиДанных() и ПолучитьИсполняемыеНастройкиКомпоновкиДанных(). Изначально эти функции предназначены для вывода списков в отчет, но, немного подправив полученую схему компоновки и настройки, получем в результате таблицу значений с одной строкой, содержащей итоги по нужным нам полям.
Вот пример для журнала банковских выписок:
Для иерархичеких списков выявилась одна особенность: СКД не содержит отбора по текущему родителю (ну может я его не нашел). Поэтому в случае со справочником можно доработать настройки типа так:
Многие задаются вопросами расчета итогов динамических списков в управляемых формах. Здесь мы не будем претендовать на академичность, оставим споры, что мол это не нужно, что это все равно что считать бородатых мужиков на движущемся эскалаторе, что это дополнительная нагрузка. Все это понимают, Кто не понимает - поймет на практике. Поэтому основываемся на. "снегопад, снегопад, если женщина просит. " или "..а мня плевать - мне очень хочется.." Я попытался решить практические проблемы при расчете и выводе итогов. В приложении примеры расчета итогов в иерархическом справочнике и журнале документов.
Рассмотрим на примере неких колонок Поступило и Списано в динамическом списке
1. Размещаем реквизиты итогов
На форму добавляем числовые реквизиты ИтогиПоступилоПодвал и ИтогиСписноПодвал и назначаем их в подвал таблицы к полям Поступило и Списано в качестве ПутьКДаннымПодвала
2. Отлавливаем изменения на клиенте
Т.к. не существует событий, связанных с изменение отбора и с поиском в динамическом списке, попробуем реализовать свою систему слежения. Для отслеживания изменений в отборе периодически нужно контролировать пользовательские настройки компоновщика списка, период списка (для журналов и документов), а так же использовать событие ПриСменеТекущегоРодителя ддля иерархического справочника.
Пока нерешенной проблемой остается изменение поиска. Стоит заметить, что если поиск выполняется средствами СУБД (не через индекс полнотекстового поиска), то настройки компоновки содержат отбор, соответствующий поиску. Поэтому, если использоватья явный вызов расчета на сервере, то итоги будут рассчитаны с учетом поиска. Но вот отследить на клиенте когда нужно вызвать сервер при поиске пока у меня не получилось.
Добавляем на форме строковый реквизит НастройкаСписка, который и будет нашим флагом. Запускаем обработчик ожидания и следим за изменениями. Если что-то поменялось - обращаемся на сервер за расчетом итогов
3. Расчитываем реквизиты итогов на сервере
Тут нужно сказать спасибо разработчикам за предоставленные фунуции для динамических списков ПолучитьИсполняемуюСхемуКомпоновкиДанных() и ПолучитьИсполняемыеНастройкиКомпоновкиДанных(). Изначально эти функции предназначены для вывода списков в отчет, но, немного подправив полученую схему компоновки и настройки, получем в результате таблицу значений с одной строкой, содержащей итоги по нужным нам полям.
Вот пример для журнала банковских выписок:
Для иерархичеких списков выявилась одна особенность: СКД не содержит отбора по текущему родителю (ну может я его не нашел). Поэтому в случае со справочником можно доработать настройки типа так:
Добрый день!
Есть динамический список с отборами и с возможностью пользователя поиском дополнительно отбирать строки. Всё работает.
Создал кнопку "Рассчитать итоги" и в подвал "Суммы" выводится итог.
Хочется это автоматизировать.
Есть событие &НаСервереБезКонтекста ПриПолученииДанныхнаСервере. Там есть строки, я могу посчитать сумму и всё. В подвал разумеется никак не вставить.
Поэтому вопрос: как с &НаСервереБезКонтекста вызвать процедуру на &НаСервере (хотя бы) с параметром, там бы вставил в подвал.
Или есть какие-то иные методики?
>Поэтому вопрос: как с &НаСервереБезКонтекста вызвать процедуру на &НаСервере (хотя бы) с параметром, там бы вставил в подвал.
Ни как.
Суть на &НаСервереБезКонтекста в том что при вызове обновленное состояние формы не передаётся на сервер (из экономии) - т.е. актуального состояния формы в момент вызова на сервере нет - поэтому вызвать &НаСервере ни как не получится.
В ПриПолученииДанныхНаСервере это &НаСервереБезКонтекста потому что динмамический список сам получает данные без передачи контекста (опять же из экономии), а это просто пост обработчик на получении данных.
P.S. Но даже если бы ПриПолученииДанныхНаСервере был контекстным, кажется это бы ни как не помогло в решении озвученной задачи - в обработчик ведь передаются только строки считанные в этом вызове, а не все вообще.
Сейчас озвученная задача хорошо не решается.
только дважды выполнять запрос. но нужно учитывать, что полный запрос по всем строкам может ОЧЕНЬ долго делать. ведь это же фулл скан
(3) Есть. События на изменение отборов - точно есть.
И по нему получать текущий запрос списка, доделать его для получения итогов и вывести - тоже можно. Правда, скорость.
всё очень просто, вызываешь скд объект динсписка, выгружаешь данные из объекта в ТЗ и считаешь итоги любой колонки
(4) Я именно про передачу данных из процедуры без контекста "наружу".
Сразу уж спрошу: "События на изменение отборов - точно есть." - а какое?
В принципе да, все правы. Я понимал что нет решения, но надеялся что может что-то появилось. По изменении отборов - да, есть событие, но если пользователь в строке поиска пишет "морковк…", то увы нет.
Кстати, а как вообще получить все строки динамического списка через СКД, если там нет условий, которые пользователь задал в поиске? С самой формы никак строки не получить?
Сегодня столкнулся с необходимостью в динамическом списке посчитать итоги по колонкам, покопавшись на форумах, понял, что тема достаточно старая, и решения ее весьма разнообразные.
Я бы хотел предложить Вам свой способ решения данной проблемы - он достаточно прост и не требует программирования и прочих заморочек.
Его главное достоинство - простота. Дело в том что, с недавних пор в динамических списках появилась возможность использовать временные таблицы в запросах и как следствие пакетные запросы.
Суть метода заключается в расчете итогов отдельным полем в самом запросе динамического списка и выводе его в каждой строке без отображения, само же поле отборажается через ТекущиеДанные элемента формы в подвале. До появления возможности использовать временные таблицы и пакеты в запросе можно было расчитать только общий итог по динамическому списку который не учитывает пользовательские отборы, из-за этого данный метод практически не использовался, пример такого запроса Вы можете увидеть ниже:
С появлением возможности использовать временные таблицы и пакетных запросов мы получили возможность расчитывать итоги в динамических списках с учетом наложенных на них отборов, без каких либо сложностей, но тут нужно отметить следующие особенности:
2) выбрать основную таблицу можно будет только из физических таблиц присутствующих в последнем запросе пакета - далее покажу на примере.
Итак, есть некий динамический список с полями числового типа, и требуется по ним рассчитать итоги, в моем примере это некий документ, у которого есть колонка "СуммаДокумента" (см. скриншот):
1-й вариант запроса будет не даст нам возможность указать Документ1 в качестве основной таблицы, как следствие с динамическим списком не будет возможности работать стандартным способом и не будет динамического чтения данных, однако он будет учитывать итоги с учетом отборов. Я покажу его в качестве примера того как делать не нужно:
2-й вариант запроса - это собственно запрос, который будет работать корректно в наших динамических списках:
Первым запросом мы читаем данные основной таблицы с учетом пользовательских отборов, вторым запросом мы делаем сразу несколько вещей
1) мы указываем динамическому списку, какая таблица у нас может быть в качестве основной, и тут же фильтруем её по данным временной таблицы
Далее нам остается в свойствах динамического списка у данного поля утановить "использовать всегда" (на форму поля итогов просто не выводим).
И для каждой колонки, в которой нужно рассчитать итоги, указываем ПутьКДаннымПодвала из данных форм со ссылкой на нужное нам поле итога.
Конечно, у данного метода есть свои особенности, но все же на текущий момент это достаточно простой и быстрый способ получить итоги в динамических списках.
Специальные предложения
Поправьте, если я чего-то недопонял.
Открытие динамического списка документов без отборов и ограничения по периоду приведет к засовыванию всей таблицы документов во временную таблицу?
(3) увы да, в первую таблицу всегда будет засовываться вся таблица, а вторая будет читать только соответствующую порцию из этой ВТ т.е. на клиента возвращается именно считанная порция а не все таблица.
Возможно я сейчас ляпнул глупость так как мои познания SQL далеки от идеала, но судя по профайлеру и поведению платформы все это работает примерно так.
Я был бы признателен гуру SQL если они на примере данных профайлера объяснили мне что происходит при таком запросе динамического списка и какие здесь могут быть подводные камни.
На моих тестах в 10 колонок итогов в 50000 документах с учетом различных отборов и без, все считаются достаточно быстро.
(4) Отображение на форме при скролинге, обновлении данных формы, и.т.д - не вызывает сильных тормозов.
(4) именно поэтому в платформе и нет нормального механизма по итогам списков документов, потому как без перебора всех документов сумму не подсчитать.
у нас, например, 50к документов создаётся за 5 дней. поставьте эксперимент на 1млн документов
(4) Проблема в том, что такое решение прикапывает лопатой основную идею динамического списка (как и получение общих итогов в принципе) - сделать производительность динамического списка фактически независящей от размера таблицы, которую он отображает (если работать в рамках индексов). С ростом размера таблицы и производительность и потребление ресурсов будут ощутимо ухудшаться.
На карманных базах можно издеваться над эффективностью почти как угодно - запаса прочности хватает.
Но в промышленных базах десятки миллионов записей - это обыденность даже для таблиц документов. Где даже банальный запрос получения количества записей в таблице выполняется ощутимое время.
Когда поработаешь с большими потоками информации и посмотришь на возникающие на глазах проблемы - поневоле в первую очередь начинаешь задумываться в том числе и о масштабируемости.
Решение не лишено остроумности, но, к сожалению, плохо масштабируемо.
ИМХО, овчинка не стоит выделки. Если кому-то так уж важны общие итоги, то разумным компромиссом выглядит их получение "по кнопке". А это проще и логичнее делать через СКД.
verniypro; dj_serega; N!ghtmare; Dach; user620589_pletnev; Amadeuc404; mickey.1cx; Stim213; + 8 – Ответить
Добрый день. пожалуйста поясните, а для чего это нужно ? Список динамический, что дает вам сумма в итогах, список постоянно изменяем? Ну если вы отбор только наложите и будете точно знать, понимать количество нужных документов. В учетных системах я не встречал практико - применение этому.
(8) Итоги по списку с установленными отборами имеют практический смысл. Это же очевидно.
Другое дело, что
1) если эти данные имеют самостоятельную ценность, то для этого обычно отчеты используются
2) если эти данные часть бизнес-процесса, влияющего на документооборот, то обычно такие бизнес-процессы автоматизируются более полно в рамках какого-нить рабочего стола на это заточенного
Просто пользователи в решении своих потребностей отталкиваются от того что имеют и редко способны самостоятельно сформулировать внятное техзадание.
Это не пользователей дело, а постановщика задачи. Пользователь должен сформулировать то, как он для себя это видит, а бизнес должен провести аудит и понять, а нужно ли это вообще и как это лучше сделать в комплексе. Хотелки отдельного пользователя могут иметь место там, где решение и разрабатывается для этого отдельного пользователя. Когда решение разрабатывается для бизнеса, то пользователь получает функционал, проанализированный бизнесом и включенный в решение бизнесом, а не пользователем.
(10) Ок. Некорректно выразился. Читать как "редко способны самостоятельно сформулировать внятные технические требования".
(10) Если мы говорим про разработку тиражных решений то я с Вами полностью согласен. Но реальность такова что практически все тиражные решения всегда затачивались и будут затачиваются под хотелки определенной группы пользователей - проводить аудит, что-то решать, думать "а оно нам надо" - для бизнеса это зачастую дорого и не интересно - бизнесу важен результат в установленных для него рамках - поэтому Бизнес рано или поздно нанимает "отдельно программиста" на которого сыплются все хотелки этого бизнеса.
Добрый день коллеги! Большое спасибо за поддержку и за интерес!
Статья предназначается в первую очередь для ТЕХ кому это нужно.
По моему опыту в большинстве случаев это капризы пользователей, не нравится им работать с отчетами и они некоторые вещи хотят видеть сразу в списках, например суммы по отобранным документам ит.д . Тут даже не всегда получается объяснить не рациональность таких требований, а можно и работы лишиться в некоторых случаях. Если мы говорим про базы где производительность критерий номер 1 то да такой подход скорее фишка нежели что-то полезное - если же мы говорим про базы КФИС то тут это будет иметь смысл так как критерий номер 1 уже не производительность а максимально возможное количество аналитики (инталев тому пример) которую хотят видеть сразу на форме и не лезть в 100500 отчетов, и не жать дополнительные кнопки.
Как бы то ни было - у людей возникает потребности в итогах динамических списков , а решения которые находят для этого разработчики весьма изощрённые - собственно им и посвящается.
(12) Хозяин-барин. Только проблема в том, что очень сложно провести границу достаточности масштабируемости.
Сегодня у вас все довольны. А завтра подрастает документооборот или просто база проживет несколько лет. И у всех начинает все глючить и подтормаживать то тут то там, потому что конфа нафарширована костылями без оглядки на масштабируемость. И стоило ли бизнесу пришедшее в негодность решение, требующее больших затрат на оптимизацию (в том числе потому, что авторов давно уж нет) того года условно "красивой жизни" - большой и жирный вопрос. Бизнес вполне умеет слушать, если говорить с ним на языке денег и предлагать разумные альтернативы.
Тоже считаю, что динамический список должен оставаться динамическим, а итоги можно считать по кнопке. Как вариант, вместо кнопки можно прицепиться к какому-либо событию, хотя их мало: ПриАктивизацииСтроки, ПриАктивизацииЯчейки. Конечно, можно еще и обработку ожидания прикрутить, а к ней, в свою очередь, тоже сделать кнопку Вкл/Выкл, ну чтобы можно было отключать ожидание и не производить постоянные вычисления.
Причем, настройки можно анализировать и принимать соответствующие решения о необходимости пересчета итогов вообще, а также по этим настройкам можно узнать для каких полей нам нужно это делать, а для каких нет.
(15) За наводку на статью спасибо - не знал что так можно. Сразу возникает вопрос - есть возможность быстро отловить момент изменения настроек динамического списка, или тут все-таки танцы с бубнами?
(17) ПриОбновленииСоставаПользовательскихНастроекНаСервереИмениНу ралиеваБорисаГеоргиевича же! Не вводите людей в заблуждение, коллега!
(16) Увы нету, только танцы.
Я, как правило, делаю кнопку, по которой, после установки фильтров, пользователь делает необходимые расчеты. Иногда, вешаю обработку на событие "ПриАктивизацииСтроки", но обработчик этот глючный и не всегда срабатывает, например, после Ctrl+F в списке остается одна строка - событие есть, меняем условие поиска при котором у нас остается опять одна строка (другая) - события нет. Поэтому, добавляю обработчик и для "ПриАктивизацииЯчейки", т.е. сместились в строке - событие есть, короче, танцы.
Вот, в 8.3.10 пообещали обработчик "ПриПолученииДанныхНаСервере", сначала обрадовался . но, обломали, вызов не контекстный, форму поменять нельзя, можно только строчки оформить, причем искать (сортировка, отбор и т.д.) по таким "данным" (их тама нету) бессмысленно.
Еще жду 8.3.11, там будет общение между сервером (фоновые задания) и клиентскими сеансами, не знаю, может там удастся прорваться, поживем увидим .
Поковырялся вчера с итогами для документов на 5 000 - летает. Если правильно "КАКать", то верхний запрос отлавливает все: поиск, поиск по полям через ссылку, отбор по любому реквизиту, поиск и отбор по характеристикам, в общем, "загнать в угол" - не вышло.
Такого быстродействия не ожидал, если честно. Думаю, что такой подход, идеален, по сравнению с попыткой ловить события активизации в списке документов, что-то там анализировать и выполнять лишние серверные (причем контекстные) вызовы.
Небольшой косяк есть, это когда после поиска получаем пустой список, а потом что-то ищем и строки в списке есть, но нет активной строки, тогда имеем ТекущиеДанные = Неопределено и сумма итога не отображается, ес-но при переходе в список сумма появляется, но это фигня.
Позже погоняю справочник, к-нить иерархический, интересно как там будут фильтры отлавливаться.
Есть динамический список и форма списка справочника. Нужно в форме отображать количество элементов в динамическом списке. Как наиболее правильно это сделать? Какой обработчик события задействовать?
(0) Заменить динамический список на коллекцию.
У динамического списка по определению нет количества (может меняться каждые 0,1 сек.).
или тебе нужно сколько записей из таблицы тебе доступны по правам?
или тебе нужно еще с учетом установленых отборов?
Считать можно АВТОНОМЕРЗАПИСИ.
Но,можно в при получении данных сделать тот же запрос,что и для списка только с приставкой КОЛИЧЕСТВО
(9) Вот ты хороший вопрос задал.
"или тебе нужно еще с учетом установленых отборов?"
Конечно с учетом. Где и кому может понадобиться без учета?
(0) ты же преподаватель и не знаешь ответ на такой простой вопрос?
нету итератора и нету количество
модифицируй запрос чтобы количество выдавал
Если бы дедушка знал количество записей, то он был бы бабушкой.
Вроде бы работала недокументированная магия через построитель запроса если ему источником динамический список засунуть. Тогда он вроде бы может родить запрос с отборами динамического списка.
Слава богу за всю мою практику такая фигня ни разу не потребовалась.
(22) Это понятно. Только как это сделать без контекста? ПриПолученииДанных вызывает процедуру без контекста
(25) Ох уж! Показываешь пользователю работу со списком. Говоришь: смотри как удобно, правую кнопку нажал, в середине есть пункт "Найти. ", и вот ты уже отобрал все нужные тебе записи. Пользователь: Вау! А сколько их?
Пропасть между разработчиками 1С и пользователями их продукта просто огромна. Почему такой очевидный вопрос от пользователя сразу не пришел в голову разработчику?
(26) Спасибо, конечно. Но у меня проблема не в этом. А в том, на какой обработчик события эту роскошь повесить
(28) Говоришь пользователю: смотри как удобно, правую кнопку нажал, в середине есть пункт "Вывести список". Или даже есть кнопка "Еще", а в ней опять таки "Вывести список". И смотришь номер последней строки.
(28) Потому что за таким вопросом, как правило, кроется плохо спроектированный интерфейс и/или бизнес процесс.
(28) Потому что разработчик платформы решал перпендикулярную инженерную задачу - как сделать пользователю комфортную работу со списками потенциально бесконечного размера. Которая исключает знание их количества.
Когда пользователю нужно это знать - это уже задача прикладного программиста обеспечить пользователя подходящими инструментами.
(30) хорошо, что вы машины не проектируете. Смотри как удобно лючок бензобака открыл, веточку в бак вставил, вытаскивает и смотришь уровень топлива
(36) делается отдельная элемента (индикатор уровня топлива) на нужной форме
которая обновляется в нужные моменты
Я так понимаю, что от любого решения Мишенька теперь будет воротить нос и выпендриваться.
Ну, что сказать. Тебе надо - ты и делай, чо.
(42) или по таймеру или в момент неких действий юзера
и да получение уровня топлива никак не привязано к форме списка, это независимое
(45)+ причем лучше совместить, чтобы если очень много действий то не надо каждый раз получать, ибо еще мало времени прошло
(44) Задачи пользователей не всегда возможно решить в реальной жизни так, как пользователям хотелось бы. Иначе все пользователи были бы молодыми, красивыми и богатыми. Но ты не инженер, тебе не понять.
ЗЫ. Но с контекстным событием обновления ДС действительно нехорошо получилось :) Нету его.
(0) отображать кол-во элементов после применения платформенных пользовательских отборов? Если так, то увы не получится - событий нет и их не перехватить
(47) это противоречит асинхронности и отказу от модальности
иначе разрабы конф начали бы на него разное вешать и получать фризы
(49) > иначе разрабы конф начали бы на него разное вешать
Хорошая присказка. Помню ее долго приговаривали, не давая пользователю делать произвольные отборы в динамических списках. Мол тормозить будет по неиндексированным полям. Потом плюнули.
А забирать возможности у разрабов конф из "благих побуждений" - это дорога в ад. Вы или крестик снимите или трусы наденьте.
(50) Нет. Он истину глаголет. В экосистеме 1С, состоящей из разработчиков платформы, разработчиков типовых, разработчиков "последней мили" и пользователей, разработчики типовых - самое слабое звено. Их по хорошему стоило бы давно ликвидировать
(54) Только ликвидаторов потом тоже обязательно зачистить. Там достойных людей никогда не встречается.
(47) Да ладно бы и фиг с ним. Берем неконтекстное ПриПолученииДанных(). Разработчики нам туда вроде как настройки ДС кидают вторым параметром. В настройках вроде как Отбор есть. Казалось бы бери и строй запрос. Ура, вроде как. Ставишь точку останова. Заходишь в список, делаешь отбор через правую кнопку. Смотришь в конфигураторе в отбор. А он ПУСТОЙ. И вот тут начинаешь материться. 1С в очередной раз сожрала у меня время. Чавкнула и не подавилась. Недоделанность хаотично разбросана по всей 1С. Никогда не знаешь, где напорешься. Ну лучше бы не делали этот обработчик события! А начав делать, доделали бы до конца!
Читайте также: