При формировании печатных форм в 1С часто возникает задача визуально выделить группы строк, например, раскрасить каждую вторую или каждую пятую группу строк. Это помогает улучшить читаемость документа и акцентировать внимание на определенных данных. Давайте подробно разберем, как мы можем реализовать вывод печатной формы с чередующейся раскраской строк каждые пять позиций: сначала пять строк без раскраски, затем пять строк с фоном, и так далее.
Основная сложность заключается в правильной организации логики переключения состояния раскраски и отслеживания текущего количества строк внутри каждой группы. Мы рассмотрим несколько подходов, которые позволят нам добиться желаемого результата, от простых счетчиков до более элегантных решений с использованием оператора деления по модулю и встроенных механизмов условного оформления.
Один из самых прямолинейных и понятных способов — это использование вспомогательного счетчика, который будет отслеживать количество выведенных строк, и флага, определяющего текущее состояние раскраски. Каждые пять строк мы будем переключать флаг и сбрасывать счетчик. Этот подход был предложен в обсуждении и является хорошей отправной точкой.
Разберем логику по шагам:
СчетчикСтрок, инициализированный нулем перед началом цикла.ФлПокраски, которая будет указывать, нужно ли красить текущую группу строк. Инициализируем ее в Истина, если первая группа должна быть окрашена, или в Ложь, если первые пять строк должны быть без раскраски. В нашем случае, по условию, первые 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 фиолетовых), а затем повторяется. Выбор между этими двумя вариантами зависит от личных предпочтений в читаемости кода.
Для более элегантного и компактного решения мы можем использовать оператор деления по модулю (`%`). Этот оператор возвращает остаток от деления одного числа на другое. Он идеально подходит для реализации циклических или чередующихся условий.
Для нашей задачи – чередования каждые 5 строк (5 без раскраски, 5 с раскраской), что образует цикл длиной в 10 строк – мы можем использовать следующую логику:
ном, который будет просто увеличиваться на 1 с каждой новой строкой, начиная с 0.ном на 10 (длину полного цикла раскраски).ном % 10 будет меньше 5, это будет соответствовать первым пяти строкам в десятистрочном цикле (0, 1, 2, 3, 4). Эти строки мы оставим без раскраски.Пример кода, основанный на этом принципе (из сообщения 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)` и определяет четность/нечетность группы из пяти строк, что также удобно для чередования.
Еще один продвинутый подход, который предлагает хорошую гибкость и читаемость, использует коллекцию типа Соответствие (аналог словаря или карты) для хранения цветов и булевый переключатель. Этот метод позволяет легко менять цвета и управлять логикой переключения, особенно если цветов больше двух или условия сложнее.
Рассмотрим логику:
Соответствие, где ключами будут булевы значения (Истина и Ложь), а значениями – соответствующие объекты Цвет. Это позволяет нам ассоциировать состояния переключателя с конкретными цветами.Переключатель (например, Истина) и переменную АктуальныйЦвет, которой присвоим цвет, соответствующий начальному значению Переключателя.Счетчик строк, инициализированный нулем.Счетчик и выводить строки с текущим АктуальныйЦвет.Счетчик на 5 без остатка (Счетчик % 5 = 0). Если да, это означает, что мы только что вывели пятую строку в текущей группе. В этом случае мы переключаем значение переменной Переключатель на противоположное (Не Переключатель) и обновляем АктуальныйЦвет, выбирая его из Соответствия по новому значению Переключателя.Пример кода из сообщения 13:
// Создаем соответствие для хранения цветов
Цвета = Новый Соответствие;
// Истина будет соответствовать "без раскраски" (прозрачный или белый)
Цвета.Вставить(Истина, Новый Цвет()); // Прозрачный цвет
// Цвета.Вставить(Истина, WebЦвета.Белый); // Если нужен именно белый
// Ложь будет соответствовать "с раскраской"
Цвета.Вставить(Ложь, WebЦвета.Фиолетовый);
Переключатель = Истина; // Начальное состояние: первые 5 строк без раскраски (соответствует Истина в Цвета)
АктуальныйЦвет = Цвета[Переключатель]; // Получаем начальный цвет
Счетчик = 0; // Инициализируем счетчик строк
Пока ВыборкаЗарплата.Следующий() Цикл
Счетчик = Счетчик + 1; // Увеличиваем счетчик для каждой строки
ОбластьЗарплата.Параметры.Заполнить(ВыборкаЗарплата);
ОбластьЗарплата.Область(1,2,1,4).ЦветФона = АктуальныйЦвет; // Применяем текущий актуальный цвет
ТабДок.Вывести(ОбластьЗарплата, ВыборкаЗарплата.Уровень);
// Проверяем, закончили ли мы группу из 5 строк
Если Счетчик % 5 = 0 Тогда
Переключатель = Не Переключатель; // Переключаем состояние
АктуальныйЦвет = Цвета[Переключатель]; // Получаем новый актуальный цвет из соответствия
КонецЕсли;
КонецЦикла;
Этот метод очень удобен, когда логика выбора цвета становится сложнее, или если вы хотите легко менять набор используемых цветов. Все цвета собраны в одном месте (в Соответствии), что упрощает их модификацию.
Помимо программных подходов, 1С предлагает встроенный механизм условного оформления в макетах табличных документов. Этот подход является более декларативным и часто предпочтительнее для задач, связанных с визуальным форматированием, поскольку он отделяет логику оформления от основного кода формирования отчета.
Как мы можем это использовать для чередующейся раскраски каждые 5 строк:
(Цел((НомерСтроки() - 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.
WebЦвета.Фиолетовый).Преимущества этого подхода:
Для создания такого правила:
(Цел((НомерСтроки() - 1) / 5) % 2 = 1). Убедитесь, что тип выражения "Выражение".WebЦвета.Фиолетовый.R1C1:R1C4, если вы оформляете строки в области ОбластьЗарплата.В ходе обсуждения также упоминались побитовые операции в 1С. Хотя они не используются напрямую для решения задачи циклической раскраски строк, важно знать, что 1С:Предприятие 8.3 поддерживает набор функций для работы с битами чисел. Эти функции могут быть полезны в более специализированных задачах, таких как:
В 1С доступны следующие побитовые операции:
ПобитовоеИ(<Число1>, <Число2>): Логическое побитовое И.ПобитовоеИЛИ(<Число1>, <Число2>): Логическое побитовое ИЛИ.ПобитовоеИсключающееИЛИ(<Число1>, <Число2>): Логическое побитовое исключающее ИЛИ.ПобитовоеНЕ(<Число>): Побитовое НЕ.ПобитовыйСдвигВлево(<Число>, <КоличествоРазрядов>): Сдвиг битов влево.ПобитовыйСдвигВправо(<Число>, <КоличествоРазрядов>): Сдвиг битов вправо.Знание этих операций расширяет инструментарий программиста 1С, но для задачи условного форматирования строк, которую мы рассматривали, они являются избыточными.
Мы рассмотрели несколько эффективных способов реализации чередующейся раскраски строк в печатных формах 1С с заданным шагом. Каждый подход имеет свои преимущества:
Выбор конкретного метода зависит от ваших предпочтений, сложности задачи и требований к читаемости и поддерживаемости кода. В большинстве случаев для такого рода задач мы бы рекомендовали использовать либо оператор деления по модулю в коде, либо механизм условного оформления в макете, так как они наиболее эффективны и гибки.