Время прочтения: 5 мин.

Все задачи, о которых пойдет речь далее, решаются при помощи функции dual():

Dual(text, number)

где

     text – значение, которое будет отображаться (например, подпись данных на точке графика).

     number – значение, которое будет использоваться в качестве реального значения для построения графика.

Чтобы было проще понять, построю гистограмму с выражением:

Получается такой график:

На подписи данных показано значение 50, но для построения столбца использовано значение 1 – это видно по оси слева.

Задача №1

Требуется на одной горизонтальной гистограмме отобразить столбцы с их значениями (цвет значений оставить черным), рядом проставить цифры с динамикой, причем расположить в зависимости от длины столбца, а, так же, выделить цветом в зависимости от знака (зеленым – положительные, красным – отрицательные), вот так:

На первый взгляд, данная задача легко решается при помощи формулы dual(), но остается загвоздка в цветах – в QV нельзя устанавливать разный цвет текста для отдельных цифр, вычисляемых в одном выражении (Expression), то есть либо все цифры – и факт, и динамика будут либо черными, либо с условным форматированием, а ТЗ у нас другое.

Мое решение:

п.1 Создаю первую гистограмму со значениями факта, с формулой Sum():

п.2 Создаю вторую диаграмму для динамики, с формулой  dual():

Для второй диаграммы:

— на вкладке Expressions оставляю галочки Invisible (для того, чтобы не отображались столбцы), Bar (чтобы не получить сообщение «All expression disabled»), Values on Data Points (для показа цифр динамики). В свойствах выражения Text Color прописываю формулу условного форматирования:

Sum({<Календарь.Дата={'$(v1004MaxDateSum)'}>}[Количество терминалов])>Sum({<Календарь.Дата={'$(v1004_1m_Date)'}>}[Количество терминалов]),
	Green(),
	rgb(255,0,0)
) 

где

v1004MaxDateSum – переменная для выбора значений текущего периода

v1004_1m_Date – переменная для выбора значений предыдущего периода,

Green() – цвет, если текущее значение больше предыдущего

Rgb(255,0,0) – цвет, если текущее значение меньше предыдущего.

— Убираю отображение всех осей и легенды, чтобы остались только значения

— Для фона диаграммы устанавливаю полную прозрачность (Вкладка Colors – Область Frame Background – Transparency)

Смотрю, что получилось:

п.3 Накладываю вторую диаграмму поверх первой – готово.

В моем случае цифры динамики иногда накладывались на цифры факта, поэтому я задал значение смещения в первую часть dual():

При помощи этой строки вставляем пробелы перед значением динамики, в количестве равном длине вычисляемого значения факта, и отодвигаем отображаемую цифру правее от факта.

Задача №2.

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

Решение:

п1. Создаю выражение, которое будет дублировать подписи данных линии «Первичка», но сам график факта будет смещен на 0,3 (30%) в зависимости от условия:

 п.2 Создаю выражение, которое будет дублировать подписи данных линии «Вторичка», но сам график факта будет смещен на 0,3 (30%) в зависимости от условия:

На самом деле п.2 не всегда обязателен, иногда бывает достаточно смещения только для одного выражения.

п.3 Графики выражений из п.1 и п.2 делаю прозрачными (Invisible на вкладке Expressions)

п.4 Для выражений «Первичка» и «Вторичка» убираю подписи данных (Values on Data Points)

Получаем график:

Но на нашем графике всего два выражение, а что делать если их три или четыре? Конечно, использовать dual()! Однако, есть тонкости — возможно, я разберу кейс с тремя выражениями в следующих постах.

Задача № 3.

Сделать лист бокс для выбора квартала с наименованием периодов в формате «№кв КВ ГОД» — например «3 КВ 2021», при том, что в исходных данных указана только дата в формате ДД.ММ.ГГГГ.

В исходных данных поле с отчетным периодом — Multifact.period_end

Решение:

Если просто сделать листбокс с указанном выше полем, то получим такой результат:

Решение:

В качестве поля для листбокса указываем Expression:

dual(Ceil(Month(Multifact.period_end)/3) & ' КВ ' & Year(Multifact.period_end), QuarterName(Multifact.period_end)) 

где

Ceil(Month(Multifact.period_end)/3) & ‘ КВ ‘ & Year(Multifact.period_end) – значение, которое будем видеть в лист бокс.

QuarterName(Multifact.period_end) – фактические значения, которые будут фильтроваться при выборе квартала и участвовать в сортировке. Функция QuarterName() нужна, чтобы отсечь лишние даты, которые не являются окончанием квартала.

Итог:

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