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С Недавно, мой постоянный клиент решил проводить маркетинговые исследования по изменению цен на товары у конкурентов... и эти данные захотел использовать в 1С в связке с его прайс-листом + куча отчетов с графиками и процентным отклонением от цен основного конкурента
В результате этого, была написана обработка собирающая данные со страниц разных сайтов. Из целей конфиденциальности - сайты раскрывать не буду...
Вид обработки загрузки данных с сайта в 1С
Ниже код загрузки данных со страницы сайта , смысл такой :
в функция передается адрес страницы сайта полученный текст страницы обрабатывается, удаляются теги из полученного текста формируется ТЗ с данными По названию ищется поставщик из вспомогательного справочника Справочники.Pr_Поставщики.НайтиПоНаименованию(, если нет - создается на выходе ТЗ с данными Код 1C v 8.х Функция ПолучитьТаблицуДанных(Строка)
тзДанных = Новый ТаблицаЗначений;
Сервер = "site.ru";
Соединение = Новый HTTPСоединение(Сервер);
Заголовки = Новый Соответствие;
Заголовки.Вставить("host", Сервер);
ТекАдрес = СтрЗаменить(Строка.Наименование.УРЛСтраницы,"http://","");
ТекАдрес = СтрЗаменить(ТекАдрес,Сервер,"");
Запрос = Новый HTTPЗапрос(ТекАдрес, Заголовки);
Ответ =Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда // Данные получены, обрабатываем их
Содержимое= Ответ.ПолучитьТелоКакСтроку();
//Выведем тест полученной страницы
НачалоБлока = "<table id=" + """" + "table-price" + """" + " cellspacing=" + """" + "0" + """" + " border=" + """" + "1" + """" + " bordercolor=" + """" + "#dedede" + """" + " class=" + """" + "tablesorter" + """" + " >";
//НачалоБлока = "<div class=" + """" + "w100fl" + """" + " id=" + """" + "kurs" + """" + ">";
КонецБлока = "</table>";
ТекстБлока = Сред(Содержимое, Найти(Содержимое, НачалоБлока) + СтрДлина(НачалоБлока), Найти(Содержимое, КонецБлока) - Найти(Содержимое, НачалоБлока) - СтрДлина(НачалоБлока));
//Обработаем тест
обрТекст = СтрЗаменить(ТекстБлока,"<tr>","");
обрТекст = СтрЗаменить(обрТекст,"</tr>",Символы.ПС);
обрТекст = СтрЗаменить(обрТекст," >", ">");
обрТекст = СтрЗаменить(обрТекст,"</th> <th>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</td> <td>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th> <th class=" + """" + "sortable_header" + """" + ">", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th> <th >", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th><th>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</td><td>", " | ");
обрТекст = СтрЗаменить(обрТекст," >", ">");
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Ложь;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML
обрТекст=RegExp.Replace(обрТекст, "");
//Сообщить(обрТекст);
Если СокрЛП(обрТекст) = "Ни одной позиции не найдено." Тогда
Сообщить(Строка(Строка.Наименование)+ " = Ни одной позиции не найдено! Строка " + Строка.Наименование);
Возврат тзДанных;
КонецЕсли;
Если Найти(обрТекст, "Страница не найдена") > 0 Тогда
Сообщить(Строка(ТекАдрес)+" = Страница не найдена, строка " + Строка.Наименование);
Возврат тзДанных;
КонецЕсли;
//Преобразуем полученный текст в таблицу
Для н=1 По СтрЧислоСтрок(обрТекст)Цикл
СтрТекста=СтрПолучитьСтроку(обрТекст,н);
Если Найти(СтрТекста, "Длина Цена") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, "Длина Цена", "Длина | Цена");
КонецЕсли;
Если Найти(СтрТекста, "Марка стали Цена") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, "Марка стали Цена", "Марка стали | Цена");
КонецЕсли;
Если Найти(СтрТекста, ", Поставщик") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, ", Поставщик", " | Поставщик");
КонецЕсли;
//Выводим текст страницы построчно
мсДанных = ПолучитьМассивИзСтрокиСРазделителем(СтрТекста, "|", Истина);
Если н=1 Тогда
Для Каждого ткЗнач из мсДанных Цикл
СтрЗапрещСимволов = " .,<>""\/-";
ИмяКолонки = ткЗнач;
Для сч33 = 1 по СтрДлина(СтрЗапрещСимволов) Цикл
ЗапрещСимв = Сред(СтрЗапрещСимволов, сч33, 1);
ИмяКолонки = СтрЗаменить(ИмяКолонки, ЗапрещСимв, "_");
КонецЦикла;
// добавим нужное количество колонок- если перед колонкой Поставщик не хватает
// бывает, что в шапке определяется меньше колонок, чем реально в таблице
Если НРег(ИмяКолонки) = "поставщик" Тогда
Для Сч_дк = (Строка.Наименование.Родитель.Поставшик - 2) по тзДанных.Колонки.Количество() Цикл
тзДанных.Колонки.Добавить("Колонка_" + (тзДанных.Колонки.Количество() + 1));
КонецЦикла;
КонецЕсли;
тзДанных.Колонки.Добавить(ИмяКолонки);
КонецЦикла;
тзДанных.Колонки.Добавить("ном", , , 7);
Иначе
НовСтр = тзДанных.Добавить(); нмас=0;
Для Каждого ткЗнач из мсДанных Цикл
НовСтр[нмас] = ткЗнач;
нмас=нмас+1;
КонецЦикла;
НовСтр.ном = н;
КонецЕсли;
//Сообщить(стр);
КонецЦикла;
тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
Для каждого стр из тзДанных Цикл
текПоставщик = Справочники.Pr_Поставщики.НайтиПоНаименованию(стр[Строка.Наименование.родитель.Поставшик-1]);
Если текПоставщик = Справочники.Pr_Поставщики.ПустаяСсылка() Тогда
НовЭлем = Справочники.Pr_Поставщики.СоздатьЭлемент();
НовЭлем.Наименование = СокрЛП(стр[Строка.Наименование.родитель.Поставшик-1]);
НовЭлем.Записать();
текПоставщик = НовЭлем.Ссылка;
КонецЕсли;
стр.СпрPr_Поставщики = текПоставщик;
КонецЦикла;
Иначе
тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
Сообщить("Ошибка получения данных для строки " + Строка.Наименование);
КонецЕсли;
Возврат тзДанных;
КонецФункции
В коде используется вспомогательная функция ПолучитьМассивИзСтрокиСРазделителем
Код 1C v 8.2 УП // Функция разбивает строку разделителем.
//
// Параметры:
// пСтрока - Строка - которую разбиваем;
// *пРазделитель - Строка, "." - символ-разделитель;
// *ОбрезатьНепечатныеСимволы - Булево, *Ложь.
//
// Возвращаемое значение:
// Массив - фрагментов.
//
Функция ПолучитьМассивИзСтрокиСРазделителем(Знач Стр, Разделитель = ".", ОбрезатьНепечатныеСимволы = Ложь) Экспорт
МассивСтрок = Новый Массив;
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
Фрагмент = Стр;
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Возврат МассивСтрок;
КонецЕсли;
Фрагмент = Лев(Стр,Поз-1);
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
Возврат МассивСтрок;
КонецФункции // ПолучитьМассивИзСтрокиСРазделителем()
Конечно, перед тем как мы начали это делать - прошерстили интернет и нашли несколько решений , вот они:
Код 1C v 8.х Соединение = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяВременногоФайла=ПолучитьИмяВременногоФайла("htm");
Соединение.open("GET", "http://mamba.ru/my", 0);
Соединение.send();
//status: //404 - Not Found //200 - Ok
ТаймАут = 200;
Начало=ТекущаяДата();
Пока Соединение.readyState <> 4 И (ТаймАут=0 ИЛИ ТекущаяДата()-Начало<ТаймАут) Цикл
бфДиалоги.ксОбработкаПрерыванияПользователя();
КонецЦикла;
//Сохраняем во временный файл
обСохранитьДвоичныйБуферВФайл(Соединение.responseBody, ИмяВременногоФайла);
Соединение.open("POST", "http://mamba.ru/my");
Соединение.send("login=xxx&password=&&&");
Функция обСохранитьДвоичныйБуферВФайл(Буфер, ИмяФайла) Экспорт
Поток = Новый COMОбъект("ADODB.Stream");
Поток.Type = 1; //Бинарный
Поток.Mode = 3;
Поток.Open();
Поток.Write(Буфер);
Поток.SaveToFile(ИмяФайла);
Поток.Close();
КонецФункции
Код 1C v 8.х НТТР = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяФайлаОтвета = КаталогВременныхФайлов() + "filename.tmp";
НТТР.open("GET", "www.google.com",0,,);
НТТР.send();
StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2);
ConnectModeEnum = Новый Структура(
"adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone,
|adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive,
|adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2);
SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2);
StreamOut = Новый COMОбъект("ADODB.Stream");
StreamOut.Type = StreamTypeEnum.adTypeBinary;
StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись
StreamOut.Open(); //Открыли на чтение и запись
StreamOut.Write(НТТР.responseBody);
StreamOut.SaveToFile(ИмяФайлаОтвета, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
StreamOut.Close();
И даже не этом сайте есть статья : Парсер сайта связного на 1С
Нужен парсер сайта в 1С!? - Обращайтесь, контакты в
профиле Категория:
Работа с Интернет, Почтой (Mail), FTP Авто добавление обработки в справочник Внешних обработок Чтобы не изменять типовую конфигурацию приходится использовать типовой механизм внешних печатных форм и обработок. Данный код проверяет - добавлена ли открываемая обработка в конфигурацию, если нет - задает вопрос и при положительном ответе - автоматически добавляет в конфигурацию:
Код 1C v 8.х ПолноеИмяФайлаОбработки = ЭтотОбъект.ИспользуемоеИмяФайла;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Наименование", ЭтотОбъект.Метаданные().Синоним);
Запрос.УстановитьПараметр("ВидОбработки", Перечисления.ВидыДополнительныхВнешнихОбработок.ПечатнаяФорма);
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ВнешниеОбработки.Ссылка
|ИЗ
| Справочник.ВнешниеОбработки КАК ВнешниеОбработки
|ГДЕ
| ВнешниеОбработки.Наименование = &Наименование
| И ВнешниеОбработки.ВидОбработки = &ВидОбработки";
Если НЕ Запрос.Выполнить().Пустой() Тогда Возврат; КонецЕсли;
Если Вопрос("Зарегистрировать обработку как печатную форму для документа ""ЗарплатаКВыплатеОрганизаций"" в справочнике ""Внешние обработки""?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда
ВнешняяОбработка = Справочники.ВнешниеОбработки.СоздатьЭлемент();
ВнешняяОбработка.Наименование = ЭтотОбъект.Метаданные().Синоним;
ВнешняяОбработка.ХранилищеВнешнейОбработки = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ПолноеИмяФайлаОбработки));
ВнешняяОбработка.ВидОбработки = Перечисления.ВидыДополнительныхВнешнихОбработок.ПечатнаяФорма;
ВнешняяОбработка.Комментарий = "Внешняя печатная форма для документа ""ЗарплатаКВыплатеОрганизаций""";
ВнешняяОбработка.КомментарийКФайлуИсточнику = ПолучитьКомментарийКФайлу(ПолноеИмяФайлаОбработки);
НовСтр = ВнешняяОбработка.Принадлежность.Добавить();
НовСтр.ПредставлениеОбъекта = "Документ ""Зарплата к выплате организаций""";
НовСтр.ХранилищеВнешнейОбработки = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ПолноеИмяФайлаОбработки));
НовСтр.СсылкаОбъекта = Документы.ЗарплатаКВыплатеОрганизаций.ПустаяСсылка();
Попытка
ВнешняяОбработка.Записать();
Исключение
Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
Категория:
1С Общие вопросы - Обычные формы Некоторые особенности работы с настройками прав доступа пользователей в типовых конфигурациях на УФ Разработчики в управляемых приложениях применили новый механизм настройки прав доступа, о которых и пойдет речь.
Будут перечислены все те грабли, которые собрал автор, чтобы вы о них знали.
Наверняка, уже все знают, что из себя представляет новая система, поэтому предистория вкрадце:
Как было раньше( в обычном приложении):
Есть документ. Есть Роли - ПолныеПрава, ДокументНетДоступа, ДокументТолькоЧтение, ДокументЧтениеИРедактирование. В конфигураторе(аналогичный механизм в реж предприятия) вы выставляете пользователям эти роли и у них появляются соответствующие права доступа на документ. Все просто и скучно и даже зевать хочется.
С введением управляемого приложения разработчики решили усложнить(читается как расширить) настройки прав доступа.
Теперь:
Вводная та же. Чтобы дать пользователю какие-то права на документ - сначала вам необходимо создать элемент справочника Профили групп доступа. Это некий агрегирующий(суммирующий значения) объект, который объединяет роли в группы ролей. Теоритически таких профилей можно создать сколько угодно много с различным набором ролей( N*(n-1), где N - количество ролей), но на практике количество профилей определяется количеством должностных обязанностей пользователей в организации и их гораздо меньше, чем ролей.
Создаем профили Бесправный(с ролью ДокументНетДоступа), Аудитор(с ролью ДокументТолькоЧтение), Бухгалтер(с ролью ДокументЧтениеИРедактирование).
Чтобы "привязать" эти профили к пользователям - нужно создать элементы справочника ГруппыДоступа. В типовых они создаются автоматически, когда вы отмечаете галочками профили для пользователя. Этот справочник соединяет профиль и пользователя(или нескольких пользователей).
При записи этого элемента справочника система автоматически добавляет роли (из профиля) в роли пользователя. Поэтому не стоит напрямую редактировать роли в конфигураторе, как раньше - при редактировании прав в Предприятии все роли в конфигураторе будут обновлены на роли из профилей пользователя. Кроме того, будет наблюдаться явное противоречение между набором профилей с ролями и ролями, установленными в конфигураторе.
Как хранятся роли в Профиле групп доступа, спросите вы. Ведь роли - это объекты МД, это не ссылочные типы. Отвечаю - для этого(и не только) разработчики создали служебный справочник ИдентификаторыОбъектовМетаданных, в котором хранится( в иерархии!) имена, синонимы, значения пустых ссылок всех объектов МД. Если вы хотите создать Профиль программно и добавить в него роль, то код примерно будет таким:
Код 1C v 8.2 УП РодительРоли = Справочники.ИдентификаторыОбъектовМетаданных.НайтиПоНаименованию("Роли");//ничего страшного искать по наименованию,
//справочник - служебный и непосредственного редактрования в нем нет
ИдентификаторМоейРоли = Справочники.ИдентификаторыОбъектовМетаданных.НайтиПоРеквизиту("Имя","МояРоль",РодительРоли);
Если ЗначениеЗаполнено(ИдентификаторМоейРоли) Тогда
НайденныйИдентификаторМоейРоли = МойПрофиль.Роли.Найти(ИдентификаторМоейРоли );
Если НайденныйИдентификаторМоейРоли= неопределено тогда
НовСтрока = МойПрофиль.Роли.Добавить();
НовСтрока.Роль = ИдентификаторМоейРоли;
КонецЕсли;
КонецЕсли;
Но если мы добавили новую роль в конфигурации, то как она попадет в справочник? Хороший вопрос. У справочника ИдентификаторыОбъектовМетаданных есть метод, позволяющий обновлять его данные. это:
Код 1C v 8.2 УП Справочники.ИдентификаторыОбъектовМетаданных.ОбновитьДанныеСправочника(ИСТИНА,ЛОЖЬ,ЛОЖЬ);//ЕстьИзменения, ЕстьУдаленные, ТолькоПроверка
Процедуру следует запускать каждый раз, когда вы вносите изменения в метаданные, особенно когда изменяете роли, объекты, связанные с новыми ролями.
Отлично. Роль добавили, идентификаторы обновили.
Но обратная связь не работает - вы в режиме предприятия назначили пользователю профиль( с созданием группы доступа), а роль у пользователя в конфигураторе не добавилась! Что делать?
За синхронизацию ролей/профилей отвечает константа ПараметрыРаботыПользователей. Если роли не обновляются в конфигураторе, следует обновить её значение:
Код 1C v 8.2 УП Константы.ПараметрыРаботыПользователей.СоздатьМенеджерЗначения().ОбновитьОбщиеПараметры();
Хорошо, скажите вы. А как быть, если я хочу создать группы доступа программно? Да не вопрос. Единственное ограничение - не допускаются дубли связок Профиль-Пользоваль в группах доступа. Примерный код будет таким:
Код 1C v 8.2 УП //МойПрофиль - профиль, который мы хотим добавить пользователю МойПользователь
Если МойПрофиль = Справочники.ПрофилиГруппДоступа.Администратор Тогда // если мы хотим пользователю дать роль Администратора,
//то нельзя создавать новую группу доступа, надо редактировать предопределенную Администраторы
ГруппаДоступаАдм = Справочники.ГруппыДоступа.Администраторы;
Если ГруппаДоступаАдм.Пользователи.Найти(МойПользователь) = неопределено Тогда
ГруппаДоступаАдмОб= ГруппаДоступаАдм.ПолучитьОбъект();
НовСтрока = ГруппаДоступаАдмОб.Пользователи.Добавить();
НовСтрока.Пользователь = МойПользователь;
ГруппаДоступаАдмОб.Записать();
КонецЕсли;
Иначе // все прочие профили, кроме Администратора
Запрос = новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|ГруппыДоступа.Ссылка
|ИЗ
|Справочник.ГруппыДоступа КАК ГруппыДоступа
|ГДЕ
|ГруппыДоступа.Профиль = &Профиль
|И (ГруппыДоступа.Пользователь = &Пользователь
|ИЛИ ГруппыДоступа.Пользователи.Пользователь = &Пользователь)
|И НЕ ГруппыДоступа.ПометкаУдаления ";
Запрос.УстановитьПараметр("Профиль",МойПрофиль);
Запрос.УстановитьПараметр("Пользователь",МойПользователь);
Выборка = Запрос.Выполнить().Выбрать();
Если НЕ Выборка.Следующий() тогда //нет такого профиля, надо создать
МояГруппаДоступаОб = справочники.ГруппыДоступа.СоздатьЭлемент();
МояГруппаДоступаОб.Наименование = Строка(МойПрофиль);
МояГруппаДоступаОб.Пользователь = мойПользователь;
Нов = МояГруппаДоступаОб.Пользователи.Добавить();
Нов.Пользователь = МойПользователь;
МояГруппаДоступаОб.Профиль = МойПрофиль;
МояГруппаДоступаОб.Записать();
КонецЕсли; //Нет такого профиля
КонецЕсли;//профиль Администратор
После выполнения этого кода, если все, что нужно обновлено - типовая конфигурация добавит пользователю роли.
Раз уж пошли по программному пути, вот код, который добавляет пользователя в справочник Пользователи и ПользователяИБ в ПользователиИнформационнойБазы:
Код 1C v 8.2 УП ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
ПользовательИБ.имя = "Иванов";
ПользовательИБ.ПолноеИмя = "Иванов Иван Иванович";
ПользовательИБ.АутентификацияСтандартная = ИСТИНА;
ПользовательИБ.Пароль = "";
ПользовательИБ.записать();
Пользователь = Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ",ПользовательИБ.УникальныйИдентификатор));
если Пользователь.Наименование = "" Тогда
//создаем пользователя
ПользовательОб = Справочники.Пользователи.СоздатьЭлемент();
ОписаниеПользователяИБ = Пользователи.НовоеОписаниеПользователяИБ();
ЗаполнитьЗначенияСвойств(ОписаниеПользователяИБ,ПользовательИБ);
ОписаниеПользователяИБ.УникальныйИдентификатор = Соединение.NewObject("УникальныйИдентификатор",ПользовательИБ.УникальныйИдентификатор);
ПользовательОб.Наименование = ОписаниеПользователяИБ.ПолноеИмя;
ОписаниеПользователяИБ.Вставить("Действие","Записать");
ПользовательОб.ДополнительныеСвойства.Вставить("ОписаниеПользователяИБ",ОписаниеПользователяИБ);
ПользовательОб.записать();
КонецЕсли;
Если вы добавляете не программно, то добавлять нужно из режима Предприятия - тогда пользовательИБ у вас сам создатся.
И если раньше, в обычном приложении, достаточно будет добавить польз в конфигураторе - и при заходе в Предприятие, этот польз сам создавался в спр Пользователи, то с управляемым приложением такой фокус не прокатит - система не даст зайти под пользователемИБ, которого нет в справочнике Пользователи.
Автор: Stim - Источник
Категория:
Управляемое приложение, Тонкий клиент Как заполнить табличную часть формы программно? Нужно по кнопке Заполнить - сформировать данные для заполнения табличных частей и заполнить их.
Форма имеет вид:
Рядом с кнопкой Записать и закрыть добавлена кнопка Заполнить документ , код ее команды:
Код 1C v 8.2 УП // Код заполнения ТЧ
&НаСервере
Процедура ЗаполнитьДокументНаСервере()
ДокОбъект = РеквизитФормыВЗначение("Объект");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ЗаказНаПроизводствоПродукция.Ссылка КАК ЗаказНаПроизводство,
| СпецификацииОперации.Операция,
| СпецификацииОперации.W1C_КоличествоОпераций,
| СпецификацииОперации.W1C_СтоимостьОднойОперации
|ПОМЕСТИТЬ втЗаказОперацияСумма
|ИЗ
| Документ.ЗаказНаПроизводство.Продукция КАК ЗаказНаПроизводствоПродукция
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Спецификации.Операции КАК СпецификацииОперации
| ПО ЗаказНаПроизводствоПродукция.Спецификация = СпецификацииОперации.Ссылка
|ГДЕ
| ЗаказНаПроизводствоПродукция.Ссылка В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| W1C_ОтчетПоВыработкеНачисления.ЗаказПроизводство
| ИЗ
| Документ.W1C_ОтчетПоВыработке.Начисления КАК W1C_ОтчетПоВыработкеНачисления
| ГДЕ
| W1C_ОтчетПоВыработкеНачисления.Ссылка.Дата МЕЖДУ &ДатаН И &ДатаК)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| W1C_ОтчетПоВыработкеНачисления.Ссылка.Организация,
| W1C_ОтчетПоВыработкеНачисления.Ссылка.Сотрудник,
| W1C_ОтчетПоВыработкеНачисления.ЗаказПроизводство,
| W1C_ОтчетПоВыработкеНачисления.Операция,
| W1C_ОтчетПоВыработкеНачисления.КоличествоПродукции КАК Количество,
| втЗаказОперацияСумма.W1C_СтоимостьОднойОперации КАК Цена,
| W1C_ОтчетПоВыработкеНачисления.Ссылка КАК ОтчетПоВыработке,
| втЗаказОперацияСумма.W1C_СтоимостьОднойОперации * W1C_ОтчетПоВыработкеНачисления.КоличествоПродукции КАК Сумма
|ИЗ
| Документ.W1C_ОтчетПоВыработке.Начисления КАК W1C_ОтчетПоВыработкеНачисления
| ЛЕВОЕ СОЕДИНЕНИЕ втЗаказОперацияСумма КАК втЗаказОперацияСумма
| ПО W1C_ОтчетПоВыработкеНачисления.ЗаказПроизводство = втЗаказОперацияСумма.ЗаказНаПроизводство
| И W1C_ОтчетПоВыработкеНачисления.Операция = втЗаказОперацияСумма.Операция
|ГДЕ
| W1C_ОтчетПоВыработкеНачисления.Ссылка.Дата МЕЖДУ &ДатаН И &ДатаК
| И W1C_ОтчетПоВыработкеНачисления.Ссылка.Организация = &Организация";
Запрос.УстановитьПараметр("ДатаК", КонецМесяца(ДокОбъект.ПериодРегистрации));
Запрос.УстановитьПараметр("ДатаН", НачалоМесяца(ДокОбъект.ПериодРегистрации));
Запрос.УстановитьПараметр("Организация", ДокОбъект.Организация);
РезультатЗапроса = Запрос.Выполнить();
ДокОбъект.Рассчет.Загрузить(Запрос.Выполнить().Выгрузить());
ОбновитьВыплату(ДокОбъект); //заполним данными вторую ТЧ
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
&НаСервере
Процедура ОбновитьВыплату(ДокОбъект)
врТЗ = ДокОбъект.Рассчет.Выгрузить();
врТЗ.свернуть("Сотрудник","Сумма");
ДокОбъект.Начисления.Загрузить(врТЗ);
КонецПроцедуры
Второй вариант заполнения: Имеем ТЧ на форме, которую необходимо программно заполнить
и код в модуле документа:
Код 1C v 8.2 УП &НаСервере
Процедура НайтиТопливоф()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СУММА(ПродажаТоплива.Номер) КАК Номер,
| ПродажаТоплива.ТипТоплива,
| СУММА(ПродажаТоплива.Количество) КАК Количество,
| СУММА(ПродажаТоплива.СуммаСНДС) КАК СуммаСНДС
|ИЗ
| Документ.ПродажаТоплива КАК ПродажаТоплива
|ГДЕ
| ПродажаТоплива.Цена <= &Цена
|
|СГРУППИРОВАТЬ ПО
| ПродажаТоплива.ТипТоплива";
Запрос.УстановитьПараметр("Цена", Объект.Цена);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Объект.ТЧ.Очистить();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
НовСтр = Объект.ТЧ.Добавить();
ЗаполнитьЗначенияСвойств(НовСтр, ВыборкаДетальныеЗаписи); //при условии что имена полей ТЧ и выборки совпадают
КонецЦикла;
КонецПроцедуры
Категория:
Управляемое приложение, Тонкий клиент Загрузить данные в 1с из текстового файла с разделителями В этой статье я расскажу, как загружать данные в 1с 8 из простейших текстовых файлов с разделителями. Обычно они имеют расширение csv (Comma-Separated Values). Т. е. название подразумевает, что в каждой строке такого текстового файла значения разделены запятой. Но на самом деле, запятую, в качестве разделителя, использовать не надёжно. Поэтому применяют другие разделители, которые в обычном тексте встречаются редко. Это могут быть символы «^», «~»,«|» и другие. Итак, наша задача состоит в том, чтобы загрузить имеющуюся в csv файле информацию в базу данных 1с. Например, в файле будут содержаться товары интернет - магазина. В качестве образца, я взял выгрузку из магазина на скрипте virtuemart. Посмотрим, как выглядит файл.
Привожу две первых строки из него:
Код ~product_sku~^~category_path~^~product_name~^~product_desc~
~20~^~Книги/Электронные книги~^~Amazon Kindle 4 Touch~^~<p>Популярная электронная книга с ч/б экраном 6", электронной бумагой E-Ink Pearl, разрешением 600x800 пикс. с 16 - ю оттенками серого.</p>~
Посмотрим на файл.
Первая строка служебная. В ней описан формат нашего файла. Т. е. в какой ячейке, что находится. Однако, имейте в виду, что такой строки может и не быть.
Ячейки образуются при помощи разделителя «^», а данные в ячейках обрамляются символом «~».
В любой конфигурации 1с есть иерархический справочник товаров. В него и будем загружать информацию.
Создадим внешнюю обработку. Добавим строковый реквизит «путьКФайлуЗагрузки» для хранения имени файла. Добавим на форму поле ввода, связанное с данным реквизитом. Включим в свойствах поля ввода кнопку выбора и создадим обработчик события «НачалоВыбора» и напишем в нём такой код:
Код 1C v 8.х Процедура путьКФайлуЗагрузкиНачалоВыбора(Элемент, СтандартнаяОбработка)
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
Фильтр = "Comma separated file (*.csv)|*.csv";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";
Если ДиалогОткрытияФайла.Выбрать() Тогда
путьКФайлуЗагрузки = ДиалогОткрытияФайла.ПолноеИмяФайла;
КонецЕсли;
КонецПроцедуры
Т. о. мы организовали диалог для выбора файла в нашей обработке.
Хорошо. Теперь, для удобства и наглядности я предлагаю создать временную табличку, в которую мы загрузим текстовый файл, а уже после её заполнения - будем осуществлять загрузку в базу 1с. Для этого, на форму добавим табличное поле «табЗагрузки», с типом значения «ТаблицаЗначений» и командной панелью. В панели поместим кнопку «Заполнить» и создадим обработчик её нажатия «КоманднаяПанель1Заполнить». Также для элемента универсальности, добавим в обработку два строковых реквизита «символОграничения» и «разделительПолей». В них мы будем хранить «^», и «~». Можно в теле модуля формы осуществить их начальную инициализацию:
разделительПолей = "^";
символОграничения = "~";
Это позволит пользователю задать свои значения и при желании сохранить настройку, которая впоследствии не затрется нашей инициализацией.
Код 1C v 8.х Процедура КоманднаяПанель1Заполнить(Кнопка)
Если табЗагрузки.Количество() > 0 И Вопрос("Таблица будет очищена. Вы уверены?",РежимДиалогаВопрос.ДаНет)
= КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;
ЗаполнитьТаблицу();
КонецПроцедуры
Процедура ЗаполнитьТаблицу()
текст = Новый ТекстовыйДокумент;
Попытка
//обязательно устанавливаем кодировку, в которой наш файл
текст.Прочитать(путьКФайлуЗагрузки,КодировкаТекста.UTF8);
Исключение
Сообщить("Не удалось прочитать файл: "
+ ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
Возврат;
КонецПопытки;
табЗагрузки.Очистить();//очищаем таблицу
табЗагрузки.Колонки.Очистить();//удаляем колонки, так как их состав мог измениться
квоСтрок = текст.КоличествоСтрок();
Если Не квоСтрок > 0 Тогда
Сообщить("Файл пустой",СтатусСообщения.Внимание);
Возврат;
КонецЕсли;
//получаем первую строку с форматом файла
стрТекста = текст.ПолучитьСтроку(1);
//преобразуем строку в массив при помощи функции общего модуля, которая есть в типовых
//ниже я дам её код, на случай, если нет
масЗначСтр = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(стрТекста,разделительПолей);
//добавляем две служебные колонки
//для возможности отказаться от загрузки определенной строки
табЗагрузки.Колонки.Добавить("не_загружать",Новый ОписаниеТипов("Булево"),"Не загружать");
//для удобства вывода комментариев с указанием номера строки по ходу загрузки
табЗагрузки.Колонки.Добавить("номер_строки",Новый ОписаниеТипов("Число",
Новый КвалификаторыЧисла(10,0,ДопустимыйЗнак.Неотрицательный)),"Номер строки");
//формируем колонки нашей таблицы
Для каждого зн Из масЗначСтр Цикл
//убираем лишний символОграничения
значение = СтрЗаменить(зн,символОграничения,"");
кол = табЗагрузки.Колонки.Добавить(значение,Новый ОписаниеТипов("Строка"));
КонецЦикла;
//создаём колонки в табличном поле
ЭлементыФормы.табЗагрузки.СоздатьКолонки();
//начиная со второй строки читаем строки файла, раскладывая их в массив
Для номСтр = 2 По квоСтрок Цикл
стрТекста = текст.ПолучитьСтроку(номСтр);
масЗначСтр = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(стрТекста,разделительПолей);
//добавляем новую строку в таблицу
новСтр = табЗагрузки.Добавить();
новСтр.номер_строки = номСтр;
//начиная с третьей колонки производим установку значений в колонки
номЗнач = 2;
Для каждого зн Из масЗначСтр Цикл
новСтр[номЗнач] = СтрЗаменить(зн,символОграничения,"");
номЗнач = номЗнач + 1;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функцию разложения строки с разделителями в массив можно разместить как в одном из общих модулей, так и непосредственно в обработке.
Код 1C v 8.х Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт
МассивСтрок = Новый Массив();
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока Истина Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока Истина Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
КонецФункции
Отлично. В итоге, после заполнения, получим примерно такую картинку:
Теперь приступим непосредственно к загрузке товаров. Рядом с кнопкой «заполнить» добавим кнопку «загрузить» и добавим обработчик её нажатия «КоманднаяПанель1Загрузить», а также добавим реквизит «ПапкаЗагрузкиВыгрузкиТоваров» с типом вашего справочника товаров для опциональной их загрузки в определенную папку. Текст обработчика будет такой:
Код 1C v 8.х Процедура КоманднаяПанель1Загрузить(Кнопка)
Если Вопрос("Вы уверены, что хотите загрузить файл?", РежимДиалогаВопрос.ДаНет)
= КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;
ВсегоСтрок = табЗагрузки.Количество();
номСтр = 1;
Для каждого стрТЗ Из табЗагрузки Цикл
Состояние("Обработано: " + Окр(номСтр * 100 / ВсегоСтрок) + "%");
номСтр = номСтр + 1;
ОбработкаПрерыванияПользователя();
//если пользователь установил не_загружать = Истина, пропускаем
Если стрТЗ.не_загружать Тогда
Продолжить;
КонецЕсли;
объект1С = вернутьТовар(стрТЗ);
Если объект1С = Неопределено Тогда
Возврат;
КонецЕсли;
Если Не ЗаписатьЭлементСпр(объект1С) Тогда
Сообщить("Загрузка прервана!",СтатусСообщения.ОченьВажное);
Возврат;
КонецЕсли;
//помечаем запись, как загруженную
стрТЗ.не_загружать = Истина;
КонецЦикла;
КонецПроцедуры
В приведенном коде две новые функции «вернутьТовар» и «ЗаписатьЭлементСпр». Вот их текст:
Код 1C v 8.х Функция вернутьТовар(стрТабФайла)
Артикул = стрТабФайла.product_sku;
Если Не ЗначениеЗаполнено(Артикул) Тогда
Сообщить("В строке " + стрТабФайла.номер_строки + " не заполнен product_sku",
СтатусСообщения.ОченьВажное);
Возврат Неопределено;
КонецЕсли;
Запрос = Новый Запрос("ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул");
Запрос.УстановитьПараметр("Артикул",Артикул);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка.ПолучитьОбъект();
Иначе
ЭтоНовый = Истина;
объект1С = Справочники.Номенклатура.СоздатьЭлемент();
объект1С.Артикул = Артикул;
объект1С.Наименование = стрТабФайла.product_name;
объект1С.Родитель = вернутьРодителяТовара(стрТабФайла.category_path);
Возврат объект1С;
КонецЕсли;
КонецФункции // вернутьТовар()
Функция ЗаписатьЭлементСпр(Спр)
Попытка
Спр.Записать();
Исключение
Сообщить("При записи элемента справочника " + Спр + " возникла ошибка: " + ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции // ЗаписатьЭлементСпр()
И осталась последняя новая функция для обработки родителя товара вернутьРодителяТовара. Текст её смотрите ниже. Комментарии по тексту.
Код 1C v 8.х Функция вернутьРодителяТовара(стрКатегории)
//главный родитель - заполненная в обработке папка
Родитель = ПапкаЗагрузкиВыгрузкиТоваров;
//строку категории раскладываем в массив используя разделитель /
масРодителей = РазложитьСтрокуВМассивПодстрок(стрКатегории,"/");
Для каждого Род Из масРодителей Цикл
//если папку не находим, создаём и назначаем в качестве родителя
//следующей и т. д. В случае проблем выдаём прекращаем загрузку
РодСс = Справочники.Номенклатура.НайтиПоНаименованию(Род,Истина);
Если РодСс.Пустая() Тогда
НовРод = Справочники.Номенклатура.СоздатьГруппу();
НовРод.Наименование = Род;
НовРод.Родитель = Родитель;
Если Не ЗаписатьЭлементСпр(НовРод) Тогда
Возврат Неопределено;
КонецЕсли;
Родитель = НовРод.Ссылка;
Иначе
Родитель = РодСс;
КонецЕсли;
КонецЦикла;
Возврат Родитель;
КонецФункции //
Все. Конечно, в реальной жизни еще много чего нужно будет дописать, но не все сразу. Такой шаблон можно использовать как отправную точку.
Скачивать файлы может только зарегистрированный пользователь!
Успехов в разработке!
Источник Категория:
Текстовый документ Парсер сайта на 1С В этой статье я постараюсь описать процесс парсинга сайтов средствами 1С с примером.
Это статья не является инструкцией к применению, а лишь демонстрирует возможности 1С.
Что мы имеем?
1. Сайт в интернете, на котором располагается список товаров. В моем случае – это интернет магазин салона «Связной»
2. Понимание основ сайтостроения… хотя бы знание HTML тегов
3. Умение кодить в 1С 8
Для начала парсинга стоит определиться с тем что мы хотим спарсить и какая у нас будет иерархия. В моем случае это категория сотовых телефонов. Верхний уровень иерархии будет производители. Почему именно так? Потомы что я так захотел. Вы же вправе использовать любую иерархию.
Далее нам будут интересны такие поля как: Наименование, Цена, Картинка и Описание... ну и пожалую захватим операционную систему, чтобы пример получился более наглядным.
1. Создаем внешнюю обработку. Те, кто не знают как это сделать - дальше могут не читать
2. Создаем форму обработки с командной панелью снизу и сверху (они могут быть полезными)
3. Размещаем на ней Панель и обзываем первую страницу "СамСайт"
4. Кладем на страницу "СамСайт" ПолеHTMLДокумента и обзываем его к примеру "Сайт"
5. Переименовываем кнопку "Выполнить", которая находится на нижней панели в "Загрузить сайт"
6. Описываем процедуру нажатия на эту кнопку так:
Код 1C v 8.х ЭлементыФормы.Сайт.Перейти("http://www.svyaznoy.ru/catalog/phone/224"); //Категория с мобильными телефонами
7. Проверяем работу нашей обработки. У меня появился сайт связного. А у Вас?
Дальше сложнее. Все еще хочешь парсить сайты? Тогда читай:
Сам парсинг сайта заключается в обходе всех элементов загруженной страницы, выдергивания необходимой информации и запихивания их в табличную часть. Для этого:
1. Создадим табличную часть "Производители" с реквизитами "Отметка" (Булево), "Наименование" (Строка 100) и "Ссылка" (Строка 300).
2. Добавляем еще одну страницу на панели и обзываем ее "Производители"
3. Размещаем на этой странице одноименную табличную часть
4. Добавляем на нижней панели кнопку "Заполнить производителей" с кодом:
Код 1C v 8.х Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
Если Стр.tagName = "H1" и Стр.innerText = "Производители" Тогда
Для Каждого опСтр из Стр.nextSibling.children Цикл
новСтр = Производители.Добавить();
новСтр.Наименование = опСтр.innerText;
новСтр.Ссылка = опСтр.firstChild.href;
КонецЦикла;
Возврат;
КонецЕсли;
КонецЦикла;
Здесь напрашиваются небольшие пояснения:
tagName - имя HTML тега в HTML документе
nextSubling - следующий элемент HTML документа от текущего
children - список дочерних элементов
firstChild - первый дочерний элемент от текущего
5. Проверям. При проверке важно, находиться на странице "СамСайт", чтобы заполнять производителей
Производители заполнены. Теперь к самим телефонам
1. Создаем табличную часть "Товары" с реквизитами "Производитель" (Строка 100), "Наименование" (Строка 100), "Цена" (Число 10,2), "Картинка" (Строка 300), "Описание" (Строка Неограниченная), "ОС" (строка 100), "Ссылка" (Строка,300)
2. Добавляем еще одну страницу на панели и обзываем ее "Товары"
3. Размещаем на этой странице одноименную табличную часть
4. Добавляем на нижней панели кнопку "Заполнить товары" с кодом:
Код 1C v 8.х Для Каждого Стр из Производители Цикл
//Если отметку сняли - то не трогаем этого производителя
Если Не Стр.Отметка Тогда
Продолжить;
КонецЕсли;
Форма = ПолучитьФорму("ФормаТоваров");
Форма.ЭлементыФормы.Сайт.Перейти(Стр.Ссылка);
Форма.ТекущийПроизводитель = Стр;
Форма.ОткрытьМодально();
КонецЦикла;
5. Создаем форму обработки "ФормаТоваров"
6. Кладем на "ФормаТоваров" ПолеHTMLДокумента и называем его "Сайт"
7. На событие ДкументСформирован у ПоляHTMLДокумента пишем код:
Код 1C v 8.х Если ЭлементыФормы.Сайт.Документ.body.all.length>1 Тогда
ГрузимТовары();
КонецЕсли;
8. Создаем переменную в модуле формы
перем ТекущийПроизводитель Экспорт;
9. Создаем процедуру ГрузимТовары():
Код 1C v 8.х Процедура ГрузимТовары()
Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
Если Стр.className = "ct_desc cleared" Тогда
новСтр = Товары.Добавить();
Для Каждого опСтр из Стр.children Цикл
Если опСтр.className = "pic_and_comp" Тогда
новСтр.Картинка = СтрЗаменить(Сред(опСтр.firstChild.style.backgroundImage,5),")","")
КонецЕсли;
Если опСтр.className = "name" Тогда
новСтр.Наименование = опСтр.innerText;
новСтр.Ссылка = опСтр.firstChild.href;
КонецЕсли;
Если опСтр.className = "price" Тогда
новСтр.Цена = Число(СтрЗаменить(СтрЗаменить(опСтр.innerText,"-","")," ",""));
КонецЕсли;
Если опСтр.className = "desc" Тогда
новСтр.Описание = опСтр.innerText;//опСтр.innerHTML - если нужно вместе с тегами
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Закрыть();
КонецПроцедуры
10. Проверям. Все работает.
Дело осталось за "операционной системой" и еще надо загрузить картинки. Давайте по порядку. Чтобы получить "ОС" нам надо открыть этот товар и считать "ОС" оттуда. Для этого делаем следующее:
1. Добавляем на нижней панели кнопку "Доп Инфо" с кодом:
Код 1C v 8.х Для Каждого Стр из Товары Цикл
Форма = ПолучитьФорму("ФормаДопИнфо");
Форма.ЭлементыФормы.Сайт.Перейти(Стр.Ссылка);
Форма.ТекущийТовар = Стр;
Форма.ОткрытьМодально();
КонецЦикла;
2. Создаем форму обработки "ФормаДопИнфо"
3. Кладем на "ФормаДопИнфо" ПолеHTMLДокумента и называем его "Сайт"
4. На событие ДкументСформирован у ПоляHTMLДокумента пишем код:
Код 1C v 8.х Если ЭлементыФормы.Сайт.Документ.body.all.length>1 Тогда
ГрузимДопИнфо();
КонецЕсли;
5. Создаем переменную в модуле формы
перем ТекущийТовар Экспорт;
6. Создаем процедуру ГрузимДопИнфо():
Код 1C v 8.х Процедура ГрузимДопИнфо();
Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
Если Стр.className = "card_spec" Тогда
Для Каждого опСтр из Стр.children Цикл
Если Найти(опСтр.innerText,"Операционная система:") Тогда
ТекущийТовар.ОС = СокрЛП(СтрЗаменить(опСтр.innerText,"Операционная система:",""));
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Закрыть();
КонецПроцедуры
7. Проверяем и переходим к последнему пункту
Заметили как похожи две последние инструкции? То-то же. Стремился к универсальности. Ну и наконец последний этап - Сохраним все изображения к примеру на диск "С" в папку "связной". Поехали
1. Добавляем на нижней панели кнопку "Сохранить Картинки" с кодом:
Код 1C v 8.х Для Каждого Стр из Товары Цикл
путьСамФайл = Лев(Стр.Картинка,Найти(Стр.Картинка,".jpg/") + 3);
самФайл = СтрЗаменить(СтрЗаменить(ПутьСамФайл,"http://static.svyaznoy.ru/upload/iblock/",""),"/","");
Стр.Картинка = СохранитьКартинкуСайта("C:\Svyaznoy",ПутьСамФайл,СамФайл);
КонецЦикла;
2. Добавляем функцию СохранитьКартинкуСайта:
Код 1C v 8.х Функция СохранитьКартинкуСайта(КаталогСохранения,КартинкаНаСайте,КартинкаУНас)
ИмяФайлаКартинки = КаталогСохранения + "\" + КартинкаУНас;
ГетЗапрос = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
ГетЗапрос.SetTimeouts(10000, 10000, 10000, 10000);
БазовыйУРЛ = КартинкаНаСайте;
Хидер1 = "Content-Type";
Хидер2 = "image/jpg"; // Тип рисунка.
ГетЗапрос.Open("GET", БазовыйУРЛ, False); // Синхронный режим.
ГетЗапрос.setRequestHeader(Хидер1, Хидер2);
ГетЗапрос.Send();
СтатусОтправки = ГетЗапрос.status;
Если СтатусОтправки <> 200 Тогда
Сообщить("Ошибка отправки запроса на: "
+ КартинкаНаСайте);
Возврат "";
КонецЕсли;
Стрим = Новый COMОбъект("ADODB.Stream");
Стрим.Mode = 3;
Стрим.Type = 1;
Стрим.Open();
Стрим.Write(ГетЗапрос.responseBody);
Стрим.SaveToFile(ИмяФайлаКартинки, 2);
Стрим.Close();
Возврат ИмяФайлаКартинки;
КонецФункции
На этом наша эпопея с парсингом закончена. Это всего лишь пример того, как это можно сделать. Приложив сюда немного своего кода - можно сделать парсер для любого сайта.
Скачивать файлы может только зарегистрированный пользователь!
Имея парсер 1С - я могу спарсить все, кроме этого парсера. Имя два парсера 1С - я могу спарсить все
Автор:
opx Категория:
Работа с Интернет, Почтой (Mail), FTP Использование Web-сервисов для синхронизации баз данных в режиме online 1с 8.х Часто при ведении учета в различных конфигурациях 1с возникает необходимость выполнения обмена данных. Для решения этой задачи принято использовать Универсальный обмен данными XML или другие внешние обработки, общим у которых является использование текстовых файлов посредников.
Я предлагаю использовать Web-сервисы 1с.
В чем необходимость обмена: Обмен данными между базами требуется для исключения дублирующих вводов одних и тех же данных в различных учетных системах.
В чем необходимость обмена в режиме online: Обмен в онлайн режиме требуется когда функции учета комплекса учетных систем выполняются в разных учетных системах.
1. Например компания использует: CRM систему учета, для ведения учета взаимоотношений с клиентами; БП 2.0 для ведения взаиморасчетов с клиентами в разрезе счетов; Счета выставляемые клиентам создаются в торговой базе, а оформление заказов поставщикам исходя из потребности клиентов в базе ориентированной на работу с пайсами поставщиков. При таком разделенном построении учета, для выставления счета в одной из баз к примеру требуется завести карточку клиента в другой базе с тем чтобы данные о контрагенте так же были доступны в базе со счетами.
2. Помимо синхронизации первичных данных, может возникнуть необходимость построения сводного отчета по данным из нескольких баз, что тоже потребует обращения к внешним данным в online режиме.
Вариант автоматизации данного процесса с использованием файлов обмена, потребует подключения обработчика ожиданий, что сможет обеспечить обмен данными только с установленной задержкой времени обмена, кроме того любая обработка ожидания будет не эффективно использовать машинное время.
Обращение к Web сервисам, возможно при возникновении любых событий (ПриЗаписи, ПриПроведении, при нажатии кнопки и т.д.). при этом не возникнет ни какой задержки реакции информационной базы к которой происходит обращение, (в отличие от запуска еще одного приложения 1с в качестве com объекта).
Итак рассмотрим вариант реализации синхронизации элементов справочников, начнем с наиболее простого со справочника "Товары" в базах "Продажи" и "Закупки". Синхронизация для начала будет односторонней, предположим что перечень товаров заводится в базе "Продажи", а в "Закупки" он передается.
Что нам потребуется для того чтобы задача возникла и могла быть решена.
1. Сервер 1с, с установленной web компонентой;
2. веб-сервер (например IIS 6.0);
3. Две или более конфигурации учетных систем.
Что нам потребуется для решения задачи.
1. Создадим в базе "Закупки" Web-сервис "Синхронизация", и добавим ему Операцию "СинхронизироватьТовар", со строковыми параметрами.
1. "GuidТовара" - сюда будем передавать уникальный идентификатор товара присвоенный в базе Продаж.
2. "GuidРодителя" - уникальный идентификатор родителя данного товара.
3. "стрСтруктураРеквизитов" - Структура реквизитов товара в виде примитивных типов (число,строка,дата,булево) преобразованная в строку.
4. "этоГруппа" - реквизит котрый позволит нам не раскрывая всей структуры реквизитов товара узнатья явлется ли товар группой и соответственно его обработать.
5. "стрТаблицаЕденицИзмерения" - Таблица содержащая описание доступных единиц измерения для товара
Далее потребуется опубликовать данный сервис на веб сервере. для этого нужно будет создать текстовый файл "wssinhron.1cws", в каталоге сайта опубликованном на веб сервере. Библиотека wsisapi.dll, должна быть подключена. Проще всего корректную настройку работы веб сервера с 1с можно провести опубликовав веб приложение через конфигуратор Администрирование->"Публикация на веб сервере". Единственным минусом является, то что в версии 8.2 файлы веб сервисов *.1cws, сами не создаются. Возможно просто мне не хватает знаний по этому вопросу но для публикации веб сервисов я пользуюсь блокнотом.
Также следует учесть что на серверах 64x следует использовать wsisapi.dll из поставки 1с 64x, даже если сам сервер 1с у вас 86x.
Итак создаем файл "wssinhron.1cws" с текстом.
{Название вашего сервера 1с}";Ref="{Назваение базы. у нас это "Market"}";"/>
Далее перейдем в модуль обработки нашего Сервиса, для наглядности я приведу пример кода своей разработки
Код 1C v 8.2 УП //стрТаблицаЕдиницИзмерения - таблица в строке с колонками.
//GUIDЕдиницы
//Базовая - булево
//Коэффициент
//ЕдиницаИзмерения - код классификатора Единиц измерения.
//Утверждено - булево
//******************************
//ТаблицаГабаритов С колонками
//ВидУпаковки (строковое значение)
//Длина
//ширина
//высота
//объем
//ОбъемныйВес
//Вес
//ФормаОснования
//ВесБрутто
//*****************************
//стрСтруктураРеквизитов - структура с праметрами
//Наименование
//код
//ПометкаУдаления
//ВидТовара - идентификатор перечисления
//GUIDПроизводителя - GUID производителя
//СтавкаНДС - число ставка
//Жив - булево
Функция СинхронизироватьТовар(GUIDтовара, GUIDродителя, этоГруппа, Уровень, стрСтруктураРеквизитов, стрТаблицаЕдиницИзмерения,стрТаблицаТНВЭД)
Попытка
СтруктураРеквизитов = ЗначениеИзСтрокиВнутр(стрСтруктураРеквизитов);
ТоварСсылка = Справочники.Товары.НайтиПоРеквизиту("GUIDтовара",СокрЛП(GUIDтовара));
Если СокрЛП(GUIDродителя)<>"" тогда
ТоварРодитель = Справочники.Товары.НайтиПоРеквизиту("GUIDтовара",СокрЛП(GUIDродителя));
иначе
ТоварРодитель = Справочники.Товары.ПустаяСсылка();
КонецЕсли;
Если ТоварРодитель.Пустая() и Уровень<>"0" тогда
Если СтруктураРеквизитов.ПометкаУдаления тогда
Возврат "ОК";
КонецЕсли;
возврат "0 Не найден родитель товара";
КонецЕсли;
Если СокрЛП(GUIDтовара) = "" тогда
возврат "0 Не верный ГУИД товара";
КонецЕсли;
//заполним реквизиты
Если ТоварСсылка.Пустая() тогда
ТоварСсылка = Справочники.Товары.НайтиПоКоду(СтруктураРеквизитов.Код);
КонецЕсли;
Если ТоварСсылка.Пустая() тогда
Если этоГруппа="1" тогда
ТоварОбъект = Справочники.Товары.СоздатьГруппу();
иначе
ТоварОбъект = Справочники.Товары.СоздатьЭлемент();
КонецЕсли;
ТоварОбъект.GUIDтовара = GUIDтовара;
иначе
ТоварОбъект = ТоварСсылка.ПолучитьОбъект();
ТоварОбъект.GUIDтовара = GUIDтовара;
КонецЕсли;
ТоварОбъект.Родитель = ТоварРодитель;
ТоварОбъект.Наименование = СтруктураРеквизитов.Наименование;
ТоварОбъект.Код = СтруктураРеквизитов.Код;
.....................
Если этоГруппа="1" тогда
иначе
Если СтруктураРеквизитов.менеджер <> "" тогда
......................
КонецЕсли;
//
Если ТоварОбъект.Производитель.Пустая() тогда
Если СтруктураРеквизитов.Производитель<>"" тогда
ТекПроизводитель = справочники.Производители.НайтиПоНаименованию(СтруктураРеквизитов.Производитель);
Если ТекПроизводитель.Пустая() тогда
НовПроизводитель = Справочники.Производители.СоздатьЭлемент();
иначе
НовПроизводитель = ТекПроизводитель.ПолучитьОбъект();
КонецЕсли;
НовПроизводитель.GUID = СтруктураРеквизитов.GUIDПроизводителя;
НовПроизводитель.Наименование = СтруктураРеквизитов.Производитель;
НовПроизводитель.Записать();
ТоварОбъект.Производитель = НовПроизводитель.ссылка;
КонецЕсли;
КонецЕсли;
ТоварОбъект.СтавкаНДС = Справочники.СтавкиНДС.НайтиПоНаименованию(СтруктураРеквизитов.СтавкаНДС,Истина);
КонецЕсли;
ТоварОбъект.Записать();
ТоварОбъект.УстановитьПометкуУдаления(СтруктураРеквизитов.ПометкаУдаления,Ложь);
ТоварСсылка = ТоварОбъект.Ссылка;
ТоварОбъект = Null;
//Синхронизируем Единицы измерения
ТаблицаЕдиниц = ЗначениеИзСтрокиВнутр(стрТаблицаЕдиницИзмерения);
Для каждого строка из ТаблицаЕдиниц цикл
ЕдиницаСсылка = Справочники.ЕдиницыИзмерения.НайтиПоРеквизиту("GUIDЕдиницы",строка.GUIDЕдиницы);
Если не ЕдиницаСсылка.Пустая() тогда
ЕдиницаОбъект = ЕдиницаСсылка.ПолучитьОбъект();
ЕдиницаОбъект.УстановитьПометкуУдаления(строка.ПометкаУдаления,Ложь);
иначе
Если строка.ПометкаУдаления тогда
продолжить;
КонецЕсли;
ЕдиницаОбъект = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
ЕдиницаОбъект.GUIDЕдиницы = строка.GUIDЕдиницы;
КонецЕсли;
ЕдиницаОбъект.Код = строка.Код;
ЕдиницаОбъект.Наименование = строка.Наименование;
....................
ЕдиницаОбъект.Габариты.Очистить();
ТаблицаГабаритов = ЗначениеИзСтрокиВнутр(строка.ТаблицаГабаритов);
Для каждого строкаГабаритов из ТаблицаГабаритов цикл
НовСтрока = ЕдиницаОбъект.Габариты.Добавить();
............................
НовСтрока.Примечание = строкаГабаритов.Примечание;
КонецЦикла;
ЕдиницаОбъект.Записать();
Если строка.Базовая тогда
ТоварОбъект = ТоварСсылка.ПолучитьОбъект();
ТоварОбъект.БазоваяЕдиницаИзмерения = ЕдиницаОбъект.Ссылка;
ТоварОбъект.Записать();
КонецЕсли;
КонецЦикла;
ТоварОбъект = ТоварСсылка.ПолучитьОбъект();
ТоварОбъект.ВремяСинхронизации = ТекущаяДата();
ТоварОбъект.Синхронизирован = истина;
ТоварОбъект.Записать();
исключение
//в случае возникновение ошибки вывод результата облегчит поиск причины.
Возврат ОписаниеОшибки();
КонецПопытки;
//Если все прошло успешно сообщим методу вызвашему веб сервис об успешном выполнении.
Возврат "ОК";
КонецФункции
Теперь, как вызвать веб сервис не зациклив при этом систему.
в нашем справонике "Товары" в базах "Продажи" и "Закупки" нам потребуются служебные реквизиты.
1. "GUIDтовара" - строковый реквизит (50)
2. "ВремяСинхронизации" - Реквизит с типом Дата и Время
3. "Синхронизирован" - тип булево.
В модуль объекта Справочника добавим предопределенные обработчики событий "ПередЗаписью()", "ПриЗаписи()" функцию "Синхронизация()" и общую переменную "передавать", и под текстом модуля присвоим этой переменной значение Истина.
Перем передавать Экспорт;
Процедура ПередЗаписью(Отказ)
Процедура ПриЗаписи(Отказ)
Функция Синхронизация()
передавать = истина;
Таким образом получится что при любой инициализации модуля наша переменная всегда имеет значение истина.
Рассмотрим наши процедуры:
Код 1C v 8.2 УП Процедура ПередЗаписью(Отказ)
#Если не ВнешнееСоединение тогда
//На случай двустороннего обмена данными, необходимо ограничить возможность вызова процедур синхронизации при записи спарвника из режима внешнего соединения.
Если передавать = истина тогда
Синхронизирован = Ложь;
КонецЕсли;
#КонецЕсли
КонецПроцедуры
Процедура ПриЗаписи(Отказ)
#Если не ВнешнееСоединение тогда
Если Константы.СинхронизироватьБазы.Получить() и передавать тогда
Синхронизация();
КонецЕсли;
#КонецЕсли
КонецПроцедуры
Функция Синхронизация()
GUIDтовара = СокрЛП(ссылка.УникальныйИдентификатор());
Если ссылка.Уровень()>0 тогда
GUIDродителя = СокрЛП(ссылка.Родитель.УникальныйИдентификатор());
Уровень = ссылка.Уровень()
иначе
GUIDродителя = "";
Уровень = "0";
КонецЕсли;
Если ЭтоГруппа тогда
СтрэтоГруппа = "1";
иначе
СтрэтоГруппа = "0";
КонецЕсли;
СтруктураРеквизитов = Новый Структура;
//заполним структуру параметров которые мы бы хотели передать в базу приемник.
СтруктураРеквизитов.Вставить("Наименование",Наименование);
СтруктураРеквизитов.Вставить("код",код);
....................
Если не ЭтоГруппа тогда
Если ОсновнойПоставщик.Пустая() тогда
......................
иначе
.....................
КонецЕсли;
КонецЕсли;
стрСтруктураРеквизитов = ЗначениеВСтрокуВнутр(СтруктураРеквизитов);
ТаблицаЕдиницИзмерения = Новый ТаблицаЗначений;
//GUIDЕдиницы
//Базовая - булево
//Коэффициент
//ЕдиницаИзмерения - код классификатора Единиц измерения.
//Утверждено - булево
//ТаблицаГабаритов
ТаблицаЕдиницИзмерения.Колонки.Добавить("Наименование");
ТаблицаЕдиницИзмерения.Колонки.Добавить("Код");
....................................
Выборка = Справочники.ЕдиницыИзмерения.Выбрать(,ссылка);
Пока Выборка.Следующий() цикл
НовСтрока = ТаблицаЕдиницИзмерения.Добавить();
НовСтрока.Наименование = Выборка.Наименование;
НовСтрока.Код = Выборка.Код;
..........................
ТаблицаГабаритов = Новый ТаблицаЗначений;
Для каждого колонка из Выборка.Габариты.Выгрузить().Колонки цикл
ТаблицаГабаритов.Колонки.Добавить(колонка.Имя);
КонецЦикла;
Для каждого строка из Выборка.Габариты цикл
НовСтрока1 = ТаблицаГабаритов.Добавить();
Для каждого колонка из ТаблицаГабаритов.Колонки цикл
НовСтрока1[колонка.Имя] = строка[колонка.Имя];
КонецЦикла;
КонецЦикла;
НовСтрока.ТаблицаГабаритов = ЗначениеВСтрокуВнутр(ТаблицаГабаритов);
КонецЦикла;
// т.к. наш вебсервис принимает в себя только строковые параметры, преобразуем наши таблицы в строки.
стрТаблицаЕдиницИзмерения = ЗначениеВСтрокуВнутр(ТаблицаЕдиницИзмерения);
есть = Ложь;
колПопыток = 0;
Пока не Есть и колПопытокцикл
Попытка
Определение = Новый WSОпределения(Константы.WebАдресМаркетинга.Получить()+"wssinhron.1cws"+"?wsdl",ПараметрыСеанса.Пользователь.Код,ПараметрыСеанса.Пользователь.ПарольЗакупок);
Прокси = Новый WSПрокси(Определение, "www.market-sinhron.gor", "Синхронизация", "СинхронизацияSoap");
Прокси.Пароль = ПараметрыСеанса.Пользователь.ПарольЗакупок;
Прокси.Пользователь = ПараметрыСеанса.Пользователь.Код;
Результат = Прокси.СинхронизироватьТовар(GUIDтовара, GUIDродителя, СтрЭтоГруппа, Уровень, стрСтруктураРеквизитов, стрТаблицаЕдиницИзмерения, стрТаблицаТНВЭД);
Определение = Null;
Прокси = Null;
есть = Истина;
исключение
колПопыток = колПопыток+1;
Определение = Null;
Прокси = Null;
КонецПопытки;
КонецЦикла;
Если колПопыток=100 тогда
#Если Клиент тогда
сообщить(ОписаниеОшибки());
Предупреждение("Ошибка синхронизации. отсутствует подключение.");
#КонецЕсли
КонецЕсли;
передавать = ложь;
сообщить(Результат);
Если Лев(Результат,2)="ОК" тогда
Синхронизирован = Истина;
ВремяСинхронизации = ТекущаяДата();
Записать();
КонецЕсли;
Если СокрЛП(Результат)="0 Не найден родитель товара" тогда
#Если Клиент тогда
Сообщить("вызов синхронизации родителя");
#КонецЕсли
ОбъектРодитель = родитель.ПолучитьОбъект();
ОбъектРодитель.Записать();
Записать();
КонецЕсли;
КонецФункции
Таким образом остается добавить в событие формы элемента "ПриЗаписи()"
Код 1C v 8.2 УП передавать = истина;
Синхронизация();
И мы сможем записывать наш элемент сколько угодно раз не вызывая зацикливания.
Для варианта двусторонней синхронизации, (когда элемент справочника может редактироваться в обоих базах) нам потребуется скопировать наш веб сервис из базы закупок в базу продаж переименовав имя файла публикации и URI пространство имен и внести соответствующие изменения в вызов веб сервиса из базы продаж в базу закупок и опубликовать его.
Важно: При успешном срабатывание вызванного сервиса из базы "Продажи", в качестве результата работы должен быть возвращен уникальный идентификатор элемента справочника из базы "Продажи". Данный результат необходимо будет присвоить соответсвующиму реквизиту справочника из базы закупок.
Аналогично приведенному примеру можно синхронизировать данные любого справочника или документа.
Построение сводных отчетов
Для получения сводного отчета нам также потребуется вызов веб сервиса из какой - либо базы. Данный веб сервис должен будет возвращать преобразованною в строку, таблицу с данными которые мы хотим использовать в нашем отчете (Например таблицу содержащую "Код товара" и "Актуальную цену поставщика на данный товар"). Далее можно преобразовать эту строку в таблицу и использовать в качестве вложенной временной таблицы любом запросе к базе "Продажи" с соединением по Коду. Исключением является использование данной таблицы в Построителе отчетов, для случая построителя нам понадобится создание, дополнительного справочника с предопределенным элементом и табличной частью, с реквизитами соответствующими полям таблицы.
Автор:
allert73 Категория:
WEB-сервисы, WS-ссылки, XDTO-пакеты Объединение 2 таблиц значений Код 1C v 8.х // Объединить 2 таблицы значения
// тзОсновная - таблица к которой будут изменяться данные
// тзПрисоединяемая - таблица из которой будут браться данные
// стОтборОдинаковых - стурктура со списком полей по которым определяеться одинаковость записи
// ДобавлятьНеНайденное - ИСТИНА => не сущесвующие записи в тзОсновная будут браться из тзПрисоединяемая
Процедура ОбъединитьТаблицыЗначений(тзОсновная,тзПрисоединяемая, стОтборОдинаковых, ДобавлятьНеНайденное = Ложь) Экспорт
Для каждого текПрисоединяемаяЗапись из тзПрисоединяемая цикл
ЗаполнитьЗначенияСвойств(стОтборОдинаковых,текПрисоединяемаяЗапись);
НайденыеСтроки = тзОсновная.НайтиСтроки(стОтборОдинаковых);
Если НайденыеСтроки.Количество() > 0 тогда
Для каждого текНайденная из НайденыеСтроки цикл
ЗаполнитьЗначенияСвойств(текНайденная,текПрисоединяемаяЗапись);
КонецЦикла;
ИначеЕсли ДобавлятьНеНайденное тогда
НовСтрокаОсновном = тзОсновная.Добавить();
ЗаполнитьЗначенияСвойств(НовСтрокаОсновном,текПрисоединяемаяЗапись);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Категория:
Работа с Таблицей Значений Как перебрать все даты с НачалоПериода по КонецПериода и получить таблицу периодов? Код 1C v 8.х Тз = Новый ТаблицаЗначений;
тз.Колонки.Добавить("День");
//Переберем все даты за период
ТекДат = НачалоДня(НачПериода);
Пока Не ТекДат = НачалоДня(КонПериода) Цикл
Состояние(ТекДат);
//Добавим текущую дату в таблицу периодов
НовСтр = Тз.Добавить();
НовСтр.День = ТекДат;
ТекДат = ТекДат+86400;//Добавим 1 День
КонецЦикла;
тз.ВыбратьСтроку();
Категория:
Работа с Датами (Временем) Как убрать из строки лишние символы? Код 1C v 8.х Функция УбратьЛишниеСимволы(Строка1) Экспорт
НовСтрока = "";
ПравильныеСимволы = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnmЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю";
Для Сч = 1 по СтрДлина(Строка1) Цикл
ТекСимв = Сред(Строка1, Сч, 1);
Если Найти(ПравильныеСимволы, ТекСимв) > 0 Тогда
НовСтрока = НовСтрока + ТекСимв;
КонецЕсли;
КонецЦикла;
Возврат НовСтрока;
КонецФункции
Категория:
Работа с Текстом (Строкой) Как выгрузить результат запроса с отбором по регистратору в табличную часть, табличное поле? Выгрузка результата запроса в табличную часть документа, справочника
Код 1C v 8.х Запрос=Новый Запрос;
// Получим суммы начисленные документами НачислениеЗарплатыРаботникамОрганизаций в ПериодВзаиморасчетов
Запрос.Текст="
|ВЫБРАТЬ
| ВзаиморасчетыСРаботникамиОрганизаций.Период,
| ВзаиморасчетыСРаботникамиОрганизаций.Регистратор,
| ВзаиморасчетыСРаботникамиОрганизаций.Физлицо,
| ВзаиморасчетыСРаботникамиОрганизаций.Организация,
| ВзаиморасчетыСРаботникамиОрганизаций.ПериодВзаиморасчетов,
| ВзаиморасчетыСРаботникамиОрганизаций.СуммаВзаиморасчетов
|ИЗ
| РегистрНакопления.ВзаиморасчетыСРаботникамиОрганизаций КАК ВзаиморасчетыСРаботникамиОрганизаций
|ГДЕ
| ВзаиморасчетыСРаботникамиОрганизаций.ПериодВзаиморасчетов = &ПериодВзаиморасчетов
| И ВзаиморасчетыСРаботникамиОрганизаций.Регистратор ССЫЛКА Документ.НачислениеЗарплатыРаботникамОрганизаций
|";
Запрос.УстановитьПараметр("ПериодВзаиморасчетов",Дата("01.09.2009 0:00:00"));
Результат = Запрос.Выполнить();
// Выгрузим Результат Запроса в ТЗ
ТзВрем = Результат.Выгрузить();
Для Каждого стр Из Тзврем Цикл
// ТаблЧастьДокРезультат - Табличная часть на форме, создаем в ней новую строку
НовСтр=ТаблЧастьДокРезультат.Добавить();
// Заполняем значения новой строки значениями результат запроса:
ЗаполнитьЗначенияСвойств(новстр , стр);
//ВНИМАНИЕ!!! ЗаполнитьЗначенияСвойств( - работает только когда имена колонок табл части и результата запроса совпадают!
//Если не совпадают, то обычным способом:
НовСтр.Дата = стр.ПериодВзаиморасчетов;
НовСтр.Сумма = стр.СуммаВзаиморасчетов;
КонецЦикла;
Выгрузка результата запроса в табличное поле с типом данных Таблица Значений
Код 1C v 8.х Запрос=Новый Запрос;
// Получим суммы начисленные документами НачислениеЗарплатыРаботникамОрганизаций в ПериодВзаиморасчетов
Запрос.Текст="
|ВЫБРАТЬ
| ВзаиморасчетыСРаботникамиОрганизаций.Период,
| ВзаиморасчетыСРаботникамиОрганизаций.Регистратор,
| ВзаиморасчетыСРаботникамиОрганизаций.Физлицо,
| ВзаиморасчетыСРаботникамиОрганизаций.Организация,
| ВзаиморасчетыСРаботникамиОрганизаций.ПериодВзаиморасчетов,
| ВзаиморасчетыСРаботникамиОрганизаций.СуммаВзаиморасчетов
|ИЗ
| РегистрНакопления.ВзаиморасчетыСРаботникамиОрганизаций КАК ВзаиморасчетыСРаботникамиОрганизаций
|ГДЕ
| ВзаиморасчетыСРаботникамиОрганизаций.ПериодВзаиморасчетов = &ПериодВзаиморасчетов
| И ВзаиморасчетыСРаботникамиОрганизаций.Регистратор ССЫЛКА Документ.НачислениеЗарплатыРаботникамОрганизаций
|";
Запрос.УстановитьПараметр("ПериодВзаиморасчетов",Дата("01.09.2009 0:00:00"));
Результат = Запрос.Выполнить();
// Выгрузим Результат Запроса в ТЗ
ТзВрем = Результат.Выгрузить();
// ТЗРезультат - это Табличное Поле на Форме, присваиваем ему таблицу значений
ТЗРезультат=ТзВрем;
//Создаем колонки в табличном поле, после чего видим в поле тз
ЭлементыФормы.ТЗРезультат.СоздатьКолонки();
Категория:
Запросы Структура ~ Преобразовании Структуры в Таблицу Значений Код 1C v 8.х //Струтура в ТЗ
Функция СтруктураВТЗ(Структр)
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Значение");
ТЗ.Колонки.Добавить("Описание");
Для Каждого ТекЭлем из Структр Цикл
НовСтр=ТЗ.Добавить();
НовСтр.Значение = ТекЭлем.Ключ;
НовСтр.Описание = ТекЭлем.Значение;
КонецЦикла;
Возврат ТЗ;
КонецФункции
//Использование
ТЗизСтруктуры = Функция СтруктураВТЗ(СтруктураКоторуюНужноПреобразовать);
Категория:
Работа с Массивом, Структурой, Соответств… Как изменить, присвоить, указать Тип Значения Ячейки табличной части? Создаем табличную часть и в ней реквизит с разными типами значений:
Код 1C v 8.х //Создадим строки с разним типом значения
НовСтрока = ТабЧасть.Добавить();
НовСтрока.РеквизитПроизвольный = 12345;
НовСтрока = ТабЧасть.Добавить();
НовСтрока.РеквизитПроизвольный = "Это строка";
НовСтрока = ТабЧасть.Добавить();
НовСтрока.РеквизитПроизвольный = ТекущаяДата();
НовСтрока = ТабЧасть.Добавить();
НовСтрока.РеквизитПроизвольный = Истина;
// измененим тип значения в ячейке ТЧ
// Найдем Строку и заменим на Дату
НайденСтрока = ТабЧасть.Найти("Это строка", "РеквизитПроизвольный");
НайденСтрока.РеквизитПроизвольный = ТекущаяДата();
// Найдем Число и заменим на Пустую ссылку справочника Номенклатуры (полученную с Вида судконто)
Счет = ПланыСчетов.Хозрасчетный.ТоварыНаСкладе;
НайденСтрока = ТабЧасть.Найти(12345, "РеквизитПроизвольный");
// Получим первое субконто Номенклатура
Субконото1 = Счет.ВидыСубконто[1];
// Присвоим тип значения
НайденСтрока.РеквизитПроизвольный = Субконото1.ВидСубконто.ТипЗначения.ПривестиЗначение();
Категория:
Работа с Типами данных