Функция получение содержимого адреса url (веб-страницы) методом GET // Возвращает содержимое ответа HTTP-сервера, полученного методом GET, в виде строки или двоичных данных
// ** Coded by Sergey (aka Porutchik) * 2014 http://forum.aeroion.ru/cat1.html //
// Параметры
// СерверПриемник - - доменное имя сервера или полный адрес (url) запрашиваемой ссылки.
// Может включать протокол (http://, https://) и порт.
// АдресСтраницы - - опционально. Адрес страницы на сервере без протокола (http://, https://),
// доменного имени сервера (хоста) и порта.
// Если не указано, адрес страницы будет извлечён из параметра СерверПриемник
// ПараметрыСоединения - - опционально. Структура, содержащая дополнительные параметры для HTTPСоединение.
// Назначение ключей:
// Логин или Пользователь - Тип Строка - Имя пользователя на указанном сервере.
// Пароль - Тип Строка - Пароль пользователя на указанном сервере.
// Прокси - Тип ИнтернетПрокси - Прокси, используемый для соединения с сервером.
// Таймаут - Тип Число - Таймаут осуществляемого соединения и операций, в секундах. 0 - не устанавливать таймаут..
// ЗаголовкиHTTP - - опционально.
// Заголовки, которые будут отправлены на сервер в виде соответствия: "Заголовок" - "Значение".
// Если указано, функция возвратит в программу заголовки HTTP-ответа с кодом состояния в ключе StatusCode,
// имя файла в ключе FileName, url-кодированное имя в ключе EncodeFileName
// ПолучитьКакДвоичныеДанные - - опционально. Определяет, в каком виде получить содержимое ответа сервера
// По умолчанию Ложь.
// ЗащищенноеСоединение - - опционально. По умолчанию Ложь.
// Если Истина, соединение будет происходить по протоколу https://
//
// Возвращаемое значение:
// , - содержимое ответа сервера, если ресурс найден по указанному адресу.
//
Функция ПолучитьСодержимоеВебАдреса(Знач СерверПриемник, Знач АдресСтраницы = "",
Знач ПараметрыСоединения = Неопределено, ЗаголовкиHTTP = Неопределено,
Знач ПолучитьКакДвоичныеДанные = Ложь, Знач ЗащищенноеСоединение = Ложь) Экспорт
Перем ИмяФайлаОтветаКодированное, ИмяФайлаОтвета, Порт, Логин, Пользователь, Пароль, Прокси, Таймаут;
Если Не ЗначениеЗаполнено(СерверПриемник) Тогда Возврат Неопределено; КонецЕсли;
Если ТипЗнч(ЗаголовкиHTTP) Тип("Соответствие") Тогда ЗаголовкиHTTP = Новый Соответствие; КонецЕсли;
Если Найти(Нрег(СерверПриемник), "https://") = 1 Тогда ЗащищенноеСоединение = Истина; КонецЕсли;
Протокол = ?(Найти(Нрег(СерверПриемник), "https://") = 1 ИЛИ ЗащищенноеСоединение, "https://", "http://");
Если Лев(НРег(СерверПриемник), СтрДлина(Протокол)) = Протокол Тогда
СерверПриемник = Сред(СерверПриемник, СтрДлина(Протокол) + 1);
КонецЕсли;
Если НЕ ЗначениеЗаполнено(АдресСтраницы) Тогда
Позиция = Найти(СерверПриемник, "/");
Если Позиция > 0 Тогда
АдресСтраницы = Сред(СерверПриемник, Позиция, СтрДлина(СерверПриемник));
СерверПриемник = Лев(СерверПриемник, Позиция - 1);
Иначе
АдресСтраницы = "/";
КонецЕсли;
КонецЕсли;
СерверПриемник = СтрЗаменить(СерверПриемник, "/", "");
//Выделяем порт из доменного имени
ПозицияДвоеточия = Найти(СерверПриемник, ":");
Если ПозицияДвоеточия > 0 Тогда
Порт = Число(Сред(СерверПриемник, ПозицияДвоеточия + 1));
СерверПриемник = Лев(СерверПриемник, ПозицияДвоеточия - 1);
КонецЕсли;
Если ТипЗнч(ПараметрыСоединения) = Тип("Структура") Тогда
Для каждого КлючЗначение из ПараметрыСоединения Цикл
Значение = КлючЗначение.Значение; Выполнить(КлючЗначение.Ключ + " = Значение;");
КонецЦикла;
Пользователь = ?(ЗначениеЗаполнено(Пользователь), Пользователь, Логин);
КонецЕсли;
НТТР = Новый HTTPСоединение(СерверПриемник, Порт, Пользователь, Пароль, Прокси, Таймаут,
?(ЗащищенноеСоединение, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено));
//Ответ от сервера получим в возвращаемом значении типа HTTPОтвет
ОтветHTTP = НТТР.Получить(Новый HTTPЗапрос(АдресСтраницы, ЗаголовкиHTTP)); //
ОшибкаЗапроса = (ОтветHTTP.КодСостояния >= 400);
//После получения ответа сервера необходимо проверить статус или код состояния.
//http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.... //Если сервер вернул один из статусов переадресации
//301 Moved Permanently («перемещено навсегда») или 302 Moved Temporar ily («перемещено временно»),
//то в этом случае можно попытаться перейти на ресурс, на который переадресовал сервер
Если ОтветHTTP.КодСостояния = 301 или ОтветHTTP.КодСостояния = 302 Тогда
Если ОтветHTTP.Заголовки.Количество() > 0 Тогда
//Адрес страницы переадресации содержится в поле Location заголовка ответа
АдресСтраницы = ОтветHTTP.Заголовки["Location"]; //
Если ЗначениеЗаполнено(АдресСтраницы) Тогда
Если Найти(НРег(АдресСтраницы), "http://") = 0 И Найти(НРег(АдресСтраницы), "https://") = 0 Тогда
АдресСтраницы = ?(Лев(АдресСтраницы, 1) = "/", Сред(АдресСтраницы, 2), АдресСтраницы);
Если Найти(АдресСтраницы, СерверПриемник + "/") = 0 Тогда
АдресСтраницы = Протокол + СерверПриемник + ?(ЗначениеЗаполнено(Порт), ":" + Порт, "") + "/" + АдресСтраницы;
КонецЕсли;
КонецЕсли;
//Если сервер вернул cookies (http://ru.wikipedia.org/wiki/HTTP_cookie, http://www.faqs.org/rfcs/rfc6265.html?#41;, //вставим их в заголовки для передачи на страницу перехода
Куки = ОтветHTTP.Заголовки["Set-Cookie"];//
Если ЗначениеЗаполнено(Куки) Тогда ЗаголовкиHTTP.Вставить("Cookie", Куки); КонецЕсли;
//Рекурсивный вызов
Возврат ПолучитьСодержимоеВебАдреса(АдресСтраницы, , , ЗаголовкиHTTP, ПолучитьКакДвоичныеДанные, ЗащищенноеСоединение);//
КонецЕсли;
КонецЕсли;
ИначеЕсли ОтветHTTP.КодСостояния >= 100 И ОтветHTTP.КодСостояния 0 Тогда
ТипСодержимого = ОтветHTTP.Заголовки["Content-Type"];
//http://ru.wikipedia.org/wiki/Список_MIME-типов Если Найти(ТипСодержимого, "text/") = 1 ИЛИ Найти(ТипСодержимого, "/javascript")
ИЛИ Найти(ТипСодержимого, "+xml") ИЛИ Найти(ТипСодержимого, "/xml") 0 ИЛИ Найти(ТипСодержимого, "/json") 0 Тогда
ПолучитьКакДвоичныеДанные = Ложь;
ИначеЕсли Найти(ТипСодержимого, "image/") = 1 ИЛИ Найти(ТипСодержимого, "video/") = 1
ИЛИ Найти(ТипСодержимого, "application/") = 1 ИЛИ Найти(ТипСодержимого, "audio/") = 1 Тогда
//Если содержимое полученного ответа представляет собой изображение, видео, приложение,
//возвращаем двоичные данные, так как возвращать в виде строки не имеет смысла.
ПолучитьКакДвоичныеДанные = Истина;
КонецЕсли;
//Некоторые сервера возвращают в типе содержимого имя отданного файла, например image/png; name="Имя файла.png"
//или отдают в заголовке Content-Disposition: attachment; filename=Имя файла.png (http://www.http11.ru/post.php?post=2) Если ОтветHTTP.Заголовки["Content-Disposition"] Неопределено Тогда
ТипСодержимого = ОтветHTTP.Заголовки["Content-Disposition"];
КонецЕсли;
ТипСодержимого = СтрЗаменить(СтрЗаменить(ТипСодержимого, """", ""), "'", "");
//в ключе filename*=UTF-8'' содержится url-кодированное имя файла
ПозицияИмениФайла = Найти(ТипСодержимого, "filename*=UTF-8");
Если ПозицияИмениФайла 0 Тогда
ИмяФайлаОтветаКодированное = Сред(ТипСодержимого, ПозицияИмениФайла + СтрДлина("filename*=UTF-8"));
ПозицияДвоеточия = Найти(ИмяФайлаОтветаКодированное, ";");
Если ПозицияДвоеточия 0 Тогда
ИмяФайлаОтветаКодированное = Лев(ИмяФайлаОтветаКодированное, ПозицияДвоеточия - 1);
КонецЕсли;
КонецЕсли;
//в ключе filename= содержится обычное имя файла
ПозицияИмениФайла = Найти(ТипСодержимого, "name=");
Если ПозицияИмениФайла 0 Тогда
ИмяФайлаОтвета = Сред(ТипСодержимого, ПозицияИмениФайла + СтрДлина("name="));
ПозицияДвоеточия = Найти(ИмяФайлаОтвета, ";");
Если ПозицияДвоеточия 0 Тогда
ИмяФайлаОтвета = Лев(ИмяФайлаОтвета, ПозицияДвоеточия - 1);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ЗаголовкиHTTP = ОтветHTTP.Заголовки;
//Добавляем в заголовки ответа код состояния (ответа) HTTP-сервера и имя файла содержимого, если есть.
ЗаголовкиHTTP.Вставить("StatusCode", ОтветHTTP.КодСостояния);
Если ЗначениеЗаполнено(ИмяФайлаОтвета) Тогда ЗаголовкиHTTP.Вставить("FileName", ИмяФайлаОтвета); КонецЕсли;
Если ЗначениеЗаполнено(ИмяФайлаОтветаКодированное) Тогда
ЗаголовкиHTTP.Вставить("EncodeFileName", ИмяФайлаОтветаКодированное);
КонецЕсли;
Если ОшибкаЗапроса ИЛИ НЕ ПолучитьКакДвоичныеДанные Тогда Возврат ОтветHTTP.ПолучитьТелоКакСтроку(); КонецЕсли;
Возврат ОтветHTTP.ПолучитьТелоКакДвоичныеДанные();
КонецФункции // ПолучитьСодержимоеВебАдреса()
//Источник: http://forum.aeroion.ru/topic749.html [/pre]Примеры использования:
// Получение содержимого в виде строки//
СодержимоеАдреса = ПолучитьСодержимоеВебАдреса("
//
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP.Вставить("Referer", "a href="http://some_site.com/" )"="">http://some_site.com/");
СодержимоеАдреса = ПолучитьСодержимоеВебАдреса(" Категория: Нет
Как декодировать (преобразовать) Unicode в 1С При разработке очередного обмена с интернет магазином через API столкнулисть что сайт возвращает ответ в виде:
Код VBS {"ok":"true","description":"\u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0430\u0437\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d"}
из кода ясно что это JSON и используя код ПрочитатьJSON
Код 1C v 8.3 Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(стрВходящая);
ДанныеЛога = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
В переменной ДанныеЛога будет структура в виде
В результате получилась функция с 2-мя вариантами возрата, в зависимости от того как нужно
Код 1C v 8.3 //Функция читает полученный JSON декадируя текст юникод
Функция ДекодироватьUniCodeВJSON(стрВходящая)
// стрВходящая содержит {"ok":"true","description":"\u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0430\u0437\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d"}
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(стрВходящая);
ДанныеЛога = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
// Вариант 1 используя перебор структуры и вывод в текстовую переменную
Текст = "";
Для каждого Элемент Из ДанныеЛога Цикл
//добавим разделитель после предыдущего значения
Текст = Текст + ?(НЕ ПустаяСтрока(Текст), Символы.ПС, "");
//добавим представление ключа и значения:
Текст = Текст + Элемент.Ключ + " = " + Элемент.Значение;
КонецЦикла;
Возврат Текст; //Вернет ok = true description = Статус заказа изменен
// Вариант 2 мспользуя ЗаписьJSON
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет));
ЗаписатьJSON(Запись, ДанныеЛога,);
Возврат Запись.Закрыть(); // Вернет JSON {"ok":"true","description":"Статус заказа изменен"}
КонецФункции
На просторах интернета была найдена еще одна функция:
Код 1C v 8.3 //Параметры: Строка в Юникод (обязательный) Тип: Строка. Исходная строка.
//Возвращаемое значение: Тип: Строка. Строка обработанных символов.
//Описание: Возвращает преобразованную строку из формата Unicod.
//Автор: Александр Кияница (treedo)
Функция ПереобразоватьЮникод(Строка)
ГотововаяСтрока = "" ;
МасУкр = Новый Массив(66) ;
МасУкр[0]="А"; МасУкр[1]="Б"; МасУкр[2]="В"; МасУкр[3]="Г"; МасУкр[4]="Ґ"; МасУкр[5]="Д";
МасУкр[6]="Е"; МасУкр[7]="Є"; МасУкр[8]="Ж"; МасУкр[9]="З"; МасУкр[10]="И"; МасУкр[11]="І";
МасУкр[12]="Ї"; МасУкр[13]="Й"; МасУкр[14]="К"; МасУкр[15]="Л"; МасУкр[16]="М"; МасУкр[17]="Н";
МасУкр[18]="О"; МасУкр[19]="П"; МасУкр[20]="Р"; МасУкр[21]="С"; МасУкр[22]="Т"; МасУкр[23]="У";
МасУкр[24]="Ф"; МасУкр[25]="Х"; МасУкр[26]="Ц"; МасУкр[27]="Ч"; МасУкр[28]="Ш"; МасУкр[29]="Щ";
МасУкр[30]="Ь"; МасУкр[31]="Ю"; МасУкр[32]="Я";
МасУкр[33]="а"; МасУкр[34]="б"; МасУкр[35]="в"; МасУкр[36]="г"; МасУкр[37]="ґ"; МасУкр[38]="д";
МасУкр[39]="е"; МасУкр[40]="є"; МасУкр[41]="ж"; МасУкр[42]="з"; МасУкр[43]="и"; МасУкр[44]="і";
МасУкр[45]="ї"; МасУкр[46]="й"; МасУкр[47]="к"; МасУкр[48]="л"; МасУкр[49]="м"; МасУкр[50]="н";
МасУкр[51]="о"; МасУкр[52]="п"; МасУкр[53]="р"; МасУкр[54]="с"; МасУкр[55]="т"; МасУкр[56]="у";
МасУкр[57]="ф"; МасУкр[58]="х"; МасУкр[59]="ц"; МасУкр[60]="ч"; МасУкр[61]="ш"; МасУкр[62]="щ";
МасУкр[63]="ь"; МасУкр[31]="ю"; МасУкр[65]="я";
МасКод = Новый Массив(66) ;
МасКод[0]="0410"; МасКод[1]="0411"; МасКод[2]="0412"; МасКод[3]="0413"; МасКод[4]="0490"; МасКод[5]="0414";
МасКод[6]="0415"; МасКод[7]="0404"; МасКод[8]="0416"; МасКод[9]="0417"; МасКод[10]="0418"; МасКод[11]="0406";
МасКод[12]="0407"; МасКод[13]="0419"; МасКод[14]="041A"; МасКод[15]="041B"; МасКод[16]="041C"; МасКод[17]="041D";
МасКод[18]="041E"; МасКод[19]="041F"; МасКод[20]="0420"; МасКод[21]="0421"; МасКод[22]="0422"; МасКод[23]="0423";
МасКод[24]="0424"; МасКод[25]="0425"; МасКод[26]="0426"; МасКод[27]="0427"; МасКод[28]="0428"; МасКод[29]="0429";
МасКод[30]="042C"; МасКод[31]="042E"; МасКод[32]="042F";
МасКод[33]="0430"; МасКод[34]="0431"; МасКод[35]="0432"; МасКод[36]="0413"; МасКод[37]="0491"; МасКод[38]="0434";
МасКод[39]="0435"; МасКод[40]="0454"; МасКод[41]="0436"; МасКод[42]="0437"; МасКод[43]="0438"; МасКод[44]="0456";
МасКод[45]="0457"; МасКод[46]="0439"; МасКод[47]="043A"; МасКод[48]="043B"; МасКод[49]="043C"; МасКод[50]="043D";
МасКод[51]="043E"; МасКод[52]="043F"; МасКод[53]="0440"; МасКод[54]="0441"; МасКод[55]="0442"; МасКод[56]="0443";
МасКод[57]="0444"; МасКод[58]="0445"; МасКод[59]="0446"; МасКод[60]="0447"; МасКод[61]="0448"; МасКод[62]="0449";
МасКод[63]="044C"; МасКод[31]="044E"; МасКод[65]="044F";
тмпСтрока = "" ;
Для Счетчик = 1 По СтрДлина(Строка) Цикл
Если Лев(Строка, 1) = "\" Тогда
Если Лев(Строка, 2) = "\u" Тогда
тмпСтрока = Прав(Лев(Строка, 6),4) ;
Если МасКод.Найти(тмпСтрока) = Неопределено Тогда
СтрокаЗамены = Прав(тмпСтрока, 1) ;
тмпСтрока = СтрЗаменить(тмпСтрока,СтрокаЗамены,ТРег(СтрокаЗамены));
Если МасКод.Найти(тмпСтрока) = Неопределено Тогда
Сообщить("Код символа не найден: " + тмпСтрока) ;
Иначе
ГотововаяСтрока = ГотововаяСтрока + МасУкр[МасКод.Найти(тмпСтрока)] ;
КонецЕсли;
Иначе
ГотововаяСтрока = ГотововаяСтрока + МасУкр[МасКод.Найти(тмпСтрока)] ;
КонецЕсли;
Строка = Прав(Строка, (СтрДлина(Строка)-6)) ;
Иначе
Строка = Прав(Строка, (СтрДлина(Строка)-2)) ;
КонецЕсли;
Иначе
ГотововаяСтрока = ГотововаяСтрока + Лев(Строка, 1) ;
Строка = Прав(Строка, (СтрДлина(Строка)-1)) ;
КонецЕсли;
КонецЦикла;
Возврат ГотововаяСтрока ;
КонецФункции
Категория:
WEB-сервисы, WS-ссылки, XDTO-пакеты Битая ссылка, , Уникальный Идентификатор, GUID - Управляемые формы Категория:
1С Общие вопросы - Управляемые формы и Такс… Как очистить справочник удалив все не используемые элементы? Очень часто менеджеры дублируют информацию в справочниках и время от времени их приходится чистить.
Но как удалить только те элементы справочника, которые не используются в документах?
Следующий пример кода поможет это сделать(в примере обрабатывается 4 справочника: Сотрудники, ФизЛица, Договора и Контрагенты) Скачать: Обработка для УТ 10 :
Код 1C v 8.х сп=Новый СписокЗначений;
сп.Добавить("СотрудникиОрганизаций");
сп.Добавить("ФизическиеЛица");
сп.Добавить("ДоговорыКонтрагентов");
сп.Добавить("Контрагенты");
Для Каждого стр из сп Цикл
текСпр=стр.Значение;
Запрос = Новый Запрос;
Текст =
"ВЫБРАТЬ
| СотрудникиОрганизаций.Ссылка
|ИЗ
| Справочник.%текСпр% КАК СотрудникиОрганизаций
|ГДЕ
| НЕ СотрудникиОрганизаций.ПометкаУдаления И НЕ СотрудникиОрганизаций.ЭтоГруппа";
Запрос.Текст = СтрЗаменить(Текст,"%текСпр%",текСпр);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
итЗаписей = Строка(ВыборкаДетальныеЗаписи.Количество());
ном=0;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ном=ном+1; Состояние(текСпр+": "+Строка(ном)+" из "+итЗаписей);
СсылкаНаУдаляемыйЭлемент = ВыборкаДетальныеЗаписи.Ссылка;
// Найти ссылки на удаляемый элемент - СсылкаНаУдаляемыйЭлемент.
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(СсылкаНаУдаляемыйЭлемент);
НайденныеСсылки = НайтиПоСсылкам(МассивСсылок);
Если НайденныеСсылки.Количество() > 0 Тогда
Сообщить("Нельзя удалять элемент:"+Строка(СсылкаНаУдаляемыйЭлемент)+", на него имеются ссылки",СтатусСообщения.Внимание);
Иначе
Сообщить("Удаляем элемент:"+Строка(СсылкаНаУдаляемыйЭлемент),СтатусСообщения.Информация);
// Получаем объект
УдаляемыйЭлемент = СсылкаНаУдаляемыйЭлемент.ПолучитьОбъект();
// Установить пометку
//УдаляемыйЭлемент.УстановитьПометкуУдаления(Истина);
// Удалить сразу
УдаляемыйЭлемент.Удалить();
КонецЕсли;
КонецЦикла;
КонецЦикла;
Категория:
Справочники ДеревоЗначений в ТекстовыйДокумент Код 1C v 8.2 УП // Выводит данные ДереваЗначений в ТекстовыйДокумент, пригодный к рассмотрению в отладчике, окне сообщений и показу.
//
// Параметры:
// рВетка - дерево значений, подлежащее выводу. Может иметь почти любую глубину иерархии, количество и тип колонок. Если хватит
// объявленных позиционных строк-заполнителей, всё поместится. Если иерархия слишком глубока, строки просто надо нарастить;
// рТекст - на входе должен быть равен Неопределено; на выходе по окончании работы содержит результатный текстовый документ;
// рПараметры - структура дополнительных настроек, допустимые ключи:
// Колонки - структура колонок, которые подлежат выводу. Если пуста или имеет тип, отличный от структуры, выводятся все колонки;
// если в ключах структуры указаны имена колонок, будут выведены только они. В значениях структуры можно передать строковое
// представление формата, согласно которому должны будут форматироваться выводимые значения. По умолчанию формата нет;
// ПоказыватьУровни - булево, управляет выводом №№ уровней (метод Уровень()), по умолчанию выключено;
// ШагОтступа - число, определяющее шаг в символах, используемый для показа псевдографики иерархии веток в дереве.
//
&НаСервереБезКонтекста
Процедура ВывестиДеревоЗначенийВТекст(Знач рВетка,рТекст,Знач рПараметры=Неопределено)
Попытка
Если рТекст=Неопределено Тогда // первая итерация, шапочный вызов исходной части
//---------------------------------------------------------------------------------------------------------------------------
// Разбираем входные данные
Если ТипЗнч(рВетка)<>Тип("ДеревоЗначений") Тогда Возврат КонецЕсли;
Если ТипЗнч(рПараметры)<>Тип("Структура") Тогда рПараметры=Новый Структура КонецЕсли;
стрКолонок=?(рПараметры.Свойство("Колонки"),рПараметры.Колонки,Неопределено);
Если ТипЗнч(стрКолонок)<>Тип("Структура") Тогда стрКолонок=Новый Структура КонецЕсли;
рПоказыватьУровни=?(рПараметры.Свойство("ПоказыватьУровни"),рПараметры.ПоказыватьУровни,Ложь); // затратное дело, кстати
рШагОтступа=?(рПараметры.Свойство("ШагОтступа"),рПараметры.ШагОтступа,2); // для отображения отступа в колонке иерархии
//---------------------------------------------------------------------------------------------------------------------------
// Определяем максимальное количество уровней
// Также можно получить максимальный уровень, "плоско" перебрав все строки (например, получив их через НайтиСтроки)
// и в цикле для каждой вызывая Уровень() и определяя максимум.
// Вариант через СКД и служебное поле "Уровень" ни на одной известной мне платформе не работоспособен (нехватка памяти).
//
//
//рДеревоДляТеста=КакНибудьСкопироватьДерево(рВетка);
//рДеревоДляТеста.Колонки.Вставить(0,"_Level",Новый ОписаниеТипов("Булево")); // самый экономный вариант, с сохранением иерархии
//мНенужных=Новый Массив;
//Для й=1 По рДеревоДляТеста.Колонки.Количество()-1 Цикл
// мНенужных.Добавить(рДеревоДляТеста.Колонки[й]);
//КонецЦикла;
//Для каждого кол Из мНенужных Цикл
// рДеревоДляТеста.Колонки.Удалить(кол);
//КонецЦикла;
//
рДеревоДляТеста=рВетка; // пока сериализуем прямо всё дерево (неоптимально, но...)
рЗапись=Новый ЗаписьXML;
рЗапись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(рЗапись,рДеревоДляТеста);
стро=рЗапись.Закрыть();
//
стро=СтрЗаменить(стро,"xmlns=","xmlns:myns1C="); // иначе не будет работать XPath
//
рЧтение=Новый ЧтениеXML;
рЧтение.УстановитьСтроку(стро);
постр=Новый ПостроительDOM;
рДокументДОМ=постр.Прочитать(рЧтение);
рВыражение="/ValueTree/row"; максКолвоУровней=1;
рРазыменователь=Новый РазыменовательПространствИменDOM(рДокументДОМ);
Пока Истина Цикл
#Если Клиент Тогда
ОбработкаПрерыванияПользователя();
#КонецЕсли
рРезультат=рДокументДОМ.ВычислитьВыражениеXPath(рВыражение,рДокументДОМ,рРазыменователь,ТипРезультатаDOMXPath.Любой);
Если рРезультат.ПолучитьСледующий()=Неопределено Тогда Прервать КонецЕсли;
рВыражение=рВыражение+"/row";
максКолвоУровней=максКолвоУровней+1;
КонецЦикла;
максКолвоУровней=максКолвоУровней-1; // можно и так: СтрЧислоВхождений(рВыражение,"/row")-1;
//---------------------------------------------------------------------------------------------------------------------------
// готовим исходный макет вывода
строПробелы=" ";
строРазделители="===============================================================================================";
строОтступы="___________________________________________________________________________________________"; // тут нужны чуть для другого
//
секШапка1="|[_HCS"+Лев(строПробелы,максКолвоУровней*рШагОтступа)+"]|"; // Hierar chyColumnShow
секГорРазделитель1="|"+Лев(строОтступы,максКолвоУровней*рШагОтступа+6)+"|"; // здесь именно Отступы!
рШиринаКолонкиИерархии=СтрДлина(секШапка1)-2;
строПолейШапки="#Поле _HCS
| #Выравнивание Центр";
строПолейЗаписи="";
//
Если рПоказыватьУровни Тогда
секШапка1=секШапка1+"[_Level]|";
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,8)+"|";
строПолейШапки=строПолейШапки+"
|#Поле _Level
| #Выравнивание Центр";
строПолейЗаписи="#Поле _Level
| #Выравнивание Центр
| #Забивать Истина";
КонецЕсли;
//
мИменКолонок=Новый Массив;
Для каждого кол Из рВетка.Колонки Цикл
Если стрКолонок.Количество()<>0 и не стрКолонок.Свойство(кол.Имя) Тогда Продолжить КонецЕсли; // чётко указаны конкретные колонки
рДлинаИмениКолонки=СтрДлина(кол.Имя);
рНужнаяШирина=Макс(?(кол.Ширина<3,10,кол.Ширина),рДлинаИмениКолонки);
// к сожалению, ключевое слово "#Поля" неприменимо - платформа падает - поэтому делаем всё сами
секШапка1=секШапка1+"["+кол.Имя+Лев(строПробелы,рНужнаяШирина-рДлинаИмениКолонки)+"]|";
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,рНужнаяШирина+1)+"=|";
строПолейШапки=строПолейШапки+"
|#Поле "+кол.Имя+"
| #Выравнивание Центр";
рОписТипов=кол.ТипЗначения;
Если рОписТипов.Типы().Количество()=1 и рОписТипов.СодержитТип(Тип("Булево")) Тогда
рВыравнивание="Центр";
ИначеЕсли рОписТипов.СодержитТип(Тип("Число")) Тогда
рВыравнивание="Право";
ИначеЕсли рОписТипов.СодержитТип(Тип("Строка")) и рОписТипов.КвалификаторыСтроки.Длина=0 Тогда
рВыравнивание="ПоШирине";
Иначе
рВыравнивание="Лево";
КонецЕсли;
строПолейЗаписи=строПолейЗаписи+?(ПустаяСтрока(строПолейЗаписи),"",Символы.ПС)+"#Поле "+кол.Имя+"
| #Выравнивание "+рВыравнивание;
Попытка
Если ЗначениеЗаполнено(стрКолонок[кол.Имя]) Тогда // указан формат, уточняющий показ колонки
строПолейЗаписи=строПолейЗаписи+"
| #Формат """+СокрЛП(стрКолонок[кол.Имя])+"""";
КонецЕсли;
Исключение
КонецПопытки;
мИменКолонок.Добавить(кол.Имя);
КонецЦикла;
секШапка2=СтрЗаменить(СтрЗаменить(секШапка1,"[","<"),"]",">");
секЗапись1=секШапка1; секЗапись2=секШапка2; // пусть они по дизайну пока не отличаются
секГорРазделитель2=СтрЗаменить(СтрЗаменить(секГорРазделитель1,"=","-"),"|","+");
// обработаем нормальное обрамление шапки колонки иерархии
секГорРазделитель1=СтрЗаменить(секГорРазделитель1,"_","=");
секГорРазделитель2=СтрЗаменить(секГорРазделитель2,"_"," ");
//
тМакет=Новый ТекстовыйДокумент;
тМакет.ДобавитьСтроку("#Область Шапка");
тМакет.ДобавитьСтроку(строПолейШапки);
тМакет.ДобавитьСтроку(секГорРазделитель1);
тМакет.ДобавитьСтроку(секШапка1);
тМакет.ДобавитьСтроку(секШапка2);
тМакет.ДобавитьСтроку(секГорРазделитель1);
тМакет.ДобавитьСтроку("#КонецОбласти");
тМакет.ДобавитьСтроку("");
тМакет.ДобавитьСтроку("#Область Запись");
тМакет.ДобавитьСтроку(строПолейЗаписи);
тМакет.ДобавитьСтроку(секЗапись1);
тМакет.ДобавитьСтроку(секЗапись2);
тМакет.ДобавитьСтроку(секГорРазделитель2);
тМакет.ДобавитьСтроку("#КонецОбласти");
рПараметры.Вставить("ИсходныйМакет",тМакет); // пусть будет
//---------------------------------------------------------------------------------------------------------------------------
// Запускаем вывод в итоговый документ
рТекст=Новый ТекстовыйДокумент;
сек=тМакет.ПолучитьОбласть("Шапка");
сек.Параметры._HCS="Иерархия";
Для каждого имякол Из мИменКолонок Цикл
кол=рВетка.Колонки[имякол];
сек.Параметры[кол.Имя]=?(ПустаяСтрока(кол.Заголовок),кол.Имя,кол.Заголовок);
КонецЦикла;
рТекст.Вывести(сек);
//
пар=Новый Структура;
пар.Вставить("МассивИмёнКолонок",мИменКолонок);
пар.Вставить("ТекущаяСекция",тМакет.ПолучитьОбласть("Запись"));
пар.Вставить("ШиринаКолонкиИерархии",рШиринаКолонкиИерархии);
пар.Вставить("ПоказыватьУровни",рПоказыватьУровни);
пар.Вставить("Отступ",0);
пар.Вставить("ШагОтступа",рШагОтступа);
ВывестиДеревоЗначенийВТекст(рВетка,рТекст,пар);
Иначе
// очередная итерация, вывод в текстовый документ
мИменКолонок=рПараметры.МассивИмёнКолонок;
рСекция=рПараметры.ТекущаяСекция;
рОтступ=рПараметры.Отступ;
рШиринаКолонкиИерархии=рПараметры.ШиринаКолонкиИерархии;
рПоказыватьУровни=рПараметры.ПоказыватьУровни;
//
строОтступы="_________________________________________________________________________________________________________";
строПробелы=" ";
//
пар=Новый Структура;
пар.Вставить("МассивИмёнКолонок",мИменКолонок);
пар.Вставить("ТекущаяСекция",рПараметры.ТекущаяСекция);
пар.Вставить("ШиринаКолонкиИерархии",рШиринаКолонкиИерархии);
пар.Вставить("ПоказыватьУровни",рПоказыватьУровни);
пар.Вставить("ШагОтступа",рПараметры.ШагОтступа);
пар.Вставить("Отступ",рОтступ+рПараметры.ШагОтступа);
//
Для каждого рПодветка Из рВетка.Строки Цикл
рСекция.Параметры._HCS=Лев(строПробелы,рОтступ)+"\"+Лев(строОтступы,рШиринаКолонкиИерархии-рОтступ-1);
Если рПоказыватьУровни Тогда
рСекция.Параметры._Level=рПодветка.Уровень();
КонецЕсли;
Для каждого имякол Из мИменКолонок Цикл
рСекция.Параметры[имякол]=рПодветка[имякол];
КонецЦикла;
рТекст.Вывести(рСекция);
ВывестиДеревоЗначенийВТекст(рПодветка,рТекст,пар)
КонецЦикла;
//
КонецЕсли;
Исключение
Сообщить("ВывестиДеревоЗначенийВТекст, ошибка: "+ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
КонецПопытки;
КонецПроцедуры
Источник
Категория:
Работа с Деревом Значений Google maps : вывод точек на карту и режим панорамы В отличие от яндекс карт в GMaps можно использовать панорамы - за что им большой плюс! Надеюсь в яндексе прочитают этот пост и тоже когда-нибудь это сделают!
Для клиента нужно было сделать вывод объектов на карту
С возможностью просмотра панорамы:
Основной HTML код карты хранится в макете:
Код VBS <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map { height: 100% }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.9&sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://www.sitedev.by/lab/markerclusterer/markerclusterer.js"></script>
<script type="text/javascript">
var latlng;
var markers = [];
var myMap;
var index = 1;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var infoWindow = new google.maps.InfoWindow;
var clusterer, mcOptions;
var trafficLayer = new google.maps.TrafficLayer();
var trafficOn = false;
var noclick = false;
var PointArray = [];
var polygons = [];
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
latlng = new google.maps.LatLng(55.75, 37.62);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDoubleClickZoom: true,
panControl: true,
zoomControl: true,
mapTypeControl: true,
scaleControl: true,
streetViewControl: true,
overviewMapControl: true
};
myMap = new google.maps.Map(document.getElementById("map"),
myOptions);
google.maps.event.addListener(myMap, 'dragend', function() {
noclick = true;
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
});
google.maps.event.addListener(myMap, 'click', function(event) {
infoWindow.close();
if (!noclick) {
addMarker(event.latLng);
}else{
noclick = false;
}
});
mcOptions = {gridSize: 3, maxZoom: 15};
clusterer = new MarkerClusterer(myMap, markers, mcOptions);
//отображение кнопки управления трафиком - все спер с примера, только подцепил свою функцию
var trafficControlDiv = document.createElement('div');
trafficControlDiv.style.padding = '5px';
// Set CSS for the control border
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '2px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'center';
controlUI.title = 'нажмите для вкл/выкл трафика';
trafficControlDiv.appendChild(controlUI);
// Set CSS for the control interior
var controlText = document.createElement('div');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = '<b>Трафик</b>';
controlUI.appendChild(controlText);
google.maps.event.addDomListener(controlUI, 'click', function (){
if (!trafficOn){
trafficOn = true;
trafficLayer.setMap(myMap);
}else{
trafficOn = false;
trafficLayer.setMap(null);
}
});
trafficControlDiv.index = 1;
myMap.controls[google.maps.ControlPosition.TOP_RIGHT].push(trafficControlDiv);
};
//добавляем маркер и отправляем в массив
function addMarker(location) {
marker = new google.maps.Marker({
position: location,
map: myMap,
title: 'Точка'+index
});
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
google.maps.event.addListener(marker, 'click', function(){
var mark = this;
var latLng = mark.getPosition();
infoWindow.setContent(mark.title);
infoWindow.open(myMap, mark);});
markers.push(marker);
index++;
document.getElementById('CoordX').value = location.lat();
document.getElementById('CoordY').value = location.lng();
}
function calcRoute(options) {
//вытягиваем из массива переданных параметров значения
//и преобразуем их в формат LatLng
var option1 = options[0];//начальная точка
var option2 = options[1];//промежуточные точки
var option3 = options[2];//конечная точка
var start = new google.maps.LatLng(option1[0], option1[1]); //первый
var end = new google.maps.LatLng(option3[0], option3[1]); //последний
//получаем транзитные точки
var waypts = [];
if(option2.length > 0) {
for(var i = 0, l = option2.length; i < l; i++) {
temp = option2[i];
Qcoord = new google.maps.LatLng(temp[0], temp[1])
waypts.push({
location:Qcoord,
stopover:true
});
}
}
//return;
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setMap(myMap);
directionsDisplay.setDirections(response);
var total = 0;
var myroute = response.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById('RouteInfo').value = "Длина маршрута - " + total + "км.";
//генерация события для перехвата в 1С
var evt = document.createEventObject();
document.body.fireEvent('ondatasetcomplete', evt);
}else{
alert(status);
}
});
}
function Reset(){
directionsDisplay.setMap(null);
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
index = 1;
//обнуляем кластер маркеров
clusterer.clearMarkers();
for (var i = 0; i < polygons.length; i++) {
polygons[i].setMap(null);
}
polygons = [];
PointArray = [];
}
function FindAdres(Adres){
Reset();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': Adres}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latlng = results[0].geometry.location;
myMap.panTo(latlng);
marker = new google.maps.Marker({
map: myMap,
position: latlng,
animation: google.maps.Animation.BOUNCE,
title:Adres
});
markers.push(marker);
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
} else {
alert("Ничего не найдено: " + status);
}
});
}
function ReverseSearchAdres(CoordX, CoordY, Adres){
Reset();
latlng = new google.maps.LatLng(CoordX, CoordY);
myMap.panTo(latlng);
var marker = new google.maps.Marker({
map: myMap,
position: latlng,
animation: google.maps.Animation.BOUNCE,
title:Adres
});
markers.push(marker);
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
}
function addToPointArray(CoordX, CoordY, ID, IconT, Text){
var latLng = new google.maps.LatLng(CoordX, CoordY);
var point = new google.maps.Marker({'position': latLng, title: Text, icon: IconT});
PointArray.push(point);
}
function drawCluster(){
clusterer.addMarkers(PointArray);
//myMap.geoObjects.add(clusterer);
}
function createPolygon(ArrayPoint, Name, color) {
//создаем массив координат вершин многоугольника
var paths = [];
for(var i = 0, l = ArrayPoint.length; i < l; i++) {
var temp = ArrayPoint[i];
Qcoord = new google.maps.LatLng(temp[0], temp[1])
paths.push(Qcoord);
};
// Создаем многоугольник
myPolygon = new google.maps.Polygon({
paths: paths,
strokeColor: color,
strokeOpacity: 0.6,
strokeWeight: 5,
fillColor: "#0000FF"
});
myPolygon.setMap(myMap);
polygons.push(myPolygon);
}
function WebClientClick() {
//очистка перед кликом координат, иначе после клика в упр. формах идет считывание координат
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
var WebClientOperation = document.getElementById("WebClientOperation").value;
//alert(WebClientOperation);
switch (WebClientOperation) {
case "0": // ничего не делаем
var a = 1;
default: // запускаем функцию
eval(WebClientOperation);
}
document.getElementById('WebClientOperation').value = "0";
}
</script>
</head>
<body onload="initialize()">
<div id="map" style="width:100%; height:100%"></div>
<input type="hidden" id="CoordX" name="CoordX" value="0"></input>
<input type="hidden" id="CoordY" name="CoordY" value="0"></input>
<input type="hidden" id="RouteInfo" name="RouteInfo" value=""></input>
<input type="hidden" id="WebClientOperation" name="WebClientOperation" value="0"></input>
<input type="hidden" id="WebClient" name="WebClient" onclick="WebClientClick();"></input>
</body>
</html>
Код вывода карты:
Код 1C v 8.х Процедура ИнициализироватьКарту()
ПутьКФайлу = КаталогВременныхФайлов()+"Карта.html";
Ф = новый Файл(ПутьКФайлу);
Если Ф.Существует() Тогда
УдалитьФайлы(ПутьКФайлу);
КонецЕсли;
Т = новый ТекстовыйДокумент;
ТД = ЭтотОбъект.ПолучитьМакет("МакетГугл");
Т.УстановитьТекст(ТД.ПолучитьТекст());
Т.Записать(ПутьКФайлу);
ЭлементыФормы.Эксплорер.Перейти(ПутьКФайлу);
КонецПроцедуры
Процедура ОчиститьКарту()
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("Reset()");
КонецПроцедуры
//к сожалению, другого спососба получить "внутрь 1С" информацию о действии пользователя на карте я не сумел
//действие пользователя на карте изменяет поле HTML-документа, но не вызывает никакого события в 1с-ке
// поэтому через обработчикОжидания делаю непрерывный опрос карты
Процедура ПриОткрытии()
ИнициализироватьКарту();
КонецПроцедуры
// вывод точек на карту
Процедура ОсновныеДействияФормыОсновныеДействияФормыВыполнить(Кнопка)
ОчиститьКарту();
СписокВидов = Новый СписокЗначений;
Для Каждого стр из ВыборВывода Цикл
если стр.пометка тогда СписокВидов.Добавить(стр.наименование); КонецЕсли;
КонецЦикла;
табАдресов.Очистить();
табАдресов = получитьтабАдресов(СписокВидов);
табУникальныхАдресов = табАдресов.скопировать();
табУникальныхАдресов.свернуть("Уник");
тзДанных = табАдресов.скопировать();
табАдресов.очистить();
Для Каждого стр из табУникальныхАдресов Цикл
Отбор = Новый Структура();
Отбор.Вставить("Уник",стр.Уник);
Строки = тзДанных.НайтиСтроки(Отбор);
НовСтр = табАдресов.добавить();
НовСтр.уник = стр.уник;
Если Строки.Количество() > 0 Тогда
для Каждого тздстр из Строки Цикл
НовСтр.Адрес = тздстр.Адрес;
НовСтр.КД = тздстр.КД;
НовСтр.КШ = тздстр.КШ;
НовСтр.ВидОбъекта = тздстр.ВидОбъекта;
НовСтр.Наименование=Строка(НовСтр.Наименование)+Строка(тздстр.Наименование)+"; ";
КонецЦикла;
КонецЕсли;
КонецЦикла;
ЭлементыФормы.табАдресов.СоздатьКолонки();
ВыборМасштаба = "50%";
ВыборРегиона = "Москва";
ЭлементыФормы.Надпись24.Заголовок = "Точек: "+Строка(табАдресов.количество());
Кол = табАдресов.Количество();
Индекс = 0;
Для Каждого ТекСтрока Из табАдресов Цикл Индекс = Индекс + 1; Если НЕ ЗначениеЗаполнено(ТекСтрока.КД) тогда Продолжить; КонецЕсли;
Широта = формат(ТекСтрока.КШ, "ЧРД=.");
Долгота = формат(ТекСтрока.КД, "ЧРД=.");
СодержимоеТочки = СокрЛП(ТекСтрока.ВидОбъекта)+": "+ СокрЛП(ТекСтрока.адрес); //опять же можно вставить свое название
Попытка
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("addToPointArray(" + Широта + "," + Долгота + ", '" + Строка(Индекс) + "', '" + СокрЛП(ТекСтрока.ВидОбъекта.ПутьКИконке)+ "', """ + СодержимоеТочки + """);");
Исключение
Сообщить("addToPointArray(" + Широта + "," + Долгота + ", '" + Строка(Индекс) + "', '" + СокрЛП(ТекСтрока.ВидОбъекта.ПутьКИконке)+ "', """ + СодержимоеТочки + """);",СтатусСообщения.Внимание);
КонецПопытки;
Состояние("Вывожу на карту " + Индекс + " из " + кол);
КонецЦикла;
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("drawCluster();");
КонецПроцедуры
Вырванная из конфигурации обработка GMaps.rar
Можно ее использовать как макет для создания обработки под свои требования.
Пример автоматизации в котором это использовалось.
Категория:
Географическая схема Яндекс карта : вывод точек на карту Пример о том,как вывести яндекс карту на форму и далее работать с ней:
Основной HTML код карты хранится в макете:
Код VBS <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Примеры. Геокодирование.</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://api-maps.yandex.ru/1.1/index.xml?key=ANpUFEkFAAAAf7jmJwMAHGZHrcLKDsbEqEVjEUtCmufxQMwAAAAAAAAAAAAvVrubVT4btztbduoIgTLAeFILaQ==" type="text/javascript"></script>
<script type="text/javascript">
var router;
var myPoints = new Array();
var myRouts = new Array();
var strOpen = "OPEN";
var strKontr = "Kontragent";
var t = new YMaps.Template('<b>$[name]</b><div id="descrID" >$[description]</div>');
YMaps.Templates.add("my#template", t);
var KopdinatShirota = 0;
var KopdinatDolgota = 0;
var UID_Zakaza = "";
/*vstavkaStiley;
var map, geoResult;
YMaps.jQuery(function () {
map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
map.setCenter(new YMaps.GeoPoint(37.62, 55.75), 12);
});
function showAddress (value, contrag, Styles, UID) {
var geocoder = new YMaps.Geocoder(value, {results: 1, boundedBy: map.getBounds()});
YMaps.Events.observe(geocoder, geocoder.Events.Load, function () {
if (this.length()) {
geoResult = this.get(0);
var point = new YMaps.GeoPoint(geoResult._point.__lng, geoResult._point.__lat);
var placemark = new YMaps.Placemark(point, {style: Styles});
placemark.name = UID;
placemark.description = contrag;
myPoints.push(placemark);
map.addOverlay(placemark);
return placemark;
}else {
}
});
YMaps.Events.observe(geocoder, geocoder.Events.Fault, function (geocoder, error) {
alert("Произошла ошибка: " + error);
return null;
})
}
function showAddressCoord (shirota, dolgota, contrag, Styles, UID) {
var point = new YMaps.GeoPoint(dolgota, shirota);
var placemark = new YMaps.Placemark(point, {style: Styles});
placemark.name = UID;
placemark.description = contrag;
myPoints.push(placemark);
map.addOverlay(placemark);
return placemark;
}
function removeAllOverlays (map) {
map.removeAllOverlays();
}
function AddRoute(wayPoint1, wayPoint2) {
if (myRouts.length>0) {lastRouter = myRouts[myRouts.length-1]; map.removeOverlay(lastRouter)};
var myRouter = new YMaps.Router([wayPoint1, wayPoint2], [], {viewAutoApply: true});
map.addOverlay(myRouter);
YMaps.Events.observe(myRouter, myRouter.Events.Success, function (myRouter) {
myRouter.getWayPoint(0).setIconContent('Начало маршрута');
myRouter.getWayPoint(1).setIconContent('Конец маршрута');
dlMar = myRouter.getDistance()/1000;
document.title = 'Дистанция: '+ dlMar.toFixed(2);
});
myRouts.push(myRouter);
return true;
}
function mapRazmer(map, SentrSh, SentrDlg, razmer) {
map.setCenter(new YMaps.GeoPoint(SentrSh, SentrDlg), razmer);
}
function changeStyle(numTochki, imStyle){
var restoreDefault = true;
tochka = myPoints[numTochki];
tochka.setOptions({style: imStyle}, restoreDefault);
point = tochka.getCoordPoint();
map.setCenter(new YMaps.GeoPoint(point.__lng, point.__lat), 12);
map.redraw();
return tochka.description;
}
</script>
</head>
<body //~~onload~~>
<div id="YMapsID" style="width:100%;height:100%"></div>
</form>
</body>
</html>
Код вывода карты:
Код 1C v 8.х //берем HTML-текст из макета и доделываем его
//создаем столько стилей, сколько есть различных картинок в папке "icons_"
//Загружаем в поле HTML-документа
//и позиционируем центр карты на Москву
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
Макет = ПолучитьМакет("Макет");
КодХТМЛ = Макет.ПолучитьТекст();
СтрокаСтиляНачальная = "var BurG = new YMaps.Style();
|BurG.iconStyle = new YMaps.IconStyle();
|BurG.iconStyle.offset = new YMaps.Point(-12, -12);
|BurG.iconStyle.href = ""http://www.burgerking.ru/favicon.ico"";
|BurG.iconStyle.size = new YMaps.Point(20, 20);
|BurG.hideIcon = false;
|BurG.balloonContentStyle = new YMaps.BalloonContentStyle(""my#template"");";
СтрокаСтиляИтоговая = "";
//
//имяКаталогаКартинок = "D:\!1C\MAPS\icons_";
//КаталогКартинок = Новый Файл(имяКаталогаКартинок);
//Если КаталогКартинок.ЭтоКаталог() тогда
// списокИменКартинок = новый таблицаЗначений;
// списокИменКартинок.Колонки.Добавить("ИмяСтиля");
// списокИменКартинок.Колонки.Добавить("ИмяФайлаКартинки");
// МассивНайденных = НайтиФайлы(имяКаталогаКартинок, "*.gif");
// Для Каждого Файл из МассивНайденных Цикл
//
// времСтрокаСтиля = СтрокаСтиляНачальная;
// времСтрокаСтиля = стрЗаменить(времСтрокаСтиля, "BurG", сокрЛП(Файл.ИмяБезРасширения));
// времСтрокаСтиля = стрЗаменить(времСтрокаСтиля, "C:/icons_/kv2_5_x.gif", "C:/icons_/" + сокрЛП(Файл.Имя));
//
// СтрокаСтиляИтоговая = СтрокаСтиляИтоговая + времСтрокаСтиля + символы.ПС;
//
// КонецЦикла;
//конецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВидыОбъектов.Ссылка,
| ВидыОбъектов.ПутьКИконке,
| ВидыОбъектов.Код
|ИЗ
| Справочник.ВидыОбъектов КАК ВидыОбъектов
|ГДЕ
| ВидыОбъектов.ПометкаУдаления = ЛОЖЬ";
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
времСтрокаСтиля = СтрокаСтиляНачальная;
времСтрокаСтиля = стрЗаменить(времСтрокаСтиля, "BurG", "s"+Строка(ВыборкаДетальныеЗаписи.код));
времСтрокаСтиля = стрЗаменить(времСтрокаСтиля, "http://www.burgerking.ru/favicon.ico", сокрЛП(ВыборкаДетальныеЗаписи.ПутьКИконке));
СтрокаСтиляИтоговая = СтрокаСтиляИтоговая + времСтрокаСтиля + символы.ПС;
КонецЦикла;
СтрокаСтиляИтоговая = СтрокаСтиляИтоговая + СтрокаСтиляНачальная + символы.ПС;
КодХТМЛ = стрЗаменить(КодХТМЛ, "/*vstavkaStiley;", СтрокаСтиляИтоговая);
путьККаталогуКартинок = СтрЗаменить(КаталогПрограммы(), "\", "/");
КодХТМЛ = СтрЗаменить(КодХТМЛ,"C:/",путьККаталогуКартинок);
ЭлементыФормы.Карта.УстановитьТекст(КодХТМЛ);
табАдресов = получитьтабАдресов();
табУникальныхАдресов = табАдресов.скопировать();
табУникальныхАдресов.свернуть("Уник");
тзДанных = табАдресов.скопировать();
табАдресов.очистить();
Для Каждого стр из табУникальныхАдресов Цикл
Отбор = Новый Структура();
Отбор.Вставить("Уник",стр.Уник);
Строки = тзДанных.НайтиСтроки(Отбор);
НовСтр = табАдресов.добавить();
НовСтр.уник = стр.уник;
Если Строки.Количество() > 0 Тогда
для Каждого тздстр из Строки Цикл
НовСтр.Адрес = тздстр.Адрес;
НовСтр.КД = тздстр.КД;
НовСтр.КШ = тздстр.КШ;
НовСтр.ВидОбъекта = тздстр.ВидОбъекта;
НовСтр.Наименование=Строка(НовСтр.Наименование)+Строка(тздстр.Наименование)+"; ";
КонецЦикла;
КонецЕсли;
КонецЦикла;
ЭлементыФормы.табАдресов.СоздатьКолонки();
ВыборМасштаба = "50%";
ВыборРегиона = "Москва";
ЭлементыФормы.Надпись24.Заголовок = "Точек: "+Строка(табАдресов.количество());
КонецПроцедуры
// Вывод точек на карту
Процедура ОсновныеДействияФормыОсновныеДействияФормыВыполнить(Кнопка)
//имя стиля совпадает с именем картинки без расширения
Всего=Строка(табАдресов.Количество()); н=0;
Для каждого строкаАдреса Из табАдресов Цикл
н=н+1; Состояние("Вывод "+Строка(н)+" из "+Всего);
////ЭТО ПРИМЕР ВЫВОДА ТОГО ИЛИ ИНОГО МАРКЕРА В ЗАВИСИМОСТИ ОТ НЕКОЕГО ПАРАМЕТРА
//Если строкаАдреса.ДокументПродажи.суммаДокумента <1000 тогда
// имяСтиля = "BurG";
//ИначеЕсли строкаАдреса.ДокументПродажи.суммаДокумента <10000 тогда
// имяСтиля = "tr2_3_x";
//ИначеЕсли строкаАдреса.ДокументПродажи.суммаДокумента <20000 тогда
// имяСтиля = "kv3_4_x";
//ИначеЕсли строкаАдреса.ДокументПродажи.суммаДокумента <50000 тогда
// имяСтиля = "tr4_1_x";
//ИначеЕсли строкаАдреса.ДокументПродажи.суммаДокумента <100000 тогда
// имяСтиля = "kv5_2_x";
//Иначе
// имяСтиля = "cr6_3_x";
//конецЕсли;
УИД_Дока = Строка(н);
имяСтиля = "s"+Строка(строкаАдреса.ВидОбъекта.код);
Попытка
Если ЗначениеЗаполнено(строкаАдреса.КД) Тогда
ВызовФункции = "showAddressCoord(" + сокрЛП(строкаАдреса.КШ) + ", " + сокрЛП(строкаАдреса.КД) + ", '"+ сокрЛП(строкаАдреса.адрес) + "', " + имяСтиля + ", '" + сокрЛП(строкаАдреса.ВидОбъекта.наименование) + "')";
Иначе
ВызовФункции = "showAddress('" + сокрЛП(строкаАдреса.адрес) + "', '" + сокрЛП(строкаАдреса.адрес) + "', " + имяСтиля + ", '" + сокрЛП(строкаАдреса.ВидОбъекта.наименование) + "')";
КонецЕсли;
ЭлементыФормы.Карта.Document.parentWindow.eval(ВызовФункции);
исключение
Сообщить("Точка с адресом " + сокрЛП(строкаАдреса.адрес) + " не может быть отбражена на карте!" );
конецПопытки
КонецЦикла;
ТочкиНеСозданы = Ложь;
ЭлементыФормы.Карта.ПолучитьТекст();
КонецПроцедуры
//Изменение масштаба
Процедура Кнопка1Нажатие(Элемент)
если ЭлементыФормы.ВыборРегиона.значение = "Москва" Тогда
СтрокаКоординат = "37.64, 55.76, ";
ИначеЕсли ЭлементыФормы.ВыборРегиона.значение = "Тверь" Тогда
СтрокаКоординат = "35.90, 56.83, ";
ИначеЕсли ЭлементыФормы.ВыборРегиона.значение = "Балашиха" Тогда
СтрокаКоординат = "37.97, 55.82, ";
Иначе
СтрокаКоординат = "37.64, 55.76, ";
конецесли;
Если ВыборМасштаба = "" тогда
возврат;
конецесли;
числоМасштаба = Число(Лев(ВыборМасштаба, стрдлина(ВыборМасштаба)-1));
числоМасштаба = числоМасштаба + 5;
ВыборМасштаба = строка(числоМасштаба) + "%";
ТекущийМасштаб = Строка(Цел((числоМасштаба/125)*(20)+4));
если стрДлина(ТекущийМасштаб) =1 тогда
ТекущийМасштаб = "0" + ТекущийМасштаб;
конецесли;
ЭлементыФормы.Карта.Document.parentWindow.eval("mapRazmer(map," + СтрокаКоординат + ТекущийМасштаб + ")");
КонецПроцедуры
Пример обратного геокодирования - получение координат по адресу:
Код 1C v 8.х Процедура ПолучитьКоординаты() Экспорт
Яндекс = Новый HTTPСоединение("geocode-maps.yandex.ru",,,,,Истина);
ВременныйФайл = КаталогВременныхФайлов() + "Yandex_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Яндекс.Получить("/1.x/?geocode=" + Адрес + "&results=1", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по яндексу адрес: " + Адрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ВременныйФайл);
ПостроительDOM = Новый ПостроительDOM;
ДокументДОМ = ПостроительDOM.Прочитать(ЧтениеXML);
СписокText = ДокументДОМ.ПолучитьЭлементыПоИмени("text");
СписокPos = ДокументДОМ.ПолучитьЭлементыПоИмени("pos");
Если (СписокText.Количество() = 0) ИЛИ (СписокPos.Количество() = 0) Тогда
Возврат;
КонецЕсли;
Для ъ = 0 по СписокText.Количество()-1 Цикл
Координаты = СписокPos[Ъ].ТекстовоеСодержимое;
Разделитель = Найти(Координаты," ");
Широта = Число(Сред(Координаты, Разделитель + 1));
Долгота = Число(Лев(Координаты, Разделитель - 1));
Если Широта = 0 ИЛИ Долгота = 0 Тогда
Продолжить;
КонецЕсли;
КД = Долгота;
КШ = Широта;
КонецЦикла;
КонецПроцедуры
Обработка вырванная из конфигурации: YandexMap.rar
Можно ее использовать как макет для создания обработки под свои требования.
Пример автоматизации в котором это использовалось.
Категория:
Географическая схема Веб браузер в 1С используя поле HTML документа Настраивал клиенту CRM, он захотел - чтобы панель управления сайтом была в 1С. Хочет - делаем:
Обработка Веб браузер проста, состоит из поля HTML документа и 20 строчек кода:
Код команд:
Код 1C v 8.3 &НаКлиенте
Процедура Команда1(Команда)
Объект.HTML = Адрес;
КонецПроцедуры
&НаКлиенте
Процедура Назад(Команда)
Элементы.HTML.Назад();
КонецПроцедуры
&НаКлиенте
Процедура АдресОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
Объект.HTML = Текст; Адрес = Текст;
КонецПроцедуры
&НаКлиенте
Процедура HTMLДокументСформирован(Элемент)
Адрес = Элемент.Документ.url;
КонецПроцедуры
Скачать обработку для 1С 8.3.7 : WebBrauzer.rar
Поле HTML документа - Это Internet Explorer в режиме совместимости IE7, и к сожалению, большинство сайтов уже ориентированы на современные браузеры и при открытии возникает ошибка:
Но у сайтов, владельцы которых позаботились о совместимости, все открывается без ошибок, например: этот https://helpf.pro или http://www.rbc.ru
Категория:
Работа с Интернет, Почтой (Mail), FTP Как программно создать нового пользователя или скопировать настройки существующего? Часто встречаю вопросы касаемые программного создания и настройки прав пользователей.
В этот статье я приведу примеры для Обычного и Управляемого приложений, которые программно создают пользователя в конфигураторе и в режиме Предприятие (справочник пользователи) и установку Групп пользователей.
В приложении к статье обработки, код которых приведен ниже: Скачать обработки
Обработки были написаны под УТ, но, при необходимости, вы можете их легко доработать под другие конфигурации.
Управляемое приложение: В конфигурациях на управляемом интерфейсе (Такси) изменили подход к ведению пользователей. Если вы добавляете не программно, то добавлять нужно из режима Предприятия - тогда пользователь ИБ у вас сам создатся. И если раньше, в обычном приложении, достаточно будет добавить польз в конфигураторе - и при заходе в Предприятие, этот польз сам создавался в спр Пользователи, то с управляемым приложением такой фокус не прокатит - система не даст зайти под пользователем ИБ, которого нет в справочнике Пользователи.
! В типовых конфигурациях для работы с пользователями активно используется БСП !
В общем модуле Пользователи используется программный интерфейс процедур и функций НовоеОписаниеПользователяИБ , ПрочитатьПользователяИБ , ЗаписатьПользователяИБ иУдалитьПользователяИБ .
Код создания нового пользователя с использованием БСП:
Код 1C v 8.3 &НаСервере
Функция КопированиеВсехНастроек(ПользовательСсылка,ПользовательПриемник)
Пользователь = Обработки.НастройкиПользователей.ИмяПользователяИБ(ПользовательСсылка);
Приемники = Новый Массив;
ТаблицаПользователей = Новый ТаблицаЗначений;
ТаблицаПользователей.Колонки.Добавить("Пользователь");
ТаблицаПользователей = Обработки.НастройкиПользователей.ПользователиДляКопирования(ПользовательСсылка, ТаблицаПользователей,
ТипЗнч(ПользовательСсылка) = Тип("СправочникСсылка.ВнешниеПользователи"));
Для Каждого СтрокаТаблицы Из ТаблицаПользователей Цикл
Приемники.Добавить(ПользовательПриемник);
КонецЦикла;
КопируемыеНастройки = Новый Массив;
КопируемыеНастройки.Добавить("НастройкиОтчетов");
КопируемыеНастройки.Добавить("НастройкиВнешнегоВида");
КопируемыеНастройки.Добавить("ПерсональныеНастройки");
КопируемыеНастройки.Добавить("Избранное");
КопируемыеНастройки.Добавить("НастройкиПечати");
КопируемыеНастройки.Добавить("ПрочиеПользовательскиеНастройки");
НастройкиСкопированы = Обработки.НастройкиПользователей.
КопированиеНастроекПользователей(ПользовательСсылка, Приемники, КопируемыеНастройки);
Возврат НастройкиСкопированы;
КонецФункции
Функция СоздатьНовыйУровеньДоступа(ФИО)
Рез = Справочники.CRM_УровниДоступа.НайтиПоНаименованию(ФИО);
Если Рез = Неопределено ИЛИ Рез = Справочники.CRM_УровниДоступа.ПустаяСсылка() Тогда
НовыйОбъект = Справочники.CRM_УровниДоступа.СоздатьЭлемент();
НовыйОбъект.Наименование = ФИО;
НовыйОбъект.Записать();
возврат НовыйОбъект.Ссылка;
КонецЕсли;
КонецФункции
Процедура ОбновитьДанныеПользователяИБ(ПользовательНастроек, Знач ОтображатьИмя = Истина)
Если ПользовательНастроек = Неопределено Тогда
Возврат;
КонецЕсли;
ПроверкаНаСуществующегоПользователя = ПользователиИнформационнойБазы.НайтиПоИмени(Объект.ФИОСоздаваемогоПользователя);
Если ПроверкаНаСуществующегоПользователя = Неопределено Тогда
Пользователь_Шаблон = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ПользовательНастроек.Наименование));
ОписаниеПользователяИБ = Пользователи.НовоеОписаниеПользователяИБ();
ПользовательИБСуществует = Ложь;
ДоступКИнформационнойБазеРазрешен = Ложь;
// Заполнение начальных значений свойств пользователяИБ.
Если ОбщегоНазначенияПовтИсп.РазделениеВключено() Тогда
ОписаниеПользователяИБ.ПоказыватьВСпискеВыбора = Ложь;
Иначе
ОписаниеПользователяИБ.ПоказыватьВСпискеВыбора =
НЕ Константы.ИспользоватьВнешнихПользователей.Получить();
КонецЕсли;
ОписаниеПользователяИБ.АутентификацияСтандартная = Истина;
ОписаниеПользователяИБ.Роли = Новый Массив;
ПрочитанныеСвойства = Неопределено;
Если Пользователи.ПрочитатьПользователяИБ(
ПользовательНастроек.ИдентификаторПользователяИБ,ПрочитанныеСвойства
) Тогда
// Установка связи пользователем ИБ.
//ДоступКИнформационнойБазеРазрешен = Истина;
// Копирование свойств и ролей пользователяИБ.
ЗаполнитьЗначенияСвойств(
ОписаниеПользователяИБ,
ПрочитанныеСвойства,
"АутентификацияOpenID,
|АутентификацияСтандартная,
|ЗапрещеноИзменятьПароль,
|ПоказыватьВСпискеВыбора,
|АутентификацияОС,
|РежимЗапуска,
|Язык,
|Роли");
КонецЕсли;
ОписаниеПользователяИБ.Вставить("Действие", "Записать");
ОписаниеПользователяИБ.Вставить("Имя", Объект.ФИОСоздаваемогоПользователя);
НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
НовыйПользователь.Наименование = Объект.ФИОСоздаваемогоПользователя;
НовыйПользователь.ТекущееПодразделение = ПользовательНастроек.ТекущееПодразделение;
НовыйПользователь.CRM_УровеньДоступа = СоздатьНовыйУровеньДоступа(Объект.ФИОСоздаваемогоПользователя);
НовыйПользователь.Недействителен = ложь;
НовыйПользователь.ДополнительныеСвойства.Вставить(
"ОписаниеПользователяИБ", ОписаниеПользователяИБ);
НовыйПользователь.Записать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ГруппыПользователейПользователиГруппы.Ссылка
|ИЗ
| Справочник.ГруппыПользователей.Состав КАК ГруппыПользователейПользователиГруппы
|ГДЕ
| ГруппыПользователейПользователиГруппы.Пользователь =Пользователь
|
|СГРУППИРОВАТЬ ПО
| ГруппыПользователейПользователиГруппы.Ссылка";
Запрос.УстановитьПараметр("Пользователь", ПользовательНастроек);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
объ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
НоваяСтрока = объ.Состав.Добавить();
НоваяСтрока.Пользователь = НовыйПользователь.Ссылка;
объ.Записать();
КонецЦикла;
Запрос.Текст =
"ВЫБРАТЬ
| ГруппыДоступаПользователи.Ссылка
|ИЗ
| Справочник.ГруппыДоступа.Пользователи КАК ГруппыДоступаПользователи
|ГДЕ
| ГруппыДоступаПользователи.Пользователь =Пользователь
|
|СГРУППИРОВАТЬ ПО
| ГруппыДоступаПользователи.Ссылка";
Запрос.УстановитьПараметр("Пользователь", ПользовательНастроек);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
объ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
НоваяСтрока = объ.Пользователи.Добавить();
НоваяСтрока.Пользователь = НовыйПользователь.Ссылка;
объ.Записать();
КонецЦикла;
КопированиеВсехНастроек(ПользовательНастроек,НовыйПользователь.Ссылка);
Иначе
сообщить("Указанное ФИО Пользователя уже используется !!! ");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьПользователя(Команда)
СоздатьПользователяНаСервере();
КонецПроцедуры
&НаСервере
Процедура СоздатьПользователяНаСервере()
Если НЕ ЗначениеЗаполнено(Объект.ШаблонПользователяДляСозданияНового) Тогда
Возврат;
КонецЕсли;
// настройки устанавливаются на форму
ОбновитьДанныеПользователяИБ(Объект.ШаблонПользователяДляСозданияНового, Ложь);
КонецПроцедуры
&НаСервере
Процедура СкопироватьНастройкиНаСервере(ИзменяемыйПользователь,ШаблонПользователяДляКопирования)
//Копируем роли пользователя
тИзменяемыйПользователь = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ИзменяемыйПользователь.Наименование));
тШаблонПользователяДляКопирования = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ШаблонПользователяДляКопирования.Наименование));
//Очищаем роли
тИзменяемыйПользователь.Роли.Очистить();
// Копируем
СписокДоступныхРолейПользователяИБ = Новый СписокЗначений;
Для Каждого мРоль Из Метаданные.Роли Цикл
СтрокаСписокаДоступныхРолей = СписокДоступныхРолейПользователяИБ.Добавить();
СтрокаСписокаДоступныхРолей.Представление = мРоль.Представление();
СтрокаСписокаДоступныхРолей.Значение = мРоль;
КонецЦикла;
Для Каждого СтрокаСпискаДоступныхРолей Из СписокДоступныхРолейПользователяИБ Цикл
Если тШаблонПользователяДляКопирования.Роли.Содержит(СтрокаСпискаДоступныхРолей.Значение) Тогда
тИзменяемыйПользователь.Роли.Добавить(СтрокаСпискаДоступныхРолей.Значение);
КонецЕсли;
КонецЦикла;
тИзменяемыйПользователь.Записать();
//Копируем настройки БСП
КопированиеВсехНастроек(ШаблонПользователяДляКопирования,ИзменяемыйПользователь);
КонецПроцедуры
&НаКлиенте
Процедура СкопироватьНастройки(Команда)
СкопироватьНастройкиНаСервере(Объект.ИзменяемыйПользователь, Объект.ШаблонПользователяДляКопирования);
КонецПроцедуры
Обычное приложение: В обычном все проще:
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
Если НЕ ЗначениеЗаполнено(ШаблонПользователяДляСозданияНового) Тогда
Возврат;
КонецЕсли;
// настройки устанавливаются на форму
ОбновитьДанныеПользователяИБ(ШаблонПользователяДляСозданияНового, Ложь);
КонецПроцедуры
Процедура ОбновитьДанныеПользователяИБ(ПользовательНастроек, Знач ОтображатьИмя = Истина)
Если ПользовательНастроек = Неопределено Тогда
Возврат;
КонецЕсли;
ПроверкаНаСуществующегоПользователя = ПользователиИнформационнойБазы.НайтиПоИмени(ФИОСоздаваемогоПользователя);
Если ПроверкаНаСуществующегоПользователя = Неопределено Тогда
Пользователь_Шаблон = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ПользовательНастроек.Код));
ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
ПользовательИБ.Имя = ФИОСоздаваемогоПользователя;
ПользовательИБ.АутентификацияСтандартная = Истина;
ПользовательИБ.Пароль = ПарольСоздаваемогоПользователя;
ПользовательИБ.ПолноеИмя = ФИОСоздаваемогоПользователя;
ПользовательИБ.ПоказыватьВСпискеВыбора = Истина;
ПользовательИБ.ОсновнойИнтерфейс = Пользователь_Шаблон.ОсновнойИнтерфейс;
ПользовательИБ.Язык = Пользователь_Шаблон.Язык;
СписокДоступныхРолейПользователяИБ = Новый СписокЗначений;
Для Каждого мРоль Из Метаданные.Роли Цикл
СтрокаСписокаДоступныхРолей = СписокДоступныхРолейПользователяИБ.Добавить();
СтрокаСписокаДоступныхРолей.Представление = мРоль.Представление();
СтрокаСписокаДоступныхРолей.Значение = мРоль;
КонецЦикла;
Для Каждого СтрокаСпискаДоступныхРолей Из СписокДоступныхРолейПользователяИБ Цикл
Если Пользователь_Шаблон.Роли.Содержит(СтрокаСпискаДоступныхРолей.Значение) Тогда
ПользовательИБ.Роли.Добавить(СтрокаСпискаДоступныхРолей.Значение);
КонецЕсли;
КонецЦикла;
ПользовательИБ.Записать();
НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
//НовыйПользователь.ИдентификаторПользователяИБ = ПользовательИБ.УникальныйИдентификатор;
НовыйПользователь.Код = ФИОСоздаваемогоПользователя;
НовыйПользователь.Наименование = ФИОСоздаваемогоПользователя;
НовыйПользователь.Родитель = ПользовательНастроек.Родитель;
НовыйПользователь.Подразделение = ПользовательНастроек.Подразделение;
НовыйПользователь.Категория = ПользовательНастроек.Категория;
НовыйПользователь.Руководитель = ПользовательНастроек.Руководитель;
НовыйПользователь.Действует = ПользовательНастроек.Действует;
НовыйПользователь.Записать();
НаборПользователя = РегистрыСведений.НастройкиПользователей.СоздатьНаборЗаписей();
НаборПользователя.Отбор.Пользователь.Установить(ПользовательНастроек);
НаборПользователя.Прочитать();
НаборНовогоПользователя = РегистрыСведений.НастройкиПользователей.СоздатьНаборЗаписей();
НаборНовогоПользователя.Отбор.Пользователь.Установить(НовыйПользователь.Ссылка);
Для Каждого СтрокаНастроек из НаборПользователя Цикл
НоваяСтрокаНастроек = НаборНовогоПользователя.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрокаНастроек,СтрокаНастроек);
НоваяСтрокаНастроек.Пользователь = НовыйПользователь.Ссылка;
Если Найти(СтрокаНастроек.Настройка.Наименование,"Основной ответственный") Тогда
НоваяСтрокаНастроек.Значение = НовыйПользователь.Ссылка;
КонецЕсли;
КонецЦикла;
Если НаборНовогоПользователя.Количество()>0 Тогда
НаборНовогоПользователя.Записать();
КонецЕсли;
сообщить("Создан пользователь "+ФИОСоздаваемогоПользователя);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ГруппыПользователейПользователиГруппы.Ссылка
|ИЗ
| Справочник.ГруппыПользователей.ПользователиГруппы КАК ГруппыПользователейПользователиГруппы
|ГДЕ
| ГруппыПользователейПользователиГруппы.Пользователь =Пользователь
|
|СГРУППИРОВАТЬ ПО
| ГруппыПользователейПользователиГруппы.Ссылка";
Запрос.УстановитьПараметр("Пользователь", ПользовательНастроек);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
объ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
НоваяСтрока = объ.ПользователиГруппы.Добавить();
НоваяСтрока.Пользователь = НовыйПользователь.Ссылка;
объ.Записать();
КонецЦикла;
Иначе
сообщить("Указанное ФИО Пользователя уже используется !!! ");
КонецЕсли;
КонецПроцедуры
еще пример:
Код 1C v 8.х Функция ДобавитьПользователя(ИмяПользователя, ДоменноеИмя, ПользовательАктивен, АутентификацияОС, Авторизация1СПредприятия, МассивРолей) Экспорт
// Попробуем найти сотрудника
Пользователь = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
// Теперь попробум найти сотрудника по пользователю ос
Если Пользователь = Неопределено Тогда
Для Каждого ТекущийПользователь Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
Если ТекущийПользователь.ПользовательОС = ДоменноеИмя Тогда
Пользователь = ТекущийПользователь;
Прервать;
Конецесли;
КонецЦикла;
КонецЕсли;
//
// Если мы не нашли сотрудника, то создадим его
Если Пользователь = Неопределено Тогда
Пользователь = ПользователиИнформационнойБазы.СоздатьПользователя();
КонецЕсли;
//
// Записываем свойства
Пользователь.АутентификацияОС = АутентификацияОС;
Пользователь.АутентификацияСтандартная = Авторизация1СПредприятия;
Пользователь.ЗапрещеноИзменятьПароль = Истина;
Пользователь.Имя = ИмяПользователя;
Пользователь.ПолноеИмя = ИмяПользователя;
Пользователь.ПоказыватьВСпискеВыбора = Ложь;
Пользователь.ПользовательОС = ДоменноеИмя;
// Сначала очистим все текущие роли
Пользователь.Роли.Очистить();
// Теперь найдем переданный массив ролей в справочнике профилей
// и добавим все роли указанные в профиле. Все очень сложно, да
МассивИменРолей = Новый Массив();
Для Каждого Роль Из МассивРолей.Role Цикл
МассивИменРолей.Добавить(Роль);
КонецЦикла;
ТекстЗапроса = "ВЫБРАТЬ
| ПрофилиГруппДоступаРоли.Роль.Имя КАК Имя
|ИЗ
| Справочник.ПрофилиГруппДоступа.Роли КАК ПрофилиГруппДоступаРоли
|ГДЕ
| ПрофилиГруппДоступаРоли.Ссылка.Наименование В(&МассивИменРолей)";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("МассивИменРолей", МассивИменРолей);
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Роль Из Результат Цикл
НайденнаяРоль = Метаданные.Роли.Найти(Роль.Имя);
Если НайденнаяРоль <> Неопределено Тогда
Пользователь.Роли.Добавить(НайденнаяРоль);
КонецЕсли;
КонецЦикла;
// Записываем!
Пользователь.Записать();
// Теперь посмотрим нужно ли деактивировать пользователя
Если Не ПользовательАктивен Тогда
ДективироватьПользователя(Пользователь);
КонецЕсли;
// Запишем еще и справочник пользователя
ЗаполнитьСправочникПользователя(Пользователь);
Возврат Истина;
КонецФункции
// Процедура заполняет помимо прочего справочник пользователя
Процедура ЗаполнитьСправочникПользователя(ПользовательИБ) Экспорт
ТекстЗапроса = "ВЫБРАТЬ
| ИСТИНА КАК ЕстьПользователь,
| Пользователи.Ссылка КАК Пользователь
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ =ИдентификаторПользователяИБ
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ЛОЖЬ,
| NULL";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("ИдентификаторПользователяИБ", ПользовательИБ.УникальныйИдентификатор);
Результат = Запрос.Выполнить().Выгрузить()[0];
ОписаниеПользователя = Пользователи.НовоеОписаниеПользователяИБ();
Если Результат.ЕстьПользователь Тогда
ПользовательОбъект = Результат.Пользователь.ПолучитьОбъект();
Иначе
ПользовательОбъект = Справочники.Пользователи.СоздатьЭлемент();
ПользовательОбъект.ИдентификаторПользователяИБ = ПользовательИБ.УникальныйИдентификатор;
ПользовательОбъект.Наименование = ПользовательИБ.Имя;
ОписаниеПользователя.Вставить("Действие", "Записать");
ПользовательОбъект.ДополнительныеСвойства.Вставить("ОписаниеПользователяИБ", ОписаниеПользователя);
КонецЕсли;
ЗаполнитьЗначенияСвойств(ОписаниеПользователя, ПользовательИБ);
Для Каждого Элемент Из ОписаниеПользователя Цикл
ПользовательОбъект.ДополнительныеСвойства.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;
ПользовательОбъект.ДополнительныеСвойства.Удалить("Роли");
ПользовательОбъект.Записать();
КонецПроцедуры
Категория:
Пользователь, роль доступа, интерфейс Динамический отчет на СКД с разными вариантами На днях делал несколько однотипных отчетов на СКД.
Общий принцип: формируются все варианты отчета, указанные в настройках схемы и каждый вариант выводится на отдельной вкладке.
Потом возникла мысль попробовать объединить все схемы в один отчет, чтобы не плодить лишних объектов в конфигурации. При этом количество вариантов в этих схемах заранее неизвестно. Ok, challenge accepted.
В тестовой конфигурации создаю для отчета две схемы компоновки, "Склад" и "Заявки".
Запросы наборов данных приводить не буду, для каждой схемы в настройках добавляю несколько вариантов отчетов.
Теперь переходим к созданию формы. Практически все реквизиты формы будут создаваться при выборе необходимого макета отчета.
Код 1C v 8.2 УП &НаСервере
Процедура СоздатьПереченьОтчетов()
Для Каждого Макет Из РеквизитФормыВЗначение("Отчет").Метаданные().Макеты Цикл
Элементы.МакетОтчета.СписокВыбора.Добавить(Макет.Имя, Макет.Синоним);
КонецЦикла;
КонецПроцедуры // СоздатьПереченьОтчетов()
&НаСервере
Процедура ОбработатьВыборМакета()
Макет = РеквизитФормыВЗначение("Отчет").ПолучитьМакет(МакетОтчета);
мУдалить = ?(ПустаяСтрока(РеквизитыКУдалению), Новый Массив, ПолучитьИзВременногоХранилища(РеквизитыКУдалению));
мДобавить = Новый Массив;
кУдалению = Новый Массив;
Для Каждого Вариант Из Макет.ВариантыНастроек Цикл
ИмяРеквизита = "ТабДок_" + Вариант.Имя;
тРеквизит = Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("ТабличныйДокумент"));
мДобавить.Добавить(тРеквизит);
кУдалению.Добавить(ИмяРеквизита);
КонецЦикла;
ИзменитьРеквизиты(мДобавить, мУдалить);
Пока Элементы.СтраницыОтчета.ПодчиненныеЭлементы.Количество() Цикл
Элементы.Удалить(Элементы.СтраницыОтчета.ПодчиненныеЭлементы[0]);
КонецЦикла;
Для Каждого Вариант Из Макет.ВариантыНастроек Цикл
Страница = Элементы.Добавить("Страница_" + Вариант.Имя, Тип("ГруппаФормы"), Элементы.СтраницыОтчета);
Страница.Вид = ВидГруппыФормы.Страница;
Страница.Заголовок = Вариант.Представление;
ИмяРеквизита = "ТабДок_" + Вариант.Имя;
ТабДок = Элементы.Добавить(ИмяРеквизита, Тип("ПолеФормы"), Страница);
ТабДок.Вид = ВидПоляФормы.ПолеТабличногоДокумента;
ТабДок.ПутьКДанным = ИмяРеквизита;
ТабДок.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ЭтаФорма[ИмяРеквизита].Очистить();
КонецЦикла;
РеквизитыКУдалению = ПоместитьВоВременноеХранилище(кУдалению, УникальныйИдентификатор);
КонецПроцедуры // ОбработатьВыборМакета()
&НаСервере
Процедура СформироватьОтчеты()
Схема = РеквизитФормыВЗначение("Отчет").ПолучитьМакет(МакетОтчета);
Для Каждого Вариант Из Схема.ВариантыНастроек Цикл
Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(Вариант.Настройки);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Отчет.КомпоновщикНастроек.ПолучитьНастройки());
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ЭтаФорма["ТабДок_" + Вариант.Имя]);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецЦикла;
КонецПроцедуры // СформироватьОтчеты()
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СоздатьПереченьОтчетов();
КонецПроцедуры
&НаКлиенте
Процедура МакетОтчетаПриИзменении(Элемент)
ОбработатьВыборМакета();
КонецПроцедуры
&НаКлиенте
Процедура Сформировать(Команда)
СформироватьОтчеты();
КонецПроцедуры
Смотрим, что получилось.
Выгрузка базы 1Cv8skd.rar
Источник
Категория:
Схема Компоновки Данных Регламентные и фоновые задания (создание, настройка, запуск) При работе в 1С встречается много рутинных операций которые должны запускаться или формироваться по расписанию выполняя то или иное действие, например: проведение документов или загрузка данных в 1С с сайта.
Недавно я разместил статью: Чтение данных с сайта в формате XML и загрузка в 1С пришло время это автоматизировать:
Регламентные и фоновые задания Механизм заданий предназначен для выполнения какой-либо прикладной или функциональности по расписанию или асинхронно.
Механизм заданий решает следующие задачи:
Возможность определения регламентных процедур на этапе конфигурирования системы; Выполнение заданных действий по расписанию; Выполнение вызова заданной процедуры или функции асинхронно, т.е. без ожидания ее завершения; Отслеживание хода выполнения определенного задания и получение его статуса завершения (значения, указывающего успешность или не успешность его выполнения); Получение списка текущих заданий; Возможность ожидания завершения одного или нескольких заданий; Управление заданиями (возможность отмены, блокировка выполнения и др.). Механизм заданий состоит из следующих компонентов:
Метаданных регламентных заданий; Регламентных заданий; Фоновых заданий; Планировщика заданий. Фоновые задания & предназначены для выполнения прикладных задач асинхронно. Фоновые задания реализуются средствами встроенного языка.
Регламентные задания & предназначены для выполнения прикладных задач по расписанию. Регламентные задания хранятся в информационной базе и создаются на основе метаданных, определяемых в конфигурации. Метаданные регламентного задания содержат такую информацию как наименование, метод, использование и т.д.
Регламентное задание имеет расписание, которое определяет, в какие моменты времени нужно выполнять связанный с регламентным заданием метод. Расписание, как правило, задается в информационной базе, но может быть задано и на этапе конфигурирования (например, для предопределенных регламентных заданий).
Планировщик заданий используется для планирования выполнения регламентных заданий. Для каждого регламентного задания планировщик периодически проверяет, соответствует ли текущая дата и время расписанию регламентного задания. Если соответствует, планировщик назначает такое задание на выполнение. Для этого по данному регламентному заданию планировщик создает фоновое задание, которое и выполняет реальную обработку.
С описанием, думаю, хватит - приступим к реализации:
Создание регламентного задания
Имя метода – путь к процедуре, которая будет выполняться в фоновом задании по заданному расписанию. Процедура должна находиться в общем модуле. Рекомендуется не использовать типовые общие модули, а создать свой. Не забудьте, что фоновые задания исполняются на сервере!
Использование – признак использования регламентного задания.
Предопределенное – указывает, является ли регламентное задание предопределенным.
Если хотите что бы регламентное задание заработало сразу после помещения в БД, укажите признак Предопределенное . В противном случае вам необходимо будет использовать обработку “Консоль заданий” или вызывать запуск задания программно. Количество повторов при аварийном завершении задания – сколько раз выполнен перезапуск фонового задания, если оно было выполнено с ошибкой.
Интервал повтора при аварийном завершении задания – с какой периодичностью будет выполнен перезапуск фонового задания, если оно было выполнено с ошибкой.
Настройка расписания Расписание выполнения задания:
Каждый час, только один день ПериодПовтораДней = 0, ПериодПовтораВТечениеДня = 3600 Каждый день один раз в день ПериодПовтораДней = 1, ПериодПовтораВТечениеДня = 0 Один день, один раз ПериодПовтораДней = 0 Через день один раз в день ПериодПовтораДней = 2 Каждый час с 01.00 до 07.00 каждый день ПериодПовтораДней = 1ПериодПовтораВТечениеДня = 3600ВремяНачала = 01.00ВремяКонца = 07.00
Каждую субботу и воскресенье в 09.00 ПериодПовтораДней = 1ДниНедели = 6, 7ВремяНачала = 09.00 Каждый день одну неделю, неделя пропуска ПериодПовтораДней = 1ПериодНедель = 2 В 01.00 один раз ВремяНачала = 01.00 Последнее число каждого месяца в 9:00. ПериодПовтораДней = 1ДеньВМесяце = -1ВремяНачала = 09.00 Пятое число каждого месяца в 9:00 ПериодПовтораДней = 1ДеньВМесяце = 5ВремяНачала = 09.00 Вторая среда каждого месяца в 9:00 ПериодПовтораДней = 1ДеньНеделиВМесяце = 2ДниНедели = 3ВремяНачала = 09.00
Особенности выполнения фоновых заданий файловом и клиент-серверном вариантах Механизмы выполнения фоновых заданий в файловом и клиент-серверном вариантах различаются.
В файловом варианте необходимо создать выделенный клиентский процесс, который будет заниматься выполнением фоновых заданий. Для этого в клиентском процессе должна периодически вызываться функция глобального контекста ВыполнитьОбработкуЗаданий. Только один клиентский процесс на информационную базу должен выполнять обработку фоновых заданий (и, соответственно, вызывать данную функцию). Если клиентского процесса для обработки фоновых заданий не создано, то при программном доступе к механизму заданий будет выдана ошибка «Менеджер заданий не активен». Не рекомендуется клиентский процесс, выполняющий обработку фоновых заданий, использовать для других функций.
После того, как клиентский процесс, выполняющий обработку фоновых заданий, запущен, остальные клиентские процессы получают возможность программного доступа к механизму фоновых заданий, т.е. могут запускать и управлять фоновыми заданиями.
В клиент-серверном варианте для выполнения фоновых заданий используется планировщик заданий, который физически находится в менеджере кластера. Планировщик для всех поставленных в очередь на выполнение фоновых заданий получает наименее загруженный рабочий процесс и использует его для выполнения соответствующего фонового задания. Рабочий процесс выполняет задание и уведомляет планировщик о результатах выполнения.
В клиент-серверном варианте имеется возможность блокирования выполнения регламентных заданий. Блокирование выполнения регламентных заданий происходит в следующих случаях:
На информационную базу установлена явная блокировка регламентных заданий. Блокировка может быть установлена через консоль кластера; На информационную базу установлена блокировка соединения. Блокировка может быть установлена через консоль кластера; Из встроенного языка вызван метод УстановитьМонопольныйРежим() с параметром Истина; В некоторых других случаях (например, при обновлении конфигурации базы данных).
Обработки запуска и просмотра регламентных заданий вы можете скачать здесь:
Для 8.2 Обычные формы: Konsol82.rar
Для 8.3 Управляемые формы: KonsolZadaniy83.rar
Категория:
Регламентные задания, Фоновые задания Как сформировать отчет СКД без проверки прав (в привилегированном режиме)? Что при разработке отчетов требуется чтобы у пользователя с ограниченными правами, отчет формировался полностью без проверки прав!
Особенно если настроен RLS
Есть несколько способов как это сделать: 1. Установить привилегированный режим в модуле отчета
Форма отчета должна быть Управляемой, далее в модуле отчета процедура обработчика «При компоновке результата»:
Код 1C v 8.3 //Перехватываем событие вывода компоновки данных в табличный документ и выводим со своим заголовком
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
УстановитьПривилегированныйРежим(Истина);
//Сформируем отчет
СформироватьОтчет(ДокументРезультат, ДанныеРасшифровки);
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
2. Формирование в п ривилегированном режиме через Общий модуль с галкой Привелигерованный
Создаем общий модуль
так же как в пункте 1 в обработчике «При компоновке результата» пишем:
Код 1C v 8.3 //Перехватываем событие вывода компоновки данных в табличный документ и выводим со своим заголовком
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
МЕ_ДляОтчетаСКД_ПривелРежим.СформироватьОтчетПривРеж(ДокументРезультат, СхемаКомпоновкиДанных, ДанныеРасшифровки, КомпоновщикНастроек);
КонецПроцедуры
В общем модуле МЕ_ДляОтчетаСКД_ПривелРежим код:
Код 1C v 8.3 Процедура СформироватьОтчетПривРеж(ТабличныйДокумент, СхемаКомпоновкиДанных, ДанныеРасшифровки, КомпоновщикНастроек) Экспорт
ТабличныйДокумент.Очистить();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки,,,Ложь);
ВнешниеНаборыДанных = Новый Структура;
/// можно передать внешние данные ВнешниеНаборыДанных.Вставить("тзПродаж", СформироватьТЗПродаж());
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных,ВнешниеНаборыДанных,ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
3. Если включен режим Использовать ограничение на уровне прав доступа - RLS
Часто используется в типовых. Тут в модуле для текущего пользователя можно на время формирования отчету установить параметр сеанса ИспользоватьОграниченияПравДоступаНаУровнеЗаписей в Ложь и RLS не сработает.
Код 1C v 8.3 ПараметрыСеанса.ИспользоватьОграниченияПравДоступаНаУровнеЗаписей=Ложь;
После завершения формирования, не забудьте включить rls обратно установив = Истина
4. Если в запросе используется конструкция вида регистратор.дата и это поле не отображается в полях отчета СКД
Допустим Вы сделали запрос по регистру накоплений и через регистратор обратились к дате или сумме документа и при формировании отчета СКД, эти поля недоступны !? как же быть?
Проблема в том - что у регистратором может выступать несколько документов и видимо права чтение/просмотр есть не на все - поэтому через скд эта таблица целиком недоступна, решение:
1. открыть доступ на все регистраторы регистра
2. в запросе четко обозначить тип
Код 1C v 8.3 //примеры
ВЫРАЗИТЬ(ДокументыОплаты.Регистратор КАК Документ.ПлатежноеПоручениеВходящее).СуммаДокумента
//или так
ВЫБОР
КОГДА РАЗНОСТЬДАТ(ВЫРАЗИТЬ(ВзаиморасчетыПоДокументам.ДокументРасчетовСКонтрагентом КАК Документ.ПоступлениеТоваровУслуг).Дата,КонецПериода, ДЕНЬ) > ВзаиморасчетыПоДокументам.ДоговорКонтрагента.ДопустимоеЧислоДнейЗадолженности
ТОГДА ДОБАВИТЬКДАТЕ(ВЫРАЗИТЬ(ВзаиморасчетыПоДокументам.ДокументРасчетовСКонтрагентом КАК Документ.ПоступлениеТоваровУслуг).Дата, ДЕНЬ, ВзаиморасчетыПоДокументам.ДоговорКонтрагента.ДопустимоеЧислоДнейЗадолженности)
ИНАЧЕ ДАТАВРЕМЯ(1, 1, 1)
КОНЕЦ КАК ДеньВозникновенияЗадолженности
В дополнении у пункту 1, код процедуры сформировать отчет(). Для вывода отчета я использую шаблон All4CF.ru_Template_SKD_v4.1 в нем уже реализованы почти все необходимые функции и работает в Обычных и УП формах:
Код 1C v 8.3 // Процедура выполняет формирование табличного документа по настройкам СКД
Процедура СформироватьОтчет(ТабличныйДокумент, ДанныеРасшифровки)
УстановитьПривилегированныйРежим(Истина);
// если отчет открывается по расшифровке, отбору, упорядочиванию,
// группировке или условному оформлению - восстановим настройки вывода заголовка,
// т.к., в переданных настройках при этом, вывод заголовка отключен
// для того, чтобы не выводился встроенный заголовок компоновки.
ВосстановитьНастройкиВыводаЗаголовка();
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ТабличныйДокумент.Очистить();
// установим обязательные настройки отчета
УстановитьПараметрыОтчета();
// Сделаем копию настроек вывода заголовка
СохранитьНастройкиВыводаЗаголовка();
ВыводитьЗаголовок = ВыводитьЗаголовокОтчета();
Если ВыводитьЗаголовок Тогда
ПрисоединитьЗаголовокОтчетаКТабличномуДокументу(ТабличныйДокумент, ПолучитьТекстЗаголовкаОтчета());
// Отключим в настройках вывод встроенного заголовка
НайденнаяНастройкаВыводаЗаголовка = КомпоновщикНастроек.Настройки.ПараметрыВывода.Элементы.Найти("ВыводитьЗаголовок");
НайденнаяНастройкаВыводаЗаголовка.Значение = ТипВыводаТекстаКомпоновкиДанных.НеВыводить;
НайденнаяНастройкаВыводаЗаголовка.Использование = Истина;
КонецЕсли;
КопияДополнительныхНастроек = УстановитьДополнительныеНастройкиДляРасшифровки();
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
// при необходимости вставим внешние наборы данных в СКД
ВнешниеНаборыДанных = Новый Структура;
ТаблицаВнешнегоНабораДанных = ПолучитьТаблицуВнешнегоНабораДанных();
ВнешниеНаборыДанных.Вставить("ТаблицаВнешнегоНабораДанных",ТаблицаВнешнегоНабораДанных);
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных,ВнешниеНаборыДанных,ДанныеРасшифровки);
ВывестиРезультатКомпоновкиСАвтофиксациейСтрок(ТабличныйДокумент, ПроцессорКомпоновкиДанных, ДанныеРасшифровки.Элементы,,,КоличествоФиксируемыхСтолбцов);
ДополнительнаяОбработкаРезультатаОтчета(ТабличныйДокумент);
Если ВыводитьЗаголовок Тогда
// вернем настройки вывода заголовка на место
ВосстановитьНастройкиВыводаЗаголовка();
КонецЕсли;
// восстановим дополнительные настройки
Для Каждого ЭлементСтруктуры Из КопияДополнительныхНастроек Цикл
КомпоновщикНастроек.Настройки.ДополнительныеСвойства.Вставить(ЭлементСтруктуры.Ключ, ЭлементСтруктуры.Значение);
КонецЦикла;
// сохраненные настройки нужны только при расшифровке и т.п.
// и не будуть давать изменить вывоз заголовка при обычном формировании.
ОчиститьСохраненныеНастройкиВыводаЗаголовка();
УстановитьВидимостьЗаголовкаОтчета(ТабличныйДокумент);
УстановитьВидимостьПараметровОтчета(ТабличныйДокумент);
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры // СформироватьОтчет()
Категория:
Схема Компоновки Данных СКД Внешний источник данных, грузим из ТЗ и далее получаем остатки на каждый документ Очень часто бывают ситуации, когда необходимо сделать отчет СКД на сложном запросе, который используюет в себе вложенные запросы и объединения внутренние и полные и т.д. - в результате в консоли этот запрос формируется верно, а в скд половина полей пустые! Связано это с особенностью СКД в объединении внутренних данных, а так же не стоит забывать что в СКД наборы данных связываются как левое соединение...
Решения возможны следующие:
Изменить запрос в СКД Сформировать запрос обычным способом и подставить эти данные в СКД как внешние Рассмотрим последний вариант:
Внешний источник данных, грузим из ТЗ Для вывода отчета я использую шаблон All4CF.ru_Template_SKD_v4.1 в нем уже реализованы почти все необходимые функции и работает в Обычных и УП формах.
В модуле объекта уже есть функция
Код 1C v 8.2 УП Функция ПолучитьТаблицуВнешнегоНабораДанных()
Возврат Новый ТаблицаЗначений;
КонецФункции // ПолучитьТаблицуВнешнегоНабораДанных()
установим в ней наш запрос, получается примерно так:
Код 1C v 8.2 УП // В данной функции можно сформировать таблицу внешнего набора данных для СКД
//
// Функция должна возвращать таблицу данных (например таблицу значений)
//
Функция ПолучитьТаблицуВнешнегоНабораДанных()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
| ВложенныйЗапрос.Регистратор КАК ДокРеал,
| ВложенныйЗапрос.Регистратор.Доставка КАК ДокДоставка
|ПОМЕСТИТЬ ОплаченнаяРеализация
|ИЗ
| (ВЫБРАТЬ
| ВзаиморасчетыСКонтрагентамиПоДокументамРасчетовОбороты.Регистратор КАК Регистратор
/////// Огромный запрос .......
| СГРУППИРОВАТЬ ПО
| ДоставкаПромежуточнаяНакладная.Ссылка,
| ДоставкаПромежуточнаяНакладная.Ссылка.Счет,
| ДоставкаПромежуточнаяНакладная.Ссылка.ВыставленоКлиенту,
| ИздержкиРаспределенныеНеНаОП.РаспределеннаяИздержка,
| ДоставкаПромежуточнаяНакладная.Ссылка.СтоимостьПрайс + ДоставкаПромежуточнаяНакладная.Ссылка.ЗатратыПриДоставке) КАК ДанныеПоДоставкам
| ПО ДанныеПоРеализации.ДокументПродажи.Доставка = ДанныеПоДоставкам.ДокДоставка";
Запрос.УстановитьПараметр("КонецПериода", НастройкаПериода.ДатаОкончания);
Запрос.УстановитьПараметр("НачалоПериода", НастройкаПериода.ДатаНачала);
Запрос.УстановитьПараметр("НачалоПериодаМинусГод", НастройкаПериода.ДатаНачала-(86400*365));
Результат = Запрос.Выполнить();
Выборка = Результат.Выгрузить();
Возврат Выборка;
КонецФункции // ПолучитьТаблицуВнешнегоНабораДанных()
Ниже в коде происходит установка внешних данных из нашей ТЗ с именем ТаблицаВнешнегоНабораДанных
Код 1C v 8.2 УП // при необходимости вставим внешние наборы данных в СКД
ВнешниеНаборыДанных = Новый Структура;
ТаблицаВнешнегоНабораДанных = ПолучитьТаблицуВнешнегоНабораДанных();
ВнешниеНаборыДанных.Вставить("ТаблицаВнешнегоНабораДанных",ТаблицаВнешнегоНабораДанных);
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных,ВнешниеНаборыДанных,ДанныеРасшифровки);
ВывестиРезультатКомпоновкиСАвтофиксациейСтрок(ТабличныйДокумент, ПроцессорКомпоновкиДанных, ДанныеРасшифровки.Элементы,,,КоличествоФиксируемыхСтолбцов);
В самой компоновке добавляем набор Объект с именем ТаблицаВнешнегоНабораДанных и перечисляем поля, которые будут использоваться в отчете:
Как я уже говорил выше, далее нам необходимо получить остатки взаиморасчетов на дату документа:
Получение остатков на документ в СКД Набор данных Запрос - назвали его Остатки:
Теперь установим связи Запроса и Объекта
Остатки нужно получать на дату документа и по контрагенту
Далее, если нужно, задайте вычисляемые поля, ресурсы, параметры и Настройте Список вывода...
Пример результата отчета:
Категория:
Схема Компоновки Данных Установка сервера 1С:Предприятия и PostgreSQL на платформе Linux. Связка сервера 1С:Предприятие и PostgreSQL вторая по популярности среди установок 1С и самое используемое решение на платформе Linux. В отличии внедрений на базе Windows и MSSQL, где трудно сделать так, чтобы не заработало, внедрения на базе Linux таят множество подводных камней для неопытного администратора. Часто бывает так, что вроде бы все сделано правильно, но ошибка следует за ошибкой. Сегодня мы рассмотрим самые типовые из них.
Общая информация Перед тем, как начинать искать ошибки установки и, вообще, приступать к внедрению серверной версии 1С:Предприятия было бы неплохо освежить представление как это работает:
Сервер 1С Предприятия. Часть 1 - Общие вопросы.
В небольших внедрениях сервер 1С и сервер СУБД обычно совмещают на одном физическом сервере, что немного сужает круг возможных ошибок. В нашем случае будет рассматриваться ситуация, когда сервера разнесены по разным машинам. В нашей тестовой лаборатории мы развернули следующую схему:
В нашем распоряжении имеются два сервера под управлением Ubuntu 12.04 x64, на одном из них установлен сервер 1С:Предприятие версии 8.3, на другом PostgreSQL 9.04 от Ethersoft, а также клиент под управлением Windows. Напоминаем, что клиент работает только с сервером 1С, который, в свою очередь, формирует необходимые запросы к серверу СУДБ. Никаких запросов от клиента к серверу управления базами данных не происходит.
Сервер баз данных не обнаруженВАЖНО: пользователь "postgres" не прошёл проверку подлинности (Ident)
Данная ошибка возникает при разнесении серверов по разным ПК из-за неправильно настроеной проверки подлинности в локальной сети. Для устранения откройте /var/lib/pgsql/data/pg_hba.conf, найдите строку:
host all all 192.168.31.0/24 ident[/pre]и приведите ее к виду:
host all all 192.168.31.0/24 md5[/pre]где 192.168.31.0/24 - диапазон вашей локальной сети. Если такой строки нет, ее следует создать в секции IPv4 local connections.
Сервер баз данных не обнаруженcould not translate host name "NAME" to address: Temporar y failure in name resolution
На первый взгляд ошибка понятна: клиент не может разрешить имя сервера СУБД, типичная ошибка для небольших сетей, где отсутствует локальный DNS-сервер. В качестве решения добавляют запись в файлhosts на клиенте, что не дает никакого результата...
А теперь вспоминаем, о чем было сказано несколько раньше. Клиентом сервера СУБД является сервер 1С, но никак не клиентский ПК, следовательно запись нужно добавлять на сервере 1С:Предприятие в файл/etc/hosts на платформе Linux или в C:\Windows\System32\drivers\etc\hosts на платформе Windows.
Аналогичная ошибка будет возникать, если вы забыли добавить запись типа A для сервера СУБД на локальном DNS-сервере.
Ошибка при выполнении операции с информационной базойserver_addr=NAME descr=11001(0x00002AF9): Этот хост неизвестен.
Как и прошлая, эта ошибка связана с неправильным разрешением клиентом имени сервера. На этот раз именно клиентским ПК. В качестве решения добавляем в файл /etc/hosts на платформе Linux или в C:\Windows\System32\drivers\etc\hosts на платформе Windows запись вида:
192.168.31.83SRV-1C-1204[/pre]где указываете адрес и имя вашего сервера 1С:Предприятия. В случае использования локального DNS следует добавить A-запись для сервера 1С.
Ошибка СУБД: DATABASE не пригоден для использования
Гораздо более серьезная ошибка, которая говорит о том, что вы установили несовместимую с 1С:Предприятие версию PostgreSQL или допустили грубые ошибки при установке, например не установили все необходимые зависимости, в частности библиотеку libICU.
Если вы имеете достаточный опыт администрирования Linux систем, то можете попробовать доустановить необходимые библиотеки и заново инициализировать кластер СУБД. В противном случае PostgreSQL лучше переустановить, не забыв удалить содержимое папки /var/lib/pgsql.
Также данная ошибка может возникать при использовании сборок 9.1.x и 9.2.x Postgre@Etersoft, подробности смотрите ниже.
Ошибка СУБД: ERROR: could not load librar y "/usr/lib/x86_64-linux-gnu/postgresql/fasttrun.so" Довольно специфичная ошибка, характерная для сборок 9.1.x и 9.2.x Postgre@Etersoft, также может приводить предыдущей ошибке. Причина кроется в неисправленной ошибке в библиотеке fasttrun.so. Решение - откатиться на сборку 9.0.x Postgre@Etersoft.
Ошибка СУБДERROR: type "mvarchar" does not exist at character 31 Возникает если база данных была создана без помощи системы 1С:Предприятия. Помните, для работы с 1С базы данных следует создавать только с использованием инструментов платформы 1С: через консоль Администрирование серверов 1С Предприятия
или через средство запуска 1С.
Сервер баз данных не обнаруженВАЖНО: пользователь "postgres" не прошёл проверку подлинности (по паролю) Очень простая ошибка. Неправильно указан пароль суперпользователя СУБД postgres. Вариантов решения два: вспомнить пароль или изменить его. Во втором случае вам нужно будет изменить пароль в свойствах всех существующих информационных баз через оснастку Администрирование серверов 1С Предприятия.
Сервер баз данных не обнаруженFATAL: database "NAME" does not exist Еще одна очень простая ошибка. Смысл ее сводится к тому, что указанная БД не существует. Чаще всего возникает из-за ошибки в указании имени базы. Следует помнить, что информационная база 1С в кластере и база данных СУБД - две разные сущности и могут иметь различные имена. Также следует помнить, что Linux системы чувствительны к регистру и для них unf83 и UNF83 два разных имени.
Источник: interface31
Категория:
Администрирование Обработка файлов в папке и запись дополнительной информации в них Частенько при загрузке данных в 1С сталкиваешься с необходимостью дополнительной обработки загружаемых файлов. Возможно это добавление какой-либо информации или наоборот удаление, а может изменение.
Ниже приведен код, который обрабатывает файлы в указанной папке и добавляет в конец файла информацию о дате его последнего изменения:
(это лишь рабочий пример / набросок - который вы можете использовать для написания своего обработчика)
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
масФайлов = НайтиФайлы(ПутьКФайлу, "*.w1c");
Для Каждого стр из масФайлов Цикл
Состояние("Обработка: "+стр.Имя);
текФайл = стр.ПолноеИмя;
ВыбФайл = Новый Файл(текФайл);
ДатаИзмененияФайла = Формат(ВыбФайл.ПолучитьУниверсальноеВремяИзменения(),"ДЛФ=D");
текДок = Новый ТекстовыйДокумент;
текДок.Прочитать(текФайл, "UTF-8");
текТекст = текДок.ПолучитьТекст()+Символы.ПС+"<&w1c&>"+ДатаИзмененияФайла;
текДок.УстановитьТекст(текТекст);
текДок.Записать(текФайл, "UTF-8");
КонецЦикла;
КонецПроцедуры
Процедура ПриОткрытии()
ПутьКФайлу="Укажите каталог"
КонецПроцедуры
Процедура ПутьКФайлуНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
// Мы выбираем каталог, поэтому фильтр по расширению файлов нам не нужен
// Оставлю на всякий случай, вдруг пригодится позже
//ДиалогОткрытияФайла.ПолноеИмяФайла = "";
//Текст = "ru = ""Текст""; en = ""Text""";
//Фильтр = НСтр(Текст)+"(*.w1c)|*.w1c";
//ДиалогОткрытияФайла.Фильтр = Фильтр;
//ДиалогОткрытияФайла.МножественныйВыбор = Истина;
ДиалогОткрытияФайла.Заголовок = "Выберите Каталог с файлами";
Если ДиалогОткрытияФайла.Выбрать() Тогда
ПутьКФайлу = ДиалогОткрытияФайла.Каталог;
//МассивФайлов = ДиалогОткрытияФайла.ВыбранныеФайлы;
//Для Каждого ИмяФайла Из МассивФайлов Цикл
// ВыбФайл = Новый Файл(ИмяФайла);
// Текст = "ru = ""; Размер = ""; en = ""; Size = """;
// Сообщить(ИмяФайла+НСтр(Текст)+ВыбФайл.Размер());
//КонецЦикла;
Иначе
Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!""";
Предупреждение(НСтр(Текст));
КонецЕсли;
КонецПроцедуры
Сама обработка : ObrabotkaFaylov.rar
Категория:
Работа с Файлами и Каталогами