Почти во всех документах QlikView есть размерности с датами, а значит, есть необходимость их выбирать. Для дизайнерских решений стандартный серый календарик не всегда подходит.
Поэтому сегодня расскажу о создании собственного календаря, в котором при желании можно управлять всем. Например, по-своему раскрашивать фон квадрариков с датами, по-своему раскрашивать сами числа, можно даже привязать цветовые решения к каким-то показателям в этих датах. Разместить в приложении целый год (12 календариков) или показывать календарь не неделями, а декадами! В общем, очень много идей можно реализовать по данной технологии. Итак приступим.
- Для создания нашего календарика возьмём объект Сводные таблицы (Pivot Table). При построении матрицы внутренних дат одного месяца для сводной таблицы нам помимо самой размерности даты (пусть она называется «ДАТА»), понадобится в скрипте обогатить её ещё тремя сопутствующими, вычисляемыми размерностями:
- Year(ДАТА)&’/’&IF(Week(ДАТА)=1 and Month(ДАТА)=12,
53
,Num(Week(ДАТА),00
)) as ДАТА_НЕДЕЛЯ’,’RGB(57,130,172)’ - WeekDay(ДАТА) as ДАТА_ДЕНЬ_НЕДЕЛИ’,
- MonthStart(ДАТА) as ДАТА_МЕСЯЦ’,
НА ЗАМЕТКУ! Обращаю внимание, чтобы в Декабре не «исчезла» часть дней из-за того, что обычно в первую неделю попадают последние дни Декабря и первые дни Января, мы перенесём последние числа декабря из 1 недели в 53.
- Начинаем создание календарика с обычной сводной таблицы (Pivot Table) с двумя измерениями:
ДАТА_НЕДЕЛЯ, ДАТА_ДЕНЬ_НЕДЕЛИ и в выражении прописываем: Day(ДАТА).
Обязательно сразу на странице «Представление» поставим галочку у опции: «Всегда полное представление».
Получаем следующее (Пример А):
- Переносим мышкой размерность ДАТА_ДЕНЬ_НЕДЕЛИ на горизонтальное размещение. Отключаем заголовок.
a) На вкладке Представление (Presentation)
- Убираем все галочки в «Разрешить сводные таблицы» (Allow Pivoting), «Индикаторы выбора» (Selection Indicators), «Всегда полностью развернуто» (Always Fully Expanded) и «Скрыть нулевые значения» (Suppress Zero-Values).
- Удаляем символ «-» в «Null Symbol” и «Missing Symbol».
- Выберем третий в списке Измерения (Expression) «Day(ДАТА)»‘ и отцентруем его «Метку» (Label) и «Данные (Числовые)» (Data Numeric) по горизонтали.
- В измерении «ДАТА_ДЕНЬ_НЕДЕЛИ» отцентруем только «Даные (Числовые)» (Data Numeric).
b) На вкладке Стиль (Style)
Чтобы сделать одновременно все вертикальные и горизонтальные линии нашего календарика более контрастными:
- Выберем текущий стиль «Текущий стиль» (Current Style) как «Базовый» (Basic), но прозрачность сетки передвинем ползунком «Прозрачность» (Cell Borders Transparency) на 70%.
- Отключим галочку: «Вертикальные границы ячеек измерений» (Vertical Dimension Cell Borders).
Получаем Пример (Б):
- Теперь переключимся через меню: Вид/Сетка (View/Design Grid) в расширенный режим дизайнера. У нас появится фоновая сетка, как признак, что режим дизайнера активирован.
a) Правой кнопкой мыши нажимаем по правой левой серой ячейке нашей таблицы, где написано ДАТА_НЕДЕЛЯ. В выпавшем меню выберем меню: «Ячейка с настраиваемым форматом» (Custom Format Cell):
b) Попадаем на форму дополнительных настроек ячейки таблицы. Делаем цвет «Цвет фона» (Background Color) прозрачным и копируем его в «Цвет текста» (Text Color).
c) Верхние и нижние границы убираем. То же самое проделываем и для ячейки, где отображается сам год и неделя (первый столбец таблицы). После чего ширину первых двух колонок можно уменьшить до минимума. Пример (В):
- Теперь, чтобы наш календарик показывал только один месяц, можно сделать рядом обычный «List Box» с размерностью ДАТА_МЕСЯЦ, которую мы уже создали на шаге 1 – Пример Г:
Однако этот вариант имеет минус – нам надо как-то обеспечить возможность выбора только одного месяца. Поэтому мы организуем выбор месяца по-другому.
- Итак, заведем переменную:
1 |
vMonthSelected = MakeDate(2015,3) |
или можно прописать начальное присвоение последнего месяца в скрипте:
1 |
LET vMonthSelected = Peek(`ДАТА_МЕСЯЦ`,-1). |
- Теперь доработаем наши измерения (вкладка Dimensions):
Вместо первого ДАТА_НЕДЕЛЯ — напишем такое условие:
1 |
IF(ДАТА_МЕСЯЦ=vMonthSelected, ДАТА_НЕДЕЛЯ) |
Вместо второго ДАТА_ДЕНЬ_НЕДЕЛИ — напишем такое условие:
1 2 3 |
IF(ДАТА_МЕСЯЦ=vMonthSelected DUAL(Lower(ДАТА_ДЕНЬ_НЕДЕЛИ), ДАТА_ДЕНЬ_НЕДЕЛИ) ) |
Тут, как можно заметить, мы сделали все наши надписи дней недели маленькими буквами, но чтобы сортировка не сбилась — обернули функцией DUAL.
На этом же шаге сделаем небольшие поправки стиля:
- Отключим бордюр: закладка «Макет» (Layuot) в свойствах объекта, убираем галочку «Использовать границы» (Use Borders)
- Сменим шрифт текста, например на Calibri: закладка «Шрифт» (Font)
Получаем Пример Д:
- Для того чтобы видеть какой месяц сейчас выбран и обозначить границы нашего календарика:
- Cоздадим дополнительный объект «Текст» (Text).
- Определим нужные размеры, выберем цвет рамки и поместим объект за календариком.
- В качестве заголовка у элемента пропишем показ текущего значения переменной vMonthSelected: =Date(vMonthSelected,
MMMM YYYY
) - Заголовок отцентрируем:
- Осталось только придумать элементы, которые будут управлять выбором нужного нам месяца, и которые будут менять значение нашей переменной vMonthSelected. Опять же, самый простой способ сделать такой элемент управления — из объекта «Текст» (Text), так как в нём есть возможность прописать команды действия (вкладка «Actions») и использовать при отображении не только буквы и цифры, но и специальные символы.
НА ЗАМЕТКУ! Спецсимволы я обычно использую с этих сайтов: http://miraduga.com/Temp/TablSpec.html и http://veseloff.net/17.html. Здесь любой спецсимвол просто копируется и вставляется в нужное место.
Итак, для выбора предыдущего месяца:
- Скопируем с указанного сайта в новый объект Text «стрелку влево».
- Отключим заголовок и рамку объекта.
- Фон сделаем прозрачным.
- В качестве действия (на вкладке «Действия», Actions) добавим всего одну команду: раздел команд «Внешний» (External) выберем команду «Установить переменную» (Set Variable):
- Переменную, которой будем управлять, укажем нашу: vMonthSelected, а саму команду, которая будет выполняться, пропишем следующую:
1 2 3 4 |
=IF( MIN({1}ДАТА_МЕСЯЦ)<vMonthSelected, Date(AddMonths(vMonthSelected,-1,1)), vMonthSelected ) |
- Аналогично сделаем текстовый объект для выбора следующего месяца, вставим в него «Стрелку вправо», а в качестве команды управляющей переменной пропишем:
1 2 3 4 |
=IF( MAX({1}ДАТА_МЕСЯЦ)>vMonthSelected, Date(AddMonths(vMonthSelected,1,1)), vMonthSelected)', |
- Усилить визуализацию можно, скрывая стрелку влево («предыдущий месяц»), когда мы дошли до самого минимального месяца, имеющегося в документе для выбора. Для этого просто надо на вкладке «Макет» (Layout) в опции «Показать – По условию» (Show – Conditional ) прописать условие показа объекта:
1 |
Match(v3Step,1,7,8,9) AND MIN({1}ДАТА_МЕСЯЦ)<vMonthSelected |
- Для стрелки вправо («Следующий месяц») условие показа объекта:
1 |
MAX({1}ДАТА_МЕСЯЦ)>vMonthSelected', |
- Ну, а теперь попробуем выбрать какую-либо дату в нашем календарике. Сюрприз? При выборе любой ячейки таблицы, вся таблица ужимается до одной этой ячейки.
Чтобы, не смотря на текущий выбор, всё равно отрисовывались все даты в календаре необходимо доработать наше текущее выражение на вкладке «Выражения» (Expressions).
Вместо уже существующей формулы «=Day(ДАТА)» напишем такое выражение: =Day(Only({1}ДАТА))’,
Теперь из-за примененного сет-анализа (set-analysis) {1} — мы получаем день даты, игнорируя все фильтры:
- Последний штрих: «подсвечиваем» выбранную дату ярким фоном. Для этого:
- Назовем наше выражение — «Число» (Метка/ Label)
- Раскроем плюсик
- В «Цвет фона» (Background Color) пропишем такую формулу:
1 |
=IF( GetPossibleCount(ДАТА)=1 AND число=Day(ДАТА), RGB(255,158,158)) |
Также рекомендую выделить субботы и воскресенья, прописав тут же в «Цвет шрифта» (Font Color) следующее условие:
1 |
=IF( Match(Only({1}ДАТА_ДЕНЬ_НЕДЕЛИ),`Сб`,`Вс`), RGB(255,30,30))', |
Ну вот и всё. Наш кастомизированный календарик готов. Пишите свои комментарии и мысли по созданию нестандартных календарей QlikView в комментариях. До скорых встреч!
Добрый день.
Спасибо, получился удобный календарик) Есть только один вопрос. Как подсвечивать выбранную дату в календарике постоянно? Не только отображать цвет при нажатии?
Спасибо за ответ.
Все получилось. Неправильно записала в формуле «число».
Но появился другой вопрос.
Как выбрать (выделить) сразу несколько дней в календаре?
У меня получилось просто выделить мышкой с нажатой левой клавишей.
По поводу нестандартного календаря могу поделиться интересной историей, которая развивается вот прямо сейчас в компании, где работаю.
Компания — ритейлер (федеральная сеть магазинов детских товаров), и в ряде отчетов и процессов аналитики/планирования использует понедельную временнУю детализацию (например при сравнении Like-for-Like, сопоставлении «Неделя CY — Неделя PY», планировании оборота и т.п.).
И (разумеется) ВНЕЗАПНО выяснилось, что в основном плане 2016 года, 1 неделя — это «короткая» с 1 по 3 января, 2 неделя — уже полная с 4 по 10 января и так далее. В принципе логично — за первую неделю года приняли первую полную.
НО! В «общечеловеческом» календаре по ГОСТ и ISO — при определении 1 недели года действует правило «в какой год попадает четверг», и если он в прошлом году — то и первые дни нового года относятся к 53 неделе прошлого. Для 2016 года 1 неделя по такому календарю — с 4 по 10 января, 2 неделя — с 11 по 17 и так далее. И что естественно, печатная продукция верстается по этому стандарту (вот прямо надо мной на стене перекидной календарь, картинки-производственные календари из интернета), и самое главное — в ИТ-системах тоже так и не иначе! (За одним исключением — функция НОМНЕДЕЛИ в Excel до 2010 включительно, в 2013 появилась НОМНЕДЕЛИ.ISO)
Когда все это дело выяснилось, первые мысли были конечно предложить переделать операционный план. Бизнес наотрез отказался, и мотивировал тоже логично — «да у вас тогда 2 неделя 2015 (05-11 янв.) и 2 неделя 2016 (11-17 янв.) совершенно разные, и по всему году рассинхрон пойдет, сравнение недели к неделе потеряет смысл».
Так что осталось единственное решение — вводить альтернативный календарь в аналитические системы.
Коллеги SAP BW (в компании два BI, SAP и Qlik) схватились за головы — у них 0CALWEEK лежит в таблицах фактов рядом с 0CALDAY и 0CALMONTH, им предстоит переколбасить все, начиная с потоков данных и заканчивая уровнем представления в отчетах.
Мне в Клике же все оказалось сделать намного проще. В большинстве приложений, где в качестве Dimension используется поле Неделя из таблицы измерения Календарь — достаточно просто изменить код в скрипте, и подменить стандартную функцию Week на ApplyMap к переданному бизнесу мэппингу недель.
Сложнее было найти решение для тех случаев, когда функции Week/WeekEnd/WeekName/MakeWeekDate используются непосредственно в Expressions (в показателях чартов, в переменных, в Set Analysis и т.п.). Но в итоге сделал изящно — создал специальные параметрические переменные:
eAltCal_Week, eAltCal_WeekName, eAltCal_WeekEnd, eAltCal_MakeWeekDate
Аналоги вышеуказанных системных функций, и вызываются с такими же параметрами, но возвращают Неделю по альтернативному календарю.
И везде прошелся поиском и заменой по всем выражениям, где было Week( SomeDate ) стало $(eAltCal_Week( SomeDate )) и т.п.
Внутри этих переменных сидит проверенная конструкция Pick( Match( ) ) , которая работает в практически любом контексте и возвращает значение из массива «правильных недель», соответствующее параметру-дате.
И в принципе все — уже через день выкатил изменения в двух приоритетных приложениях.
САПеры же пока продолжают оценивать скоуп изменений ))
Гибкость Клика и скорость изменений иногда действительно бывает удивительной по сравнению с аналогичными продуктами.
Добрый день. Календарь получился очень удобный, но также не могу выделить сразу несколько дней в календаре, подскажите решение. Заранее спасибо за ответ.
Добрый день!
Реализован Ваш календарик почти во всех отчетах компании (более 30 отчетов)! Все отлично и удобно. Но! Появилось одно Но! При переходе на QlikView 12 — он перестал работать. С чем это может быть связано? Заранее спасибо за ответ.