При доработке ЗУПа потребовалось во фронте расчетчика информативно выводить все плановые начисления и удержания по сотруднику на текущий момент. В результате 2 удобные функции, результат возвращают в виде таблицы значений:
Код 1C v 8.3 Функция ПолучитьСписокПлановыхНачислений(Организация, Сотрудник, ДатаО) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПлановыеНачисленияСрезПоследних.Период,
| ПлановыеНачисленияСрезПоследних.ВидРасчета,
| ПлановыеНачисленияСрезПоследних.Показатель1,
| ПлановыеНачисленияСрезПоследних.Валюта1,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд1,
| ПлановыеНачисленияСрезПоследних.Показатель2,
| ПлановыеНачисленияСрезПоследних.Валюта2,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд2,
| ПлановыеНачисленияСрезПоследних.Показатель3,
| ПлановыеНачисленияСрезПоследних.Валюта3,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд3,
| ПлановыеНачисленияСрезПоследних.Показатель4,
| ПлановыеНачисленияСрезПоследних.Валюта4,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд4,
| ПлановыеНачисленияСрезПоследних.Показатель5,
| ПлановыеНачисленияСрезПоследних.Валюта5,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд5,
| ПлановыеНачисленияСрезПоследних.Показатель6,
| ПлановыеНачисленияСрезПоследних.Валюта6,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд6,
| ПлановыеНачисленияСрезПоследних.Действие,
| ПлановыеНачисленияСрезПоследних.ПериодЗавершения,
| ПлановыеНачисленияСрезПоследних.ВидРасчетаЗавершения,
| ПлановыеНачисленияСрезПоследних.ДействиеЗавершения,
| ПлановыеНачисленияСрезПоследних.Показатель1Завершения,
| ПлановыеНачисленияСрезПоследних.Показатель2Завершения,
| ПлановыеНачисленияСрезПоследних.Показатель3Завершения,
| ПлановыеНачисленияСрезПоследних.Показатель4Завершения,
| ПлановыеНачисленияСрезПоследних.Показатель5Завершения,
| ПлановыеНачисленияСрезПоследних.Показатель6Завершения,
| ПлановыеНачисленияСрезПоследних.Валюта1Завершения,
| ПлановыеНачисленияСрезПоследних.Валюта2Завершения,
| ПлановыеНачисленияСрезПоследних.Валюта3Завершения,
| ПлановыеНачисленияСрезПоследних.Валюта4Завершения,
| ПлановыеНачисленияСрезПоследних.Валюта5Завершения,
| ПлановыеНачисленияСрезПоследних.Валюта6Завершения,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд1Завершения,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд2Завершения,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд3Завершения,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд4Завершения,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд5Завершения,
| ПлановыеНачисленияСрезПоследних.ТарифныйРазряд6Завершения,
| ПлановыеНачисленияСрезПоследних.Регистратор
|ИЗ
| РегистрСведений.ПлановыеНачисленияРаботниковОрганизаций.СрезПоследних(
| &ДатаСреза,
| Организация =ГоловнаяОрганизация
| И Сотрудник =Ссылка) КАК ПлановыеНачисленияСрезПоследних
|ГДЕ
| ВЫБОР
| КОГДА ПлановыеНачисленияСрезПоследних.Действие = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.Прекратить)
| И ПлановыеНачисленияСрезПоследних.ДействиеЗавершения = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.ПустаяСсылка)
| ТОГДА ЛОЖЬ
| КОГДА ПлановыеНачисленияСрезПоследних.Действие = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.Прекратить)
| И ПлановыеНачисленияСрезПоследних.ДействиеЗавершения <> ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.ПустаяСсылка)
| ИДатаСреза < ПлановыеНачисленияСрезПоследних.ПериодЗавершения
| ТОГДА ЛОЖЬ
| КОГДА ПлановыеНачисленияСрезПоследних.ДействиеЗавершения = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.Прекратить)
| ИДатаСреза >= ПлановыеНачисленияСрезПоследних.ПериодЗавершения
| ТОГДА ЛОЖЬ
| ИНАЧЕ ИСТИНА
| КОНЕЦ";
Запрос.УстановитьПараметр("ГоловнаяОрганизация", Организация);
Запрос.УстановитьПараметр("ДатаСреза", ДатаО);
Запрос.УстановитьПараметр("Ссылка", Сотрудник);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Функция ПолучитьСписокПлановыхУдержаний(Организация, Сотрудник, ДатаО) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПлановыеУдержанияСрезПоследних.Период,
| ПлановыеУдержанияСрезПоследних.ВидРасчета,
| ПлановыеУдержанияСрезПоследних.Показатель1,
| ПлановыеУдержанияСрезПоследних.Валюта1,
| ПлановыеУдержанияСрезПоследних.Показатель2,
| ПлановыеУдержанияСрезПоследних.Валюта2,
| ПлановыеУдержанияСрезПоследних.Показатель3,
| ПлановыеУдержанияСрезПоследних.Валюта3,
| ПлановыеУдержанияСрезПоследних.Показатель4,
| ПлановыеУдержанияСрезПоследних.Валюта4,
| ПлановыеУдержанияСрезПоследних.Показатель5,
| ПлановыеУдержанияСрезПоследних.Валюта5,
| ПлановыеУдержанияСрезПоследних.Показатель6,
| ПлановыеУдержанияСрезПоследних.Валюта6,
| ПлановыеУдержанияСрезПоследних.Действие,
| ПлановыеУдержанияСрезПоследних.ПериодЗавершения,
| ПлановыеУдержанияСрезПоследних.ДействиеЗавершения,
| ПлановыеУдержанияСрезПоследних.Показатель1Завершения,
| ПлановыеУдержанияСрезПоследних.Показатель2Завершения,
| ПлановыеУдержанияСрезПоследних.Показатель3Завершения,
| ПлановыеУдержанияСрезПоследних.Показатель4Завершения,
| ПлановыеУдержанияСрезПоследних.Показатель5Завершения,
| ПлановыеУдержанияСрезПоследних.Показатель6Завершения,
| ПлановыеУдержанияСрезПоследних.Валюта1Завершения,
| ПлановыеУдержанияСрезПоследних.Валюта2Завершения,
| ПлановыеУдержанияСрезПоследних.Валюта3Завершения,
| ПлановыеУдержанияСрезПоследних.Валюта4Завершения,
| ПлановыеУдержанияСрезПоследних.Валюта5Завершения,
| ПлановыеУдержанияСрезПоследних.Валюта6Завершения,
| ПлановыеУдержанияСрезПоследних.Регистратор
|ИЗ
| РегистрСведений.ПлановыеУдержанияРаботниковОрганизаций.СрезПоследних(
| &ДатаСреза,
| Организация =ГоловнаяОрганизация
| И Физлицо =Ссылка) КАК ПлановыеУдержанияСрезПоследних
|ГДЕ
| ВЫБОР
| КОГДА ПлановыеУдержанияСрезПоследних.Действие = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.Прекратить)
| И ПлановыеУдержанияСрезПоследних.ДействиеЗавершения = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.ПустаяСсылка)
| ТОГДА ЛОЖЬ
| КОГДА ПлановыеУдержанияСрезПоследних.Действие = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.Прекратить)
| И ПлановыеУдержанияСрезПоследних.ДействиеЗавершения <> ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.ПустаяСсылка)
| ИДатаСреза < ПлановыеУдержанияСрезПоследних.ПериодЗавершения
| ТОГДА ЛОЖЬ
| КОГДА ПлановыеУдержанияСрезПоследних.ДействиеЗавершения = ЗНАЧЕНИЕ(Перечисление.ВидыДействияСНачислением.Прекратить)
| ИДатаСреза >= ПлановыеУдержанияСрезПоследних.ПериодЗавершения
| ТОГДА ЛОЖЬ
| ИНАЧЕ ИСТИНА
| КОНЕЦ";
Запрос.УстановитьПараметр("ГоловнаяОрганизация", Организация);
Запрос.УстановитьПараметр("ДатаСреза", ДатаО);
Запрос.УстановитьПараметр("Ссылка", Сотрудник.Физлицо);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
При написании небольших автоматизированных тестов часто надо обойти всю конфигурацию и проверить, например, для всех форм какое-нибудь свойство. Это всё легко делается через свойство глобального контекста "Метаданные", но чтоб дорбаться до обхода реквизитов надо написать кучу вложенных циклов. При этом код становится слабочитаемым и слабомодифицируемым.
Ниже приведен небольшой модуль, который решает задачу легко и удобно. Создана специальная функция РазвернутьСтрокуОбходаМетаданных, которая может по строке типа "Метаданные.Справочники.*.Реквизиты.*" построить массив строк с перечислением всех реквизитов всех справочников. При помощи этой и нескольких других функций в экспортных функциях модуля реализованы вполне прикладные задачи - получение всех реквизитов, всех макетов, всех форм конфигурации и построение таблицы всех составных типов.
Код 1C v 8.х // Автор: Alexander Speshilov
// Рекрсивная функция, которая разворачивает строку вида "Метаданные.Справочники.*[Имя].Реквизиты.*.Тип"
// в массив строк, заменяя "*" или другой символ, задаваемый параметрами обходом всех элементов
// коллекции. Допускает выполнение функций встроенного языка (не стоит отдавать ввод параметров
// пользователям). При этом выражение, используемое для получения по умолчанию может быть задано в
// квадратных скобках или параметром функции.
//
// Параметры
// СтрокаОбхода - Строка - Разворачиваемая строка
// ЗаменяемоеЗначение - Строка - заменяемое значение
// ПредставлениеПоУмолчанию - Строка - выражение для получения представления
//
// Возвращаемое значение:
// Массив строк
//
Функция РазвернутьСтрокуОбходаМетаданных(СтрокаОбхода, ЗаменяемоеЗначение = "*", ПредставлениеПоУмолчанию = "")
Рез = Новый Массив;
ЧастиСтрокиОбхода = РазобратьСтрокуОбхода(СтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию);
Если ЧастиСтрокиОбхода = Неопределено тогда
Рез.Добавить(СтрокаОбхода); //фактически это ограничение рекурсии.
Иначе
ОбъектКоллекции = Вычислить(ЧастиСтрокиОбхода.СтрокаКоллекции);
РазвернутаяКоллекция = РазвернутьКоллекциюВПредставления(ОбъектКоллекции, ЧастиСтрокиОбхода.СтрокаПредставление);
Для каждого ЭлементРазвернутойКоллекции Из РазвернутаяКоллекция Цикл
// рекурсивный вызов
ТекущаяСтрокаОбхода = ЧастиСтрокиОбхода.СтрокаНачало + ЭлементРазвернутойКоллекции + ЧастиСтрокиОбхода.СтрокаКонец;
МассивЭлемента = РазвернутьСтрокуОбходаМетаданных(ТекущаяСтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию);
Для каждого ПримитивныйЭлементОбхода Из МассивЭлемента Цикл
Рез.Добавить(ПримитивныйЭлементОбхода);
КонецЦикла;
КонецЦикла;
КонецЕсли;
Возврат Рез;
КонецФункции // РазвернутьСтрокуОбходаМетаданных()
// Разбирает строку обхода на удобные для работы поля
//
// Параметры
// СтрокаОбхода - Строка - Разворачиваемая строка
// ЗаменяемоеЗначение - Строка - заменяемое значение
// ПредставлениеПоУмолчанию - Строка - выражение для получения представления
//
// Возвращаемое значение:
// Структура с полями ПозицияЗамены, СтрокаНачало, СтрокаКоллекции, СтрокаПредставление, СтрокаКонец
// или Неопределено (если строка не содержит ЗаменяемоеЗначение)
//
Функция РазобратьСтрокуОбхода(СтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию)
Если ПустаяСтрока(ЗаменяемоеЗначение) Тогда
ВызватьИсключение "Некорректное выражение заменяемого значения";
КонецЕсли;
ПозицияЗамены = Найти(СтрокаОбхода, ЗаменяемоеЗначение);
// Если не найдена строка - возвращаем неопределено, как индикатор
Если ПозицияЗамены = 0 Тогда
Возврат Неопределено;
КонецЕсли;
СтрокаНачало = Лев(СтрокаОбхода,ПозицияЗамены - 1);
//Получение строки для выражения-коллекции
СтрокаКоллекции = СтрокаНачало;
Если Прав(СтрокаКоллекции, 1) = "." Тогда
СтрокаКоллекции = Лев(СтрокаКоллекции,СтрДлина(СтрокаКоллекции) - 1);
КонецЕсли;
ПозицияОкончанияЗамены = ПозицияЗамены + СтрДлина(ЗаменяемоеЗначение);
ОстатокВыражения = Сред(СтрокаОбхода, ПозицияОкончанияЗамены);
//Обработка явного задания представления
ОткрывающаяСкобка = "[";
ЗакрывающаяСкобка = "]";
Если Найти(ОстатокВыражения, ОткрывающаяСкобка) = 1 Тогда
ОстатокВыражения = Сред(ОстатокВыражения, СтрДлина(ОткрывающаяСкобка) + 1);
ПозицияЗакрывающейСкобки = Найти(ОстатокВыражения, ЗакрывающаяСкобка);
Если ПозицияЗакрывающейСкобки = 0 Тогда
ВызватьИсключение "Синтаксическая ошибка разбора выражения";
КонецЕсли;
СтрокаПредставление = Лев(ОстатокВыражения, ПозицияЗакрывающейСкобки - 1);
ОстатокВыражения = Сред(ОстатокВыражения, ПозицияЗакрывающейСкобки + СтрДлина(ЗакрывающаяСкобка));
Иначе
СтрокаПредставление = ПредставлениеПоУмолчанию;
КонецЕсли;
СтрокаКонец = ОстатокВыражения;
Рез = Новый Структура("ПозицияЗамены, СтрокаНачало, СтрокаКоллекции, СтрокаПредставление, СтрокаКонец",
ПозицияЗамены, СтрокаНачало, СтрокаКоллекции, СтрокаПредставление, СтрокаКонец);
Возврат Рез;
КонецФункции // РазобратьСтрокуОбхода()
// Разворачивает объект коллекции в массив представления элементов
//
// Параметры
// Коллекция - Произвольный - Коллекция, которую можно обойти через "Для каждого"
// ПредставлениеЭлемента - Строка - необяз., свойство элементов коллекции, которое
// используется для получения представления.
//
// Возвращаемое значение:
// Массив - Массив представлений коллекции
//
Функция РазвернутьКоллекциюВПредставления(Коллекция, Знач ПредставлениеЭлемента = "")
//Проверка и подгонка параметров
Если не ПустаяСтрока(ПредставлениеЭлемента) Тогда
Если Найти(ПредставлениеЭлемента, ";")>0 Тогда
ВызватьИсключение "Некорректное выражение представления";
КонецЕсли;
ПредставлениеЭлемента = "." + ПредставлениеЭлемента;
КонецЕсли;
Рез = Новый Массив;
Для каждого ЭлементКоллекции Из Коллекция Цикл
ТекПредставление = Строка(Вычислить("ЭлементКоллекции" + ПредставлениеЭлемента));
Рез.Добавить(ТекПредставление);
КонецЦикла;
Возврат Рез;
КонецФункции // РазвернутьКоллекцию()
// Разворачивает массив строк через РазвернутьСтрокуОбходаМетаданных
//
// Параметры
// МассивСтрокОбхода - Массив - Массив разворачиваемых строк
// ЗаменяемоеЗначение - Строка - заменяемое значение
// ПредставлениеПоУмолчанию - Строка - выражение для получения представления
//
// Возвращаемое значение:
// Массив строк
//
Функция РазвернутьМассивСтрокОбходаМетаданных(МассивСтрокОбхода, ЗаменяемоеЗначение = "*", ПредставлениеПоУмолчанию = "Имя")
Рез = Новый Массив;
Для каждого СтрокаОбхода Из МассивСтрокОбхода Цикл
ДополнениеРезультата = РазвернутьСтрокуОбходаМетаданных(СтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию);
Для каждого ТекСтрока Из ДополнениеРезультата Цикл
Рез.Добавить(ТекСтрока);
КонецЦикла;
КонецЦикла;
Возврат Рез;
КонецФункции // РазвернутьМассивСтрокОбходаМетаданных()
// Преобразует строку в массив одиночных строк по разделителю Символы.ПС
//
// Параметры
// ПреобразуемаяСтрока - строка для преобразования
// ИгнорироватьПустые - Булево - Пропускать пустые строки
// СокращатьПробелы - Использовать СокрЛП
//
// Возвращаемое значение:
// Массив строк
//
Функция ПолучитьМассивСтрокМногострочнойСтроки(ПреобразуемаяСтрока, ИгнорироватьПустые = Истина, СокращатьПробелы = Истина)
Рез = Новый Массив;
ЧислоСтрок = СтрЧислоСтрок(ПреобразуемаяСтрока);
Для Сч = 1 По ЧислоСтрок Цикл
ТекСтрока = СтрПолучитьСтроку(ПреобразуемаяСтрока, Сч);
Если ИгнорироватьПустые и ПустаяСтрока(ТекСтрока) Тогда
Продолжить;
КонецЕсли;
Если СокращатьПробелы Тогда
ТекСтрока = СокрЛП(ТекСтрока);
КонецЕсли;
Рез.Добавить(ТекСтрока);
КонецЦикла;
Возврат Рез;
КонецФункции // ПолучитьМассивСтрокМногострочнойСтроки()
// Возвращает все реквизиты конфигурации, которые сохраняются в ИБ
//
// Параметры - Нет
//
// Возвращаемое значение:
// Массив объектов метаданных
//
Функция ПолучитьВсеХранимыеРеквизитыКонфигурации() Экспорт
СтрокаВсехРеквизитов =
"
|Метаданные.Константы.*
|Метаданные.ПланыОбмена.*.Реквизиты.*
|Метаданные.ПланыОбмена.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Справочники.*.Реквизиты.*
|Метаданные.Справочники.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Документы.*.Реквизиты.*
|Метаданные.Документы.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Последовательности.*.Измерения.*
|Метаданные.ПланыВидовХарактеристик.*.Реквизиты.*
|Метаданные.ПланыВидовХарактеристик.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.ПланыСчетов.*.Реквизиты.*
|Метаданные.ПланыСчетов.*.ПризнакиУчета.*
|Метаданные.ПланыСчетов.*.ПризнакиУчетаСубконто.*
|Метаданные.ПланыСчетов.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.ПланыВидовРасчета.*.Реквизиты.*
|Метаданные.ПланыВидовРасчета.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.РегистрыСведений.*.Измерения.*
|Метаданные.РегистрыСведений.*.Ресурсы.*
|Метаданные.РегистрыСведений.*.Реквизиты.*
|Метаданные.РегистрыНакопления.*.Измерения.*
|Метаданные.РегистрыНакопления.*.Ресурсы.*
|Метаданные.РегистрыНакопления.*.Реквизиты.*
|Метаданные.РегистрыБухгалтерии.*.Измерения.*
|Метаданные.РегистрыБухгалтерии.*.Ресурсы.*
|Метаданные.РегистрыБухгалтерии.*.Реквизиты.*
|Метаданные.РегистрыРасчета.*.Измерения.*
|Метаданные.РегистрыРасчета.*.Ресурсы.*
|Метаданные.РегистрыРасчета.*.Реквизиты.*
|Метаданные.БизнесПроцессы.*.Реквизиты.*
|Метаданные.БизнесПроцессы.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Задачи.*.Реквизиты.*
|Метаданные.Задачи.*.РеквизитыАдресации.*
|Метаданные.Задачи.*.ТабличныеЧасти.*.Реквизиты.*
|";
ВсеХранимыеРеквизитыКонфигурации = РазвернутьМассивСтрокОбходаМетаданных(ПолучитьМассивСтрокМногострочнойСтроки(СтрокаВсехРеквизитов));
Возврат ВсеХранимыеРеквизитыКонфигурации;
КонецФункции // ПолучитьВсеХранимыеРеквизитыКонфигурации()
// Возвращает все реквизиты конфигурации составного типа, которые сохраняются в ИБ
//
// Параметры - Нет
//
// Возвращаемое значение:
// ТаблицаЗначений
//
Функция ПолучитьВсеХранимыеРеквизитыКонфигурацииСоставногоТипа() Экспорт
ВсеХранимыеРеквизитыКонфигурации = ПолучитьВсеХранимыеРеквизитыКонфигурации();
Рез = Новый ТаблицаЗначений;
Рез.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
Рез.Колонки.Добавить("Тип", Новый ОписаниеТипов("ОписаниеТипов"));
Рез.Колонки.Добавить("КоличествоПростыхТипов", Новый ОписаниеТипов("Число"));
Для каждого ТекРеквизит Из ВсеХранимыеРеквизитыКонфигурации Цикл
Реквизит = Вычислить(ТекРеквизит);
Тип = Реквизит.Тип;
КоличествоПростыхТипов = Тип.Типы().Количество();
Если КоличествоПростыхТипов<>1 Тогда
ТекСтрока = Рез.Добавить();
ТекСтрока.Имя = ТекРеквизит;
ТекСтрока.Тип = Тип;
ТекСтрока.КоличествоПростыхТипов = КоличествоПростыхТипов;
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции // ПолучитьВсеХранимыеРеквизитыКонфигурации()
// Возвращает все формы конфигурации
//
// Параметры - Нет
//
// Возвращаемое значение:
// Массив объектов метаданных
//
Функция ПолучитьВсеФормыКонфигурации() Экспорт
СтрокаВсехРеквизитов =
"
|Метаданные.ПланыОбмена.*.Формы.*
|Метаданные.КритерииОтбора.*.Формы.*
|Метаданные.ОбщиеФормы.*
|Метаданные.Справочники.*.Формы.*
|Метаданные.Документы.*.Формы.*
|Метаданные.ЖурналыДокументов.*.Формы.*
|Метаданные.Перечисления.*.Формы.*
|Метаданные.Отчеты.*.Формы.*
|Метаданные.Обработки.*.Формы.*
|Метаданные.ПланыВидовХарактеристик.*.Формы.*
|Метаданные.ПланыСчетов.*.Формы.*
|Метаданные.ПланыВидовРасчета.*.Формы.*
|Метаданные.РегистрыСведений.*.Формы.*
|Метаданные.РегистрыНакопления.*.Формы.*
|Метаданные.РегистрыБухгалтерии.*.Формы.*
|Метаданные.РегистрыРасчета.*.Формы.*
|Метаданные.БизнесПроцессы.*.Формы.*
|Метаданные.Задачи.*.Формы.*
|";
ВсеФормыКонфигурации = РазвернутьМассивСтрокОбходаМетаданных(ПолучитьМассивСтрокМногострочнойСтроки(СтрокаВсехРеквизитов));
Возврат ВсеФормыКонфигурации;
КонецФункции // ПолучитьВсеФормыКонфигурации()
// Возвращает все макеты конфигурации
//
// Параметры - Нет
//
// Возвращаемое значение:
// Массив объектов метаданных
//
Функция ПолучитьВсеМакетыКонфигурации() Экспорт
СтрокаВсехРеквизитов =
"
|Метаданные.ПланыОбмена.*.Макеты.*
|Метаданные.ОбщиеМакеты.*
|Метаданные.Справочники.*.Макеты.*
|Метаданные.Документы.*.Макеты.*
|Метаданные.ЖурналыДокументов.*.Макеты.*
|Метаданные.Перечисления.*.Макеты.*
|Метаданные.Отчеты.*.Макеты.*
|Метаданные.Обработки.*.Макеты.*
|Метаданные.ПланыВидовХарактеристик.*.Макеты.*
|Метаданные.ПланыСчетов.*.Макеты.*
|Метаданные.ПланыВидовРасчета.*.Макеты.*
|Метаданные.РегистрыСведений.*.Макеты.*
|Метаданные.РегистрыНакопления.*.Макеты.*
|Метаданные.РегистрыБухгалтерии.*.Макеты.*
|Метаданные.РегистрыРасчета.*.Макеты.*
|Метаданные.БизнесПроцессы.*.Макеты.*
|Метаданные.Задачи.*.Макеты.*
|";
ВсеМакетыКонфигурации = РазвернутьМассивСтрокОбходаМетаданных(ПолучитьМассивСтрокМногострочнойСтроки(СтрокаВсехРеквизитов));
Возврат ВсеМакетыКонфигурации;
КонецФункции // ПолучитьВсеМакетыКонфигурации()
У разработчиков на платформе 1С иногда возникает задача по взаимодействию системы 1С: Предприятие с различными почтовыми программами и протоколами. 1С Предприятие 8.0 имеет довольно
удобные средства для отправки сообщений, импорта писем из почтового клиента в справочник или другой объект конфигурации, работы с MAPI, SMTP или POP3.
При работе с почтой разделяют два способа доступа к почтовому ящику, почтовому клиенту:
объект "Почта" и объект "Интернет почта", каждый из объектов имеет свои достоинства.
Почта - предоставляет доступ к почте через встроенный почтовый клиент, работает по технологии MAPI.
Интернет почта - объект открывает возможности по доступу непосредственно к почтовым ящикам и учетным записям находящимися на почтовом сервере, использование и работа данного объекта не зависит от установленных в системе почтовых клиентов, даже если почтовый клиент установлен в системе "ИнтернетПочта" будет работать параллельно с ним, объект использует интернет-протоколы SMTP, POP3.
1.Получение сообщений объектом "Почта".
Для работы с объектом Почта необходимо наличие установленного на компьютере почтового клиента с описанными учетными записями.
Для подключения к почтовому клиенту у объекта есть метод "Подключиться".
Код 1C v 8.х
Почта = Новый Почта;
Почта.Подключиться(,);
Первый параметр - имя профиля, к примеру, если в системе установлен MS Outlook, то как правило его профиль называется Outlook. Следовательно при подключении строка выглядела бы так:
Код 1C v 8.х
Почта.Подключиться("Outlook");
Второй параметр отвечает за пароль к учетной записи.
Далее необходимо произвести выбор необходимых нам писем, для этой цели объект Почта имеет метод "Выбрать". У метода два параметра, первый отвечает за выбор непрочитанных писем - Истина (при Ложь будут выбраны все письма, находящиеся в папке "Входящие" почтового клиента), второй отвечает за выборку вложений, при Ложь, вложения выбираются.
//Выбираем все письма, со всеми вложениями.
Код 1C v 8.х Сообщения = Почта.Выбрать(Ложь,Ложь);
(иногда при взаимодействии с Outlook 2003 возникает проблема, при которой 1С 8 просто аварийно завершает работу с ошибкой, именно на данной строке кода, это лечится установкой пакета обновления SP2 для MS Office 2003).
Далее после выборки сообщений необходимо перебрать их в цикле и сохранить, на форме необходимо добавить ТабличноеПоле1 куда будут сохраняться входящие письма.
Код 1C v 8.х Для каждого Сообщение Из Сообщения Цикл
//Добавляем строку в табличную часть
СтрокаТП = ТабличноеПоле1.Добавить();
// Перебираем коллекцию получателей сообщения
Для каждого Получатель Из Письмо.Получатели Цикл
Получатели = Получатели + Получатель.Пользователь + " <" + Получатель.Адрес + "> ";
КонецЦикла;
СтрокаТП.Кому = Получатели;
Попытка
СтрокаТП.ОтКого= Сообщение.Отправитель.Адрес;
Исключение
СтрокаТП.ОтКого= Сообщение.Отправитель;
КонецПопытки;
СтрокаТП.Тема = Сообщение.Тема;
СтрокаТП.Текст = Сообщение.Текст;
СтрокаТП.Дата = Сообщение.ДатаПолучения;
// Перебираем вложения письма
Для каждого Вложение Из Сообщение.Вложения Цикл
Вложение.Данные.Записать(Вложение.Наименование);
//Запоминаем имена вложение прикрепленных к данному письму, и сохраним в ТабличноеПоле1
Влож=Влож+Вложение.Наименование+",";
КонецЦикла;
СтрокаТП.ПутьВложения=Влож;
КонецЦикла;
//отключение
Почта.Отключиться();
Все реквизиты входящих писем сохраняются в соответствующие поля табличного поля, вложения сохраняются в каталог временных файлов, а имена вложений в реквизит табличного поля. Для более удобного хранения вложений писем, 1С 8 имеет тип "Хранилище значения", который позволяет хранить двоичные данные, далее при получении сообщений объектом ИнтернетПочта рассмотрим возможность хранения в "Хранилище значения".
2.Отправка сообщений объектом "Почта"
При отправке сообщения, подключение к почтовому клиенту производится точно так же, как и при получении, перед отправкой необходимо подготовить письмо.
Код 1C v 8.х Сообщение = Новый ПочтовоеСообщение;
Сообщение.Текст = "текст сообщения";
Сообщение.Отправитель = "petya@pupkin.com";
Сообщение.Тема ="Тема сообщения";
Сообщение.Получатели.Добавить("vasya@pupkin.com");
Сообщение.Вложения.Добавить(Новый ДвоичныеДанные("C:\file.jpg"),"file.jpg");
Почта = Новый Почта;
//подключаемся без параметров, к клиенту установленному по умолчанию в системе
Почта.Подключиться(,);
Попытка
//Пытаемся послать письмо
Почта.Послать(Сообщение,Истина);
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
//отключение
Почта.Отключиться();
В методе Почта.Послать(Сообщение,Истина) два параметра, первый принимает ссылку на почтовое сообщение, второй параметр определяет, требуется ли запрос на подтверждение о получении письма адресатом (Истина - запрос включен). После этих операций письмо попадает в папку "Исходящие" почтового клиента, и в зависимости от настроек клиента отправляется сразу или по команде пользователя.
В MS Outlook встроена защита от несанкционированного доступа к адресной книге и базе почтовых сообщений, и защита от несанкционированной отправки электронных писем через службы Outlook. В Outlook 2003 система безопасности срабатывает не только при попытке получить адрес отправителя письма, но даже при попытке получить его текст. В действительности защита выражается в показываемом пользователю окне системы безопасности при обращении к некоторым объектам и свойствам объектов Outlook и предлагает открыть доступ на определенное время, следует разрешить доступ.
3.Получение сообщений объектом "ИнтернетПочта".
Перед подключением к почтовому серверу, для объекта ИнтернетПочта необходимо заполнить данные Профиля учетной записи, и затем передать эти данные в метод "Подключиться".
Код 1C v 8.х Функция ПолучитьПрофиль()
Профиль = Новый ИнтернетПочтовыйПрофиль;
// SMTP сервер
Профиль.АдресСервераSMTP = "smtp.pupkin.com";
// Порт SMTP сервера
Профиль.ПортSMTP = 25;
// POP3 сервер
Профиль.АдресСервераPOP3 = "pop.pupkin.com";
// Порт POP3 сервера
Профиль.ПортPOP3 = 110;
// Пароль к почтовому ящику
Профиль.Пароль = "pass";
// Пароль пользователя для SMTP сервера
Профиль.ПарольSMTP = "pass";
// Логин пользователя
Профиль.Пользователь = "vasya";
// Логин пользователя для SMTP сервера
Профиль.ПользовательSMTP = "vasya";
// Время ожидания выполнения операции в секундах
Профиль.ВремяОжидания = 50;
Возврат Профиль;
КонецФункции
Почта = Новый ИнтернетПочта;
Попытка
Почта.Подключиться(ПолучитьПрофиль());
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
Заголовки=Почта.ПолучитьЗаголовки()
Если Заголовки.Количество()=0 Тогда
Предупреждение("В почтовом ящике нет входящих сообщений!", ,"Нет сообщений");
КонецЕсли;
// Загрузка сообщений в массив
Сообщения = Почта.Выбрать(Истина,Заголовки);
Для каждого Сообщение Из Сообщения Цикл
СтрокаТП = ТабличноеПолеИнтернетПочта.Добавить();
СтрокаТП.Дата = Сообщение.ДатаОтправления;
СтрокаТП.ОтКого = Сообщение.Отправитель.Пользователь + " <" + Сообщение.Отправитель.Адрес + "> ";
СтрокаТП.Тема = Сообщение.Тема;
// Перебираем получателей сообщения
Для каждого Получатель Из Сообщение.Получатели Цикл
КомуВходящие = КомуВходящие + Получатель.Пользователь + " <" + Получатель.Адрес + "> ";
КонецЦикла;
СтрокаТП.Кому = КомуВходящие;
// Перебираем тексты сообщения
Для каждого ТекстСообщения Из Сообщение.Тексты Цикл
ТекстВходящие = ТекстВходящие + ТекстСообщения.Текст;
КонецЦикла;
СтрокаТП.Текст = ТекстВходящие;
// Перебираем вложения письма
Для каждого Вложение Из Сообщение.Вложения Цикл
Вложение.Данные.Записать(Вложение.Name);
СправочникВложения.РеквизитВложение = новый ХранилищеЗначения(Новый ДвоичныеДанные(Вложение.Name));
СправочникВложения.ИмяВложения=Вложение.Name;
КонецЦикла;
КонецЦикла;
// отключение
Почта.Отключиться();
Метод Почта.Выбрать(Истина,Заголовки); имеет два параметра, первый отвечает за удаление писем с сервера (при Истина-удалять), второй параметр отвечает за массив сообщений для выборки (т.е. закачки на компьютер клиента с сервера), если параметр пуст, то выбираются все сообщения находящиеся на сервере.
При переборе вложений, данные полученные из письма сохраняются в реквизит типа ХранилищеЗначения, заранее созданного справочника "СправочникВложения" в конфигураторе, т.к. данные первоначально сохраняются на диск, а затем загружаются в справочник, то, после загрузки в соответствующий реквизит справочника данные можно удалить. Не рекомендуется хранить данные типа ХранилищеЗначения в Табличных частях справочников, т.к. при больших объемах данных это затормаживает работу конфигурации.
4.Отправка сообщений объектом "ИнтернетПочта".
При отправке сообщения используется Функция ПолучитьПрофиль().
Код 1C v 8.х
Почта = Новый ИнтернетПочта;
Попытка
Почта.Подключиться(ПолучитьПрофиль());
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
Сообщение = Новый ИнтернетПочтовоеСообщение;
Сообщение.Вложения.Добавить(Новый ДвоичныеДанные("C:\file.jpg"),"file.jpg");
Сообщение.Отправитель = "vasya@pupkin.com";
Сообщение.ИмяОтправителя = "Вася";
ПочтовыеАдреса = Сообщение.Получатели;
ПочтовыйАдрес = ПочтовыеАдреса.Добавить();
ПочтовыйАдрес.Адрес = "petya@pupkin.com";
Сообщение.Тема ="Тема сообщения";
ИнтернетТекстПочтовогоСообщения = Сообщение.Тексты.Добавить();
ИнтернетТекстПочтовогоСообщения.Текст = "Текст сообщения";
ИнтернетТекстПочтовогоСообщения.ТипТекста = ТипТекстаПочтовогоСообщения.ПростойТекст;
Попытка
// Пытаемся послать письмо
Почта.Послать(Сообщение);
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
// отключение
Почта.Отключиться();
Удобно подключить автополучение/автоотправку почты командой "ПодключитьОбработчикОжидания(,)". Первый параметр в команде отвечает за наименование вызываемой процедуры, и второй, период ожидания процедуры в секундах, обычно обработчик ожидания вставляется в глобальный модуль системы (например, в процедуру ПриНачалеРаботыСистемы()) и указывает на процедуру с пометкой Экспорт.
Например, можно создать процедуру ПроверитьПочту, в которую вставить загрузку писем из почтового ящика и вставить ее в следующую строку:
ПодключитьОбработчикОжидания("ПроверитьПочту",60)
Также для обработки и просмотра сообщений в формате HTML удобно пользоваться компонентом "Поле HTML документа", для загрузки HTML текста в компонент используется метод ПолеHTMLдокумента.УстановитьТекст(Html), где Html-это документа полученный из текста сообщения. Есть вариант загрузки HTML с диска (если это вложение), ПолеHTMLдокумента.Перейти("file:\\C:\File.html").
После использования нескольких или сразу всех способов работы с электронной почтой, образуется полноценный почтовый клиент с возможностью хранения и обработки писем с вложениями на базе 1С предприятие 8.0.
Автор:
Alimov Roman Как организовать работу с почтой без установленного почтового клиента на компьютере пользователя?