Как найти документ по уникальному идентификатору через com соединение? Потребовалось написать небольшую синхронизацию данных в дополнении к стандартной УТ-БП, нужно по уникальному идентификатору искать документы:
Стандартное Соединение.Справочники.Номенклатура.ПолучитьСсылку(УИ);
Выдает ошибку {Форма.Форма.Форма(301)}: Ошибка при вызове метода контекста (ПолучитьСсылку): Произошла исключительная ситуация: Несоответствие типов (параметр номер '1')
Нужно уникальный идентификатор создавать в com: Соединение.Справочники.Номенклатура.ПолучитьСсылку(Соединение.NewObject("УникальныйИдентификатор",Строка(УИ)));
Рабочий пример:
Код 1C v 8.3 &НаСервере
Функция ПодключитьБазуНаСервере(Соединение = "")
Объект.ФайловаяБазаДанных=Ложь;
Объект.Сервер="srv1с";
Объект.База="buh";
Объект.ИмяПользователя="Obmen";
Объект.Пароль="1qaz";
// Подключение к 1С
Если Объект.ФайловаяБазаДанных Тогда
СтрокаПодключения = "file='" + Объект.ПутьКБазе + "'; usr='" + Объект.ИмяПользователя + "'; pwd='" + Объект.Пароль + "';";
Иначе
СтрокаПодключения = "srvr='" + Объект.Сервер + "'; ref='" + Объект.База + "'; usr='" + Объект.ИмяПользователя + "'; pwd='" + Объект.Пароль + "';";
КонецЕсли;
Попытка
V8 = Новый COMObject("V83.COMConnector");
Соединение = V8.Connect(СтрокаПодключения);
ЕстьСоединение = Истина;
Исключение
ЕстьСоединение = Ложь;
Сообщить(ОписаниеОшибки());
КонецПопытки;
Возврат Соединение;
КонецФункции
&НаСервере
Процедура ОбновитьДанныеПлатежейНаСервере()
Соединение = ПодключитьБазуНаСервере();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|ПоступлениеБезналичныхДенежныхСредствРасшифровкаПлатежа.Ссылка КАК Ссылка,
|ПоступлениеБезналичныхДенежныхСредствРасшифровкаПлатежа.ОснованиеПлатежа КАК ОснованиеПлатежа,
|ПоступлениеБезналичныхДенежныхСредствРасшифровкаПлатежа.Сумма КАК Сумма
|ИЗ
|Документ.ПоступлениеБезналичныхДенежныхСредств.РасшифровкаПлатежа КАК ПоступлениеБезналичныхДенежныхСредствРасшифровкаПлатежа
|ГДЕ
|НЕ ПоступлениеБезналичныхДенежныхСредствРасшифровкаПлатежа.ОснованиеПлатежа ССЫЛКА Документ.ЗаказКлиента";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
УИД = ВыборкаДетальныеЗаписи.Ссылка.УникальныйИдентификатор();
СсылкаНаДок = Соединение.Документы.ПоступлениеНаРасчетныйСчет.ПолучитьСсылку(Соединение.NewObject("УникальныйИдентификатор",Строка(УИД)));
//Сообщить(СсылкаНаДок.Номер);
Для каждого СтрокаИсточник Из СсылкаНаДок.РасшифровкаПлатежа Цикл
//Сообщить("Счет: "+Строка(СтрокаИсточник.СчетНаОплату.Номер));
УИД = Соединение.String(СтрокаИсточник.СчетНаОплату.УникальныйИдентификатор());
текДок= Документы.ЗаказКлиента.ПолучитьСсылку(Новый УникальныйИдентификатор(УИД));
Если ЗначениеЗаполнено(текДок) Тогда
Сообщить(текДок);
текОбъект=ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
текОбъект.РасшифровкаПлатежа[0].ОснованиеПлатежа= текДок;
текОбъект.РасшифровкаПлатежа[0].Заказ= текДок;
текОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДанныеПлатежей(Команда)
ОбновитьДанныеПлатежейНаСервере();
КонецПроцедуры
Категория:
COM-объекты, WMI, WSH Дата создания объекта по ссылке (GUID) Код позволяет получить информацию о дате и времени создания объекта ИБ (документ, элемент справочника) по уникальному идентификатору (GUID)
Позволяет узнать, когда был создан документ или элемент справочника. Для получения информации используется уникальный идентификатор объекта в ИБ.
Код 1C v 8.3 Функция ДатаСозданияСсылки(Ссылка) Экспорт
Если НЕ ЗначениеЗаполнено(Ссылка) Тогда
Возврат Неопределено;
КонецЕсли;
Момент = Дата(1, 1, 1);
Попытка
УИ = Строка(Ссылка.УникальныйИдентификатор());
УИ = ВРег(СтрЗаменить(УИ,"-",""));
Если Сред(УИ, 13, 1) = "1" Тогда
Значение16 = ВРег(Сред(УИ, 14, 3) + Сред(УИ, 9, 4) + Сред(УИ, 1, 8));
Цифры16 = "123456789ABCDEF";
Значение10 = 0;
Длина16 = СтрДлина(Значение16);
Для Ном = 1 По Длина16 Цикл
Значение10 = Значение10 + Pow(16, Длина16-Ном)*Найти(Цифры16, Сред(Значение16, Ном, 1));
КонецЦикла;
Значение10 = Значение10/10000000;
Момент = Дата(1582, 10, 15, 3, 0, 0) + Значение10;
КонецЕсли;
Исключение
КонецПопытки;
Возврат Момент;
КонецФункции
Категория:
Встроенные Функции Яндекс карта : вывод точек на карту Пример о том,как вывести яндекс карту на форму и далее работать с ней:
Основной 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 октября запустить авто нумерацию с номера 00010000, но старые счета не трогать!
Попросили - сделали:
т.к. Старые трогать нельзя - простое восстановление нумерации отпадает
Первое решение, которое пришло в голову, сделать выборку по моментувремени создания счета - обратная сортировка - получить первый - и к полученному номеру документа +1
Но оказалось, что бывает такое: менеджеры создают счета сегодня, но ставят дату вчера - и получается только что созданный документ уже не последний пришлось переделать алгоритм.
Нужно сортировать именно по дате создания документа! Реквизита такого нет, но решение было найдено в ГУИДе документа, вот статья на эту тему: Как по GUID определить время и дату создания ссылки?
Только алгоритм решили немного переделать - не получаем дату создания документа, а сортируем по части ГУИДа, которая является началом периода создания документа.
Код получился такой:
Код 1C v 8.2 УП //В модуле объекта документа
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
//... стандартный код
//All4CF - Установим новый номер
Если ЭтоНовый() Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 30
| СчетНаОплатуПокупателю.Номер,
| СчетНаОплатуПокупателю.Ссылка
|ИЗ
| Документ.СчетНаОплатуПокупателю КАК СчетНаОплатуПокупателю
|
|УПОРЯДОЧИТЬ ПО
| СчетНаОплатуПокупателю.МоментВремени УБЫВ";
Результат = Запрос.Выполнить().Выбрать();
спНомеров = Новый СписокЗначений;
Пока Результат.Следующий() Цикл
тевгуи д = Результат.Ссылка.УникальныйИдентификатор(); спНомеров.Добавить(Результат.Ссылка, Сред(тевгуи д,10,9)+Сред(тевгуи д,0,8));
КонецЦикла;
спНомеров.СортироватьПоПредставлению(НаправлениеСортировки.Убыв);
послНомер = спНомеров[0].Значение.Номер;
ДлиНом=СтрДлина(СокрЛП(послНомер));
Номер = Формат(Число(послНомер)+1,"ЧЦ="+ДлиНом+"; ЧВН=; ЧГ=0");
КонецЕсли;
КонецПроцедуры // ПередЗаписью
Встречалось ли у вас такая ситуация? Как решали?
Категория:
Документы О формате EnterpriseData Для облегчения интеграции с программными продуктами фирмы «1С» разработан формат обмена данными EnterpriseData. Формат основан на XML и является бизнес-ориентированным – описанные в нем структуры данных соответствуют бизнес-сущностям (документам и элементам справочников), представленным в программах «1С», например: акт выполненных работ, приходный кассовый ордер, контрагент, договор и т. п. Это делает формат интуи тивно понятным и легким в использовании.
Формат EnterpriseData предназначен для обмена данными внутри компании (в том числе между разнородными и территориально удаленными информационными системами) и призван покрыть все сферы деятельности предприятия – финансы, производство, закупки и продажи, складские операции и т. п.
Описание формата Версия 1.0.1 формата включает в себя описание 94 типов бизнес-сущностей из различных областей бизнеса (подробное описание формата можно найти здесь). Формат является расширяемым – фирма «1С» будет добавлять в него описание новых бизнес-сущностей и расширять существующие сущности новыми полями. Поддержка формата в продуктах фирмы «1С» обеспечивает совместимость снизу вверх – все программы сторонних производителей, обменивающихся данными в формате EnterpriseData с продуктами «1С», при выходе новых версий формата корректно продолжат работу.
Формат предназначен для обмена информацией между любыми информационными системами: он не зависит от особенностей собственного программного обеспечения или структур информационных баз, которые участвуют в обмене и не содержит в себе явных ограничений использования.
Обмен данными с программами «1С» Предварительная настройка на стороне «1С»
Чтобы начать обмен данными в формате EnterpriseData между приложением «1С» и сторонним приложением, надо на стороне «1С» настроить синхронизацию данных. В ходе настройки указывается уникальный код приложения, с которым будет производиться обмен, а также по какому каналу будет происходить обмен данными. В настоящий момент доступны следующие опции:
веб-сервис, файловый обмен через каталог, файловый обмен через FTP. Обмен через электронную почту
В случае обмена через веб-сервис стороннее приложение будет инициировать сеанс обмена данными путем вызова соответствующих веб-методов приложения «1С». В остальных случаях инициатором сеанса обмена будет приложение «1С».
Также на стороне «1С» настраивается, с какой периодичностью будет происходить синхронизация (для вариантов с файловым обменом через каталог и электронную почту):
по расписанию (с заданной периодичностью);
вручную; пользователь должен будет вручную запускать синхронизацию каждый раз, когда это ему потребуется.
Формат файлов обмена
В ходе синхронизации приложения «1С» и сторонние приложения обмениваются сообщениями – XML-файлами определенной структуры. Эти файлы состоят из двух секций – <Header> и <Body>. Секция <Header> содержит сообщение-квитанцию <Confirmation> (о ней ниже), а <Body> – информацию об измененных бизнес-сущностях в формате EnterpriseData.
Подробнее на сайте 1С
Категория:
Конвертация данных, Обмен, Перенос Обмен данными с сайтом используя формат JSON в 1С Формат JSON в 1С до версии 8.3.6 не реализован, но нижет я приведу примеры функций которые можно использовать для полноценной работы JSON в 1С предыдущий версий.
JSON (JavaScript Object Notation) это текстовый формат обмена данными, широко используемый в веб-приложениях. По сравнению с XML он является более лаконичным и занимает меньше места. Кроме этого все браузеры имеют встроенные средства для работы с JSON.
Необходимость работы с этим форматом на уровне платформы обусловлена не только тем, что это «модный современный» формат, который прикладные решения 1С:Предприятия сами по себе могут использовать для интеграции со сторонними приложениями. Другая причина заключается ещё и в том, что JSON активно используется в HTTP интерфейсах. А в 1С:Предприятии как раз есть такие механизмы, в которых хочется использовать этот формат. Это REST интерфейс приложения, автоматически генерируемый платформой, и HTTP-сервисы, которые вы можете создавать самостоятельно.
В платформе с версии 8.3.6: Потоковое чтение и запись JSON:
Объекты потоковой работы - это общие объекты ЧтениеJSON и ЗаписьJSON. Они последовательно читают JSON из файла или строки, или последовательно записывают JSON в файл или строку. Таким образом, чтение и запись JSON происходят без формирования всего документа в памяти.
В качестве иллюстрации потокового чтения JSON можно привести следующий пример:
Код 1C v 8.3 // Пример чтения JSON.
ЧтениеJSON = Новый ЧтениеJSON;
// Либо открыть файл, из которого будет выполняться чтение, // либо установить строку, из которой будет выполняться чтение.
ЧтениеJSON.ОткрытьФайл("ИмяФайла");
//ЧтениеJSON.УстановитьСтроку("СтрокаJSON");
Пока ЧтениеJSON.Прочитать() Цикл
TипJSON = ЧтениеJSON.ТипТекущегоЗначения;
Если TипJSON = ТипЗначенияJSON.Число ИЛИ TипJSON = ТипЗначенияJSON.Строка ИЛИ TипJSON = ТипЗначенияJSON.Булево ИЛИ TипJSON = ТипЗначенияJSON.Null Тогда
// Обработать значение
Значение = ЧтениеJSON.ТекущееЗначение;
ИначеЕсли ТипJSON = ТипЗначенияJSON.Комментарий Тогда
// Обработать комментарий
Комментарий = ЧтениеJSON.ТекущееЗначение;
ИначеЕсли TипJSON = ТипЗначенияJSON.ИмяСвойства Тогда
// Обработать имя свойства
ИмяСвойства = ЧтениеJSON.ТекущееЗначение;
ИначеЕсли TипJSON = ТипЗначенияJSON.НачалоМассива ИЛИ TипJSON = ТипЗначенияJSON.КонецМассива ИЛИ TипJSON = ТипЗначенияJSON.НачалоОбъекта ИЛИ TипJSON = ТипЗначенияJSON.КонецОбъекта ИЛИ TипJSON = ТипЗначенияJSON.Ничего Тогда
// Обработать начало/коней массива/объекта или отсутствие данных, // ТекущееЗначение читать не нужно.
КонеиЕсли;
КокецЦикла;
ЧтениеJSON.Закрыть();
// При записи JSON вы самостоятельно формируете его структуру. Чтобы «подстраховать» вас от ошибок, объект ЗаписьJSON автоматически проверяет правильность записываемой структуры.
// Для увеличения скорости работы эту проверку можно отключить. В примере ниже это строка:
ЗаписьJSON.ПроверятьСтруктуру = Ложь;
// Также при записи вы можете управлять некоторыми параметрами формируемого текста, например использованием двойных кавычек, переносом строк, символами отступа и экранированием символов.
// В примере ниже для форматирования текста используется символ табуляции:
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON( , Символы.Таб) ;
ЗаписьJSON.ОткрытьФайл("ИмяФайла", , , ПараметрыЗаписиJSON);
// Потоковая запись JSON может выглядеть следующим образом. Записывается массив из четырёх элементов. Три из них примитивного типа, а четвёртый элемент - это объект с двумя свойствами:
// Пример записи JSON. ЗаписьJSON = Новый ЗаписьJSON;
// Для увеличения скорости работы можно отключить автоматическую проверку // правильности структуры записываемого документа JSON. ЗаписьиЗСЖ.ПроверятьСтруктуру = Ложь;
// Для красоты результирующего текста можно увеличить "лесенку".
// Стандартный отступ - 1 пробел.
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON( , Символы.Таб);
// Либо открыть файл, в который будет выполнена запись,
// либо указать, что запись будет выполнена в строку, которую вернет метод Закрыть().
ЗаписьJSON.ОткрытьФайл("ИмяФайла", , , ПараметрыЗаписиJSON);
//ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
// Записать массив.
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("СвойствоТипаМассив");
ЗаписьJSON.ЗаписатьНачалоМассива();
// Первый элемент массива - Строка. ЗаписьJSON.ЗаписатьЗначение("Значение строка");
// Второй элемент массива - Число. ЗаписьJSON.ЗаписатьЗначение(12.345, Истина);
// Третий элемент массива - Булево. ЗаписьJSON-ЗаписатьЗначение(Истина);
// Четвертый элемент массива - объект с двумя свойствами. ЗаписьJSON.ЗаписатьНачалоОбъекта();
// Первое свойство объекта - Строка
ЗаписьJSON.ЗаписатьИмяСвойства("СвойствоТипаСтрока");
ЗаписьJSON.ЗаписатьЗначение("Значение строка");
// Второе свойство объекта - Неопределено
ЗаписьJSON.ЗаписатьИмяСвойства("СвойствоТипаНеопределено");
ЗаписьJSON.ЗаписатьЗначение(Неопределено);
ЗаписьJSON.ЗаписатьКонецОбъекта();
Запись JSON. ЗаписатьКонецМассива () ;
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьJSON.Закрыть();
//CTpoKaJSON = ЗаписьJSON.Закрыть();
Результат такой записи:
Код 1C v 8.х
{
"СвойствоТипаМассив": [
"Значение строка",
1.2345E1,
true,
{
"СвойствоТипаСтрока": "Значение строка",
"СвойствоТипаНеопределено": null
}
]
}
Сериализация примитивных типов и коллекций в JSON
Вторая группа средств работы с JSON хороша тем, что избавляет вас от рутинной работы по чтению/записи каждого отдельного значения или свойства. При чтении документы JSON отображаются в фиксированный набор типов платформы: Строка, Число, Булево, Неопределено, Массив, ФиксированныйМассив, Структура, ФиксированнаяСтруктура, Соответствие, Дата. Соответственно, в обратную сторону, композиция объектов этих типов позволяет сформировать в памяти и быстро записать в файл структуру JSON. Таким образом, чтение и запись небольшого объема JSON заранее известной структуры можно производить немногими строчками кода.
Основное назначение этих средств мы видим в обмене информацией с внешними системами, чтении конфигурационных файлов в формате JSON.
Сериализацию вы можете выполнять с помощью методов глобального контекста ПрочитатьJSON() и ЗаписатьJSON(). Они работают в связке с объектами ЧтениеJSON и ЗаписьJSON.
В качестве примера десериализации JSON можно рассмотреть чтение массива из двух объектов:
Код 1C v 8.3 // В качестве примера десериализации JSON можно рассмотреть чтение массива из двух объектов:
[
{
"имя": "Anton",
"фамилия": "Иванов",
"возраст": 25
},
{
"имя": "Ирина",
"фамилия": "Иванова",
"возраст": 20
}
]
// Код 1С:Предприятия, выполняющий десериализацию, может выглядеть следующим образом:
// Пример чтения JSON.
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.ОткрытьФайл("ИмяФайла");
Сотрудники = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Для каждого Сотрудник из Сотрудники Цикл
// Обработать данные сотрудника.
ИмяСотрудника = Сотрудник.имя; ФамилияСотрудника = Сотрудник.фамилия; ВозрастСотрудника = Сотрудник.возраст;
КонецЦикла;
// А пример сериализации (записи) в JSON может выглядеть так:
// Пример записи JSON
Структура = Новый Структура;
Вставить("Фамилия","Иванов");
Зставить("Имя", "Иван");
Вставить("Отчество", "Иванович");
Зставить("Возраст", 40) ;
Зставить("Женат", Истина);
Телефоны = Новый Массив;
Телефоны.Добавить("8-999-999-99-90") ;
Телефоны.Добавить("8-999-999-99-91") ;
Структура.Вставить("Телефоны", Телефены);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл("ИмяФайла", , , Новый ПapaмeтpыЗaпиcиJS0N( , Символы.Таб) ) ;
ЗаписатьJSON(ЗаписьJSON, Структура);
ЗаписьJSON.Закрыть();
// Результат записи:
{
"Фамилия": "Иванов",
"Имя": "Иван",
"Отчество": "Иванович",
"Возраст": 40,
"Женат": true,
"Телефоны": [
"8-999-999-99-90",
"8-999-999-99-91"
]
}
Подробнее вы можете посмотреть здесь
В платформе с версии 8.3.7: Полностью автоматизировали работу с JSON и реализовали в платформе третью группу средств. Они позволяют сериализовать в JSON прикладные типы 1С:Предприятия: ссылки, объекты, наборы записей и вообще любые типы, для которых поддерживается XDTO сериализация. Конечно же, мы обеспечили и обратную операцию - десериализацию. Зачем это нужно!?
Прежде всего, и в основном, XDTO сериализацию в JSON мы рекомендуем использовать при обмене данными между двумя прикладными решениями 1С:Предприятия. По сравнению с XML формат JSON более компактный, сериализация/десериализация в/из JSON выполняется быстрее. Кроме этого мы предприняли дополнительные меры для того, чтобы сократить объём передаваемых данных.
Кроме обмена между приложениями 1С:Предприятия этот механизм можно использовать и для обмена с внешними системами, готовыми принимать типы данных 1С:Предприятия. Например, XDTO сериализацию в JSON можно использовать для организации собственного HTTP интерфейса прикладного решения. Сервис на платформе 1С:Предприятия будет формировать ответ в памяти в виде строки JSON. А затем передавать её при помощи объекта HTTPСервисОтвет. Реализованный нами механизм сериализации полностью соответствует стандарту JSON. Поэтому внешняя система не должна испытывать каких-либо трудностей с десериализацией.
Использование XDTO сериализации в JSON для других задач видится нам маловероятным. Потому что если внешняя система не готова работать с прикладными типами 1С:Предприятия, то зачем их ей передавать? А если предполагается обмениваться только примитивными типами и коллекциями, то для этой задачи хорошо подходят методы ПрочитатьJSON() и ЗаписатьJSON(). Подробнее здесь
ДО платформы версии 8.3.6, т.е. 8.3.5 и ниже: На HelpF уже есть статья где описан пример: Работа с форматом JSON в 1С но не приведены функции, вот они:
Код 1C v 8.х Функция ПреобразоватьвСистему(Число10,система) Экспорт
Если система > 36 или система < 2 тогда
Сообщить("Выбранная система исчисления не поддерживается");
Возврат -1;
КонецЕсли;
СтрокаЗначений = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
СтрокаСистема = "";
Пока Число10 > 0 цикл
РезДеления = Число10/система;
ЧислоСистема = цел(РезДеления);
остатокОтДеления = Число10 - система*(ЧислоСистема);
СтрокаСистема = сред(СтрокаЗначений,остатокОтДеления+1,1)+ СтрокаСистема;
Число10 = ?(ЧислоСистема=0,0,РезДеления);
КонецЦикла;
Нечётное = стрДлина(СтрокаСистема) - цел(стрДлина(СтрокаСистема)/2)*2;
Если Нечётное тогда
СтрокаСистема = "0"+СтрокаСистема;
КонецЕсли;
Возврат СтрокаСистема;
КонецФункции
Функция URLEncode(стр) Экспорт
Длина=СтрДлина(Стр);
Итог="";
Для Н=1 По Длина Цикл
Знак=Сред(Стр,Н,1);
Код=КодСимвола(Знак);
если ((Знак>="a")и(Знак<="z")) или
((Знак>="A")и(Знак<="Z")) или
((Знак>="0")и(Знак<="9")) тогда
Итог=Итог+Знак;
Иначе
Если (Код>=КодСимвола("А"))И(Код<=КодСимвола("п")) Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(208,16)+"%"+ПреобразоватьвСистему(144+Код-КодСимвола("А"),16);
ИначеЕсли (Код>=КодСимвола("р"))И(Код<=КодСимвола("я")) Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(209,16)+"%"+ПреобразоватьвСистему(128+Код-КодСимвола("р"),16);
ИначеЕсли (Знак="ё") Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(209,16)+"%"+ПреобразоватьвСистему(145,16);
ИначеЕсли (Знак="Ё") Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(208,16)+"%"+ПреобразоватьвСистему(129,16);
Иначе
Итог=Итог+"%"+ПреобразоватьвСистему(Код,16);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Итог;
КонецФункции
Функция СформироватьСтрокуJSONИзМассива(Объект)
СтрокаJSON = "[";
Для каждого Элемент Из Объект Цикл
Если ТипЗнч(Элемент) = Тип("Строка") Тогда
СтрокаJSON = СтрокаJSON + """" + Элемент + """";
ИначеЕсли ТипЗнч(Элемент) = Тип("Число") Тогда
СтрокаJSON = СтрокаJSON + СтрЗаменить(Строка(Элемент), Символы.НПП, "");
ИначеЕсли ТипЗнч(Элемент) = Тип("Булево") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент, "БЛ=false; БИ=true");
ИначеЕсли ТипЗнч(Элемент) = Тип("Дата") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент - Дата(1970,1,1,1,0,0), "ЧГ=0");
ИначеЕсли ТипЗнч(Элемент) = Тип("Массив") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент);
ИначеЕсли ТипЗнч(Элемент) = Тип("Структура") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент);
ИначеЕсли ТипЗнч(Элемент) = Тип("ТаблицаЗначений") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент);
Иначе
СтрокаJSON = СтрокаJSON + """" + URLEncode(Строка(Элемент)) + """";
КонецЕсли;
СтрокаJSON = СтрокаJSON + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "]";
КонецФункции
Функция СформироватьСтрокуJSONИзСтруктуры(Объект)
СтрокаJSON = "{";
Для каждого Элемент Из Объект Цикл
Если Элемент.Значение = "" Тогда
Продолжить;
КонецЕсли;
СтрокаJSON = СтрокаJSON + """" + Элемент.Ключ + """" + ":";
Если ТипЗнч(Элемент.Значение) = Тип("Строка") Тогда
СтрокаJSON = СтрокаJSON + """" + Элемент.Значение + """";
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Число") Тогда
СтрокаJSON = СтрокаJSON + СтрЗаменить(Строка(Элемент.Значение), Символы.НПП, "");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Булево") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент.Значение, "БЛ=false; БИ=true");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Дата") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент.Значение - Дата(1970,1,1,1,0,0), "ЧГ=0");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Массив") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Структура") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("ТаблицаЗначений") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
Иначе
СтрокаJSON = СтрокаJSON + """" + URLEncode(Строка(Элемент.Значение)) + """";
КонецЕсли;
СтрокаJSON = СтрокаJSON + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "}";
КонецФункции
Функция СформироватьСтрокуJSON(Объект) Экспорт
СтрокаJSON = "";
Если ТипЗнч(Объект) = Тип("Массив") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзМассива(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("Структура") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("ТаблицаЗначений") Тогда
СоставСтруктуры = "";
Для каждого Колонка Из Объект.Колонки Цикл
СоставСтруктуры = СоставСтруктуры + ?(ЗначениеЗаполнено(СоставСтруктуры), ",", "") + Колонка.Имя;
КонецЦикла;
МассивСтрок = Новый Массив;
Для каждого Строка Из Объект Цикл
СтруктураКолонок = Новый Структура(СоставСтруктуры);
ЗаполнитьЗначенияСвойств(СтруктураКолонок, Строка);
МассивСтрок.Добавить(СтруктураКолонок);
КонецЦикла;
СтрокаJSON = СформироватьСтрокуJSONИзМассива(МассивСтрок);
КонецЕсли;
Возврат СтрокаJSON;
КонецФункции
Процедура ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, ТипДанных)
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
НомерЗначения = 0;
Пока ТекстJSON <> "" Цикл
ПервыйСимвол = Лев(ТекстJSON, 1);
Если ПервыйСимвол = "{" Тогда
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
ИначеЕсли ТипДанных = "Массив" Тогда
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "[" Тогда
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
Иначе
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "}" И ТипДанных = "Структура" Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
ИначеЕсли ПервыйСимвол = "]" И ТипДанных = "Массив" Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
Иначе
Если ТипДанных = "Структура" Тогда
Поз = Найти(ТекстJSON, ":");
Если Поз = 0 Тогда
Прервать;
КонецЕсли;
ИмяЗначения = СокрЛП(Лев(ТекстJSON, Поз-1));
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз+1));
Если Лев(ТекстJSON, 1) = "{" Тогда
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Иначе
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз-1);
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
КонецЕсли;
Результат.Вставить(ИмяЗначения, Значение);
ИначеЕсли ТипДанных = "Массив" Тогда
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз-1);
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
Результат.Добавить(Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЗаполнитьСтруктуруИзОтветаJSON(Знач ТекстJSON) Экспорт
Результат = Новый Структура;
ТекстJSON = СтрЗаменить(ТекстJSON, "\""", """");
ТекстJSON = СтрЗаменить(ТекстJSON, """", "");
Если Лев(ТекстJSON, 1) = "{" Тогда
ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
МассивДанных = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(МассивДанных, ТекстJSON, "Массив");
Результат.Вставить("Значение", МассивДанных);
КонецЕсли;
Возврат Результат;
КонецФункции
Примеры их использования:
Код 1C v 8.х ////////////////////////////////////////////////////////
// преобразование простой структуры
Данные = Новый Структура("server,user,hash",
10234, 3745, "8263ad83ce");
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// {"server":"10234","user":"3745","hash":"8263ad83ce"}
////////////////////////////////////////////////////////
// преобразования массива
Данные = Новый Массив;
Данные.Добавить("Nissan");
Данные.Добавить("Ford");
Данные.Добавить("Audi");
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// ["Nissan","Ford","Audi"]
////////////////////////////////////////////////////////
// преобразование сложной структуры
Данные = Новый Структура;
Данные.Добавить("server", 10234);
Данные.Добавить("users", Новый Массив);
Данные.Добавить("hash", "8263ad83ce");
Данные.users.Добавить(3745);
Данные.users.Добавить(7462);
Данные.users.Добавить(2374);
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// {"server":"10234","users":["3745","7462","2374"],"hash":"8263ad83ce"}
////////////////////////////////////////////////////////
// еще один пример массива
Данные = Новый Структура;
Данные.Вставить("server", 10234);
Данные.Вставить("users", Новый Массив);
Данные.users.Добавить(Новый Структура("id,name", 3745, "Jack"));
Данные.users.Добавить(Новый Структура("id,name", 7246, "Nick"));
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// {"server":"10234","users":[{"id":"3745","name":"Jack"},{"id":"7462","name":"Nick"}>
////////////////////////////////////////////////////////
// преобразование таблицы значений
ТаблПользователей = Новый ТаблицаЗначений;
ТаблПользователей.Колонки.Добавить("id");
ТаблПользователей.Колонки.Добавить("name");
НоваяСтрока = ТаблПользователей.Добавить();
НоваяСтрока.id = 3276;
НоваяСтрока.name = "Jack";
НоваяСтрока = ТаблПользователей.Добавить();
НоваяСтрока.id = 3276;
НоваяСтрока.name = "Nick";
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// [{"id":"3745","name":"Jack"},{"id":"7462","name":"Nick"}]
Пишите комменты
Категория:
Работа с Интернет, Почтой (Mail), FTP Авто добавление обработки в справочник Внешних обработок Чтобы не изменять типовую конфигурацию приходится использовать типовой механизм внешних печатных форм и обработок. Данный код проверяет - добавлена ли открываемая обработка в конфигурацию, если нет - задает вопрос и при положительном ответе - автоматически добавляет в конфигурацию:
Код 1C v 8.х ПолноеИмяФайлаОбработки = ЭтотОбъект.ИспользуемоеИмяФайла;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Наименование", ЭтотОбъект.Метаданные().Синоним);
Запрос.УстановитьПараметр("ВидОбработки", Перечисления.ВидыДополнительныхВнешнихОбработок.ПечатнаяФорма);
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ВнешниеОбработки.Ссылка
|ИЗ
| Справочник.ВнешниеОбработки КАК ВнешниеОбработки
|ГДЕ
| ВнешниеОбработки.Наименование = &Наименование
| И ВнешниеОбработки.ВидОбработки = &ВидОбработки";
Если НЕ Запрос.Выполнить().Пустой() Тогда Возврат; КонецЕсли;
Если Вопрос("Зарегистрировать обработку как печатную форму для документа ""ЗарплатаКВыплатеОрганизаций"" в справочнике ""Внешние обработки""?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда
ВнешняяОбработка = Справочники.ВнешниеОбработки.СоздатьЭлемент();
ВнешняяОбработка.Наименование = ЭтотОбъект.Метаданные().Синоним;
ВнешняяОбработка.ХранилищеВнешнейОбработки = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ПолноеИмяФайлаОбработки));
ВнешняяОбработка.ВидОбработки = Перечисления.ВидыДополнительныхВнешнихОбработок.ПечатнаяФорма;
ВнешняяОбработка.Комментарий = "Внешняя печатная форма для документа ""ЗарплатаКВыплатеОрганизаций""";
ВнешняяОбработка.КомментарийКФайлуИсточнику = ПолучитьКомментарийКФайлу(ПолноеИмяФайлаОбработки);
НовСтр = ВнешняяОбработка.Принадлежность.Добавить();
НовСтр.ПредставлениеОбъекта = "Документ ""Зарплата к выплате организаций""";
НовСтр.ХранилищеВнешнейОбработки = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ПолноеИмяФайлаОбработки));
НовСтр.СсылкаОбъекта = Документы.ЗарплатаКВыплатеОрганизаций.ПустаяСсылка();
Попытка
ВнешняяОбработка.Записать();
Исключение
Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
Категория:
1С Общие вопросы - Обычные формы Как преобразовать <Объект не найден> в УникальныйИдентификатор (GUID) Для того чтобы преобразовать <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824) в УникальныйИдентификатор (GUID), можно воспользоваться кодом:
Код 1C v 8.х // ГУИДУдОбъкта = <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824)
ГУИДУдОбъктаСтр = СтрЗаменить(ГУИДУдОбъкта,"<Объект не найден> (","");
ГУИДУдОбъктаСтр = СтрЗаменить(ГУИДУдОбъктаСтр,")","");
ГУИДУдОбъктаСтр = СтрЗаменить(ГУИДУдОбъктаСтр,"0x","");
ГУИДУдОбъктаСтр = Сред(ГУИДУдОбъктаСтр, Найти(ГУИДУдОбъктаСтр,":")+1, СтрДлина(ГУИДУдОбъктаСтр));
// Преобразуем GUID
ГУИД = Сред(ГУИДУдОбъктаСтр,25,8)+"-"+Сред(ГУИДУдОбъктаСтр,21,4)+"-"+Сред(ГУИДУдОбъктаСтр,17,4)+"-"+Сред(ГУИДУдОбъктаСтр,1,4)+"-"+Сред(ГУИДУдОбъктаСтр,5,12);
//и получаем ГУИД = 05dbe824-a4c6-11dd-bf56-00145e3710ab
Категория:
Полезные, Универсальные Функции Как создать Фиксированный массив? ФиксированныйМассив , элементами которого могут быть значения перечисленных типов, включая ФиксированныйМассив. ФиксированныйМассив не допускает никаких изменений своего содержимого и может быть сконстр
уи рован из объекта типа "Массив";
А если проще, то:
Фиксированный массив от того и фиксированный, что
не поддается изменению .
Инициализируй массив один раз, помещай в фиксированный и больше не трогай
Код 1C v 8.х НовыйМассив = Новый Массив;
НовыйМассив.Добавить(1);
НовыйМассив.Добавить(2);
НовыйМассив.Добавить(3);
ФиксированныеЧисла = Новый ФиксированныйМассив(НовыйМассив);
// Получился константный массив на основе обычного:
// нельзя менять значения имеющихся элементов, нельзя добавлять новые элементы, нельзя удалять имеющиеся элементы
//ИЛИ
НовыйМассив = Новый Массив();
НовыйМассив.Добавить(Новый СвязьПараметраВыбора("Отбор.Владелец", "ВладелецНаселенногоПункта",РежимИзмененияСвязанногоЗначения.Очищать));
НовыйМассив.Добавить(Новый СвязьПараметраВыбора("Отбор.ТипНаселенногоПункта", "ТипНаселенногоПункта",РежимИзмененияСвязанногоЗначения.Очищать));
НовыеСвязи = Новый ФиксированныйМассив(НовыйМассив);
Категория:
Работа с Массивом, Структурой, Соответств… Как получить ссылку на объект из навигационной ссылки? Код 1C v 8.2 УП Процедура ПолучитьСсылкуИзНавигационной(НС)
ПерваяТочка = Найти(НС, "e1cib/data/");
ВтораяТочка = Найти(НС, "?ref=");
ПредставлениеТипа = Сред(НС, ПерваяТочка + 11, ВтораяТочка - ПерваяТочка - 11);
ШаблонЗначения = ЗначениеВСтрокуВнутр(ПредопределенноеЗначение(ПредставлениеТипа + ".ПустаяСсылка"));
ЗначениеСсылки = СтрЗаменить(ШаблонЗначения, "00000000000000000000000000000000", Сред(НС, ВтораяТочка + 5));
Ссылка = ЗначениеИзСтрокиВнутр(ЗначениеСсылки);
КонецПроцедуры
Категория:
Полезные, Универсальные Функции Работа с почтой с помощью внешней компоненты DialMail Скачать компоненту dialmail.dll и примеры работы в 1С Скачивать файлы может только зарегистрированный пользователь!
Подключение:
Код 1C v 7.x Процедура ПриОткрытии()
Путь = КаталогИБ() + "DialMail.dll";
Если ЗагрузитьВнешнююКомпоненту(Путь) = 0 Тогда Сообщить("Неудачная попытка загрузить DialMail.dll"); КонецЕсли;
КонецПроцедуры;
Отправка почты:
Код 1C v 7.x Процедура ОтправитьПочту()
ОтправкаПочты = СоздатьОбъект("AddIn.SMTP");
ОтправкаПочты.РабочийКаталог=СокрЛП(КаталогИБ());
ОтправкаПочты.УстановитьКодировкуИСпособКодирования(14, 1);
ОтправкаПочты.MakeContentDescriptionTag = 0;
ОтправкаПочты.ПочтоваяПрограмма = "Имя почтовой программы";
//В моем случае ошибки пишутся в отдельный каталог в текстовые файлы, имена которых соответствуют дате.
ВыбФайл = СокрЛП(КаталогОшибок) +"\"+ СокрЛП(ДатаЧисло(ТекущаяДата())) + СокрЛП(ДатаМесяц(ТекущаяДата()))+ СокрЛП(ДатаГод(ТекущаяДата())) + ".txt";
//имя файла - вложения должно быть в кавычках.
ВыбФайл = """" + ВыбФайл + """";
// От кого, Кому, Копии - это адреса почты.
ОтправкаПочты.СоздатьПисьмо(ОтКого,Кому,СокрЛП(СпрПочта.Копии),"Ошибки обмена в " + СокрЛП(Константа.Магазин.Наименование),,"Данное письмо сформировано автоматически. Смотри вложение",СокрЛП(ВыбФайл));
Если ОтправкаПочты.Подключиться("smtp.mail.ru","25",ИмяПользователя,Пароль)=0 тогда
Сообщить("Не смогли подключиться к SMTP-серверу");
КонецЕсли;
Если ОтправкаПочты.ОтправитьВсеПисьма(0,1,0) = -100 Тогда
Сообщить("Успешно отправлено");
КонецЕсли;
КонецПроцедуры
******************************* FAQ **************************************
(1) Как организовать дозвон? (тонкости организации дозвона)
1. Во первых, надо вручную создать подключение в списке удаленного
доступа (win 2000 - пуск, настройка, сеть и уд.доступ, создание
нового подключения).
Или создать подключение с помощью компоненты (см. "Атрибуты
подключений" и "СохранитьНастройкиПодключения()").
2. Если импульсный набор, то перед номером телефона надо ставить "p"
напр "p212121", тоновый - по умолчанию или "t". Если необходимо ждать
гудка после цифры, то ставится "w", напр. "t8w0952223333".
3. (только если RAS-сервер находится под управлением Windows 95-98)
Если система-клиент NT, 2000 или XP тогда в свойствах созданного
в п.1 соединения в разделе "Безопасность" выберите возможность
отправления незашифрованного пароля (win 2000 - закладка
"безопасность", п. Дополнительные (особые параметры), кн
"Настройка", п.Разрешить следующие протоколы, галочка
ТОЛЬКО на "Незашифрованный пароль PAP")
4. При вызове дозвона, необходимо использовать имя созданного в
п.1 подключения в качестве первого параметра.
5. При использовании процедуры "ОбработкаВнешнегоСобытия" (последний
параметр = 1 в Дозвониться (RASDIAL), ПолучитьПисьмо,
ПолучитьВсеПисьма (POP3), ОтправитьПисьмо, ОтправитьВсеПисьма(SMTP)
форма подключения в обязательном порядке должна быть в "фокусе",
иначе события могут теряться. Вернее они не теряются, а начинают
(пытаются) обрабатываться в глобальном модуле.
*********************************************************************
(2) Через какие объекты добраться до общих методов ?
Если методы и свойства "общие" это значит, что у объектов POP3 и SMTP есть одинаково действующие
методы и свойства.
Код 1C v 7.x Получ=СоздатьОбъект("AddIn.POP3");
Отпр=СоздатьОбъект("AddIn.SMTP");
Получ.РабочийКаталог="c:\Export\";
Отпр.РабочийКаталог="c:\Import\";
!!! Отметим при этом, что Получ.РабочийКаталог<>Отпр.РабочийКаталог !!!
"РабочийКаталог" - одинаковое свойство для объектов POP3 и SMTP
*********************************************************************
(3) Почему при дозвоне компонента 3 раза подряд генерирует
событие "Начало Аутенфикации"?.
Дозвон происходит через системную DLL'ку RasDial.
Все события, которые генерируются этой DLL'кой перенаправляются
компонентой DialMail в 1С (процедура ОбработкаВнешнегоСобытия(...))
Так что от компоненты в данном случае ничего не зависит.
Причина этого (можно предположить) лежит на уровне того сервера,
к которому идет подсоединение (кто мешает аутенфикацию
проводить 3 раза или 3-мя различными способами?).
*********************************************************************
(4) При дозвоне (отправке, приеме почты) у меня в форме перестают
генерироваться события в процедуре ОбработкаВнешнегоСобытия(...),
хотя дозвон (отправка, прием почты) продолжает свою работу.
Это глюк 1С. Проявляется иногда во время работы компоненты при
сворачивании окон программ,открытия новых окон программ, при
потере фокуса 1С-Предприятием. Лечится это следующим образом.
На самом деле все события, сгенерированные компонентой, не пропадают
если процедуру ОбработкаВнешнегоСобытия(...) разместить
в глобальном модуле. В этом случае нам нужна будет глобальная
переменная - контекст нашей формы. Все переменные, которые нам
понадобятся в процедуре ОбработкаВнешнегоСобытия(...), можно
сделать либо глобальными, либо разместить на нашей форме в виде
невидимых реквизитов.
КоличествоСобытий - реквизит, размещенный на нашей форме
Код 1C v 7.x //Глобальный модуль
========================================
Перем КонтекстНашейФормы Экспорт;
...
Процедура ВзятьКонтекст(Конт) Экспорт
КонтекстНашейФормы=Конт;
КонецПроцедуры
Процедура ОсвободитьКонтекст() Экспорт
КонтекстНашейФормы=-1;
КонецПроцедуры
...
Процедура ОбработкаВнешнегоСобытия(Источник,Событие,Данные)
...
Если КонтекстНашейФормы<>-1 тогда
КонтекстНашейФормы.КоличествоСобытий=КоличествоСобытий+1;
КонтекстНашейФормы.Форма.Обновить(0);
КонецЕсли;
...
КонецПроцедуры
...
КонтекстНашейФормы=-1;
========================================
Модуль нашей формы
========================================
Перем Дозвон;
Процедура ПриОткрытии()
...
ЗагрузитьВнешнююКомпоненту("DialMail.dll");
Дозвон=СоздатьОбъект("AddIn.RasDial");
ВзятьКонтекст(Конт);
...
КонецПроцедуры
Процедура ПриЗакрытии()
...
ОсвободитьКонтекст(Конт)
...
КонецПроцедуры
Процедура НашДозвон()
Дозвон.Дозвониться("Мое соединение",
"логин","пароль","p1055555",1);
КонецПроцедуры
========================================
*********************************************************************
(5) Можно ли использовать дозвон для разговоров по телефону?
Нет. Компонента не предназначена для простых звонков на
телефон. Только для установления "сетевого" соединения между
2-мя компьютерами (например, между клиентским компьютером и
компьютером провайдера).
*********************************************************************
(6) Хотелось бы использовать компоненту DialMail в проектах,
написанных на Visual Basic, Delphi и т.д.
Компонента 1С хоть и полностью COM объект, но интерфейс
особый, свой - 1С-ий. Чтобы работать с данной компонентой
из других средств разработки, надо полностью переписывать
компоненту. Мне это не нужно, да и нет времени.
*********************************************************************
(7) Дайте исходники!
Модули Synapse, на которых базируются почтовые клиенты компонеты, лежат
в http://www.ararat.cz/synapse/ , могу прислать примеры компоненты
и интерфейсный модуль RasUnit.pas (для облегченной работы с RAS API -
тоже кстати из инета). Могу оказать посильную помощь, если что-то с этими
исходниками будет неясно. Но полностью исходники выложу в свободное
распространение только когда не буду поддерживать компоненту.
*********************************************************************
(8) Почему при передаче/приеме почты возникает ошибка 10054?
10054 - "Connection reset by peer", т.е. "Соединение сброшено удаленной
системой"
Происходит в результате:
1. Выключения сокета на удаленной машине в
рез-те ресета или таймаута
2. Вызывается локальной машиной при обнаружении потери
соединения (например, если дозванивались по dial-up и соединение
разорвалось - свойственно плохим модемам и плохим тел. линиям)
3. Связано с неправильным использованием "потоков" при приеме/передаче
Например, последовательность
Код 1C v 7.x pop3.ПолучитьВсеПисьма(0,1,1);
pop3.Отключиться();
может вызвать именно эту ошибку.
Пояснение: Т.к. получение запущено в отдельном потоке (3-ий параметр=1),
команда отключения вызовет закрытие сокета. Поток, который принимает почту,
из-за закрытия сокета "внешним процессом" инициирует данную ошибку -
фактически причина №2.
*********************************************************************
(9) RasDial: Как задать импульсный/тоновый набор номера,
паузу для ожидания гудка, и т.п. ?
Начинаться номер телефона может с "p" или "t" - cоответственно импульсный
или тоновый набор номера, по умолчанию - тоновый набор номера.
"w" - пауза, дождемся гудка - "линия свободна", "," - пауза в не помню сколько
времени (1 сек?) Пример задания телефонного номера: p8w095,,1234567
В данном примере - 'p' - импульсный набор, после '8' пауза, дождемся гудка,
после '095' подождем 2 сек и продолжим набирать номер. Более подробную
информацию по данным управляющим символам можно найти на просторах интернета.
*********************************************************************
Компонента DIALMAIL. (c) SWA corp. (e-mail:SWA@list.ru) Категория:
Работа с Интернет, Почтой (Mail), FTP Как программно прочитать Журнал Регистрации? Код 1C v 8.х ИмяФайла=ПолучитьИмяВременногоФайла("XML");
Результат.Очистить();
Фильтр=Новый Структура;
Фильтр.Вставить("ДатаНачала", НачалоПериода);
Фильтр.Вставить("ДатаОкончания", ОкончаниеПериода);
Фильтр.Вставить("Событие", "_$Data$_.Post");
Состояние("Выгрузка журнала...");
ВыгрузитьЖурналРегистрации(ИмяФайла, Фильтр, "Дата, Метаданные, Данные, ПредставлениеДанных, ИмяПользователя");
Состояние("Обработка журнала...");
ЧтениеXML=Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайла);
ПостроительDOM=Новый ПостроительDOM;
ДокументDOM=ПостроительDOM.Прочитать(ЧтениеXML);
Event=ДокументDOM.ПолучитьЭлементыПоИмени("v8e:Event");
Для й=0 По Event.Количество()-1 Цикл
ДочерниеУзлы=Event[й].ДочерниеУзлы;
Для Каждого Узел Из ДочерниеУзлы Цикл
Если Узел.ИмяУзла="v8e:Date" Тогда
ДатаСобытия=СтрЗаменить(Узел.ТекстовоеСодержимое, "T", "");
ДатаСобытия=СтрЗаменить(ДатаСобытия, ":", "");
ДатаСобытия=Дата(СтрЗаменить(ДатаСобытия, "-", ""));
ИначеЕсли Узел.ИмяУзла="v8e:MetadataName" Тогда
МетаданныеДокумента=СтрЗаменить(Узел.ТекстовоеСодержимое, "Document.", "");
ИначеЕсли Узел.ИмяУзла="v8e:Data" Тогда
УИД=Узел.ТекстовоеСодержимое;
ИначеЕсли Узел.ИмяУзла="v8e:DataPresentation" Тогда
ПредставлениеДанных=Узел.ТекстовоеСодержимое;
ИначеЕсли Узел.ИмяУзла="v8e:UserName" Тогда
Пользователь=Узел.ТекстовоеСодержимое;
КонецЕсли;
КонецЦикла;
Ссылка=Документы[МетаданныеДокумента].ПолучитьСсылку(Новый УникальныйИдентификатор(УИД));
ДатаОбъекта=Ссылка.Дата;
НоваяСтрока=Результат.Добавить();
НоваяСтрока.ДатаСобытия=ДатаСобытия;
НоваяСтрока.ДатаОбъекта=ДатаОбъекта;
НоваяСтрока.ПредставлениеДанных=ПредставлениеДанных;
НоваяСтрока.Пользователь=Пользователь;
НоваяСтрока.РазностьДат=Окр((ДатаСобытия-ДатаОбъекта)/86400);
НоваяСтрока.Ссылка=Ссылка;
КонецЦикла;
Категория:
Администрирование Использование 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-пакеты Яндекс, Google, Рамблер Карты и 1С Обработка демонстрирует возможности интеграции 1С с картографическими сервисами, в ней поддерживается работа трех поставщиков услуг / карт — Яндекс, Google. Рамблер.
Автор: Діма Головаченко - http://smaylukk.com.ua
но так вот сама обработка + еще 2 :
Скачивать файлы может только зарегистрированный пользователь!
Код Модуля Обработки:
Код 1C v 8.х Перем СтруктураПоставщиковКарт Экспорт;
Перем СтруктураЧисел;
/////////////////////////РАБОТА С JSON //////////////////////////////////////////
Функция СформироватьСтрокуJSONИзМассива(Объект)
СтрокаJSON = "[";
Для каждого Элемент Из Объект Цикл
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент) + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "]";
КонецФункции
Функция СформироватьСтрокуJSONИзСтруктуры(Объект)
СтрокаJSON = "{";
Для каждого Элемент Из Объект Цикл
Если Элемент.Значение = "" Тогда
Продолжить;
КонецЕсли;
СтрокаJSON = СтрокаJSON + """" + Элемент.Ключ + """" + ":";
Если ТипЗнч(Элемент.Значение) = Тип("Строка") Тогда
СтрокаJSON = СтрокаJSON + """" + URLEncode(Элемент.Значение) + """";
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Число") Тогда
СтрокаJSON = СтрокаJSON + СтрЗаменить(Строка(Элемент.Значение), Символы.НПП, "");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Булево") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент.Значение, "БЛ=false; БИ=true");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Дата") Тогда
// преобразование в unixtime
СтрокаJSON = СтрокаJSON + Формат(ТекущаяДата() - Дата(1970,1,1,1,0,0), "ЧГ=0");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Массив") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Структура") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("ТаблицаЗначений") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
Иначе
СтрокаJSON = СтрокаJSON + """" + URLEncode(Строка(Элемент.Значение)) + """";
КонецЕсли;
СтрокаJSON = СтрокаJSON + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "}";
КонецФункции
Функция СформироватьСтрокуJSON(Объект) Экспорт
СтрокаJSON = "";
Если ТипЗнч(Объект) = Тип("Массив") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзМассива(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("Структура") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("ТаблицаЗначений") Тогда
// преобразуем таблицу значений в массив структур - работает дольше, но кода меньше
// если нужна скорость, то нужно отдельно обработать таблицу значений
СоставСтруктуры = "";
Для каждого Колонка Из Объект.Колонки Цикл
СоставСтруктуры = СоставСтруктуры + ?(ЗначениеЗаполнено(СоставСтруктуры), ",", "") + Колонка.Имя;
КонецЦикла;
МассивСтрок = Новый Массив;
Для каждого Строка Из Объект Цикл
СтруктураКолонок = Новый Структура(СоставСтруктуры);
ЗаполнитьЗначенияСвойств(СтруктураКолонок, Строка);
МассивСтрок.Добавить(СтруктураКолонок);
КонецЦикла;
СтрокаJSON = СформироватьСтрокуJSONИзМассива(МассивСтрок);
КонецЕсли;
Возврат СтрокаJSON;
КонецФункции
Процедура ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, ТипДанных)
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2)); // удалим открывающий символ структуры(массива)
НомерЗначения = 0;
Пока ТекстJSON <> "" Цикл
ПервыйСимвол = Лев(ТекстJSON, 1);
Если ПервыйСимвол = "{" Тогда
// вложенная структура
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
ИначеЕсли ТипДанных = "Массив" Тогда
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "[" Тогда
// вложенный массив
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
Иначе
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "}" И ТипДанных = "Структура" Тогда
// структура закончилась
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
ИначеЕсли ПервыйСимвол = "]" И ТипДанных = "Массив" Тогда
// массив закончился
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
Иначе
Если ТипДанных = "Структура" Тогда
//ПервыйКавычка = Ложь;
//Если Лев(ТекстJSON, 1) = """" Тогда
// ПервыйКавычка = Истина;
//КонецЕсли;
Поз = Найти(ТекстJSON, ":");
Если Поз = 0 Тогда
// неверный формат, прервемся
Прервать;
КонецЕсли;
//ПредпоследнийКавычка = Ложь;
//Если Сред(ТекстJSON, Поз - 1, 1) = """" Тогда
// ПредпоследнийКавычка = Истина;
//КонецЕсли;
ИмяЗначения = СокрЛП(Лев(ТекстJSON, Поз - 1));
ИмяЗначения = СтрЗаменить(ИмяЗначения, """", "");
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз+1));
Если Лев(ТекстJSON, 1) = "{" Тогда
// значение является структурой
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
// значение является массивом
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Иначе
// обычное значение
ПервыйКавычка = Ложь;
ПредпоследнийКавычка = Ложь;
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = """" Тогда
Если ПервыйКавычка Тогда
ПредпоследнийКавычка = Истина;
Иначе
ПервыйКавычка = Истина;
КонецЕсли;
КонецЕсли;
Если (Символ = "," И ((ПервыйКавычка И ПредпоследнийКавычка) Или (Не ПервыйКавычка И Не ПредпоследнийКавычка))) ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
//ПредпоследнийКавычка = Ложь;
//Если Сред(ТекстJSON, Поз - 1, 1) = """" Тогда
// ПредпоследнийКавычка = Истина;
//КонецЕсли;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз - 1);
Значение = СтрЗаменить(Значение, """", "");
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
КонецЕсли;
Результат.Вставить(ИмяЗначения, Значение);
ИначеЕсли ТипДанных = "Массив" Тогда
// обычное значение
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
//ПредпоследнийКавычка = Ложь;
//Если Сред(ТекстJSON, Поз - 1, 1) = """" Тогда
// ПредпоследнийКавычка = Истина;
//КонецЕсли;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз - 1);
Значение = СтрЗаменить(Значение, """", "");
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
Результат.Добавить(Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЗаполнитьСтруктуруИзОтветаJSON(Знач ТекстJSON) Экспорт
Результат = Новый Структура;
ТекстJSON = СтрЗаменить(ТекстJSON, "\""", """"); // заменим последовательность \" на "
//ТекстJSON = СтрЗаменить(ТекстJSON, """", ""); // а теперь удалим все кавычки
Если Лев(ТекстJSON, 1) = "{" Тогда
// начало структуры
ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
// начало массива
МассивДанных = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(МассивДанных, ТекстJSON, "Массив");
Результат.Вставить("Значение", МассивДанных);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция КодСимволаASCII(Символ)
КодUNICODE = КодСимвола(Символ);
Если ((КодUNICODE > 1039) И (КодUNICODE < 1104)) Тогда
Возврат (КодUNICODE - 848);
ИначеЕсли КодUNICODE = 8470 Тогда
Возврат 185;
ИначеЕсли КодUNICODE = 1105 Тогда
Возврат 184;
ИначеЕсли КодUNICODE = 1025 Тогда
Возврат 168;
Иначе
Возврат КодUNICODE;
КонецЕсли;
КонецФункции
Функция URLEncode(value)
table = "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14" +
"%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28" +
"%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B%3C" +
"%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F%50" +
"%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F%60%61%62%63%64" +
"%65%66%67%68%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78" +
"%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C" +
"%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0" +
"%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4" +
"%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8" +
"%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC" +
"%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0" +
"%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF";
result = "";
length = СтрДлина( value );
Для i = 1 По length Цикл
symbol = Сред( value, i, 1 );
//code = КодСимвола( symbol );
code = КодСимволаASCII( symbol );
result = result + Сред( table, code*3 + 1, 3 );
КонецЦикла;
Возврат result;
КонецФункции
/////////////////////////РАБОТА С JSON //////////////////////////////////////////
//Функция декодирует полученный unicod текст - из ответа геокодера Рамблера
// в привычный нам
//Параметры:
// Строка
//Возвращаемое значение:
// Строка
Функция UnicodeEncode(Строка) Экспорт
Результат = Истина;
Попытка
//регулярное выражение
Рег = Новый COMОбъект("VBScript.RegExp");
Рег.IgnoreCase = Истина;
Рег.Global = Истина;
Рег.Multiline = Ложь;
Рег.Pattern = "u[0-9a-f]+";
Колекция = Рег.Execute(Строка);
Для Каждого Элемент Из Колекция Цикл
Если СтрДЛина(Элемент.value) = 1 Тогда
Продолжить;
КонецЕсли;
КодСимвола = ПереводЧислаИз16в10(Сред(ВРег(Элемент.value), 2));
Символ = Символ(КодСимвола);
Строка = СтрЗаменить(Строка, "\" + Элемент.value, Символ);
КонецЦикла;
Исключение
Результат = Ложь;
Сообщить("Ошибка преобразования из Unicode", СтатусСообщения.Информация);
КонецПопытки;
Возврат Результат;
КонецФункции
Функция ПереводЧислаИз16в10(Знач Значение)
Результат = 0;
//перевод значения в строку
Если ТипЗнч(Значение) <> Тип("Строка") Тогда
Значение = СокрЛП(Строка(Значение));
КонецЕсли;
МаксРазрядЦелых = 0;
МаксРазрядЦелых = СтрДлина(Значение) - 1;
н = МаксРазрядЦелых;
Ин = 1;
Пока н >= 0 Цикл
ТекЗначение = СтруктураЧисел.Получить(Сред(Значение, Ин, 1)) * Pow(16, н);
Результат = Результат + ТекЗначение;
н = н - 1;
Ин = Ин + 1;
КонецЦикла;
Возврат Результат;
КонецФункции
///////////////////////////
СтруктураПоставщиковКарт = Новый Соответствие;
СтруктураПоставщиковКарт.Вставить(0, "Яндекс");
СтруктураПоставщиковКарт.Вставить(1, "Гугл");
СтруктураПоставщиковКарт.Вставить(2, "2ГИС");
СтруктураПоставщиковКарт.Вставить(3, "Рамблер");
СтруктураЧисел = Новый Соответствие;
СтруктураЧисел.Вставить("0", 0);
СтруктураЧисел.Вставить("1", 1);
СтруктураЧисел.Вставить("2", 2);
СтруктураЧисел.Вставить("3", 3);
СтруктураЧисел.Вставить("4", 4);
СтруктураЧисел.Вставить("5", 5);
СтруктураЧисел.Вставить("6", 6);
СтруктураЧисел.Вставить("7", 7);
СтруктураЧисел.Вставить("8", 8);
СтруктураЧисел.Вставить("9", 9);
СтруктураЧисел.Вставить("A", 10);
СтруктураЧисел.Вставить("B", 11);
СтруктураЧисел.Вставить("C", 12);
СтруктураЧисел.Вставить("D", 13);
СтруктураЧисел.Вставить("E", 14);
СтруктураЧисел.Вставить("F", 15);
Код Формы Управляемой:
Код 1C v 8.2 УП
&НаКлиенте
Процедура НайтиАдрес(Команда)
НайтиАдресНаКарте(ТекАдрес);
КонецПроцедуры
&НаКлиенте
Процедура ИнициализацияКарты(Команда)
ИнициализироватьКарту();
КонецПроцедуры
&НаКлиенте
Процедура СправочнаяИнформация(Команда)
Элементы.ГруппаСправка.Видимость = Не Элементы.ГруппаСправка.Видимость;
КонецПроцедуры
&НаКлиенте
Процедура Разработчик(Команда)
ЗапуститьПриложение("http://smaylukk.com.ua/?lang=Ru");
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.ТипКарты = Параметры.ТипКарты;
ТекОбъект = РеквизитФормыВЗначение("Объект");
Поставщик = ТекОбъект.СтруктураПоставщиковКарт.Получить(Объект.ТипКарты);
Макет = ТекОбъект.ПолучитьМакет("Справка");
ТекстСправки = Макет.ПолучитьОбласть("Справка" + Поставщик).Область().Текст;
Справка = ТекстСправки;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Элементы.ГруппаСправка.Видимость = Ложь;
Заголовок = "Работа с картами. Поставщик - " + Поставщик;
ИнициализироватьКарту();
КонецПроцедуры
&НаКлиенте
Процедура ПриЗакрытии()
//удаление временных файлов
Для Каждого ТекЭлемент Из МассивВременныхФайлов Цикл
УдалитьФайлы(ТекЭлемент.Значение);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
//Процедура составляет имя процедуры поставщика
// и запускает ее на исполнение
//Параметры:
// НачалоИмени - Строка
Процедура ВыполнитьПроцедуруПоставщика(ИмяПроцедуры)
Выполнить ИмяПроцедуры;
КонецПроцедуры
&НаКлиенте
//процедура инициализирует карту постащика из макета
Процедура ИнициализироватьКарту()
Текст = ПолучитьТекстМакета("Макет" + Поставщик);
Эксплорер = Текст;
КонецПроцедуры
&НаСервере
Функция ПолучитьТекстМакета(ИмяМакета)
Макет = РеквизитФормыВЗначение("Объект").ПолучитьМакет(ИмяМакета);
Результат = Макет.ПолучитьТекст();
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура ОчисткаКарты()
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "Reset()";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
///////////////////////////////////////////////////////////////////////
///////////////////ГЕОКОДИРОВАНИЕ И ПОИСК АДРЕСА///////////////////////
///////////////////////////////////////////////////////////////////////
&НаКлиенте
Процедура НайтиАдресНаКарте(Адрес = "")
//поиск адреса
Если Адрес = "" Тогда
Адрес = "Москва";
КонецЕсли;
// дальше пробуем с помощью геокодинга вывести данные поиска в таблицу
ТаблицаАдресов.Очистить();
ПоискАдреса(Адрес);
Если Поставщик = "Яндекс" Тогда
ПроизвестиГеокодинг_Яндекс();
ИначеЕсли Поставщик = "Гугл" Тогда
ПроизвестиГеокодинг_Гугл();
ИначеЕсли Поставщик = "Рамблер" Тогда
ПроизвестиГеокодинг_Рамблер();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПоискАдреса(Адрес)
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "FindAdres(""" + Адрес + """);";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаСервере
//Процедура выводит в таблицу данные геокдинга Яндекса
//
//Параметры:
// ТекАдрес - Строка
Процедура ПроизвестиГеокодинг_Яндекс()
Яндекс = Новый HTTPСоединение("geocode-maps.yandex.ru");
ВременныйФайл = КаталогВременныхФайлов() + "Yandex_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Яндекс.Получить("/1.x/?geocode=" + ТекАдрес + "&results=10", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по яндексу адрес: " + ТекАдрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ВременныйФайл);
ПостроительDOM = Новый ПостроительDOM;
ДокументДОМ = ПостроительDOM.Прочитать(ЧтениеXML);
СписокText = ДокументДОМ.ПолучитьЭлементыПоИмени("text");
СписокPos = ДокументДОМ.ПолучитьЭлементыПоИмени("pos");
Если (СписокText.Количество() = 0) ИЛИ (СписокPos.Количество() = 0) Тогда
Возврат;
КонецЕсли;
Для ъ = 0 по СписокText.Количество()-1 Цикл
Координаты = СписокPos[Ъ].ТекстовоеСодержимое;
Разделитель = Найти(Координаты," ");
Широта = Число(Сред(Координаты, Разделитель + 1));
Долгота = Число(Лев(Координаты, Разделитель - 1));
Если Широта = 0 ИЛИ Долгота = 0 Тогда
Продолжить;
КонецЕсли;
стрАдрес = ТаблицаАдресов.Добавить();
Если СписокText.Количество() > ъ Тогда
стрАдрес.Адрес = СписокText[Ъ].ТекстовоеСодержимое;
стрАдрес.Широта = Широта;
стрАдрес.Долгота = Долгота;
КонецЕсли;
КонецЦикла;
МассивВременныхФайлов.Добавить(ВременныйФайл);
КонецПроцедуры
&НаСервере
//Процедура выводит в таблицу данные геокдинга Гугл
//
//Параметры:
// ТекАдрес - Строка
Процедура ПроизвестиГеокодинг_Гугл()
Гугл = Новый HTTPСоединение("maps.googleapis.com");
ВременныйФайл = КаталогВременныхФайлов() + "Google_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Гугл.Получить("/maps/api/geocode/xml?address=" + ТекАдрес + "&language=ru&sensor=false", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по Google адрес: " + ТекАдрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ВременныйФайл);
ПостроительDOM = Новый ПостроительDOM;
ДокументДОМ = ПостроительDOM.Прочитать(ЧтениеXML);
ТаблицаРезультатов = ДокументДОМ.ПолучитьЭлементыПоИмени("result");
Если ДокументДОМ.ПолучитьЭлементыПоИмени("status")[0].ТекстовоеСодержимое <> "OK" ИЛИ ТаблицаРезультатов.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для ТекРезультат = 0 по ТаблицаРезультатов.Количество() -1 Цикл
СписокText = ТаблицаРезультатов[ТекРезультат].ПолучитьЭлементыПоИмени("formatted_address");
ЭлементыШиротаДолгота = ТаблицаРезультатов[ТекРезультат].ПолучитьЭлементыПоИмени("location");
Широта = ЭлементыШиротаДолгота[0].ПолучитьЭлементыПоИмени("lat")[0].ТекстовоеСодержимое;
Долгота = ЭлементыШиротаДолгота[0].ПолучитьЭлементыПоИмени("lng")[0].ТекстовоеСодержимое;
Если Широта = 0 ИЛИ Долгота = 0 Тогда
Продолжить;
КонецЕсли;
стрАдрес = ТаблицаАдресов.Добавить();
стрАдрес.Широта = Широта;
стрАдрес.Долгота = Долгота;
стрАдрес.Адрес = СписокText[0].ТекстовоеСодержимое;
КонецЦикла;
МассивВременныхФайлов.Добавить(ВременныйФайл);
КонецПроцедуры
&НаСервере
//Процедура выводит в таблицу данные геокдинга Рамблер
//
//Параметры:
// ТекАдрес - Строка
Процедура ПроизвестиГеокодинг_Рамблер()
ТемпАдрес = СтрЗаменить(ТекАдрес, " ", "+");
Рамблер = Новый HTTPСоединение("maps.rambler.ru");
ВременныйФайл = КаталогВременныхФайлов() + "Рамблер_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Рамблер.Получить("/search/?&a=search&q=" + ТемпАдрес + "&n=10", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по Рамблер адрес: " + ТекАдрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
а = 1;
Т = Новый ТекстовыйДокумент;
Т.Прочитать(ВременныйФайл);
СтрокаОтвет = Т.ПолучитьТекст();
Результат = РеквизитФормыВЗначение("Объект").UnicodeEncode(СтрокаОтвет);
Если Результат Тогда
СтруктураJSON = РеквизитФормыВЗначение("Объект").ЗаполнитьСтруктуруИзОтветаJSON(СтрокаОтвет);
КонецЕсли;
МассивРезультатов = СтруктураJSON.res;
//обрабатываем элементы массива - только адреса. POI можно обработать отдельно пожеланию
Для Каждого Результат Из МассивРезультатов Цикл
Для Каждого ТекРезультат Из Результат.matches Цикл
стрАдрес = ТаблицаАдресов.Добавить();
стрАдрес.Долгота = Число(ТекРезультат.x);
стрАдрес.Широта = Число(ТекРезультат.y);
Если Результат.type = "addr" Тогда //Результат.type = "poi" - содержит в себе список точек интереса
стрАдрес.Адрес = ТекРезультат.addr;
Иначе
стрАдрес.Адрес = ТекРезультат.name + " - " + ТекРезультат.addr;
КонецЕсли;
КонецЦикла;
КонецЦикла;
МассивВременныхФайлов.Добавить(ВременныйФайл);
КонецПроцедуры
&НаКлиенте
Процедура ОбратнПоискАдреса(Широта, Долгота, Адрес)
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "ReverseSearchAdres(" + Широта + "," + Долгота + ", """ + Адрес + """);";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
Процедура ТаблицаАдресовВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Если ЗначениеЗаполнено(ТаблицаАдресов[ВыбраннаяСтрока].Широта) И ЗначениеЗаполнено(ТаблицаАдресов[ВыбраннаяСтрока].Долгота) Тогда
СтандартнаяОбработка = Ложь;
КонецЕсли;
Широта = Формат(ТаблицаАдресов[ВыбраннаяСтрока].Широта, "ЧЦ=10; ЧДЦ=7; ЧРД=.; ЧРГ=");
Долгота = Формат(ТаблицаАдресов[ВыбраннаяСтрока].Долгота, "ЧЦ=10; ЧДЦ=7; ЧРД=.; ЧРГ=");
ОбратнПоискАдреса(Широта, Долгота, ТаблицаАдресов[ВыбраннаяСтрока].Адрес);
КонецПроцедуры
&НаКлиенте
Процедура ТекАдресПриИзменении(Элемент)
НайтиАдресНаКарте(ТекАдрес);
КонецПроцедуры
///////////////////////////////////////////////////////////////////////
///////////////////МАРШРУТИЗАЦИЯ, КЛАСТЕРА И ПОЛИГОН///////////////////////////////////////
///////////////////////////////////////////////////////////////////////
&НаКлиенте
Процедура ЭксплорерПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
ПолучитьКоординаты();
КонецПроцедуры
&НаКлиенте
Процедура ПостроитьМаршрут(Команда)
Если ТаблицаТочек.Количество() <= 1 Тогда
Предупреждение("Недостаточно точек для построение маршрута!");
Возврат;
КонецЕсли;
Если Поставщик = "Яндекс" Тогда
ПостроитьМаршрут_Яндекс();
ИначеЕсли Поставщик = "Гугл" Тогда
ПостроитьМаршрут_Гугл();
ИначеЕсли Поставщик = "Рамблер" Тогда
ПостроитьМаршрут_Рамблер();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
//Процедура выстраивает маршрут для Яндекса
//
//Параметры:
//
Процедура ПостроитьМаршрут_Яндекс()
ПараметрыМаршрута = ПолучитьПараметрыМаршрутаЯндекс();
ОчисткаКарты();
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "calcRoute(" + ПараметрыМаршрута + ")";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
//Функция получает массив точек, для передачи параметров в Яндекс
//
//Параметры:
//
//Возвращаемое значение:
// Строка
Функция ПолучитьПараметрыМаршрутаЯндекс()
Результат = "";
Результат = Результат + "[[" + СтрЗаменить(Строка(ТаблицаТочек[0].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[0].Долгота), ",", ".") + "],";
Для Ин = 1 По ТаблицаТочек.Количество() - 2 Цикл
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ин].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ин].Долгота), ",", ".") + "],";
КонецЦикла;
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Долгота), ",", ".") + "]]";
Возврат Результат;
КонецФункции
&НаКлиенте
//Процедура выстраивает маршрут для Гугл
//
//Параметры:
//
Процедура ПостроитьМаршрут_Гугл()
ПараметрыМаршрута = ПолучитьПараметрыМаршрутаГугл();
ОчисткаКарты();
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "calcRoute(" + ПараметрыМаршрута + ")";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
//Функция получает массив точек, для передачи параметров в Гугл
//
//Параметры:
//
//Возвращаемое значение:
// Строка
Функция ПолучитьПараметрыМаршрутаГугл()
Результат = "";
ВнутрМассив = "";
Результат = Результат + "[[" + СтрЗаменить(Строка(ТаблицаТочек[0].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[0].Долгота), ",", ".") + "],";
Если ТаблицаТочек.Количество() = 2 Тогда
Результат = Результат + "[],";
Иначе
Для Ин = 1 По ТаблицаТочек.Количество() - 2 Цикл
ВнутрМассив = ВнутрМассив + "[" + СтрЗаменить(Строка(ТаблицаТочек[ин].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ин].Долгота), ",", ".") + "],";
КонецЦикла;
Результат = Результат + "[" + Сред(ВнутрМассив, 1, СтрДлина(ВнутрМассив) - 1) + "],";
КонецЕсли;
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Долгота), ",", ".") + "]]";
Возврат Результат;
КонецФункции
&НаКлиенте
//Процедура выстраивает маршрут для Рамблера
//
//Параметры:
//
Процедура ПостроитьМаршрут_Рамблер()
ПараметрыМаршрута = ПолучитьПараметрыМаршрутаРамблер();
ОчисткаКарты();
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "calcRoute(" + ПараметрыМаршрута + ")";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
//Функция получает массив точек, для передачи параметров в Рамблер
//
//Параметры:
//
//Возвращаемое значение:
// Строка
Функция ПолучитьПараметрыМаршрутаРамблер()
Результат = "";
Результат = Результат + "[[" + СтрЗаменить(Строка(ТаблицаТочек[0].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[0].Долгота), ",", ".") + "],";
Для Ин = 1 По ТаблицаТочек.Количество() - 2 Цикл
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ин].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ин].Долгота), ",", ".") + "],";
КонецЦикла;
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Долгота), ",", ".") + "]]";
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура СоздатьКластер(Команда)
Если ТаблицаТочек.Количество() <= 1 Тогда
Предупреждение("Недостаточно точек для построение кластера!");
Возврат;
КонецЕсли;
ОчисткаКарты();
ПостроитьКластера();
КонецПроцедуры
&НаКлиенте
Процедура ПостроитьКластера()
Кол = ТаблицаТочек.Количество();
Индекс = 1;
Для Каждого ТекСтрока Из ТаблицаТочек Цикл
Широта = формат(ТекСтрока.Широта, "ЧРД=.");
Долгота = формат(ТекСтрока.Долгота, "ЧРД=.");
СодержимоеТочки = "Содерижмое точки"; //опять же можно вставить свое название
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "addToPointArray(" + Широта + "," + Долгота + ", '" + ТекСтрока.Точка + "', """ + СодержимоеТочки + """);";
Элементы.Эксплорер.document.getElementById("WebClient").click();
Состояние("Обработан " + Индекс + " из " + кол);
Индекс = Индекс + 1;
КонецЦикла;
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "drawCluster();";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьВсе(Команда)
ОчисткаКарты();
ТаблицаТочек.Очистить();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьКарту(Команда)
ОчисткаКарты();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьТаблицу(Команда)
ТаблицаТочек.Очистить();
КонецПроцедуры
&НаКлиенте
//Процедура получает координаты установленной точки
Процедура ПолучитьКоординаты()
Попытка
ЧислоТип = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 12));
КоординатаX = Элементы.Эксплорер.document.getElementById("CoordX").value;
КоординатаX = ЧислоТип.ПривестиЗначение(КоординатаX);
КоординатаY = Элементы.Эксплорер.document.getElementById("CoordY").value;
КоординатаY = ЧислоТип.ПривестиЗначение(КоординатаY);
Кол = ТаблицаТочек.Количество();
Если КоординатаX > 0 И КоординатаY > 0 И (Кол = 0 Или КоординатаX <> ТаблицаТочек[Кол - 1].Широта И КоординатаY <> ТаблицаТочек[Кол - 1].Долгота) Тогда
НоваяСтрока = ТаблицаТочек.Добавить();
НоваяСтрока.Точка = "Точка" + ТаблицаТочек.Количество();
НоваяСтрока.Широта = КоординатаX;
НоваяСтрока.Долгота = КоординатаY;
КонецЕсли;
Исключение
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПострениеПолигона(Команда)
Если ТаблицаТочек.Количество() <= 1 Тогда
Предупреждение("Недостаточно точек для построение полигона!");
Возврат;
КонецЕсли;
ОчисткаКарты();
ПостроитьПолигон();
КонецПроцедуры
&НаКлиенте
//Процедура выстраивает маршрут для Рамблера
//
//Параметры:
//
Процедура ПостроитьПолигон()
МассивТочек = "[";
Для Каждого ТекТочка Из ТаблицаТочек Цикл
Широта = формат(ТекТочка.Широта, "ЧРД=.");
Долгота = формат(ТекТочка.Долгота, "ЧРД=.");
МассивТочек = МассивТочек + "[" + Широта + "," + Долгота + "],";
КонецЦикла;
МассивТочек = Сред(МассивТочек, 1, СтрДлина(МассивТочек) - 1) + "]";
Цвет16 = Получить16Цвет();
Название = "Полигон";//вставить свое
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "createPolygon(" + МассивТочек + ", '" + Название + "', '" + Цвет16 + "');";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаСервере
//Функция возвращает значение случайного цвета в 16-ричном формате
//
//Параметры:
// нет
//Возвращаемое значение:
// Строка
Функция Получить16Цвет()
Результат = "";
Строка16 = "0123456789ABCDEF";
ГСЧ = Новый ГенераторСлучайныхЧисел;
Результат = "#";
Для н = 1 По 6 Цикл
м = ГСЧ.СлучайноеЧисло(1, 16);
Результат = Результат + Сред(Строка16, м, 1);
КонецЦикла;
Возврат Результат;
КонецФункции
Категория:
COM-объекты, WMI, WSH Формирование HTML-документа, содержащего ссылки на объекты базы данных В данной статье рассматривается способ программного формирования HTML документа, содержащего ссылки на объекты базы данных 1С, такие как справочники, документы и т.д. Показан пример построения обработчика события OnClick ПоляHTMLДокумента, для обработки клика на html-ссылке.
Предисловие
Однажды, дописывая обработку, создающую и модифицирующую, не суть важно какие документы, я подумал, что неплохо было бы вывести для пользователя некое резюме:
“Создан документ такой-то”
“Изменен документ такой-то” и т.д.
От обычного, в таких случаях, вывода информации в окно сообщений я сразу отказался, так как не удобно это, сначала читать в окне сообщений “Создан документ … ” а потом запоминать его номер, открывать соответствующий журнал (или форму списка) и искать там этот документ. А если документов много и пользователь хочет посмотреть все документы?(или выборочно) Насколько это неудобно я убедился при отладке обработки …
То, что в форме есть элемент управления именуемый ПолеHTMLДокумента я конечно знал, но вот представилась возможность познакомиться с ним поближе. Было решено реестр обработанных документов выводить в виде html документа содержащего ссылки на эти самые документы, а по клику на ссылке открывать форму соответствующего документа. Здесь мне многие могут возразить: “А почему бы для этих целей не использовать обычный макет, выводимый в табличный документ, а для открытия документов использовать расшифровку? И чем Ваш способ лучше?” Отвечаю: Конечно можно использовать, и мой способ ничем не лучше. Он просто другой. Ведь у хорошего программиста для решения одной задачи должно быть в арсенале несколько инструментов.
Итак, перейдем от слов к делу, в рамках данной статьи рассмотрим следующую задачу: Сформировать html-документ, содержащий ссылки на элементы справочника номенклатура, по клику требуется открывать форму соответствующего элемента. Создаем новый отчет, его форму, на форме размещаем элемент управления ПолеHTMLДокумента.
Текст модуля формы:
Код 1C v 8.х Процедура ДобавитьТекстHTML(ТекстHTML, Элемент);
// Ссылку будем формировать хитро:
// Предполагаем что символ "-" не входит в имена объектов метаданных,
// учавствующих в формировании html
// Тогда ссылка будет иметь следующий вид:
// Номенклатура-d341d377-b3b1-11dc-a100-0011d85708ff
// Передавать нашу ссылку будем через атрибут id
СсылкаНаЭлемент = Элемент.Метаданные().Имя+"-"
+Элемент.Ссылка.УникальныйИдентификатор();
ТекстHTML.ДобавитьСтроку("<A id=""" + СсылкаНаЭлемент + """ href= """
+ Элемент + """ >"+Элемент+"</A><BR>");
КонецПроцедуры
Процедура ДействияФормыСформировать(Кнопка)
Запрос = Новый Запрос("
|ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура");
ТекстHTML = Новый ТекстовыйДокумент;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДобавитьТекстHTML(ТекстHTML, Выборка.Ссылка);
КонецЦикла;
ЭлементыФормы.ПолеHTMLДокумента.УстановитьТекст(ТекстHTML.ПолучитьТекст());
КонецПроцедуры
Ну вот html мы сформировали, теперь чтобы ссылки “ожили” надо написать обработчик события OnClick элемента управления ПолеHTMLДокумента.
Код 1C v 8.х // Функция получает элемент - <A> по данному элементу
// Производит поиск элемента <A> среди родительских элементов данного
//
// Параметры:
// Элемент - COMОбъект, элемент HTML документа,
// по которому нужно найти ссылку
//
// Возвращаемое значение:
// COMОбъект - если ссылка обнаружена, иначе - Неопределено
Функция НайтиСсылку(Элемент)
Врем = Элемент;
Пока Врем <> Неопределено Цикл
Если НРег(Врем.tagName) = "a" Тогда
Возврат Врем;
КонецЕсли;
Врем = Врем.parentElement;
КонецЦикла;
Возврат Неопределено;
КонецФункции // НайтиСсылку(Элемент)
Процедура ПолеHTMLДокументаonclick(Элемент, pEvtObj)
htmlElement = НайтиСсылку(pEvtObj.srcElement);
// Анализируем если произошло нажание не ссылку
Если htmlElement <> Неопределено Тогда
// Если у ссылки есть идентификатор
Если СокрЛП(htmlElement.id) <> "" Тогда
// Получаем адрес ссылки из атрибута id
СсылкаНаЭлемент = htmlElement.id;
Разделитель = Найти(СсылкаНаЭлемент,"-");
Если Разделитель > 0 Тогда
// Получаем тип элемента
ТипЭлемента = Лев(СсылкаНаЭлемент,Разделитель-1);
// Получаем УникальныйИдентификатор
ГУИД = Сред(СсылкаНаЭлемент,Разделитель+1);
Справочники[ТипЭлемента].ПолучитьСсылку(
Новый УникальныйИдентификатор(ГУИД)).ПолучитьФорму().Открыть();
КонецЕсли;
// Не отработали нажатие
pEvtObj.returnValue = Ложь;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Всё можно пробовать!
Заключение
Обратите внимание что ссылку я формировал следующим образом:
<ИмяОбъектаМетаданных>-<УникальныйИдентификатор> это сделано для того, чтобы в обработчике onclick можно было определить к какому объекту метаданных относится данный УникальныйИдентификатор, потому что имея ТОЛЬКО УникальныйИдентификатор невозможно определить к какому объекту метаданных он относиться. Точнее возможно, но уж слишком долго и неудобно – путем перебора всех метаданных в цикле, для каждого объекта метаданных выполнять попытку <ОбъектМетаданных>.ПолучитьСсылку(Новый УникальныйИдентификатор(НашУникальныйИдентификатор))
Хотя в нашем примере только один справочник, и указывать его вид было необязательно, и так понятно что это УникальныйИдентификатор элемента справочника Номенклатура, но вдруг Вам потребуется работать с несколькими справочниками, вот тут то мой способ задания ссылки Вам и пригодится.
Скачивать файлы может только зарегистрированный пользователь!
P.S. Платформа 8.2 имеет встроенный механизм работы со ссылками на объекты БД и данная задача наверняка упростится, но это уже другая тема.
Источник:
obrabotki.com Категория:
Работа с Интернет, Почтой (Mail), FTP