Как получить координаты выделенной области на Яндекс Карте? На одном проекте потребовалось получать координаты выделенной области на яндекс карте, после долгих изучений получилось следующее:
Вид Формы: На карте выделяете объект, нажимаете кнопку Получить координаты выделенной области и заполняется таблица координат
Код инициализации карты и обработчик кнопки получения координат:
Код 1C v 8.х Процедура ИнициализироватьКарту()
ПутьКФайлу = КаталогВременныхФайлов()+"yamaps.html";
Ф = новый Файл(ПутьКФайлу);
Если Ф.Существует() Тогда
УдалитьФайлы(ПутьКФайлу);
КонецЕсли;
Т = новый ТекстовыйДокумент;
ТД = ЭтотОбъект.ПолучитьМакет("МакетЯндекс");
Т.УстановитьТекст(ТД.ПолучитьТекст());
Т.Записать(ПутьКФайлу);
ЭлементыФормы.Эксплорер.Перейти(ПутьКФайлу);
КонецПроцедуры
Процедура ВыполнитьСкрипт(Команда) Экспорт
ЭлементыФормы.Эксплорер.document.getElementById("WebClientOperation").value = Команда;
ЭлементыФормы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
Процедура ПриОткрытии()
ИнициализироватьКарту();
КонецПроцедуры
Процедура ПолучитьКоординатыНажатие(Элемент)
ВыполнитьСкрипт("GetGEO();");
ТекКоординаты=ЭлементыФормы.Эксплорер.document.getElementById("geometry").innerText;
ТекКоординаты=СтрЗаменить(ТекКоординаты,"Координаты: [","");
МассивСтроки = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(ТекКоординаты, "], [ ");
Точки.Очистить();
Для Каждого стр из МассивСтроки Цикл
Текстр=СтрЗаменить(стр,"[","");
Текстр=СтрЗаменить(Текстр,"]","");
Текстр=СокрЛП(Текстр);
нСтрок=Точки.Добавить();
симвЗапятой=Найти(Текстр,",");
нСтрок.Широта=Лев(Текстр,симвЗапятой-1);
нСтрок.Долгота=Сред(Текстр,симвЗапятой+2,СтрДлина(Текстр));
КонецЦикла;
//Сообщить(ТекКоординаты);
КонецПроцедуры
Макет
Код VBS <!DOCTYPE html">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map { height: 100% }
</style>
<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
<script src="http://yandex.st/jquery/1.6.4/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var index = 1;
var MyMap, route;
var clusterer;
var PointArray = [];
var noclick = false;
ymaps.ready(init);
function init(){
myMap = new ymaps.Map ("map", {
center: [55.75, 37.62],
zoom: 10
}),
polygon = new ymaps.GeoObject({
geometry: {
type: "Polygon",
coordinates: []
}
});
myMap.behaviors.enable('scrollZoom');
myMap.behaviors.disable('dblClickZoom');
myMap.events.add('click', function (e) {
if (!noclick) {
// addMarker(e.get('coords'));
}else{
noclick = false;
}
});
myMap.events.add('drag end', function (e) {
noclick = true;
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
});
// создадим кластеризатор и запретим приближать карту при клике на кластеры
//clusterer = new ymaps.Clusterer({clusterDisableClickZoom: true, synchAdd: true});
//myMap.geoObjects.add(clusterer);
myMap.geoObjects.add(polygon);
polygon.editor.startDrawing();
$('input').attr('disabled', false);
// Обработка нажатия на любую кнопку.
$('input').click(
function () {
// Отключаем кнопки, чтобы на карту нельзя было
// добавить более одного редактируемого объекта (чтобы в них не запутаться).
$('input').attr('disabled', true);
GetGEO();
});
}
function addMarker(coordPosition){
myPlacemark = new ymaps.Placemark(coordPosition, {
// Свойства
// Текст метки
iconContent: 'Точка'+index
}, {
// Опции
// Иконка метки будет растягиваться под ее контент
preset: 'islands#blueStretchyIcon'
});
myMap.geoObjects.add(myPlacemark);
document.getElementById('CoordX').value = coordPosition[0].toPrecision(15);
document.getElementById('CoordY').value = coordPosition[1].toPrecision(15);
index++;
}
function calcRoute(options){
ymaps.route(options, {
// Опции маршрутизатора
mapStateAutoApply: true, // автоматически позиционировать карту
avoidTrafficJams: false // Учитывать пробки
}).then(
function (router) {
route = router;
myMap.geoObjects.add(route);
//заполняем и сохраняем инфо про маршрут
document.getElementById('RouteInfo').value = "Длина маршрута - " + route.getHumanLength() + ". Время - " + route.getHumanJamsTime();
//генерация события для перехвата в 1С
var evt = document.createEventObject();
document.body.fireEvent('ondatasetcomplete', evt);
},
function (error) {
alert("Возникла ошибка: " + error.message);
});
}
function calcLine(options){
var poly = new ymaps.Polyline(options, {
hintContent: "Маршрут",
balloonContent: "Маршрут экспедитора",
balloonContentHeader: "",
balloonContentBody: "",
balloonContentFooter: ""
}, {
cursor: "pointer",
draggable: false,
hasBalloon: true,
hasHint: true,
interactiveZIndex: false,
opacity: 1,
openBalloonOnClick: true,
openEmptyBalloon: false,
openEmptyHint: false,
openHintOnHover: true,
strokeColor: '#E33926',
strokeOpacity: 0.8,
strokeStyle: '',
strokeWidth: 5,
syncOverlayInit: false,
visible: true
});
myMap.geoObjects.add(poly);
myMap.setBounds(poly.geometry.getBounds());
}
function Reset(){
// Удаляем все геообъекты на карте
myMap.geoObjects.removeAll();
PointArray = [];
index = 1;
}
function ChangeCityMSK(){
myMap.panTo([55.75, 37.62], {
flying: 1
});
}
function ChangeCitySPB(){
myMap.panTo([59.938531, 30.313497], {
flying: 1
});
}
function ChangeCityKRAS(){
myMap.panTo([45.04, 38.97], {
flying: 1
});
}
function ChangePlace(k,d){
myMap.panTo([k, d], {
flying: 1
});
}
function FindAdres(Adres){
Reset();
var myGeocoder = ymaps.geocode(Adres);
myGeocoder.then(
function (res){
var firstGeoObject = res.geoObjects.get(0);
if(firstGeoObject != null){
myMap.panTo(
// Координаты нового центра карты
firstGeoObject.geometry.getCoordinates(), {
/* Опции перемещения:
разрешить уменьшать и затем увеличивать зум
карты при перемещении между точками
*/
flying: true
}
);
myPlacemark = new ymaps.Placemark(firstGeoObject.geometry.getCoordinates(), {
// Свойства
// Текст метки
iconContent: Adres
}, {
// Опции
// Иконка метки будет растягиваться под ее контент
preset: 'islands#blueStretchyIcon'
});
myMap.geoObjects.add(myPlacemark);
}else{
alert("Ничего не найдено");}
}
);
}
function ReverseSearchAdres(CoordX, CoordY, Adres){
Reset();
var CoordPosition = [CoordX, CoordY];
myMap.panTo(
// Координаты нового центра карты
CoordPosition, {
/* Опции перемещения:
разрешить уменьшать и затем увеличивать зум
карты при перемещении между точками
*/
flying: true
}
);
myPlacemark = new ymaps.Placemark(CoordPosition, {
// Свойства
// Текст метки
iconContent: Adres
}, {
// Опции
// Иконка метки будет растягиваться под ее контент
preset: 'islands#blueStretchyIcon'
});
myMap.geoObjects.add(myPlacemark);
}
function addToPointArrayM(CoordX, CoordY, TextC, Text){
var CoordPosition = [CoordX, CoordY];
myPlacemark = new ymaps.Placemark(CoordPosition, {
// Свойства
// Текст метки
iconContent: Text
}, {
// Опции
// Иконка метки будет растягиваться под ее контент
preset: TextC
});
myMap.geoObjects.add(myPlacemark);
}
function addToPointArrayPointOne(CoordX, CoordY, ID, Text){
var point = new ymaps.GeoObject({
geometry: {type: "Point", coordinates: [CoordX, CoordY>,
properties: {
clusterCaption: ID,
iconContent: ID,
hintContent: ID,
balloonContent: Text,
balloonContentBody: Text
}
});
myMap.geoObjects.add(point);
}
function addToPointArray(CoordX, CoordY, ID, Text){
var point = new ymaps.GeoObject({
geometry: {type: "Point", coordinates: [CoordX, CoordY>,
properties: {
clusterCaption: ID,
iconContent: ID,
hintContent: ID,
balloonContent: Text,
balloonContentBody: Text
}
});
PointArray.push(point);
}
function drawCluster(){
clusterer.add(PointArray);
myMap.geoObjects.add(clusterer);
}
function createPolygon(ArrayPoint, Name, color) {
// Создаем многоугольник
myPolygon = new ymaps.Polygon([
// Координаты вершин внешней границы многоугольника.
ArrayPoint
], {
//Свойства
hintContent: Name
}, {
// Опции.
// Цвет заливки (зеленый)
fillColor: color,
// Цвет границ (синий)
strokeColor: '#0000FF',
// Прозрачность (полупрозрачная заливка)
opacity: 0.6,
// Ширина линии
strokeWidth: 5,
// Стиль линии
strokeStyle: 'shortdash'
});
myMap.geoObjects.add(myPolygon);
}
function WebClientClick() {
//очистка перед кликом координат, иначе после клика в упр. формах идет считывание координат
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
var WebClientOperation = document.getElementById("WebClientOperation").value;
//alert(WebClientOperation);
switch (WebClientOperation) {
case "0": // ничего не делаем
var a = 1;
default: // запускаем функцию
eval(WebClientOperation);
}
document.getElementById('WebClientOperation').value = "0";
}
function GetGEO(){
polygon.editor.stopEditing();
printGeometry(polygon.geometry.getCoordinates());
}
// Выводит массив координат геообъекта в <div id="geometry">
function printGeometry (coords) {
$('#geometry').html('Координаты: ' + stringify(coords));
function stringify (coords) {
var res = '';
if ($.isArray(coords)) {
res = '[ ';
for (var i = 0, l = coords.length; i < l; i++) {
if (i > 0) {
res += ', ';
}
res += stringify(coords[i]);
}
res += ' ]';
} else if (typeof coords == 'number') {
res = coords.toPrecision(6);
} else if (coords.toString) {
res = coords.toString();
}
return res;
}
}
</script>
</head>
<body>
<div id="geometry"/></div>
<div id="map" style="width:100%; height:100%"></div>
<input type="hidden" id="CoordX" name="CoordX" value="0"></input>
<input type="hidden" id="CoordY" name="CoordY" value="0"></input>
<input type="hidden" id="RouteInfo" name="RouteInfo" value=""></input>
<input type="hidden" id="WebClientOperation" name="WebClientOperation" value="0"></input>
<input type="hidden" id="WebClient" name="WebClient" onclick="WebClientClick();"></input>
<!-- <input type="button" value="Завершить редактирование" id="stopEditPolyline"/> -->
</body>
</html>
Категория:
Географическая схема Фоновые задания: Пример запуска выполнения процедуры / функции на сервере Как в 1С производится запуск фоновых заданий, каким образом можно получить список заданий при помощи метода "ПолучитьФоновыеЗадания()?
В одном проекте понадобилось запускать выполнение выгрузки на сайт с сервера.
Пользователь на своем клиенте открывает обработку, устанавливает параметры и нажимает выгрузить.
Выгрузка идет не с компьютера клиента, а создается фоновое задание на сервере!
На клиенте в модуле Кнопки Выгрузить:
Код 1C v 8.3 Процедура КоманднаяПанель1ВыгрузитьНаСайт(Кнопка)
//Выгружается фоновым заданием на серваке
ПараметрыФоновогоЗадания = Новый Массив;
ПараметрыФоновогоЗадания.Добавить(Группа); //Группа номенклатуры
ФоновыеЗадания.Выполнить("МодульРегламентныхЗаданий.ВыгрузкаПрайсаНАФТП",
ПараметрыФоновогоЗадания, Новый УникальныйИдентификатор,
"Выгрузка прайса на сайт");
ПоказатьОповещениеПользователя("Выгрузка прайса на сайт", ,"Запущено задание выгрузки прайса на сайт, проверьте данные на сайте через 2-3 минуты...", БиблиотекаКартинок.Информация32);
ПараметрыФоновогоЗадания - это переменные функции, они задаются по порядку как определены в вызываемой функции.
На сервере в общем модуле МодульРегламентныхЗаданий:
Код 1C v 8.3 Процедура ВыгрузкаПрайсаНАФТП(Группа) Экспорт
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| ПрайсЛист1СрезПоследних.НоменклатураПрайса,
| ПрайсЛист1СрезПоследних.Цена
|ИЗ
| РегистрСведений.ПрайсЛист.СрезПоследних(, Поставщик = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) КАК ПрайсЛист1СрезПоследних
|ГДЕ
| &Условие
| И ПрайсЛист1СрезПоследних.НоменклатураПрайса.ИДдляСайта > 0";
Если ЗначениеЗаполнено(Группа) Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Условие", "ПрайсЛист1СрезПоследних.НоменклатураПрайса В ИЕРАРХИИ(&НоменклатураПрайса)")
Иначе
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Условие", "ИСТИНА")
КонецЕсли;
Запрос.УстановитьПараметр("НоменклатураПрайса", Группа);
Выборка = Запрос.Выполнить().Выбрать();
Текст = Новый ТекстовыйДокумент;
Пока Выборка.Следующий() Цикл
НомПрайса = Выборка.НоменклатураПрайса;
ЦенаА = Выборка.Цена;
Цена = Ценообразование.ОкруглитьЦену(ЦенаА * ( 1 + НомПрайса.Наценка20 / 100) + НомПрайса.Надбавка20, НомПрайса.ПорядокОкругления, НомПрайса.ОкруглятьВБольшуюСторону);
Если Цена > 0 Тогда
Текст.ДобавитьСтроку(""+Формат(НомПрайса.ИДдляСайта, "ЧГ=0")+";"+Формат(Цена, "ЧГ=0"));
КонецЕсли;
КонецЦикла;
// запись в текстовый файл
ПутьКФайлВыгр = "\\FG-1\1c_data\naSite\vigruz.csv";//"D:\!!!For1C!!!\naSite\vigruz.csv";
Текст.Записать(ПутьКФайлВыгр, "windows-1251");
КаталогНаSFTPСервере = "/sitetest.ru/public_html/p";
Попытка
ИмяПользователя = "serveruser";
ПарольПользователя = "password";
Сервер = "192.253.6.47";
Порт = "21";
Прокси = Новый ИнтернетПрокси();
Прокси.Пользователь = ИмяПользователя;
Прокси.Пароль = ПарольПользователя;
FTPСоединение = Новый FTPСоединение(Сервер,,ИмяПользователя,ПарольПользователя,,Ложь);
FTPСоединение.УстановитьТекущийКаталог(КаталогНаSFTPСервере);
//FTPСоединение.ПассивныйРежим(Ложь);
ТекущийКаталог = FTPСоединение.ТекущийКаталог();
Исключение
КонецПопытки;
FTPСоединение.Записать(ПутьКФайлВыгр,"vigruz.csv");
//Вызов PHP скрипта для иморта данных из csv файла на сайт
НТТР = Новый HTTPСоединение("sitetest.ru");
ФайлРезультата = ПолучитьИмяВременногоФайла();
НТТР.Получить("/p/import_price.php", ФайлРезультата);
КонецПроцедуры
Как Получить фоновые задания?
Напишем в процедуре обработки нажания следующий код:
Код 1C v 8.2 УП &НаКлиенте
Процедура ПолучитьФоновыеЗадания(Команда)
ПолучитьФоновыеЗаданияНаСервере();
КонецПроцедуры
Текст процедуры на сервере:
Код 1C v 8.2 УП &НаСервере
Процедура ПолучитьФоновыеЗаданияНаСервере()
ПараметрыОтбора = Новый Структура("Наименование", "Тестовое задание");
СписокФоновыхЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(ПараметрыОтбора);
Для каждого Задание Из СписокФоновыхЗаданий Цикл
Сообщить(Задание.Наименование);
КонецЦикла;
КонецПроцедуры // ПолучитьФоновыеЗаданияНаСервере()
В окно сообщений выведутся наименования выполняющихся и выполненных в 1С фоновых заданий с наименованием "Тестовое задание", так как мы сделали отбор именно по этому наименованию.
Категория:
Регламентные задания, Фоновые задания ДеревоЗначений в ТекстовыйДокумент Код 1C v 8.2 УП // Выводит данные ДереваЗначений в ТекстовыйДокумент, пригодный к рассмотрению в отладчике, окне сообщений и показу.
//
// Параметры:
// рВетка - дерево значений, подлежащее выводу. Может иметь почти любую глубину иерархии, количество и тип колонок. Если хватит
// объявленных позиционных строк-заполнителей, всё поместится. Если иерархия слишком глубока, строки просто надо нарастить;
// рТекст - на входе должен быть равен Неопределено; на выходе по окончании работы содержит результатный текстовый документ;
// рПараметры - структура дополнительных настроек, допустимые ключи:
// Колонки - структура колонок, которые подлежат выводу. Если пуста или имеет тип, отличный от структуры, выводятся все колонки;
// если в ключах структуры указаны имена колонок, будут выведены только они. В значениях структуры можно передать строковое
// представление формата, согласно которому должны будут форматироваться выводимые значения. По умолчанию формата нет;
// ПоказыватьУровни - булево, управляет выводом №№ уровней (метод Уровень()), по умолчанию выключено;
// ШагОтступа - число, определяющее шаг в символах, используемый для показа псевдографики иерархии веток в дереве.
//
&НаСервереБезКонтекста
Процедура ВывестиДеревоЗначенийВТекст(Знач рВетка,рТекст,Знач рПараметры=Неопределено)
Попытка
Если рТекст=Неопределено Тогда // первая итерация, шапочный вызов исходной части
//---------------------------------------------------------------------------------------------------------------------------
// Разбираем входные данные
Если ТипЗнч(рВетка)<>Тип("ДеревоЗначений") Тогда Возврат КонецЕсли;
Если ТипЗнч(рПараметры)<>Тип("Структура") Тогда рПараметры=Новый Структура КонецЕсли;
стрКолонок=?(рПараметры.Свойство("Колонки"),рПараметры.Колонки,Неопределено);
Если ТипЗнч(стрКолонок)<>Тип("Структура") Тогда стрКолонок=Новый Структура КонецЕсли;
рПоказыватьУровни=?(рПараметры.Свойство("ПоказыватьУровни"),рПараметры.ПоказыватьУровни,Ложь); // затратное дело, кстати
рШагОтступа=?(рПараметры.Свойство("ШагОтступа"),рПараметры.ШагОтступа,2); // для отображения отступа в колонке иерархии
//---------------------------------------------------------------------------------------------------------------------------
// Определяем максимальное количество уровней
// Также можно получить максимальный уровень, "плоско" перебрав все строки (например, получив их через НайтиСтроки)
// и в цикле для каждой вызывая Уровень() и определяя максимум.
// Вариант через СКД и служебное поле "Уровень" ни на одной известной мне платформе не работоспособен (нехватка памяти).
//
//
//рДеревоДляТеста=КакНибудьСкопироватьДерево(рВетка);
//рДеревоДляТеста.Колонки.Вставить(0,"_Level",Новый ОписаниеТипов("Булево")); // самый экономный вариант, с сохранением иерархии
//мНенужных=Новый Массив;
//Для й=1 По рДеревоДляТеста.Колонки.Количество()-1 Цикл
// мНенужных.Добавить(рДеревоДляТеста.Колонки[й]);
//КонецЦикла;
//Для каждого кол Из мНенужных Цикл
// рДеревоДляТеста.Колонки.Удалить(кол);
//КонецЦикла;
//
рДеревоДляТеста=рВетка; // пока сериализуем прямо всё дерево (неоптимально, но...)
рЗапись=Новый ЗаписьXML;
рЗапись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(рЗапись,рДеревоДляТеста);
стро=рЗапись.Закрыть();
//
стро=СтрЗаменить(стро,"xmlns=","xmlns:myns1C="); // иначе не будет работать XPath
//
рЧтение=Новый ЧтениеXML;
рЧтение.УстановитьСтроку(стро);
постр=Новый ПостроительDOM;
рДокументДОМ=постр.Прочитать(рЧтение);
рВыражение="/ValueTree/row"; максКолвоУровней=1;
рРазыменователь=Новый РазыменовательПространствИменDOM(рДокументДОМ);
Пока Истина Цикл
#Если Клиент Тогда
ОбработкаПрерыванияПользователя();
#КонецЕсли
рРезультат=рДокументДОМ.ВычислитьВыражениеXPath(рВыражение,рДокументДОМ,рРазыменователь,ТипРезультатаDOMXPath.Любой);
Если рРезультат.ПолучитьСледующий()=Неопределено Тогда Прервать КонецЕсли;
рВыражение=рВыражение+"/row";
максКолвоУровней=максКолвоУровней+1;
КонецЦикла;
максКолвоУровней=максКолвоУровней-1; // можно и так: СтрЧислоВхождений(рВыражение,"/row")-1;
//---------------------------------------------------------------------------------------------------------------------------
// готовим исходный макет вывода
строПробелы=" ";
строРазделители="===============================================================================================";
строОтступы="___________________________________________________________________________________________"; // тут нужны чуть для другого
//
секШапка1="|[_HCS"+Лев(строПробелы,максКолвоУровней*рШагОтступа)+"]|"; // HierarchyColumnShow
секГорРазделитель1="|"+Лев(строОтступы,максКолвоУровней*рШагОтступа+6)+"|"; // здесь именно Отступы!
рШиринаКолонкиИерархии=СтрДлина(секШапка1)-2;
строПолейШапки="#Поле _HCS
| #Выравнивание Центр";
строПолейЗаписи="";
//
Если рПоказыватьУровни Тогда
секШапка1=секШапка1+"[_Level]|";
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,8)+"|";
строПолейШапки=строПолейШапки+"
|#Поле _Level
| #Выравнивание Центр";
строПолейЗаписи="#Поле _Level
| #Выравнивание Центр
| #Забивать Истина";
КонецЕсли;
//
мИменКолонок=Новый Массив;
Для каждого кол Из рВетка.Колонки Цикл
Если стрКолонок.Количество()<>0 и не стрКолонок.Свойство(кол.Имя) Тогда Продолжить КонецЕсли; // чётко указаны конкретные колонки
рДлинаИмениКолонки=СтрДлина(кол.Имя);
рНужнаяШирина=Макс(?(кол.Ширина<3,10,кол.Ширина),рДлинаИмениКолонки);
// к сожалению, ключевое слово "#Поля" неприменимо - платформа падает - поэтому делаем всё сами
секШапка1=секШапка1+"["+кол.Имя+Лев(строПробелы,рНужнаяШирина-рДлинаИмениКолонки)+"]|";
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,рНужнаяШирина+1)+"=|";
строПолейШапки=строПолейШапки+"
|#Поле "+кол.Имя+"
| #Выравнивание Центр";
рОписТипов=кол.ТипЗначения;
Если рОписТипов.Типы().Количество()=1 и рОписТипов.СодержитТип(Тип("Булево")) Тогда
рВыравнивание="Центр";
ИначеЕсли рОписТипов.СодержитТип(Тип("Число")) Тогда
рВыравнивание="Право";
ИначеЕсли рОписТипов.СодержитТип(Тип("Строка")) и рОписТипов.КвалификаторыСтроки.Длина=0 Тогда
рВыравнивание="ПоШирине";
Иначе
рВыравнивание="Лево";
КонецЕсли;
строПолейЗаписи=строПолейЗаписи+?(ПустаяСтрока(строПолейЗаписи),"",Символы.ПС)+"#Поле "+кол.Имя+"
| #Выравнивание "+рВыравнивание;
Попытка
Если ЗначениеЗаполнено(стрКолонок[кол.Имя]) Тогда // указан формат, уточняющий показ колонки
строПолейЗаписи=строПолейЗаписи+"
| #Формат """+СокрЛП(стрКолонок[кол.Имя])+"""";
КонецЕсли;
Исключение
КонецПопытки;
мИменКолонок.Добавить(кол.Имя);
КонецЦикла;
секШапка2=СтрЗаменить(СтрЗаменить(секШапка1,"[","<"),"]",">");
секЗапись1=секШапка1; секЗапись2=секШапка2; // пусть они по дизайну пока не отличаются
секГорРазделитель2=СтрЗаменить(СтрЗаменить(секГорРазделитель1,"=","-"),"|","+");
// обработаем нормальное обрамление шапки колонки иерархии
секГорРазделитель1=СтрЗаменить(секГорРазделитель1,"_","=");
секГорРазделитель2=СтрЗаменить(секГорРазделитель2,"_"," ");
//
тМакет=Новый ТекстовыйДокумент;
тМакет.ДобавитьСтроку("#Область Шапка");
тМакет.ДобавитьСтроку(строПолейШапки);
тМакет.ДобавитьСтроку(секГорРазделитель1);
тМакет.ДобавитьСтроку(секШапка1);
тМакет.ДобавитьСтроку(секШапка2);
тМакет.ДобавитьСтроку(секГорРазделитель1);
тМакет.ДобавитьСтроку("#КонецОбласти");
тМакет.ДобавитьСтроку("");
тМакет.ДобавитьСтроку("#Область Запись");
тМакет.ДобавитьСтроку(строПолейЗаписи);
тМакет.ДобавитьСтроку(секЗапись1);
тМакет.ДобавитьСтроку(секЗапись2);
тМакет.ДобавитьСтроку(секГорРазделитель2);
тМакет.ДобавитьСтроку("#КонецОбласти");
рПараметры.Вставить("ИсходныйМакет",тМакет); // пусть будет
//---------------------------------------------------------------------------------------------------------------------------
// Запускаем вывод в итоговый документ
рТекст=Новый ТекстовыйДокумент;
сек=тМакет.ПолучитьОбласть("Шапка");
сек.Параметры._HCS="Иерархия";
Для каждого имякол Из мИменКолонок Цикл
кол=рВетка.Колонки[имякол];
сек.Параметры[кол.Имя]=?(ПустаяСтрока(кол.Заголовок),кол.Имя,кол.Заголовок);
КонецЦикла;
рТекст.Вывести(сек);
//
пар=Новый Структура;
пар.Вставить("МассивИмёнКолонок",мИменКолонок);
пар.Вставить("ТекущаяСекция",тМакет.ПолучитьОбласть("Запись"));
пар.Вставить("ШиринаКолонкиИерархии",рШиринаКолонкиИерархии);
пар.Вставить("ПоказыватьУровни",рПоказыватьУровни);
пар.Вставить("Отступ",0);
пар.Вставить("ШагОтступа",рШагОтступа);
ВывестиДеревоЗначенийВТекст(рВетка,рТекст,пар);
Иначе
// очередная итерация, вывод в текстовый документ
мИменКолонок=рПараметры.МассивИмёнКолонок;
рСекция=рПараметры.ТекущаяСекция;
рОтступ=рПараметры.Отступ;
рШиринаКолонкиИерархии=рПараметры.ШиринаКолонкиИерархии;
рПоказыватьУровни=рПараметры.ПоказыватьУровни;
//
строОтступы="_________________________________________________________________________________________________________";
строПробелы=" ";
//
пар=Новый Структура;
пар.Вставить("МассивИмёнКолонок",мИменКолонок);
пар.Вставить("ТекущаяСекция",рПараметры.ТекущаяСекция);
пар.Вставить("ШиринаКолонкиИерархии",рШиринаКолонкиИерархии);
пар.Вставить("ПоказыватьУровни",рПоказыватьУровни);
пар.Вставить("ШагОтступа",рПараметры.ШагОтступа);
пар.Вставить("Отступ",рОтступ+рПараметры.ШагОтступа);
//
Для каждого рПодветка Из рВетка.Строки Цикл
рСекция.Параметры._HCS=Лев(строПробелы,рОтступ)+"\"+Лев(строОтступы,рШиринаКолонкиИерархии-рОтступ-1);
Если рПоказыватьУровни Тогда
рСекция.Параметры._Level=рПодветка.Уровень();
КонецЕсли;
Для каждого имякол Из мИменКолонок Цикл
рСекция.Параметры[имякол]=рПодветка[имякол];
КонецЦикла;
рТекст.Вывести(рСекция);
ВывестиДеревоЗначенийВТекст(рПодветка,рТекст,пар)
КонецЦикла;
//
КонецЕсли;
Исключение
Сообщить("ВывестиДеревоЗначенийВТекст, ошибка: "+ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
КонецПопытки;
КонецПроцедуры
Источник
Категория:
Работа с Деревом Значений Google maps : вывод точек на карту и режим панорамы В отличие от яндекс карт в GMaps можно использовать панорамы - за что им большой плюс! Надеюсь в яндексе прочитают этот пост и тоже когда-нибудь это сделают!
Для клиента нужно было сделать вывод объектов на карту
С возможностью просмотра панорамы:
Основной HTML код карты хранится в макете:
Код VBS <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map { height: 100% }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.9&sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://www.sitedev.by/lab/markerclusterer/markerclusterer.js"></script>
<script type="text/javascript">
var latlng;
var markers = [];
var myMap;
var index = 1;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var infoWindow = new google.maps.InfoWindow;
var clusterer, mcOptions;
var trafficLayer = new google.maps.TrafficLayer();
var trafficOn = false;
var noclick = false;
var PointArray = [];
var polygons = [];
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
latlng = new google.maps.LatLng(55.75, 37.62);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDoubleClickZoom: true,
panControl: true,
zoomControl: true,
mapTypeControl: true,
scaleControl: true,
streetViewControl: true,
overviewMapControl: true
};
myMap = new google.maps.Map(document.getElementById("map"),
myOptions);
google.maps.event.addListener(myMap, 'dragend', function() {
noclick = true;
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
});
google.maps.event.addListener(myMap, 'click', function(event) {
infoWindow.close();
if (!noclick) {
addMarker(event.latLng);
}else{
noclick = false;
}
});
mcOptions = {gridSize: 3, maxZoom: 15};
clusterer = new MarkerClusterer(myMap, markers, mcOptions);
//отображение кнопки управления трафиком - все спер с примера, только подцепил свою функцию
var trafficControlDiv = document.createElement('div');
trafficControlDiv.style.padding = '5px';
// Set CSS for the control border
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '2px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'center';
controlUI.title = 'нажмите для вкл/выкл трафика';
trafficControlDiv.appendChild(controlUI);
// Set CSS for the control interior
var controlText = document.createElement('div');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = '<b>Трафик</b>';
controlUI.appendChild(controlText);
google.maps.event.addDomListener(controlUI, 'click', function (){
if (!trafficOn){
trafficOn = true;
trafficLayer.setMap(myMap);
}else{
trafficOn = false;
trafficLayer.setMap(null);
}
});
trafficControlDiv.index = 1;
myMap.controls[google.maps.ControlPosition.TOP_RIGHT].push(trafficControlDiv);
};
//добавляем маркер и отправляем в массив
function addMarker(location) {
marker = new google.maps.Marker({
position: location,
map: myMap,
title: 'Точка'+index
});
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
google.maps.event.addListener(marker, 'click', function(){
var mark = this;
var latLng = mark.getPosition();
infoWindow.setContent(mark.title);
infoWindow.open(myMap, mark);});
markers.push(marker);
index++;
document.getElementById('CoordX').value = location.lat();
document.getElementById('CoordY').value = location.lng();
}
function calcRoute(options) {
//вытягиваем из массива переданных параметров значения
//и преобразуем их в формат LatLng
var option1 = options[0];//начальная точка
var option2 = options[1];//промежуточные точки
var option3 = options[2];//конечная точка
var start = new google.maps.LatLng(option1[0], option1[1]); //первый
var end = new google.maps.LatLng(option3[0], option3[1]); //последний
//получаем транзитные точки
var waypts = [];
if(option2.length > 0) {
for(var i = 0, l = option2.length; i < l; i++) {
temp = option2[i];
Qcoord = new google.maps.LatLng(temp[0], temp[1])
waypts.push({
location:Qcoord,
stopover:true
});
}
}
//return;
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setMap(myMap);
directionsDisplay.setDirections(response);
var total = 0;
var myroute = response.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById('RouteInfo').value = "Длина маршрута - " + total + "км.";
//генерация события для перехвата в 1С
var evt = document.createEventObject();
document.body.fireEvent('ondatasetcomplete', evt);
}else{
alert(status);
}
});
}
function Reset(){
directionsDisplay.setMap(null);
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
index = 1;
//обнуляем кластер маркеров
clusterer.clearMarkers();
for (var i = 0; i < polygons.length; i++) {
polygons[i].setMap(null);
}
polygons = [];
PointArray = [];
}
function FindAdres(Adres){
Reset();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': Adres}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latlng = results[0].geometry.location;
myMap.panTo(latlng);
marker = new google.maps.Marker({
map: myMap,
position: latlng,
animation: google.maps.Animation.BOUNCE,
title:Adres
});
markers.push(marker);
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
} else {
alert("Ничего не найдено: " + status);
}
});
}
function ReverseSearchAdres(CoordX, CoordY, Adres){
Reset();
latlng = new google.maps.LatLng(CoordX, CoordY);
myMap.panTo(latlng);
var marker = new google.maps.Marker({
map: myMap,
position: latlng,
animation: google.maps.Animation.BOUNCE,
title:Adres
});
markers.push(marker);
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
}
function addToPointArray(CoordX, CoordY, ID, IconT, Text){
var latLng = new google.maps.LatLng(CoordX, CoordY);
var point = new google.maps.Marker({'position': latLng, title: Text, icon: IconT});
PointArray.push(point);
}
function drawCluster(){
clusterer.addMarkers(PointArray);
//myMap.geoObjects.add(clusterer);
}
function createPolygon(ArrayPoint, Name, color) {
//создаем массив координат вершин многоугольника
var paths = [];
for(var i = 0, l = ArrayPoint.length; i < l; i++) {
var temp = ArrayPoint[i];
Qcoord = new google.maps.LatLng(temp[0], temp[1])
paths.push(Qcoord);
};
// Создаем многоугольник
myPolygon = new google.maps.Polygon({
paths: paths,
strokeColor: color,
strokeOpacity: 0.6,
strokeWeight: 5,
fillColor: "#0000FF"
});
myPolygon.setMap(myMap);
polygons.push(myPolygon);
}
function WebClientClick() {
//очистка перед кликом координат, иначе после клика в упр. формах идет считывание координат
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
var WebClientOperation = document.getElementById("WebClientOperation").value;
//alert(WebClientOperation);
switch (WebClientOperation) {
case "0": // ничего не делаем
var a = 1;
default: // запускаем функцию
eval(WebClientOperation);
}
document.getElementById('WebClientOperation').value = "0";
}
</script>
</head>
<body onload="initialize()">
<div id="map" style="width:100%; height:100%"></div>
<input type="hidden" id="CoordX" name="CoordX" value="0"></input>
<input type="hidden" id="CoordY" name="CoordY" value="0"></input>
<input type="hidden" id="RouteInfo" name="RouteInfo" value=""></input>
<input type="hidden" id="WebClientOperation" name="WebClientOperation" value="0"></input>
<input type="hidden" id="WebClient" name="WebClient" onclick="WebClientClick();"></input>
</body>
</html>
Код вывода карты:
Код 1C v 8.х Процедура ИнициализироватьКарту()
ПутьКФайлу = КаталогВременныхФайлов()+"Карта.html";
Ф = новый Файл(ПутьКФайлу);
Если Ф.Существует() Тогда
УдалитьФайлы(ПутьКФайлу);
КонецЕсли;
Т = новый ТекстовыйДокумент;
ТД = ЭтотОбъект.ПолучитьМакет("МакетГугл");
Т.УстановитьТекст(ТД.ПолучитьТекст());
Т.Записать(ПутьКФайлу);
ЭлементыФормы.Эксплорер.Перейти(ПутьКФайлу);
КонецПроцедуры
Процедура ОчиститьКарту()
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("Reset()");
КонецПроцедуры
//к сожалению, другого спососба получить "внутрь 1С" информацию о действии пользователя на карте я не сумел
//действие пользователя на карте изменяет поле HTML-документа, но не вызывает никакого события в 1с-ке
// поэтому через обработчикОжидания делаю непрерывный опрос карты
Процедура ПриОткрытии()
ИнициализироватьКарту();
КонецПроцедуры
// вывод точек на карту
Процедура ОсновныеДействияФормыОсновныеДействияФормыВыполнить(Кнопка)
ОчиститьКарту();
СписокВидов = Новый СписокЗначений;
Для Каждого стр из ВыборВывода Цикл
если стр.пометка тогда СписокВидов.Добавить(стр.наименование); КонецЕсли;
КонецЦикла;
табАдресов.Очистить();
табАдресов = получитьтабАдресов(СписокВидов);
табУникальныхАдресов = табАдресов.скопировать();
табУникальныхАдресов.свернуть("Уник");
тзДанных = табАдресов.скопировать();
табАдресов.очистить();
Для Каждого стр из табУникальныхАдресов Цикл
Отбор = Новый Структура();
Отбор.Вставить("Уник",стр.Уник);
Строки = тзДанных.НайтиСтроки(Отбор);
НовСтр = табАдресов.добавить();
НовСтр.уник = стр.уник;
Если Строки.Количество() > 0 Тогда
для Каждого тздстр из Строки Цикл
НовСтр.Адрес = тздстр.Адрес;
НовСтр.КД = тздстр.КД;
НовСтр.КШ = тздстр.КШ;
НовСтр.ВидОбъекта = тздстр.ВидОбъекта;
НовСтр.Наименование=Строка(НовСтр.Наименование)+Строка(тздстр.Наименование)+"; ";
КонецЦикла;
КонецЕсли;
КонецЦикла;
ЭлементыФормы.табАдресов.СоздатьКолонки();
ВыборМасштаба = "50%";
ВыборРегиона = "Москва";
ЭлементыФормы.Надпись24.Заголовок = "Точек: "+Строка(табАдресов.количество());
Кол = табАдресов.Количество();
Индекс = 0;
Для Каждого ТекСтрока Из табАдресов Цикл Индекс = Индекс + 1; Если НЕ ЗначениеЗаполнено(ТекСтрока.КД) тогда Продолжить; КонецЕсли;
Широта = формат(ТекСтрока.КШ, "ЧРД=.");
Долгота = формат(ТекСтрока.КД, "ЧРД=.");
СодержимоеТочки = СокрЛП(ТекСтрока.ВидОбъекта)+": "+ СокрЛП(ТекСтрока.адрес); //опять же можно вставить свое название
Попытка
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("addToPointArray(" + Широта + "," + Долгота + ", '" + Строка(Индекс) + "', '" + СокрЛП(ТекСтрока.ВидОбъекта.ПутьКИконке)+ "', """ + СодержимоеТочки + """);");
Исключение
Сообщить("addToPointArray(" + Широта + "," + Долгота + ", '" + Строка(Индекс) + "', '" + СокрЛП(ТекСтрока.ВидОбъекта.ПутьКИконке)+ "', """ + СодержимоеТочки + """);",СтатусСообщения.Внимание);
КонецПопытки;
Состояние("Вывожу на карту " + Индекс + " из " + кол);
КонецЦикла;
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("drawCluster();");
КонецПроцедуры
Вырванная из конфигурации обработка GMaps.rar
Можно ее использовать как макет для создания обработки под свои требования.
Пример автоматизации в котором это использовалось.
Категория:
Географическая схема Полнотекстовый Поиск - пример поиска контрагентов в базе У клиента огромная база клиентов и соответственно огромный штат менеджеров. Дошло до того, что менеджеры в поисках новых клиентов( знакомство, интернет, реклама и т.д.) очень часто звонят одним и тем же клиентам по несколько раз. Стали вести базу звонков... Но в базе одного и того же клиента могли назвать по разному - как-только вздумается...
Понадобился поиск по нечеткому названию и для этого решено было использовать полнотекстовый поиск 1С :
Механизм полнотекстового поиска в 1С позволяет быстро находить необходимую для пользователя информацию. Данный вид поиска особенно эффективен, если информационная база располагает большим объемом информации, а также точно не известно, где находятся интересующие пользователя данные или как часто бывает, их точное название не известно.
Смысл обработки в том, что менеджер копирует названия клиентов в список слева, нажимает Выполнить поиск и справа видит найденных в базе контрагентов (подходящих по нечеткости). Порог нечеткости менеджеры могут устанавливать сами.
Приведу краткий пример реализации данного поиска, код:
Код 1C v 8.х
Процедура КнопкаВыполнитьНажатие(Кнопка)
Если ПолнотекстовыйПоиск.ПолучитьРежимПолнотекстовогоПоиска() <> РежимПолнотекстовогоПоиска.Разрешить Тогда
Отказ = Истина;
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = НСтр("ru = 'Использование полнотекстового поиска не разрешено. Вы можете включить его в диалоге ""Управление полнотекстовым поиском""'", "ru");
Сообщение.Сообщить();
Возврат;
КонецЕсли;
тчРезультата.Очистить();
текдок = Новый ТекстовыйДокумент;
текдок.УстановитьТекст(ТестПоиска);
Для Ном=1 по текдок.КоличествоСтрок() цикл
Стр = СокрЛП(текдок.ПолучитьСтроку(Ном));
СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(Стр);
СписокПоиска.ПолучатьОписание = Истина;
СписокПоиска.РазмерПорции = 5;
СписокПоиска.ПорогНечеткости = ПорогНечеткости;
МассивОтбор = Новый Массив();
МассивОтбор.Добавить(Метаданные.Справочники.Контрагенты);
//МассивОтбор.Добавить(Метаданные.Документы.КассовыйЧек);
СписокПоиска.ОбластьПоиска = МассивОтбор;
СписокПоиска.ПерваяЧасть(); // Выдает по 5 результатов - РазмерПорции
// Если нужно листать
// СписокПоиска.ПредыдущаяЧасть(ТекущаяПозиция);
// СписокПоиска.СледующаяЧасть(ТекущаяПозиция);
Для каждого Результат Из СписокПоиска Цикл
нСтр=тчРезультата.Добавить();
нСтр.ТекстПоиска=Стр;
нСтр.Контрагент=Результат.Значение;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура ПриОткрытии()
ПорогНечеткости=15;
КонецПроцедуры
Результат обработки:
Категория:
Встроенные Функции Как обработать файлы с разделителями, изменив их структуру и сохранив в кодировке UTF8 без BOM Частенько при разработке сайтов приходится обрабатывать тысячи однотипных файлов... чтобы оптимизировать эту рутинную работу я набросал небольшую обработку, которая перебирает в указанном каталоге все файлы с расширением w1c и полностью меняет структуру данного файла, сохраняя его в кодировке UTF8 без BOM сигнатуры
Код обработки файлов:
Код 1C v 8.3 &НаКлиенте
Процедура КомандаОбрW1C(Команда)
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытия = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытия.Каталог = "";
ДиалогОткрытия.МножественныйВыбор = Ложь;
ДиалогОткрытия.Заголовок = "Выберите каталог с Файлами";
Если ДиалогОткрытия.Выбрать() Тогда
ПутьККаталогу = ДиалогОткрытия.Каталог;
ВыбранКаталог = НайтиФайлы(ПутьККаталогу, "*.*");
Для каждого НайденныйФайл Из ВыбранКаталог Цикл
Если НайденныйФайл.ЭтоКаталог() Тогда //Каталог
//каталоги пока не трогаем
ИначеЕсли НайденныйФайл.Расширение=".w1c" Тогда // Файл для обработки
Сообщить(НайденныйФайл.ПолноеИмя);
ОбработатьФайл(НайденныйФайл.ПолноеИмя);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьФайл(ТекФайл)
//Прочитаем текст файла
ОбрФайл = Новый ТекстовыйДокумент;
ОбрФайл.Прочитать(ТекФайл,"UTF-8");
врТекст = ОбрФайл.ПолучитьТекст();
врМассив = РазложитьСтрокуВМассив(врТекст,"<&w1c&>");
/// Переформируем структуру файла
новТекст = СокрЛП(врМассив[0])+"<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[1])+"<&w1c&>"+"1<&w1c&>";
//Получим атрибуты файла
АтрибутыФайла = Новый Файл(ТекФайл);
новТекст = новТекст + Формат(АтрибутыФайла.ПолучитьВремяИзменения(),"ДФ=dd/MM/yyyy")+"<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[2])+"<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[3])+"<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[4])+"<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[5])+"<&w1c&>";
новТекст = новТекст + "no-mods<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[6])+"<&w1c&>";
новТекст = новТекст + СокрЛП(врМассив[7]);
// Запишем в тот же файл
ОбрФайл.Очистить();
ОбрФайл.УстановитьТекст(новТекст);
ОбрФайл.Записать(ТекФайл,"UTF-8");
//Но нужно получить файл UTF8 без сигнатуры BOM
Данные = Новый ДвоичныеДанные(ТекФайл);
Строка64=Base64Строка(Данные);
Строка64=Прав(Строка64,СтрДлина(Строка64)-4);
ДанныеНаЗапись=Base64Значение(Строка64);
ДанныеНаЗапись.Записать(ТекФайл); // записываем
КонецПроцедуры
//// Вспомогательное
&НаКлиенте
Функция РазложитьСтрокуВМассив(Знач Стр, Разделитель = ",") Экспорт
МассивСтрок = Новый Массив();
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
КонецФункции
Внешний вид обработки получился таким:
Обработка написана для Web-Студии W1C : Первый Веб-Консультант
Категория:
Текстовый документ Обработка файлов в папке и запись дополнительной информации в них Частенько при загрузке данных в 1С сталкиваешься с необходимостью дополнительной обработки загружаемых файлов. Возможно это добавление какой-либо информации или наоборот удаление, а может изменение.
Ниже приведен код, который обрабатывает файлы в указанной папке и добавляет в конец файла информацию о дате его последнего изменения:
(это лишь рабочий пример / набросок - который вы можете использовать для написания своего обработчика)
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
масФайлов = НайтиФайлы(ПутьКФайлу, "*.w1c");
Для Каждого стр из масФайлов Цикл
Состояние("Обработка: "+стр.Имя);
текФайл = стр.ПолноеИмя;
ВыбФайл = Новый Файл(текФайл);
ДатаИзмененияФайла = Формат(ВыбФайл.ПолучитьУниверсальноеВремяИзменения(),"ДЛФ=D");
текДок = Новый ТекстовыйДокумент;
текДок.Прочитать(текФайл, "UTF-8");
текТекст = текДок.ПолучитьТекст()+Символы.ПС+"<&w1c&>"+ДатаИзмененияФайла;
текДок.УстановитьТекст(текТекст);
текДок.Записать(текФайл, "UTF-8");
КонецЦикла;
КонецПроцедуры
Процедура ПриОткрытии()
ПутьКФайлу="Укажите каталог"
КонецПроцедуры
Процедура ПутьКФайлуНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
// Мы выбираем каталог, поэтому фильтр по расширению файлов нам не нужен
// Оставлю на всякий случай, вдруг пригодится позже
//ДиалогОткрытияФайла.ПолноеИмяФайла = "";
//Текст = "ru = ""Текст""; en = ""Text""";
//Фильтр = НСтр(Текст)+"(*.w1c)|*.w1c";
//ДиалогОткрытияФайла.Фильтр = Фильтр;
//ДиалогОткрытияФайла.МножественныйВыбор = Истина;
ДиалогОткрытияФайла.Заголовок = "Выберите Каталог с файлами";
Если ДиалогОткрытияФайла.Выбрать() Тогда
ПутьКФайлу = ДиалогОткрытияФайла.Каталог;
//МассивФайлов = ДиалогОткрытияФайла.ВыбранныеФайлы;
//Для Каждого ИмяФайла Из МассивФайлов Цикл
// ВыбФайл = Новый Файл(ИмяФайла);
// Текст = "ru = ""; Размер = ""; en = ""; Size = """;
// Сообщить(ИмяФайла+НСтр(Текст)+ВыбФайл.Размер());
//КонецЦикла;
Иначе
Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!""";
Предупреждение(НСтр(Текст));
КонецЕсли;
КонецПроцедуры
Сама обработка : ObrabotkaFaylov.rar
Категория:
Работа с Файлами и Каталогами Загрузка данных в 1С из PDF В данной статье описан пример реализации загрузки данных накладных из PDF файлов для одного крупного Ритейла...
И так у Нас есть несколько файлов в формате pdf, которые нам необходимо загрузить в 1С.
Чтение PDF файлов из 1С
Первым дело я стал искать, как напрямую можно прочитать данные из 1С в PDF файлах - было найдено много информации и вариантов решений, но к сожалению большинство из них не правильно работали с кодировкой В результате банальный текст вида Красный стул превращался в страшную кракозябру.
Далее после долгих поисков был найден конвертер PDF в TXT - pdf2txt
Поддержка командной строки:
PDF2TXT <input PDF file> [output TXT file] [-logfile] [-open] [-space] [-html] [-format] [-silent] [-blankline] [-summary] [-zoom <num>] [-?] [-h]
<input PDF file> : Open an existing PDF file to convert.
[output TXT file] : Write to TEXT file, the default is same filename of input PDF file.
[-first <page number>]: Specify the first page number.
[-last <page number>]: Specify the last page number.
[-logfile] : Write log to "C:\pdf2txt.log" file.
[-open] : Auto open the text file after it be created.
[-space] : Auto insert spaces into text file.
[-html] : Output to a HTML file, not a text file.
[-format] : Keep the page layout in the generated TXT file.
[-silent] : Disable error and warning messages.
[-blankline] : Auto delete blank line in the generated TXT file.
[-summary] : Get PDF document summary.
[-zoom <num>] : Set zoom ratio, the range is from 50 to 200.
[-unicode] : Create UTF-8 encoding text file.
Примеры:
Код Batch File (DOS, CMD, BAT) C:\>PDF2TXT C:\input.pdf
C:\>PDF2TXT C:\input.pdf -unicode
C:\>PDF2TXT C:\input.pdf -first 10 -last 12
C:\>PDF2TXT C:\input.pdf C:\output.txt
C:\>PDF2TXT C:\input.pdf -open -silent -logfile -zoom 150
C:\>PDF2TXT C:\input.pdf C:\output.txt -open -silent
C:\>PDF2TXT C:\*.pdf
C:\>PDF2TXT C:\*.pdf C:\*.txt
C:\>PDF2TXT C:\test\*.pdf C:\test\*.txt
В архиве (Скачать Вы можете из статьи по ссылке ) заготовка 1С обработки для частного случая, если она Вам подойдет - Хорошо
Если же нет, то Мы можем для Вас быстро доработать загрузку PDF в 1С !
Код на 1С для конфигурации УТ 10.3:
Код 1C v 8.х Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт
МассивСтрок = Новый Массив();
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
ТекЗнч = СокрЛП(Лев(Стр,Поз-1));
Если ЗначениеЗаполнено(ТекЗнч) Тогда
МассивСтрок.Добавить(ТекЗнч);
КонецЕсли;
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
КонецФункции
Процедура КнопкаВыполнитьНажатие(Кнопка)
//Ищем Файлы
тч.Очистить();
НайденныеФайлы = НайтиФайлы(ПутьКPDF,"*.pdf",ложь);
Для каждого стр Из НайденныеФайлы Цикл
Нстр = ТЧ.Добавить();
Нстр.ФайлPDF = стр.Имя;
КонецЦикла;
ЭтаФорма.Обновить();
//Преобразуем PDF в TXT
Для каждого стр Из ТЧ Цикл
Попытка
pdf = СокрЛП(ПутьКPDF+"\"+стр.ФайлPDF);
txt = СтрЗаменить(pdf,"pdf","txt");
Команд = ПутьКPDF2TXT+"\pdf2txt.exe "+pdf+" "+txt;
ЗапуститьПриложение(Команд,ПутьКPDF,Истина);
стр.ФайлTXT = txt;
Исключение
стр.ФайлTXT = "!!!_ОШИБКА";
КонецПопытки;
ЭлементыФормы.ТЧ.ТекущаяСтрока = стр;
ЭлементыФормы.ТЧ.ОбновитьСтроки(стр);
КонецЦикла;
мТекущийПользователь = глЗначениеПеременной("глТекущийПользователь");
мСкладПоУмолчанию = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОсновнойСклад");
мОсновноеПодразделение = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОсновноеПодразделение");
мОсновнаяВалютаВзаиморасчетов = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОсновнаяВалютаВзаиморасчетов");
мОсновноеВедениеВзаиморасчетовПоДоговорам = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОсновноеВедениеВзаиморасчетовПоДоговорам");
мВидНоменклатурыПоУмолчанию = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОсновнойВидНоменклатуры");
мОтражатьВРеглУчете = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОтражатьДокументыВУправленческомУчете");
мОтражатьВБухУчета = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОтражатьДокументыВБухгалтерскомУчете");
мОтражатьВНалУчете = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(мТекущийПользователь, "ОтражатьДокументыВНалоговомУчете");
//Создаем Документ
Для каждого стр Из ТЧ Цикл
Состояние("Загружаю: "+стр.ФайлTXT);
текдок=Новый ТекстовыйДокумент;
текдок.Прочитать(стр.ФайлTXT,"UTF-8");
ЗагрузкаТЧ=Ложь;
ДокВозвратТоваровОтПокупателя = Документы.ВозвратТоваровОтПокупателя.СоздатьДокумент();
ДокВозвратТоваровОтПокупателя.Ответственный = мТекущийПользователь;
ДокВозвратТоваровОтПокупателя.Дата = ОбщегоНазначения.ПолучитьРабочуюДату();
ДокВозвратТоваровОтПокупателя.УстановитьНовыйНомер();
ДокВозвратТоваровОтПокупателя.ВидПоступления = Перечисления.ВидыПоступленияТоваров.НаСклад;
ДокВозвратТоваровОтПокупателя.СкладОрдер = Склад;
ДокВозвратТоваровОтПокупателя.Подразделение = мОсновноеПодразделение;
ДокВозвратТоваровОтПокупателя.ВалютаДокумента = Справочники.Валюты.НайтиПоКоду("643");
ДокВозвратТоваровОтПокупателя.УчитыватьНДС = ИСТИНА;
ДокВозвратТоваровОтПокупателя.СуммаВключаетНДС = ИСТИНА;
Для Ном=1 по текдок.КоличествоСтрок() цикл
ТСтр = текдок.ПолучитьСтроку(Ном);
ТекСтр = СокрЛП(ТСтр);
Если Найти(ТекСтр, "Всего по накладной")>0 Тогда
ЗагрузкаТЧ=Ложь;
//делаем пересчеты сумм, количества мест и НДС по строкам
Для Каждого СтрокаТабличнойЧасти Из ДокВозвратТоваровОтПокупателя.Товары Цикл
ОбработкаТабличныхЧастей.РассчитатьКоличествоМестТабЧасти(СтрокаТабличнойЧасти, ДокВозвратТоваровОтПокупателя);
ОбработкаТабличныхЧастей.РассчитатьСуммуТабЧасти(СтрокаТабличнойЧасти, ДокВозвратТоваровОтПокупателя);
ОбработкаТабличныхЧастей.РассчитатьСуммуНДСТабЧасти(СтрокаТабличнойЧасти, ДокВозвратТоваровОтПокупателя);
КонецЦикла;
Попытка
ДокВозвратТоваровОтПокупателя.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ДокВозвратТоваровОтПокупателя.Записать(РежимЗаписиДокумента.Запись);
КонецПопытки;
стр.Документ = ДокВозвратТоваровОтПокупателя.Ссылка;
стр.Инфо = "Все ОК";
ЭлементыФормы.ТЧ.ТекущаяСтрока = стр;
ЭлементыФормы.ТЧ.ОбновитьСтроки(стр);
//ВСЕ
Прервать;
КонецЕсли;
Если ЗагрузкаТЧ Тогда
ТекСтр = СтрЗаменить(ТекСтр, "подложке ","подложке");
ТекСтр = СтрЗаменить(ТекСтр, " ","|");
СтрМ=РазложитьСтрокуВМассивПодстрок(ТекСтр,"|");
Если СтрМ.Количество()>2 Тогда
//Сообщить(СтрМ);
Попытка
НоваяСтрока = ДокВозвратТоваровОтПокупателя.Товары.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоКоду(СтрМ[2]);
//НоваяСтрока.ХарактеристикаНоменклатуры = СтрокаТаблицы.ХарактеристикаНоменклатуры;
//УстановитьСтавкуНДСВТабЧасти(НоваяСтрока, СтрокаТаблицы);
//ПроверитьНаличиеСерииНоменклатуры(НоваяСтрока, СтрокаТаблицы);
//УстановитьПризнакВеденияПоСериямНоменклатуры(НоваяСтрока);
НоваяСтрока.ЕдиницаИзмерения = НоваяСтрока.Номенклатура.БазоваяЕдиницаИзмерения;
НоваяСтрока.Коэффициент = 1;
НоваяСтрока.Количество = Число(СтрМ[6]);
НоваяСтрока.Цена = Число(СтрМ[7]);
НоваяСтрока.Сумма = Число(СтрМ[8]);
НоваяСтрока.СуммаНДС = Число(СтрМ[11]);
НоваяСтрока.Качество = Справочники.Качество.Новый;
Попытка
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС["НДС"+Лев(СокрЛП(СтрМ[9]),2)];
Исключение
НоваяСтрока.СтавкаНДС = НоваяСтрока.Номенклатура.СтавкаНДС;
КонецПопытки;
Исключение
Сообщить("Не загружено: "+ТекСтр);
КонецПопытки;
Иначе
Продолжить;
КонецЕсли;
Иначе
// Возможно что-то будет
КонецЕсли;
//Сообщить(ТекСтр);
Если Найти(ТекСтр, "Товарная накладная")>0 Тогда
ТекСтр = СтрЗаменить(ТекСтр, " ","|");
СтрМ=РазложитьСтрокуВМассивПодстрок(ТекСтр,"|");
Если СтрМ.Количество()>1 Тогда
//Сообщить(СтрМ);
ДокВозвратТоваровОтПокупателя.НомерВходящегоДокументаЭлектронногоОбмена = СтрМ[1];
ТекДата = СтрМ[2];
ДокВозвратТоваровОтПокупателя.ДатаВходящегоДокументаЭлектронногоОбмена = Дата(Прав(ТекДата,4)+Сред(ТекДата,4,2)+Лев(ТекДата,2));
КонецЕсли;
КонецЕсли;
Если Найти(ТекСтр, "Грузополучатель:")>0 Тогда
//Сообщить(ТекСтр);
//Получим ИНН
ГдеИНН = Найти(ТекСтр, "ИНН");
Если ГдеИНН>0 Тогда
ГдеИННвр= лев(ТекСтр,ГдеИНН+15);
текИНН = Прав(гдеИННвр, СтрДлина(ГдеИННвр)-(ГдеИНН+3));
текИНН = СокрЛП(СтрЗаменить(текИНН,".","")); текИНН = СокрЛП(СтрЗаменить(текИНН,",",""));
ТекОрганизация = Справочники.Организации.НайтиПоРеквизиту("ИНН",текИНН);
Если ТекОрганизация=Справочники.Организации.ПустаяСсылка() Тогда
ДокВозвратТоваровОтПокупателя.Организация = Организация;
Иначе
ДокВозвратТоваровОтПокупателя.Организация = ТекОрганизация;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Найти(ТекСтр, "Поставщик:")>0 Тогда
//Сообщить(ТекСтр);
//Получим ИНН
ГдеИНН = Найти(ТекСтр, "ИНН");
Если ГдеИНН>0 Тогда
ГдеИННвр= лев(ТекСтр,ГдеИНН+15);
текИНН = Прав(гдеИННвр, СтрДлина(ГдеИННвр)-(ГдеИНН+3));
текИНН = СокрЛП(СтрЗаменить(текИНН,".","")); текИНН = СокрЛП(СтрЗаменить(текИНН,",",""));
ТекПоставщик = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН",текИНН);
ДокВозвратТоваровОтПокупателя.Контрагент = ТекПоставщик;
ДокВозвратТоваровОтПокупателя.ДоговорКонтрагента = ТекПоставщик.ОсновнойДоговорКонтрагента;
КонецЕсли;
КонецЕсли;
Если Найти(ТекСтр, "Плательщик:")>0 Тогда
//Сообщить(ТекСтр);
//Получим ИНН
ГдеИНН = Найти(ТекСтр, "ИНН");
Если ГдеИНН>0 Тогда
ГдеИННвр= лев(ТекСтр,ГдеИНН+15);
текИНН = Прав(гдеИННвр, СтрДлина(ГдеИННвр)-(ГдеИНН+3));
текИНН = СокрЛП(СтрЗаменить(текИНН,".","")); текИНН = СокрЛП(СтрЗаменить(текИНН,",",""));
ТекПлательщик = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН",текИНН);
КонецЕсли;
КонецЕсли;
Если текстр="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" Тогда
ЗагрузкаТЧ=Истина;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура ПутьКPDF2TXTОткрытие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытия = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытия.Каталог = "";
ДиалогОткрытия.МножественныйВыбор = Ложь;
ДиалогОткрытия.Заголовок = "Выберите каталог с PDF2TXT";
Если ДиалогОткрытия.Выбрать() Тогда
ПутьКPDF2TXT = ДиалогОткрытия.Каталог;
ПутьКPDF = ДиалогОткрытия.Каталог;
КонецЕсли;
КонецПроцедуры
Процедура ПутьКPDFОткрытие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытия = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытия.Каталог = "";
ДиалогОткрытия.МножественныйВыбор = Ложь;
ДиалогОткрытия.Заголовок = "Выберите каталог с PDF2TXT";
Если ДиалогОткрытия.Выбрать() Тогда
ПутьКPDF = ДиалогОткрытия.Каталог;
КонецЕсли;
КонецПроцедуры
Категория:
Загрузка данных в 1С Выгрузка картинок из базы 1С в XML В нынешнее время для электронного каталога или интернет-магазина необходимо выгружать не только информацию о цене и характеристиках товара, но и сопутствующие изображения. Хранящиеся в базе или связанные с номенклатурой изображения порой приходилось выгружать отдельно, подвергая предварительной обработке имена файлов, подгоняя их под правила связи товара с изображениями в приемнике. Тем не менее, в 1С существует возможность поместить двоичные данные изображений в виде строки в XML, либо другой файл выгрузки, чтобы уже на месте разобрать информацию о товаре.
Рассмотрим на примере следующей конфигурации.
Перечень объектов:
- справочники "Номенклатура", подчиненный ему справочник "Файлы";
- документ "Установка цен";
- обработка "Выгрузка прайса";
- перечисления "Типы файлов", "Типы номенклатуры";
- регистр "Цены номенклатуры".
Для начала, добавим форму элемента для справочника "Файлы"
Код 1C v 8.2 УП &НаСервере
Процедура ОбновитьКартинкуФорма(ХранилищеКартинки)
Если Объект.ТипФайла = Перечисления.ТипыФайлов.Картинка Тогда
Картинка = ПоместитьВоВременноеХранилище(ХранилищеКартинки.Получить(), УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры // ОбновитьКартинку()
&НаСервере
Процедура ПоместитьНаСервер(Данные = Неопределено)
ХранилищеКартинки = ?(Данные = Неопределено, Неопределено, Новый ХранилищеЗначения(Данные));
ОбновитьКартинкуФорма(ХранилищеКартинки);
КонецПроцедуры // ПоместитьНаСервер()
&НаКлиенте
Процедура ДобавитьФайл(Команда)
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
ДиалогОткрытияФайла.Фильтр = "Все *.*|*.*|.jpg|*.jpg|.png|*.png";
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";
Если ДиалогОткрытияФайла.Выбрать() Тогда
мФайл = ДиалогОткрытияФайла.ПолноеИмяФайла;
ПоместитьНаСервер(Новый ДвоичныеДанные(мФайл));
Иначе
Текст = "Файл не выбран!";
Предупреждение(Текст);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ОбновитьКартинкуФорма(ТекущийОбъект.ХранилищеФайла);
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
ТекущийОбъект.ХранилищеФайла = ?(ПустаяСтрока(Картинка), Неопределено, Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(Картинка)));
КонецПроцедуры
Настроим форму документа "Установка цен".
Код 1C v 8.2 УП &НаСервере
Процедура ЗаполнитьТЧ()
Результат = ВыгрузкаПрайса.ПолучитьТаблицуЦен(Объект.Дата);
Объект.Товары.Загрузить(Результат);
КонецПроцедуры // ЗаполнитьТЧ()
&НаКлиенте
Процедура Заполнить(Команда)
ЗаполнитьТЧ();
КонецПроцедуры
Добавляем обработку выгрузки в XML.
Код 1C v 8.2 УП &НаКлиенте
Процедура Выгрузить(Команда)
Если ПустаяСтрока(ФайлВыгрузки) Тогда
Возврат;
КонецЕсли;
мСтрока = ВыгрузкаПрайса.ПолучитьДанныеXML();
мФайл = Новый ТекстовыйДокумент;
мФайл.УстановитьТекст(мСтрока);
мФайл.Записать(ФайлВыгрузки);
КонецПроцедуры
&НаКлиенте
Процедура ФайлВыгрузкиОткрытие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Режим = РежимДиалогаВыбораФайла.Сохранение;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = ФайлВыгрузки;
Фильтр = "(*.xml)|*.xml";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";
Если ДиалогОткрытияФайла.Выбрать() Тогда
ФайлВыгрузки = ДиалогОткрытияФайла.ПолноеИмяФайла;
Иначе
Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!""";
Предупреждение(НСтр(Текст));
КонецЕсли;
КонецПроцедуры
При заполнении табличной части "Товары" документа "Установка цен" и в обработке выгрузки мы обращаемся к общему модулю "Выгрузка прайса":
Код 1C v 8.2 УП Функция ПолучитьТаблицуЦен(ДатаЗапроса = Неопределено) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| ЕСТЬNULL(Цены.Цена, 0) КАК Цена,
| ПРЕДСТАВЛЕНИЕ(Номенклатура.Ссылка) КАК НоменклатураСтрока
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Товар,
| ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
| ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК ЦеныНоменклатурыСрезПоследних) КАК Цены
| ПО Номенклатура.Ссылка = Цены.Товар
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа
|
|УПОРЯДОЧИТЬ ПО
| Номенклатура
|АВТОУПОРЯДОЧИВАНИЕ";
Запрос.УстановитьПараметр("Дата", ?(ЗначениеЗаполнено(ДатаЗапроса), ДатаЗапроса, ТекущаяДата()));
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции // ПолучитьТаблицуЦен()
Функция ПолучитьИзображения(НоменклатураСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Файлы.Ссылка
|ИЗ
| Справочник.Файлы КАК Файлы
|ГДЕ
| Файлы.Владелец = &Владелец
| И Файлы.ТипФайла = ЗНАЧЕНИЕ(Перечисление.ТипыФайлов.Картинка)
| И НЕ Файлы.ПометкаУдаления";
Запрос.УстановитьПараметр("Владелец", НоменклатураСсылка);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Функция ПолучитьДанныеXML() Экспорт
ТЧ_Цены = ПолучитьТаблицуЦен();
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("price_list");
Для Каждого СтрокаЦен Из ТЧ_Цены Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("tovar");
ЗаписьXML.ЗаписатьАтрибут("name", СтрокаЦен.НоменклатураСтрока);
ЗаписьXML.ЗаписатьАтрибут("price", Формат(СтрокаЦен.Цена, "ЧРД=.; ЧГ=0"));
ТЧ = ПолучитьИзображения(СтрокаЦен.Номенклатура);
Если НЕ ТЧ.Количество() = 0 Тогда
ЗаписьXML.ЗаписатьНачалоЭлемента("picture_list");
Для Каждого СтрТЧ Из ТЧ Цикл
мДанные = СтрТЧ.Ссылка.ХранилищеФайла.Получить();
Если НЕ ЗначениеЗаполнено(мДанные) Тогда
Продолжить;
КонецЕсли;
ЗаписьXML.ЗаписатьНачалоЭлемента("picture");
ЗаписьXML.ЗаписатьАтрибут("binary", Base64Строка(мДанные));
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЕсли;
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
СтрокаXML = ЗаписьXML.Закрыть();
Возврат СтрокаXML;
КонецФункции // ПолучитьФайлXML()
Кодирование изображений выполняется с помощью функции Base64Строка , в качестве аргумента передаются двоичные данные из справочника "Файлы". Предполагается, что приемник XML может выполнить обратное преобразование. В 1С это можно сделать с помощью функции Base64Значение.
результат выгрузки прайса в XML:
Код Batch File (DOS, CMD, BAT) <?xml version="1.0"?>
<price_list>
<tovar name="Товар 1" price="5">
<picture_list>
<picture binary="iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAB3RJTUUH3QINBSMt
F2PHEwAAABd0RVh0U29mdHdhcmUAR0xEUE5HIHZlciAzLjRxhaThAAAACHRwTkdH
TEQzAAAAAEqAKR8AAAAEZ0FNQQAAsY8L/GEFAAAABmJLR0QA/wD/AP+gvaeTAAAA
pklEQVR4nGP4jw3kajICEVYpBmRFcMafGkMgQhZB1wBRBDEYohquBy6F0AAXejM5
DoiQbUAWgehB2ACRg0jDEbIgRCUTAyponLY4XF8cjoBcNAUMaB44EiEBRJhsuJOY
8rSY+oMNgDohJBCsvPiyZd0xIAIyICJwBUDF6E4iDEh1EnoowdXBVaOFElnBCvE3
cggCufAwgIQ1xMdQP5CcNMhJfMQnbwDR3npihwr9YwAAAABJRU5ErkJggg=="/>
</picture_list>
</tovar>
<tovar name="Товар 2" price="10"/>
<tovar name="Товар 3" price="15"/>
<tovar name="Товар 4" price="18">
<picture_list>
<picture binary="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
rVebJ+JFAAAAAElFTkSuQmCC"/>
</picture_list>
</tovar>
<tovar name="Услуга 1" price="32"/>
<tovar name="Услуга 2" price="15"/>
</price_list>
Источник
Категория:
XML, DBF, TXT, CSV Получение уникального идентификатора ссылки в СКД Как известно, с помощью языка запросов 1С получить уникальный идентификатор объекта ссылочного типа на данный момент нельзя. Но используя возможность СКД обращаться к внешним функциям можно получить строковое представление уникального идентификатора ссылки. Для этого необходимо использовать глобальную функцию XMLСтрока в вычисляемых полях в макете схемы компоновки.
Далее проведем эксперимент по быстродействию получения результата через запрос с последующей обработкой выборки и вариантов с использованием СКД.
Рассмотрим два случая - вывод в табличный документ и формирование текстового документа.
Так же в случае с СКД мы можем создать схему компоновки программно или использовать готовую. Результат работы СКД так же можно обойти в цикле, либо вывести в таблицу значений с последующей обработкой. Для экспериментов будет использоваться платформа 8.3, конфигурация УТ11 (файловая), справочник "КлассификаторБанковРФ", более 4000 элементов.
Схему компоновки и макет можно посмотреть, скачав обработку (ссылка в конце).
Код 1C v 8.2 УП &НаКлиентеНаСервереБезКонтекста
Функция ПолучитьТекстЗапроса()
Возврат "ВЫБРАТЬ
| КлассификаторБанковРФ.Ссылка,
| КлассификаторБанковРФ.Наименование
|ИЗ
| Справочник.КлассификаторБанковРФ КАК КлассификаторБанковРФ";
КонецФункции // ПолучитьТекстЗапроса()
&НаСервере
Функция ПолучитьСхемуОбработки()
Возврат РеквизитФормыВЗначение("Отчет").ПолучитьМакет("Макет");
КонецФункции
&НаСервереБезКонтекста
Функция ПолучитьСхемуКомпоновки()
Схема = Новый СхемаКомпоновкиДанных;
ИсточникДанных = Схема.ИсточникиДанных.Добавить();
ИсточникДанных.Имя = "Источник";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "НаборДанных";
НаборДанных.ИсточникДанных = "Источник";
НаборДанных.Запрос = ПолучитьТекстЗапроса();
НаборСсылка = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
НаборСсылка.Поле = "Ссылка";
НаборСсылка.ПутьКДанным = "Ссылка";
НаборНаименование= НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
НаборНаименование.Поле = "Наименование";
НаборНаименование.ПутьКДанным = "Наименование";
ПолеИД = Схема.ВычисляемыеПоля.Добавить();
ПолеИД.Выражение = "XMLСтрока(Ссылка)";
ПолеИД.Заголовок = "ИД";
ПолеИД.ПутьКДанным = "ИД";
СтрокаТЗ = Схема.НастройкиПоУмолчанию.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
СтрокаТЗ.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
ЭлементыВыбора = Схема.НастройкиПоУмолчанию.Выбор.Элементы;
ПолеСсылка = ЭлементыВыбора.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ПолеСсылка.Поле = Новый ПолеКомпоновкиДанных("Ссылка");
ПолеНаименование = ЭлементыВыбора.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ПолеНаименование.Поле = Новый ПолеКомпоновкиДанных("Наименование");
ПолеИД = ЭлементыВыбора.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ПолеИД.Поле = Новый ПолеКомпоновкиДанных("ИД");
Возврат Схема;
КонецФункции
&НаСервереБезКонтекста
Функция ЗаполнитьПоКомпоновкеПрямойОбход(Схема)
Док = Новый ТекстовыйДокумент;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Схема.НастройкиПоУмолчанию,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет,,, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(Новый ТаблицаЗначений);
ПроцессорВывода.НачатьВывод();
Пока Истина Цикл
ЭлементКомпоновки = ПроцессорКомпоновки.Следующий();
Если ЭлементКомпоновки = Неопределено Тогда
Прервать;
КонецЕсли;
ПроцессорВывода.ВывестиЭлемент(ЭлементКомпоновки);
Если ЭлементКомпоновки.Макет = "Макет2" И ЭлементКомпоновки.ТипЭлемента = ТипЭлементаРезультатаКомпоновкиДанных.НачалоИКонец Тогда
Док.ДобавитьСтроку(ЭлементКомпоновки.ЗначенияПараметров.П2.Значение + ";" + ЭлементКомпоновки.ЗначенияПараметров.П3.Значение);
КонецЕсли;
КонецЦикла;
ТЗ = ПроцессорВывода.ЗакончитьВывод();
Возврат Док;
КонецФункции // ЗаполнитьПоКомпоновкеПрямойОбход()
&НаСервере
Функция ЗаполнитьОбходТЗ(ИспользоватьСхемуОбработки)
Если ИспользоватьСхемуОбработки Тогда
Схема = ПолучитьСхемуОбработки();
Иначе
Схема = ПолучитьСхемуКомпоновки();
КонецЕсли;
Возврат ЗаполнитьПоКомпоновкеОбходТЗ(Схема);
//Возврат ЗаполнитьПоКомпоновкеОбходТЗ(?(ИспользоватьСхемуОбработки, ПолучитьСхемуОбработки(), ПолучитьСхемуКомпоновки()));
КонецФункции // ЗаполнитьОбходТЗ()
&НаСервере
Функция ЗаполнитьПрямойОбход(ИспользоватьСхемуОбработки)
Если ИспользоватьСхемуОбработки Тогда
Схема = ПолучитьСхемуОбработки();
Иначе
Схема = ПолучитьСхемуКомпоновки();
КонецЕсли;
Возврат ЗаполнитьПоКомпоновкеПрямойОбход(Схема);
//Возврат ЗаполнитьПоКомпоновкеПрямойОбход(?(ИспользоватьСхемуОбработки, ПолучитьСхемуОбработки(), ПолучитьСхемуКомпоновки()));
КонецФункции // ЗаполнитьОбходТЗ()
&НаСервереБезКонтекста
Функция ЗаполнитьПоКомпоновкеОбходТЗ(Схема)
Док = Новый ТекстовыйДокумент;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Схема.НастройкиПоУмолчанию,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет,,, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(Новый ТаблицаЗначений);
ТЗ = ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Для Каждого СтрокаТЗ Из ТЗ Цикл
Док.ДобавитьСтроку(СтрокаТЗ.Наименование + ";" + СтрокаТЗ.ИД);
КонецЦикла;
Возврат Док;
КонецФункции // ЗаполнитьПоКомпоновкеОбходТЗ()
&НаСервереБезКонтекста
Функция ЗаполнитьПоЗапросу()
Док = Новый ТекстовыйДокумент;
Запрос = Новый Запрос(ПолучитьТекстЗапроса());
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
Док.ДобавитьСтроку(Результат.Наименование + ";" + XMLСтрока(Результат.Ссылка));
КонецЦикла;
Возврат Док;
КонецФункции // ЗаполнитьПоЗапросу()
&НаСервере
Процедура ЗаполнитьТабДокСхема(ИспользоватьСхемуОбработки)
Если ИспользоватьСхемуОбработки Тогда
Схема = ПолучитьСхемуОбработки();
ТабДок = ТабДок1;
Иначе
Схема = ПолучитьСхемуКомпоновки();
ТабДок = ТабДок2;
КонецЕсли;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Схема.НастройкиПоУмолчанию);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет,,, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры // ЗаполнитьТабДокСхема()
&НаСервере
Процедура ЗаполнитьТабДокЗапрос()
Макет = РеквизитФормыВЗначение("Отчет").ПолучитьМакет("Отчет");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Запрос = Новый Запрос(ПолучитьТекстЗапроса());
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
ОбластьСтрока.Параметры.Заполнить(Результат);
ОбластьСтрока.Параметры.ИД = XMLСтрока(Результат.Ссылка);
ТабДок3.Вывести(ОбластьСтрока);
КонецЦикла;
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЗаполнитьТабДокСхема(Истина);
ЗаполнитьТабДокСхема(Ложь);
ЗаполнитьТабДокЗапрос();
Т1 = ЗаполнитьПоЗапросу();
Т2 = ЗаполнитьОбходТЗ(Ложь);
Т3 = ЗаполнитьОбходТЗ(Истина);
Т4 = ЗаполнитьПрямойОбход(Ложь);
Т5 = ЗаполнитьПрямойОбход(Истина);
КонецПроцедуры
По результатам замера производительности видно, что вывод результата в табличный документ происходит быстрее при использовании СКД, причем вариант с программным созданием схемы отрабатывает несколько быстрее.
В тоже время вывод результатов в текстовый документ отрабатывает быстрее для запроса.
Программное создание схемы компоновки отработало быстрее, чем получение макета схемы.
Источник
Категория:
Схема Компоновки Данных Сравнение: Конкатенация, ТекстовыйДокумент, ЗаписьXML Немного теории:
Конкатенация (соединение строк). Казалось бы - ну что может быть проще и однозначнее? Ан нет. Выражение T = "А"+"Б"; (если оно не вычислено на этапе компиляции/разбора) требует выделения памяти для "А", памяти для "Б", анализа длин "А" и "Б", выделение памяти для T, копирование первой строки, копирование второй строки. Это медленно, особенно если в цикле дописывается кусочек в конец строки.
В "нормальных" системах, например в .NET от этого можно уйти используя так называемые StringBuilder - это специальный объект, который более эффективно выделяет память (крупными блоками) и не копирует зря строки. По сути это поток (stream) который используется для записи в память, как в файл. А вот в 1С такого нет. Фиг вам товарищи, а не эффективная работа со строками
Но фиг только тем у кого хитрости мало, а для остальных есть варианты.
ТекстовыйДокумент
Оказывается, что метод ДобавитьСтроку() для типа ТекстовыйДокумент для больших строк работает гораздо эффективнее чем тупая конкатенация. Возможно, это связано с тем, что этот тип - обёртка к текстовому редактору, встроенному в 1С. Кстати, этот редактор для простых текстовых файлов файлов мне нравится гораздо больше, чем например, notepad или редактор Visual Studio - он позволяет бодрее работать с большими текстами, как в длину, так и в ширину.
Но! У этого способа есть недостаток - в 8.0 и 8.1 он не доступен на сервере, т.к. считается "интерфейсным". Обидно. Но это заставляет искать нас более эффективный способ:
ЗаписьXML
Опа! А при чём здесь XML? Правильно, XML нам не нужен. Но важно, что тип ЗаписьXML представляет собой как раз обёртку над последовательной записью в поток. А если учесть, что он позволяет формировать результат в память в виде строки, а не только в файл, то это уже готовый кандидат на замену StringBuilder. Осталось только упомянуть, что он позволяет дозаписывать в "XML" всё что угодно при помощи метода ЗаписатьБезОбработки().
Код 1C v 8.2 УП ДлинаДобавляемогоКуска = 200; //символов, последний - ПС
ОбщаяДлинаСтроки = 1000000;
КоличествоИтераций = 10;
//Создаём базовую строчку:
БазоваяСтрока = "";
Для Сч = 1 по ДлинаДобавляемогоКуска-1 Цикл
БазоваяСтрока = БазоваяСтрока + "Ы";
КонецЦикла;
БазоваяСтрокаПС = БазоваяСтрока + Символы.ПС;
//Способ 1. Добавление строк к концу строки
Сообщить("Способ 1. Добавление строк к концу строки - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 1. Добавление строк к концу строки - " + Строка(СчИтераций));
СтрокаРезультат = "";
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
СтрокаРезультат = СтрокаРезультат + БазоваяСтрокаПС;
КонецЦикла;
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 1. Добавление строк к концу строки - Окончание " + Строка(ТекущаяДата()));
//Способ 2. Добавление строк в текстовый документ
Сообщить("Способ 2. Добавление строк в текстовый документ - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 2. Добавление строк в текстовый документ - " + Строка(СчИтераций));
ТекстПостроитель = Новый ТекстовыйДокумент;
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
ТекстПостроитель.ДобавитьСтроку(БазоваяСтрока); //ПС добавляется сам
КонецЦикла;
СтрокаРезультат = ТекстПостроитель.ПолучитьТекст();
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 2. Добавление строк в текстовый документ - Окончание " + Строка(ТекущаяДата()));
//Способ 3. Создание через ЗаписьXML
Сообщить("Способ 3. Создание через ЗаписьXML - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 3. Создание через ЗаписьXML - " + Строка(СчИтераций));
ТекстПостроитель = Новый ЗаписьXML;
ТекстПостроитель.УстановитьСтроку();
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
ТекстПостроитель.ЗаписатьБезОбработки(БазоваяСтрокаПС);
КонецЦикла;
СтрокаРезультат = ТекстПостроитель.Закрыть();
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 3. Создание через ЗаписьXML - Окончание " + Строка(ТекущаяДата()));
//ЗЫ: данный код проверен в 8.2
Результаты забегов
У меня на тестовой среде получилось примерно следующее время:
1. Конкатенация - 24 секунды
2. Текстовый документ 1,5 секунды
3. ЗаписьXML - около 0,4 секунды
Пишет
Alexander Speshilov Категория:
Работа с Текстом (Строкой) Импорт в 1С из текстовых файлов (TXT, CSV) Не редко возникает необходимость загрузить в справочники или документы 1С данные из текстового файла. Приведенный пример внешней обработки позволит преобразовать текстовый файл с известным разделителем данных в поле табличного документа для последующей обработки уже внутри 1С:Предприятия. Обработка содержит функцию разбора строки на массив данных, настраиваемый разделитель строки текста на "столбцы", процедуру чтения данных из текстового файла.
Разбор строки в массив с использованием функций из конфигурации 1С
Для разложения строки в массив в конфигурация 1С:Бухгалтерия, 1С:Торговля и 1С:УПП имеется замечательная функция - Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт. Функция "расщепляет" строку на подстроки, используя заданный разделитель. Разделитель может иметь любую длину. Если в качестве разделителя задан пробел, рядом стоящие пробелы считаются одним разделителем, а ведущие и хвостовые пробелы параметра "Стр" игнорируются. Подробнее можно прочесть внутри конфигурации - "Общие модули" -> "Общего назначения". Функция возвращает массив значений, элементы которого - подстроки.
Чтение текстового файла (txt) в 1С
Операцию импорта - экспорта текстовых файлов (формат тхт или csv, а также htm, html) очень удобно реализовать при помощи конструкции следующего вида:
1. Функция ПолучитьПотокЧтенияСтрок(Файл) - Назначение: Проверить наличие файла (функция Файл()), Создать текстовый документ (Новый ТекстовыйДокумент()), вызвать метод "Прочитать" для открытия потока чтения файла. Возвращает поток, готовый для чтения.
2. Процедура ЧтениеТХТФайла(Элемент) - Назначение: В цикле произвести последовательное чтение строк файла текстового документа, разбирая на массив колонок данных и добавляя значения массива в табличное поле;
Исходный код 1С функции создания текстового потока чтения файла ТХТ:
Код 1C v 8.х Функция ПолучитьПотокЧтенияСтрок(Файл)
Попытка
// Используется для доступа к параметрам файлов или каталогов.
ТекстовыйФайл = Новый Файл(Файл);
Если ТекстовыйФайл.Существует() = Ложь Тогда
Сообщить("Файла "+Файл+" не существует!");
Возврат Неопределено;
КонецЕсли;
// Текстовый документ предназначен для работы с текстами.
// Объект позволяет получать и сохранять текст в файле,
// работать со строками
ПотокЧтенияСтрок = Новый ТекстовыйДокумент();
ПотокЧтенияСтрок.Прочитать(ТекстовыйФайл);
Исключение
Сообщить("Файл не прочитан.", СтатусСообщения.Внимание);
Сообщить(ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
// Возвращает текст, извлеченный из файла
Возврат ПотокЧтенияСтрок;
КонецФункции // ПолучитьПотокЧтенияСтрок
// Исходный код функции загрузки строк в табличное поле:
Процедура ЧтениеТХТФайла(Элемент)
// Проверка на наличие имени файла
Если ПустаяСтрока(ИмяФайла) Тогда
Предупреждение("Для запуска обработки необходимо предварительно выбрать файл данных.");
Возврат;
КонецЕсли;
// Открыть файл, создать текстовый документ, прочитать
ПотокСтрок = ПолучитьПотокЧтенияСтрок(ИмяФайла);
// Очистить предыдущие значения
ТаблицаДокумента.Очистить();
ТаблицаДокумента.Колонки.Очистить();
// Создать колонки табличного документа
ТаблицаДокумента.Колонки.Добавить("Номер",,"Номер",5);
ТаблицаДокумента.Колонки.Добавить("Артикул",,"Артикул",11);
ТаблицаДокумента.Колонки.Добавить("Номенклатура",,"Номенклатура",25);
ТаблицаДокумента.Колонки.Добавить("Цена",,"Цена",6);
// Последовательное чтение строк текстового файла
КоличествоСтрок = ПотокСтрок.КоличествоСтрок();
Для Строка = 1 По КоличествоСтрок Цикл
// Обработка нажатия Ctrl + Break
ОбработкаПрерыванияПользователя();
// Чтение строки из файла тхт / csv
СтрокаИзФайла = ПотокСтрок.ПолучитьСтроку(Строка);
// Разбор строки в массив, используя в качествен символа-разделителя "|"
МассивСтрок = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(СтрокаИзФайла,"|");
// Добавить данные в табличную часть экранной формы
Стр=ТаблицаДокумента.Добавить();
Стр.Номер = Строка;
Стр.Артикул = МассивСтрок[0];
Стр.Номенклатура = МассивСтрок[1];
Стр.Цена = МассивСтрок[2];
// Отобразить информацию о ходе выполнения обработки
Состояние("Обработка строки файла : "
+ "строка " + Строка + " из " + КоличествоСтрок);
КонецЦикла;
// Отобразить результаты загрузки в форме элемента
ЭлементыФормы.ТаблицаДокумента.Значение = ТаблицаДокумента;
ЭлементыФормы.ТаблицаДокумента.СоздатьКолонки();
КонецПроцедуры // ЧтениеTXTФайла(Элемент)
В данном примере была произведена загрузка из текстового файла в следующем формате:
Код 7754|Процессор Atom 1.7|10,00
5054|Процессор AMD x64|8,99
7546|Мышь Microsoft|45,88
Категория:
XML, DBF, TXT, CSV Загрузить данные в 1с из текстового файла с разделителями В этой статье я расскажу, как загружать данные в 1с 8 из простейших текстовых файлов с разделителями. Обычно они имеют расширение csv (Comma-Separated Values). Т. е. название подразумевает, что в каждой строке такого текстового файла значения разделены запятой. Но на самом деле, запятую, в качестве разделителя, использовать не надёжно. Поэтому применяют другие разделители, которые в обычном тексте встречаются редко. Это могут быть символы «^», «~»,«|» и другие. Итак, наша задача состоит в том, чтобы загрузить имеющуюся в csv файле информацию в базу данных 1с. Например, в файле будут содержаться товары интернет - магазина. В качестве образца, я взял выгрузку из магазина на скрипте virtuemart. Посмотрим, как выглядит файл.
Привожу две первых строки из него:
Код ~product_sku~^~category_path~^~product_name~^~product_desc~
~20~^~Книги/Электронные книги~^~Amazon Kindle 4 Touch~^~<p>Популярная электронная книга с ч/б экраном 6", электронной бумагой E-Ink Pearl, разрешением 600x800 пикс. с 16 - ю оттенками серого.</p>~
Посмотрим на файл.
Первая строка служебная. В ней описан формат нашего файла. Т. е. в какой ячейке, что находится. Однако, имейте в виду, что такой строки может и не быть.
Ячейки образуются при помощи разделителя «^», а данные в ячейках обрамляются символом «~».
В любой конфигурации 1с есть иерархический справочник товаров. В него и будем загружать информацию.
Создадим внешнюю обработку. Добавим строковый реквизит «путьКФайлуЗагрузки» для хранения имени файла. Добавим на форму поле ввода, связанное с данным реквизитом. Включим в свойствах поля ввода кнопку выбора и создадим обработчик события «НачалоВыбора» и напишем в нём такой код:
Код 1C v 8.х Процедура путьКФайлуЗагрузкиНачалоВыбора(Элемент, СтандартнаяОбработка)
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
Фильтр = "Comma separated file (*.csv)|*.csv";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";
Если ДиалогОткрытияФайла.Выбрать() Тогда
путьКФайлуЗагрузки = ДиалогОткрытияФайла.ПолноеИмяФайла;
КонецЕсли;
КонецПроцедуры
Т. о. мы организовали диалог для выбора файла в нашей обработке.
Хорошо. Теперь, для удобства и наглядности я предлагаю создать временную табличку, в которую мы загрузим текстовый файл, а уже после её заполнения - будем осуществлять загрузку в базу 1с. Для этого, на форму добавим табличное поле «табЗагрузки», с типом значения «ТаблицаЗначений» и командной панелью. В панели поместим кнопку «Заполнить» и создадим обработчик её нажатия «КоманднаяПанель1Заполнить». Также для элемента универсальности, добавим в обработку два строковых реквизита «символОграничения» и «разделительПолей». В них мы будем хранить «^», и «~». Можно в теле модуля формы осуществить их начальную инициализацию:
разделительПолей = "^";
символОграничения = "~";
Это позволит пользователю задать свои значения и при желании сохранить настройку, которая впоследствии не затрется нашей инициализацией.
Код 1C v 8.х Процедура КоманднаяПанель1Заполнить(Кнопка)
Если табЗагрузки.Количество() > 0 И Вопрос("Таблица будет очищена. Вы уверены?",РежимДиалогаВопрос.ДаНет)
= КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;
ЗаполнитьТаблицу();
КонецПроцедуры
Процедура ЗаполнитьТаблицу()
текст = Новый ТекстовыйДокумент;
Попытка
//обязательно устанавливаем кодировку, в которой наш файл
текст.Прочитать(путьКФайлуЗагрузки,КодировкаТекста.UTF8);
Исключение
Сообщить("Не удалось прочитать файл: "
+ ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
Возврат;
КонецПопытки;
табЗагрузки.Очистить();//очищаем таблицу
табЗагрузки.Колонки.Очистить();//удаляем колонки, так как их состав мог измениться
квоСтрок = текст.КоличествоСтрок();
Если Не квоСтрок > 0 Тогда
Сообщить("Файл пустой",СтатусСообщения.Внимание);
Возврат;
КонецЕсли;
//получаем первую строку с форматом файла
стрТекста = текст.ПолучитьСтроку(1);
//преобразуем строку в массив при помощи функции общего модуля, которая есть в типовых
//ниже я дам её код, на случай, если нет
масЗначСтр = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(стрТекста,разделительПолей);
//добавляем две служебные колонки
//для возможности отказаться от загрузки определенной строки
табЗагрузки.Колонки.Добавить("не_загружать",Новый ОписаниеТипов("Булево"),"Не загружать");
//для удобства вывода комментариев с указанием номера строки по ходу загрузки
табЗагрузки.Колонки.Добавить("номер_строки",Новый ОписаниеТипов("Число",
Новый КвалификаторыЧисла(10,0,ДопустимыйЗнак.Неотрицательный)),"Номер строки");
//формируем колонки нашей таблицы
Для каждого зн Из масЗначСтр Цикл
//убираем лишний символОграничения
значение = СтрЗаменить(зн,символОграничения,"");
кол = табЗагрузки.Колонки.Добавить(значение,Новый ОписаниеТипов("Строка"));
КонецЦикла;
//создаём колонки в табличном поле
ЭлементыФормы.табЗагрузки.СоздатьКолонки();
//начиная со второй строки читаем строки файла, раскладывая их в массив
Для номСтр = 2 По квоСтрок Цикл
стрТекста = текст.ПолучитьСтроку(номСтр);
масЗначСтр = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(стрТекста,разделительПолей);
//добавляем новую строку в таблицу
новСтр = табЗагрузки.Добавить();
новСтр.номер_строки = номСтр;
//начиная с третьей колонки производим установку значений в колонки
номЗнач = 2;
Для каждого зн Из масЗначСтр Цикл
новСтр[номЗнач] = СтрЗаменить(зн,символОграничения,"");
номЗнач = номЗнач + 1;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функцию разложения строки с разделителями в массив можно разместить как в одном из общих модулей, так и непосредственно в обработке.
Код 1C v 8.х Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт
МассивСтрок = Новый Массив();
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока Истина Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока Истина Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
КонецФункции
Отлично. В итоге, после заполнения, получим примерно такую картинку:
Теперь приступим непосредственно к загрузке товаров. Рядом с кнопкой «заполнить» добавим кнопку «загрузить» и добавим обработчик её нажатия «КоманднаяПанель1Загрузить», а также добавим реквизит «ПапкаЗагрузкиВыгрузкиТоваров» с типом вашего справочника товаров для опциональной их загрузки в определенную папку. Текст обработчика будет такой:
Код 1C v 8.х Процедура КоманднаяПанель1Загрузить(Кнопка)
Если Вопрос("Вы уверены, что хотите загрузить файл?", РежимДиалогаВопрос.ДаНет)
= КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;
ВсегоСтрок = табЗагрузки.Количество();
номСтр = 1;
Для каждого стрТЗ Из табЗагрузки Цикл
Состояние("Обработано: " + Окр(номСтр * 100 / ВсегоСтрок) + "%");
номСтр = номСтр + 1;
ОбработкаПрерыванияПользователя();
//если пользователь установил не_загружать = Истина, пропускаем
Если стрТЗ.не_загружать Тогда
Продолжить;
КонецЕсли;
объект1С = вернутьТовар(стрТЗ);
Если объект1С = Неопределено Тогда
Возврат;
КонецЕсли;
Если Не ЗаписатьЭлементСпр(объект1С) Тогда
Сообщить("Загрузка прервана!",СтатусСообщения.ОченьВажное);
Возврат;
КонецЕсли;
//помечаем запись, как загруженную
стрТЗ.не_загружать = Истина;
КонецЦикла;
КонецПроцедуры
В приведенном коде две новые функции «вернутьТовар» и «ЗаписатьЭлементСпр». Вот их текст:
Код 1C v 8.х Функция вернутьТовар(стрТабФайла)
Артикул = стрТабФайла.product_sku;
Если Не ЗначениеЗаполнено(Артикул) Тогда
Сообщить("В строке " + стрТабФайла.номер_строки + " не заполнен product_sku",
СтатусСообщения.ОченьВажное);
Возврат Неопределено;
КонецЕсли;
Запрос = Новый Запрос("ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул");
Запрос.УстановитьПараметр("Артикул",Артикул);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка.ПолучитьОбъект();
Иначе
ЭтоНовый = Истина;
объект1С = Справочники.Номенклатура.СоздатьЭлемент();
объект1С.Артикул = Артикул;
объект1С.Наименование = стрТабФайла.product_name;
объект1С.Родитель = вернутьРодителяТовара(стрТабФайла.category_path);
Возврат объект1С;
КонецЕсли;
КонецФункции // вернутьТовар()
Функция ЗаписатьЭлементСпр(Спр)
Попытка
Спр.Записать();
Исключение
Сообщить("При записи элемента справочника " + Спр + " возникла ошибка: " + ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции // ЗаписатьЭлементСпр()
И осталась последняя новая функция для обработки родителя товара вернутьРодителяТовара. Текст её смотрите ниже. Комментарии по тексту.
Код 1C v 8.х Функция вернутьРодителяТовара(стрКатегории)
//главный родитель - заполненная в обработке папка
Родитель = ПапкаЗагрузкиВыгрузкиТоваров;
//строку категории раскладываем в массив используя разделитель /
масРодителей = РазложитьСтрокуВМассивПодстрок(стрКатегории,"/");
Для каждого Род Из масРодителей Цикл
//если папку не находим, создаём и назначаем в качестве родителя
//следующей и т. д. В случае проблем выдаём прекращаем загрузку
РодСс = Справочники.Номенклатура.НайтиПоНаименованию(Род,Истина);
Если РодСс.Пустая() Тогда
НовРод = Справочники.Номенклатура.СоздатьГруппу();
НовРод.Наименование = Род;
НовРод.Родитель = Родитель;
Если Не ЗаписатьЭлементСпр(НовРод) Тогда
Возврат Неопределено;
КонецЕсли;
Родитель = НовРод.Ссылка;
Иначе
Родитель = РодСс;
КонецЕсли;
КонецЦикла;
Возврат Родитель;
КонецФункции //
Все. Конечно, в реальной жизни еще много чего нужно будет дописать, но не все сразу. Такой шаблон можно использовать как отправную точку.
Скачивать файлы может только зарегистрированный пользователь!
Успехов в разработке!
Источник Категория:
Текстовый документ Как получить HTML ссылку на объект БД? Код 1C v 8.х Процедура ДобавитьТекстHTML(ТекстHTML, Элемент);
СсылкаНаЭлемент = ЗначениеВСтрокуВнутр(Элемент);
ТекстHTML.ДобавитьСтроку("<A href= " + "v8:"+СсылкаНаЭлемент
+ ">"+Элемент+"</A><BR>");
КонецПроцедуры
Процедура ДействияФормыСформировать(Кнопка)
Запрос = Новый Запрос("
|ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура");
ТекстHTML = Новый ТекстовыйДокумент;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДобавитьТекстHTML(ТекстHTML, Выборка.Ссылка);
КонецЦикла;
ЭлементыФормы.ПолеHTMLДокумента.УстановитьТекст(ТекстHTML.ПолучитьТекст());
КонецПроцедуры
Процедура ПолеHTMLДокументаonclick(Элемент, pEvtObj)
// Отказ от стандартной обработки клика.
pEvtObj.returnValue = Ложь;
Если ВРег(pEvtObj.srcElement.tagName) = "A" Тогда
СсылкаТекст = Сред(pEvtObj.srcElement.href, 4);
Ссылка = ЗначениеИзСтрокиВнутр(СсылкаТекст);
Если Ссылка.Пустая()
Или Ссылка.ПолучитьОбъект() = Неопределено Тогда
Предупреждение("Ошибка открытия объекта.",, "Ошибка");
Возврат;
Иначе
ОткрытьЗначение(Ссылка);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Категория:
HTML, JS, VML Поле выбора ~ Как работать с многострочным полем? Код 1C v 8.х Текст=Новый ТекстовыйДокумент;
Текст.УстановитьТекст(ЭлементыФормы.ПолеВвода1.Значение);
Для i=1 По Текст.КоличествоСтрок() Цикл
Строка = Текст.ПолучитьСтроку(i);
Массив = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(Строка, Символы.Таб);
Попытка
Сообщить(Массив[1]);
Исключение
КонецПопытки;
КонецЦикла;
Категория:
Работа с Формой (Диалог) и её элементами