Чтение данных с сайта в формате XML и загрузка в 1С При разработке веб проекта нам потребовалось получать с одного сайта данные в формате XML и загружать их в 1С.
Сайт выдает XML вида (Ссылка на этот xml в коде, внизу):
Код 1C v 8.3 This XML file does not appear to have any style information associated with it. The document tree is shown below.
<updates version="1.0" generator="SEOBudget" url="http://seobudget.ru/updates/">
<update id="cy" name="Обновление тИЦ Яндекса">
<date id="1823" index="1419324939" timestamp="1419324939">23.12.2014 11:55:39 MSK</date>
<date id="1792" index="1415776885" timestamp="1415776885">12.11.2014 10:21:25 MSK</date>
<date id="1760" index="1412923802" timestamp="1412924102">10.10.2014 10:55:02 MSK</date>
</update>
<update id="serp" name="Обновление поисковой выдачи Яндекса">
<date id="1872" index="1424898000" timestamp="1425604249">06.03.2015 04:10:49 MSK</date>
<date id="1871" index="1423602000" timestamp="1425586715">05.03.2015 23:18:35 MSK</date>
<date id="1868" index="1423602000" timestamp="1425402241">03.03.2015 20:04:01 MSK</date>
</update>
<update id="yaca" name="Обновление Яндекс.Каталога">
<date id="1875" index="1425931200" timestamp="1425973201">10.03.2015 10:40:01 MSK</date>
<date id="1874" index="1425758400" timestamp="1425886502">09.03.2015 10:35:02 MSK</date>
<date id="1873" index="1425585600" timestamp="1425628803">06.03.2015 11:00:03 MSK</date>
</update>
<update id="pr" name="Обновление Google PR">
<date id="1512" index="1386353345" timestamp="1386353345">06.12.2013 22:09:05 MSK</date>
<date id="1265" index="1360130400" timestamp="1360130400">06.02.2013 10:00:00 MSK</date>
<date id="1196" index="1352376123" timestamp="1352376123">08.11.2012 16:02:03 MSK</date>
</update>
<update id="user" name="Обновление ПФ в Яндексе">
<date id="1799" index="1415950021" timestamp="1416986821">26.11.2014 10:27:01 MSK</date>
<date id="1763" index="1409237032" timestamp="1413211432">13.10.2014 18:43:52 MSK</date>
<date id="1665" index="1400617705" timestamp="1401222505">28.05.2014 00:28:25 MSK</date>
</update>
</updates><br>
В результате была написана обработка загрузки данных с сайта в 1С, ее код:
Код 1C v 8.3 &НаСервере
Функция ЧтениеXMLВДерево(Путь)
//Создаем дерево
Дерево = Новый ДеревоЗначений;
Дерево.Колонки.Добавить("Имя");
Дерево.Колонки.Добавить("Значение");
//Откроем XML
XMLФайл = Новый ЧтениеXML;
XMLФайл.ОткрытьФайл(Путь);
//Прочитаем XML и создадим дерево
ПрочитатьXMLПоТегам(XMLФайл, Дерево.Строки);
XMLФайл.Закрыть();
ТекДанные = Неопределено;
//Обработаем дерево данных
Для каждого СтрокаП из Дерево.Строки Цикл
Для каждого СтрокаВ из СтрокаП.Строки Цикл
// Сообщить(СтрокаВ.Имя);
Для каждого СтрокаТ из СтрокаВ.Строки Цикл
//Сообщить(СтрокаТ.Имя);
Если СтрокаТ.Значение = "cy" тогда
ТекДанные = Перечисления.Показатель.TiC;
ИначеЕсли СтрокаТ.Значение = "serp" тогда
ТекДанные = Перечисления.Показатель.SYa;
ИначеЕсли СтрокаТ.Значение = "yaca" тогда
ТекДанные = Перечисления.Показатель.CatYa;
ИначеЕсли СтрокаТ.Значение = "pr" тогда
ТекДанные = Перечисления.Показатель.RP;
ИначеЕсли СтрокаТ.Значение = "user" тогда
ТекДанные = Перечисления.Показатель.PFYa;
КонецЕсли;
Для каждого СтрокаД из СтрокаТ.Строки Цикл
Если СтрокаД.Имя="timestamp" Тогда
// Получим из timestamp дату события
ДатаИзменения = МестноеВремя('19700101'+СтрокаД.значение);
//Запишем в регистр
НовЗапись = РегистрыСведений.ТиЦиRP.СоздатьМенеджерЗаписи();
НовЗапись.Показатель = ТекДанные;
НовЗапись.Период = ДатаИзменения;
НовЗапись.Записать();
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецФункции
&НаСервереБезКонтекста
Процедура ПрочитатьXMLПоТегам(XMLФайл, ТекущийНаборСтрок)
Пока XMLФайл.Прочитать() Цикл
Если XMLФайл.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
НоваяСтрока = ТекущийНаборСтрок.Добавить();
НоваяСтрока.Имя = XMLФайл.Имя;
НоваяСтрока.Значение = "";
Пока XMLФайл.ПрочитатьАтрибут() Цикл
НоваяСтрокаАтрибут = НоваяСтрока.Строки.Добавить();
НоваяСтрокаАтрибут.Имя = XMLФайл.Имя;
НоваяСтрокаАтрибут.Значение = СокрЛП(XMLФайл.Значение);
КонецЦикла;
ПрочитатьXMLПоТегам(XMLФайл, НоваяСтрока.Строки);
ИначеЕсли XMLФайл.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Возврат;
ИначеЕсли XMLФайл.ТипУзла = ТипУзлаXML.Текст Тогда
ТекущийНаборСтрок.Родитель.Значение = СокрЛП(XMLФайл.Значение);
Иначе
Сообщить("Тип узла: " + XMLФайл.ТипУзла + " НЕ ОБРАБОТАН", СтатусСообщения.Важное);
Конецесли;
КонецЦикла;
КонецПроцедуры
// Кнопка Обработки
&НаКлиенте
Процедура СборXML(Команда)
ЧтениеXMLВДерево("http://seobudget.ru/downloads/updates.xml");
КонецПроцедуры
Результат загруженный в регистр сведений:
Категория:
Работа с Интернет, Почтой (Mail), FTP Как мы писали парсер сайта с ценами для 1С Недавно, мой постоянный клиент решил проводить маркетинговые исследования по изменению цен на товары у конкурентов... и эти данные захотел использовать в 1С в связке с его прайс-листом + куча отчетов с графиками и процентным отклонением от цен основного конкурента
В результате этого, была написана обработка собирающая данные со страниц разных сайтов. Из целей конфиденциальности - сайты раскрывать не буду...
Вид обработки загрузки данных с сайта в 1С
Ниже код загрузки данных со страницы сайта , смысл такой :
в функция передается адрес страницы сайта полученный текст страницы обрабатывается, удаляются теги из полученного текста формируется ТЗ с данными По названию ищется поставщик из вспомогательного справочника Справочники.Pr_Поставщики.НайтиПоНаименованию(, если нет - создается на выходе ТЗ с данными Код 1C v 8.х Функция ПолучитьТаблицуДанных(Строка)
тзДанных = Новый ТаблицаЗначений;
Сервер = "site.ru";
Соединение = Новый HTTPСоединение(Сервер);
Заголовки = Новый Соответствие;
Заголовки.Вставить("host", Сервер);
ТекАдрес = СтрЗаменить(Строка.Наименование.УРЛСтраницы,"http://","");
ТекАдрес = СтрЗаменить(ТекАдрес,Сервер,"");
Запрос = Новый HTTPЗапрос(ТекАдрес, Заголовки);
Ответ =Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда // Данные получены, обрабатываем их
Содержимое= Ответ.ПолучитьТелоКакСтроку();
//Выведем тест полученной страницы
НачалоБлока = "<table id=" + """" + "table-price" + """" + " cellspacing=" + """" + "0" + """" + " border=" + """" + "1" + """" + " bordercolor=" + """" + "#dedede" + """" + " class=" + """" + "tablesorter" + """" + " >";
//НачалоБлока = "<div class=" + """" + "w100fl" + """" + " id=" + """" + "kurs" + """" + ">";
КонецБлока = "</table>";
ТекстБлока = Сред(Содержимое, Найти(Содержимое, НачалоБлока) + СтрДлина(НачалоБлока), Найти(Содержимое, КонецБлока) - Найти(Содержимое, НачалоБлока) - СтрДлина(НачалоБлока));
//Обработаем тест
обрТекст = СтрЗаменить(ТекстБлока,"<tr>","");
обрТекст = СтрЗаменить(обрТекст,"</tr>",Символы.ПС);
обрТекст = СтрЗаменить(обрТекст," >", ">");
обрТекст = СтрЗаменить(обрТекст,"</th> <th>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</td> <td>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th> <th class=" + """" + "sortable_header" + """" + ">", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th> <th >", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th><th>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</td><td>", " | ");
обрТекст = СтрЗаменить(обрТекст," >", ">");
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Ложь;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML
обрТекст=RegExp.Replace(обрТекст, "");
//Сообщить(обрТекст);
Если СокрЛП(обрТекст) = "Ни одной позиции не найдено." Тогда
Сообщить(Строка(Строка.Наименование)+ " = Ни одной позиции не найдено! Строка " + Строка.Наименование);
Возврат тзДанных;
КонецЕсли;
Если Найти(обрТекст, "Страница не найдена") > 0 Тогда
Сообщить(Строка(ТекАдрес)+" = Страница не найдена, строка " + Строка.Наименование);
Возврат тзДанных;
КонецЕсли;
//Преобразуем полученный текст в таблицу
Для н=1 По СтрЧислоСтрок(обрТекст)Цикл
СтрТекста=СтрПолучитьСтроку(обрТекст,н);
Если Найти(СтрТекста, "Длина Цена") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, "Длина Цена", "Длина | Цена");
КонецЕсли;
Если Найти(СтрТекста, "Марка стали Цена") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, "Марка стали Цена", "Марка стали | Цена");
КонецЕсли;
Если Найти(СтрТекста, ", Поставщик") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, ", Поставщик", " | Поставщик");
КонецЕсли;
//Выводим текст страницы построчно
мсДанных = ПолучитьМассивИзСтрокиСРазделителем(СтрТекста, "|", Истина);
Если н=1 Тогда
Для Каждого ткЗнач из мсДанных Цикл
СтрЗапрещСимволов = " .,<>""\/-";
ИмяКолонки = ткЗнач;
Для сч33 = 1 по СтрДлина(СтрЗапрещСимволов) Цикл
ЗапрещСимв = Сред(СтрЗапрещСимволов, сч33, 1);
ИмяКолонки = СтрЗаменить(ИмяКолонки, ЗапрещСимв, "_");
КонецЦикла;
// добавим нужное количество колонок- если перед колонкой Поставщик не хватает
// бывает, что в шапке определяется меньше колонок, чем реально в таблице
Если НРег(ИмяКолонки) = "поставщик" Тогда
Для Сч_дк = (Строка.Наименование.Родитель.Поставшик - 2) по тзДанных.Колонки.Количество() Цикл
тзДанных.Колонки.Добавить("Колонка_" + (тзДанных.Колонки.Количество() + 1));
КонецЦикла;
КонецЕсли;
тзДанных.Колонки.Добавить(ИмяКолонки);
КонецЦикла;
тзДанных.Колонки.Добавить("ном", , , 7);
Иначе
НовСтр = тзДанных.Добавить(); нмас=0;
Для Каждого ткЗнач из мсДанных Цикл
НовСтр[нмас] = ткЗнач;
нмас=нмас+1;
КонецЦикла;
НовСтр.ном = н;
КонецЕсли;
//Сообщить(стр);
КонецЦикла;
тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
Для каждого стр из тзДанных Цикл
текПоставщик = Справочники.Pr_Поставщики.НайтиПоНаименованию(стр[Строка.Наименование.родитель.Поставшик-1]);
Если текПоставщик = Справочники.Pr_Поставщики.ПустаяСсылка() Тогда
НовЭлем = Справочники.Pr_Поставщики.СоздатьЭлемент();
НовЭлем.Наименование = СокрЛП(стр[Строка.Наименование.родитель.Поставшик-1]);
НовЭлем.Записать();
текПоставщик = НовЭлем.Ссылка;
КонецЕсли;
стр.СпрPr_Поставщики = текПоставщик;
КонецЦикла;
Иначе
тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
Сообщить("Ошибка получения данных для строки " + Строка.Наименование);
КонецЕсли;
Возврат тзДанных;
КонецФункции
В коде используется вспомогательная функция ПолучитьМассивИзСтрокиСРазделителем
Код 1C v 8.2 УП // Функция разбивает строку разделителем.
//
// Параметры:
// пСтрока - Строка - которую разбиваем;
// *пРазделитель - Строка, "." - символ-разделитель;
// *ОбрезатьНепечатныеСимволы - Булево, *Ложь.
//
// Возвращаемое значение:
// Массив - фрагментов.
//
Функция ПолучитьМассивИзСтрокиСРазделителем(Знач Стр, Разделитель = ".", ОбрезатьНепечатныеСимволы = Ложь) Экспорт
МассивСтрок = Новый Массив;
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
Фрагмент = Стр;
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Возврат МассивСтрок;
КонецЕсли;
Фрагмент = Лев(Стр,Поз-1);
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
Возврат МассивСтрок;
КонецФункции // ПолучитьМассивИзСтрокиСРазделителем()
Конечно, перед тем как мы начали это делать - прошерстили интернет и нашли несколько решений , вот они:
Код 1C v 8.х Соединение = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяВременногоФайла=ПолучитьИмяВременногоФайла("htm");
Соединение.open("GET", "http://mamba.ru/my", 0);
Соединение.send();
//status: //404 - Not Found //200 - Ok
ТаймАут = 200;
Начало=ТекущаяДата();
Пока Соединение.readyState <> 4 И (ТаймАут=0 ИЛИ ТекущаяДата()-Начало<ТаймАут) Цикл
бфДиалоги.ксОбработкаПрерыванияПользователя();
КонецЦикла;
//Сохраняем во временный файл
обСохранитьДвоичныйБуферВФайл(Соединение.responseBody, ИмяВременногоФайла);
Соединение.open("POST", "http://mamba.ru/my");
Соединение.send("login=xxx&password=&&&");
Функция обСохранитьДвоичныйБуферВФайл(Буфер, ИмяФайла) Экспорт
Поток = Новый COMОбъект("ADODB.Stream");
Поток.Type = 1; //Бинарный
Поток.Mode = 3;
Поток.Open();
Поток.Write(Буфер);
Поток.SaveToFile(ИмяФайла);
Поток.Close();
КонецФункции
Код 1C v 8.х НТТР = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяФайлаОтвета = КаталогВременныхФайлов() + "filename.tmp";
НТТР.open("GET", "www.google.com",0,,);
НТТР.send();
StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2);
ConnectModeEnum = Новый Структура(
"adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone,
|adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive,
|adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2);
SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2);
StreamOut = Новый COMОбъект("ADODB.Stream");
StreamOut.Type = StreamTypeEnum.adTypeBinary;
StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись
StreamOut.Open(); //Открыли на чтение и запись
StreamOut.Write(НТТР.responseBody);
StreamOut.SaveToFile(ИмяФайлаОтвета, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
StreamOut.Close();
И даже не этом сайте есть статья : Парсер сайта связного на 1С
Нужен парсер сайта в 1С!? - Обращайтесь, контакты в
профиле Категория:
Работа с Интернет, Почтой (Mail), FTP Как обработать файлы с разделителями, изменив их структуру и сохранив в кодировке 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 : Первый Веб-Консультант
Категория:
Текстовый документ Подсчет реального количества месяцев между датами, включая начало и конец месяца В одном проекте понадобилось подсчитывать полное количество месяцев между датами,
Допустим надо получить кол-во месяцев между датами 25.10.14 и 21.11.14
Функция РазницаДатВМесяцах ( Как вычислить разницу между двумя датами в месяцах ) вернет 1 , по сути разница между датами = одному месяцу,
но по факту работы будут в 10 и 11 месяцах, т.е. всего 2, в итоге была написана простая функция, ее код ниже:
Код 1C v 8.2 УП тДат=ДатаНачала; КолМес = 0;
Пока Месяц(тДат)<> Месяц(ДатаОкончания) Цикл
КолМес = КолМес+1;
тДат = ДобавитьМесяц(тДат,1);
КонецЦикла;
Результат = КолМес+1;
Категория:
Работа с Датами (Временем) Загрузка картинок в базу 1С (сохранение в хранилище значений) В теме форма: v8: Получение данных из ХралищаЗначений
Bell в управляемом интерфейсе пробует сохранить выбранные картинки в базу 1С, но возникли сложности с сохранением в хранилище значений. как пример Bell приложил CF файл с мини конфигурацией, за что ему большое спасибо, т.к. большая часть материалов этой статьи написана им, я лишь поправил небольшие участки кода связанные с передачей файлов и сохранение в хранилище значений.
Так как везде уже Такси, то CF я перевел в этот режим и в нем демонстрирую.
Имеется справочник Хранилище данных :
Основная Форма Элемента:
Ее код:
Код 1C v 8.3 // ПРОЦЕДУРЫ ФОРМЫ
//======================================================================================================
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Объект.Ссылка.Пустая() Тогда
Объект.Наименование = ".";
КонецЕсли;
Если НЕ Параметры.Ключ.Пустая() Тогда
ДанныеАдрес = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ДанныеХЗ");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Объект.Ссылка.Пустая() Тогда
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Если ЭтоАдресВременногоХранилища(ДанныеАдрес) Тогда
РежимСжатия = Новый СжатиеДанных(9);
ДанныеСохранения = ПолучитьИзВременногоХранилища(ДанныеАдрес);
ТекущийОбъект.ДанныеХЗ = Новый ХранилищеЗначения(ДанныеСохранения, РежимСжатия);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Если ЭтоАдресВременногоХранилища(ДанныеАдрес) Тогда
УдалитьИзВременногоХранилища(ДанныеАдрес);
ДанныеАдрес = ПолучитьНавигационнуюСсылку(ТекущийОбъект.Ссылка, "ДанныеХЗ");
КонецЕсли;
КонецПроцедуры
// ПРОЦЕДУРЫ ЭЛЕМЕНТОВ ФОРМЫ
//======================================================================================================
&НаКлиенте
Процедура ВыбратьДанные(Команда)
ДанныеВыбрать();
КонецПроцедуры
&НаКлиенте
Процедура СохранитьДанные(Команда)
Если НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
Предупреждение(НСтр("ru = 'Элемент не записан !!!'"));
Возврат;
КонецЕсли;
ДанныеСохранения = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ДанныеХЗ");
ИмяСохранения = Объект.Наименование;
//ИмяСохранения = Объект.Наименование + Объект.ДанныеРасширение;
ПолучитьФайл(ДанныеСохранения, ИмяСохранения, Истина);
КонецПроцедуры
// ПРОЦЕДУРЫ ПРОЧИЕ
//======================================================================================================
&НаКлиенте
Процедура ДанныеВыбрать()
ПолученныеДанныеАдрес = "";
Если ПоместитьФайл(ПолученныеДанныеАдрес, , Объект.ДанныеПуть, Истина, УникальныйИдентификатор)Тогда
ДанныеАдрес = ПолученныеДанныеАдрес;
ВыбранныйФайл = Новый Файл(Объект.ДанныеПуть);
Объект.Наименование = ВыбранныйФайл.Имя;
Объект.ДанныеТекущаяДата = ТекущаяДата();
Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
так же имеется общая форма ФормаЗагрузкиФайлов
При помощи ее выбираются файлы изображений и загружаются в справочник - одновременно можно загружать несколько файлов
код формы:
Код 1C v 8.3 // ПРОЦЕДУРЫ ЭЛЕМЕНТОВ ФОРМЫ
//======================================================================================================
&НаКлиенте
Процедура СписокФайловПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа)
Отказ = Истина;
ДобавитьФайлы();
КонецПроцедуры
// ПРОЦЕДУРЫ ПРОЧИЕ
//======================================================================================================
&НаКлиенте
Процедура ДобавитьФайлы()
ВыборФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ВыборФайла.МножественныйВыбор = Истина;
ВыборФайла.Заголовок = НСтр("ru = 'Выбор файла'", "ru");
ВыборФайла.Фильтр = НСтр("ru = 'Все файлы'", "ru") + " (*.*)|*.*";
ВыборФайла.ПредварительныйПросмотр = Истина;
Если ВыборФайла.Выбрать() Тогда
Для каждого СтрокаФайл Из ВыборФайла.ВыбранныеФайлы Цикл
ОписаниеФайла = Новый Файл(СтрокаФайл);
НВС = СписокФайлов.Добавить();
НВС.ПолноеИмяФайла = СтрокаФайл;
НВС.РазмерФайла = ОписаниеФайла.Размер();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура Загрузить()
Если НЕ ПроверитьЗаполнение() Тогда
Возврат;
КонецЕсли;
ОчиститьСообщения();
Если СписокФайлов.Количество() = 0 Тогда
Сообщить("Файлы не выбраны !!!'");
Возврат;
КонецЕсли;
ПомещаемыеФайлы = Новый Массив;
Для каждого СтрокаФайл Из СписокФайлов Цикл
Описание = Новый ОписаниеПередаваемогоФайла(СтрокаФайл.ПолноеИмяФайла, "");
ПомещаемыеФайлы.Добавить(Описание);
КонецЦикла;
// -------------------------------------------------------------------------------
ПомещенныеФайлы = Новый Массив;
СписокЗагруженныхФайлов = Новый СписокЗначений;
Если ПоместитьФайлы(ПомещаемыеФайлы, ПомещенныеФайлы, , Ложь, УникальныйИдентификатор) Тогда
Закрыть(Истина);
Иначе
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = НСтр("ru = 'Файлы не загружены'", "ru");
Сообщение.Сообщить();
КонецЕсли;
ОповеститьОВыборе(ПомещенныеФайлы);
КонецПроцедуры
&НаСервере
Функция ПоместитьВыбранныеФайлыВХранилище(ПомещаемыеФайлы)
АдресХЗ = ПоместитьВоВременноеХранилище(ПомещаемыеФайлы, УникальныйИдентификатор);
Возврат АдресХЗ;
КонецФункции
в коде вызывается ОповеститьОВыборе(ПомещенныеФайлы) и срабатывает обработчик в ФормаСпискаДополнительно
Код 1C v 8.3 &НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ИсточникВыбора.ИмяФормы = "ОбщаяФорма.ФормаЗагрузкиФайлов" Тогда
ОбработкаВыбораПодборНаСервере(ВыбранноеЗначение);
КонецЕсли;
КонецПроцедуры
и следующим кодом идет создание элементов справочника и загрузка изображений из временного хранилища
Код 1C v 8.3 &НаСервере
Процедура ОбработкаВыбораПодборНаСервере(ВыбранноеЗначение)
Для Каждого СтрокаФайл Из ВыбранноеЗначение Цикл
Файл = Новый Файл(СтрокаФайл.Имя);
ХранимыйФайл = Справочники.ХранилищеДанныхСправочники.СоздатьЭлемент();
ХранимыйФайл.Наименование = Файл.Имя;
ХранимыйФайл.ДанныеПуть = Файл.Путь;
ХранимыйФайл.ДанныеТекущаяДата = ТекущаяДата();
ХранимыйФайл.ДанныеХЗ = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(СтрокаФайл.Хранение), Новый СжатиеДанных());
ХранимыйФайл.Записать();
КонецЦикла;
Элементы.Список.Обновить();
КонецПроцедуры
Скачать DT - Платформа 8.3.4
Категория:
Работа с Хранилищем Значений Набор функций для работы с разделителями в строке Код 1C v 8.х // Функция разбивает строку разделителем.
//
// Параметры:
// пСтрока - Строка - которую разбиваем;
// *пРазделитель - Строка, "." - символ-разделитель;
// *ОбрезатьНепечатныеСимволы - Булево, *Ложь.
//
// Возвращаемое значение:
// Массив - фрагментов.
//
Функция ПолучитьМассивИзСтрокиСРазделителем(Знач Стр, Разделитель = ".", ОбрезатьНепечатныеСимволы = Ложь) Экспорт
МассивСтрок = Новый Массив;
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
Фрагмент = Стр;
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Возврат МассивСтрок;
КонецЕсли;
Фрагмент = Лев(Стр,Поз-1);
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
Возврат МассивСтрок;
КонецФункции // ПолучитьМассивИзСтрокиСРазделителем()
// Функция собирает строку из элементов массива с разделителем.
//
// Параметры:
// пМассив - Массив - из которого формируем строку;
// *пРазделитель - Строка - символ-разделитель.
//
// Возвращаемое значение:
// Строка.
//
Функция ПолучитьСтрокуСРазделителемИзМассива(пМассив, пРазделитель = ", ") Экспорт
Результат = "";
Для Каждого Элемент Из пМассив Цикл
Результат = Результат + пРазделитель + Строка(Элемент);
КонецЦикла;
Возврат Сред(Результат, СтрДлина(пРазделитель) + 1);
КонецФункции // ПолучитьСтрокуСРазделителемИзМассива()
// Получает первый фрагмент, отделяемый разделителем от строки.
// Написана для оптимизации по скорости.
//
// Параметры:
// пСтрока - Строка - которую разбиваем;
// *пРазделитель - Строка, "." - символ-разделитель;
// *пЛиИспользоватьГраницуЕслиМаркерНеНайден - Булево, *Истина.
//
// Возвращаемое значение:
// - Строка - первый фрагмент строки;
// Неопределено - в строке не обнаружен разделитель.
//
Функция ПолучитьПервыйФрагмент(пСтрока, пРазделитель = ".",
пЛиИспользоватьГраницуЕслиМаркерНеНайден = Истина) Экспорт
Позиция = Найти(пСтрока, пРазделитель);
Если Позиция > 0 Тогда
Возврат Лев(пСтрока, Позиция - 1);
Иначе
Если пЛиИспользоватьГраницуЕслиМаркерНеНайден Тогда
Возврат пСтрока;
Иначе
Возврат пСтрока;
КонецЕсли;
КонецЕсли;
КонецФункции // ПолучитьПервыйФрагмент()
// Получает последний фрагмент, отделяемый разделителем от строки.
//
// Параметры:
// пСтрока - Строка - в которой ищем;
// *пМаркер – Строка, "." – отсекающий маркер;
// *пЛиИспользоватьГраницуЕслиМаркерНеНайден - Булево, *Истина - разрешение использования границ строки
// в случае, если маркер не найден.
//
// Возвращаемое значение:
// Неопределено - маркер не найден;
// – Число – позиция маркера.
//
Функция ПолучитьПоследнийФрагмент(пСтрока, пМаркер = ".",
пЛиИспользоватьГраницуЕслиМаркерНеНайден = Истина) Экспорт
Подстрока = пСтрока;
МаркерНайден = Ложь;
Пока пМаркер <> "" Цикл
Позиция = Найти(Подстрока, пМаркер);
Если Позиция = 0 Тогда
Прервать;
КонецЕсли;
МаркерНайден = Истина;
Подстрока = Сред(Подстрока, Позиция + СтрДлина(пМаркер));
КонецЦикла;
Если Истина
И Не МаркерНайден
И пЛиИспользоватьГраницуЕслиМаркерНеНайден
Тогда
Возврат пСтрока;
ИначеЕсли МаркерНайден Тогда
Возврат Подстрока;
Иначе
Возврат "";
КонецЕсли;
КонецФункции // ПолучитьПоследнийФрагмент()
// Получает подстроку заключенную между первым вхождением начального маркера и первым вхождением
// в правой части конечного маркера. Сами маркеры не включаются в результат. Опционально - если
// маркер не найден, то границей считается граница строки.
//
// Параметры:
// пСтрока - Строка - в которой ищем;
// *пНачальныйМаркер - Строка, *Неопределено - начальный маркер подстроки;
// *пКонечныйМаркер - Строка, *Неопределено - конечный маркер подстроки;
// *пЛиИспользоватьГраницуЕслиМаркерНеНайден - Булево, *Истина - разрешение использования границ строки
// в случае, если маркер не найден;
// *пЛиВключатьМаркеры - Булево, *Ложь - включение маркеров в результат.
//
// Возвращаемое значение:
// Неопределено - обязательные условия не выполнены;
// Строка – найденная подстрока.
//
Функция ПолучитьСтрокуМеждуМаркерами(пСтрока, пНачальныйМаркер = Неопределено, пКонечныйМаркер = Неопределено,
пЛиИспользоватьГраницуЕслиМаркерНеНайден = Истина, пЛиВключатьМаркеры = Ложь) Экспорт
ПозицияНачальногоМаркера = Найти(пСтрока, пНачальныйМаркер);
Если Истина
И ПозицияНачальногоМаркера = 0
И пЛиИспользоватьГраницуЕслиМаркерНеНайден = Ложь
Тогда
Возврат Неопределено;
КонецЕсли;
Если Ложь
ИЛИ пНачальныйМаркер = Неопределено
ИЛИ ПозицияНачальногоМаркера = 0
Тогда
ПозицияНачальногоМаркера = - СтрДлина(пНачальныйМаркер);
КонецЕсли;
Стр = Сред(пСтрока, ПозицияНачальногоМаркера + СтрДлина(пНачальныйМаркер));
ПозицияКонечногоМаркера = Найти(Стр, пКонечныйМаркер);
Если Истина
И ПозицияКонечногоМаркера = 0
И пЛиИспользоватьГраницуЕслиМаркерНеНайден = Ложь
Тогда
Возврат Неопределено;
КонецЕсли;
Если Ложь
ИЛИ пКонечныйМаркер = Неопределено
ИЛИ ПозицияКонечногоМаркера = 0
Тогда
ПозицияКонечногоМаркера = СтрДлина(Стр) + 1;
КонецЕсли;
Результат = Лев(Стр, ПозицияКонечногоМаркера - 1);
Если пЛиВключатьМаркеры Тогда
Если пНачальныйМаркер <> Неопределено Тогда
Результат = пНачальныйМаркер + Результат;
КонецЕсли;
Если пКонечныйМаркер <> Неопределено Тогда
Результат = Результат + пКонечныйМаркер;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции // ПолучитьСтрокуМеждуМаркерами()
Категория:
Работа с Текстом (Строкой) Поиск в базе битых ссылок - "объект не найден" В статье
Битая ссылка, <Объект не найден>, Уникальный Идентификатор, GUID мы обсуждали как востановить битые ссылки!
А вот как найти в базе все битые ссылки, которые имеют вид типа "<Объект не найден> (137:8b270030482898d011daad3cc45fc830)"?
Для поиска этого была
написана данная обработка:
Скачивать файлы может только зарегистрированный пользователь!
Для поиска: Выбираем объекты метаданных , которые хотим проверить, жмем кнопочку "Выполнить" и наблюдаем в таблице выходные данные. Откуда можем попасть в объекты-источники.
Для программиста:
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
ИспользоватьОграничение = ЗначениеЗаполнено(ОграничениеТипов);
РезультатПоиска.Очистить();
Для Каждого ОбъектыМетаданных Из КоллекцияОбъектов Цикл
Для Каждого ОбъектМетаданных Из ОбъектыМетаданных Цикл
Состояние(ОбъектМетаданных.ПолноеИмя());
ПроверитьОбъектНаБитыеСсылки(ОбъектМетаданных);
КонецЦикла;
КонецЦикла;
Для Каждого ОбъектыМетаданных Из КоллекцияРегистров Цикл
Для Каждого ОбъектМетаданных Из ОбъектыМетаданных Цикл
Состояние(ОбъектМетаданных.ПолноеИмя());
ПроверитьРегистрНаБитыеСсылки(ОбъектМетаданных);
КонецЦикла;
КонецЦикла;
//Анализ последовательностей
//ПроверитьОбъектНаБитыеСсылки(Метаданные.Справочники.СотрудникиОрганизаций);
КонецПроцедуры
Процедура ВывестиДанные(ТекстЗапроса)
Запрос = Новый Запрос(ТекстЗапроса);
Попытка
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
ТЗ = РезультатЗапроса.Выгрузить();
Для Каждого Стр Из ТЗ Цикл
ОбработкаПрерыванияПользователя();
Строка = РезультатПоиска.Добавить();
ЗаполнитьЗначенияСвойств(Строка, Стр);
КонецЦикла;
КонецЕсли;
Исключение
Сообщить(ИнформацияОбОшибке().Описание + " " + ИнформацияОбОшибке().Причина);
КонецПопытки;
КонецПроцедуры
Процедура ПроверитьРегистрНаБитыеСсылки(ОбъектМетаданных)
ИмяТаблицы = ОбъектМетаданных.ПолноеИмя();
Если Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
Если ОбъектМетаданных.РежимЗаписи = НезависимыйРежимЗаписи Тогда
//АнализСвойствРегистраСведений(ОбъектМетаданных, ОбъектМетаданных.Измерения, ИмяТаблицы);
//АнализСвойствРегистраСведений(ОбъектМетаданных, ОбъектМетаданных.Ресурсы, ИмяТаблицы);
//АнализСвойствРегистраСведений(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
Возврат;
КонецЕсли;
АнализСвойствРегистра(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
КонецЕсли;
АнализСвойствРегистра(ОбъектМетаданных, ОбъектМетаданных.Измерения, ИмяТаблицы);
АнализСвойствРегистра(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
АнализРегистратораРегистра(ОбъектМетаданных, ИмяТаблицы);
Если Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда
//Для рег. бухгалтерии анализ субконто
КонецЕсли;
Если Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
//Для регистров расчета доп. анализ
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьОбъектНаБитыеСсылки(ОбъектМетаданных)
ИмяТаблицы = ОбъектМетаданных.ПолноеИмя();
АнализСвойствОбъекта(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
Для Каждого ТабЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
Если ТабличныеЧастиИсключения.Найти(ТабЧасть.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
АнализСвойствОбъекта(ОбъектМетаданных, ТабЧасть.Реквизиты, ИмяТаблицы + "." + ТабЧасть.Имя)
КонецЦикла;
//проверка владельца у справочников
Если Метаданные.Справочники.Содержит(ОбъектМетаданных) И ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
МассивВладельцев = Новый Массив;
Для Каждого Элемент Из ОбъектМетаданных.Владельцы Цикл
МассивВладельцев.Добавить(Элемент);
КонецЦикла;
//АнализСвойствВладельцаОбъекта(ОбъектМетаданных, МассивВладельцев, ИмяТаблицы);
КонецЕсли;
//Для задач поле исполнитель
//проверки в журналах
ОбработкаПрерыванияПользователя();
КонецПроцедуры
Процедура АнализСвойствОбъекта(ОбъектМетаданных, Свойства, ИмяТаблицы)
Для Каждого Реквизит Из Свойства Цикл
Если РеквизитыИсключения.Найти(Реквизит.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
Для Каждого моТип Из Реквизит.Тип.Типы() Цикл
ТекстЗапроса = "";
МетаданныеТипа = Метаданные.НайтиПоТипу(моТип);
Если МетаданныеТипа <> Неопределено
И Не Метаданные.Перечисления.Содержит(МетаданныеТипа) Тогда
Если ИспользоватьОграничение Тогда
Если Не ПоискПоТипу(МетаданныеТипа.ПолноеИмя()) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ДобавитьВЗапросОбъект(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, Реквизит.Имя, моТип);
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ВывестиДанные(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура АнализСвойствРегистра(ОбъектМетаданных, Свойства, ИмяТаблицы)
Для Каждого Реквизит Из Свойства Цикл
Если РеквизитыИсключения.Найти(Реквизит.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
Для Каждого моТип Из Реквизит.Тип.Типы() Цикл
ТекстЗапроса = "";
МетаданныеТипа = Метаданные.НайтиПоТипу(моТип);
Если МетаданныеТипа <> Неопределено
И Не Метаданные.Перечисления.Содержит(МетаданныеТипа) Тогда
Если ИспользоватьОграничение Тогда
Если Не ПоискПоТипу(МетаданныеТипа.ПолноеИмя()) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ДобавитьВЗапросРегистр(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, Реквизит.Имя, моТип);
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ВывестиДанные(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура АнализРегистратораРегистра(ОбъектМетаданных, ИмяТаблицы)
МассивРегистраторов = ПолучитьСписокРегистраторов(ОбъектМетаданных);
Для Каждого Регистратор Из МассивРегистраторов Цикл
Если РеквизитыИсключения.Найти("Регистратор") <> Неопределено Тогда
Продолжить;
КонецЕсли;
моТип = Регистратор;
ТекстЗапроса = "";
МетаданныеТипа = Метаданные.НайтиПоТипу(моТип);
Если МетаданныеТипа <> Неопределено
И Не Метаданные.Перечисления.Содержит(МетаданныеТипа) Тогда
Если ИспользоватьОграничение Тогда
Если Не ПоискПоТипу(МетаданныеТипа.ПолноеИмя()) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ДобавитьВЗапросРегистр(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, "Регистратор", моТип);
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ВывестиДанные(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ПолучитьСписокРегистраторов(ОбъектМетаданных)
МассивРегистраторов = Новый Массив;
МенеджерОбъект = ПолучитьМенеджерОбъекта(ОбъектМетаданных);
Если МенеджерОбъект <> Неопределено Тогда
НаборЗаписей = МенеджерОбъект.СоздатьНаборЗаписей();
ЭлементОтбора = НаборЗаписей.Отбор.Регистратор;
МассивРегистраторов = ЭлементОтбора.ТипЗначения.Типы();
КонецЕсли;
Возврат МассивРегистраторов;
КонецФункции
Функция ПолучитьМенеджерОбъекта(ОбъектМетаданных)
Перем МенеджерОбъекта;
Если Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыБухгалтерии[ОбъектМетаданных.Имя];
ИначеЕсли Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыНакопления[ОбъектМетаданных.Имя];
ИначеЕсли Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыСведений[ОбъектМетаданных.Имя];
ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыРасчета[ОбъектМетаданных.Имя];
КонецЕсли;
Возврат МенеджерОбъекта;
КонецФункции
Функция ПоискПоТипу(ИмяТипа)
Результат = Ложь;
Если ИспользоватьОграничение Тогда
МассивСтрок = ОграничениеТипов.НайтиСтроки(Новый Структура("ТипДанных", ИмяТипа));
Если ЗначениеЗаполнено(МассивСтрок) Тогда
Результат = Истина;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура ДобавитьВЗапросРегистр(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, ИмяРеквизита, ТипРеквизита)
Текст = "ВЫБРАТЬ Об." + ИмяРеквизита + " КАК Объект,
| """ + ИмяТаблицы + "." + ИмяРеквизита + """ КАК ТаблицаИсточник,
| Об.Регистратор КАК ОбъектИсточник,
| " + ДобавитьОписаниеТипа(ИмяРеквизита, ТипРеквизита) + "
|ИЗ
| " + ИмяТаблицы + " КАК Об
|ГДЕ " + ДобавитьУсловия(ИмяРеквизита, ТипРеквизита);
ТекстЗапроса = ТекстЗапроса + ?(ПустаяСтрока(ТекстЗапроса), "", Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС) + Текст;
КонецПроцедуры
Процедура ДобавитьВЗапросОбъект(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, ИмяРеквизита, ТипРеквизита)
Текст = "ВЫБРАТЬ Об." + ИмяРеквизита + " КАК Объект,
| """ + ИмяТаблицы + "." + ИмяРеквизита + """ КАК ТаблицаИсточник,
| Об.Ссылка КАК ОбъектИсточник,
| " + ДобавитьОписаниеТипа(ИмяРеквизита, ТипРеквизита) + "
|ИЗ
| " + ИмяТаблицы + " КАК Об
|ГДЕ " + ДобавитьУсловия(ИмяРеквизита, ТипРеквизита);
ТекстЗапроса = ТекстЗапроса + ?(ПустаяСтрока(ТекстЗапроса), "", Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС) + Текст;
КонецПроцедуры
Функция ДобавитьУсловия(ИмяРеквизита, ТипРеквизита)
мдОбъекта = Метаданные.НайтиПоТипу(ТипРеквизита);
ИмяТаблицы = мдОбъекта.ПолноеИмя();
ПроверкаНаПустыеЗначения = " Об." + ИмяРеквизита + " ССЫЛКА " + ИмяТаблицы;
ПроверкаНаПустыеЗначения = ПроверкаНаПустыеЗначения + " И ВЫРАЗИТЬ(Об." + ИмяРеквизита + " КАК " + ИмяТаблицы + ").Ссылка есть null";
Если Не Метаданные.Перечисления.Содержит(мдОбъекта) Тогда
ПроверкаНаПустыеЗначения = ПроверкаНаПустыеЗначения + " И Об." + ИмяРеквизита + " <> Значение(" + ИмяТаблицы + ".ПустаяСсылка)";
КонецЕсли;
Возврат ПроверкаНаПустыеЗначения;
КонецФункции
Функция ДобавитьОписаниеТипа(ИмяРеквизита, ТипРеквизита)
ОбъектТипа = Метаданные.НайтиПоТипу(ТипРеквизита);
ИмяТаблицы = ОбъектТипа.ПолноеИмя();
ОписаниеТипа = """" + ИмяТаблицы + """ КАК ТипДанных";
Возврат ОписаниеТипа;
КонецФункции
Процедура ОграничениеТиповТипДанныхНачалоВыбора(Элемент, СтандартнаяОбработка)
Перем ЭлементСписка;
СтандартнаяОбработка = Ложь;
Строка = ЭлементыФормы.ОграничениеТипов.ТекущиеДанные;
Если Не ПустаяСтрока(Строка.ТипДанных) Тогда
ЭлементСписка = СписокТипов.НайтиПоЗначению(Строка.ТипДанных);
КонецЕсли;
ВыбранныйЭлемент = СписокТипов.ВыбратьЭлемент( , ЭлементСписка);
Если ВыбранныйЭлемент <> Неопределено Тогда
Строка.ТипДанных = ВыбранныйЭлемент.Значение;
КонецЕсли;
КонецПроцедуры
РеквизитыИсключения = Новый Массив;
ТабличныеЧастиИсключения = Новый Массив;
СписокТипов = Новый СписокЗначений;
Для Каждого ОбъектМетаданных Из Метаданные.Справочники Цикл
СписокТипов.Добавить(ОбъектМетаданных.ПолноеИмя(), ОбъектМетаданных.Имя, , БиблиотекаКартинок.СправочникОбъект);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Документы Цикл
СписокТипов.Добавить(ОбъектМетаданных.ПолноеИмя(), ОбъектМетаданных.Имя, , БиблиотекаКартинок.ДокументОбъект);
КонецЦикла;
КоллекцияОбъектов = Новый Массив;
КоллекцияОбъектов.Добавить(Метаданные.ПланыОбмена);
КоллекцияОбъектов.Добавить(Метаданные.Справочники);
КоллекцияОбъектов.Добавить(Метаданные.Документы);
КоллекцияОбъектов.Добавить(Метаданные.ПланыВидовХарактеристик);
КоллекцияОбъектов.Добавить(Метаданные.ПланыСчетов);
КоллекцияОбъектов.Добавить(Метаданные.ПланыВидовРасчета);
КоллекцияОбъектов.Добавить(Метаданные.БизнесПроцессы);
КоллекцияОбъектов.Добавить(Метаданные.Задачи);
КоллекцияРегистров = Новый Массив;
КоллекцияРегистров.Добавить(Метаданные.РегистрыСведений);
КоллекцияРегистров.Добавить(Метаданные.РегистрыНакопления);
КоллекцияРегистров.Добавить(Метаданные.РегистрыБухгалтерии);
КоллекцияРегистров.Добавить(Метаданные.РегистрыРасчета);
Категория:
1С Общие вопросы - Обычные формы Отправка sms из 1C через avisosms.ru. Столкнулся с задачей отправки sms из 1С. Спасибо Якову за напутствие в решении данной задачи и указание сервиса avisosms.ru.
На сайте сервиса предоставлена документация по работе с ним. В частности сервис предлагает следующие варианты работы:
* JSON протокол
* email2SMS протокол
* HTTP GET протокол
* Удаленный доступ к телефонной книге
* XML протокол
После проб и ошибок с протоколом email2sms (ну не любит мой провайдер через smtp слать письма на не очень красивые адреса относя их к спаму и блокируя) был выбран вариант решения с JSON протоколом. Для краткой демонстрации работы сервера приведена небольшая конфигурация. Конфигурация
написана на 1С Предприятие 8.2 с поддержкой работы веб-клиента. Для работы конфигурации необходимо заполнить константы:
* ПользовательСМС – Ваш логин в систему;
* ПарольСМС – Ваш пароль в систему;
* ПодписьСМС – Ваш адрес отправителя, который был создан в личном кабинете.
Конфигурация позволяет:
* Отправлять смс контрагенту, номер которого записан в соответствующем реквизите (номер пишем в формате 380ХХХХХХХХХХ);
* Получать статусы отправленных смс.
Ниже приведу код формирования запроса на отправку смс
Код 1C v 8.2 УП &НаСервере
Функция ОтправитьСервер()
УспешнаяОтправка = Ложь;
ПараметрJSON = "{'username': '" + Константы.ПользовательСМС.Получить() + "'";
ПараметрJSON = ПараметрJSON + ",'password': '" + Константы.ПарольСМС.Получить() + "'";
ПараметрJSON = ПараметрJSON + ",'request_type': 'send_message'";
ПараметрJSON = ПараметрJSON + ",'destination_address': '" + Объект.Контрагент.НомерТелефона+ "'";
ПараметрJSON = ПараметрJSON + ",'message': '" + Объект.ТекстСМС+ "'";
ПараметрJSON = ПараметрJSON + ",'source_address': '" + Константы.ПодписьСМС.Получить() + "'";
ПараметрJSON = ПараметрJSON + ",flash:'0'}";
Попытка
WinHttp=Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Option(2,"Windows-1251");
WinHttp.Open("POST","http://api.avisosms.ru/sms/json/",0);
WinHttp.SetRequestHeader("Accept-Language", "ru");
WinHttp.SetRequestHeader("Accept-Charset","Windows-1251");
WinHttp.setRequestHeader("Content-Language", "ru");
WinHttp.setRequestHeader("Content-Charset", "Windows-1251");
WinHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=Windows-1251");
WinHttp.Send(ПараметрJSON);
ТекстОтвет = WinHttp.ResponseText();
Если Найти(ТекстОтвет, "OK_Operation_Completed") Тогда
УспешнаяОтправка = Истина;
КонецЕсли;
Исключение
Сообщить("Ошибка соединения:");
Сообщить(ОписаниеОшибки());
КонецПопытки;
//Запись отправленной смс в историю
Если УспешнаяОтправка Тогда
ПозицияКодаНачало = Найти(ТекстОтвет, "messageId") + СтрДлина("messageId")+3;
ПозицияКодаКонец = Найти(ТекстОтвет, "}");
КодСМС = Сред(ТекстОтвет, ПозицияКодаНачало, ПозицияКодаКонец-ПозицияКодаНачало-1);
СМСРассылка.ЗаписатьСМСВИсторию(Объект.Контрагент, Объект.ТекстСМС, КодСМС);
Иначе
Сообщить("Отправка смс не состоялась. Текст ошибки: " + ТекстОтвет);
КонецЕсли;
Возврат УспешнаяОтправка;
КонецФункции
Источник Категория:
COM-объекты, WMI, WSH Функция проверки, строка написана только русскими и латинскими буквами? Код 1C v 8.х // Параметры:
// СтрокаПараметр - строка, проверяемая строка.
//
// Возвращаемое значение:
// Истина - строка состоит из допустимых символов
// Ложь - в строке встречаются недопустимые символы
//
// Описание:
// Строка проверяется на наличие только русских и латинских букв;
// кроме того, допускаются дефис, "Ё", "ё".
//
Функция СтрокаНаписанаРусскимиИлиЛатинскими(Знач СтрокаПараметр)
СтрокаПараметр = СокрЛП(СтрокаПараметр);
КоличествоСимволов = СтрДлина(СтрокаПараметр);
Если КоличествоСимволов > 0 Тогда
ПервыйСимвол = КодСимвола(Лев(СтрокаПараметр,1));
Русские = (ПервыйСимвол >= 192) или (ПервыйСимвол = 184) или (ПервыйСимвол = 168);
СписокДопустимыхЗначений = Новый Соответствие;
СписокДопустимыхЗначений.Вставить(184,Истина); // ё
СписокДопустимыхЗначений.Вставить(168,Истина); // Ё
СписокДопустимыхЗначений.Вставить(45,Истина); // "-"
Для Сч = 1 По КоличествоСимволов Цикл
Код = КодСимвола(Сред(СтрокаПараметр,Сч));
// Большие латинские буквы: 65 - 90
// Маленькие латинские буквы: 97 - 122
// Русские буквы: 192 и больше
//русские:
Если Русские Тогда
Если (СписокДопустимыхЗначений[Код] = Неопределено) и (Код < 192) Тогда
Возврат Ложь;
КонецЕсли;
// латинские:
ИначеЕсли (Код <> 45) и ((Код < 65) или (Код > 90) и (Код < 97) или (Код > 122)) Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
Категория:
Работа с Текстом (Строкой) Функция проверки наличия только русских букв в строке допускаются пробелы и дефис и спецсимволы Код 1C v 8.х Функция СтрокаНаписанаПоРусски(Знач СтрокаПараметр) Экспорт
СтрокаПараметр = СокрЛП(СтрокаПараметр);
СписокДопустимыхЗначений = Новый СписокЗначений;
СписокДопустимыхЗначений.Добавить(184);
СписокДопустимыхЗначений.Добавить(168);
СписокДопустимыхЗначений.Добавить(45);
СписокДопустимыхЗначений.Добавить(46);
СписокДопустимыхЗначений.Добавить(32);
СписокДопустимыхЗначений.Добавить(48);
СписокДопустимыхЗначений.Добавить(49);
СписокДопустимыхЗначений.Добавить(50);
СписокДопустимыхЗначений.Добавить(51);
СписокДопустимыхЗначений.Добавить(52);
СписокДопустимыхЗначений.Добавить(53);
СписокДопустимыхЗначений.Добавить(54);
СписокДопустимыхЗначений.Добавить(55);
СписокДопустимыхЗначений.Добавить(56);
СписокДопустимыхЗначений.Добавить(57);
Для Сч=1 По СтрДлина(СтрокаПараметр) Цикл
Код = КодСимвола(СтрокаПараметр,Сч);
Если (Код<192) И (СписокДопустимыхЗначений.НайтиПоЗначению(Код) = Неопределено) Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Категория:
Работа с Текстом (Строкой) Функция дни рождения сотрудников Данная функция
написана для ЗиК 7.7
Код 1C v 7.x
//Функция подбирает окончание для возраста
Функция СтрГода(Возраст)
Остаток = Возраст%10;
Если Остаток = 1 Тогда
Стр = "год";
ИначеЕсли ((Остаток > 1) и (Остаток < 5)) Тогда
Стр = "года";
Иначе
Стр = "лет";
КонецЕсли;
Возврат Стр;
КонецФункции
//Формируем дни рождения Сотрудников
Процедура ДниРожденияСотрудников()
ТекстДР="";
Именинники = СоздатьОбъект("СписокЗначений");
СпрСотр = СоздатьОбъект("Справочник.Сотрудники");
СпрСотр.ВыбратьЭлементы();
Пока СпрСотр.ПолучитьЭлемент()= 1 Цикл
ТекЭлем = СпрСотр.ТекущийЭлемент();
Если ТекЭлем.ЭтоГруппа() = 0 Тогда
Если ((ТекЭлем.Родитель <> "Уволенные")) Тогда
ТекСотр = СпрСотр.ТекущийЭлемент();
Если (ПустоеЗначение(ТекСотр.СостояниеФизЛица.Получить(НачМесяца(ТекущаяДата()))) = 0) Тогда
Если (ДатаМесяц(ТекСотр.ДатаРождения) = ДатаМесяц(ТекущаяДата())) Тогда
Именинники.ДобавитьЗначение(ТекСотр);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если Именинники.РазмерСписка() <> 0 Тогда
ТекстДР=ТекстДР+" ********* СПИСОК ИМЕНИННИКОВ *********"+РазделительСтрок+" за месяц "+Формат(ТекущаяДата(),"ДММММ")+РазделительСтрок;
ТекстДР=ТекстДР+"-----------------------------------------------------------------------------------------------------------------------------------------------"+РазделительСтрок;
Для к = 1 по Именинники.РазмерСписка() Цикл
Сотр = Именинники.ПолучитьЗначение(к);
Возраст = (Число(ДатаГод(ТекущаяДата()))-Число(ДатаГод(Сотр.ДатаРождения)));
РазницаДней = (Число(ДатаЧисло(Сотр.ДатаРождения))-Число(ДатаЧисло(ТекущаяДата())));
СтрГода = СтрГода(Возраст);
Если (ДатаЧисло(Сотр.ДатаРождения) < ДатаЧисло(ТекущаяДата())) Тогда
ТекстДР=ТекстДР+" "+Сотр+" "+Сотр.ДатаРождения+" уже исполнилось "+Возраст+" "+СтрГода+"!"+РазделительСтрок;
Иначе
Если (РазницаДней = 2) Тогда
ТекстДР=ТекстДР+"ПОСЛЕЗАВТРА! "+Сотр+" послезавтра "+Сотр.ДатаРождения+" будет праздновать " + Возраст + "-й День Рождения!!!! ";
ИначеЕсли (РазницаДней = 1) Тогда
ТекстДР=ТекстДР+"ЗАВТРА! "+ Сотр + " будет отмечает свой " + Возраст + "-й День рождения!";
ИначеЕсли (РазницаДней = 0) Тогда
ТекстДР=ТекстДР+"СЕГОДНЯ! "+ Сотр + " отмечает свой " + Возраст + "-й День рождения!";
КонецЕсли;
ТекстДР=ТекстДР+" ( "+Сотр.Подразделение.Получить(ТекущаяДата())+" , "+Сотр.Должность.Получить(ТекущаяДата())+" )"+РазделительСтрок;
КонецЕсли;
КонецЦикла;
Иначе
ТекстДР=ТекстДР+"В текущем месяце именинников нет!";
КонецЕсли;
Сообщить(ТекстДР);
КонецПроцедуры
В файловом архиве есть и сама обработка.
Категория:
Полезные, Универсальные Функции Как сохранить поле BLOB (image) как файл на диск? Наиболее эффективно это можно сделать с помощью объектов OLE Automation , работа с которыми осуществляется при помощи:
sp_OACreate, sp_OAGetProperty, sp_OASetProperty, sp_OAMethod, sp_OAGetErrorInfo, sp_OADestroy (подробное описание есть в http://technet.microsoft.com/ru-ru/library/ms203721(sql.90).aspx).
Рабочий пример процедуры (была
написана для сохранения zip-архивов, хранящихся в базе):
Код CREATE PROCEDURE dbo.SaveRequestDataAsFile (
@FileName varchar(1024) --имя файла
,@FilePath varchar(1024) --путь файла
,@ReqID --некое условие на таблицу
)
AS
BEGIN
DECLARE
@Stream integer,
@Buffer varbinary(4096),
@Size integer,
@Pos integer,
@BufSize integer,
@FileNameLocal varchar(1024),
@HR integer
if RIGHT(@FilePath, 1)<>'&# 092;' begin set @FilePath=@FilePath+'&# 092;' end
set @FileNameLocal = @FilePath + @FileName
SET @BufSize = 4096
EXEC @HR = sp_OACreate 'ADODB.Stream',@Stream OUT
if @HR<>0
begin
--обработка ошибки создания объекта
EXEC [dbo].[sp_displayoaerrorinfo] @Stream ,@HR
end
EXEC @HR = sp_OASetProperty @Stream,'Type',1 -- binary
EXEC @HR = sp_OASetProperty @Stream,'Mode',3 -- write|read
EXEC @HR = sp_OAMethod @Stream,'Open'
S_elect
@Size = DATALENGTH(SrvRequests.RequestData)
FROM SrvRequests WHERE SrvRequests.RequestID = @ReqID
Set @Pos=0
WHILE @Pos < @Size BEGIN
SET @BufSize = CASE WHEN @Size - @Pos < 4096 THEN @Size - @Pos ELSE 4096 END
S_elect @Buffer = substring(SrvRequests.RequestData ,@Pos+1, @BufSize)
from SrvRequests where SrvRequests.RequestID = @ReqID
EXEC @HR = sp_OAMethod @Stream, 'Write', NULL, @Buffer
SET @Pos = @Pos + @BufSize
END
EXEC @HR = sp_OAMethod @Stream,'SaveToFile',null, @FileNameLocal,2
EXEC @HR = sp_OAMethod @Stream,'Close'
EXEC @HR = sp_OADestroy @Stream
END
Рекомендуется создать еще пару процедур для внятного описания ошибок в случае их возникновения
Код CREATE PROCEDURE sp_hexadecimal
@binvalue varbinary(255),
@hexvalue varchar(255) OUTPUT
AS
DECLARE @charvalue varchar(255)
DECLARE @i int
DECLARE @length int
DECLARE @hexstring char(16)
S_elect @charvalue = '0x'
S_elect @i = 1
S_elect @length = DATALENGTH(@binvalue)
S_elect @hexstring = '0123456789abcdef'
WHILE (@i <= @length)
BEGIN
DECLARE @tempint int
DECLARE @firstint int
DECLARE @secondint int
S_elect @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
S_elect @firstint = FLOOR(@tempint/16)
S_elect @secondint = @tempint - (@firstint* 16)
S_elect @charvalue = @charvalue +
SUBSTRING(@hexstring, @firstint+1, 1) +
SUBSTRING(@hexstring, @secondint+1, 1)
S_elect @i = @i + 1
END
----------------------------------------------------------------------
CREATE PROCEDURE sp_displayoaerrorinfo
@object int,
@hresult int
AS
DECLARE @output varchar(255)
DECLARE @hrhex char(10)
DECLARE @hr int
DECLARE @source varchar(255)
DECLARE @description varchar(255)
PRINT 'OLE Automation Error Information'
EXEC sp_hexadecimal @hresult, @hrhex OUT
S_elect @output = ' HRESULT: ' + @hrhex
PRINT @output
EXEC @hr = sp_OAGetErrorInfo @object, @source OUT, @description OUT
IF @hr = 0
BEGIN
S_elect @output = ' Source: ' + @source
PRINT @output
S_elect @output = ' Description: ' + @description
PRINT @output
END
ELSE
BEGIN
PRINT ' sp_OAGetErrorInfo failed.'
RETURN
END
Категория:
OLE, ActiveX