Программный запуск отчета 1с 8.3 (управляемые формы)

Если нужно по кнопке на произвольной форме запустить отчет с параметрами (отбором) написанный на СКД, можно сделать как показано далее. Создадим простой отчет  — продажи по номенклатурным группам (Конфигурация 1С Бухгалтерия 3.0). Запрос отчета:

ВЫБРАТЬ
   РеализацияУслугОбороты.НоменклатурнаяГруппа,
   РеализацияУслугОбороты.СуммаОборот
ИЗ
   РегистрНакопления.РеализацияУслуг.Обороты КАК РеализацияУслугОбороты

Настройки отчета в СКД:

salerep

Обратим внимание на форму отчета, в верхней части размещен отбор ФИКСИРОВАННЫХ НАСТРОЕК, обратите на это внимание.

repparam2

Отчет надо поместить в конфигурацию. Допустим, есть обработка и надо вывеси отчет с отбором  по номенклатурной группе, в обработке создаем команду и в клиентском обработчике пишем код:

ОтборОтчета = новый Структура(«НоменклатурнаяГруппа», Ссылка_НоменклатурнаяГруппа);
ПараметрыОтчета = Новый Структура(«СформироватьПриОткрытии, Отбор», истина, ОтборОтчета);
ОткрытьФорму(«Отчет.ПродажиПоНоменклатурнымГруппам.Форма», ПараметрыОтчета);

В переменной «Ссылка_НоменклатурнаяГруппа» указана номенклатурная группа по которой делается отбор. В результате, получим такой вид сформированного отчета:

repfinal

Замена обработки в конфигурации

Если надо существующую обработку в конфигурации заменить на новую, например кем-то подправленную, необходимо запустить 1С в режиме конфигуратора, найти в дереве нужную обработку, затем в контекстном меню выбрать «Заменить на внешнюю обработку, отчет …»

chobrab

Затем выберите файл с нужной обработкой, в диалоге выбора нажмите «Открыть»:

dialopen

Обновите конфигурацию и перезапустите 1С Предприятие:

renconf

Обработка загружена и готова к использованию.

Как установить параметр СКД программно (управляемые формы)

&НаСервере
Процедура УстановитьПараметрСКД()
   ПараметрСКД = Отчет.КомпоновщикНастроек.
Настройки.ПараметрыДанных.

  Элементы.Найти(«ИмяПараметра»)
  ПараметрСКД.Использование = Истина;
  ПараметрСКД.Значение = Значение;
КонецПроцедуры

Чтение файлов Excel при помощи ADO

При больших файлах Excel чтение каждой ячейки через COM объект Excel.Application приводит к большим затратам времени, для ускорения процесса чтения можно воспользоваться объектом ADODB. Обработка происходит на клиенте, поэтому файл Excel читается в массив строк, где строка представлена как массив.

&НаКлиенте
Функция ПолучитьМассивXLSФайла(ИмяФайлаЗагрузки)

Connection = Новый COMОбъект(«ADODB.Connection»);
// Можно использовать строку подключения для Excel ранее 2007
//СтрокаПодключения = «Provider=Microsoft.Jet.OLEDB.4.0; Data Source = » + ИмяФайлаЗагрузки;
СтрокаПодключения = «Provider=Microsoft.ACE.OLEDB.12.0; Data Source = « + ИмяФайлаЗагрузки;
СтрокаПодключения = СтрокаПодключения+«; Extended Properties = «+«»»Excel 8.0″+»;HDR=NO;IMEX=1″»;»;

Попытка
   Connection.Open(СтрокаПодключения);
Исключение
   Сообщить(ОписаниеОшибки());
   Возврат Неопределено;
КонецПопытки;

Command = Новый COMОбъект(«ADODB.Command»);
axCatalog = Новый COMОбъект(«ADOX.Catalog»);
axCatalog.ActiveConnection = Connection;
// получить имя первого листа
Для каждого Лист ИЗ axCatalog.Tables Цикл
      ИмяТаблицы = Лист.Name;
      Прервать;
КонецЦикла;

RecordSet = Новый COMОбъект(«ADODB.RecordSet»);
Command.ActiveConnection = Connection;
Command.CommandText =«SELECT COUNT(*) FROM [«+ИмяТаблицы+«]»;
Command.CommandType =1;
RecordSet = Command.Execute();
КоличествоСтрок = RecordSet.Fields(0).Value;
Command.CommandText = «SELECT * FROM [«+ИмяТаблицы+«]»;
Command.CommandType = 1;
Попытка
      RecordSet = Command.Execute();
Исключение
      Сообщить(ОписаниеОшибки());
КонецПопытки;

RecordSet.MoveNext();
ФайлВФормеМассива = новый Массив;

