Как программно создать нового пользователя или скопировать настройки существующего? Часто встречаю вопросы касаемые программного создания и настройки прав пользователей.
В этот статье я приведу примеры для Обычного и Управляемого приложений, которые программно создают пользователя в конфигураторе и в режиме Предприятие (справочник пользователи) и установку Групп пользователей.
В приложении к статье обработки, код которых приведен ниже: Скачать обработки
Обработки были написаны под УТ, но, при необходимости, вы можете их легко доработать под другие конфигурации.
Управляемое приложение: В конфигурациях на управляемом интерфейсе (Такси) изменили подход к ведению пользователей. Если вы добавляете не программно, то добавлять нужно из режима Предприятия - тогда пользователь ИБ у вас сам создатся. И если раньше, в обычном приложении, достаточно будет добавить польз в конфигураторе - и при заходе в Предприятие, этот польз сам создавался в спр Пользователи, то с управляемым приложением такой фокус не прокатит - система не даст зайти под пользователем ИБ, которого нет в справочнике Пользователи.
! В типовых конфигурациях для работы с пользователями активно используется БСП !
В общем модуле Пользователи используется программный интерфейс процедур и функций НовоеОписаниеПользователяИБ , ПрочитатьПользователяИБ , ЗаписатьПользователяИБ иУдалитьПользователяИБ .
Код создания нового пользователя с использованием БСП:
Код 1C v 8.3 &НаСервере
Функция КопированиеВсехНастроек(ПользовательСсылка,ПользовательПриемник)
Пользователь = Обработки.НастройкиПользователей.ИмяПользователяИБ(ПользовательСсылка);
Приемники = Новый Массив;
ТаблицаПользователей = Новый ТаблицаЗначений;
ТаблицаПользователей.Колонки.Добавить("Пользователь");
ТаблицаПользователей = Обработки.НастройкиПользователей.ПользователиДляКопирования(ПользовательСсылка, ТаблицаПользователей,
ТипЗнч(ПользовательСсылка) = Тип("СправочникСсылка.ВнешниеПользователи"));
Для Каждого СтрокаТаблицы Из ТаблицаПользователей Цикл
Приемники.Добавить(ПользовательПриемник);
КонецЦикла;
КопируемыеНастройки = Новый Массив;
КопируемыеНастройки.Добавить("НастройкиОтчетов");
КопируемыеНастройки.Добавить("НастройкиВнешнегоВида");
КопируемыеНастройки.Добавить("ПерсональныеНастройки");
КопируемыеНастройки.Добавить("Избранное");
КопируемыеНастройки.Добавить("НастройкиПечати");
КопируемыеНастройки.Добавить("ПрочиеПользовательскиеНастройки");
НастройкиСкопированы = Обработки.НастройкиПользователей.
КопированиеНастроекПользователей(ПользовательСсылка, Приемники, КопируемыеНастройки);
Возврат НастройкиСкопированы;
КонецФункции
Функция СоздатьНовыйУровеньДоступа(ФИО)
Рез = Справочники.CRM_УровниДоступа.НайтиПоНаименованию(ФИО);
Если Рез = Неопределено ИЛИ Рез = Справочники.CRM_УровниДоступа.ПустаяСсылка() Тогда
НовыйОбъект = Справочники.CRM_УровниДоступа.СоздатьЭлемент();
НовыйОбъект.Наименование = ФИО;
НовыйОбъект.Записать();
возврат НовыйОбъект.Ссылка;
КонецЕсли;
КонецФункции
Процедура ОбновитьДанныеПользователяИБ(ПользовательНастроек, Знач ОтображатьИмя = Истина)
Если ПользовательНастроек = Неопределено Тогда
Возврат;
КонецЕсли;
ПроверкаНаСуществующегоПользователя = ПользователиИнформационнойБазы.НайтиПоИмени(Объект.ФИОСоздаваемогоПользователя);
Если ПроверкаНаСуществующегоПользователя = Неопределено Тогда
Пользователь_Шаблон = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ПользовательНастроек.Наименование));
ОписаниеПользователяИБ = Пользователи.НовоеОписаниеПользователяИБ();
ПользовательИБСуществует = Ложь;
ДоступКИнформационнойБазеРазрешен = Ложь;
// Заполнение начальных значений свойств пользователяИБ.
Если ОбщегоНазначенияПовтИсп.РазделениеВключено() Тогда
ОписаниеПользователяИБ.ПоказыватьВСпискеВыбора = Ложь;
Иначе
ОписаниеПользователяИБ.ПоказыватьВСпискеВыбора =
НЕ Константы.ИспользоватьВнешнихПользователей.Получить();
КонецЕсли;
ОписаниеПользователяИБ.АутентификацияСтандартная = Истина;
ОписаниеПользователяИБ.Роли = Новый Массив;
ПрочитанныеСвойства = Неопределено;
Если Пользователи.ПрочитатьПользователяИБ(
ПользовательНастроек.ИдентификаторПользователяИБ,ПрочитанныеСвойства
) Тогда
// Установка связи пользователем ИБ.
//ДоступКИнформационнойБазеРазрешен = Истина;
// Копирование свойств и ролей пользователяИБ.
ЗаполнитьЗначенияСвойств(
ОписаниеПользователяИБ,
ПрочитанныеСвойства,
"АутентификацияOpen ID,
|АутентификацияСтандартная,
|ЗапрещеноИзменятьПароль,
|ПоказыватьВСпискеВыбора,
|АутентификацияОС,
|РежимЗапуска,
|Язык,
|Роли");
КонецЕсли;
ОписаниеПользователяИБ.Вставить("Действие", "Записать");
ОписаниеПользователяИБ.Вставить("Имя", Объект.ФИОСоздаваемогоПользователя);
НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
НовыйПользователь.Наименование = Объект.ФИОСоздаваемогоПользователя;
НовыйПользователь.ТекущееПодразделение = ПользовательНастроек.ТекущееПодразделение;
НовыйПользователь.CRM_УровеньДоступа = СоздатьНовыйУровеньДоступа(Объект.ФИОСоздаваемогоПользователя);
НовыйПользователь.Недействителен = ложь;
НовыйПользователь.ДополнительныеСвойства.Вставить(
"ОписаниеПользователяИБ", ОписаниеПользователяИБ);
НовыйПользователь.Записать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ГруппыПользователейПользователиГруппы.Ссылка
|ИЗ
| Справочник.ГруппыПользователей.Состав КАК ГруппыПользователейПользователиГруппы
|ГДЕ
| ГруппыПользователейПользователиГруппы.Пользователь =Пользователь
|
|СГРУППИРОВАТЬ ПО
| ГруппыПользователейПользователиГруппы.Ссылка";
Запрос.УстановитьПараметр("Пользователь", ПользовательНастроек);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
объ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
НоваяСтрока = объ.Состав.Добавить();
НоваяСтрока.Пользователь = НовыйПользователь.Ссылка;
объ.Записать();
КонецЦикла;
Запрос.Текст =
"ВЫБРАТЬ
| ГруппыДоступаПользователи.Ссылка
|ИЗ
| Справочник.ГруппыДоступа.Пользователи КАК ГруппыДоступаПользователи
|ГДЕ
| ГруппыДоступаПользователи.Пользователь =Пользователь
|
|СГРУППИРОВАТЬ ПО
| ГруппыДоступаПользователи.Ссылка";
Запрос.УстановитьПараметр("Пользователь", ПользовательНастроек);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
объ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
НоваяСтрока = объ.Пользователи.Добавить();
НоваяСтрока.Пользователь = НовыйПользователь.Ссылка;
объ.Записать();
КонецЦикла;
КопированиеВсехНастроек(ПользовательНастроек,НовыйПользователь.Ссылка);
Иначе
сообщить("Указанное ФИО Пользователя уже используется !!! ");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьПользователя(Команда)
СоздатьПользователяНаСервере();
КонецПроцедуры
&НаСервере
Процедура СоздатьПользователяНаСервере()
Если НЕ ЗначениеЗаполнено(Объект.ШаблонПользователяДляСозданияНового) Тогда
Возврат;
КонецЕсли;
// настройки устанавливаются на форму
ОбновитьДанныеПользователяИБ(Объект.ШаблонПользователяДляСозданияНового, Ложь);
КонецПроцедуры
&НаСервере
Процедура СкопироватьНастройкиНаСервере(ИзменяемыйПользователь,ШаблонПользователяДляКопирования)
//Копируем роли пользователя
тИзменяемыйПользователь = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ИзменяемыйПользователь.Наименование));
тШаблонПользователяДляКопирования = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ШаблонПользователяДляКопирования.Наименование));
//Очищаем роли
тИзменяемыйПользователь.Роли.Очистить();
// Копируем
СписокДоступныхРолейПользователяИБ = Новый СписокЗначений;
Для Каждого мРоль Из Метаданные.Роли Цикл
СтрокаСписокаДоступныхРолей = СписокДоступныхРолейПользователяИБ.Добавить();
СтрокаСписокаДоступныхРолей.Представление = мРоль.Представление();
СтрокаСписокаДоступныхРолей.Значение = мРоль;
КонецЦикла;
Для Каждого СтрокаСпискаДоступныхРолей Из СписокДоступныхРолейПользователяИБ Цикл
Если тШаблонПользователяДляКопирования.Роли.Содержит(СтрокаСпискаДоступныхРолей.Значение) Тогда
тИзменяемыйПользователь.Роли.Добавить(СтрокаСпискаДоступныхРолей.Значение);
КонецЕсли;
КонецЦикла;
тИзменяемыйПользователь.Записать();
//Копируем настройки БСП
КопированиеВсехНастроек(ШаблонПользователяДляКопирования,ИзменяемыйПользователь);
КонецПроцедуры
&НаКлиенте
Процедура СкопироватьНастройки(Команда)
СкопироватьНастройкиНаСервере(Объект.ИзменяемыйПользователь, Объект.ШаблонПользователяДляКопирования);
КонецПроцедуры
Обычное приложение: В обычном все проще:
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
Если НЕ ЗначениеЗаполнено(ШаблонПользователяДляСозданияНового) Тогда
Возврат;
КонецЕсли;
// настройки устанавливаются на форму
ОбновитьДанныеПользователяИБ(ШаблонПользователяДляСозданияНового, Ложь);
КонецПроцедуры
Процедура ОбновитьДанныеПользователяИБ(ПользовательНастроек, Знач ОтображатьИмя = Истина)
Если ПользовательНастроек = Неопределено Тогда
Возврат;
КонецЕсли;
ПроверкаНаСуществующегоПользователя = ПользователиИнформационнойБазы.НайтиПоИмени(ФИОСоздаваемогоПользователя);
Если ПроверкаНаСуществующегоПользователя = Неопределено Тогда
Пользователь_Шаблон = ПользователиИнформационнойБазы.НайтиПоИмени(сокрлп(ПользовательНастроек.Код));
ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
ПользовательИБ.Имя = ФИОСоздаваемогоПользователя;
ПользовательИБ.АутентификацияСтандартная = Истина;
ПользовательИБ.Пароль = ПарольСоздаваемогоПользователя;
ПользовательИБ.ПолноеИмя = ФИОСоздаваемогоПользователя;
ПользовательИБ.ПоказыватьВСпискеВыбора = Истина;
ПользовательИБ.ОсновнойИнтерфейс = Пользователь_Шаблон.ОсновнойИнтерфейс;
ПользовательИБ.Язык = Пользователь_Шаблон.Язык;
СписокДоступныхРолейПользователяИБ = Новый СписокЗначений;
Для Каждого мРоль Из Метаданные.Роли Цикл
СтрокаСписокаДоступныхРолей = СписокДоступныхРолейПользователяИБ.Добавить();
СтрокаСписокаДоступныхРолей.Представление = мРоль.Представление();
СтрокаСписокаДоступныхРолей.Значение = мРоль;
КонецЦикла;
Для Каждого СтрокаСпискаДоступныхРолей Из СписокДоступныхРолейПользователяИБ Цикл
Если Пользователь_Шаблон.Роли.Содержит(СтрокаСпискаДоступныхРолей.Значение) Тогда
ПользовательИБ.Роли.Добавить(СтрокаСпискаДоступныхРолей.Значение);
КонецЕсли;
КонецЦикла;
ПользовательИБ.Записать();
НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
//НовыйПользователь.ИдентификаторПользователяИБ = ПользовательИБ.УникальныйИдентификатор;
НовыйПользователь.Код = ФИОСоздаваемогоПользователя;
НовыйПользователь.Наименование = ФИОСоздаваемогоПользователя;
НовыйПользователь.Родитель = ПользовательНастроек.Родитель;
НовыйПользователь.Подразделение = ПользовательНастроек.Подразделение;
НовыйПользователь.Категория = ПользовательНастроек.Категория;
НовыйПользователь.Руководитель = ПользовательНастроек.Руководитель;
НовыйПользователь.Действует = ПользовательНастроек.Действует;
НовыйПользователь.Записать();
НаборПользователя = РегистрыСведений.НастройкиПользователей.СоздатьНаборЗаписей();
НаборПользователя.Отбор.Пользователь.Установить(ПользовательНастроек);
НаборПользователя.Прочитать();
НаборНовогоПользователя = РегистрыСведений.НастройкиПользователей.СоздатьНаборЗаписей();
НаборНовогоПользователя.Отбор.Пользователь.Установить(НовыйПользователь.Ссылка);
Для Каждого СтрокаНастроек из НаборПользователя Цикл
НоваяСтрокаНастроек = НаборНовогоПользователя.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрокаНастроек,СтрокаНастроек);
НоваяСтрокаНастроек.Пользователь = НовыйПользователь.Ссылка;
Если Найти(СтрокаНастроек.Настройка.Наименование,"Основной ответственный") Тогда
НоваяСтрокаНастроек.Значение = НовыйПользователь.Ссылка;
КонецЕсли;
КонецЦикла;
Если НаборНовогоПользователя.Количество()>0 Тогда
НаборНовогоПользователя.Записать();
КонецЕсли;
сообщить("Создан пользователь "+ФИОСоздаваемогоПользователя);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ГруппыПользователейПользователиГруппы.Ссылка
|ИЗ
| Справочник.ГруппыПользователей.ПользователиГруппы КАК ГруппыПользователейПользователиГруппы
|ГДЕ
| ГруппыПользователейПользователиГруппы.Пользователь =Пользователь
|
|СГРУППИРОВАТЬ ПО
| ГруппыПользователейПользователиГруппы.Ссылка";
Запрос.УстановитьПараметр("Пользователь", ПользовательНастроек);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
объ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
НоваяСтрока = объ.ПользователиГруппы.Добавить();
НоваяСтрока.Пользователь = НовыйПользователь.Ссылка;
объ.Записать();
КонецЦикла;
Иначе
сообщить("Указанное ФИО Пользователя уже используется !!! ");
КонецЕсли;
КонецПроцедуры
еще пример:
Код 1C v 8.х Функция ДобавитьПользователя(ИмяПользователя, ДоменноеИмя, ПользовательАктивен, АутентификацияОС, Авторизация1СПредприятия, МассивРолей) Экспорт
// Попробуем найти сотрудника
Пользователь = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
// Теперь попробум найти сотрудника по пользователю ос
Если Пользователь = Неопределено Тогда
Для Каждого ТекущийПользователь Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
Если ТекущийПользователь.ПользовательОС = ДоменноеИмя Тогда
Пользователь = ТекущийПользователь;
Прервать;
Конецесли;
КонецЦикла;
КонецЕсли;
//
// Если мы не нашли сотрудника, то создадим его
Если Пользователь = Неопределено Тогда
Пользователь = ПользователиИнформационнойБазы.СоздатьПользователя();
КонецЕсли;
//
// Записываем свойства
Пользователь.АутентификацияОС = АутентификацияОС;
Пользователь.АутентификацияСтандартная = Авторизация1СПредприятия;
Пользователь.ЗапрещеноИзменятьПароль = Истина;
Пользователь.Имя = ИмяПользователя;
Пользователь.ПолноеИмя = ИмяПользователя;
Пользователь.ПоказыватьВСпискеВыбора = Ложь;
Пользователь.ПользовательОС = ДоменноеИмя;
// Сначала очистим все текущие роли
Пользователь.Роли.Очистить();
// Теперь найдем переданный массив ролей в справочнике профилей
// и добавим все роли указанные в профиле. Все очень сложно, да
МассивИменРолей = Новый Массив();
Для Каждого Роль Из МассивРолей.Role Цикл
МассивИменРолей.Добавить(Роль);
КонецЦикла;
ТекстЗапроса = "ВЫБРАТЬ
| ПрофилиГруппДоступаРоли.Роль.Имя КАК Имя
|ИЗ
| Справочник.ПрофилиГруппДоступа.Роли КАК ПрофилиГруппДоступаРоли
|ГДЕ
| ПрофилиГруппДоступаРоли.Ссылка.Наименование В(&МассивИменРолей)";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("МассивИменРолей", МассивИменРолей);
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Роль Из Результат Цикл
НайденнаяРоль = Метаданные.Роли.Найти(Роль.Имя);
Если НайденнаяРоль <> Неопределено Тогда
Пользователь.Роли.Добавить(НайденнаяРоль);
КонецЕсли;
КонецЦикла;
// Записываем!
Пользователь.Записать();
// Теперь посмотрим нужно ли деактивировать пользователя
Если Не ПользовательАктивен Тогда
ДективироватьПользователя(Пользователь);
КонецЕсли;
// Запишем еще и справочник пользователя
ЗаполнитьСправочникПользователя(Пользователь);
Возврат Истина;
КонецФункции
// Процедура заполняет помимо прочего справочник пользователя
Процедура ЗаполнитьСправочникПользователя(ПользовательИБ) Экспорт
ТекстЗапроса = "ВЫБРАТЬ
| ИСТИНА КАК ЕстьПользователь,
| Пользователи.Ссылка КАК Пользователь
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ =ИдентификаторПользователяИБ
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ЛОЖЬ,
| NULL";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("ИдентификаторПользователяИБ", ПользовательИБ.УникальныйИдентификатор);
Результат = Запрос.Выполнить().Выгрузить()[0];
ОписаниеПользователя = Пользователи.НовоеОписаниеПользователяИБ();
Если Результат.ЕстьПользователь Тогда
ПользовательОбъект = Результат.Пользователь.ПолучитьОбъект();
Иначе
ПользовательОбъект = Справочники.Пользователи.СоздатьЭлемент();
ПользовательОбъект.ИдентификаторПользователяИБ = ПользовательИБ.УникальныйИдентификатор;
ПользовательОбъект.Наименование = ПользовательИБ.Имя;
ОписаниеПользователя.Вставить("Действие", "Записать");
ПользовательОбъект.ДополнительныеСвойства.Вставить("ОписаниеПользователяИБ", ОписаниеПользователя);
КонецЕсли;
ЗаполнитьЗначенияСвойств(ОписаниеПользователя, ПользовательИБ);
Для Каждого Элемент Из ОписаниеПользователя Цикл
ПользовательОбъект.ДополнительныеСвойства.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;
ПользовательОбъект.ДополнительныеСвойства.Удалить("Роли");
ПользовательОбъект.Записать();
КонецПроцедуры
Категория:
Пользователь, роль доступа, интерфейс Как получить текст из html? Один мой хороший клиент использует встроенный в 1С почтовый клиент.
До этого все работало хорошо, но недавно из-за установки нового банк-клиента на компьютере обновили Internet Explorer до 11 версии - стала появляться ошибка:
Поле объекта не обнаружено innerText
Пришлось немного доработать типовую функцию получения текста из html:
Код 1C v 8.х Функция ПреобразоватьТекстИзХТМЛФорматаВПростой(ТекстВФорматеХТМЛ) Экспорт
Попытка
НовыйHTMLДокумент = Новый COMОбъект("HtmlFile");
НовыйHTMLДокумент.open ("text/html");
НовыйHTMLДокумент.write(ТекстВФорматеХТМЛ);
НовыйHTMLДокумент.close();
Возврат СтрЗаменить(НовыйHTMLДокумент.all.item(0).innerText, Символ(13), "");
Исключение
Построитель = Новый ПостроительDOM;
ЧтениеHTML = Новый ЧтениеHTML;
ЧтениеHTML.УстановитьСтроку(ТекстВФорматеХТМЛ);
ДокументHTML = Построитель.Прочитать(ЧтениеHTML);
Возврат СокрЛП(ДокументHTML.Тело.ТекстовоеСодержимое);
КонецПопытки;
КонецФункции
еще функции пример получения:
Код 1C v 8.х // Процедура изменяет признак формат текста письма (Текст, HТМЛ),
// и при этом конвертирует сам текст.
//
// Параметры:
// ЭУHTML,ЭУТекст - Элементы управления формы, соответственно поле HTML и поле Текст
// Кнопка - выбранная кнопка ее текст "Простой текст" или "HTML" новый вид текста письма
// либо текст кнопки если пометку кнопки менять не требуется, соответственно
// вопрос о потере форматирования задаваться не будет
// Возвращаемое значение:
// Булево, признак выполнения изменения формата
//
Функция удИзменитьФорматТекста(ЭУHTML,ЭУТекст, Кнопка) Экспорт
Если ТипЗнч(Кнопка) = Тип("Строка") Тогда
НовыйВидТекстаПисьма = Кнопка;
ЕстьКнопка = Ложь;
Иначе
Если Кнопка.Пометка Тогда
Возврат Ложь;
КонецЕсли;
НовыйВидТекстаПисьма = Кнопка.Текст;
ЕстьКнопка = Истина;
КонецЕсли;
Если Найти(НовыйВидТекстаПисьма,"Простой текст") > 0 Тогда
ИсходныйТекст = ЭУHTML.ПолучитьТекст();
НачалоBODY = Найти(ИсходныйТекст, "<BODY>");
КонецBODY = Найти(ИсходныйТекст, "</BODY>");
Если ЕстьКнопка и (НачалоBODY > 0 И КонецBODY > 0 И (НачалоBODY + 6) < КонецBODY) Тогда
СтрокаВопроса = "Будет потеряно форматирование текста. Продолжить?";
ОтветНаВопрос = Вопрос(СтрокаВопроса, РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Нет);
Если ОтветНаВопрос <> КодВозвратаДиалога.Да Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
ФорматТекста = ЭУHTML.Документ.all.item(0).innerText;
ЭУТекст.Значение = СтрЗаменить(ФорматТекста, Символ(13), "");
ЭУТекст.Видимость = Истина;
ЭУHTML.Видимость = Ложь;
ЭУHTML.УстановитьТекст("");
Иначе
ФорматХТМЛ = СтрЗаменить(ЭУТекст.Значение, Символы.ПС, "<BR>");
ЭУHTML.УстановитьТекст(ФорматХТМЛ);
ЭУHTML.Видимость = Истина;
ЭУТекст.Видимость = Ложь;
КонецЕсли;
Если ЕстьКнопка Тогда
Кнопка.Пометка = Истина;
КонецЕсли;
Возврат Истина;
КонецФункции // обИзменитьФорматТекста()
Категория:
Работа с Интернет, Почтой (Mail), FTP Блокировка записей, невозможно изменить или удалить из регистра. Конфликт блокировок MS SQL + 1C При попытке удалить запись из регистра сведений - получаю ошибку: она заблокирована, ошибка блокировок и т.д.
Отключил всех пользователей, перезапустил сервер, пробую удалить - опять ошибка блокировки
Путем тестов было вяснено, что проблема не в коде, а происходит это на этапе обращения платформы к SQL серверу... после долгих поисков решений, в интернете была найдена статья, которая помогла в решении данной проблемы:
Кто что блокирует, MS SQL + 1C
В повседневной работе достаточно задействовать только первый блок "/*кто кого*/". Открываем MS SQL Server Management Studio, правой на корень - "new query" - вставляем код запроса (только верхнюю часть до "Кто что блокирует", остальное - для детального анализа), выполняем запрос (вверху есть кнопочка выполнения запроса).
Выполнив запрос, запоминаем "ID виновника", быстренько идем в консоль сервера 1С, заходим в ветку "Сеансы" нашей базы. Видим все соединения с 1С-сервером, ищем там колонку "Соединение с СУБД", чтобы увидеть соединения 1С-сервера с MSSQL-сервером. В колонке будет всего несколько заполненных значений, среди них и будет "ID виновника".
Что делать если его там нет, тут 3 варианта:
1. Вернитесь в MSSQL и сделайте запрос еще несколько раз подряд, если значения меняются или таблица вообще пуста - постоянной блокировки нет, у вас (уже) все в порядке.
2. Сеанс который блокирует MSSQL находится в другой базе т.е. блокировка не в той базе (можно попробовать задействовать ветку всех сеансов в консоли 1С-сервера) - вернитесь в MSSQL и внимательно посмотрите в колонку DB в ней находится название базы.
3. Бывает что ID процесса в 1С-консоли вообще отсутствует, такое тоже бывает если у вас есть какие-то внешние программы подключенные напрямую в базу 1С, если пускаете кого-то в MSSQL напрямую, то вариант не исключен.
Код SQL-запроса:
Код SQL SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE @dbid AS smallint;
use [ВАШАБАЗА];
SET @dbid=DB_ID();
/*кто кого*/
SELECT DB_NAME(pr1.dbid) AS 'DB'
,pr1.spid AS 'ID жертвы'
,RTRIM(pr1.loginame) AS 'Login жертвы'
,pr2.spid AS 'ID виновника'
,RTRIM(pr2.loginame) AS 'Login виновника'
,pr1.program_name AS 'программа жертвы'
,pr2.program_name AS 'программа виновника'
,txt.[text] AS 'Запрос виновника'
FROM MASTER.dbo.sysprocesses pr1(NOLOCK)
JOIN MASTER.dbo.sysprocesses pr2(NOLOCK)
ON (pr2.spid = pr1.blocked)
OUTER APPLY sys.[dm_exec_sql_text](pr2.[sql_handle]) AS txt
WHERE pr1.blocked <> 0
/* Кто что блокирует */
SELECT s.[nt_username]
,request_session_id
,tran_locks.[request_status]
,rd.[Description] + ' (' + tran_locks.resource_type + ' ' + tran_locks.request_mode + ')' [Object]
,txt_blocked.[text]
,COUNT(*) [COUNT]
FROM sys.dm_tran_locks AS tran_locks WITH (NOLOCK)
JOIN sys.sysprocesses AS s WITH (NOLOCK)
ON tran_locks.request_session_id = s.[spid]
JOIN (
SELECT 'KEY' AS sResource_type
,p.[hobt_id] AS [id]
,QUOTENAME(o.name) + '.' + QUOTENAME(i.name) AS [Description]
FROM sys.partitions p
JOIN sys.objects o
ON p.object_id = o.object_id
JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
UNION ALL
SELECT 'RID' AS sResource_type
,p.[hobt_id] AS [id]
,QUOTENAME(o.name) + '.' + QUOTENAME(i.name) AS [Description]
FROM sys.partitions p
JOIN sys.objects o
ON p.object_id = o.object_id
JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
UNION ALL
SELECT 'PAGE'
,p.[hobt_id]
,QUOTENAME(o.name) + '.' + QUOTENAME(i.name)
FROM sys.partitions p
JOIN sys.objects o
ON p.object_id = o.object_id
JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
UNION ALL
SELECT 'OBJECT'
,o.[object_id]
,QUOTENAME(o.name)
FROM sys.objects o
) AS RD
ON RD.[sResource_type] = tran_locks.resource_type
AND RD.[id] = tran_locks.resource_associated_entity_id
OUTER APPLY sys.[dm_exec_sql_text](s.[sql_handle]) AS txt_Blocked
WHERE (
tran_locks.request_mode = 'X'
AND tran_locks.resource_type = 'OBJECT'
)
OR tran_locks.[request_status] = 'WAIT'
GROUP BY
s.[nt_username]
,request_session_id
,tran_locks.[request_status]
,rd.[Description] + ' (' + tran_locks.resource_type + ' ' + tran_locks.request_mode + ')'
,txt_blocked.[text]
ORDER BY
6 DESC
IF EXISTS ( SELECT Name
FROM tempdb..sysobjects
WHERE name LIKE '#LOCK_01_01%' )
DROP TABLE #LOCK_01_01
CREATE TABLE #LOCK_01_01
(
spid INT,
dbid INT,
ObjId INT,
IndId SMALLINT,
Type VARCHAR(20),
Resource VARCHAR(50),
Mode VARCHAR(20),
Status VARCHAR(20)
)
INSERT INTO #LOCK_01_01
EXEC sp_lock
select OBJECT_NAME(ObjId) as [Имя объекта], Mode [Тип блокировки (код)],
CASE
WHEN Mode='Sch-S' THEN 'Блокировка стабильности схемы. Гарантирует, что элемент схемы, такой как таблица или индекс, не будет удален до тех пор, пока сеанс связи удерживает блокировку стабильности схемы на данный элемент схемы;'
WHEN Mode='Sch-М' THEN '= Блокировка изменения схемы. Должен поддерживаться любым сеансом связи, во время которого предполагается изменить схему данного ресурса. Гарантирует, что другие сеансы не имеют ссылок на обозначенный объект;'
WHEN Mode='S' THEN 'S = Коллективная блокировка. Удерживающему сеансу предоставлен коллективный доступ к ресурсу;'
WHEN Mode='U' THEN 'U = Блокировка обновления. Указывает блокировку обновления, полученную на ресурсы, которые со временем могут быть обновлены. Используется для предотвращения общей формы взаимоблокировки, которая возникает, когда множество сеансов блокируют ресурсы для потенциального обновления в последующее время;'
WHEN Mode='X' THEN 'X = Монопольная блокировка. Удерживающему сеансу предоставлен исключительный доступ к ресурсу;'
WHEN Mode='IS' THEN 'IS = Блокировка с намерением коллективного доступа. Указывает намерение поместить S блокировки на некоторые подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='IU' THEN 'IU = Блокировка с намерением обновления. Указывает намерение поместить U блокировки на некоторые подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='IX' THEN 'IX = Блокировка с намерением монопольного доступа. Указывает намерение поместить X блокировки на некоторые подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='SIU' THEN 'SIU = Коллективная блокировка с намерением обновления. Указывает коллективный доступ к ресурсу с намерением получения блокировок обновления на подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='SIX' THEN 'SIX = Коллективная блокировка с намерением монопольного доступа. Указывает коллективный доступ к ресурсу с намерением получения монопольных блокировок на подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='UIX' THEN 'UIX = Блокировка обновления с намерением монопольного доступа. Указывает блокировку обновления ресурса с намерением получения монопольных блокировок на подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='BU' THEN 'BU = Блокировка массового обновления. Используется для массовых операций;'
--[ ELSE else_result_expression ]
END as [Тип блокировки]
,syspr.spid, syspr.dbid, syspr.open _tran, syspr.status, syspr.hostprocess, syspr.loginame, syspr.hostname
From
#LOCK_01_01
inner join master.dbo.sysprocesses as syspr
on syspr.spid = #LOCK_01_01.spid and syspr.dbid = #LOCK_01_01.dbid
where
#LOCK_01_01.Type = 'TAB'
and
#LOCK_01_01.dbid = @dbid
/* Чем занят сервер*/
SELECT s.[spid]
,s.[loginame]
,s.[open _tran]
,s.[blocked]
,s.[waittime]
,s.[cpu]
,s.[physical_io]
,s.[memusage]
INTO #sysprocesses
FROM sys.[sysprocesses] s
WAITFOR DELAY '00:00:01'
SELECT txt.[text]
,s.[spid]
,s.[loginame]
,s.[hostname]
,DB_NAME(s.[dbid]) [db_name]
,SUM(s.[waittime] -ts.[waittime]) [waittime]
,SUM(s.[cpu] -ts.[cpu]) [cpu]
,SUM(s.[physical_io] -ts.[physical_io]) [physical_io]
,s.[program_name]
FROM sys.[sysprocesses] s
JOIN #sysprocesses ts
ON s.[spid] = ts.[spid]
AND s.[loginame] = ts.[loginame]
OUTER APPLY sys.[dm_exec_sql_text](s.[sql_handle]) AS txt
WHERE s.[cpu] -ts.[cpu]
+ s.[physical_io] -ts.[physical_io]
> 500
OR (s.[waittime] -ts.[waittime]) > 3000
GROUP BY
txt.[text]
,s.[spid]
,s.[loginame]
,s.[hostname]
,DB_NAME(s.[dbid])
,s.[program_name]
ORDER BY
[physical_io] DESC
DROP TABLE #sysprocesses
Категория:
Администрирование Универсальный парсер RSS для 1С На одном проекте - клиент попросил отображать в программе данные, которые выдаю специализированные сайта в формате RSS - Что делать !?
Писать парсер rss для 1С
Первым делом, взглянув на ссылки, подумал что - обычный XML, сейчас его разложу и быстренько загружу в базу, но:
Выяснилось что сайты имеют разные форматы ввода RSS и главное они не валидные(
таким образом, написав небольшой код, который получает ссылку, далее XMLФайл.Прочитать() на одном сайте проходил на ура (этот пример я описывал в статье: Чтение данных с сайта в формате XML и загрузка в 1С ), а вот второй сайт, и третий тоже, при попытке прочитать() выдавали:
{ОбщийМодуль.РегЗадания.Модуль(79)}: Ошибка при вызове метода контекста (Прочитать)
Пока XMLФайл.Прочитать() Цикл
по причине:
Ошибка разбора XML: - [1,1]
Фатальная ошибка:
Extra content at the end of the document
SystemId url rss
решил попробовать на rss других известных сайтов - 80% из проверяемых выдавали ошибку
Пришлось написать прямой построчный парсер RSS: Структура конфигурации
ИсточникиRSS - URL на RSS, ДанныеRSS - сюда записываются загруженные данные новостей
Код получился таким(в принципе код универсальный, но возможно что-то придется подпилить):
Код 1C v 8.3
// RSS
Процедура ПрочитатьRSS(ИсточникRSS)
url = ИсточникRSS.UrlRSS;
// Получим Сервер
Если Найти(url,".ru")>0 Тогда urlСервер = Лев(url,Найти(url,".ru")+2);
ИначеЕсли Найти(url,".com")>0 Тогда urlСервер = Лев(url,Найти(url,".com")+3);
ИначеЕсли Найти(url,".org")>0 Тогда urlСервер = Лев(url,Найти(url,".org")+3);
ИначеЕсли Найти(url,".info")>0 Тогда urlСервер = Лев(url,Найти(url,".info")+4);
ИначеЕсли Найти(url,".pro")>0 Тогда urlСервер = Лев(url,Найти(url,".pro")+3);
КонецЕсли;
//Определим тип соединения
Если Лев(url,5)="https" Тогда
//ssl = Новый ЗащищенноеСоединениеOpen SSL(Новый СертификатКлиентаWindows(), Новый СертификатыУдостоверяющихЦентровWindows());
ssl = Новый ЗащищенноеСоединениеOpen SSL( неопределено, неопределено );
ТекАдрес = СтрЗаменить(url,urlСервер,""); Сервер = СтрЗаменить(urlСервер,"https://","");
Соединение = Новый HTTPСоединение(Сервер,,,,,
5, // таймаут в секундах
ssl // защищенное HTTPS соединение
);
Иначе //Обычный HTTP
ТекАдрес = СтрЗаменить(url,urlСервер,""); Сервер = СтрЗаменить(urlСервер,"http://","");
Соединение = Новый HTTPСоединение(Сервер);
КонецЕсли;
Заголовки = Новый Соответствие;
Заголовки.Вставить("host", Сервер);
Запрос = Новый HTTPЗапрос(ТекАдрес, Заголовки);
Ответ =Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда // Данные получены, обрабатываем их
Содержимое= Ответ.ПолучитьТелоКакСтроку();
//Преобразуем содержимое
Содержимое = СтрЗаменить(Содержимое,"<br/>","|");
Содержимое = СтрЗаменить(Содержимое,"<![CDATA[",""); Содержимое = СтрЗаменить(Содержимое,"]]>","");
Содержимое = СтрЗаменить(Содержимое,Символы.ПС,""); Содержимое = СтрЗаменить(Содержимое,Символы.ВК,"");
Содержимое = СтрЗаменить(Содержимое,Символы.ВТаб,""); Содержимое = СтрЗаменить(Содержимое,Символы.Таб,"");
Содержимое = СтрЗаменить(Содержимое,"><",">"+Символы.ПС+"<");
RegExp = Новый COMОбъект("VBScript.RegExp"); //Регулярка
RegExp.IgnoreCase = Ложь;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML
//Разберем полученный текст в таблицу
ЭтоЗапись=Ложь;
Для н=1 По СтрЧислоСтрок(Содержимое)Цикл
обрТекст=СтрПолучитьСтроку(Содержимое,н);
Если обрТекст = "<item>" Тогда //Началась запись
ЗаписьСтр = Новый Структура(); ЭтоЗапись=Истина; Продолжить;
ИначеЕсли обрТекст = "</item>" Тогда //Закончилась запись
/////////////// ЗАПИСЬ Закончилась //////////////
/// теперь запишем ее в базу - Справочник ДанныеRSS
// сначала ПОИСК ДУБЛЕЙ - вдруг уже загружен
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеRSS.Ссылка
|ИЗ
| Справочник.ДанныеRSS КАК ДанныеRSS
|ГДЕ
| ДанныеRSS.ИсточникRSS =ИсточникRSS
| И ДанныеRSS.link ПОДОБНОlink";
Запрос.УстановитьПараметр("link", "%"+ЗаписьСтр.link+"%");
Запрос.УстановитьПараметр("ИсточникRSS", ИсточникRSS);
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Если РезультатЗапроса.Следующий() Тогда
// Такая запись уже есть, пока ничего не делаем
Иначе
//СОЗДАЕМ Новый
НовЭлем = Справочники.ДанныеRSS.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(НовЭлем,ЗаписьСтр);
НовЭлем.ИсточникRSS = ИсточникRSS;
НовЭлем.Записать();
КонецЕсли;
/////////////////////// *** /////////////////////
ЭтоЗапись=Ложь; Продолжить;
КонецЕсли; //Данные записи
Если ЭтоЗапись Тогда
Если Найти(обрТекст,"title>")>0 и Найти(обрТекст,"/title>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"title",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
ЗаписьСтр.Вставить("Наименование",СокрЛП(обрТекст));
КонецЕсли;
Если Найти(обрТекст,"link>")>0 и Найти(обрТекст,"/link>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"link",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
ЗаписьСтр.Вставить("link",СокрЛП(обрТекст));
КонецЕсли;
Если Найти(обрТекст,"description>")>0 и Найти(обрТекст,"/description>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"description",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
обрТекст=RegExp.Replace(обрТекст, ""); //Удалим все теги
ЗаписьСтр.Вставить("desc",СокрЛП(обрТекст));
КонецЕсли;
Если Найти(обрТекст,"pubDate>")>0 и Найти(обрТекст,"/pubDate>")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"pubDate",""); обрТекст = СтрЗаменить(обрТекст,"<>",""); обрТекст = СтрЗаменить(обрТекст,"</>","");
ЗаписьСтр.Вставить("pubDate",ПреобразоватьRFC822КДате0(СокрЛП(обрТекст)));
КонецЕсли;
Если Найти(обрТекст,"enclosure")>0 Тогда
обрТекст = СтрЗаменить(обрТекст,"""",""); обрТекст = СтрЗаменить(обрТекст,"<enclosure url=","");
обрТекст = СтрЗаменить(обрТекст,"<enclosure url=",""); обрТекст = СтрЗаменить(обрТекст,"type=image/png length=/>","");
ЗаписьСтр.Вставить("img",СокрЛП(обрТекст));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ПроверкаRSS() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИсточникиRSS.Ссылка КАК Ссылка
|ИЗ
| Справочник.ИсточникиRSS КАК ИсточникиRSS
|ГДЕ
| ИсточникиRSS.Использовать
| И ДОБАВИТЬКДАТЕ(ИсточникиRSS.ДатаПоследнегоОбновления, СЕКУНДА, ИсточникиRSS.ПериодОбновленияВСекундах) <ТекДата";
Запрос.УстановитьПараметр("ТекДата", ТекущаяДата());
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ПрочитатьRSS(ВыборкаДетальныеЗаписи.Ссылка);
// Запишем дату последнего обновления
ТекОб = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
ТекОб.ДатаПоследнегоОбновления = ТекущаяДата();
ТекОб.Записать();
КонецЦикла;
КонецПроцедуры
Функция ПреобразоватьRFC822КДате0(ДатаВФорматеRFC822) Экспорт
КопияСтроки = ДатаВФорматеRFC822;
СтруктураДаты = Новый Структура("Год,Месяц,День,Час,Минута,Секунда", "","","","","","");
Месяцы = Новый Структура("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", "01","02","03","04","05","06","07","08","09","10","11","12");
Для каждого КлючИЗначение Из Месяцы Цикл
Позиция = Найти(КопияСтроки,КлючИЗначение.Ключ);
Если Позиция > 0 Тогда
СтруктураДаты.Месяц = КлючИЗначение.Значение;
Прервать;
КонецЕсли;
КонецЦикла;
Состояние = 0;
КопияСтроки = СтрЗаменить(КопияСтроки,", 1 ",", 01 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 2 ",", 02 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 3 ",", 03 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 4 ",", 04 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 5 ",", 05 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 6 ",", 06 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 7 ",", 07 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 8 ",", 08 ");
КопияСтроки = СтрЗаменить(КопияСтроки,", 9 ",", 09 ");
Для ш=0 По СтрДлина(КопияСтроки) Цикл
ТекущийСимвол = Сред(КопияСтроки,ш,1); //ПолучитьСимвол(КопияСтроки, ш);
ТекСимволЦифра= ЭтоЦифра(ТекущийСимвол);
Если ТекСимволЦифра И Состояние = 0 Тогда
СтруктураДаты.День = СтруктураДаты.День + ТекущийСимвол;
Состояние = 1; //начало день
ИначеЕсли ТекСимволЦифра И Состояние = 1 Тогда
СтруктураДаты.День = СтруктураДаты.День + ТекущийСимвол;
Состояние = 2; //ждем год
ИначеЕсли ТекСимволЦифра И Состояние = 2 Тогда
СтруктураДаты.Год = СтруктураДаты.Год + ТекущийСимвол;
Состояние = 3; //продолжаем год
ИначеЕсли ТекСимволЦифра И Состояние = 3 Тогда
СтруктураДаты.Год = СтруктураДаты.Год + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = " " И Состояние = 3 Тогда
Состояние = 4; //дальше час
ИначеЕсли ТекСимволЦифра И Состояние = 4 Тогда
СтруктураДаты.Час = СтруктураДаты.Час + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = ":" И Состояние = 4 Тогда
Состояние = 5; //дальше минута
ИначеЕсли ТекСимволЦифра И Состояние = 5 Тогда
СтруктураДаты.Минута = СтруктураДаты.Минута + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = ":" И Состояние = 5 Тогда
Состояние = 6; //дальше секунда
ИначеЕсли ТекСимволЦифра И Состояние = 6 Тогда
СтруктураДаты.Секунда = СтруктураДаты.Секунда + ТекущийСимвол;
ИначеЕсли ТекущийСимвол = " " И Состояние = 6 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Попытка
Результат = Дата(СтруктураДаты.Год+СтруктураДаты.Месяц+СтруктураДаты.День
+СтруктураДаты.Час+СтруктураДаты.Минута+СтруктураДаты.Секунда);
Исключение
Результат = Неопределено;
КонецПопытки;
Возврат Результат;
КонецФункции
Функция ЭтоЦифра(Символ) Экспорт
Если (КодСимвола(Символ)>=48) И (КодСимвола(Символ)<=57) Тогда Возврат Истина; Иначе Возврат ложь; КонецЕсли;
КонецФункции
Функция ПолучитьСимвол(КопияСтроки, ш)
Возврат Сред(КопияСтроки,ш,1);
КонецФункции
Результат загрузки новостей RSS HelpF.pro
Кстати, как позже выяснилось, здесь уже есть статья с примером через IE и DOM: Получения новостей с RSS-канала сайта buh.ru
Категория:
Работа с Интернет, Почтой (Mail), FTP Как мы писали парсер сайта с ценами для 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 Ошибка СУБД. Превышен максимально допустимый размер внутреннего файла .../1CV8.CD Однажды вылетело: "Ошибка СУБД. Превышен максимально допустимый размер внутреннего файла .../1CV8.CD"
И Все! Данных больше ввести никаких нельзя. Размер Файла 1Cv8.1CD 4,5 ГБ.
Ответ: Про ограничения в файловой версии можно прочитать на последнем ИТС. Действительно - 4 Гб.
Решение: Переходить на MS SQL. В серверном варианте размер базы ограничен возможностями MS SQL сервера.
Дополнение от Andy1981:
Столкнулся с проблемой только сейчас. До этого постоянно работал на серваках, даже тестовая база была развернута на собственном скуле, который крутился у меня локально :-)
В общем-то, решение тривиально, переход на клиент-серверный вариант, и всех делов. Но! Меня задело за живое. Даже если решение очевидно, нужно сначала обосновать его, а не слепо следовать предложенному варианту. Прежде чем выносить вердикт, относительно того, как нужно поступить, исполнил элементарный скрипт на SQL, получил табличку в виде ИмяТаблицыБД|РазмерТаблицы. Прекрасно, но это позволит лишь определить, в каком классе объектов метаданных проблема. Далее, используя Enterprise Integrator получил имя справочника (в моем случае), имеющего проблемный размер. Далее дело за малым - всего-то и делов - определиться, каким образом можно оптимизировать хранение данных? В моем случае ответ оказался практически очевиден. Оптимизировать можно и нужно, и использование сервера БД нецелесообразно. Вполне возможно, что таблица распухает вполне обоснованно, тогда переход на SQL (например), является неизбежным.
Скрипт для вычисления объемов таблиц БД:
Код SQL USE MyInfoBase --Имя БД
DECLARE @tbl TABLE (
name nvarchar(128),
[rows] char(11),
reserved varchar(18),
data varchar(18),
index_size varchar(18),
unused varchar(18)
)
DECLARE @name sysname
DECLARE CUR CURSOR FOR SELECT name FROM sys.tables
OPEN CUR
FETCH NEXT FROM CUR INTO @name
WHILE @@FETCH_STATUS = 0 BEGIN
INSERT @tbl EXEC sp_spaceused @name
FETCH NEXT FROM CUR INTO @name
END
CLOSE CUR
DEALLOCATE CUR
SELECT
name,
[rows],
reserved,
data,
index_size,
unused,
reserved_kb
FROM
(SELECT
name,
[rows],
reserved,
data,
index_size,
unused,
CONVERT(bigint, REPLACE(reserved, ' KB', '')) AS reserved_kb
FROM @tbl
) Q
ORDER BY
reserved_kb DESC
COMPUTE SUM(reserved_kb)
Категория:
Системные Ошибки Загрузка данных в 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С 8.2 Начиная с платформы 8.2.14 в 1С появилась коллекция "Внешние источники данных ". Использование объектов этой коллекции позволяет работать с внешними данными через ODBC. Стандартные механизмы платформы позволяют просматривать данные и использовать их в запросах. Тем не менее, на примере взаимодействия с SQL покажу возможность работы с внешними источниками на прямое добавление/изменение данных SQL из 1С.
Создадим для начала через консоль сервера SQL базу "test" с таблицей "assortment", строковые поля id, name, price. Сделаем ключевым поле id и внесем пару строк в таблицу. Потом создадим пустую базу 1С, в конфигураторе добавим внешний источник данных "ВнешнийSQL". На вкладке "Данные" добавим нашу таблицу. Можно ввести строку соединения, либо воспользоваться конструктором строки. В моей строке указаны явно учетная запись суперадминистратора (sa) и пароль к ней. Поскольку это сервер для тестов, вопросом безопасности можно пренебречь. Для реальной базы такого делать не стоит, либо можно завести отдельного пользователя с правами чтения/записи только на эту базу и хранить его данные.
После подключения находим в списке таблиц нашу, выбираем необходимые поля, в нашем случае все.
После добавляем формы для объекта и списка.
Если запустить нашу конфигурацию сейчас, то элементы формы списка будут открываться только на просмотр.
Теперь начинаем вносить изменения в формы, начнем с формы объекта. В свойствах реквизита "Объект" убираем галку "Сохраняемые данные", после этого реквизиты формы будут доступны для редактирования. Так же добавляем команду "ЗаписатьДанные" и прописываем код сохранения данных.
Код 1C v 8.3 &НаСервере
Процедура ЗаписатьСервер()
пСеанс = ВнешниеИсточникиДанных.ВнешнийSQL.ПолучитьОбщиеПараметрыСоединения();
Если НЕ пСеанс.СУБД = "MSSQLServer" Тогда
Возврат;
КонецЕсли;
ЗапросSQL = ?(Объект.Ссылка.Пустая(), ПолучитьЗапросДобавления(), ПолучитьЗапросОбновления());
Connection = Новый COMОбъект("ADODB.Connection");
Command = Новый COMОбъект("ADODB.Command");
RecordSet = Новый COMОбъект("ADODB.RecordSet");
//учетка и пароль уже в строке подключения
//иначе их необходимо добавить в строку
Попытка
Connection.Open (СокрЛП(пСеанс.СтрокаСоединения));
Command.ActiveConnection = Connection;
Command.CommandText = ЗапросSQL;
RecordSet = Command.Execute();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры // ЗаписатьСервер()
&НаСервере
Функция ПолучитьЗапросОбновления()
мДанные = Объект.Ссылка.Метаданные();
СтрокаПоля = "";
СтрокаДанные = "";
ДанныеОбъект = Объект.Ссылка.ПолучитьОбъект();
Для Каждого мПоле Из мДанные.Поля Цикл
Если Объект[мПоле.Имя] = ДанныеОбъект[мПоле.Имя] Тогда
Продолжить;
КонецЕсли;
СтрокаДанные = СтрокаДанные + ?(ПустаяСтрока(СтрокаДанные), " SET ", ", ") + мПоле.Имя + "= '" + Объект[мПоле.Имя] + "'";
КонецЦикла;
//делаем UDPDATE по id, поскольку оно у нас ключевое
ЗапросSQL = "UPDATE " + мДанные.ИмяВИсточникеДанных + СтрокаДанные + "WHERE (id = '" + ДанныеОбъект.id + "')";
Возврат ЗапросSQL;
КонецФункции
&НаСервере
Функция ПолучитьЗапросДобавления()
мДанные = Объект.Ссылка.Метаданные();
СтрокаПоля = "";
СтрокаДанные = "";
Для Каждого мПоле Из мДанные.Поля Цикл
СтрокаПоля = СтрокаПоля + ?(ПустаяСтрока(СтрокаПоля), " (", ", ") + мПоле.Имя;
СтрокаДанные = СтрокаДанные + ?(ПустаяСтрока(СтрокаДанные), " VALUES (", ", ") + "'" + Объект[мПоле.Имя] + "'";
КонецЦикла;
СтрокаПоля = СтрокаПоля + ")";
СтрокаДанные = СтрокаДанные + ")";
ЗапросSQL = "INSERT INTO " + мДанные.ИмяВИсточникеДанных + СтрокаПоля + СтрокаДанные;
Возврат ЗапросSQL;
КонецФункции
&НаКлиенте
Процедура ЗаписатьДанные(Команда)
ЗаписатьСервер();
//делаем оповещение для списка, поскольку он автоматически не обновляется
Оповестить("ОбновитьВнешнийИсточникДанных");
КонецПроцедуры
Теперь в форме списка на панель вешаем команду "Добавить" и добавляем обработку оповещения.
Код 1C v 8.3 &НаКлиенте
Процедура Добавить(Команда)
ОткрытьФорму("ВнешнийИсточникДанных.ВнешнийSQL.Таблица.dbo_assortment.ФормаОбъекта");
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ОбновитьВнешнийИсточникДанных" Тогда
Элементы.Список.Обновить();
КонецЕсли;
КонецПроцедуры
Вот и все, теперь мы можем как добавлять, так и редактировать данные таблицы. При необходимости можно добавить дополнительный контроль ввода, автонумерацию, удаление и прочие механизмы.
Источник
Категория:
Внешние источники данных Как напечатать документ на определенном принтере из сеанса RDP (Терминал) В 1С есть возможность обратиться к принтеру по имени перед печатью, однако при работе через терминал к названию принтера добавляется (перенаправлено N), где N постоянно меняется. Решение следующее:
Код 1C v 8.2 УП
&НаКлиенте
Функция ИмяПринтераRDP(ИмяПринтера)
Shell = Новый COMОбъект("Wscript.Shell");
Task = Shell.Exec("query session");
РезультатЗапроса = Task.StdOut.ReadAll();
РезультатЗапроса = Декодер(РезультатЗапроса, "windows-1251", "cp866");
Task.Terminate();
Shell = Неопределено;
Network = Новый COMОбъект("WScript.Network");
ПользовательОС = Network.UserName();
Network = Неопределено;
НомерСеанса = RegExpGetFirstMatch("rdp-tcp\S+\s+" + ПользовательОС + "\s+(\d+)", РезультатЗапроса);
Возврат ИмяПринтера + " (перенаправлено " + НомерСеанса + ")";
КонецФункции
Функция Декодер(Стр, Вход, Выход)
Stream = Новый COMОбъект("Adodb.Stream");
Stream.Type = 2;
Stream.Mode = 3;
Stream.Charset = Вход;
Stream.Open ();
Stream.WriteText(Стр);
Stream.Position = 0;
Stream.Charset = Выход;
Результат = Stream.ReadText(-1);
Stream.Close();
Возврат Результат;
КонецФункции
Функция RegExpGetFirstMatch(Маска, Строка, МногострочныйРежим = Истина, ГлобальныйПоиск = Истина, БезУчетаРегистра = Истина)
RegExp = Новый COMОбъект("VBScript.RegExp");
// Параметры
RegExp.Multiline = МногострочныйРежим;
RegExp.Global = ГлобальныйПоиск;
RegExp.IgnoreCase = БезУчетаРегистра;
RegExp.Pattern = Маска;
Matches = RegExp.Execute(Строка);
Если Matches.Count = 1 тогда
Возврат Matches.Item(0).SubMatches.Item(0);
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Категория:
Полезные, Универсальные Функции Работа с бинарными файлами, Двоичные данные и кодировка Base64 Считать данные из двоичного файла можно при помощи функции ДвоичныеДанные(ИмяФайла). Например:
Код 1C v 8.2 УП ДД = ДвоичныеДанные(ИмяФайла);
или через ADODB.Stream
Код 1C v 8.х Процедура Пример(ИмяФайла)
// Перечисления из библиотеки ADO
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);
StreamIn = Новый COMОбъект("ADODB.Stream"); //Для создания этого объекта требуется MDAC 2.5 и выше
StreamIn.Type = StreamTypeEnum.adTypeBinary;
StreamIn.Open (); //По умолчанию открывается на чтение
StreamIn.LoadFromFile(ИмяФайла); //Очевидно, что для больших файлов так поступать нехорошо.
Data = StreamIn.Read(); //у переменной Data тип COMSafeArray, это массив байтов
StreamIn.Close(); //Больше нам этот поток не нужен - закрываем.
//Конечно, манипуляция в памяти приемлима только для небольших файлов!
СодержимоеМассив = Data.Выгрузить();
//...
//...
//тут можно по-всякому поиздеваться над массивом
//...
//...
//Запихиваем массив 1С в COMSafeArray. VT_UI1 - обозначение однобайтного беззнакового целого.
Data = Новый COMSafeArray(СодержимоеМассив, "VT_UI1", СодержимоеМассив.Количество());
StreamOut = Новый COMОбъект("ADODB.Stream");
StreamOut.Type = StreamTypeEnum.adTypeBinary;
StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись.
StreamOut.Open (); //Открыли на чтение и запись
StreamOut.Write(Data);
StreamOut.SaveToFile(ИмяФайла, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
StreamOut.Close();
КонецПроцедуры
Двоичные данные и кодировка Base64 в 1С 8.Х
Считать данные из двоичного файла можно при помощи функции
ДвоичныеДанные(ИмяФайла). Например:
Код 1C v 8.2 УП ДД = ДвоичныеДанные(ИмяФайла);
Здесть ДД - специальный объект, который называется "двоичные данные".
В языке 1С есть функция, которая преобразует двоичные данные в строку
Base64Строка(ДвоичныеДанные). Например:
Код 1C v 8.2 УП Строка64 = Base64Строка(ДвоичныеДанные);
Здесть Строка64 - обычная строка, с которой можно делать все, что угодно.
В конце статьи приведена функция
Преобразовать64(Строка64 = неопределено, Массив64 = неопределено) , которая преобразовывает строку в массив байтов, и обратно.
Для того, чтобы получить массив байтов из строки, вызываем ее так:
Код 1C v 8.2 УП Массив64 = Преобразовать64(Строка64 , );
Для обратного преобразования вызываем так:
Код 1C v 8.2 УП Строка64 = Преобразовать64( , Массив64 );
Преобразовать строку в двоичные данные можно при помощи функции Base64Значение(Строка64)
Все указанные функции, кроме Преобразовать64, являются встроенными функциям платформы.
Далее листинг функции Преобразовать64:
Код 1C v 8.2 УП //Автор: Гобсек
&НаСервере
Функция Преобразовать64(Строка64 = неопределено, Массив64 = неопределено)
Таб64 = Новый ТаблицаЗначений;
Таб64.Колонки.Добавить("Код");
Таб64.Колонки.Добавить("Символ");
Нпп = 0;
Для Код = КодСимвола("A") По КодСимвола("Z") Цикл
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = Символ(Код);
Нпп = Нпп + 1;
КонецЦикла;
Для Код = КодСимвола("a") По КодСимвола("z") Цикл
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = Символ(Код);
Нпп = Нпп + 1;
КонецЦикла;
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = "0";
Нпп = Нпп + 1;
Для Код = 1 По 9 Цикл
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = Формат(Код,"ЧЦ=1; ЧДЦ=0");
Нпп = Нпп + 1;
КонецЦикла;
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = "+";
Нпп = Нпп + 1;
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = "/";
Если Массив64 = неопределено Тогда
Если Строка64 = неопределено Тогда
Сообщить("неверный вызов функции");
Возврат неопределено;
КонецЕсли;
//Уберем переносы строк
Строка64 = СтрЗаменить(Строка64, Символ(10), "");
Строка64 = СтрЗаменить(Строка64, Символ(13), "");
//преобразовываем строку в массив
Если СтрДлина(Строка64) % 4 <> 0 Тогда
Сообщить("длина строки на входе должна быть кратна 4");
Сообщить(СтрДлина(Строка64));
Возврат неопределено;
КонецЕсли;
Кол4 = Цел(СтрДлина(Строка64) / 4);
РазмерМ = Кол4 * 3;
Если Прав(Строка64, 2) = "==" Тогда
РазмерМ = РазмерМ - 2;
ИначеЕсли Прав(Строка64, 1) = "=" Тогда
РазмерМ = РазмерМ - 1;
КонецЕсли;
Массив64 = Новый Массив(РазмерМ);
Для А = 1 По Кол4 Цикл
Число3 = 0;
Для Б = 1 По 4 Цикл
Буква1 = Сред(Строка64, (А-1)*4 + Б, 1);
Если Буква1 = "=" Тогда
Код4 = 0;
Иначе
стрН = Таб64.Найти(Буква1, "Символ");
Если стрН = Неопределено Тогда
Сообщить("ошибка при поиске "+ КодСимвола(Буква1));
Иначе
Код4 = стрН.Код;
КонецЕсли;
КонецЕсли;
Число3 = Число3 * 64 + Код4;
КонецЦикла;
Ост = Число3 % 256;
Индекс = (А-1)*3 + 2;
Если Индекс <= РазмерМ - 1 Тогда
Массив64[Индекс] = Ост;
КонецЕсли;
Число3 = (Число3 - Ост) / 256;
Ост = Число3 % 256;
Индекс = (А-1)*3 + 1;
Если Индекс <= РазмерМ - 1 Тогда
Массив64[Индекс] = Ост;
КонецЕсли;
Число3 = (Число3 - Ост) / 256;
Ост = Число3 % 256;
Массив64[(А-1)*3 + 0] = Ост;
КонецЦикла;
Возврат Массив64;
Иначе //Преобразовываем массив в строку
Строка64 = "";
Кол3 = Цел(Массив64.Количество() / 3);
Если Массив64.Количество() % 3 <> 0 Тогда
Кол3 = Кол3 + 1;
КонецЕсли;
Для А = 1 По Кол3 Цикл
Число3 = Массив64[(А-1)*3];
Если (А-1)*3+1 <= Массив64.ВГраница() Тогда
Код3 = Массив64[(А-1)*3+1];
Иначе
Код3 = 0;
КонецЕсли;
Число3 = Число3*256 + Код3;
Если (А-1)*3+2 <= Массив64.ВГраница() Тогда
Код3 = Массив64[(А-1)*3+2];
Иначе
Код3 = 0;
КонецЕсли;
Число3 = Число3*256 + Код3;
Ост4 = Число3 % 64;
Число3 = (Число3 - Ост4) / 64;
Ост3 = Число3 % 64;
Число3 = (Число3 - Ост3) / 64;
Ост2 = Число3 % 64;
Число3 = (Число3 - Ост2) / 64;
Ост1 = Число3 % 64;
Число3 = (Число3 - Ост1) / 64;
стрН = Таб64.Найти(Ост1, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
стрН = Таб64.Найти(Ост2, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
стрН = Таб64.Найти(Ост3, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
стрН = Таб64.Найти(Ост4, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
КонецЦикла;
//Если количество символов не делится на 3, то на конце должны быть
//знаки "="
Если Массив64.Количество() % 3 = 1 Тогда
Строка64 = Лев(Строка64, СтрДлина(Строка64)-2)+ "==";
ИначеЕсли Массив64.Количество() % 3 = 2 Тогда
Строка64 = Лев(Строка64, СтрДлина(Строка64)-1)+ "=";
КонецЕсли;
Возврат Строка64;
КонецЕсли;
КонецФункции
Категория:
OLE, ActiveX Как зашифровать строку SHA512 ? Код 1C v 8.х //при использовании кода заменить [ на < и ] на >
Функция ЗашифроватьSHA512(Строка, СекретныйКлюч)
Текст = Новый COMОбъект("System.Text.UTF8Encoding");
Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA512");
Криптография.Key = Текст.GetBytes_4(СекретныйКлюч);
ХешБайт = Криптография.ComputeHash_2(Текст.GetBytes_4(Строка)).Выгрузить();
HTML = Новый COMОбъект("htmlfile");
HTML.Open ("text/html");
HTML.Write("[script] ПреобразоватьСтроку = function(x,y){return x.toString(y?y:16)} [/ script]");
ЯваСкрипт = HTML.documentElement.document.Script;
Хеш = "";
Для Каждого Байт Из ХешБайт Цикл
Символ = ЯваСкрипт.ПреобразоватьСтроку(Байт);
Хеш = Хеш + ?(СтрДлина(Символ) = 2, Символ, "0"+Символ);
КонецЦикла;
Возврат Хеш;
КонецФункции
Категория:
COM-объекты, WMI, WSH Управляем 1С со стороны используя web-сервис Передача команд 1С на выполнение через ссылки в письме.
web-сервисы помогают интегрировать 1С с различными программами, делая её более гибкой. Статей в интеренете достаточно можно, но в основном там описывается выгрузка из 1С, обмен между двумя 1С или 1С и каким-то мощным программным продуктом написанным на C или других языках.
Для меня же была поставлена задача возможности управление 1С через браузер. Как пример: обрабатывать завершение задачи БП в 1С по ссылке в письме (примерно такого типа http://site.ru/?user=000000001&bp=000000555, т.е. отсюда видно, что пользователь 000000001 хочет закрыть задачу 000000555), т.е. пользователь со своего смартфона не имеющего доступа к 1С как таковому, должен получить возможность управлять ею извне. Собственно, более сложной задачей можно поставить написание собственных web-форм, более легких и компактных, с произвольным дизайном для управления 1С.
Задача с точки зрения написания кода 1С очень легкая. Основная сложность заключалась в освоении HTML и JavaScript для управления извне. Начальные знаний по этому вопросу я подчерпнул из статьи Примеры пользования web сервисов 1С из браузера.
Настройка 1С
Для возможности использовать 1С в вебе необходимо:
1. Установить модуль расширения веб-сервера;
2. Настроить Windows: доустановить компоненты IIS и настроить проверку подлинности. Всё это можно прочитать в статье
Настройка веб-клиента 1С:Предприятие 8.2 под Windows 7 x64 и IIS.
Программирование 1С
Теперь можно приступить к конфигурированию.
1. Создадим Web-сервис Input:
1.1. Input имеет операцию InputData которая принимает два параметра: User и Command, и возвращает параметр типа "boolean (http://www.w3.org/2001/XMLSchema)". Текст функции InputData:
Код 1C v 8.х Функция InputData(User, Command)
обДанные = Справочники.Данные.СоздатьЭлемент();
обДанные.Наименование = User + ":" + Command;
обДанные.Записать();
Возврат Истина;
КонецФункции
1.2. Устанавливаем для Input URI пространства имен = "http://infostart.ru". Здесь может быть любое уникальное имя, обычно это ссылка на сайт.
1.3. Устанавливаем для Input имя файла публикации = "input.1cws". Это имя web-сервиса к которому будем устанавливать соединение.
2. Для наглядности примера создадим справочник Данные, все параметры оставим по умолчанию.
3. Публикуем нашу конфигурацию и web-сервис: Администрирование -> Публикация на веб сервере...
На этом конфигурирование заканчивается, всё остальное сделает за нас 1С.
Разработка HTML страницы
Эта часть далась для меня тяжело, т.к. я ещё только делаю первые шаги в этой теме. Буду рад замачаниям и советам. А так, я постараюсь объяснить всё на пальцах тем, кто как и я знаком по большей части с 1С.
После установки ISS (я уже давал ссылку в начале статьи) на диске C появится каталог C:\inetpub\wwwroot, в этом каталоге располагается сайт. Для локальной машины (на которой установили ISS) он виден так http://localhost/, ну а для пользователей извне, как-то так http://infostart.ru (по правде там немного сложнее, но не суть, мы сейчас не про это). Заглавная страница сайта будет грузиться из файла index.htm каталога C:\inetpub\wwwroot
Исходники файлов можно скачать здесь:
Скачивать файлы может только зарегистрированный пользователь!
Код файла index.htm попытаюсь объяснить как могу, т.к. сам некоторые моменты не понимаю:
Код [html xmlns="http://www.w3.org/1999/xhtml"] // Неважно. Используется в XHTML для объявления пространства имен.
[head] // Предназначен для хранения других элементов, цель которых — помочь браузеру в работе с данными.
[meta http-equiv="Content-Type" content="text/html; charset=utf-8" /] // Неважно. Мета-теги используются для указания описания.
[title]Тест веб сервиса 1С[/title] // Неважно. Определяет заголовок документа, то что видит пользователь как текст вкладки.
[script type="text/javascript" src="../js/connect1c.js"] [/script] // Важно. Подключение JavaScript библиотек. В моём случае это мой модуль соединения с 1С.
[script type="text/javascript" src="../js/parameters.js"] [/script] // Важно. А это модуль обработки параметров строки браузера.
[/head]
[body] // Предназначен для хранения содержания веб-страницы (контента), отображаемого в окне браузера.
[p id="response1C"][/p] // Важно. Метка response1C, куда вернёться ответ запроса 1С.
[/body]
[script type="text/javascript"] // Важно. Начало основного скрипта, который выдёргивает из строки браузера всё что идёт дальше знака вопроса,
а дальше парсит по определенному алгоритму. В нашем случае будут искаться ключевые слова "user=" и "command=".
user = GetParameter("user"); // Важно. Находим значение user. Сам метод GetParameter находится в библиотеке parameters.js, о которой поговорим чуть позже.
command = GetParameter("command"); // Важно. Находим значение command.
Inquiry1C(user, command); // Важно. Запрос к 1С с найденными параметрами. Сам метод Inquiry1C находится в библиотеке connect1c.js
[/script]
[/html]
Заменил < на [, а > - ], замените перед использованием обратно.
Рассмотрим библиотеку parameters.js, которая находится в папке C:\inetpub\wwwroot\js
f
Код unction GetParameter(pName) { // Сам метод я нашёл на просторах интернета.
search = window.location.search; // window.location - это по сути URL, метод search этого объекта возвращает часть адреса после символа "?", включая символ "?".
begin = search.indexOf(pName) + pName.length + 1; // Вычисляем позицию начала строки значения параметра для вырезания. +1 - в нашем случае это знак "=".
Итого, для search = "?user=007" мы найдём позицию начала равной 6 (нумерация с нуля).
end = search.indexOf('&', begin); // Находим позицию конца выражения. В нашем случае, разделение параметров осуществляется знаком "&", и если мы его не найдём,
то позицией конца будет последний символ строки search (смотри дальше код).
if (end == -1) {
end = search.length;
};
return unescape(search.substring(begin, end)); // Метод unescape возвращает строку, содержащую данные типа charString (не знаю зачем это надо,
но видимо такое приведение типа здесь необходимо). Ну а метод substring - извлекает подстроку из строки.
}
Теперь рассмотрим библиотеку connect1c.js, которая также находится в папке C:\inetpub\wwwroot\js
function Inquiry1C(pUser, pCommand) { // Основной метод этой библиотеки. Запрос к 1С.
XMLHTTP = CreateRequestObject(); // Создание XML HTTP запроса. Сам метод я узнал из википедии.
XMLHTTP.
open ('POST', '../TestWeb/ws/Input.1cws', true, "Admin", "1"); // Создаём соединение типа POST, где второй параметр - адрес; параметр true - значит асинхронное,
то есть браузер не будет ждать ответа сервера, а продолжит работу; далее пользователь и пароль с правами на операцию InputData (этот тот метод, который мы написали в 1С),
саму операцию можно выполнять в привилегированном режиме, чтобы не мучиться с правами для пользователя Admin.
XMLHTTP.onreadystatechange = function() {WhenAnswering1C(XMLHTTP)}; // Когда 1С отработает, автоматически сработает метод WhenAnswering (о нём чуть ниже по тексту этой библиотеки).
XMLHTTP.send(''
+ ' '
+ ' '
+ ''
+ pUser + ' '
+ ''
+ pCommand + ' '
+ ' '); // Отправка XML запроса, где описывается метод к исполнению в 1С, с переданными параметрами из нашей строки URL.
// Строку запроса можно раскурить минут за 5
}
function CreateRequestObject() { // Чудо метод из википедии "Пример использования". По сути, ничего сложного.
if (typeof XMLHttpRequest === 'undefined') {
XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
catch(e) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
}
return new XMLHttpRequest();
}
function WhenAnswering1C(pXMLHTTP) { // Метод, который срабатывает после обработки запроса 1С.
status = StausRequest(pXMLHTTP); // Вычисляется статус для отправки сообщения пользователю (о нём чуть ниже).
document.getElementById("response1C").appendChild(document.createTextNode(status)); // Вывод на экран в помеченную область response1C (о ней я писал в основном файле).
Метод getElementById возвращает ссылку на узел документа.
Метод appendChild добавляет нод в конце списка дочерных нодов элемента, т.е. встраивает в нашу область нужный нам текст.
}
function StausRequest(pXMLHTTP) // Определение статуса.
{
status = "";
if (pXMLHTTP.readyState == 4) { // Опять же, читая википедию можно понять, readyState - это текущее состояние объекта (0 — не инициализирован, 1 — открыт,
2 — отправка данных, 3 — получение данных и 4 — данные загружены).
if (pXMLHTTP.status != 200) { // status - HTTP-статус в виде числа (404 — «Not Found», 200 — «OK» и т. д.)
status = "Запрос завершился неудачно. Ответ сервера: " + pXMLHTTP.responseText; // responseText -текст ответа на запрос.
Если состояние не 3 или 4, возвращает пустую строку.
}
else {
if (RequestSuccessful(pXMLHTTP)) { // Проверка ответа от 1С (о нём чуть ниже).
status = "Запрос отработан.";
}
else {
status = "Запрос был отклонён.";
};
};
};
return status;
}
function RequestSuccessful(pXMLHTTP) { // Проверка ответа от 1С. Здесь мы получим возвращаемое от 1С значение (в нашем случае 1С может вернуть тип булево).
DOM = pXMLHTTP.responseXML.getElementsByTagName("return")[0]; // responseXML - Текст ответа на запрос в виде XML, который затем может быть обработан посредством DOM.
Если состояние не 4, возвращает null.
response = DOM.childNodes[0].data; // Достаём данные из ответа.
return response == "true"; // Если правда, то правда
По правде, я не смог преобразовать сроку в булево, поэтому пришлось оставить так.
}
Проверка
Открываем браузер и вводим строку "localhost/?user=007&command=hello world!":
После чего можно открыть 1С и убедиться что создался элемент справочника:
На этом пример ознакомления управления 1С извне можно считать законченным
Автор:
Soloist Категория:
WEB-сервисы, WS-ссылки, XDTO-пакеты Парсер сайта на 1С В этой статье я постараюсь описать процесс парсинга сайтов средствами 1С с примером.
Это статья не является инструкцией к применению, а лишь демонстрирует возможности 1С.
Что мы имеем?
1. Сайт в интернете, на котором располагается список товаров. В моем случае – это интернет магазин салона «Связной»
2. Понимание основ сайтостроения… хотя бы знание HTML тегов
3. Умение кодить в 1С 8
Для начала парсинга стоит определиться с тем что мы хотим спарсить и какая у нас будет иерархия. В моем случае это категория сотовых телефонов. Верхний уровень иерархии будет производители. Почему именно так? Потомы что я так захотел. Вы же вправе использовать любую иерархию.
Далее нам будут интересны такие поля как: Наименование, Цена, Картинка и Описание... ну и пожалую захватим операционную систему, чтобы пример получился более наглядным.
1. Создаем внешнюю обработку. Те, кто не знают как это сделать - дальше могут не читать
2. Создаем форму обработки с командной панелью снизу и сверху (они могут быть полезными)
3. Размещаем на ней Панель и обзываем первую страницу "СамСайт"
4. Кладем на страницу "СамСайт" ПолеHTMLДокумента и обзываем его к примеру "Сайт"
5. Переименовываем кнопку "Выполнить", которая находится на нижней панели в "Загрузить сайт"
6. Описываем процедуру нажатия на эту кнопку так:
Код 1C v 8.х ЭлементыФормы.Сайт.Перейти("http://www.svyaznoy.ru/catalog/phone/224"); //Категория с мобильными телефонами
7. Проверяем работу нашей обработки. У меня появился сайт связного. А у Вас?
Дальше сложнее. Все еще хочешь парсить сайты? Тогда читай:
Сам парсинг сайта заключается в обходе всех элементов загруженной страницы, выдергивания необходимой информации и запихивания их в табличную часть. Для этого:
1. Создадим табличную часть "Производители" с реквизитами "Отметка" (Булево), "Наименование" (Строка 100) и "Ссылка" (Строка 300).
2. Добавляем еще одну страницу на панели и обзываем ее "Производители"
3. Размещаем на этой странице одноименную табличную часть
4. Добавляем на нижней панели кнопку "Заполнить производителей" с кодом:
Код 1C v 8.х Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
Если Стр.tagName = "H1" и Стр.innerText = "Производители" Тогда
Для Каждого опСтр из Стр.nextSibling.children Цикл
новСтр = Производители.Добавить();
новСтр.Наименование = опСтр.innerText;
новСтр.Ссылка = опСтр.firstChild.href;
КонецЦикла;
Возврат;
КонецЕсли;
КонецЦикла;
Здесь напрашиваются небольшие пояснения:
tagName - имя HTML тега в HTML документе
nextSubling - следующий элемент HTML документа от текущего
children - список дочерних элементов
firstChild - первый дочерний элемент от текущего
5. Проверям. При проверке важно, находиться на странице "СамСайт", чтобы заполнять производителей
Производители заполнены. Теперь к самим телефонам
1. Создаем табличную часть "Товары" с реквизитами "Производитель" (Строка 100), "Наименование" (Строка 100), "Цена" (Число 10,2), "Картинка" (Строка 300), "Описание" (Строка Неограниченная), "ОС" (строка 100), "Ссылка" (Строка,300)
2. Добавляем еще одну страницу на панели и обзываем ее "Товары"
3. Размещаем на этой странице одноименную табличную часть
4. Добавляем на нижней панели кнопку "Заполнить товары" с кодом:
Код 1C v 8.х Для Каждого Стр из Производители Цикл
//Если отметку сняли - то не трогаем этого производителя
Если Не Стр.Отметка Тогда
Продолжить;
КонецЕсли;
Форма = ПолучитьФорму("ФормаТоваров");
Форма.ЭлементыФормы.Сайт.Перейти(Стр.Ссылка);
Форма.ТекущийПроизводитель = Стр;
Форма.ОткрытьМодально();
КонецЦикла;
5. Создаем форму обработки "ФормаТоваров"
6. Кладем на "ФормаТоваров" ПолеHTMLДокумента и называем его "Сайт"
7. На событие ДкументСформирован у ПоляHTMLДокумента пишем код:
Код 1C v 8.х Если ЭлементыФормы.Сайт.Документ.body.all.length>1 Тогда
ГрузимТовары();
КонецЕсли;
8. Создаем переменную в модуле формы
перем ТекущийПроизводитель Экспорт;
9. Создаем процедуру ГрузимТовары():
Код 1C v 8.х Процедура ГрузимТовары()
Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
Если Стр.className = "ct_desc cleared" Тогда
новСтр = Товары.Добавить();
Для Каждого опСтр из Стр.children Цикл
Если опСтр.className = "pic_and_comp" Тогда
новСтр.Картинка = СтрЗаменить(Сред(опСтр.firstChild.style.backgroundImage,5),")","")
КонецЕсли;
Если опСтр.className = "name" Тогда
новСтр.Наименование = опСтр.innerText;
новСтр.Ссылка = опСтр.firstChild.href;
КонецЕсли;
Если опСтр.className = "price" Тогда
новСтр.Цена = Число(СтрЗаменить(СтрЗаменить(опСтр.innerText,"-","")," ",""));
КонецЕсли;
Если опСтр.className = "desc" Тогда
новСтр.Описание = опСтр.innerText;//опСтр.innerHTML - если нужно вместе с тегами
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Закрыть();
КонецПроцедуры
10. Проверям. Все работает.
Дело осталось за "операционной системой" и еще надо загрузить картинки. Давайте по порядку. Чтобы получить "ОС" нам надо открыть этот товар и считать "ОС" оттуда. Для этого делаем следующее:
1. Добавляем на нижней панели кнопку "Доп Инфо" с кодом:
Код 1C v 8.х Для Каждого Стр из Товары Цикл
Форма = ПолучитьФорму("ФормаДопИнфо");
Форма.ЭлементыФормы.Сайт.Перейти(Стр.Ссылка);
Форма.ТекущийТовар = Стр;
Форма.ОткрытьМодально();
КонецЦикла;
2. Создаем форму обработки "ФормаДопИнфо"
3. Кладем на "ФормаДопИнфо" ПолеHTMLДокумента и называем его "Сайт"
4. На событие ДкументСформирован у ПоляHTMLДокумента пишем код:
Код 1C v 8.х Если ЭлементыФормы.Сайт.Документ.body.all.length>1 Тогда
ГрузимДопИнфо();
КонецЕсли;
5. Создаем переменную в модуле формы
перем ТекущийТовар Экспорт;
6. Создаем процедуру ГрузимДопИнфо():
Код 1C v 8.х Процедура ГрузимДопИнфо();
Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
Если Стр.className = "card_spec" Тогда
Для Каждого опСтр из Стр.children Цикл
Если Найти(опСтр.innerText,"Операционная система:") Тогда
ТекущийТовар.ОС = СокрЛП(СтрЗаменить(опСтр.innerText,"Операционная система:",""));
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Закрыть();
КонецПроцедуры
7. Проверяем и переходим к последнему пункту
Заметили как похожи две последние инструкции? То-то же. Стремился к универсальности. Ну и наконец последний этап - Сохраним все изображения к примеру на диск "С" в папку "связной". Поехали
1. Добавляем на нижней панели кнопку "Сохранить Картинки" с кодом:
Код 1C v 8.х Для Каждого Стр из Товары Цикл
путьСамФайл = Лев(Стр.Картинка,Найти(Стр.Картинка,".jpg/") + 3);
самФайл = СтрЗаменить(СтрЗаменить(ПутьСамФайл,"http://static.svyaznoy.ru/upload/iblock/",""),"/","");
Стр.Картинка = СохранитьКартинкуСайта("C:\Svyaznoy",ПутьСамФайл,СамФайл);
КонецЦикла;
2. Добавляем функцию СохранитьКартинкуСайта:
Код 1C v 8.х Функция СохранитьКартинкуСайта(КаталогСохранения,КартинкаНаСайте,КартинкаУНас)
ИмяФайлаКартинки = КаталогСохранения + "\" + КартинкаУНас;
ГетЗапрос = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
ГетЗапрос.SetTimeouts(10000, 10000, 10000, 10000);
БазовыйУРЛ = КартинкаНаСайте;
Хидер1 = "Content-Type";
Хидер2 = "image/jpg"; // Тип рисунка.
ГетЗапрос.Open ("GET", БазовыйУРЛ, False); // Синхронный режим.
ГетЗапрос.setRequestHeader(Хидер1, Хидер2);
ГетЗапрос.Send();
СтатусОтправки = ГетЗапрос.status;
Если СтатусОтправки <> 200 Тогда
Сообщить("Ошибка отправки запроса на: "
+ КартинкаНаСайте);
Возврат "";
КонецЕсли;
Стрим = Новый COMОбъект("ADODB.Stream");
Стрим.Mode = 3;
Стрим.Type = 1;
Стрим.Open ();
Стрим.Write(ГетЗапрос.responseBody);
Стрим.SaveToFile(ИмяФайлаКартинки, 2);
Стрим.Close();
Возврат ИмяФайлаКартинки;
КонецФункции
На этом наша эпопея с парсингом закончена. Это всего лишь пример того, как это можно сделать. Приложив сюда немного своего кода - можно сделать парсер для любого сайта.
Скачивать файлы может только зарегистрированный пользователь!
Имея парсер 1С - я могу спарсить все, кроме этого парсера. Имя два парсера 1С - я могу спарсить все
Автор:
opx Категория:
Работа с Интернет, Почтой (Mail), FTP Отправка sms из 1C через МТС Коммуникатор Есть сервис МТС Коммуникатор - удобный обмен SMS-сообщениями с Вашими сотрудниками, клиентами и партнерами. Так вот через него мы настроили
отправку СМС клиентам компании из 1С :
Код 1C v 8.2 УП Если ПустаяСтрока(ТелефонКлиента) Тогда
Сообщить("Не определен телефон экспедитора загрузки");
Предупреждение("СМС не может быть отправлено");
Иначе
Адресат = ТелефонКлиента;
Адресат = СтрЗаменить(СтрЗаменить(Адресат, "(", ""), ")", "");
Адресат = СтрЗаменить(СтрЗаменить(СтрЗаменить(Адресат, ".", ""), "-", ""), " ", "");
Адресат = СтрЗаменить(Адресат, "+", "");
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Option(2, "Windows-1251");
WinHttp.Open ("POST", "http://mtscommunicator.ru/m2m/m2m_api.asmx/SendMessage", 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");
ПараметрыPOST = "msid=" + Адресат + "&message=" + ПодготовитьСообщение(ТекстСМС) + "&naming=USER&login=NUMERLOGIN&password=PASSWORD";
Ошибка = Ложь;
ИДСообщения = "";
Попытка
WinHttp.Send(ПараметрыPOST);
ИмяФайлаЗапроса = ПолучитьИмяВременногоФайла();
Текст = Новый ЗаписьТекста(ИмяФайлаЗапроса, КодировкаТекста.UTF8);
Текст.ЗаписатьСтроку(WinHttp.ResponseText());
Текст.Закрыть();
Ошибка = (WinHttp.Status <> 200);
Исключение
Ошибка = Истина;
КонецПопытки;
Если НЕ Ошибка Тогда
Попытка
XMLОтвет = Новый ЧтениеXML;
XMLОтвет.ОткрытьФайл(ИмяФайлаЗапроса);
Пока XMLОтвет.Прочитать() Цикл
Если XMLОтвет.ТипУзла = ТипУзлаXML.НачалоЭлемента И (XMLОтвет.Имя = "long") Тогда
XMLОтвет.Прочитать();
ИДСообщения = XMLОтвет.Значение;
Прервать;
КонецЕсли;
КонецЦикла;
Исключение
Ошибка = Истина;
КонецПопытки;
КонецЕсли;
Если Ошибка Тогда
Сообщить("Не удалось отправить СМС. Проверьте настройки подключения");
Предупреждение("СМС не было отправлено");
Иначе
ПоказатьОповещениеПользователя("Отправка СМС",, "СМС-сообщение отправлено ", БиблиотекаКартинок.СМС);
КонецЕсли;
КонецЕсли;
//Преобразование текста сообщения
Функция ПодготовитьСообщение(Сообщение)
ВрСообщение = "";
Для ТекСимвол = 1 По СтрДлина(Сообщение) Цикл
Если КодСимвола(Сред(Сообщение, ТекСимвол, 1)) = 10 Тогда
ВрСообщение = ВрСообщение + " ";
Иначе
ВрСообщение = ВрСообщение + Сред(Сообщение, ТекСимвол, 1);
КонецЕсли;
КонецЦикла;
Сообщение = ВрСообщение;
Сообщение = СтрЗаменить(Сообщение, "%", "%25");
Сообщение = СтрЗаменить(Сообщение, " ", "%20");
Сообщение = СтрЗаменить(Сообщение, "&", "%26");
Сообщение = СтрЗаменить(Сообщение, "#", "%23");
Сообщение = СтрЗаменить(Сообщение, "*", "%2A");
Сообщение = СтрЗаменить(Сообщение, "|", "%7C");
Сообщение = СтрЗаменить(Сообщение, "\", "%5C");
Сообщение = СтрЗаменить(Сообщение, "/", "%2F");
Сообщение = СтрЗаменить(Сообщение, "?", "%3F");
Сообщение = СтрЗаменить(Сообщение, "^", "%5E");
Возврат Сообщение;
КонецФункции
Категория:
COM-объекты, WMI, WSH Добавим документы ODF (Open Office/LibreOffice) в стандартную обработку Загрузки Табличного документа Доброго времени суток!
Обработку ЗагрузкаданныхизТабличногоДокументаконечно должен знать каждый 1С-ник. И сколько бы обработок такого плана не появлялось, эта остается классикой. Даже претензии можно предъявлять если вы в ней что-то не понимаете к самой 1С. Хотя какие претензии, исходный код открыть – изучай, не хочу…
Еще чем мне нравится эта обработка – тем что вы читаете данные из внешнего источника, показываете их с помощью объекта табличное поле и только затем выбираете алгоритм загрузки в 1С. При чем загрузка у Вас происходит в среде 1С без привлечения дополнительных компонентов. Без всяких выпадов в неизвестный объект OLE, полей которые не прочитались в обработке загрузки. Если вы видете данные в табличном поле, то они и будут грузиться по вашему алгоритму.
Но что-то в ней не хватает. Конечно стандарта офисных документов ODF (
Open Document Format и между прочим ГОСТ Р ИСО/МЭК 26300-2010). Как говаривал мой начальник – есть чем себя занять. Из всех внешних загрузок, которые сейчас есть к сожалению самыми распостраненными являются OLE(Com+) технологии. Возможно что-то еще появиться, но пока примемся за них.
Залезаем в код и видим несколько однотипных функуций
Функция мПрочитатьТабличныйДокументИзExcel(ТабличныйДокумент, ИмяФайла, НомерЛистаExcel = 1) Экспорт
Функция мПрочитатьТабличныйДокументИзТекста(ТабличныйДокумент, ИмяФайла, НомерЛистаExcel = 1) Экспорт
Пора добавить свою:
Код 1C v 8.х
// Функция считывает в табличный документ данные из файла в формате ODF Calc(ods)
//
// Параметры:
// ТабличныйДокумент – ТабличныйДокумент, в который необходимо прочитать данные
// ИмяФайла – имя файла в формате ODF, из которого необходимо прочитать данные
// НомерЛистаCalc – номер листа книги Calc, из которого необходимо прочитать данные
//
// Возвращаемое значение:
// Истина, если файл прочитан, Ложь – иначе
//
Функция мПрочитатьТабличныйДокументИзCalc(ТабличныйДокумент, ИмяФайла, НомерЛистаCalc = 1) Экспорт
ВыбФайл = Новый Файл(ИмяФайла);
Если НЕ ВыбФайл.Существует() Тогда
Сообщить(“Файл не существует!”);
Возврат Ложь;
КонецЕсли;
Попытка
ServiceManager = Новый COMОбъект(“com.sun.star.ServiceManager”);
Desktop = ServiceManager.CreateInstance(“com.sun.star.frame.Desktop”);
Desktop.getCurrentFrame().getContainerWindow().setVisible(Ложь); //сделаем невидимым основное окно.
//установим параметры – не показывать таблицу Calc
Параметры = Новый COMSafeArray(“VT_DISPATCH”, 1);
Свойство = ServiceManager.Bridge_GetStruct(“com.sun.star.beans.PropertyValue”);
Свойство.Name = “Hidden”;
Свойство.Value = true;
Параметры.SetValue(0,Свойство);
Document = Desktop.LoadComponentFromURL(“file:///” + ИмяФайла, “_blank”, 0, Параметры);
Состояние(“Обработка файла Office Calc …”);
Листы = Document.getSheets();
Лист = Листы.getByIndex(НомерЛистаCalc-1);
Исключение
Сообщить(“Ошибка загрузки данных. Возможно неверно указан номер листа книги Calc.”);
Возврат ложь;
КонецПопытки;
ТабличныйДокумент.Очистить();
//Определение максимум ячейки с данными…
НульЯчейка = Лист.GetCellbyPosition(0,0);
НульКурсор = Лист.createCursorByRange(НульЯчейка);
НульКурсор.GotoEndOfUsedArea(1);
НульАдрес = НульКурсор.RangeAddress;
ПослСтрока = НульАдрес.EndRow;
ПослКолонка = НульАдрес.EndColumn;
//Для Column = 1 По ПослКолонка + 1 Цикл
// ТабличныйДокумент.Область(“C” + Формат(Column, “ЧГ=”)).ШиринаКолонки = Лист.getColumns.getByIndex(Column-1).Width;
//КонецЦикла;
Для Row = 1 По ПослСтрока + 1 Цикл
Если Лист.getCellByPosition(Column-1,Row-1).getType() = 0 Или Лист.getCellByPosition(Column-1,Row-1).getType() = 1 Тогда ТабличныйДокумент.Область(“R” + Формат(Row, “ЧГ=”) +”C” + Формат(Column, “ЧГ=”)).Текст = Лист.getCellByPosition(Column-1,Row-1).value;
ИначеЕсли Лист.getCellByPosition(Column-1,Row-1).getType() = 2 Тогда ТабличныйДокумент.Область(“R” + Формат(Row, “ЧГ=”) +”C” + Формат(Column, “ЧГ=”)).Текст = Лист.getCellByPosition(Column-1,Row-1).string;
КонецЕсли;
КонецЦикла;
//ServiceManager.quit();
Document.Dispose();
Document = 0;
Параметры = 0;
Desktop = 0;
ServiceManager = 0;
Возврат Истина;
КонецФункции
И добавим в форму выбора файла ods по тексту.
Код 1C v 8.х ДиалогВыбораФайла.Фильтр = “Табличный документ (*.mxl)|*.mxl|Лист Calc (*.ods)|*.ods|Лист Excel (*.xls)|*.xls|Текстовый документ (*.txt)|*.txt|dBase III (*.dbf)|*.dbf|”;
И выбор функции для ods
ИначеЕсли нРег(ФайлНаДиске.Расширение) = “.ods” Тогда
мПрочитатьТабличныйДокументИзCalc(ТабличныйДокумент,ДиалогВыбораФайла.ПолноеИмяФайла);
Вот так лучше.
Сайт
sikuda.ru Категория:
Работа с Microsoft Office и OpenOffice