SMTP greeting failure: 421 SMTP connection broken (reply) Описание ошибки: С сентября 2014 Яндекс.Почта, Mail.ru перешли на протокол SSL, что сделало их ещё более безопасными. Чтобы и дальше работать с письмами через 1С, Вам нужно изменить их настройки и внести доработки в код конфигураций.
Найденные решения:
Ошибка наблюдается, в частности, в случае, когда меняются настройки почты. Например мне довелось столкнуться в случае, когда ввели для почты SSL-шифрование. Если это Ваш случай, то из быстрых и простых остается только обновление до версии платформы 8.3, где поддержка этого шифрования для "ИнтернетПочтовыйПрофиль" реализована. И доработка кода типовых конфигураций для учета настроек SSL-шифрования и включения у почтового профиля.
Код 1C v 8.х ИнтернетПочтовыйПрофиль.ИспользоватьSSLPOP3 = Истина;ИнтернетПочтовыйПрофиль.ИспользоватьSSLSMTP = Истина; Сопровождающие проблему ошибки:
Яндекс.Почта адрес_почты@yandex.ru. {ОбщийМодуль.УправлениеЭлектроннойПочтой.Модуль(1065)}: Ошибка при вызове метода контекста (Подключиться): Почтовый ящик пользователя "адрес_почты@yandex.ru" на сервере "pop.yandex.ru" не найден. Ответ сервера: "[AUTH] Working without SSL/TLS encryption is not allowed. Please visit https://help.yandex.ru/mail/mail-clients/ssl.xml. sc=NXhLmqHbM4YK"
Если установлены не правильные порты, то получим ошибку:Ошибка при вызове метода контекста (Подключиться): TLS/SSL failure for smtp.mail.ru: Invalid token, probably not an SSL server Установите порты 465 для smtp, 995 для pop3.
При соединении с Яндексом: в логинах оставить только содержимое логина до @yandex.ru, т.е. из примера "адрес_почты" (без кавычек). Устанавливаем для pop3 и smtp SSL-шифрование. Если почта корпоративная на Яндексе, и в наименовании не используется @yandex.ru, то оставляем логин, равный наименованию почты, как есть.
Mail.ru Не включено SSL-шифрование для учетной записи электронной почты. Ошибка при вызове метода контекста (Подключиться): Can not authenticate to POP3 server: POP3 is available only with SSL or TLS connection enabled
Если установлены не правильные порты, то получим ошибку:Ошибка при вызове метода контекста (Подключиться): TLS/SSL failure for smtp.mail.ru: Invalid token, probably not an SSL server Устанавливаем порты 465 для smtp, 995 для pop3.
Если возникает ошибка:Ошибка при вызове метода контекста (Подключиться): Can't connect to smtp.mail.ru,495: Timed out - значит неправильно указан порт.
Если возникает ошибка:Ошибка при вызове метода контекста (Подключиться): SMTP greeting failure: 421 SMTP connection broken (reply) Порты настроены правильно, не установлено SSL-шифрование для smtp.
В паролях для почты не использовать спецсимволы, пример из опыта: в пароле к почте был символ "+", пока из пароля не убрали, соединение не происходило! Система выдавала ошибку: Ошибка при вызове метода контекста (Подключиться): Can not authenticate to SMTP server: 535 5.7.8 Error: authentication failed: Invalid user or password! Разработчики 1С вносят фунционал в рабочие конфигурации, например: УТ 10.3.30.1 от 26.09.2014, описание обновления: В справочник "Учетные записи электронной почты" добавлены реквизиты "Использовать защищенную версию протокола SMTP" и "Использовать защищенную версию протокола POP3". При установке этих реквизитов предоставляется возможность подключаться к почтовым серверам через безопасное соединение (SSL). Реквизиты доступны при использовании версии платформы не ниже 8.3.1.
P.S.: Возможно еще использование дополнительной программы stunnel. Но мне этот вариант меньше понравился. Т.к. клиенту не хотелось зависеть от программиста каждый раз, когда появляется новая почта или рабочее место, а чтобы сразу можно было из 1С настроить, как и раньше.
Журавлев А.С. (Сайт www.azhur-c.ru)
Категория:
Системные Ошибки Как в СКД повторять шапку на каждой странице при печати и вывести колонтитулы? Нужно выводить на каждой странице отчета, шапку. Отчет сделан через СКД (Схема компоновки данных). В схеме есть макет, в нем есть ячейки шапки.
Для этого используется метод - ПовторятьПриПечатиСтроки, о нем я уже писал: Как при печати выводить шапку на каждой странице (ПовторятьПриПечатиСтроки)?
Код кнопки формирования отчета:
Код 1C v 8.3 СводнаяКартаРезультат = Новый ТабличныйДокумент;
ПечатьСводнойКартыНаСервере(СводнаяКартаРезультат);
СводнаяКартаРезультат.Показать("СводнаяКарта"); Процедура вывода отчета:
Код 1C v 8.3 &НаСервере
Процедура ПечатьСводнойКартыНаСервере(СводнаяКартаРезультат)
СхемаКомпоновкиДанных = Справочники.Номенклатура.ПолучитьМакет("МакетСводнаяКарта");
СводнаяКартаРезультат.ПовторятьПриПечатиСтроки = СводнаяКартаРезультат.Область(7, , 7); // <- Строки вывода повторения нужно считать в уже результате вывода, а не в макете!
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
НомеклатураСсылка = Настройки.ПараметрыДанных.Элементы.Найти("НоменклатураСсылка");
НомеклатураСсылка.Значение = Объект.Ссылка;
НомеклатураСсылка.Использование = Истина;
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных,Настройки, ДанныеРасшифровки);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки,,ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(СводнаяКартаРезультат);
//ПроцессорВывода.ОтображатьПроцентВывода = Истина;
ПроцессорВывода.НачатьВывод();
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных, Истина);
ПроцессорВывода.ЗакончитьВывод();
КонецПроцедуры Если дополнительно нужно вывести колонтитулы,
тогда:
Код 1C v 8.3 // Верхний колонтитул
ТабДок.ВерхнийКолонтитул.Выводить = Истина;
ТабДок.ВерхнийКолонтитул.НачальнаяСтраница = 2;
ТабДок.ВерхнийКолонтитул.Шрифт = Новый Шрифт(Результат.ВерхнийКолонтитул.Шрифт, , , , Истина);
ТабДок.ВерхнийКолонтитул.ТекстСлева = "Заголовок отчета";
ТабДок.ВерхнийКолонтитул.ТекстВЦентре = "Стр. [&НомерСтраницы] из [&СтраницВсего]";
ТабДок.ВерхнийКолонтитул.ТекстСправа = "Дата/время печати: [&Дата]/[&Время]";
// Нижний колонтитул
ТабДок.НижнийКолонтитул.Выводить = Истина;
ТабДок.НижнийКолонтитул.Шрифт = Новый Шрифт(Результат.ВерхнийКолонтитул.Шрифт, , , , Истина);
ТабДок.НижнийКолонтитул.ТекстВЦентре = "Заголовок отчета"; Категория:
Схема Компоновки Данных Как при печати выводить шапку на каждой странице (ПовторятьПриПечатиСтроки)? Необходимо при печати, если происходит переход на следующую страницу таблицы, выводить шапку таблицы вверху на новой странице.
для печати шапки на каждой странице в языке программирования есть специальный метод - ПовторятьПриПечатиСтроки
Примеры его использования:
Код 1C v 8.х ТабДок.ПовторятьПриПечатиСтроки = ТабДок.Область(1, , 2, );
ЭлементыФормы.Поле_ТД.ПовторятьПриПечатиСтроки = Макет.Область("Шапка_Спецификации"); //или так
ЭлементыФормы.Поле_ТД.ПовторятьПриПечатиСтроки = Макет.Область("R777:R778"); Полный код вывода табличного документа с повторением шапки на каждой странице:
Код 1C v 8.х Функция ПечатьПриказаТ11а()
ТабДокумент = Новый ТабличныйДокумент;
ТабДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ПечатнаяФорма_МатериальнаяПомощь_Т11а";
ТабДокумент.ПовторятьПриПечатиСтроки = ТабДокумент.Область("R21:R22");
Макет = ПолучитьМакет("Т11а");
ОбластьМакетаШапкаДокумента = Макет.ПолучитьОбласть("Шапка");
ОбластьПовторятьПриПечати = Макет.ПолучитьОбласть("ПовторятьПриПечати");
ОбластьМакетаСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьМакетаПодвал = Макет.ПолучитьОбласть("Подвал");
ВыборкаДляШапкиДокумента = СформироватьЗапросДляШапкиДокумента().Выбрать();
ВыборкаРаботники = СформироватьЗапросДляТабличнойЧасти(1).Выбрать(); // ТЧ "Начисления"
Если ВыборкаРаботники.Количество() = 0 Тогда
ВыборкаРаботники = СформироватьЗапросДляТабличнойЧасти(2).Выбрать(); // ТЧ "Доп.Начисления"
КонецЕсли;
// Массив с двумя строками - для разбиения на страницы
ВыводимыеОбласти = Новый Массив();
ВыводимыеОбласти.Добавить(ОбластьМакетаСтрока);
// Вывод шапки документа
Пока ВыборкаДляШапкиДокумента.Следующий() Цикл
ОбластьМакетаШапкаДокумента.Параметры.Заполнить(ВыборкаДляШапкиДокумента);
ОбластьМакетаШапкаДокумента.Параметры.НазваниеОрганизации = СокрЛП(ОбластьМакетаШапкаДокумента.Параметры.НазваниеОрганизации);
КонецЦикла;
ТабДокумент.Вывести(ОбластьМакетаШапкаДокумента);
ном=0;
Пока ВыборкаРаботники.Следующий() Цикл
ОбластьМакетаСтрока.Параметры.Заполнить(ВыборкаРаботники);
ном=ном+1;
ОбластьМакетаСтрока.Параметры.ПодразделениеОрганизации = ВыборкаРаботники.ПодразделениеОрганизации.ПолноеНаименование();
ОбластьМакетаСтрока.Параметры.ном=ном;
ТабДокумент.Вывести(ОбластьМакетаСтрока);
КонецЦикла;
ОбластьМакетаПодвал.Параметры.Заполнить(ВыборкаДляШапкиДокумента); // Из запроса шапка документа.
ТабДокумент.Вывести(ОбластьМакетаПодвал);
Если ТабДокумент.ВысотаТаблицы > 0 Тогда
Возврат УниверсальныеМеханизмы.НапечататьДокумент(ТабДокумент, 1, Ложь, ОбщегоНазначения.СформироватьЗаголовокДокумента(СсылкаНаОбъект,"Приказ о поощрении работника "));
КонецЕсли;
//Возврат ТабДокумент;
КонецФункции Категория:
Табличный документ Разница между датами в рабочих днях, подсчет рабочих дней в 1С Разрабатывая некий функционал в 1С, бывает, необходимо посчитать количество рабочих дней после какой-то даты.
В этой статье примеры кода и запросы в которых считается количество рабочих дней:
Код, при вычислении определяет только по дню недели, викидывая выходные. Праздники не учитывает!
Код 1C v 8.х Функция РабочихДнейСДаты(НачДата,КолвоДней) Экспорт
Перем РабочихДней, ОбычныхДней, ДеньНедели;
РабочихДней = 0; ОбычныхДней = 0;
Пока РабочихДней < Число(КолвоДней) Цикл
ОбычныхДней = ОбычныхДней+ 1;
// определим день недели
ДеньНедели=ДеньНедели(НачДата+(ОбычныхДней*86400));
// если не выходной, то прошел еще один рабочий день
Если ДеньНедели < 6 Тогда
РабочихДней=РабочихДней+1;
КонецЕсли;
КонецЦикла;
Возврат (НачДата + (РабочихДней*86400));
КонецФункции
// Пример использования
ТриДняОтОбработки = РабочихДнейСДаты(нДатаОбработки,3);
Если РабочаяДата>ТриДняОтОбработки Тогда
Предупреждение("Прошло больше 3-х дней после обработки заказа. Цены не актуальны!
|Отправьте заказ на новую обработку! ");
Иначе
// ... неки код
КонецЕсли; В запросе, с использованием производственного календаря и учетом всех праздников:
Код 1C v 8.х ВЫБРАТЬ
РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК Дата
ПОМЕСТИТЬ Даты
ИЗ
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
РегламентированныйПроизводственныйКалендарь.ДатаКалендаря В(&ВходящиеДаты)
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Даты.Дата,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) КАК КоличествоРабочихДней,
МАКСИМУМ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) КАК ДатаКалендаря,
РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря КАК ДатаКалендаряДляГруппировки
ИЗ
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Даты КАК Даты
ПО (Даты.Дата <= РегламентированныйПроизводственныйКалендарь.ДатаКалендаря)
И (ДОБАВИТЬКДАТЕ(Даты.Дата, ДЕНЬ,ГлубинаДней) > РегламентированныйПроизводственныйКалендарь.ДатаКалендаря)
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь1
ПО РегламентированныйПроизводственныйКалендарь.ДатаКалендаря <= РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря
ГДЕ
(РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный)
ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий))
СГРУППИРОВАТЬ ПО
РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря,
Даты.Дата
ИМЕЮЩИЕ
МАКСИМУМ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря
И КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) =РабочихДней
Еще один вариант, в котором допустим, что:
1) Регистр сведений Календарь имеет структуру (Измерения={ДатаКалендаря}, Ресурсы={ВидДня}), а перечисление ВидыДня задано как {Рабочий, Предпразничный} и праздничные дни в календаре отсутствуют.
2) В документе Реализация заданы поля Дата и ОтсрочкаДней. Тогда:
Код 1C v 8.х Выбрать
Р.Ссылка, Р.Дата,
минимум(isnull(К.ДатаКалендаря, добавитькдате(Р.Дата, день, Р.ОтсрочкаДней))) как ДатаКредита
из Документ.Реализация как Р
левое соединение РегистрСведений.Календарь как К
по добавитькдате(Р.Дата, день, Р.ОтсрочкаДней) <= К.ДатаКалендаря
сгруппировать по
Р.Ссылка, Р.Дата Собственно, если календарь содержит и праздничные дни, то можно добавить секцию ГДЕ, и там отобрать только рабочие дни. В секции ГДЕ можно отобрать и интересующий календарь, если ведется несколько календарей.
Категория:
Работа с Датами (Временем) Пример создания внешней печатной формы для управляемого приложения Пример создания внешней печатной формы АКТа для Бухгалтерии 3.0
1. В конфигураторе 1C Предприятия 8 создаем внешнюю обработку (Файл->Новый->Внешняя обработка), задаем имя.
2. В модуле обработки пишем код. Постараюсь его максимально комментировать. Главное должно быть:
функция ПечатьВнешнейПечатнойФормы табличного документа - которая выведет данные в макет функция Печать - вызывается из конфигурации! в нее передается массив печатаемых объектов и функция СведенияОВнешнейОбработке(). Она необходима для регистрации печатной формы в справочнике ДополнительныеОтчетыИОбработки, в ней собирается структура с данными для подключения формы. Эта функция, а также ряд сопутствующих ей, практически одинаковы для всех печатных форм, поэтому их можно просто копировать в новую печатную форму ничего не меняя. Код 1C v 8.3 // Функция формирует табличный документ с Внешней печатной формой
//
// Возвращаемое значение:
// Табличный документ - печатная форма акта
Функция ПечатьВнешнейПечатнойФормы(МассивОбъектов, ОбъектыПечати, Подписант) Экспорт
ТабДок = новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
ОбластьШапки = Макет.ПолучитьОбласть("Шапка");
ОбластьДанные = Макет.ПолучитьОбласть("Данные");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
Запрос = новый запрос;
Запрос.УстановитьПараметр("МассивОбъектов",МассивОбъектов);
Запрос.Текст = "ВЫБРАТЬ
| РеализацияТоваровУслугТовары.Номенклатура,
| РеализацияТоваровУслугТовары.Сумма,
| РеализацияТоваровУслугТовары.Количество,
| РеализацияТоваровУслугТовары.Цена,
| РеализацияТоваровУслугТовары.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
|ГДЕ
| РеализацияТоваровУслугТовары.Ссылка В(&МассивОбъектов)
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| РеализацияТоваровУслугУслуги.Номенклатура,
| РеализацияТоваровУслугУслуги.Сумма,
| РеализацияТоваровУслугУслуги.Количество,
| РеализацияТоваровУслугУслуги.Цена,
| РеализацияТоваровУслугУслуги.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг.Услуги КАК РеализацияТоваровУслугУслуги
|ГДЕ
| РеализацияТоваровУслугУслуги.Ссылка В(&МассивОбъектов)
|
|УПОРЯДОЧИТЬ ПО
| Ссылка";
ОбщаяВыборка = Запрос.Выполнить().Выгрузить();
Для Каждого СсылкаНаОбъект из МассивОбъектов Цикл
ОбластьШапки.Параметры.ТекстЗаголовка = "Акт № "+СсылкаНаОбъект.Номер;
ОбластьШапки.Параметры.Организация = СсылкаНаОбъект.Организация;
ТабДок.Вывести(ОбластьШапки);
Отбор = Новый Структура;
Отбор.Вставить("Ссылка",СсылкаНаОбъект);
Выборка = ОбщаяВыборка.НайтиСтроки(Отбор);
ИтогоСумма = 0;
ИтогоКоличество = 0;
Для Каждого Стр из Выборка Цикл
ЗаполнитьЗначенияСвойств(ОбластьДанные.Параметры,Стр);
ИтогоСумма = ИтогоСумма + Стр.Сумма;
ИтогоКоличество = ИтогоКоличество + Стр.Количество;
ТабДок.Вывести(ОбластьДанные);
КонецЦикла;
ОбластьПодвал.Параметры.ИтогоСумма = ИтогоСумма;
ОбластьПодвал.Параметры.Подписант = Подписант;
ТабДок.Вывести(ОбластьПодвал);
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЦикла;
Возврат ТабДок;
КонецФункции
// Экспортная процедура печати, вызываемая из основной программы
//
// Параметры:
// ВХОДЯЩИЕ:
// МассивОбъектовНазначения - Массив - список объектов ссылочного типа для печати документа
// Как правило, содержит один элемент с ссылкой на вызвавший форму объект (документ, справочник)
//
// ИСХОДЯЩИЕ:
// КоллекцияПечатныхФорм - ТаблицаЗначений - таблица сформированных табличных документов.
// Как правило, содержит одну строку с именем текущей печатной формы
// ОбъектыПечати - СписокЗначений - список объектов печати.
// ПараметрыВывода - Структура - Параметры сформированных табличных документов. Содержит поля:
// ДоступнаПечатьПоКомплектно - булево - по умолчанию Ложь
// ПолучательЭлектронногоПисьма
// ОтправительЭлектронногоПисьма
//
Процедура Печать(МассивОбъектовНазначения, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "АКТПечатьВнешняя") Тогда
ТабличныйДокумент = ПечатьВнешнейПечатнойФормы(МассивОбъектовНазначения, ОбъектыПечати, "");
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "АКТПечатьВнешняя", "АКТ (внешний)", ТабличныйДокумент);
ИначеЕсли УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "АКТПечатьВнешняяИван") Тогда
ТабличныйДокумент = ПечатьВнешнейПечатнойФормы(МассивОбъектовНазначения, ОбъектыПечати, "Иванов А.Ю.");
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "АКТПечатьВнешняяИван", "АКТ (внешний) Иванов", ТабличныйДокумент);
ИначеЕсли УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "АКТПечатьВнешняяПетр") Тогда
ТабличныйДокумент = ПечатьВнешнейПечатнойФормы(МассивОбъектовНазначения, ОбъектыПечати, "Петров В.С.");
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "АКТПечатьВнешняяПетр", "АКТ (внешний) Петров", ТабличныйДокумент);
КонецЕсли;
КонецПроцедуры
#Область СведенияОВнешнейОбработке
// Сервисная экспортная функция. Вызывается в основной программе при регистрации обработки в информационной базе
// Возвращает структуру с параметрами регистрации
//
// Возвращаемое значение:
// Структура с полями:
// Вид - строка, вид обработки, один из возможных: "ДополнительнаяОбработка", "ДополнительныйОтчет",
// "ЗаполнениеОбъекта", "Отчет", "ПечатнаяФорма", "СозданиеСвязанныхОбъектов"
// Назначение - Массив строк имен объектов метаданных в формате:
// <ИмяКлассаОбъектаМетаданного>.[ * | <ИмяОбъектаМетаданных>].
// Например, "Документ.СчетЗаказ" или "Справочник.*". Параметр имеет смысл только для назначаемых обработок, для глобальных может не задаваться.
// Наименование - строка - Наименование обработки, которым будет заполнено наименование элемента справочника по умолчанию.
// Информация - строка - Краткая информация или описание по обработке.
// Версия - строка - Версия обработки в формате “<старший номер>.<младший номер>” используется при загрузке обработок в информационную базу.
// БезопасныйРежим - булево - Принимает значение Истина или Ложь, в зависимости от того, требуется ли устанавливать или отключать безопасный режим
// исполнения обработок. Если истина, обработка будет запущена в безопасном режиме.
//
Функция СведенияОВнешнейОбработке() Экспорт
//Инициализируем структуру с параметрами регистрации
ПараметрыРегистрации = Новый Структура;
// Первый параметр, который мы должны указать - это какой вид обработки системе должна зарегистрировать.
// Допустимые типы: ДополнительнаяОбработка, ДополнительныйОтчет, ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма"); //может быть - ПечатнаяФорма, ЗаполнениеОбъекта, ДополнительныйОтчет, СозданиеСвязанныхОбъектов...
МассивНазначений = Новый Массив;
// Теперь нам необходимо передать в виде массива имен, к чему будет подключена наша ВПФ
// Имейте ввиду, что можно задать имя в таком виде: Документ.* - в этом случае обработка будет подключена ко всем документам в системе,
// которые поддерживают механизм ВПФ
МассивНазначений.Добавить("Документ.РеализацияТоваровУслуг"); //Указываем документ к которому делаем внешнюю печ. форму
ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
ПараметрыРегистрации.Вставить("Наименование", "АКТ (Внешний)"); //имя под которым обработка будет зарегестрирована в справочнике внешних обработок
ПараметрыРегистрации.Вставить("БезопасныйРежим", ЛОЖЬ); // Зададим право обработке на использование безопасного режима. Более подробно можно узнать в справке к платформе (метод УстановитьБезопасныйРежим)
ПараметрыРегистрации.Вставить("Версия", "1.0"); // эти два параметра играют больше информационную роль,
ПараметрыРегистрации.Вставить("Информация", "Дополнительная печатная форма"); // т.е. это то, что будет видеть пользователь в информации к обработке
// Создадим таблицу команд (подробнее смотрим ниже)
ТаблицаКоманд = ПолучитьТаблицуКоманд();
ДобавитьКоманду(ТаблицаКоманд, "Внешний: АКТ", "АКТПечатьВнешняя", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ДобавитьКоманду(ТаблицаКоманд, "Внешний: АКТ (Иванов)", "АКТПечатьВнешняяИван", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ДобавитьКоманду(ТаблицаКоманд, "Внешний: АКТ (Петров)", "АКТПечатьВнешняяПетр", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
#КонецОбласти
#Область Вспомогательное
// ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ РЕГИСТРАЦИИ ОБРАБОТКИ
// Формирует структуру с параметрами регистрации регистрации обработки в информационной базе
//
// Параметры:
// ОбъектыНазначенияФормы - Массив - Массив строк имен объектов метаданных в формате:
// <ИмяКлассаОбъектаМетаданного>.[ * | <ИмяОбъектаМетаданных>].
// или строка с именем объекта метаданных
// НаименованиеОбработки - строка - Наименование обработки, которым будет заполнено наименование элемента справочника по умолчанию.
// Необязательно, по умолчанию синоним или представление объекта
// Информация - строка - Краткая информация или описание обработки.
// Необязательно, по умолчанию комментарий объекта
// Версия - строка - Версия обработки в формате “<старший номер>.<младший номер>” используется при загрузке обработок в информационную базу.
//
//
// Возвращаемое значение:
// Структура
//
Функция ПолучитьПараметрыРегистрации(ОбъектыНазначенияФормы = Неопределено, НаименованиеОбработки = "", Информация = "", Версия = "1.0")
Если ТипЗнч(ОбъектыНазначенияФормы) = Тип("Строка") Тогда
ОбъектНазначенияФормы = ОбъектыНазначенияФормы;
ОбъектыНазначенияФормы = Новый Массив;
ОбъектыНазначенияФормы.Добавить(ОбъектНазначенияФормы);
КонецЕсли;
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
ПараметрыРегистрации.Вставить("Назначение", ОбъектыНазначенияФормы);
Если Не ЗначениеЗаполнено(НаименованиеОбработки) Тогда
НаименованиеОбработки = ЭтотОбъект.Метаданные().Представление();
КонецЕсли;
ПараметрыРегистрации.Вставить("Наименование", НаименованиеОбработки);
Если Не ЗначениеЗаполнено(Информация) Тогда
Информация = ЭтотОбъект.Метаданные().Комментарий;
КонецЕсли;
ПараметрыРегистрации.Вставить("Информация", Информация);
ПараметрыРегистрации.Вставить("Версия", Версия);
Возврат ПараметрыРегистрации;
КонецФункции
// Формирует таблицу значений с командами печати
//
// Возвращаемое значение:
// ТаблицаЗначений
//
Функция ПолучитьТаблицуКоманд()
Команды = Новый ТаблицаЗначений;
//Представление команды в пользовательском интерфейсе
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
//Уникальный идентификатор команды или имя макета печати
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
//Способ вызова команды: "ОткрытиеФормы", "ВызовКлиентскогоМетода", "ВызовСерверногоМетода"
// "ОткрытиеФормы" - применяется только для отчетов и дополнительных отчетов
// "ВызовКлиентскогоМетода" - вызов процедуры Печать(), определённой в модуле формы обработки
// "ВызовСерверногоМетода" - вызов процедуры Печать(), определённой в модуле объекта обработки
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
//Показывать оповещение.
//Если Истина, требуется показать оповещение при начале и при завершении работы обработки.
//Имеет смысл только при запуске обработки без открытия формы
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
//Дополнительный модификатор команды.
//Используется для дополнительных обработок печатных форм на основе табличных макетов.
//Для таких команд должен содержать строку ПечатьMXL
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
Возврат Команды;
КонецФункции
// Вспомогательная процедура.
//
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование = "ВызовСерверногоМетода", ПоказыватьОповещение = Ложь, Модификатор = "ПечатьMXL")
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = Представление;
НоваяКоманда.Идентификатор = Идентификатор;
НоваяКоманда.Использование = Использование;
НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры
#КонецОбласти 3. Добавляем макет вывода печатной формы:
4. Сохраняем и добавляем в конфигурацию:
Подключается через Администрирование - Печатные формы, отчеты и обработки:
Создаете новую обработку, записывайте и при открытии документа Реализация, нажав на Печать - появляются доступные печатные формы с разными подписывающими.
Скачать Шаблон внешней печатной формы для управляемого приложения
Категория:
Внешние печатные формы, отчеты и обработк… Как получить текст из html? Один мой хороший клиент использует встроенный в 1С почтовый клиент.
До этого все работало хорошо, но недавно из-за установки нового банк-клиента на компьютере обновили Internet Explorer до 11 версии - стала появляться ошибка:
Поле объекта не обнаружено innerText
Пришлось немного доработать типовую функцию получения текста из html:
Код 1C v 8.х Функция ПреобразоватьТекстИзХТМЛФорматаВПростой(ТекстВФорматеХТМЛ) Экспорт
Попытка
НовыйHTMLДокумент = Новый COMОбъект("HtmlFile");
НовыйHTMLДокумент.open("text/html");
НовыйHTMLДокумент.write(ТекстВФорматеХТМЛ);
НовыйHTMLДокумент.close();
Возврат СтрЗаменить(НовыйHTMLДокумент.all.item(0).innerText, Символ(13), "");
Исключение
Построитель = Новый ПостроительDOM;
ЧтениеHTML = Новый ЧтениеHTML;
ЧтениеHTML.УстановитьСтроку(ТекстВФорматеХТМЛ);
ДокументHTML = Построитель.Прочитать(ЧтениеHTML);
Возврат СокрЛП(ДокументHTML.Тело.ТекстовоеСодержимое);
КонецПопытки;
КонецФункции еще функции пример получения:
Код 1C v 8.х // Процедура изменяет признак формат текста письма (Текст, HТМЛ),
// и при этом конвертирует сам текст.
//
// Параметры:
// ЭУHTML,ЭУТекст - Элементы управления формы, соответственно поле HTML и поле Текст
// Кнопка - выбранная кнопка ее текст "Простой текст" или "HTML" новый вид текста письма
// либо текст кнопки если пометку кнопки менять не требуется, соответственно
// вопрос о потере форматирования задаваться не будет
// Возвращаемое значение:
// Булево, признак выполнения изменения формата
//
Функция удИзменитьФорматТекста(ЭУHTML,ЭУТекст, Кнопка) Экспорт
Если ТипЗнч(Кнопка) = Тип("Строка") Тогда
НовыйВидТекстаПисьма = Кнопка;
ЕстьКнопка = Ложь;
Иначе
Если Кнопка.Пометка Тогда
Возврат Ложь;
КонецЕсли;
НовыйВидТекстаПисьма = Кнопка.Текст;
ЕстьКнопка = Истина;
КонецЕсли;
Если Найти(НовыйВидТекстаПисьма,"Простой текст") > 0 Тогда
ИсходныйТекст = ЭУHTML.ПолучитьТекст();
НачалоBODY = Найти(ИсходныйТекст, "<BODY>");
КонецBODY = Найти(ИсходныйТекст, "</BODY>");
Если ЕстьКнопка и (НачалоBODY > 0 И КонецBODY > 0 И (НачалоBODY + 6) < КонецBODY) Тогда
СтрокаВопроса = "Будет потеряно форматирование текста. Продолжить?";
ОтветНаВопрос = Вопрос(СтрокаВопроса, РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Нет);
Если ОтветНаВопрос <> КодВозвратаДиалога.Да Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
ФорматТекста = ЭУHTML.Документ.all.item(0).innerText;
ЭУТекст.Значение = СтрЗаменить(ФорматТекста, Символ(13), "");
ЭУТекст.Видимость = Истина;
ЭУHTML.Видимость = Ложь;
ЭУHTML.УстановитьТекст("");
Иначе
ФорматХТМЛ = СтрЗаменить(ЭУТекст.Значение, Символы.ПС, "<BR>");
ЭУHTML.УстановитьТекст(ФорматХТМЛ);
ЭУHTML.Видимость = Истина;
ЭУТекст.Видимость = Ложь;
КонецЕсли;
Если ЕстьКнопка Тогда
Кнопка.Пометка = Истина;
КонецЕсли;
Возврат Истина;
КонецФункции // обИзменитьФорматТекста() Категория:
Работа с Интернет, Почтой (Mail), FTP Что такое менеджер временных таблиц и как с ним работать? В 1С есть такая замечательная вещь, как МенеджерВременныхТаблиц . Этот объект позволяет передавать временные таблицы из одного запроса в другой. То есть, мы можем создать временную таблицу в запросе, прерваться, выполнить какой-нибудь код, и продолжить работу с этой временной таблицей дальше.
Код 1C v 8.2 УП Запрос = Новый Запрос;
МВТ = Новый МенеджерВременныхТаблиц;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "ВЫБРАТЬ
| ТЧ.Номенклатура
|ПОМЕСТИТЬ ВременнаяТЗ
|ИЗ
| &ТЧ КАК ТЧ
|ГДЕ
| ТЧ.Номенклатура В ИЕРАРХИИ(&Номенклатура)
| И ТЧ.Цена < 5";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("ТЧ", ТЧ);
РезультатЗапроса = Запрос.Выполнить();
Запрос2 = Новый Запрос;
Запрос2.Текст = "ВЫБРАТЬ
| ВременнаяТЗ.Номенклатура
|ИЗ
| ВременнаяТЗ КАК ВременнаяТЗ";
Запрос2.МенеджерВременныхТаблиц = МВТ;
РезультатЗапроса = Запрос2.Выполнить().Выгрузить(); Например, в отчете в зависимости от выбранных настроек первичные данные обрабатываются тем или иным способом. Тогда имеет смысл в одной процедуре сформировать эти данные и поместить их во временную таблицу, которую уже передаем через менеджер временных таблиц в другую процедуру, отвечающую за выбранный способ обработки. Это позволит сократить код, сделать запросы более читаемыми. А так же в случае, если возникнут изменения в методике подготовки первичных данных для обработки, то потребуется внести изменения только в один запрос, а не в каждый.
В качестве примера работы с менеджером временных таблиц приведу следующую обработку.
Я создаю менеджер временных таблиц, и передаю его последовательно в каждую процедуру, для создания и объединения временных таблиц. Результат выводится в сводную таблицу.
Код 1C v 8.2 УП &НаКлиенте
Процедура ЗаполнитьСводную(Команда)
ЗаполнитьСводнуюНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьСводнуюНаСервере()
МенВТ = Новый МенеджерВременныхТаблиц;
ПолучитьДанныеА(МенВТ);
ПолучитьДанныеБ(МенВТ);
ЗагрузитьСводные(МенВТ);
МенВТ.Закрыть();
КонецПроцедуры
&НаСервере
Процедура ПолучитьДанныеА(МенВремТаб)
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенВремТаб;
Запрос.Текст = "ВЫБРАТЬ
| ТаблицаА.Контрагент КАК Контрагент,
| ТаблицаА.Сумма
|ПОМЕСТИТЬ ТабА
|ИЗ
|ТаблицаА КАК ТаблицаА
|
|ИНДЕКСИРОВАТЬ ПО
| Контрагент";
Запрос.УстановитьПараметр("ТаблицаА", ТаблицаА.Выгрузить());
Запрос.Выполнить();
КонецПроцедуры // ПолучитьДанныеА()
&НаСервере
Процедура ПолучитьДанныеБ(МенВремТаб)
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенВремТаб;
Запрос.Текст = "ВЫБРАТЬ
| ТаблицаБ.Контрагент КАК Контрагент,
| ТаблицаБ.Комментарий
|ПОМЕСТИТЬ ТабБ
|ИЗ
|ТаблицаБ КАК ТаблицаБ
|
|ИНДЕКСИРОВАТЬ ПО
| Контрагент";
Запрос.УстановитьПараметр("ТаблицаБ", ТаблицаБ.Выгрузить());
Запрос.Выполнить();
КонецПроцедуры // ПолучитьДанныеА()
&НаСервере
Процедура ЗагрузитьСводные(МенВремТаб)
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенВремТаб;
Запрос.Текст = "ВЫБРАТЬ
| ЕСТЬNULL(ТабА.Контрагент, ТабБ.Контрагент) КАК Контрагент,
| ЕСТЬNULL(ТабА.Сумма, 0) КАК Сумма,
| ЕСТЬNULL(ТабБ.Комментарий, """") КАК Комментарий
|ИЗ
| ТабА КАК ТабА
| ПОЛНОЕ СОЕДИНЕНИЕ ТабБ КАК ТабБ
| ПО ТабА.Контрагент = ТабБ.Контрагент
|
|УПОРЯДОЧИТЬ ПО
| Контрагент
|АВТОУПОРЯДОЧИВАНИЕ";
ТаблицаСводная.Загрузить(Запрос.Выполнить().Выгрузить());
КонецПроцедуры // ЗагрузитьСводные() Категория:
Запросы Динамический отчет на СКД с разными вариантами На днях делал несколько однотипных отчетов на СКД.
Общий принцип: формируются все варианты отчета, указанные в настройках схемы и каждый вариант выводится на отдельной вкладке.
Потом возникла мысль попробовать объединить все схемы в один отчет, чтобы не плодить лишних объектов в конфигурации. При этом количество вариантов в этих схемах заранее неизвестно. Ok, challenge accepted.
В тестовой конфигурации создаю для отчета две схемы компоновки, "Склад" и "Заявки".
Запросы наборов данных приводить не буду, для каждой схемы в настройках добавляю несколько вариантов отчетов.
Теперь переходим к созданию формы. Практически все реквизиты формы будут создаваться при выборе необходимого макета отчета.
Код 1C v 8.2 УП &НаСервере
Процедура СоздатьПереченьОтчетов()
Для Каждого Макет Из РеквизитФормыВЗначение("Отчет").Метаданные().Макеты Цикл
Элементы.МакетОтчета.СписокВыбора.Добавить(Макет.Имя, Макет.Синоним);
КонецЦикла;
КонецПроцедуры // СоздатьПереченьОтчетов()
&НаСервере
Процедура ОбработатьВыборМакета()
Макет = РеквизитФормыВЗначение("Отчет").ПолучитьМакет(МакетОтчета);
мУдалить = ?(ПустаяСтрока(РеквизитыКУдалению), Новый Массив, ПолучитьИзВременногоХранилища(РеквизитыКУдалению));
мДобавить = Новый Массив;
кУдалению = Новый Массив;
Для Каждого Вариант Из Макет.ВариантыНастроек Цикл
ИмяРеквизита = "ТабДок_" + Вариант.Имя;
тРеквизит = Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("ТабличныйДокумент"));
мДобавить.Добавить(тРеквизит);
кУдалению.Добавить(ИмяРеквизита);
КонецЦикла;
ИзменитьРеквизиты(мДобавить, мУдалить);
Пока Элементы.СтраницыОтчета.ПодчиненныеЭлементы.Количество() Цикл
Элементы.Удалить(Элементы.СтраницыОтчета.ПодчиненныеЭлементы[0]);
КонецЦикла;
Для Каждого Вариант Из Макет.ВариантыНастроек Цикл
Страница = Элементы.Добавить("Страница_" + Вариант.Имя, Тип("ГруппаФормы"), Элементы.СтраницыОтчета);
Страница.Вид = ВидГруппыФормы.Страница;
Страница.Заголовок = Вариант.Представление;
ИмяРеквизита = "ТабДок_" + Вариант.Имя;
ТабДок = Элементы.Добавить(ИмяРеквизита, Тип("ПолеФормы"), Страница);
ТабДок.Вид = ВидПоляФормы.ПолеТабличногоДокумента;
ТабДок.ПутьКДанным = ИмяРеквизита;
ТабДок.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ЭтаФорма[ИмяРеквизита].Очистить();
КонецЦикла;
РеквизитыКУдалению = ПоместитьВоВременноеХранилище(кУдалению, УникальныйИдентификатор);
КонецПроцедуры // ОбработатьВыборМакета()
&НаСервере
Процедура СформироватьОтчеты()
Схема = РеквизитФормыВЗначение("Отчет").ПолучитьМакет(МакетОтчета);
Для Каждого Вариант Из Схема.ВариантыНастроек Цикл
Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(Вариант.Настройки);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Отчет.КомпоновщикНастроек.ПолучитьНастройки());
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ЭтаФорма["ТабДок_" + Вариант.Имя]);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецЦикла;
КонецПроцедуры // СформироватьОтчеты()
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СоздатьПереченьОтчетов();
КонецПроцедуры
&НаКлиенте
Процедура МакетОтчетаПриИзменении(Элемент)
ОбработатьВыборМакета();
КонецПроцедуры
&НаКлиенте
Процедура Сформировать(Команда)
СформироватьОтчеты();
КонецПроцедуры Смотрим, что получилось.
Выгрузка базы 1Cv8skd.rar
Источник
Категория:
Схема Компоновки Данных Управление регистрацией документа в последовательности документов Для управления регистрацией документа в последовательности документов служит набор записей регистрации в последовательности документов.
У документа есть свойство ПринадлежностьПоследовательностям. Значением свойства является коллекция наборов записей регистрации в последовательности документов. Для каждой последовательности, в которой участвует документ, существует свой собственный экземпляр набора записей. Если у документа стоит режим автоматического заполнения последовательностей, то перед записью документа наборы записей регистрации будут автоматически заполнены. Для последовательностей без измерений набор записей будет содержать только одну запись. Для последовательностей с измерениями число записей зависит от содержания документа и настройки соответствия измерений последовательности реквизитам документа.
Набор записей автоматически заполняется до записи документа и записывается после записи документа в одной транзакции с ним. Это позволяет в обработчиках событий документа ПередЗаписью() и ПриЗаписи() переопределить набор записей регистрации. Так, например, если документ входит в последовательность Последовательность1 и у документа стоит признак автоматического заполнения последовательности, то для того что бы отменить его регистрацию в последовательности в зависимости от значения реквизита документа достаточно в модуль документа вставить обработчик события ПередЗаписью() следующего содержания:
Код 1C v 8.х Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если Не Регистрировать Тогда
ПринадлежностьПоследовательностям.Последовательность1.Очистить();
КонецЕсли;
КонецПроцедуры В этом случае если реквизит Регистрировать имеет значение "Ложь", то документ не будет зарегистрирован в последовательности Последовательность1. Кроме отмены регистрации документа в последовательности, доступна возможность написания собственного алгоритма регистрации документа в последовательности. Для этого надо очистить набор записей регистрации и заполнить его новыми записями.
Код 1C v 8.х Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
ПринадлежностьПоследовательностям.Последовательность1.Очистить();
Если ВидРегистрации = 1 Тогда
ЗП = ПринадлежностьПоследовательностям.Последовательность1.Добавить();
ЗП.Измерение = Реквизит1;
ИначеЕсли ВидРегистрации = 2 Тогда
ПринадлежностьПоследовательностям.Последовательность1.Добавить();
ЗП.Измерение = Реквизит2;
КонецЕсли;
КонецПроцедуры
Пример
Код 1C v 8.х // Зарегистрируем в последовательности УУ
Если ОтражатьВУправленческомУчете Тогда
ЗаписьРегистрации = ПринадлежностьПоследовательностям.ПартионныйУчет.Добавить();
ЗаписьРегистрации.Период = Дата;
КонецЕсли;
Процедура ПоследовательностьВзаиморачеты(ДокумСсылка) Экспорт
ДокументМоментВремени = Новый МоментВремени(ДокумСсылка.дата, ДокумСсылка);
НаборЗаписей = Последовательности.Взаиморасчеты.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокумСсылка);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Регистратор = ДокумСсылка;
НоваяЗапись.Период = ДокумСсылка.Дата;
НаборЗаписей.Записать();
//Установим границу последовательности на документ
Последовательности.Взаиморасчеты.УстановитьГраницу(ДокументМоментВремени);
КонецПроцедуры
Функция ПолучитьГраницуПоследовательности(Организация = Неопределено) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПартионныйУчетГраницы.МоментВремени
|ИЗ
| Последовательность.ПартионныйУчет.Границы КАК ПартионныйУчетГраницы
|";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.МоментВремени;
Иначе
Возврат Новый МоментВремени('00010101');
КонецЕсли;
КонецФункции
Процедура ОбновитьСписокПоследовательностей()
Для каждого Последовательность Из Обр.СписокПоследовательностей Цикл
ИмяПоследовательности = Последовательность.ИмяПоследовательности;
ГраницаПоследовательности = Последовательности[ИмяПоследовательности].ПолучитьГраницу();
ДатаГраницы = ГраницаПоследовательности.Дата;
Последовательность.Актуальность = "" + ДатаГраницы + " " + ГраницаПоследовательности.Ссылка;
Последовательность.ДатаГраницы = ДатаГраницы;
КонецЦикла;
КонецПроцедуры
// Процедура выполняет поиск и исправление ошибок в последовательности.
//
Процедура КорректировкаРегистрацииВПоследовательности()
Для Каждого ТекПоследовательность Из Метаданные.Последовательности Цикл
ТекстЕстьДвижения = "
| ВЫБОР
| КОГДА СписанныеТоварыСрезПоследних.Регистратор ЕСТЬ NULL";
Для Каждого ДвиженияВлияющиеНаПоследовательность Из ТекПоследовательность.Движения Цикл
ТекстЕстьДвижения = ТекстЕстьДвижения + "
| И РегистрНакопления" + ДвиженияВлияющиеНаПоследовательность.Имя + ".Регистратор ЕСТЬ NULL";
КонецЦикла;
ТекстЕстьДвижения = ТекстЕстьДвижения + "
| ТОГДА ЛОЖЬ
| ИНАЧЕ ИСТИНА
| КОНЕЦ";
ТекстЗапроса = "ВЫБРАТЬ
| Последовательность.Регистратор КАК Регистратор,
| Последовательность.Регистратор.Проведен КАК Проведен,
| Последовательность.Регистратор.Дата КАК Дата,
| Последовательность.Период КАК Период,
|" + ТекстЕстьДвижения + " КАК ЕстьДвижения
|ИЗ
| Последовательность." + ТекПоследовательность.Имя + " КАК Последовательность
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СписанныеТовары КАК СписанныеТоварыСрезПоследних
| ПО Последовательность.Регистратор = СписанныеТоварыСрезПоследних.Регистратор
| И СписанныеТоварыСрезПоследних.НомерСтроки = 1";
Для Каждого ДвиженияВлияющиеНаПоследовательность Из ТекПоследовательность.Движения Цикл
ТекстЗапроса = ТекстЗапроса + "
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления." +ДвиженияВлияющиеНаПоследовательность.Имя + ".Обороты(, , Регистратор, ) КАК РегистрНакопления" + ДвиженияВлияющиеНаПоследовательность.Имя + "
| ПО Последовательность.Регистратор = РегистрНакопления" + ДвиженияВлияющиеНаПоследовательность.Имя + ".Регистратор";
КонецЦикла;
ТекстЗапроса = ТекстЗапроса + "
|ГДЕ
| НЕ (Последовательность.Регистратор.Проведен
| И (Последовательность.Регистратор ССЫЛКА Документ.КорректировкаСтоимостиСписанияТоваров
| ИЛИ Последовательность.Регистратор.Дата = Последовательность.Период)
| И " + ТекстЕстьДвижения + ")
|";
Запрос = Новый Запрос(ТекстЗапроса);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если Не Выборка.Проведен Тогда
НаборЗаписей = Последовательности[ТекПоследовательность.Имя].СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
НаборЗаписей.Записать();
ИначеЕсли (Выборка.Дата <> Выборка.Период)
И (ТипЗнч(Выборка.Регистратор) <> Тип("ДокументСсылка.КорректировкаСтоимостиСписанияТоваров")) Тогда
НаборЗаписей = Последовательности[ТекПоследовательность.Имя].СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
НаборЗаписей.Прочитать();
Для Каждого СтрокаНабора Из НаборЗаписей Цикл
СтрокаНабора.Период = Выборка.Дата;
КонецЦикла;
НаборЗаписей.Записать();
КонецЕсли;
Если Не Выборка.ЕстьДвижения Тогда
НаборЗаписей = Последовательности[ТекПоследовательность.Имя].СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
НаборЗаписей.Записать();
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура УдалитьРегистрациюДокументаВПоследовательностях(ДокументОбъект, ПроверятьДвижения = Ложь)Экспорт
// получение списка последовательностей в которых зарегистрирован документ
Если ПроверятьДвижения Тогда
ТаблицаРегистраций = ОпределитьНаличиеРегистрацииДокументаВПоследовательности(ДокументОбъект);
КонецЕсли;
КоллекцияПоследовательностей = ДокументОбъект.ПринадлежностьПоследовательностям;
Для Каждого НаборЗаписейРегистрацииВПоследовательности ИЗ КоллекцияПоследовательностей Цикл
Если (НаборЗаписейРегистрацииВПоследовательности.Количество() > 0)
ИЛИ (ПроверятьДвижения И (НЕ ТаблицаРегистраций.Найти(НаборЗаписейРегистрацииВПоследовательности.Метаданные().Имя,"Имя") = Неопределено)) Тогда
НаборЗаписейРегистрацииВПоследовательности.Очистить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры//УдалитьРегистрациюДокументаВПоследовательностях
Функция ОпределитьНаличиеРегистрацииДокументаВПоследовательности(ДокументОбъект) Экспорт
ТекстЗапроса = "";
Для Каждого Последовательность ИЗ ДокументОбъект.ПринадлежностьПоследовательностям Цикл
// в запросе получаем имена последовательностей, в которых документ зарегистрирован
ТекстЗапроса = ТекстЗапроса + "
|" + ?(ТекстЗапроса = "", "", "ОБЪЕДИНИТЬ ВСЕ ") + "
|ВЫБРАТЬ """ + Последовательность.Метаданные().Имя
+ """ КАК Имя ИЗ " + Последовательность.Метаданные().ПолноеИмя()
+ " ГДЕ Регистратор =Регистратор";
КонецЦикла;
Если ТекстЗапроса = "" Тогда
Возврат Новый ТаблицаЗначений();
Иначе
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Регистратор", ДокументОбъект.Ссылка);
ТаблицаЗапроса = Запрос.Выполнить().Выгрузить();
Возврат ТаблицаЗапроса;
КонецЕсли;
КонецФункции Категория:
Документы История развития запросов: Простые запросы, Временные таблицы, Пакетные запросы Простые запросы Разберем, как изменялся (скорее дополнялся) синтаксис текстов запросов на простом примере: Проводится документ Расходная содержащая в табличной части Товары список продаваемых товаров и количество. При проведении такого документа необходимо обеспечить контроль отрицательных остатков хранящихся в регистре накопления остатков ОстаткиТоваров .
Структура конфигурации представлена на рисунке справа:
Сформируем запрос к табличной части документа и виртуальной таблице Остатки регистра накопления. Учтем возможные дубли строк в документе, для этого произведем группирование записей.
Код 1C v 8.х Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Док.Номенклатура,
| СУММА(Док.Количество) КАК Док_Количество,
| МИНИМУМ(ЕСТЬNULL(Рег.КоличествоОстаток,0)) КАК Рег_Количество
|
|ИЗ
| Документ.Расходная.Товары КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ
| РегистрНакопления.ОстаткиТоваров.Остатки() КАК Рег
| ПО
| Док.Номенклатура = Рег.Номенклатура
|
|ГДЕ
| Ссылка =Ссылка
|СГРУППИРОВАТЬ ПО Док.Номенклатура";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
//Проверка отрицательных остатков
//Проведение по регистру
КонецЦикла;
КонецПроцедуры Естественно приведенный запрос абсолютно не оптимален. С помощью вложенных запросов оптимизируем его: Произведем группирование табличной части документа до соединения с таблицей остатков, в параметры виртуальной таблицы передадим список товаров как значение условия для расчета остатков. В итоге наш запрос примет следующий вид:
Код 1C v 8.х |ВЫБРАТЬ
| Док.Номенклатура,
| Док.Количество КАК Док_Количество,
| ЕСТЬNULL(Рег.КоличествоОстаток,0) КАК Рег_Количество
|
|ИЗ
| (ВЫБРАТЬ
| Номенклатура, СУММА(Количество) КАК Количество
| ИЗ
| Документ.Расходная.Товары
| ГДЕ
| Ссылка =Ссылка
| СГРУППИРОВАТЬ ПО Номенклатура) КАК Док
|
| ЛЕВОЕ СОЕДИНЕНИЕ
| РегистрНакопления.ОстаткиТоваров.Остатки( , Номенклатура В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
| ИЗ
| Документ.Расходная.Товары
| ГДЕ
| Ссылка =Ссылка)) КАК Рег
| ПО
| Док.Номенклатура = Рег.Номенклатура"; Если бы в запросе необходимо было бы получить данные из остатков разных регистров то значение фильтра, а следовательно и наш второй вложенный запрос, повторялся бы во всех параметрах виртуальных таблиц, естественно что система при каждом вложенном запросе заново обращается к базе данных для получения данных.
Временные таблицы Не помню уже с какого релиза в запросах стало можно использовать временные таблицы. Для этого используется объект «Менеджер временных таблиц». Фактически менеджер временных таблиц описывает пространство имен временных таблиц и отвечает за их создание и уничтожение в базе данных.
Сами временные таблицы действительно физически создаются в базе, соответственно следует относиться к ним осторожно, так как дисковая подсистема на сегодняшний момент самая медленная часть техники, а скорость создания и уничтожения таблиц напрямую от нее зависит.
Перепишем запрос для использования временных таблиц. Во временные таблицы поместим сгруппированную табличную часть документа и список товаров для фильтра виртуальных таблиц:
Код 1C v 8.х Процедура ОбработкаПроведения(Отказ, РежимПроведения)
МВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "
|ВЫБРАТЬ
| Номенклатура, СУММА(Количество) КАК Количество
|ПОМЕСТИТЬ ДокТЧ
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка =Ссылка
|СГРУППИРОВАТЬ ПО Номенклатура";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить(); //Прим. 1
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
|ПОМЕСТИТЬ СписокТоваров
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка =Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить(); //Прим. 2
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "
|ВЫБРАТЬ
| Док.Номенклатура,
| Док.Количество КАК Док_Количество,
| ЕСТЬNULL(Рег.КоличествоОстаток,0) КАК Рег_Количество
|ИЗ
| ДокТЧ КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ
| РегистрНакопления.ОстаткиТоваров.Остатки(,
| Номенклатура В(ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
| ИЗ
| СписокТоваров КАК СписокТоваров)) КАК Рег
| ПО
| Док.Номенклатура = Рег.Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
//Проверка отрицательных остатков
//Проведение по регистру
КонецЦикла;
КонецПроцедуры При использовании временных таблиц в тексте запроса применяют инструкцию Поместить для создания новой временной таблицы, в этом случае в результат запроса система передает не содержимое этой таблицы (см прим 1 и прим 2 в тексте выше), а количество записей помещенных во временную таблицу, по желанию можно не принимать это значение.
Также допускается использование инструкции Уничтожить в этом случае временная таблица уничтожается, в противном случае временные таблицы уничтожаются вместе с объектом менеджер временных таблиц.
В основном нашем запросе я использовал названия временных таблиц как указание на источник получения данных (им обязательно надо назначать синоним, что мы и видим в тексте). Использовать временные таблицы как источник можно не единожды, что при умелом их применении позволит и сократить текст запроса (улучшиться читабельность сложных запросов) и увеличить скорость (при использовании данных временной таблицы в нескольких местах запроса).
Пакетные запросы Пакетные запросы логично дополняют функционал временных таблиц и дают больше возможностей при работе с запросами.
В пакетном запросе фактически можно описать несколько запросов, как связанных между собой использованием временных таблиц, так и не связанных (можно, но не понятно зачем?). В итоге можно выполнить последовательно все запросы и принять в результате либо массив с результатами исполнения каждого запроса, либо результат последнего. Для получения массива с результатами запроса применяют метод ВыполнитьПакет() объекта запрос, а для получения результата последнего запроса ВыполнитьЗапрос().
В тексте запроса, запросы пакета разделяются символом «;» (точка с запятой). Область имен виртуальных таблиц у одного пакетного запроса одна. Использование менеджера временных таблиц не требуется, но возможно если вы хотите передать временные таблицы из одного пакетного запроса в другой.
Перепишем процедуру для использования пакетных запросов:
Код 1C v 8.х Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Номенклатура, СУММА(Количество) КАК Количество
|ПОМЕСТИТЬ ДокТЧ
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка =Ссылка
|СГРУППИРОВАТЬ ПО Номенклатура
|;
|
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
|ПОМЕСТИТЬ СписокТоваров
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка =Ссылка
|;
|
|ВЫБРАТЬ
| Док.Номенклатура,
| Док.Количество КАК Док_Количество,
| ЕСТЬNULL(Рег.КоличествоОстаток,0) КАК Рег_Количество
|ИЗ
| ДокТЧ КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ
| РегистрНакопления.ОстаткиТоваров.Остатки(,
| Номенклатура В(ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
| ИЗ
| СписокТоваров КАК СписокТоваров)) КАК Рег
| ПО
| Док.Номенклатура = Рег.Номенклатура";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
МассивРезультаттов = Запрос.ВыполнитьПакет(); //Прим. 1
РезультатЗапроса = Запрос.Выполнить(); //Прим. 2
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
//Проверка отрицательных остатков
//Проведение по регистру
КонецЦикла;
КонецПроцедуры Фактически я убрал определение объекта запрос и использование менеджера временных таблиц, объединил тексты запросов (обратите внимание на разделитель «;» между текстами). В результате текст запроса стал читабельнее (а при использовании конструктора запросов намного увеличивается удобство чтения запроса).
После выполнения запроса в переменную МассивРезультатов у нас попадет 3 элемента. Первые два будут содержать число характеризующее количество записей помещенных во временные таблицы ДокТЧ и СписокТоваров , а третий будет содержать выборку с полями Номенклатура, Док_Количество и Рег_Количество .
В переменную РезультатЗапроса попадет только выборка.
Ну вот и все что касается пакетных запросов. Очень удобный механизм и с точки зрения написания запросов и с точки зрения чтения сложных запросов.
Автор: Павел Чистов
Категория:
Запросы Функции для работы с ZIP-архивами В работе часто приходится сжимать выгруженные данные в zip архив, отправлять по почте, и потом автоматически разархивировать полученный zip файл:
Код 1C v 8.х // Распаковывает файл архива ZIP в указанный каталог; Извлекает все файлы архива
//
// Параметры:
// ПолноеИмяФайлаАрхива - Строка - имя файла архива, который необходимо распаковать
// ПутьРаспаковкиФайлов - Строка - путь по которому необходимо распаковать файлы
// ПарольАрхива - Строка - пароль для распаковки архива. По умолчанию пустая строка
//
// Возвращаемое значение:
// Результат - Булево - Истина, если успешно, Ложь, если нет.
//
Функция РаспаковатьZipФайл(Знач ПолноеИмяФайлаАрхива, Знач ПутьРаспаковкиФайлов, Знач ПарольАрхива = "") Экспорт
// возвращаемое значение функции
Результат = Истина;
Попытка
Архиватор = Новый ЧтениеZipФайла(ПолноеИмяФайлаАрхива, ПарольАрхива);
Исключение
Архиватор = Неопределено;
СообщитьОбОшибке(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Ложь;
КонецПопытки;
Попытка
Архиватор.ИзвлечьВсе(ПутьРаспаковкиФайлов, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка при распаковке файлов архива: %1 в каталог: %2'");
СтрокаСообщения = ПодставитьПараметрыВСтроку(СтрокаСообщения, ПолноеИмяФайлаАрхива, ПутьРаспаковкиФайлов);
Сообщить(СтрокаСообщения);
Результат = Ложь;
КонецПопытки;
Архиватор.Закрыть();
Архиватор = Неопределено;
Возврат Результат;
КонецФункции
// Запаковывает указанный каталог в файл архива ZIP
//
// Параметры:
// ПолноеИмяФайлаАрхива - Строка - имя файла архива, в который необходимо запаковать
// МаскаУпаковкиФайлов - Строка - имя файла, помещаемого в архив, или маска.
// Недопустимо использование в именах файлов и папок букв национальных алфавитов, которые при
// преобразовании из символов UNICODE в узкие символы могут быть преобразованы с потерей информации.
// Рекомендуется использовать в именах файлов и папок символы латинского алфавита.
// ПарольАрхива - Строка - пароль для архива. По умолчанию пустая строка
//
// Возвращаемое значение:
// Результат - Булево - Истина, если успешно, Ложь, если нет.
//
Функция ЗапаковатьВZipФайл(Знач ПолноеИмяФайлаАрхива, Знач МаскаУпаковкиФайлов, Знач ПарольАрхива = "") Экспорт
// возвращаемое значение функции
Результат = Истина;
Попытка
Архиватор = Новый ЗаписьZipФайла(ПолноеИмяФайлаАрхива, ПарольАрхива);
Исключение
Архиватор = Неопределено;
СообщитьОбОшибке(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Ложь;
КонецПопытки;
Попытка
Архиватор.Добавить(МаскаУпаковкиФайлов, РежимСохраненияПутейZIP.НеСохранятьПути);
Архиватор.Записать();
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка при запаковке файлов архива: %1 из каталог: %2'");
СтрокаСообщения = ПодставитьПараметрыВСтроку(СтрокаСообщения, ПолноеИмяФайлаАрхива, МаскаУпаковкиФайлов);
Сообщить(СтрокаСообщения);
Результат = Ложь;
КонецПопытки;
Архиватор = Неопределено;
Возврат Результат;
КонецФункции В примере используется строковая функция ПодставитьПараметрыВСтроку ():
Код 1C v 8.х // Подставляет параметры в строку. Максимально возможное число параметров - 9.
// Параметры в строке задаются как %<номер параметра>. Нумерация параметров начинается с единицы.
//
// Параметры:
// СтрокаПодстановки – Строка – шаблон строки с параметрами (вхождениями вида "%ИмяПараметра");
// Параметр<n> - Строка - подставляемый параметр.
//
// Возвращаемое значение:
// Строка – текстовая строка с подставленными параметрами.
//
// Пример:
// ПодставитьПараметрыВСтроку(НСтр("ru='%1 пошел в %2'"), "Вася", "Зоопарк") = "Вася пошел в Зоопарк".
//
Функция ПодставитьПараметрыВСтроку(Знач СтрокаПодстановки,
Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено,
Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено,
Знач Параметр7 = Неопределено, Знач Параметр8 = Неопределено, Знач Параметр9 = Неопределено) Экспорт
Если СтрокаПодстановки = Неопределено ИЛИ СтрДлина(СтрокаПодстановки) = 0 Тогда
Возврат "";
КонецЕсли;
Результат = "";
НачПозиция = 1;
Позиция = 1;
Пока Позиция <= СтрДлина(СтрокаПодстановки) Цикл
СимволСтроки = Сред(СтрокаПодстановки, Позиция, 1);
Если СимволСтроки <> "%" Тогда
Позиция = Позиция + 1;
Продолжить;
КонецЕсли;
Результат = Результат + Сред(СтрокаПодстановки, НачПозиция, Позиция - НачПозиция);
Позиция = Позиция + 1;
СимволСтроки = Сред(СтрокаПодстановки, Позиция, 1);
Если СимволСтроки = "%" Тогда
Позиция = Позиция + 1;
НачПозиция = Позиция;
Результат = Результат + "%";
Продолжить;
КонецЕсли;
Попытка
НомерПараметра = Число(СимволСтроки);
Исключение
ВызватьИсключение НСтр("ru='Входная строка СтрокаПодстановки имеет неверный формат: %'" + СимволСтроки);
КонецПопытки;
Если СимволСтроки = "1" Тогда
ЗначениеПараметра = Параметр1;
ИначеЕсли СимволСтроки = "2" Тогда
ЗначениеПараметра = Параметр2;
ИначеЕсли СимволСтроки = "3" Тогда
ЗначениеПараметра = Параметр3;
ИначеЕсли СимволСтроки = "4" Тогда
ЗначениеПараметра = Параметр4;
ИначеЕсли СимволСтроки = "5" Тогда
ЗначениеПараметра = Параметр5;
ИначеЕсли СимволСтроки = "6" Тогда
ЗначениеПараметра = Параметр6;
ИначеЕсли СимволСтроки = "7" Тогда
ЗначениеПараметра = Параметр7;
ИначеЕсли СимволСтроки = "8" Тогда
ЗначениеПараметра = Параметр8;
ИначеЕсли СимволСтроки = "9" Тогда
ЗначениеПараметра = Параметр9;
Иначе
ВызватьИсключение НСтр("ru='Входная строка СтрокаПодстановки имеет неверный формат: %'" + ЗначениеПараметра);
КонецЕсли;
Если ЗначениеПараметра = Неопределено Тогда
ЗначениеПараметра = "";
Иначе
ЗначениеПараметра = Строка(ЗначениеПараметра);
КонецЕсли;
Результат = Результат + ЗначениеПараметра;
Позиция = Позиция + 1;
НачПозиция = Позиция;
КонецЦикла;
Если (НачПозиция <= СтрДлина(СтрокаПодстановки)) Тогда
Результат = Результат + Сред(СтрокаПодстановки, НачПозиция, СтрДлина(СтрокаПодстановки) - НачПозиция + 1);
КонецЕсли;
Возврат Результат;
КонецФункции Категория:
Работа с Файлами и Каталогами Универсальные функции работы с регистрами сведений Разработка любой конфигурации потребует использования регистров сведений! Чтобы упростить запись и чтение данных в регистре сведений, Вы можете использовать универсальные функции:
Код 1C v 8.х // Добавляет одну запись в регистр сведений по переданным значениям структуры
//
// Параметры:
// СтруктураЗаписи - Структура - структура, по значениям которой необходимо создать набор записей и заполнить этот набор
// ИмяРегистра - Строка - имя регистра сведений, в который необходимо добавить запись
//
Процедура ДобавитьЗаписьВРегистрСведений(СтруктураЗаписи, Знач ИмяРегистра, Загрузка = Ложь) Экспорт
НаборЗаписей = СоздатьНаборЗаписейРегистраСведений(СтруктураЗаписи, ИмяРегистра);
// добавляем только одну запись в новый набор записей
НоваяЗапись = НаборЗаписей.Добавить();
// заполняем значения свойств записи из переданной структуры
ЗаполнитьЗначенияСвойств(НоваяЗапись, СтруктураЗаписи);
НаборЗаписей.ОбменДанными.Загрузка = Загрузка;
// записываем набор записей
НаборЗаписей.Записать();
КонецПроцедуры
// Обновляет запись в регистр сведений по переданным значениям структуры
//
// Параметры:
// СтруктураЗаписи - Структура - структура, по значениям которой необходимо создать менеджер записи и обновить запись
// ИмяРегистра - Строка - имя регистра сведений, в котором необходимо обновить запись
//
Процедура ОбновитьЗаписьВРегистрСведений(СтруктураЗаписи, Знач ИмяРегистра) Экспорт
МетаданныеРегистра = Метаданные.РегистрыСведений[ИмяРегистра];
// создаем менеджер записи регистра
МенеджерЗаписи = РегистрыСведений[ИмяРегистра].СоздатьМенеджерЗаписи();
// устанавливаем отбор по измерениям регистра
Для Каждого Измерение ИЗ МетаданныеРегистра.Измерения Цикл
// если задано значение в структуре, то отбор устанавливаем
Если СтруктураЗаписи.Свойство(Измерение.Имя) Тогда
МенеджерЗаписи[Измерение.Имя] = СтруктураЗаписи[Измерение.Имя];
КонецЕсли;
КонецЦикла;
// считываем запись из базы данных
МенеджерЗаписи.Прочитать();
// заполняем значения свойств записи из переданной структуры
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтруктураЗаписи);
// записываем менеджер записи
МенеджерЗаписи.Записать();
КонецПроцедуры
// Удаляет набор записей в регистре по переданным значениям структуры
//
// Параметры:
// СтруктураЗаписи - Структура - структура, по значениям которой необходимо удалить набор записей
// ИмяРегистра - Строка - имя регистра сведений, в котором необходимо удалить набор записей
//
Процедура УдалитьНаборЗаписейВРегистреСведений(СтруктураЗаписи, ИмяРегистра, Загрузка = Ложь) Экспорт
НаборЗаписей = СоздатьНаборЗаписейРегистраСведений(СтруктураЗаписи, ИмяРегистра);
НаборЗаписей.ОбменДанными.Загрузка = Загрузка;
// записываем набор записей
НаборЗаписей.Записать();
КонецПроцедуры
// Создает набор записей регистра сведений по переданным значениям структуры. Добавляет одну запись в набор
//
// Параметры:
// СтруктураЗаписи - Структура - структура по значениям которой необходимо создать набор записей и заполнить этот набор
// ИмяРегистра - Строка - имя регистра сведений
//
Функция СоздатьНаборЗаписейРегистраСведений(СтруктураЗаписи, ИмяРегистра) Экспорт
МетаданныеРегистра = Метаданные.РегистрыСведений[ИмяРегистра];
// создаем набор записей регистра
НаборЗаписей = РегистрыСведений[ИмяРегистра].СоздатьНаборЗаписей();
// устанавливаем отбор по измерениям регистра
Для Каждого Измерение ИЗ МетаданныеРегистра.Измерения Цикл
// если задано значение в структуре, то отбор устанавливаем
Если СтруктураЗаписи.Свойство(Измерение.Имя) Тогда
НаборЗаписей.Отбор[Измерение.Имя].Установить(СтруктураЗаписи[Измерение.Имя]);
КонецЕсли;
КонецЦикла;
Возврат НаборЗаписей;
КонецФункции
Категория:
Регистры сведений Как прочитать записи регистра сведений установив отбор и удалить записи? Прочитать записи регистра сведений можно двумя способами: Через Набор Записей или Менеджер
Вот пример через набор записей :
Код 1C v 8.х // Добавление новых данных в существующую запись регистра сведений
НаборЗаписей = РегистрыСведений.ДокументоОборот.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Доставка.Установить(Доставка);
НаборЗаписей.Отбор.Этап.Установить(Этап);
НаборЗаписей.Прочитать();
Для каждого Запись из НаборЗаписей Цикл
Запись.ДатаВремя = ДатаР;
Запись.Отдел = фио.Подразделение;
Запись.ФИО = ПараметрыСеанса.ТекущийПользователь;
Запись.Документы = Документы;
Запись.Примечание = Примечание;
КонецЦикла;
НаборЗаписей.Записать(); Пример с использованием набора записей и менеджера записи:
Код 1C v 8.х НаборЗаписей = РегистрыСведений.CRM_Напоминания.СоздатьНаборЗаписей();
Отбор = НаборЗаписей.Отбор;
Отбор.Объект.Установить(Объект.Ссылка);
Отбор.Завершено.Установить(Ложь);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 0 Тогда
Если ЗадаватьВопрос Тогда
ТекстВопроса = "Завершить все напоминания для " + Строка(Объект.Ссылка) + " ?";
Ответ = Вопрос(ТекстВопроса,РежимДиалогаВопрос.ДаНет, ,КодВозвратаДиалога.Да);
Иначе
Ответ = КодВозвратаДиалога.Да
КонецЕсли;
Если Ответ = КодВозвратаДиалога.Да Тогда
Для каждого Запись Из НаборЗаписей Цикл
РегистрСведенийМенеджерЗаписи = РегистрыСведений.CRM_Напоминания.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(РегистрСведенийМенеджерЗаписи, Запись);
РегистрСведенийМенеджерЗаписи.Прочитать();
Если РегистрСведенийМенеджерЗаписи.Выбран() Тогда //напоминание небыло удалено
Если НЕ РегистрСведенийМенеджерЗаписи.УдалитьПоИстеченииСрока Тогда
РегистрСведенийМенеджерЗаписи.Завершено = Истина;
РегистрСведенийМенеджерЗаписи.Записать();
Иначе
РегистрСведенийМенеджерЗаписи.Удалить();
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
А вот пример через менеджер записи:
Код 1C v 8.х МенеджерЗаписи = РегистрыСведений.НоменклатураКонтрагентов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Контрагент = Контрагент;
МенеджерЗаписи.Номенклатура = СтрокаТаблицыТовары.Номенклатура;
МенеджерЗаписи.ХарактеристикаНоменклатуры = СтрокаТаблицыТовары.ХарактеристикаНоменклатуры;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
Вес = МенеджерЗаписи.ВесНоменклатурыКонтрагента;
КонецЕсли; Категория:
Регистры сведений Функция очищает текст в формате HTML от тегов и возвращает неформатированный текст - вариант 2 Категория:
Работа с Текстом (Строкой) Функция очищает текст в формате HTML от тегов и возвращает неформатированный текст Работая с html данными, бывает необходимо получить только чистый текст, исключив все теги и скрипты.
Ниже приведена универсальная функция, оставляющая только текст:
Код 1C v 8.х // Очищает текст в формате HTML от тегов и возвращает неформатированный текст.
Функция ИзвлечьТекстИзHTML(Знач ИсходныйТекст) Экспорт
Результат = "";
Текст = НРег(ИсходныйТекст);
// отрезаем всё что не body
Позиция = Найти(Текст, "<body");
Если Позиция > 0 Тогда
Текст = Сред(Текст, Позиция + 5);
ИсходныйТекст = Сред(ИсходныйТекст, Позиция + 5);
Позиция = Найти(Текст, ">");
Если Позиция > 0 Тогда
Текст = Сред(Текст, Позиция + 1);
ИсходныйТекст = Сред(ИсходныйТекст, Позиция + 1);
КонецЕсли;
КонецЕсли;
Позиция = Найти(Текст, "</body>");
Если Позиция > 0 Тогда
Текст = Лев(Текст, Позиция - 1);
ИсходныйТекст = Лев(ИсходныйТекст, Позиция - 1);
КонецЕсли;
// вырезаем скрипты
Позиция = Найти(Текст, "<script");
Пока Позиция > 0 Цикл
ПозицияЗакрывающегоТега = Найти(Текст, "</script>");
Текст = Лев(Текст, Позиция - 1) + Сред(Текст, ПозицияЗакрывающегоТега + 9);
ИсходныйТекст = Лев(ИсходныйТекст, Позиция - 1) + Сред(ИсходныйТекст, ПозицияЗакрывающегоТега + 9);
Позиция = Найти(Текст, "<script");
КонецЦикла;
// вырезаем все теги
Позиция = Найти(Текст, "<");
Пока Позиция > 0 Цикл
Результат = Результат + Лев(ИсходныйТекст, Позиция-1);
Текст = Сред(Текст, Позиция + 1);
ИсходныйТекст = Сред(ИсходныйТекст, Позиция + 1);
Позиция = Найти(Текст, ">");
Если Позиция > 0 Тогда
Текст = Сред(Текст, Позиция + 1);
ИсходныйТекст = Сред(ИсходныйТекст, Позиция + 1);
КонецЕсли;
Позиция = Найти(Текст, "<");
КонецЦикла;
Результат = Результат + ИсходныйТекст;
Возврат СокрЛП(Результат);
КонецФункции Категория:
Работа с Текстом (Строкой)