Пока RecordSet.EOF() = 0 Цикл
   МассивСтроки = новый Массив;
   для НомерПоля = 1 по RecordSet.Fields.Count цикл
      МассивСтроки.Добавить(RecordSet.Fields(НомерПоля1).Value);
   КонецЦикла;
   ФайлВФормеМассива.Добавить(МассивСтроки);
   RecordSet.MoveNext();
КонецЦикла;
RecordSet.Close();
Connection.Close();

Возврат ФайлВФормеМассива;

КонецФункции

Если названия листов на русском языке, то после имени листа надо ставить знак «$».

Как получить макет отчета в управляемой форме

Функция ПолучитьМакетНаСервере()

ОбъектОтчета = РеквизитФормыВЗначение(«Отчет»);
Макет = ОбъектОтчета.ПолучитьМакет(«Макет»);
Возврат Макет;

КонецФункции

Форматирование области табличного документа

Программное изменение внешнего вида табличного документа позволяет изменить границу ячейки или области (на примере — пунктирная граница):

ГраницаПунктир = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.РедкийПунктир,1);

ОбластьМакета = Макет.ПолучитьОбласть(«СтрокаТаблицы»);

ОбластьМакета.Область(«R1C4:R1C7»).ГраницаСнизу = ГраницаПунктир;
ОбластьМакета.Область(«R2C4:R2C7»).ГраницаСверху = ГраницаПунктир;
ОбластьМакета.Область(«R1C4:R1C7»).ГраницаСлева = ГраницаПунктир;
ОбластьМакета.Область(«R1C4:R1C7»).ГраницаСправа = ГраницаПунктир;

Так же можно программно объединять ячейки в табличном документе:

ТабДок.Область(«R1C1:R1C4»).Объединить();

Удаление дублей иерархии при получении результата запроса

При использовании запросов с оператором ИЕРАРХИЯ и последующей выгрузке в дерево есть проблема, с которой знакомы большинство программистов — наличие дублей в иерархии, на справочника номенклатуры:

Запрос и результат:

request

Чтобы убрать дубли после получения дерева значений из результата запроса можно воспользоваться функциями ниже. Поле ключа — поле иерархии (Номенклатура).

Функция УдалитьДублирующиесяУзлыДерева(Дерево, _ПоляКлюча) Экспорт

ПоляКлюча = СтрРазделить(_ПоляКлюча, «,»);
Дерево2 = новый ДеревоЗначений;
для каждого колонка из Дерево.Колонки цикл
Дерево2.Колонки.Добавить(колонка.Имя, колонка.ТипЗначения);
КонецЦикла;
для каждого СтрКорня из Дерево.Строки цикл
НС = Дерево2.Строки.Добавить();
ЗаполнитьЗначенияСвойств(НС, СтрКорня);
СкопироватьРекурсивно(НС, СтрКорня, ПоляКлюча);
КонецЦикла;

Возврат Дерево2;

КонецФункции

Процедура СкопироватьРекурсивно(СтрокаКопия, СтрДерева, ПоляКлюча)

для каждого СтрПотомка из СтрДерева.Строки цикл
ЕстьРазличия = ложь;
для каждого ПолеКлюча из ПоляКлюча цикл
Если СтрПотомка[ПолеКлюча] <> СтрДерева[ПолеКлюча] тогда
ЕстьРазличия = истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЕстьРазличия тогда
НС = СтрокаКопия.Строки.Добавить();
ЗаполнитьЗначенияСвойств(НС, СтрПотомка);
СкопироватьРекурсивно(НС, СтрПотомка, ПоляКлюча);
Иначе
СкопироватьРекурсивно(СтрокаКопия, СтрПотомка, ПоляКлюча);
КонецЕсли;
КонецЦикла;

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

Печать на принтере документов Word и Excel из 1Сv8.3

Если требуется немедленная программная печать на принтере по выбору, к примеру,  при распечатке прикрепленных документов. Ниже приведен код, позволяющий распечатать документы Word и Excel:

