1С: Раскраска строк на форме списка (условное оформление)

Задача: обеспечить раскраску строк по условию на форме списка

Решение: может быть разным, в зависимости от сложности условий и способа вывода данных на форму.

Вариант 1: данные формируются запросом СКД, динамически:

В этом случае заходим во вкладку «Условное оформление» и настраиваем собственно условия:

Вариант 2: данные формируются «как обычно».

В этом случае в свойствах формы ищем реквизит «Условное оформление» и настраиваем по тому-же принципу как и в Варианте 1

Вариант 3: подходит для «сложных» вариантов оформления, когда при помощи первого и второго варианта, нужного эффекта добиться не удалось. В свойстве «ПриОткрытии» размещаем код вида:

&НаКлиенте
Процедура УстановитьУсловноеОформлениеДляПоляДатаДоговора()

   // Создание элемента условного оформления
   ЭлементыОформления = СписокПартийДС.УсловноеОформление.Элементы.Добавить();
   ЭлементыОформления.Использование = Истина;

   // Настройка оформляемого поля
   Поля = ЭлементыОформления.Поля.Элементы.Добавить();
   Поля.Использование = Истина;
   Поля.Поле = Новый ПолеКомпоновкиДанных("ДатаДог");
   Поля = ЭлементыОформления.Поля.Элементы.Добавить();
   Поля.Использование = Истина;

   // Создание условия для элемента оформления
   Отбор = ЭлементыОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
   Отбор.Использование = Истина;
   Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
   Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДатаДог");
   Отбор.ПравоеЗначение = ТекущаяДата() + 31557600;

   // Установка цвета оформления
   Оформление = ЭлементыОформления.Оформление;
   Оформление.УстановитьЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ЦветФона"), WebЦвета.ЛососьСветлый);

КонецПроцедуры

1С: Итоги в подвале на форме списка

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

1. Ставим галочку подвал в свойствах списка

2. На событие «ПриАктивацииСтроки» у списка вешаем следующий код:

&НаСервере
Функция СписокВКоллекциюЗначений()
	//Получаем схема компановки данных (здесь хранится текст запроса)
	Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();	
	//Получаем настройки пользователя (отборы, сортировки и т.п.)
	Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();	
	//Выводим динамический список в таблицу значений
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных();
	МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , ,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
	Результат = ПроцессорВывода.Вывести(ПроцессорКомпоновки);	
	//Возвращаем полученную таблицу значений
	Возврат  Результат;	
КонецФункции

&НаСервере
Функция ПосчитатьИтогиНаСервере()
	ВсеЭлементы=СписокВКоллекциюЗначений();
	ЗадолженостьПоУведомлению=0;ОстатокЗадолженности=0;ТекущаяЗадолженость=0;	
	для каждого стр из ВсеЭлементы цикл
		ЗадолженостьПоУведомлению=ЗадолженостьПоУведомлению+стр.ЗадолженостьПоУведомлению;
		ОстатокЗадолженности=ОстатокЗадолженности+стр.ОстатокЗадолженности;
		ТекущаяЗадолженость=ТекущаяЗадолженость+стр.ТекущаяЗадолженость;
	КонецЦикла;	
	элементы.Список.ПодчиненныеЭлементы.ЗадолженостьПоУведомлению.ТекстПодвала=ЗадолженостьПоУведомлению;
	элементы.Список.ПодчиненныеЭлементы.ОстатокЗадолженности.ТекстПодвала=ОстатокЗадолженности;
	элементы.Список.ПодчиненныеЭлементы.ТекущаяЗадолженость.ТекстПодвала=ТекущаяЗадолженость;
КонецФункции

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	ПосчитатьИтогиНаСервере();
КонецПроцедуры

И вуаля, видим нечто подобное:

1С и проблема чтения xlsx файлов с датами

Проблема: при разборе файла формата xlsx часть дат в ячейках сдвигается ровнехонько на 4 года назад. Т.е. открываем файл экселем — видим 2026 год. Открываем файл при помощий табличного документа 1С — видим 2022.

Долго думал.. Хорошо рядом человек оказался, который с этой проблемой уже сталкивался. Оказывается некоторые файлы xlsx сохраняются в формате в котором «эпоха» начинается с 1900г, а часть с 1904. И определить средствами 1С, в каком формате сохранен именно этот файл, нет никакой возможности — только самому делать поправку даты:

ДатаВЯчейке=ДатаВЯчейке+1462 * 86400;

Более подробно можно почитать тут

1С: Оптимизация времени разбора большого XLSX файла

Для чтения и разбора файлов формата xlsx на 1С обычно используют следующую схему разбора файла:

