Как правильно реализовать чередующуюся раскраску строк в печатной форме 1С с заданным шагом?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

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

1. Использование простого счетчика с флагом для переключения состояния

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

Разберем логику по шагам:

  1. Нам потребуется переменная-счетчик, например, СчетчикСтрок, инициализированный нулем перед началом цикла.
  2. Также нужна переменная-флаг, например, ФлПокраски, которая будет указывать, нужно ли красить текущую группу строк. Инициализируем ее в Истина, если первая группа должна быть окрашена, или в Ложь, если первые пять строк должны быть без раскраски. В нашем случае, по условию, первые 5 строк без раскраски, поэтому ФлПокраски = Ложь.
  3. Внутри цикла по выборке данных мы будем увеличивать СчетчикСтрок для каждой выводимой строки.
  4. Мы будем проверять значение ФлПокраски. Если флаг установлен, применяем желаемый цвет фона; в противном случае – устанавливаем цвет фона по умолчанию или не устанавливаем его вовсе, чтобы сохранить прозрачность.
  5. После вывода строки, мы проверяем, достиг ли СчетчикСтрок значения 5. Если да, это означает, что мы закончили текущую группу из пяти строк. В этом случае мы переключаем флаг ФлПокраски на противоположное значение (с Истина на Ложь или наоборот) и сбрасываем СчетчикСтрок обратно в 0, чтобы начать отсчет для следующей группы.

Давайте посмотрим на пример кода, основанный на этом подходе:


// Инициализация переменных перед циклом
СчетчикСтрок = 0;
ФлПокраски = Ложь; // Первые 5 строк без раскраски

Пока ВыборкаЗарплата.Следующий() Цикл
    // Заполняем параметры области из текущей строки выборки
    ОбластьЗарплата.Параметры.Заполнить(ВыборкаЗарплата);

    // Определяем цвет фона в зависимости от флага
    Если ФлПокраски Тогда
        ОбластьЗарплата.Область(1,2,1,4).ЦветФона = WebЦвета.Фиолетовый;
    Иначе
        // Важно: если "нет раскраски" означает прозрачный фон,
        // то нужно использовать Новый Цвет() или не устанавливать ЦветФона.
        // WebЦвета.Белый - это конкретный белый цвет, не прозрачность.
        ОбластьЗарплата.Область(1,2,1,4).ЦветФона = Новый Цвет(); // Для прозрачного фона
        // Или ОбластьЗарплата.Область(1,2,1,4).ЦветФона = WebЦвета.Белый; // Если нужен именно белый
    КонецЕсли;

    // Выводим область
    ТабДок.Вывести(ОбластьЗарплата, ВыборкаЗарплата.Уровень);

    // Увеличиваем счетчик строк
    СчетчикСтрок = СчетчикСтрок + 1;

    // Проверяем, достигли ли мы конца текущей группы из 5 строк
    Если СчетчикСтрок = 5 Тогда
        ФлПокраски = Не ФлПокраски; // Переключаем флаг
        СчетчикСтрок = 0;           // Сбрасываем счетчик для новой группы
    КонецЕсли;
КонецЦикла;

Обратите внимание на важный нюанс, упомянутый в сообщении 3: "нет раскраски" и WebЦвета.Белый – это разные вещи. Если вам нужен именно прозрачный фон (то есть, чтобы фон брался из нижележащих областей или был по умолчанию), то следует использовать Новый Цвет() или просто не присваивать значение свойству ЦветФона. Присвоение WebЦвета.Белый установит именно белый фон, который может перекрыть стандартное оформление.

Предложенный в сообщении 2 вариант немного отличается, он использует счетчик, который работает от 1 до 10, переключая раскраску после 5 строк, и сбрасывается после 10. Давайте проанализируем его:


Покрасим = 1; // Счетчик от 1 до 10
Пока ВыборкаЗарплата.Следующий() Цикл
    ОбластьЗарплата.Параметры.Заполнить(ВыборкаЗарплата);
    Если Покрасим > 5 Тогда // Если счетчик больше 5 (то есть, строки 6-10)
        ОбластьЗарплата.Область(1,2,1,4).ЦветФона = WebЦвета.Фиолетовый;
    Иначе // Если счетчик 1-5
        ОбластьЗарплата.Область(1,2,1,4).ЦветФона = WebЦвета.Белый; // Здесь используется WebЦвета.Белый
    КонецЕсли;
    ТабДок.Вывести(ОбластьЗарплата, ВыборкаЗарплата.Уровень);
    Если Покрасим = 10 Тогда // Если достигли конца 10-строчного цикла
        Покрасим = 1;         // Сбрасываем счетчик
    Иначе
        Покрасим = Покрасим + 1; // Увеличиваем счетчик
    КонецЕсли;