&НаКлиенте
Процедура ПечатьDOCФайлов(ПутьКФайлу, ИмяПринтера = «»
WordAppl = Новый COMОбъект(«Word.Application»);
WordAppl.Documents.Open(ПутьКФайлу);
WordAppl.Documents(ПутьКФайлу).Activate();
WordAppl.ActivePrinter = ИмяПринтера;
WordAppl.ActiveDocument.PrintOut();
WordAppl.ActiveDocument.close();
КонецПроцедуры

&НаКлиенте
Процедура ПечатьExcelФайлов(ПутьКФайлу, ИмяПринтера = «»)
ExcelAppl = Новый COMОбъект(«Excel.Application»);
ExcelAppl.Workbooks.Open(ПутьКФайлу);
ExcelAppl.ActiveSheet.PrintOut(,,,,ИмяПринтера);
ExcelAppl.WorkBooks.Close();
ExcelAppl.Quit();
КонецПроцедуры

Полезные функции

Выделяет из строки числовые символы и возвращает число
Функция ОставитьЧисловыеСимволыВСтроке(СтрокаСЧислом, ВернутьЧисло=истина)

ДлинаСтроки = СтрДлина(СтрокаСЧислом);
СтрокаФинал = «»;
для й=1 по ДлинаСтроки цикл
ТекСимвол = Сред(СтрокаСЧислом,й,1);
Если ТекСимвол >= «0» и ТекСимвол <= «9» тогда
СтрокаФинал = СтрокаФинал + ТекСимвол;
КонецЕсли;
КонецЦикла;
Возврат ?(ВернутьЧисло, Число(СтрокаФинал), СтрокаФинал);
КонецФункции

Получение описания типа (для динамического добавления колонки в таблицу значений)
Функция ПолучитьОписаниеЦелочисленногоТипа() Экспорт

КЧ = Новый КвалификаторыЧисла(10);
Массив = Новый Массив;
Массив.Добавить(Тип(«Число»));
Возврат Новый ОписаниеТипов(Массив, , ,КЧ);
КонецФункции

Преобразование строки таблицы значений в структуру
Функция СтрокуТЗВСтруктуру(ТЗ, НомерСтроки=0) Экспорт
Стрктура = новый Структура;
для каждого Колонка из ТЗ.Колонки цикл
Стрктура.Вставить(Колонка.Имя, ТЗ[НомерСтроки][Колонка.Имя]);
КонецЦикла;
возврат Стрктура;
КонецФункции

Функция для получения описания типов строки, заданной длины
Функция ПолучитьОписаниеТиповСтроки(ДлинаСтроки
Массив = Новый Массив;
Массив.Добавить(Тип(«Строка»));
КвалификаторСтроки = Новый КвалификаторыСтроки(ДлинаСтроки, ДопустимаяДлина.Переменная);
Возврат Новый ОписаниеТипов(Массив, , КвалификаторСтроки);
КонецФункции

Функция для получения описания типов числа, заданной разрядности
Функция ПолучитьОписаниеТиповЧисла(Разрядность,РазрядностьДробнойЧасти=0
Массив = Новый Массив;
Массив.Добавить(Тип(«Число»));
КвалификаторЧисла = Новый КвалификаторыЧисла(Разрядность,РазрядностьДробнойЧасти);
Возврат Новый ОписаниеТипов(Массив, КвалификаторЧисла);
КонецФункции

Функция для получения описания типов даты
Функция ПолучитьОписаниеТиповДаты(ЧастиДаты
Массив = Новый Массив;
Массив.Добавить(Тип(«Дата»));
КвалификаторДаты = Новый КвалификаторыДаты(ЧастиДаты);
Возврат Новый ОписаниеТипов(Массив, , , КвалификаторДаты);
КонецФункции

Создание дерева в СКД и выгрузка его в дерево значений

Допустим, имеется таблица с товарами и суммами, колонки приведены ниже:
— Идентификатор строки (id)
— Идентификатор строки родителя (idParent)
— Наименование (строка)
— Сумма

id idParent Наименование Сумма (руб.)
1 Монитор 5000
2 Мышь, клавиатура 2000
3 Системный блок
4 3 Материнская плата 10000
5 3 Жесткий диск 3000

Колонка «Наименование» не является справочником и не позволяет автоматически создать иерархию, конечно ее можно создать программно, но это трудоемко, особенно собирать суммы итогов по иерархии. Итак, нам нужно получить дерево значений без особо трудного кодирования. Для начала, создадим СКД и создадим 2 частично одинаковых выборки с данными, как показано на рисунках ниже:

Первая выборка, задающая иерархию

SetIerarh

Вторая выборка, такая же как первая, но содержит больше колонок

SetData

Связи между выборками, образующих дерево

svyaz

Структура итоговых данных — само дерево

report

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

result

Ниже приведен код, позволяющий получить дерево из СКД в переменную «ДеревоЗначений»:

СхемаКомпоновкиДанных = РеквизитФормыВЗначение(«Отчет»).ПолучитьМакет(«МакетДанные»);
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);

НастройкиКомпоновщика = КомпоновщикНастроек.Настройки;
ПараметрыНастройки = НастройкиКомпоновщика.ПараметрыДанных;

// если нужны параметры — устанавливаем так
Параметр = ПараметрыНастройки.Элементы.Найти(«Дата»);
Параметр.Использование = Истина;
Параметр.Значение = Отчет.Дата;

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