ТабличныйДокументХар = Новый ТабличныйДокумент; 
ТабличныйДокументХар.Прочитать(парам.ВременныйФайл,СпособЧтенияЗначенийТабличногоДокумента.Текст);		
// читаем каждый лист по отдельности
Для Каждого ОбластьТД ИЗ ТабличныйДокументХар.Области Цикл
    ОбластьФайла = ТабличныйДокументХар.ПолучитьОбласть(ОбластьТД.Имя,);
    КолВоСтрокФайла = ОбластьФайла.ПолучитьРазмерОбластиДанныхПоВертикали();
    КолВоКолонокФайла = ОбластьФайла.ПолучитьРазмерОбластиДанныхПоГоризонтали();
	НачСтрока=3;КонСтрока=0;
    НачСтрока = ?(НачСтрока = 0, 2, НачСтрока);
    КонСтрока = ?(КонСтрока = 0, КолвоСтрокФайла, КонСтрока);						
    // перебираем все строки без шапки
    Для нСтрокаТФ = НачСтрока ПО КонСтрока Цикл      				
        ПКолонка=Формат(ном_кол, "ЧГ=0");
        Данные=ОбластьФайла.ПолучитьОбласть("R"+ПСтрока + "C1").ТекущаяОбласть.Текст;
    конеццикла
конеццикла    

Так-же встречается другой вариант, у которого есть особенность — не учитывается что файл может содержать листы:

ТабличныйДокументХар = Новый ТабличныйДокумент; 
ТабличныйДокументХар.Прочитать(парам.ВременныйФайл,СпособЧтенияЗначенийТабличногоДокумента.Текст);		
КолВоСтрокФайла = ТабличныйДокументХар.ПолучитьРазмерОбластиДанныхПоВертикали();
КолВоКолонокФайла = ТабличныйДокументХар.ПолучитьРазмерОбластиДанныхПоГоризонтали();  
СтрокиДиапазона =   50000;
НачСтрокаДиапазона = 3; 
КонСтрокаДиапазона = мин(КолВоСтрокФайла, СтрокиДиапазона);
КолВоСтрокФайла_часть = КолВоСтрокФайла;
Пока  КолВоСтрокФайла_часть>0 Цикл
	ОбластьФайла = ТабличныйДокументХар.ПолучитьОбласть(НачСтрокаДиапазона,1,КонСтрокаДиапазона,КолВоКолонокФайла);		
	Если КолвоСтрокФайла = 0 Тогда ТабличныйДокументХар = Неопределено;КонецЕсли;
	Для стр = 1  по КонСтрокаДиапазона-НачСтрокаДиапазона+1 Цикл  
              Данные=ОбластьФайла.Область(стр,2).Текст;
	КонецЦикла;  
	КолВоСтрокФайла_часть = КолВоСтрокФайла_часть-СтрокиДиапазона;
	НачСтрокаДиапазона = НачСтрокаДиапазона +СтрокиДиапазона;
	КонСтрокаДиапазона = КонСтрокаДиапазона +СтрокиДиапазона;
КонецЦикла;

Если сравнивать производительность каждого метода, то выходит следующая картина (для файла размером 254 тыс строк):

Метод 1Метод 2
Время работы кода1 784 сек714 сек

1с: Формулы в макете

Задача: при формировании файла формата xlsx из заполненного макета, необходимо вставить формулы.

Решение: в макете формулы вставить не возможно, из-за ограничений платформы 1С. Однако есть другой пусть — вставить формулы уже после формирования файла xlsx. Файл этого формата, по сути zip архив, в котором содержаться файлы xml с данными листов. Поэтому вполне возможно, проставив в макете в нужные формулы в текстовом формате, заменить их на «настоящие» уже в самом файле

Примечание: Задача решена на основе разработок описанных тут и тут. К себе на сайт утащил наработки, потому что-то с «интернетом творится что-то странное» — сегодня статьи есть, а завтра их уже снесли или разместили в платный раздел.

Всю работу по преобразованию разместил в отдельны модуль:


// Процедура - Извлечь архив, распаковывает ZIP-архив в указанный каталог
Процедура ИзвлечьАрхив(ПутьФайла, ПутьКаталога) Экспорт
   ДДФайла = Новый ДвоичныеДанные(ПутьФайла);
   Поток = Новый ПотокВПамяти(ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ДДФайла));
   Попытка
       Архив = Новый ЧтениеZipФайла(Поток);
       Архив.ИзвлечьВсе(ПутьКаталога, РежимВосстановленияПутейФайловZIP.Восстанавливать);
       Архив.Закрыть();
   Исключение
       Сообщить("Ошибка при извлечении архива: " + ПутьФайла);
   КонецПопытки;
   Поток.Закрыть();                                                                                              
КонецПроцедуры

// Процедура - Собрать архив, упаковывает файлы из каталога в ZIP-архив
Процедура СобратьАрхив(ПутьКаталога, ПутьФайла) Экспорт
   Архив = Новый ЗаписьZipФайла(ПутьФайла);
   Архив.Добавить(ПутьКаталога + "\*.*",
   РежимСохраненияПутейZIP.СохранятьОтносительныеПути,
   РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);
   Архив.Записать();
КонецПроцедуры

// Функция - Получить DOM-документ из XML-файла, возвращает XML-файл как DOM-модель
Функция ПолучитьDOMДокументИзXMLФайла(ПутьXMLФайла) Экспорт
   ЧтениеXML = Новый ЧтениеXML;
   ЧтениеXML.ОткрытьФайл(ПутьXMLФайла);
   ПостроительDOM = Новый ПостроительDOM;
   ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
   ЧтениеXML.Закрыть();
   Возврат ДокументDOM;
