Отправка почты через Mail.ru с использованием технологии шифрования SSL Часто клиенты просят сделать автоматическую отправку счетов или отчетов на электронную почту, ниже приведены примеры кода для разных версий 1С:
Код 1C v 8.3
//Код для обычного приложения, для управляемого приложения отправка почты так же, только с файлами и предупреждение нужно изменить код
Функция ПолучитьПрофильПочты()
//Создаем профиль либо считываем из справочника
Профиль = Новый ИнтернетПочтовыйПрофиль;
Профиль.АдресСервераSMTP = "smtp.mail.ru";//Отправитель.АдресСервераSMTP; //"smtp.mail.ru";
Профиль.АдресСервераPOP3 = "pop.mail.ru"; //Отправитель.АдресСервераPOP3; //"pop.mail.ru";
Профиль.ПортPOP3 = 995;//Отправитель.ПортPOP3; //110;
Профиль.ПортSMTP = 465;//Отправитель.ПортSMTP; //587;
Профиль.Пользователь = "s_v@inbox.ru";// Отправитель.Email; //"test@mail.ru";
Профиль.Пароль = "8mFTnDjC4KftTzh"; //Отправитель.Пароль; //"123456789";
Профиль.ПользовательSMTP = "s_v@inbox.ru";//Отправитель.Email; //"test@mail.ru";
Профиль.ПарольSMTP = "8mFTnDjC4KftTzh";//Отправитель.Пароль; //"123456789";
Профиль.АутентификацияSMTP = СпособSMTPАутентификации.Login;
Профиль.ИспользоватьSSLPOP3 = Истина;
Профиль.ИспользоватьSSLSMTP = Истина;
//Создаем письмо
Возврат Профиль;
КонецФункции
Процедура ОсновныеДействияФормыСчетОтправитьНаПочту(Кнопка)
Если ЗначениеЗаполнено(Ответственный.ПочтаДляОтправкиСчета) Тогда
Почта = Новый ИнтернетПочта;
Письмо = Новый ИнтернетПочтовоеСообщение;
Текст = Письмо.Тексты.Добавить("В приложении счет");
Текст.ТипТекста = ТипТекстаПочтовогоСообщения.ПростойТекст;
Письмо.Тема = Строка(Ссылка);
Письмо.Отправитель = "s_vmeste@inbox.ru";
Письмо.ИмяОтправителя = "1С";
Письмо.Получатели.Добавить(Ответственный.ПочтаДляОтправкиСчета);
врфайл=ПолучитьИмяВременногоФайла("pdf");
текТабдок=СчетФаксимилеТовары(); //Функция возвращает табличный документ печать счета
текТабдок.Записать(врфайл,ТипФайлаТабличногоДокумента.PDF);
Письмо.Вложения.Добавить(врфайл);
//добавляем вложение если нужно, например "C:\Приложение.doc"
//Вложений можно добавлять сколько требуется.
//Отправляем письмо
Попытка
Почта.Подключиться(ПолучитьПрофильПочты()); Почта.Послать(Письмо); Предупреждение("Письмо отправлено",3);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
//Закрываем письмо
Почта.Отключиться();
//Закрываем файл вложения
Письмо.Вложения.Очистить();
Иначе
Предупреждение("В настройках ответственного не указана почта для отправки счета");
КонецЕсли;
КонецПроцедуры
С версиями 8.2 сложнее, так как все почтовые сервисы перешли на SSL, а медоты:
Код 1C v 8.3 Профиль.ИспользоватьSSLPOP3 = Истина;
Профиль.ИспользоватьSSLSMTP = Истина;
появились только в 8.3.1 , остается использовать stunnel или CDO :
Код 1C v 8.2 УП //Отправка через CDO, Адрессаты через ";"
Функция ПослатьПоПочте(Знач Адрессаты, ТемаСообщения = "",ТекстСообщения = "" ,СписокВложений = "")Экспорт
Оправитель = "s_v@inbox.ru";
Пароль = "8mFTnDjC4KftTzh";
loConfig = Новый COMОбъект("CDO.Configuration");
loCdoMessage = Новый COMОбъект("CDO.Message");
loCdoMessage.Configuration = loConfig;
loCdoMessage.From = Строка("1С <"+Оправитель+">"); //loCdoMessage.From = "Тест 1C"""" <xxxxxxx@yandex.ru>";
loCdoMessage.To = Адрессаты; //loCdoMessage.To = "xxxxxxx@gmail.ru>";
loCdoMessage.Subject = ?(ТемаСообщения="","1С",ТемаСообщения);
loCdoMessage.TextBody = "1C";
HTMLBody = "<html>
|<head>
|<meta content=""text/html; charset=Windows-1251"" http-equiv=""content-type"">
|<title > Тестовое сообщение </title >
|</head>
|<body>
|<h4>" + ТекстСообщения + "</h4>
|<p></p>
|</body>
|</html>";
//loCdoMessage.BodyPart.Charset = "windows-1251";
loCdoMessage.HTMLBody = HTMLBody;
Если ТипЗнч(СписокВложений) = Тип("Строка") И Не СписокВложений = "" Тогда
Попытка
loCdoMessage.AddAttachment(СписокВложений);
Исключение
КонецПопытки;
ИначеЕсли ТипЗнч(СписокВложений) = Тип("СписокЗначений") Тогда
Для каждого ПутьКВложению Из СписокВложений Цикл
Попытка
loCdoMessage.AddAttachment(ПутьКВложению.Значение);
Исключение
КонецПопытки;
КонецЦикла;
КонецЕсли;
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing"). Value = 2;
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver"). Value = "smtp.mail.ru";
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport"). Value = "465";
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"). Value = 1;
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername"). Value = Оправитель;
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword"). Value = Пароль;
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl"). Value = 1;
loConfig.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout").Value = 60;
loConfig.Fields.Update();
Попытка
loCdoMessage.Send();
Исключение
Сообщить(ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
Процедура ОсновныеДействияФормыСчетТовары(Кнопка)
Если ЗначениеЗаполнено(Менеджер.ПочтаДляОтправкиСчета) Тогда
врфайл=ПолучитьИмяВременногоФайла("xls");
текТабдок=СчетФаксимилеТовары();
текТабдок.Записать(врфайл,ТипФайлаТабличногоДокумента.XLS);
ПослатьПоПочте(Менеджер.ПочтаДляОтправкиСчета,Строка(Ссылка),"Счет в приложении",врфайл);
Предупреждение("Письмо отправлено",3);
Иначе
Предупреждение("В настройках ответственного не указана почта для отправки счета");
КонецЕсли;
КонецПроцедуры
Через stunnel в 1С код, менять не нужно, только установить программу и изменить настройки подключения к почтовому ящику
Скачиваем stunnel c официального сайта (stunnel.org) и запускаем инсталятор, жмем yes при установке спросит страну и ваши данные, это нужно для создания сертификата на вашем компьютере.
После запуска в трее появится его иконка, правой клавишей и редактировать edit configuration
В блокноте откроется файл настроек, там будет пример для gmail дополняем или заменяем его следующим:
Код Batch File (DOS, CMD, BAT) [gmail-pop3]
client = yes
accept = 127.0.0.1:10110
connect = pop.gmail.com:995
[gmail-imap]
client = yes
accept = 127.0.0.1:10143
connect = imap.gmail.com:993
[gmail-smtp]
client = yes
accept = 127.0.0.1:10025
connect = smtp.gmail.com:465
[yandex-pop3]
client = yes
accept = 127.0.0.1:20110
connect = pop.yandex.ru:995
[yandex-imap]
client = yes
accept = 127.0.0.1:20143
connect = imap.yandex.ru:993
[yandex-smtp]
client = yes
accept = 127.0.0.1:20025
connect = smtp.yandex.ru:465
[mail-pop3]
client = yes
accept = 127.0.0.1:30110
connect = pop.mail.ru:995
[mail-imap]
client = yes
accept = 127.0.0.1:30143
connect = imap.mail.ru:993
[mail-smtp]
client = yes
accept = 127.0.0.1:30025
connect = smtp.mail.ru:465
Сохраняем файл и делаем Reload configuration
В настройка 1С меняем порты для работы
gmail
pop3 10110
imap 10143
smtp 10025
yandex
pop3 20110
imap 20143
smtp 20025
mail
pop3 30110
imap 30143
smtp 30025
Если в коде прописано, то:
Код 1C v 8.х Функция ПолучитьПрофильПочты()
//Создаем профиль либо считываем из справочника
Профиль = Новый ИнтернетПочтовыйПрофиль;
Профиль.АдресСервераSMTP = "localhost";//"smtp.mail.ru";//Отправитель.АдресСервераSMTP; //"smtp.mail.ru";
Профиль.АдресСервераPOP3 = "localhost";//"pop.mail.ru"; //Отправитель.АдресСервераPOP3; //"pop.mail.ru";
Профиль.ПортPOP3 = 30110;//Отправитель.ПортPOP3; //110; 995
Профиль.ПортSMTP = 30025;//Отправитель.ПортSMTP; //587; 465
Профиль.Пользователь = "s_v@inbox.ru";// Отправитель.Email; //"test@mail.ru";
Профиль.Пароль = "8mFTnDjC4KftTzh"; //Отправитель.Пароль; //"123456789";
Профиль.ПользовательSMTP = "s_v@inbox.ru";//Отправитель.Email; //"test@mail.ru";
Профиль.ПарольSMTP = "8mFTnDjC4KftTzh";//Отправитель.Пароль; //"123456789";
Профиль.АутентификацияSMTP = СпособSMTPАутентификации.Login;
//Профиль.ИспользоватьSSLPOP3 = Истина;
//Профиль.ИспользоватьSSLSMTP = Истина;
//Создаем письмо
Возврат Профиль;
КонецФункции
Все, можно отправлять и проверять работу через консоль Show log window в меню
P.S. Почтовый ящик в примерах не рабочий, как пример
Категория:
Работа с Интернет, Почтой (Mail), FTP Как в СКД вывести дату и время формирования отчета? Есть несколько вариантов вывода информации перед основным отчетом,какой лучше?! - зависит от задачи:
Допустим нам нужно вывести дату и время формирования отчета и свою шапку отчета, например так:
Варианты решения:
1. Использование группировки и макета заголовка: 1. Создаем в схеме новую группировку (без поля) и установим имя группировке Шапка отчета.
2. Удалим у данной группировки из выбранных полей автополе
В других настройках выберем макет оформления "Без оформления" (иначе на наш макет будет накладываться стандартный макет и вокруг всех ячеек будет рамка)
На вкладке макеты добавляем макет заголовка группировки (при добавлении указываем наше имя группировки (Шапка отчета) и указываем область с нашими данными), справа в табличном документе пишем необходимый текст и параметр
Сохраняем, формируем и видим результат как выше
2. Программное изменение текста заголовка Код нужно установить в процедуре модуля отчета ПриКомпоновкеРезультата()
Код 1C v 8.2 УП ЗначениеПараметра = КомпоновщикНастроек.Настройки.ПараметрыВывода.
НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Title "));
ЗначениеПараметра.Значение="Отчет сформирован "+Формат(ТекущаяДата(),"ДЛФ=DDT");
ЗначениеПараметра.Использование = Истина;
еще пример:
Код 1C v 8.3 Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
КомпоновщикНастроек.Настройки.ПараметрыВывода.Элементы.Найти("ВыводитьЗаголовок").Использование = Истина;
КомпоновщикНастроек.Настройки.ПараметрыВывода.Элементы.Найти("ВыводитьЗаголовок").Значение = ТипВыводаТекстаКомпоновкиДанных.Выводить;
КомпоновщикНастроек.Настройки.ПараметрыВывода.Элементы.Найти("Заголовок").Использование = Истина;
КомпоновщикНастроек.Настройки.ПараметрыВывода.Элементы.Найти("Заголовок").Значение = "Пример вывода своего заголовка," + Символы.ПС
+ "Отчет сформирован "+Формат(ТекущаяДата(),"ДЛФ=DDT");
КонецПроцедуры
3. Вывод табличного макета с параметром перед формированием отчета Создаем макет ВыводСформирован , в нем создаем параметр Сформирован и назначаем имя области Заголовок
В модуле перед
Код 1C v 8.х МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
Пишем:
Код 1C v 8.х // получим макет заголовка отчета
МакетЗаголовка = ПолучитьМакет("ВыводСформирован");
ОбластьЗаголовка = МакетЗаголовка.ПолучитьОбласть("Заголовок");
ОбластьЗаголовка.Параметры.Сформирован = "Сформирован: " + Формат(ТекущаяДата(),"ДЛФ=DDT");
//ОбластьЗаголовка.Параметры.Заголовок = ТекстЗаголовка;
ТабличныйДокумент.Вывести(ОбластьЗаголовка);
в результате:
Категория:
Схема Компоновки Данных 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
Можно ее использовать как макет для создания обработки под свои требования.
Пример автоматизации в котором это использовалось.
Категория:
Географическая схема Реквизит ~ Как сохранять и восстанавливать значения Объектов и Реквизитов на форме УП? У управляемой формы реквизиты заведенные как реквизиты формы, при закрытии и открытии ее заново могут сохраняться и восстанавливаться, достаточно только поставить напротив галочку сохранять и в свойствах формы выбрать "АвтоматическоеСохранениеДанныхВНастройках" - Использовать.
Подробнее в этой статье Как сохранять и восстанавливать значения реквизитов на форме? и там же пример для обычных форм.
А что же делать с реквизитами, которые выступают в роли реквизитов объектов ?
у них такой настройки нет нет - напишем:
Код 1C v 8.3 &НаСервере
Процедура ВосстановитьНастройки()
КлючОбъекта = "ЗагрузкаИЗPDF_All4CF.ru";
КлючНастроек = "ЗагрузкаИЗPDF_All4CF.ru";
ОписаниеНастроек = "ЗагрузкаИЗPDF_All4CF.ru";
ИмяПользователя = "";
ЗначениеНастроек = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек, ОписаниеНастроек, ИмяПользователя);
Если ТипЗнч(ЗначениеНастроек) = Тип("Соответствие") Тогда
Объект.Склад = ЗначениеНастроек.Получить("Склад");
Объект.Организация = ЗначениеНастроек.Получить("Организация");
Объект.ПутьКPDF2TXT = ЗначениеНастроек.Получить("ПутьКPDF2TXT");
Объект.ПутьКPDF = ЗначениеНастроек.Получить("ПутьКPDF");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ВосстановитьНастройки();
КонецПроцедуры
&НаСервере
Процедура СохранитьНастройки()
КлючОбъекта = "ЗагрузкаИЗPDF_All4CF.ru";
КлючНастроек = "ЗагрузкаИЗPDF_All4CF.ru";
ОписаниеНастроек = "ЗагрузкаИЗPDF_All4CF.ru";
ИмяПользователя = "";
Настройки = Новый Соответствие;
Настройки.Вставить("ПутьКPDF2TXT", Объект.ПутьКPDF2TXT);
Настройки.Вставить("ПутьКPDF", Объект.ПутьКPDF);
Настройки.Вставить("Склад", Объект.Склад);
Настройки.Вставить("Организация", Объект.Организация);
ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя);
КонецПроцедуры
&НаКлиенте
Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
СохранитьНастройки();
КонецПроцедуры
Открыв обработку и заполним поля закрываем ее, при следующем открытии все поля заполнены из сохраненных настроек:
Категория:
Работа с Формой (Диалог) и её элементами Универсальный парсер RSS для 1С На одном проекте - клиент попросил отображать в программе данные, которые выдаю специализированные сайта в формате RSS - Что делать !?
Писать парсер rss для 1С
Первым делом, взглянув на ссылки, подумал что - обычный XML, сейчас его разложу и быстренько загружу в базу, но:
Выяснилось что сайты имеют разные форматы ввода RSS и главное они не валидные(
таким образом, написав небольшой код, который получает ссылку, далее XMLФайл.Прочитать() на одном сайте проходил на ура (этот пример я описывал в статье: Чтение данных с сайта в формате XML и загрузка в 1С ), а вот второй сайт, и третий тоже, при попытке прочитать() выдавали:
{ОбщийМодуль.РегЗадания.Модуль(79)}: Ошибка при вызове метода контекста (Прочитать)
Пока XMLФайл.Прочитать() Цикл
по причине:
Ошибка разбора XML: - [1,1]
Фатальная ошибка:
Extra content at the end of the document
SystemId url rss
решил попробовать на rss других известных сайтов - 80% из проверяемых выдавали ошибку
Пришлось написать прямой построчный парсер RSS: Структура конфигурации
ИсточникиRSS - URL на RSS, ДанныеRSS - сюда записываются загруженные данные новостей
Код получился таким(в принципе код универсальный, но возможно что-то придется подпилить):
Код 1C v 8.3
// RSS
Процедура ПрочитатьRSS(ИсточникRSS)
url = ИсточникRSS.UrlRSS;
// Получим Сервер
Если Найти(url,".ru")>0 Тогда urlСервер = Лев(url,Найти(url,".ru")+2);
ИначеЕсли Найти(url,".com")>0 Тогда urlСервер = Лев(url,Найти(url,".com")+3);
ИначеЕсли Найти(url,".org")>0 Тогда urlСервер = Лев(url,Найти(url,".org")+3);
ИначеЕсли Найти(url,".info")>0 Тогда urlСервер = Лев(url,Найти(url,".info")+4);
ИначеЕсли Найти(url,".pro")>0 Тогда urlСервер = Лев(url,Найти(url,".pro")+3);
КонецЕсли;
//Определим тип соединения
Если Лев(url,5)="https" Тогда
//ssl = Новый ЗащищенноеСоединениеOpenSSL(Новый СертификатКлиентаWindows(), Новый СертификатыУдостоверяющихЦентровWindows());
ssl = Новый ЗащищенноеСоединениеOpenSSL( неопределено, неопределено );
ТекАдрес = СтрЗаменить(url,urlСервер,""); Сервер = СтрЗаменить(urlСервер,"https://","");
Соединение = Новый HTTPСоединение(Сервер,,,,,
5, // таймаут в секундах
ssl // защищенное HTTPS соединение
);
Иначе //Обычный HTTP
ТекАдрес = СтрЗаменить(url,urlСервер,""); Сервер = СтрЗаменить(urlСервер,"http://","");
Соединение = Новый HTTPСоединение(Сервер);
КонецЕсли;
Заголовки = Новый Соответствие;
Заголовки.Вставить("host", Сервер);
Запрос = Новый HTTPЗапрос(ТекАдрес, Заголовки);
Ответ =Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда // Данные получены, обрабатываем их
Содержимое= Ответ.ПолучитьТелоКакСтроку();
//Преобразуем содержимое
Содержимое = СтрЗаменить(Содержимое,"<br/>","|");
Содержимое = СтрЗаменить(Содержимое,"<![CDATA[",""); Содержимое = СтрЗаменить(Содержимое,"]]>","");
Содержимое = СтрЗаменить(Содержимое,Символы.ПС,""); Содержимое = СтрЗаменить(Содержимое,Символы.ВК,"");
Содержимое = СтрЗаменить(Содержимое,Символы.ВТаб,""); Содержимое = СтрЗаменить(Содержимое,Символы.Таб,"");
Содержимое = СтрЗаменить(Содержимое,"><",">"+Символы.ПС+"<");
RegExp = Новый COMОбъект("VBScript.RegExp"); //Регулярка
RegExp.IgnoreCase = Ложь;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML
//Разберем полученный текст в таблицу
ЭтоЗапись=Ложь;
Для н=1 По СтрЧислоСтрок(Содержимое)Цикл
обрТекст=СтрПолучитьСтроку(Содержимое,н);
Если обрТекст = "<item>" Тогда //Началась запись
ЗаписьСтр = Новый Структура(); ЭтоЗапись=Истина; Продолжить;
ИначеЕсли обрТекст = "</item>" Тогда //Закончилась запись
/////////////// ЗАПИСЬ Закончилась //////////////
/// теперь запишем ее в базу - Справочник ДанныеRSS
// сначала ПОИСК ДУБЛЕЙ - вдруг уже загружен
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеRSS.Ссылка
|ИЗ
| Справочник.ДанныеRSS КАК ДанныеRSS
|ГДЕ
| ДанныеRSS.ИсточникRSS =ИсточникRSS
| И ДанныеRSS.link ПОДОБНОlink";
Запрос.УстановитьПараметр("link", "%"+ЗаписьСтр.link+"%");
Запрос.УстановитьПараметр("ИсточникRSS", ИсточникRSS);
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Если РезультатЗапроса.Следующий() Тогда
// Такая запись уже есть, пока ничего не делаем
Иначе
//СОЗДАЕМ Новый
НовЭлем = Справочники.ДанныеRSS.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(НовЭлем,ЗаписьСтр);
НовЭлем.ИсточникRSS = ИсточникRSS;
НовЭлем.Записать();
КонецЕсли;
/////////////////////// *** /////////////////////
ЭтоЗапись=Ложь; Продолжить;
КонецЕсли; //Данные записи
Если ЭтоЗапись Тогда
Если Найти(обрТекст,"title >")>0 и Найти(обрТекст,"/title >")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"title ",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
ЗаписьСтр.Вставить("Наименование",СокрЛП(обрТекст));
КонецЕсли;
Если Найти(обрТекст,"link>")>0 и Найти(обрТекст,"/link>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"link",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
ЗаписьСтр.Вставить("link",СокрЛП(обрТекст));
КонецЕсли;
Если Найти(обрТекст,"description>")>0 и Найти(обрТекст,"/description>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"description",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
обрТекст=RegExp.Replace(обрТекст, ""); //Удалим все теги
ЗаписьСтр.Вставить("desc",СокрЛП(обрТекст));
КонецЕсли;
Если Найти(обрТекст,"pubDate>")>0 и Найти(обрТекст,"/pubDate>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"pubDate",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
ЗаписьСтр.Вставить("pubDate",ПреобразоватьRFC822КДате0(СокрЛП(обрТекст)));
КонецЕсли;
Если Найти(обрТекст,"enclosure")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"""",""); обрТекст = СтрЗаменить(обрТекст,"<enclosure url=","");
обрТекст = СтрЗаменить(обрТекст,"<enclosure url=",""); обрТекст = СтрЗаменить(обрТекст,"type=image/png length=/>","");
ЗаписьСтр.Вставить("img",СокрЛП(обрТекст));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ПроверкаRSS() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИсточникиRSS.Ссылка КАК Ссылка
|ИЗ
| Справочник.ИсточникиRSS КАК ИсточникиRSS
|ГДЕ
| ИсточникиRSS.Использовать
| И ДОБАВИТЬКДАТЕ(ИсточникиRSS.ДатаПоследнегоОбновления, СЕКУНДА, ИсточникиRSS.ПериодОбновленияВСекундах) <ТекДата";
Запрос.УстановитьПараметр("ТекДата", ТекущаяДата());
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ПрочитатьRSS(ВыборкаДетальныеЗаписи.Ссылка);
// Запишем дату последнего обновления
ТекОб = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
ТекОб.ДатаПоследнегоОбновления = ТекущаяДата();
ТекОб.Записать();
КонецЦикла;
КонецПроцедуры
Функция ПреобразоватьRFC822КДате0(ДатаВФорматеRFC822) Экспорт
КопияСтроки = ДатаВФорматеRFC822;
СтруктураДаты = Новый Структура("Год,Месяц,День,Час,Минута,Секунда", "","","","","","");
Месяцы = Новый Структура("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", "01","02","03","04","05","06","07","08","09","10","11","12");
Для каждого КлючИЗначение Из Месяцы Цикл
Позиция = Найти(КопияСтроки,КлючИЗначение.Ключ);
Если Позиция > 0 Тогда
СтруктураДаты.Месяц = КлючИЗначение.Значение;
Прервать;
КонецЕсли;
КонецЦикла;
Состояние = 0;
КопияСтроки = СтрЗаменить(КопияСтроки,", 1 ",", 01 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 2 ",", 02 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 3 ",", 03 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 4 ",", 04 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 5 ",", 05 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 6 ",", 06 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 7 ",", 07 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 8 ",", 08 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 9 ",", 09 ");
Для ш=0 По СтрДлина(КопияСтроки) Цикл
ТекущийСимвол = Сред(КопияСтроки,ш,1); //ПолучитьСимвол(КопияСтроки, ш);
ТекСимволЦифра= ЭтоЦифра(ТекущийСимвол);
Если ТекСимволЦифра И Состояние = 0 Тогда
СтруктураДаты.День = СтруктураДаты.День + ТекущийСимвол;
Состояние = 1; //начало день
ИначеЕсли ТекСимволЦифра И Состояние = 1 Тогда
СтруктураДаты.День = СтруктураДаты.День + ТекущийСимвол;
Состояние = 2; //ждем год
ИначеЕсли ТекСимволЦифра И Состояние = 2 Тогда
СтруктураДаты.Год = СтруктураДаты.Год + ТекущийСимвол;
Состояние = 3; //продолжаем год
ИначеЕсли ТекСимволЦифра И Состояние = 3 Тогда
СтруктураДаты.Год = СтруктураДаты.Год + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = " " И Состояние = 3 Тогда
Состояние = 4; //дальше час
ИначеЕсли ТекСимволЦифра И Состояние = 4 Тогда
СтруктураДаты.Час = СтруктураДаты.Час + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = ":" И Состояние = 4 Тогда
Состояние = 5; //дальше минута
ИначеЕсли ТекСимволЦифра И Состояние = 5 Тогда
СтруктураДаты.Минута = СтруктураДаты.Минута + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = ":" И Состояние = 5 Тогда
Состояние = 6; //дальше секунда
ИначеЕсли ТекСимволЦифра И Состояние = 6 Тогда
СтруктураДаты.Секунда = СтруктураДаты.Секунда + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = " " И Состояние = 6 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Попытка
Результат = Дата(СтруктураДаты.Год+СтруктураДаты.Месяц+СтруктураДаты.День
+СтруктураДаты.Час+СтруктураДаты.Минута+СтруктураДаты.Секунда);
Исключение
Результат = Неопределено;
КонецПопытки;
Возврат Результат;
КонецФункции
Функция ЭтоЦифра(Символ) Экспорт
Если (КодСимвола(Символ)>=48) И (КодСимвола(Символ)<=57) Тогда Возврат Истина; Иначе Возврат ложь; КонецЕсли;
КонецФункции
Функция ПолучитьСимвол(КопияСтроки, ш)
Возврат Сред(КопияСтроки,ш,1);
КонецФункции
Результат загрузки новостей RSS HelpF.pro
Кстати, как позже выяснилось, здесь уже есть статья с примером через IE и DOM: Получения новостей с RSS-канала сайта buh.ru
Категория:
Работа с Интернет, Почтой (Mail), FTP Отображение PDF файлов в 1С используя ActiveX Adobe PDF Reader Часто при разработке какого-либо функционала в 1С мы делаем прикрепление файлов pdf.
Итак, Первым делом идет Выбор файла, далее нужно быстро просмотреть приложенный файл.
Для решения используются следующие варианты:
файл Выбирается по кнопке Выбор файла и помещается в Реквизит с типом Хранилище Значений
Код 1C v 8.х Процедура КнопкаВыбратьСканНажатие(Элемент)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл";
Диалог.ПолноеИмяФайла = "";
Фильтр = "Все файлы (*.*)|*.*";
Диалог.Фильтр = Фильтр;
Если Диалог.Выбрать() Тогда
Попытка
ПутьКВнешнемуФайлу = Диалог.ПолноеИмяФайла;
СканФайл = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ПутьКВнешнемуФайлу));
СканНазвание = СтрЗаменить(Диалог.ПолноеИмяФайла, Диалог.Каталог,"");
Исключение
СканНазвание = "ОШИБКА!";
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Для открытия используем:
1. Открытие файла в программе Adobe Acrobat Reader
для этого используйте код:
Код 1C v 8.х Процедура ОсновныеДействияФормыПечатьСканВорд(Кнопка)
ИмяМакета = СканФайл;
Если Прав(СканНазвание,3)="doc" или Прав(СканНазвание,3)="docx" Тогда
Состояние("Идет печать в Word");
УниверсальныеМеханизмы.НапечататьВнешнююФорму(Ссылка, ИмяМакета);
Иначе
ИмяКаталога = КаталогВременныхФайлов();
ИмяФайла = "vrem" + Формат(ТекущаяДата(),"ДФ=yyyyMMddhhmmss")+СокрЛП(Прав(СканНазвание,5));
ИмяФайла = РаботаСФайлами.ПолучитьИмяФайла(ИмяКаталога, ИмяФайла);
ДвоичныеДанные = ИмяМакета.Получить();
Если ДвоичныеДанные = Неопределено Тогда
Предупреждение("Не могу открыть файл, прикрепите новый внешний файл!");
Иначе
ДвоичныеДанные.Записать(ИмяФайла);
ЗапуститьПриложение(ИмяФайла);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
2. Добавляем на форму элемент ActiveX Adobe PDF Reader
для этого используйте код:
Код 1C v 8.х Процедура ОсновныеДействияФормыПечатьСканВорд(Кнопка)
ИмяМакета = СканФайл;
Если Прав(СканНазвание,3)="doc" или Прав(СканНазвание,3)="docx" Тогда
Состояние("Идет печать в Word");
УниверсальныеМеханизмы.НапечататьВнешнююФорму(Ссылка, ИмяМакета);
Иначе
ИмяКаталога = КаталогВременныхФайлов();
ИмяФайла = "vrem" + Формат(ТекущаяДата(),"ДФ=yyyyMMddhhmmss")+СокрЛП(Прав(СканНазвание,5));
ИмяФайла = РаботаСФайлами.ПолучитьИмяФайла(ИмяКаталога, ИмяФайла);
ДвоичныеДанные = ИмяМакета.Получить();
Если ДвоичныеДанные = Неопределено Тогда
Предупреждение("Не могу открыть файл, прикрепите новый внешний файл!");
Иначе
ДвоичныеДанные.Записать(ИмяФайла);
// Вывод в элемент ActiveX Adobe PDF Reader
ЭлементыФормы.PDFСканДоговор.LoadFile(ИмяФайла);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Вот так это выглядит:
Категория:
OLE, ActiveX Как добавить подписи в отчет СКД? Во многих организациях сформированные отчеты заверяют подписями.
В данном примере я покажу как можно вывести подписи для типового отчета ЗУП Свод начислений.
Для начала создадим макет в котором и разместим подписи, макет я создам общий, т.к. он будет использоваться и в других отчетах.
Макет такой:
Открываем Отчет СводНачисленнойЗарплатыОрганизаций, открываем Форму и ищем процедуру
ОбновитьОтчет()
После
Код 1C v 8.х СформироватьОтчет(ЭлементыФормы.Результат, ДанныеРасшифровки);
добавляем вывод подписей
Код 1C v 8.х Макет = ПолучитьОбщийМакет("МакетПодписи");
ОбластьВывести = Макет.ПолучитьОбласть("Подпись");
ЭлементыФормы.Результат.Вывести(ОбластьВывести);
Полный код процедуры ОбновитьОтчет()
Код 1C v 8.х Процедура ОбновитьОтчет() Экспорт
СостояниеМодифицированности = Модифицированность;
Если ПанельНастроекНарисована <> Истина Тогда
ОбновлениеОтображения();
КонецЕсли;
ТиповыеОтчеты.ЗагрузитьВРеквизитЗначенияНастроекПанелиПользователя(ЭтотОбъект, ЭтаФорма);
ПараметрыПанели = ТиповыеОтчеты.ПолучитьПараметрыПанелиПользователяОбъекта(ОтчетОбъект);
ЗначенияНастроек = ТиповыеОтчеты.ПолучитьЗначенияНастроекПанелиПользователяОбъекта(ОтчетОбъект);
Отказ = ложь;
ТиповыеОтчеты.ПроверитьЗначенияПараметров(ЗначенияНастроек, ПараметрыПанели, Отказ);
Если Отказ тогда
Возврат;
КонецЕсли;
РежимформированияОтчета = НЕ ЭтоОтработкаРасшифровки;
СформироватьОтчет(ЭлементыФормы.Результат, ДанныеРасшифровки);
//Мигачев - Вывод подписей
Макет = ПолучитьОбщийМакет("МакетПодписи");
ОбластьВывести = Макет.ПолучитьОбласть("Подпись");
// Если надо вывести параметр
//ОбластьВывести.Параметры.Подписант = Бухгалтер;
ЭлементыФормы.Результат.Вывести(ОбластьВывести);
//*//
УправлениеОтчетами.УстановитьКолонтитулыПоУмолчанию(ЭлементыФормы.Результат, Заголовок, Строка(ПараметрыСеанса.ТекущийПользователь));
Модифицированность = СостояниеМодифицированности;
КонецПроцедуры
Категория:
Схема Компоновки Данных Система оповещений Пользователей (универсальная) Для одного проекта пришлось сделать простую систему оповещений!
Она состоит из:
Общая форма
Общий модуль
Регистр Сведений
Общая Форма
На ней поле HTML Документа и Кнопка Ознакомлен (подтверждение что пользователь это видел)
Код 1C v 8.х Перем ТекДата, ТипСсылки, ТекСсылка;
Процедура ПриОткрытии()
ТекДата = Дата;
ЭлементыФормы.ПолеHTMLДокумента.УстановитьТекст(Текст);
КонецПроцедуры
Процедура ОзнакомленНажатие(Элемент)
Если ЗначениеЗаполнено(ТекДата) Тогда
НаборЗаписей = РегистрыСведений.МЕ_Оповещения.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Получатель.Установить(Пользователь);
НаборЗаписей.Отбор.Период.Установить(ТекДата);
НаборЗаписей.Прочитать();
НовыйНомер = НаборЗаписей[0];
НовыйНомер.ДатаОзнакомления = ТекущаяДата();
НаборЗаписей.Записать();
Если ЗначениеЗаполнено(НовыйНомер.ТипСсылки) Тогда
ТекСсылка = НовыйНомер.Ссылка;
ТипСсылки = НовыйНомер.ТипСсылки;
КонецЕсли;
КонецЕсли;
Парам = Новый Структура;
Парам.Вставить("ТипСсылки", ТипСсылки);
Парам.Вставить("ТекСсылка", ТекСсылка);
ЭтаФорма.Закрыть(Парам);
КонецПроцедуры
Процедура ПолеHTMLДокументаonclick(Элемент, pEvtObj)
// Отказ от стандартной обработки клика.
pEvtObj.returnValue = Ложь;
Если ВРег(pEvtObj.srcElement.tagName) = "A" Тогда
СсылкаТекст = Сред(pEvtObj.srcElement.href, 4);
Ссылка = ЗначениеИзСтрокиВнутр(СсылкаТекст);
Если Ссылка.Пустая()
Или Ссылка.ПолучитьОбъект() = Неопределено Тогда
Предупреждение("Ошибка открытия объекта.",, "Ошибка");
Возврат;
Иначе
ОткрытьЗначение(Ссылка);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В общем Модуле:
Код 1C v 8.х Процедура СоздатьОповещение(Получатель,ТекстОповещения, ТипСсылки=Неопределено, Ссылка=Неопределено) Экспорт
НаборЗаписей = РегистрыСведений.МЕ_Оповещения.СоздатьНаборЗаписей();
НовЗапись = НаборЗаписей.Добавить();
НовЗапись.Период = ТекущаяДата();
НовЗапись.Получатель = Получатель;
НовЗапись.ТекстОповещения = ТекстОповещения;
Если НЕ ТипСсылки=Неопределено Тогда
НовЗапись.ТипСсылки = ТипСсылки;
КонецЕсли;
Если НЕ Ссылка=Неопределено Тогда
НовЗапись.Ссылка = Ссылка;
КонецЕсли;
НаборЗаписей.Записать(Ложь);
КонецПроцедуры // СоздатьОповещение()
Процедура ПоказатьОповещение(ТекстОповещения)
формОповещ = ПолучитьОбщуюФорму("МЕ_Оповещения");
формОповещ.текст=ТекстОповещения;
Если Не формОповещ.Открыта() Тогда
формОповещ.ОткрытьМодально();
КонецЕсли;
КонецПроцедуры
Регистр сведений (для хранения сообщений):
Думаю что все поля понятны из названия, только ТипСсылки - Строка 35
Проверка непрочитанных сообщений и вызов окна:
Код 1C v 8.х //Проверим Оповещения для пользователя
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МЕ_Оповещения.Период КАК Период,
| МЕ_Оповещения.Получатель,
| МЕ_Оповещения.ТекстОповещения,
| МЕ_Оповещения.ДатаОзнакомления
|ИЗ
| РегистрСведений.МЕ_Оповещения КАК МЕ_Оповещения
|ГДЕ
| МЕ_Оповещения.ДатаОзнакомления = &ДатаОзнакомления
| И МЕ_Оповещения.Получатель = &Получатель
|
|УПОРЯДОЧИТЬ ПО
| Период";
Запрос.УстановитьПараметр("ДатаОзнакомления", Дата("01.01.0001 0:00:00"));
Запрос.УстановитьПараметр("Получатель", ПараметрыСеанса.ТекущийПользователь);
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
формОповещ = ПолучитьОбщуюФорму("МЕ_Оповещения");
формОповещ.дата=Результат.период;
формОповещ.пользователь=Результат.Получатель;
формОповещ.текст=Результат.ТекстОповещения;
Если Не формОповещ.Открыта() Тогда
Структ = формОповещ.ОткрытьМодально();
Если Структ = Неопределено Тогда
// Ничего
Иначе
Если СокрЛП(Структ.ТипСсылки) = "ОбработкаЦен" Тогда
Обр = Обработки.ОбработкаЦен.Создать();
Обр.Счет = Структ.ТекСсылка;
Обр.ПолучитьФорму().Открыть();
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Пример добавления сообщения:
Код 1C v 8.х МЕ_Оповещения.СоздатьОповещение(ТекДоговорКИзменению.Менеджер, "Ваш Договор №"+СокрЛП(ТекДоговорКИзменению.Номер)+
" - Отклонен!!! - "+ИмяПользователя()+"!"+Символы.ПС+" Исправьте его учитывая Комментарии и запустите на Согласование!", "", ТекДоговорКИзменению.Ссылка);
или
//Создадим оповещение с Передачей ссылки
Текст = "" + ПараметрыСеанса.ТекущийПользователь+": Необходимо Доработать цены:<br> <b>"+Счет.Ссылка+"</b>";
МЕ_Оповещения.СоздатьОповещение(СнабженецПоследнееИзменение, Текст, "ОбработкаЦен", Счет.Ссылка);
Категория:
Полезные, Универсальные Функции Документ не регистрируется в последовательности, как зарегистрировать программно? Ранее я уже писал:
Что такое Последовательность Документов (в кратце и доступно)
В интернете полно вопросам по созданию новой последовательности документов и регистрации в ней документов, и так по порядку:
1. Создали новую последовательность
2. На закладке Использование указали регистрируемые документы и регистры движений:
3.
Для автоматического регистрирования документов - в свойствах документа должно быть в разделе
Данные , поле
Заполнение последовательности - автоматически
4. Если указано: Не заполнять автоматически
Документы в последовательности не регистрируются сами, для этого в обработку проведения надо добавить код:
Код 1C v 8.х НаборЗаписей = Последовательности.ПартионныйУчет.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Регистратор = ДокументСсылка;
НоваяЗапись.Период = ДокументСсылка.Дата;
НаборЗаписей.Записать();
Если у последовательности есть Измерение, например Организация, то код:
Код 1C v 8.х НаборЗаписей = Последовательности.ПартионныйУчет.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Организация = ДокументСсылка.Организация;
НоваяЗапись.Регистратор = ДокументСсылка;
НоваяЗапись.Период = ДокументСсылка.Дата;
НаборЗаписей.Записать();
Категория:
Документы Как сделать паузу при выполнении кода с информативным сообщением для пользователя Реализация красивой задержки в обработках или в любом другом месте программного кода
Код 1C v 8.х
// Предваряющий код
// Место, где необходимо сделать паузу и съесть твикс )
// И, чтобы пользователь сильно не волновался вывести красивое окно с картинкой
//...
Если ФлажокИспользоватьПаузуМеждуДокументами Тогда
Форма = ПолучитьФорму("ФормаПаузы");
Форма.ПараметрФормы = ДлительностьПаузы;
Форма.ОткрытьМодально();
КонецЕсли;
//...
// Продолжить выполнение кода
Код 1C v 8.х
// Молуль формы "ФормаПаузы"
// В реквизитах формы создаем новый с названием ПараметрФормы к который при открытии передадим период задержки
Процедура ЗакрытиеФормыОбработки()
ЭтаФорма.Закрыть();
КонецПроцедуры
Процедура ПриОткрытии()
ПодключитьОбработчикОжидания("ЗакрытиеФормыОбработки", ПараметрФормы);
КонецПроцедуры
П.С.
При использовании в боевой базе был достигнут эффект зависания окна. Метод был использован в цикле, и после около 200 циклов окно перестало откликаться. Так что рекомендую использовать этот метод в маленьких циклах. Решил задачу через
Код 1C v 8.х
Предупреждение("Пауза...", ДлительностьПаузы);
Категория:
Работа с Формой (Диалог) и её элементами Материалы по ЗУП Проф и ЗУП Корп Категория:
1С Зарплата и Управление Персоналом 2.5 Как в УТ 11 убрать префиксы с печатной формы? Нужно открыть ОбщийМодуль
ПрефиксацияОбъектовКлиентСервер
и найти процедуру
ПолучитьНомерНаПечать
В коде:
Код 1C v 8.2 УП // после
Функция ПолучитьНомерНаПечать(Знач НомерОбъекта, УдалитьПрефиксИнформационнойБазы = Ложь, УдалитьПользовательскийПрефикс = Ложь) Экспорт
// добавляем
//Префикс при печати нам не нужен
УдалитьПрефиксИнформационнойБазы = Истина;
Категория:
1С Управление торговлей 10.3 Настройка и оптимизация сервера, кластера 8.3 Ставя очередное обновление Бухгалтерии получил ошибку "Я работаю только на 8.3.4", ну вот... пришло время поставить 8.3.4. и так:
Процесс скачивания и установки новой платформы я описывать не буду, там все просто.
Служба Агент Сервера 1С
По умолчанию он ставиться на порт 1540, а там у меня крутится 8.2, поэтому меняем в ветке рееста
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\1C:Enterprise 8.3 Server Agent Параметр ImagePath
меняем номера портов, добавляя смещение: "C:\Program Files\1cv8\8.3.4.365\bin\ragent.exe" -srvc -agent -regport 1741 -port 1740 -range 1660:1691 -d "C:\Program Files\1cv8\srvinfo"
Запускаем Агента и Открываем консоль Администрирования серверов 1С и создаем кластер 8.3
Указал имя сервера и настроил на порт 1740 (на 1540 работает 8.2)
Создаем кластер + чуток оптимизировал( У меня всего небольшой ОДИН сервер, поэтому - указываю Интервал перезапуска рабочих процессов и объем памяти. т.к у меня один сервер - уровень отказоустойчивости - 0)
Теперь подробнее:
1. Интервал перезапуска: 86400 сек (24 часа). Момент перезапуска не регламентируется, видимо с момента установки параметров, либо запуска сервера приложений.
2. Также можно указать допустимый объем памяти: 3000000 Кб (3 Гб) - Для сервера с 4 ГБ оперативы,
Если ее меньше, то не заполняйте этот параметр! .
3. Интервал превышения допустимого объема памяти — это непрерывный интервал времени превышения допустимого объема памяти, после которого сервер перезапустит процесс. Если указано 0 сек — будет ждать вечно.
4. Количество Рабочих процессов расчитывается автоматически на основании Ваших настроек
5. Уровень отказоустойчивости можно задавать уровень отказоустойчивости кластера как количество рабочих серверов, которые могут одновременно выйти из строя, и это не приведет к аварийному завершению работы пользователей. Резервные сервисы запускаются автоматически в количестве, необходимом для обеспечения заданной отказоустойчивости; в реальном режиме времени выполняется репликация активного сервиса на резервные.
6. Режим распределения нагрузки, который можно использовать либо для повышения производительности системы вцелом, либо использовать новый режим «экономии памяти», который позволяет работает «с ограниченной памятью» в случаи если используемая конфигурация «любит отъедать память».
Рабочий сервер
Сервер у меня простенький, 2 Gb оперативы всего и на нем будет всего 2 базы, поэтому настрою его так:
параметр Количество ИБ на процесс ставлю равным 1, т.е. хочу чтобы для каждой ИБ запускался свой процесс - это позволит уменьшить взаимное влияние как по надежности, так и по производительности.
Вы же настраивате под характеристики своего сервера!
Информационная база
Добавляю ИБ:
В стартере пописываю базу:
Требования назначения функциональности
Я у себя это не настраиваю но думаю надо сказать об этом:
Управление кластером заключается в том, что администратор определяет состав компьютеров (рабочих серверов), на которых размещается кластер. Кроме этого (при необходимости) он может определить "требования" к ним: какие сервисы и соединения с информационными базами должны работать на каждом из рабочих серверов. Менеджеры кластера и рабочие процессы запускаются автоматически, исходя из назначенных "требований". "Требования" к рабочим серверам могут быть заданы интерактивно, из консоли администрирования кластера, или программно, из встроенного языка.
Так на ноутбуке с ключом защиты чтобы не запускать пользователей на сервер кластера надо добавить «требования» для объекта требования «Клиентское соединение с ИБ» — «Не назначать», т.е. запретить рабочим процессам данного сервера обрабатывать клиентские соединения. Еще больший интерес предоставляет возможность запускать «только фоновые задания» на рабочем сервере кластера без сеансов пользователей. Таким образом можно высоконагруженные задачи (код) вынести на отдельный машины. При чем можно одно фоновое задание «закрытия месяца» через «Значение дополнительного параметра» запускать на одном компьютере, а фоновое задание «Обновление полнотекстового индекса» на другом. Уточнение происходит через указание "Значение дополнительного параметра". Например если указать BackgroundJob.CommonModule в качестве значения, то можно ограничить работу рабочего сервера в кластере только фоновыми заданиями с любым содержимым. Значение BackgroundJob.CommonModule..- укажет конкретный код.
Профили безопасности
Профили безопасности служат для того, чтобы запретить прикладному решению выполнять действия, которые могут быть потенциально опасны для функционирования кластера серверов.
Администратор кластера может назначить любой информационной базе один из существующих в кластере профилей безопасности. И тогда потенциально опасная функциональность прикладного решения будет ограничена в тех пределах, которые описаны в этом профиле.
Стандартно, после создания, профиль безопасности запрещает выполнение всех потенциально опасных действий:
-обращение к файловой системе сервера;
-запуск COM-объектов;
-использование внешних компонентов 1С:Предприятия;
-запуск внешних обработок и отчётов;
-запуск приложений, установленных на сервере;
-обращение к ресурсам Интернета.
Таким образом защититься от нежелательных действий незнакомого прикладного решения очень просто: нужно создать пустой профиль безопасности и назначить его информационной базе. Далее, если есть необходимость, можно расширять этот профиль, описывая в нём действия, которые разрешается выполнять прикладному решению.
Расположение служебных файлов менеджера кластера в 1С Предприятии 8.3
Если при установке системы! «1С:Предприятие» был выбран вариант запуска сервера «1С:Предприятия» как сервиса, то первый запуск агента сервера будет выполнен еще в процессе установки системы. При этом сервис будет запущен от имени пользователя, выбранного в диалоге установки системы, но служебные файлы кластера серверов будут расположены в каталоге <каталог установки системы 1С:Предприятие>\srvinfo (в параметрах сервиса будет в явном виде указан ключ запуска -d).
Если при установке системы «1С:Предприятие» был выбран вариант запуска сервера как приложения, то запуск сервера в процессе установки системы не выполняется; агента сервера необходимо запустить самостоятельно, после того как установка системы будет закончена. При этом если ключ запуска -d указан не будет, служебные файлы кластера серверов будут расположены в каталоге по умолчанию: %USERPROFILE%\LocalSettings\ApplicationData\lC\lCv8 (%LOCALAPPDATA%\lC\lCv8 для ОС WindowsVista и старше).
ВНИМАНИЕ! Если однажды на данном центральном сервере уже был создан кластер, то при смене варианта запуска агента сервера (сервис, приложение) или при смене пользователя, от имени которого работает агент сервера, всегда следует заботиться о правильном указании пути к каталогу служебных файлов кластера серверов. Если в процессе запуска агент сервера не обнаружит список кластеров, он создаст новый кластер на данном сервере.
В операционной системе Linux служебные файлы кластера серверов будут расположены в папке /home/usrlcv8/.lcv8/lC/lcv8 (или сокращенный вариант записи - ~/.1cv8/1C/1cv8).
Категория:
Администрирование Срез последних (остатки) на каждую дату Бывают ситуации, когда в запросе требуется получить остатки не на фиксированную дату (параметр - один на весь отчет), а на произвольную, (когда дата остатков в каждой строке своя).
Существует несколько способов получить нужные данные.
1.Непосредственно в запросе (через реальную таблицу регистра)
Способ подходит практически для любой ситуации, и поэтому наиболее универсален. Единственный, пожалуй, минус этого способа - если в отчете пользователю не требуется курс, то запрос быдет выбирать избыточные данные.
Вызов СрезПоследних() можно использовать только с передачей в него заранее готового значения даты, на которую требуется получить значения. Поэтому сабж делается через стыковку нескольких запросов - основной, к нему стыкуется запрос по регистру сведений с условием по дате и поиском записи с максимальной датой (периодом).
Код 1C v 8.х ВЫБРАТЬ
Таб1.СсылкаДок,
Таб1.ДатаДок,
Таб1.ВалютаДок,
Таб2.Курс
ИЗ
(ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК СсылкаДок,
ЗаказПокупателя.Дата КАК ДатаДок,
ЗаказПокупателя.ВалютаДокумента КАК ВалютаДок,
МАКСИМУМ(Валюты.Период) КАК ПериодДок
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Валюты
ПО Валюты.Период <= ЗаказПокупателя.Дата И
Валюты.Валюта = ЗаказПокупателя.ВалютаДокумента
СГРУППИРОВАТЬ ПО
ЗаказПокупателя.Ссылка) КАК Таб1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Таб2
ПО Таб1.ПериодДок = Таб2.Период И Таб1.ВалютаДок = Таб2.Валюта
Для общего развития:
Что есть срез последних в платформе?
Код 1C v 8.х ВЫБРАТЬ
Рег.Период,
Рег.Измерение,
Рег.Ресурс
ИЗ
РегситрСведений.ПериодическийРегистр.СрезПоследних(&Дата) КАК Рег
В зависимости от периодичности регистра (по времени, по позизии регистратора) ВТ разворачивается в следующий запрос:
1. По времени (год, месяц, ... секунда)
Код 1C v 8.х ВЫБРАТЬ
Таблица3.Ресурс,
Таблица3.Измерение,
Таблица3.Период
ИЗ
(ВЫБРАТЬ
Таблица1.Измерение КАК Измерение,
МАКСИМУМ(Таблица1.Период) КАК Период
ИЗ
РегистрСведений.ПериодическийРегистр КАК Таблица1
ГДЕ
Таблица1.Период <= &Дата
СГРУППИРОВАТЬ ПО
Таблица1.Измерение) КАК Таблица2
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПериодическийРегистр КАК Таблица3
ПО Таблица2.Измерение= Таблица3.Измерение
И Таблица2.Период = Таблица3.Период
2. По позиции регистратора
В данном случае нужно еще раз обернуть выборку
Код 1C v 8.х ВЫБРАТЬ
Таблица5.Ресурс,
Таблица5.Измерение,
Таблица5.Период,
Таблица5.Регистратор
ИЗ
(ВЫБРАТЬ
МАКСИМУМ(Таблица3.Регистратор) КАК Регистратор,
Таблица3.Измерение
ИЗ
(ВЫБРАТЬ
Таблица1.Измерение КАК Измерение,
МАКСИМУМ(Таблица1.Период) КАК Период
ИЗ
РегистрСведений.ПериодическийРегистр КАК Таблица1
ГДЕ
Таблица1.Период <= &Дата
СГРУППИРОВАТЬ ПО
Таблица1.Измерение) КАК Таблица2
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПериодическийРегистр КАК Таблица3
ПО Таблица2.Измерение= Таблица3.Измерение
И Таблица2.Период = Таблица3.Период
СГРУППИРОВАТЬ ПО
Таблица3.Измерение) КАК Таблица4
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПериодическийРегистр КАК Таблица5
ПО Таблица4.Измерение = Таблица5.Измерение
И Таблица4.Регистратор = Таблица5.Регистратор
Все это можно увидеть посмотрев технологический журнал с включенным режимом протоколирования запросов
2.Система компоновки данных (передача набора значений одной таблицы в параметр виртуальной таблицы)
Данный способ подходит для отчетов. Из очевидных плюсов - если курс (или другие данные) не нужны для построения отчета, то СКД не будет их получать. Однако быстродействие такого отчета может оказаться и несколько ниже, чем в первом способе.
Для примера сделаем отчет - список заказов покупателей.
Для этого создадим набор данных "Документы" - запрос:
Код 1C v 8.х ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК ЗаказПокупателя,
ЗаказПокупателя.Дата КАК Дата,
ЗаказПокупателя.ВалютаДокумента КАК ВалютаДокумента,
ЗаказПокупателя.СуммаДокумента КАК СуммаДокумента
{ВЫБРАТЬ
ЗаказПокупателя.*,
Дата,
ВалютаДокумента.*,
СуммаДокумента}
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
{ГДЕ
ЗаказПокупателя.Ссылка.* КАК ЗаказПокупателя,
ЗаказПокупателя.СуммаДокумента}
Для того, чтобы потом успешно свзать наборы данных, в запрос необходимо включить поля "Дата" и "ВалютаДокумента". Чтобы они не появлялись в списке доступных полей, если это необходимо, их можно убрать, установив флажки ограничений в таблице "Поля" схемы компоновки. В остальном запрос вряд ли требует комментариев.
Для того, чтобы получить информацию о курсах валют, добавим второй набор данных-запрос, "Курсы валют":
Код 1C v 8.х ВЫБРАТЬ
&Дата КАК Дата,
КурсыВалютСрезПоследних.Валюта КАК Валюта,
КурсыВалютСрезПоследних.Курс КАК Курс,
КурсыВалютСрезПоследних.Кратность КАК Кратность
{ВЫБРАТЬ
Дата,
Валюта.*,
Курс,
Кратность}
ИЗ
РегистрСведений.КурсыВалют.СрезПоследних(&Дата, Валюта = &Валюта) КАК КурсыВалютСрезПоследних
{ГДЕ
КурсыВалютСрезПоследних.Курс,
КурсыВалютСрезПоследних.Кратность}
В этом запросе имеются 2 параметра: "Дата" и "Валюта". Эти параметры будут установлены СКД при соединении наборов. Кроме того, параметр "Дата" указан в выбранных полях - это нужно для соединения таблиц.
Для ненужный полей "Дата" и "Валюта" также устанавливаем флажки ограничений, чтобы они не появлялись в доступных полях.
Перейдем к соединению наборов. На странице "Связи наборов данных" добавим 2 связи:
1. Источник связи - набор "Документы", приемник - набор "Курсы валют". Выражение источник - "Дата", выражение приемник - "Дата", Параметр - "Дата"
2. Источник связи - набор "Документы", приемник - набор "Курсы валют". Выражение источник - "ВалютаДокумента", выражение приемник - "Валюта", Параметр - "Валюта"
Главное здесь - параметры связи. При соединении наборов данных, если указан параметр, СКД передает в подчиненный набор (в нашем случае - запрос "Курсы валют") параметры, указанные в соединении. Значениями параметров будут значения соответствующих полей набора-источника.
Перейдем к вычисляемым полям. Добавим вычисляемое поле "СуммаВВалютеУпрУчета". Выражение поля - "СуммаДокумента * Курс / Кратность".
Также укажем поля "СуммаДокумента" и "СуммаВВалютеУпрУчета" как ресурсы
Настроим отчет.
Добавим одну группировку "Детальные записи", в выбранных полях укажем "ЗаказПолкупателя", "Курс" и "Кратность". Добавим ресурсы "СуммаДокумента" и "СуммаВВалютеУпрУчета"
Можно формировать отчет
Категория:
Регистры накопления