КонецЦикла;

Этот вариант также корректен и решает задачу, но он предполагает, что цикл раскраски длится 10 строк (5 белых, 5 фиолетовых), а затем повторяется. Выбор между этими двумя вариантами зависит от личных предпочтений в читаемости кода.

2. Применение оператора деления по модулю (%) для более компактного кода

Для более элегантного и компактного решения мы можем использовать оператор деления по модулю (`%`). Этот оператор возвращает остаток от деления одного числа на другое. Он идеально подходит для реализации циклических или чередующихся условий.

Для нашей задачи – чередования каждые 5 строк (5 без раскраски, 5 с раскраской), что образует цикл длиной в 10 строк – мы можем использовать следующую логику:

  1. Введем общий счетчик строк, скажем, ном, который будет просто увеличиваться на 1 с каждой новой строкой, начиная с 0.
  2. Для определения раскраски мы будем анализировать остаток от деления ном на 10 (длину полного цикла раскраски).
  3. Если остаток от деления ном % 10 будет меньше 5, это будет соответствовать первым пяти строкам в десятистрочном цикле (0, 1, 2, 3, 4). Эти строки мы оставим без раскраски.
  4. Если остаток будет равен или больше 5 (5, 6, 7, 8, 9), это будут следующие пять строк, которые мы окрасим.

Пример кода, основанный на этом принципе (из сообщения 6):


ном = 0; // Инициализируем счетчик строк с нуля
Пока ВыборкаЗарплата.Следующий() Цикл
    // Заполняем параметры области
    ОбластьЗарплата.Параметры.Заполнить(ВыборкаЗарплата);

    // Устанавливаем цвет фона с помощью тернарного оператора '?'
    // Если (ном % 10 < 5) ИСТИНА, то WebЦвета.Белый (или Новый Цвет()), иначе WebЦвета.Фиолетовый
    // Важно: в сообщении 6 написано WebЦвета.Фиолетовый и WebЦвета.Белый.
    // Если "нет раскраски" - это прозрачный фон, то используем Новый Цвет()
    ОбластьЗарплата.Область(1,2,1,4).ЦветФона = ?(ном % 10 < 5, Новый Цвет(), WebЦвета.Фиолетовый); 
    // Если нужно строго "белый, потом фиолетовый", то:
    // ОбластьЗарплата.Область(1,2,1,4).ЦветФона = ?(ном % 10 < 5, WebЦвета.Белый, WebЦвета.Фиолетовый);

    // В исходном сообщении была лишняя строка ФлПокраски=Не ФлПокраски;, ее нужно убрать,
    // так как логика раскраски полностью определяется оператором модуля.

    // Выводим область
    ТабДок.Вывести(ОбластьЗарплата, ВыборкаЗарплата.Уровень);

    // Увеличиваем общий счетчик строк
    ном = ном + 1;
КонецЦикла;

Этот подход значительно сокращает код и делает его более декларативным. Он также легко масштабируется: если вам нужно чередовать раскраску, например, каждые 3 строки (3 без, 3 с), вы будете использовать ном % 6 < 3.

Обсуждение в сообщениях 7-12 показывает, как можно по-разному формулировать условия с оператором модуля. Например, Цел(НомерСтроки / 5) % 2 является более близким аналогом `odd(строка div 5)` и определяет четность/нечетность группы из пяти строк, что также удобно для чередования.

3. Использование Соответствия и переключателя для гибкости

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

Рассмотрим логику:

  1. Создадим новый объект Соответствие, где ключами будут булевы значения (Истина и Ложь), а значениями – соответствующие объекты Цвет. Это позволяет нам ассоциировать состояния переключателя с конкретными цветами.
  2. Инициализируем булеву переменную Переключатель (например, Истина) и переменную АктуальныйЦвет, которой присвоим цвет, соответствующий начальному значению Переключателя.
  3. Введем Счетчик строк, инициализированный нулем.
  4. В цикле мы будем увеличивать Счетчик и выводить строки с текущим АктуальныйЦвет.
  5. После вывода каждой строки мы проверяем, делится ли Счетчик на 5 без остатка (Счетчик % 5 = 0). Если да, это означает, что мы только что вывели пятую строку в текущей группе. В этом случае мы переключаем значение переменной Переключатель на противоположное (Не Переключатель) и обновляем АктуальныйЦвет, выбирая его из Соответствия по новому значению Переключателя.

Пример кода из сообщения 13:


// Создаем соответствие для хранения цветов
Цвета = Новый Соответствие;
// Истина будет соответствовать "без раскраски" (прозрачный или белый)
Цвета.Вставить(Истина, Новый Цвет()); // Прозрачный цвет
// Цвета.Вставить(Истина, WebЦвета.Белый); // Если нужен именно белый
// Ложь будет соответствовать "с раскраской"
Цвета.Вставить(Ложь, WebЦвета.Фиолетовый);

Переключатель = Истина; // Начальное состояние: первые 5 строк без раскраски (соответствует Истина в Цвета)
АктуальныйЦвет = Цвета[Переключатель]; // Получаем начальный цвет

Счетчик = 0; // Инициализируем счетчик строк

Пока ВыборкаЗарплата.Следующий() Цикл
    Счетчик = Счетчик + 1; // Увеличиваем счетчик для каждой строки

    ОбластьЗарплата.Параметры.Заполнить(ВыборкаЗарплата);
    ОбластьЗарплата.Область(1,2,1,4).ЦветФона = АктуальныйЦвет; // Применяем текущий актуальный цвет

    ТабДок.Вывести(ОбластьЗарплата, ВыборкаЗарплата.Уровень);

    // Проверяем, закончили ли мы группу из 5 строк
    Если Счетчик % 5 = 0 Тогда
        Переключатель = Не Переключатель; // Переключаем состояние
        АктуальныйЦвет = Цвета[Переключатель]; // Получаем новый актуальный цвет из соответствия
    КонецЕсли;
КонецЦикла;

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

4. Использование условного оформления в макете табличного документа

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

Как мы можем это использовать для чередующейся раскраски каждые 5 строк:

  1. Откройте макет вашего табличного документа, который вы используете для вывода.
  2. В макете найдите раздел "Условное оформление" (обычно доступен через меню "Таблица" -> "Условное оформление..." или на панели инструментов макета).
  3. Создайте новое правило условного оформления.
  4. В этом правиле укажите область макета, к которой будет применяться оформление (например, всю строку или определенные ячейки).
  5. Самое главное – задайте условие для применения оформления. Для нашей задачи мы можем использовать выражение на встроенном языке запросов 1С, основанное на номере строки. Например, для чередования 5 строк без раскраски и 5 строк с раскраской, нам нужно определить группы по 10 строк и красить вторые пять.
  6. Выражение может выглядеть так: (Цел((НомерСтроки() - 1) / 5) % 2 = 1).
    • НомерСтроки() возвращает текущий номер строки в табличном документе (начиная с 1).
    • (НомерСтроки() - 1) позволяет нам работать с индексами, начинающимися с 0, что удобнее для деления по модулю.
    • Цел((НомерСтроки() - 1) / 5) группирует строки по пять. Например, строки 1-5 дадут 0, 6-10 дадут 1, 11-15 дадут 2 и так далее.
    • % 2 = 1 проверяет, является ли результат деления на 5 нечетным. Это означает, что каждая вторая группа из пяти строк (1-5, *6-10*, 11-15, *16-20*) будет удовлетворять условию. Если вам нужно красить *первую* группу из пяти, тогда используйте % 2 = 0.
  7. В настройках оформления для этого правила укажите желаемый цвет фона (например, WebЦвета.Фиолетовый).
  8. Если вам нужен "прозрачный" фон для неокрашенных строк, убедитесь, что других правил, устанавливающих фон, нет или что это правило применяется с нужной приоритетностью.

Преимущества этого подхода:

Для создания такого правила:

  1. Откройте макет отчета.
  2. Перейдите в "Таблица" -> "Условное оформление".
  3. Добавьте новый элемент.
  4. На вкладке "Условие" нажмите на кнопку "..." и введите выражение: (Цел((НомерСтроки() - 1) / 5) % 2 = 1). Убедитесь, что тип выражения "Выражение".
  5. На вкладке "Оформление" установите "Цвет фона" в WebЦвета.Фиолетовый.
  6. На вкладке "Область" укажите, к каким ячейкам будет применяться оформление, например, R1C1:R1C4, если вы оформляете строки в области ОбластьЗарплата.

5. Дополнительная информация о побитовых операциях в 1С

В ходе обсуждения также упоминались побитовые операции в 1С. Хотя они не используются напрямую для решения задачи циклической раскраски строк, важно знать, что 1С:Предприятие 8.3 поддерживает набор функций для работы с битами чисел. Эти функции могут быть полезны в более специализированных задачах, таких как:

В 1С доступны следующие побитовые операции:

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

Заключение

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

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

← На главную