КонецФункции

// Процедура - Сохранить DOM-документ как XML-файл, записывает DOM в указанный файл
Процедура СохранитьDOMДокументКАКXMLФайл(ДокументDOM, ПутьXMLФайла) Экспорт
   ЗаписьXML = Новый ЗаписьXML();
   ЗаписьXML.ОткрытьФайл(ПутьXMLФайла);
   ЗаписьDOM = Новый ЗаписьDOM();
   ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML);
   ЗаписьXML.Закрыть();
КонецПроцедуры

// Точка входа - непосредственно на входе - имя файла, где необходимо вставить
// формулы
Процедура ЗаполнитьФормулыВФайлеXLSX(ПутьДоФайла) экспорт    
    ВременныйКаталог = КаталогВременныхФайлов() + "\excel_temp\";    
    СоздатьКаталог(ВременныйКаталог);    
    ИзвлечьАрхив(ПутьДоФайла, ВременныйКаталог);    
    ПутьДоXMLФайлаЛист1 = ВременныйКаталог + "xl\worksheets\sheet1.xml";
    // Чтение распакованного xml-файла листа 1 в ДокументDOM
    ДокументDOM = ПолучитьDOMДокументИзXMLФайла(ПутьДоXMLФайлаЛист1);
    СтроковыеЗначения = ПолучитьDOMДокументИзXMLФайла(ВременныйКаталог + "xl\sharedStrings.xml");    
    ВсеЯчейки = ДокументDOM.ПолучитьЭлементыПоИмени("c");
    ВсеСтроки = ДокументDOM.ПолучитьЭлементыПоИмени("row");
    ВсегоСтрок = ВсеСтроки.Количество();
    ВсеСтроковыеЗначения = СтроковыеЗначения.ЭлементДокумента.ДочерниеУзлы;    
    // Обход ячеек и определение формул по произвольному алгоритму
    Для Каждого Ячейка Из ВсеЯчейки Цикл        
        ИмяЯчейки = Ячейка.ПолучитьАтрибут("r");
        Если ИмяЯчейки = Неопределено Тогда Продолжить;КонецЕсли;        
        ИмяСтолбца = Сред(ИмяЯчейки, 1, 1);
        ИмяСтроки = Сред(ИмяЯчейки, 2);        
        НомерСтроки = Число(ИмяСтроки);    
        ТипЯчейки = Ячейка.ПолучитьАтрибут("t");
        Если ТипЯчейки="s" Тогда            
           Если Ячейка.ПервыйДочерний.ИмяУзла = "v" Тогда // здесь лежит какое-то значение  
           // надо найти значение в строках SharedStrings    
              ЗначениеЯчейки = ВсеСтроковыеЗначения[Число(Ячейка.ПервыйДочерний.ТекстовоеСодержимое)];                    
                    ЭтоФормула=СтрНачинаетсяС(ЗначениеЯчейки.ТекстовоеСодержимое,"="); //    Формула начинается с "="
                    Если ЭтоФормула Тогда 
                        формула=ЗначениеЯчейки.ТекстовоеСодержимое;
						формула=СтрЗаменить(формула,"=","");
                        Пока Ячейка.ЕстьДочерниеУзлы() Цикл
                            Ячейка.УдалитьДочерний(Ячейка.ПервыйДочерний);
                        КонецЦикла;                        
                        // Заполнение формулы
                        ЭлФормула = ДокументDOM.СоздатьЭлемент("f");
                        ЭлФормула.ТекстовоеСодержимое = Формула;                    
                        Ячейка.ДобавитьДочерний(ЭлФормула);
                    КонецЕсли;
           КонецЕсли;
        КонецЕсли;
    КонецЦикла;    
    // Запись модифицированного объекта ДокументDOM в xml-файл листа 1
    СохранитьDOMДокументКАКXMLФайл(ДокументDOM, ПутьДоXMLФайлаЛист1);    
    УдалитьФайлы(ПутьДоФайла);    
    СобратьАрхив(ВременныйКаталог, ПутьДоФайла);    
    УдалитьФайлы(ВременныйКаталог);    
КонецПроцедуры

Как использовать:

ТабДок=Новый ТабличныйДокумент;
Макет=ПолучитьОбщийМакет("ШаблонЛКУКЛС");
...
ОбластьТушка=Макет.ПолучитьОбласть("Тушка");
ОбластьТушка.Параметры.Разница="=G"+(ГСч+1)+"-H"+(ГСч+1); // = означает что тут формула в ячейке
ТабДок.Вывести(ОбластьТушка);					
...

ВрФайл=ПолучитьИмяВременногоФайла("xlsx");
ТабДок.Записать(ВрФайл,ТипФайлаТабличногоДокумента.XLSX);
						
СК_ГР_ФормулыВмакете.ЗаполнитьФормулыВФайлеXLSX(ВрФайл); // А теперь магия! Вставим формулу..
1 2 3 52