Вывод результата запроса на форму УП в таблицу значений (аналог СоздатьКолонки() для УП) при разработке на обычных формах было удобно выводить результат запроса используя метод СоздатьКолоки():
Код 1C v 8.х Процедура ПоискНажатие(Элемент)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДокументоОборот.Этап,
| ДокументоОборот.Отдел,
| ДокументоОборот.ФИО,
| ДокументоОборот.ДатаВремя КАК Дата_Время,
| ДокументоОборот.Документы,
| ДокументоОборот.Примечание,
| ДокументоОборот.Доставка
|ИЗ
| РегистрСведений.ДокументоОборот КАК ДокументоОборот
|ГДЕ
| ДокументоОборот.Документы ПОДОБНОДокументы
| И ДокументоОборот.Доставка.Дата МЕЖДУДатаН ИДатаК
|
|УПОРЯДОЧИТЬ ПО
| ДокументоОборот.ДатаВремя";
Запрос.УстановитьПараметр("Документы", "%"+СокрЛП(Строка(СтрокаПоиска))+"%");
Запрос.УстановитьПараметр("ДатаК", КонПериода);
Запрос.УстановитьПараметр("ДатаН", НачПериода);
Рез=Запрос.Выполнить();
НайденДок = рез.Выгрузить();
ЭлементыФормы.НайденДок.СоздатьКолонки();
В управляемом приложении метод СоздатьКолоки() не доступен, ниже представлена процедура, которая отображает на управляемой форме содержимое таблицы значений переданное ей в качестве параметра:
Пример формы:
Код вывода результата запроса на управляемую форму :
Код 1C v 8.2 УП &НаСервере
Процедура СоздатьТаблицуФормы(Знач ИмяПоляТаблицыФормы, Знач ИмяРеквизитаДанныеФормыКоллекция, Знач ТаблицаЗначений)
// Если руками не создали эелемент формы Таблица, то создается программно
Если Элементы.Найти(ИмяПоляТаблицыФормы) = Неопределено Тогда
ЭлементРеквизита = Элементы.Добавить(ИмяПоляТаблицыФормы, Тип("ТаблицаФормы"),);
ЭлементРеквизита.ПутьКДанным = ИмяРеквизитаДанныеФормыКоллекция;
КонецЕсли;
УдаляемыеРеквизиты = Новый Массив;
РеквизитыДляУдаления = ПолучитьРеквизиты(ИмяРеквизитаДанныеФормыКоллекция);
Для Каждого РеквизитУдаления Из РеквизитыДляУдаления Цикл
УдаляемыеРеквизиты.Добавить(ИмяРеквизитаДанныеФормыКоллекция+"."+РеквизитУдаления.Имя);
// Удаляем элементы формы
Элементы.Удалить(Элементы[ИмяПоляТаблицыФормы+РеквизитУдаления.Имя]);
КонецЦикла;
// Добавление реквизитов в таблицу формы
ДобавляемыеРеквизиты = Новый Массив;
Для каждого Колонка Из ТаблицаЗначений.Колонки Цикл
ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, ИмяРеквизитаДанныеФормыКоллекция, Колонка.Заголовок));
КонецЦикла;
ИзменитьРеквизиты(ДобавляемыеРеквизиты,УдаляемыеРеквизиты);
// Добавление элементов форму
Для каждого Колонка Из ТаблицаЗначений.Колонки Цикл
ЭлементРеквизита = Элементы.Добавить(ИмяПоляТаблицыФормы + Колонка.Имя, Тип("ПолеФормы"), Элементы[ИмяПоляТаблицыФормы]);
ЭлементРеквизита.ПутьКДанным = ИмяРеквизитаДанныеФормыКоллекция + "." + Колонка.Имя;
ЭлементРеквизита.Вид = ВидПоляФормы.ПолеВвода;
КонецЦикла;
ЗначениеВРеквизитФормы(ТаблицаЗначений, ИмяРеквизитаДанныеФормыКоллекция);
КонецПроцедуры
&НаСервере
Процедура ВПоискНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслугСерии.Серия КАК Серия,
| РеализацияТоваровУслугСерии.Ссылка КАК Реализация,
| РеализацияТоваровУслугСерии.Ссылка.ЗаказКлиента КАК ЗаказКлиента,
| РеализацияТоваровУслугСерии.Ссылка.Контрагент КАК Контрагент,
| РеализацияТоваровУслугСерии.Ссылка.Договор КАК Договор
|ИЗ
| Документ.РеализацияТоваровУслуг.Серии КАК РеализацияТоваровУслугСерии
|ГДЕ
| РеализацияТоваровУслугСерии.Серия В
| (ВЫБРАТЬ
| СерииНоменклатуры.Ссылка КАК Ссылка
| ИЗ
| Справочник.СерииНоменклатуры КАК СерииНоменклатуры
| ГДЕ
| СерииНоменклатуры.Наименование ПОДОБНОНаименование)
|
|УПОРЯДОЧИТЬ ПО
| Серия
|АВТОУПОРЯДОЧИВАНИЕ";
Запрос.УстановитьПараметр("Наименование", "%"+НомерФН+"%");
РезультатЗапроса = Запрос.Выполнить();
ТаблицаЗапроса = Запрос.Выполнить().Выгрузить();
СоздатьТаблицуФормы("ТЗ","ТЗ",ТаблицаЗапроса);
КонецПроцедуры
&НаКлиенте
Процедура ВПоиск(Команда)
ВПоискНаСервере();
КонецПроцедуры
Категория:
Управляемое приложение, Тонкий клиент Функции сохранения таблицы значений в файл и чтения из файла В данном примере хочу привести несколько универсальных функций по выгрузке таблицы значений в файл и дальнейшего чтения из файла:
П орядок программных действий при выгрузке в файл выглядит так:
Подготавливаем таблицу значений (выгружаем из табличной части, выбираем колонки); Конвертируем таблицу значений в табличный документ; Сохраняем табличный документ в MXL. При загрузке таблицы порядок действий такой:
Читаем из файла табличный документ; Конвертируем табличный документ в таблицу значений; Используем эту таблицу значений в своих целях (загружаем в табличную часть). Соответственно файл для хранения данных таблицы имеет расширение *.mxl.
Основные функции для реализации поставленной задачи следующие:
ПреобразоватьТДвТЗ – Функция преобразования табличного документа в таблицу значений.
ПреобразоватьТЗвТД – Функция обратного преобразования таблицы значений в табличный документ.
ПрочитатьТЗИзMXL – Читает из файла данные, определяет колонки таблицы и преобразует эти данные в таблицу значений.
ЗаписатьТЗВMXL – Преобразует таблицу значений в табличный документ и записывает его в файл.
Код 1C v 8.3 // Преобразовать табличный документ в таблицу значений.
//
// Параметры:
// ТабДок - <ТабличныйДокумент> - Исходный табличный документ;
// СтруктураКолонок - <Структура>, <ТаблицаЗначений> - Структура колонок;
// НачалоСтрока - <Число> - Строка начала области;
// НачалоСтолбец - <Число> - Столбец начала области;
// КонецСтрока - <Число> - Строка конца области;
// КонецСтолбец - <Число> - Столбец конца области.
//
// Возвращаемое значение:
// <ТаблицаЗначений> - Полученная таблица значений.
//
Функция ПреобразоватьТДвТЗ(ТабДок, СтруктураКолонок, Знач НачалоСтрока = Неопределено, Знач НачалоСтолбец = Неопределено, Знач КонецСтрока = Неопределено, Знач КонецСтолбец = Неопределено) Экспорт
// Определение габаритов таблицы
Если НачалоСтрока = Неопределено И НачалоСтолбец = Неопределено Тогда
НачалоСтрока = 1;
НачалоСтолбец = 1;
КонецЕсли;
Если НачалоСтрока = Неопределено Тогда
НачалоСтрока = 1;
Пока НЕ ТабДок.Область(НачалоСтрока, НачалоСтолбец).СодержитЗначение
И НачалоСтрока < ТабДок.ВысотаТаблицы
Цикл
НачалоСтрока = НачалоСтрока + 1;
КонецЦикла;
ИначеЕсли НачалоСтолбец = Неопределено Тогда
НачалоСтолбец = 1;
Пока НЕ ТабДок.Область(НачалоСтрока, НачалоСтолбец).СодержитЗначение
И НачалоСтолбец < ТабДок.ШиринаТаблицы
Цикл
НачалоСтолбец = НачалоСтолбец + 1;
КонецЦикла;
КонецЕсли;
КонецСтрока = ?(КонецСтрока = Неопределено, ТабДок.ВысотаТаблицы, КонецСтрока);
КонецСтолбец = ?(КонецСтолбец = Неопределено, ТабДок.ШиринаТаблицы, КонецСтолбец);
// Преобразование
ЭтоТаблица = (ТипЗнч(СтруктураКолонок) = Тип("ТаблицаЗначений"));
ТабЗначений = ПолучитьТаблицуВывода(СтруктураКолонок);
Для ИндексСтроки = НачалоСтрока По КонецСтрока Цикл
СтрокаТЗ = ТабЗначений.Добавить();
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из СтруктураКолонок Цикл
НаименованиеКолонки = ?(ЭтоТаблица, Колонка.Наименование, Колонка.Ключ);
пИндексКолонки = ?(ЭтоТаблица, Колонка.СтолбецОтчёт, ИндексКолонки);
Если ТабДок.Область(ИндексСтроки, пИндексКолонки).СодержитЗначение Тогда
СтрокаТЗ[НаименованиеКолонки] = ТабДок.Область(ИндексСтроки, пИндексКолонки).Значение;
Иначе
СтрокаТЗ[НаименованиеКолонки] = ТабДок.Область(ИндексСтроки, пИндексКолонки).Текст;
КонецЕсли;
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
КонецЦикла;
Возврат ТабЗначений;
КонецФункции;
// Преобразовать таблицу значений в табличный документ.
//
// Параметры:
// ТабЗначений - <ТаблицаЗначений> - Исходная таблица значений;
// ТабДок - <ТабличныйДокумент> - Полученный табличный документ. Если параметр не задан,
// то документ создаётся заново и возвращается функцией;
// НачалоСтрока - <Число> - Строка начала области;
// НачалоСтолбец - <Число> - Столбец начала области;
// ВыводитьЗаголовки - <Булево> - Определяет выводить ли имена колонок или нет.
//
// Возвращаемое значение:
// <ТабличныйДокумент> - Полученный табличный документ (возвращает параметр "ТабДок").
//
Функция ПреобразоватьТЗвТД(ТабЗначений, ТабДок = Неопределено, Знач НачалоСтрока = Неопределено, Знач НачалоСтолбец = Неопределено, ВыводитьЗаголовки = Ложь) Экспорт
Если ТабДок = Неопределено Тогда
ТабДок = Новый ТабличныйДокумент;
КонецЕсли;
// Определение габаритов таблицы
НачалоСтрока = ?(НачалоСтрока = Неопределено, 1, НачалоСтрока);
НачалоСтолбец = ?(НачалоСтолбец = Неопределено, 1, НачалоСтолбец);
// Преобразование
ИндексСтроки = НачалоСтрока;
Если ВыводитьЗаголовки Тогда
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из ТабЗначений.Колонки Цикл
ТабДок.Область(ИндексСтроки, ИндексКолонки).Текст = ?(ПустаяСтрока(Колонка.Заголовок), Колонка.Имя, Колонка.Заголовок);
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
ИндексСтроки = ИндексСтроки + 1;
КонецЕсли;
Для Каждого Элемент Из ТабЗначений Цикл
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из ТабЗначений.Колонки Цикл
ТабДок.Область(ИндексСтроки, ИндексКолонки).СодержитЗначение = Истина;
ТабДок.Область(ИндексСтроки, ИндексКолонки).ТипЗначения = Новый ОписаниеТипов(Колонка.ТипЗначения);
ТабДок.Область(ИндексСтроки, ИндексКолонки).Значение = Элемент[Колонка.Имя];
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
ИндексСтроки = ИндексСтроки + 1;
КонецЦикла;
Возврат ТабДок;
КонецФункции;
// Читает табличный документ из файла MXL и преобразует его в таблицу значений.
//
// Параметры:
// ИмяФайла - <Строка> - Путь к файлу MXL;
// СтруктураКолонок - <Структура>, <ТаблицаЗначений> - Структура колонок. Если этот параметр
// не задан, то структура колонок формируется из самого табличного документа;
// ЕстьЗаголовок - <Булево> - Есть ли первая строка с заголовками или нет.
//
// Возвращаемое значение:
// <ТаблицаЗначений> - Полученная таблица значений.
//
Функция ПрочитатьТЗИзMXL(ИмяФайла, СтруктураКолонок = Неопределено, ЕстьЗаголовок = Истина) Экспорт
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);
Если СтруктураКолонок = Неопределено И ЕстьЗаголовок Тогда
СтруктураКолонок = Новый Структура;
Для ИндексКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Обл1 = ТабДок.Область(1, ИндексКолонки);
Обл2 = ТабДок.Область(2, ИндексКолонки);
ИмяКолонки = СокрЛП(Обл1.Текст);
ИмяКолонки = ?(Найти(ИмяКолонки, " ") > 0, СтрЗаменить(ТРег(ИмяКолонки), " ", ""), ИмяКолонки);
СтруктураКолонок.Вставить(ИмяКолонки, ?(Обл2.СодержитЗначение, Обл2.ТипЗначения, Новый ОписаниеТипов));
КонецЦикла;
ИначеЕсли СтруктураКолонок = Неопределено И НЕ ЕстьЗаголовок Тогда
СтруктураКолонок = Новый Структура;
Для ИндексКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Обл2 = ТабДок.Область(1, ИндексКолонки);
ИмяКолонки = "К" + Формат(ИндексКолонки, "ЧДЦ=0; ЧН=0; ЧГ=0");
СтруктураКолонок.Вставить(ИмяКолонки, ?(Обл2.СодержитЗначение, Обл2.ТипЗначения, Новый ОписаниеТипов));
КонецЦикла;
КонецЕсли;
Таблица = ПреобразоватьТДвТЗ(ТабДок, СтруктураКолонок, ?(ЕстьЗаголовок, 2, 1), 1);
Возврат Таблица;
КонецФункции;
// Сохраняет таблицу значений в файле в виде табличного документа.
//
// Параметры:
// ИмяФайла - <Строка> - Путь к файлу MXL;
// ТабЗначений - <ТаблицаЗначений> - Сохраняемая таблица значений;
// ЕстьЗаголовок - <Булево> - Есть ли первая строка с заголовками или нет.
//
Процедура ЗаписатьТЗВMXL(ИмяФайла, ТабЗначений, ЕстьЗаголовок = Истина) Экспорт
ТабДок = ПреобразоватьТЗвТД(ТабЗначений, Неопределено, 1, 1, ЕстьЗаголовок);
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.MXL);
КонецПроцедуры;
Еще небольшой набор функций для вывода таблицы значений в табличный документ. После формирования табличного документа, - сохраняем его в файл mxl.
Табличный документ можно сохранить a файлы следующих типов:
ANSITXT - Текстовый документ DOCX - документ MS Word HTML HTML3 HTML4 HTML5 MXL MXL7 ODS - Файл Open Office PDF - файл Acrobat Readr TXT - Текстовый документ XLS - файл Excel XLS95 - файл Excel95 XLS97 - файл Excel97 XLSX - файл Excel2010 Код 1C v 8.3 // Получаем таблицу значения из файла.
Функция ЗагрузитьТЗизФайла(ИмяФайла)
Путь = КаталогВременныхФайлов() + ИмяФайла;
Текст = Новый ЧтениеТекста(Путь, КодировкаТекста.UTF8);
стрТЗ = Текст.Прочитать();
Текст.Закрыть();
// получим таблицу значений из строки
ТЗ = ЗначениеИзСтрокиВнутр(стрТЗ);
Возврат ТЗ;
КонецФункции
// Заполнить ячейки в строке значениями
//
Функция ЗаписьТЗ2ТабДок(записьТЗ,НомерСтроки,ТабличныйДокумент)
НомерКолонки = 1;
Символ160 = Символ(160);
// цикл по колонкам таблицы
// РезультатЗапроса.Колонки.Количество() // - количество колонок
Для каждого полеТЗ из ЗаписьТЗ цикл
// значения ячейки в Excel
типПоляТЗ = ТипЗнч(полеТЗ);
если типПоляТЗ = Тип("Число") тогда
полеТЗ=Строка(полеТЗ);
полеТЗ=СтрЗаменить(полеТЗ,Символ160,"");
полеТЗ=СтрЗаменить(полеТЗ,",",".");
иначеесли типПоляТЗ = Тип("Строка") тогда
иначе
полеТЗ = строка(полеТЗ);
КонецЕсли;
имяОбласти = "R" + номерСтроки + "C" + НомерКолонки;
имяОбласти = СтрЗаменить(имяОбласти,Символ(160),"");
Ячейка = ТабличныйДокумент.Область(имяОбласти);
Ячейка.Текст = полеТЗ;
НомерКолонки = НомерКолонки + 1;
КонецЦикла;
КонецФункции
// Заполнить наименованиями колонок таблицу
Функция НаимКолонок2Mxl(ТаблицаЗначений,ТабличныйДокумент)
// массКолонки = новый массив();
номерСтроки=1;
номКолонки=1;
ТабличныйДокумент = новый ТабличныйДокумент;
// цикл по коллекции колонок
Для НомКол=0 по ТаблицаЗначений.Колонки.Количество() - 1 Цикл
//Сообщить(Колонка.Имя + "(" + Колонка.ТипЗначения + ")" );
имяКолонки=ТаблицаЗначений.Колонки[НомКол].Имя;
//ТабличныйДокумент.Область(
имяОбласти = "R" + номерСтроки + "C" + номКолонки;
имяОбласти = СтрЗаменить(имяОбласти,Символ(160),"");
Ячейка = ТабличныйДокумент.Область(имяОбласти);
//значениеЯчейки = СтрЗаменить(имяОбласти,Символ(160),"");
Ячейка.Текст = имяКолонки;
// на основе текущего шрифта сделаем Жирный
ЖирныйШрифт = ?(ЖирныйШрифт = Неопределено,Новый Шрифт(Ячейка.Шрифт,,,Истина),ЖирныйШрифт);
Ячейка.Шрифт = ЖирныйШрифт;
номКолонки = номКолонки + 1;
КонецЦикла;
КонецФункции
// Заполнить построчно табличный документ
Функция Таблица2Mxl(ТаблицаЗначений,ТабличныйДокумент)
//Выборка = РезультатЗапроса.Выбрать();
НомСтр=1; // заполняем данными начиная со 2-й строки
// цикл по строкам таблицы
Для каждого записьТЗ из ТаблицаЗначений Цикл
НомСтр = НомСтр + 1;
// цикл по колонкам таблицы
ЗаписьТЗ2ТабДок(записьТЗ,НомСтр,ТабличныйДокумент);
КонецЦикла;
КонецФункции
// Таблица значений в табличный документ
Функция ТаблицаЗначений2Mxl(ТаблицаЗначений,ФайлMxl)
ТабличныйДокумент = новый ТабличныйДокумент;
// вывести колонки
НаимКолонок2Mxl(ТаблицаЗначений,ТабличныйДокумент);
// вывести содержимое таблицы
Таблица2Mxl(ТаблицаЗначений,ТабличныйДокумент);
ТабличныйДокумент.Записать(ФайлMxl,ТипФайлаТабличногоДокумента.MXL);
ТабличныйДокумент.Показать(ФайлMxl,ФайлMxl);
Возврат 0;
КонецФункции
Функция Тест_ВыгрузитьТЗвMxl();
файл_мТЗИсходныеДанные = "мТЗИсходныеДанные.dat";
ТЗ = ЗагрузитьТЗизФайла(файл_мТЗИсходныеДанные);
ФайлMxl = КаталогВременныхФайлов() + СтрЗаменить(файл_мТЗИсходныеДанные,".dat",".mxl");
ТаблицаЗначений2Mxl(ТЗ,ФайлMxl);
КонецФункции
Тест_ВыгрузитьТЗвMxl();
Пример выгруженной таблицы значений в файл:
Категория:
Работа с Таблицей Значений Преобразование ТаблицыЗначений во временную таблицу Код 1C v 8.х Процедура ПреобразоватьТЗвТЗсОписаниемТипов(ТЗ)
ТипизированнаяТЗ = Новый ТаблицаЗначений;
Для й=1 По Тз.Количество() Цикл ТипизированнаяТЗ.Добавить(); //Создаем строки
КонецЦикла;
ДЗТипов = Новый ДеревоЗначений;
ДЗТипов.Колонки.Добавить("ИмяКолонки");
ДЗТипов.Колонки.Добавить("ТипЗначений");
Для Каждого Колонка из Тз.Колонки Цикл
СтрокаКолонки = ДЗТипов.Строки.Добавить();
СтрокаКолонки.ИмяКолонки = Колонка.Имя;
ТекСТрокаТипа = СтрокаКолонки.Строки.Добавить();
ТекСТрокаТипа.ИмяКолонки = Колонка.Имя; //Заполняется для красоты
ТекСТрокаТипа.ТипЗначений = ТипЗнч(тз[0][Колонка.Имя]);
Для Каждого СтокаТЗ из Тз Цикл
ТекТип = ТипЗнч(СтокаТЗ[Колонка.Имя]);
Если НЕ ТекТип = ТекСТрокаТипа.ТипЗначений Тогда
Если СтрокаКолонки.Строки.Найти(ТекТип, "ТипЗначений")=Неопределено Тогда
ТекСТрокаТипа = СтрокаКолонки.Строки.Добавить();
ТекСТрокаТипа.ИмяКолонки = Колонка.Имя;//Заполняется для красоты
ТекСТрокаТипа.ТипЗначений = ТекТип;
КонецЕслИ;
КонецЕслИ;
КонецЦикла;
МассивТипов = СтрокаКолонки.Строки.ВыгрузитьКолонку("ТипЗначений");
ТипизированнаяТЗ.Колонки.Добавить(Колонка.Имя, Новый ОписаниеТипов(МассивТипов),Колонка.Заголовок);
ТипизированнаяТЗ.ЗагрузитьКолонку(Тз.ВыгрузитьКолонку(Колонка),Колонка.Имя);
КонецЦикла;
КонецПроцедуры
Источник
Категория:
Запросы ДеревоЗначений в ТекстовыйДокумент Код 1C v 8.2 УП // Выводит данные ДереваЗначений в ТекстовыйДокумент, пригодный к рассмотрению в отладчике, окне сообщений и показу.
//
// Параметры:
// рВетка - дерево значений, подлежащее выводу. Может иметь почти любую глубину иерархии, количество и тип колонок. Если хватит
// объявленных позиционных строк-заполнителей, всё поместится. Если иерархия слишком глубока, строки просто надо нарастить;
// рТекст - на входе должен быть равен Неопределено; на выходе по окончании работы содержит результатный текстовый документ;
// рПараметры - структура дополнительных настроек, допустимые ключи:
// Колонки - структура колонок, которые подлежат выводу. Если пуста или имеет тип, отличный от структуры, выводятся все колонки;
// если в ключах структуры указаны имена колонок, будут выведены только они. В значениях структуры можно передать строковое
// представление формата, согласно которому должны будут форматироваться выводимые значения. По умолчанию формата нет;
// ПоказыватьУровни - булево, управляет выводом №№ уровней (метод Уровень()), по умолчанию выключено;
// ШагОтступа - число, определяющее шаг в символах, используемый для показа псевдографики иерархии веток в дереве.
//
&НаСервереБезКонтекста
Процедура ВывестиДеревоЗначенийВТекст(Знач рВетка,рТекст,Знач рПараметры=Неопределено)
Попытка
Если рТекст=Неопределено Тогда // первая итерация, шапочный вызов исходной части
//---------------------------------------------------------------------------------------------------------------------------
// Разбираем входные данные
Если ТипЗнч(рВетка)<>Тип("ДеревоЗначений") Тогда Возврат КонецЕсли;
Если ТипЗнч(рПараметры)<>Тип("Структура") Тогда рПараметры=Новый Структура КонецЕсли;
стрКолонок=?(рПараметры.Свойство("Колонки"),рПараметры.Колонки,Неопределено);
Если ТипЗнч(стрКолонок)<>Тип("Структура") Тогда стрКолонок=Новый Структура КонецЕсли;
рПоказыватьУровни=?(рПараметры.Свойство("ПоказыватьУровни"),рПараметры.ПоказыватьУровни,Ложь); // затратное дело, кстати
рШагОтступа=?(рПараметры.Свойство("ШагОтступа"),рПараметры.ШагОтступа,2); // для отображения отступа в колонке иерархии
//---------------------------------------------------------------------------------------------------------------------------
// Определяем максимальное количество уровней
// Также можно получить максимальный уровень, "плоско" перебрав все строки (например, получив их через НайтиСтроки)
// и в цикле для каждой вызывая Уровень() и определяя максимум.
// Вариант через СКД и служебное поле "Уровень" ни на одной известной мне платформе не работоспособен (нехватка памяти).
//
//
//рДеревоДляТеста=КакНибудьСкопироватьДерево(рВетка);
//рДеревоДляТеста.Колонки.Вставить(0,"_Level",Новый ОписаниеТипов("Булево")); // самый экономный вариант, с сохранением иерархии
//мНенужных=Новый Массив;
//Для й=1 По рДеревоДляТеста.Колонки.Количество()-1 Цикл
// мНенужных.Добавить(рДеревоДляТеста.Колонки[й]);
//КонецЦикла;
//Для каждого кол Из мНенужных Цикл
// рДеревоДляТеста.Колонки.Удалить(кол);
//КонецЦикла;
//
рДеревоДляТеста=рВетка; // пока сериализуем прямо всё дерево (неоптимально, но...)
рЗапись=Новый ЗаписьXML;
рЗапись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(рЗапись,рДеревоДляТеста);
стро=рЗапись.Закрыть();
//
стро=СтрЗаменить(стро,"xmlns=","xmlns:myns1C="); // иначе не будет работать XPath
//
рЧтение=Новый ЧтениеXML;
рЧтение.УстановитьСтроку(стро);
постр=Новый ПостроительDOM;
рДокументДОМ=постр.Прочитать(рЧтение);
рВыражение="/ValueTree/row"; максКолвоУровней=1;
рРазыменователь=Новый РазыменовательПространствИменDOM(рДокументДОМ);
Пока Истина Цикл
#Если Клиент Тогда
ОбработкаПрерыванияПользователя();
#КонецЕсли
рРезультат=рДокументДОМ.ВычислитьВыражениеXPath(рВыражение,рДокументДОМ,рРазыменователь,ТипРезультатаDOMXPath.Любой);
Если рРезультат.ПолучитьСледующий()=Неопределено Тогда Прервать КонецЕсли;
рВыражение=рВыражение+"/row";
максКолвоУровней=максКолвоУровней+1;
КонецЦикла;
максКолвоУровней=максКолвоУровней-1; // можно и так: СтрЧислоВхождений(рВыражение,"/row")-1;
//---------------------------------------------------------------------------------------------------------------------------
// готовим исходный макет вывода
строПробелы=" ";
строРазделители="===============================================================================================";
строОтступы="___________________________________________________________________________________________"; // тут нужны чуть для другого
//
секШапка1="|[_HCS"+Лев(строПробелы,максКолвоУровней*рШагОтступа)+"]|"; // HierarchyColumnShow
секГорРазделитель1="|"+Лев(строОтступы,максКолвоУровней*рШагОтступа+6)+"|"; // здесь именно Отступы!
рШиринаКолонкиИерархии=СтрДлина(секШапка1)-2;
строПолейШапки="#Поле _HCS
| #Выравнивание Центр";
строПолейЗаписи="";
//
Если рПоказыватьУровни Тогда
секШапка1=секШапка1+"[_Level]|";
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,8)+"|";
строПолейШапки=строПолейШапки+"
|#Поле _Level
| #Выравнивание Центр";
строПолейЗаписи="#Поле _Level
| #Выравнивание Центр
| #Забивать Истина";
КонецЕсли;
//
мИменКолонок=Новый Массив;
Для каждого кол Из рВетка.Колонки Цикл
Если стрКолонок.Количество()<>0 и не стрКолонок.Свойство(кол.Имя) Тогда Продолжить КонецЕсли; // чётко указаны конкретные колонки
рДлинаИмениКолонки=СтрДлина(кол.Имя);
рНужнаяШирина=Макс(?(кол.Ширина<3,10,кол.Ширина),рДлинаИмениКолонки);
// к сожалению, ключевое слово "#Поля" неприменимо - платформа падает - поэтому делаем всё сами
секШапка1=секШапка1+"["+кол.Имя+Лев(строПробелы,рНужнаяШирина-рДлинаИмениКолонки)+"]|";
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,рНужнаяШирина+1)+"=|";
строПолейШапки=строПолейШапки+"
|#Поле "+кол.Имя+"
| #Выравнивание Центр";
рОписТипов=кол.ТипЗначения;
Если рОписТипов.Типы().Количество()=1 и рОписТипов.СодержитТип(Тип("Булево")) Тогда
рВыравнивание="Центр";
ИначеЕсли рОписТипов.СодержитТип(Тип("Число")) Тогда
рВыравнивание="Право";
ИначеЕсли рОписТипов.СодержитТип(Тип("Строка")) и рОписТипов.КвалификаторыСтроки.Длина=0 Тогда
рВыравнивание="ПоШирине";
Иначе
рВыравнивание="Лево";
КонецЕсли;
строПолейЗаписи=строПолейЗаписи+?(ПустаяСтрока(строПолейЗаписи),"",Символы.ПС)+"#Поле "+кол.Имя+"
| #Выравнивание "+рВыравнивание;
Попытка
Если ЗначениеЗаполнено(стрКолонок[кол.Имя]) Тогда // указан формат, уточняющий показ колонки
строПолейЗаписи=строПолейЗаписи+"
| #Формат """+СокрЛП(стрКолонок[кол.Имя])+"""";
КонецЕсли;
Исключение
КонецПопытки;
мИменКолонок.Добавить(кол.Имя);
КонецЦикла;
секШапка2=СтрЗаменить(СтрЗаменить(секШапка1,"[","<"),"]",">");
секЗапись1=секШапка1; секЗапись2=секШапка2; // пусть они по дизайну пока не отличаются
секГорРазделитель2=СтрЗаменить(СтрЗаменить(секГорРазделитель1,"=","-"),"|","+");
// обработаем нормальное обрамление шапки колонки иерархии
секГорРазделитель1=СтрЗаменить(секГорРазделитель1,"_","=");
секГорРазделитель2=СтрЗаменить(секГорРазделитель2,"_"," ");
//
тМакет=Новый ТекстовыйДокумент;
тМакет.ДобавитьСтроку("#Область Шапка");
тМакет.ДобавитьСтроку(строПолейШапки);
тМакет.ДобавитьСтроку(секГорРазделитель1);
тМакет.ДобавитьСтроку(секШапка1);
тМакет.ДобавитьСтроку(секШапка2);
тМакет.ДобавитьСтроку(секГорРазделитель1);
тМакет.ДобавитьСтроку("#КонецОбласти");
тМакет.ДобавитьСтроку("");
тМакет.ДобавитьСтроку("#Область Запись");
тМакет.ДобавитьСтроку(строПолейЗаписи);
тМакет.ДобавитьСтроку(секЗапись1);
тМакет.ДобавитьСтроку(секЗапись2);
тМакет.ДобавитьСтроку(секГорРазделитель2);
тМакет.ДобавитьСтроку("#КонецОбласти");
рПараметры.Вставить("ИсходныйМакет",тМакет); // пусть будет
//---------------------------------------------------------------------------------------------------------------------------
// Запускаем вывод в итоговый документ
рТекст=Новый ТекстовыйДокумент;
сек=тМакет.ПолучитьОбласть("Шапка");
сек.Параметры._HCS="Иерархия";
Для каждого имякол Из мИменКолонок Цикл
кол=рВетка.Колонки[имякол];
сек.Параметры[кол.Имя]=?(ПустаяСтрока(кол.Заголовок),кол.Имя,кол.Заголовок);
КонецЦикла;
рТекст.Вывести(сек);
//
пар=Новый Структура;
пар.Вставить("МассивИмёнКолонок",мИменКолонок);
пар.Вставить("ТекущаяСекция",тМакет.ПолучитьОбласть("Запись"));
пар.Вставить("ШиринаКолонкиИерархии",рШиринаКолонкиИерархии);
пар.Вставить("ПоказыватьУровни",рПоказыватьУровни);
пар.Вставить("Отступ",0);
пар.Вставить("ШагОтступа",рШагОтступа);
ВывестиДеревоЗначенийВТекст(рВетка,рТекст,пар);
Иначе
// очередная итерация, вывод в текстовый документ
мИменКолонок=рПараметры.МассивИмёнКолонок;
рСекция=рПараметры.ТекущаяСекция;
рОтступ=рПараметры.Отступ;
рШиринаКолонкиИерархии=рПараметры.ШиринаКолонкиИерархии;
рПоказыватьУровни=рПараметры.ПоказыватьУровни;
//
строОтступы="_________________________________________________________________________________________________________";
строПробелы=" ";
//
пар=Новый Структура;
пар.Вставить("МассивИмёнКолонок",мИменКолонок);
пар.Вставить("ТекущаяСекция",рПараметры.ТекущаяСекция);
пар.Вставить("ШиринаКолонкиИерархии",рШиринаКолонкиИерархии);
пар.Вставить("ПоказыватьУровни",рПоказыватьУровни);
пар.Вставить("ШагОтступа",рПараметры.ШагОтступа);
пар.Вставить("Отступ",рОтступ+рПараметры.ШагОтступа);
//
Для каждого рПодветка Из рВетка.Строки Цикл
рСекция.Параметры._HCS=Лев(строПробелы,рОтступ)+"\"+Лев(строОтступы,рШиринаКолонкиИерархии-рОтступ-1);
Если рПоказыватьУровни Тогда
рСекция.Параметры._Level=рПодветка.Уровень();
КонецЕсли;
Для каждого имякол Из мИменКолонок Цикл
рСекция.Параметры[имякол]=рПодветка[имякол];
КонецЦикла;
рТекст.Вывести(рСекция);
ВывестиДеревоЗначенийВТекст(рПодветка,рТекст,пар)
КонецЦикла;
//
КонецЕсли;
Исключение
Сообщить("ВывестиДеревоЗначенийВТекст, ошибка: "+ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
КонецПопытки;
КонецПроцедуры
Источник
Категория:
Работа с Деревом Значений Синтаксический анализ JSON - выражения средствами 1С 7.7 Код 1C v 7.x
Перем Л_Лев_Фиг_Скобка, Л_Прав_Фиг_Скобка, Л_Лев_Кв_Скобка, Л_Прав_Кв_Скобка, Л_Кавычка, Л_Экран, Л_Двоеточие, Л_Запятая, Л_Число, Л_Строка, Л_Константа, Л_Финиш;
Перем Цифры1_9, Цифры0_9, ПервыеСимволыКонстант, ОдносимвольныеЛексемы;
Перем НомЛексемы, ТекЛексема;
Перем JSON_Error;
Перем В_Массив, В_Объект, В_Значение;
//*****
Перем НомерСимвола;
Перем ФлагОшибки;
Перем СписокСтроковыхКонстант;
Перем СтекЛексем;
Перем АнализируемаяСтрока;
//*****
Перем ТекКаталог, ТекФайл;
//*****
Функция ПолучитьОбъект_ТЗ() Далее
Функция ПолучитьМассив_ТЗ() Далее
//*****
Функция ТекущиеСимволы(Сколько)
Возврат Сред(АнализируемаяСтрока, НомерСимвола, Сколько);
КонецФункции
//*****
Функция ПрошлыйСимвол(Сдвиг)
Возврат Сред(АнализируемаяСтрока, НомерСимвола - Сдвиг, 1);
КонецФункции
//*****
Процедура ДобавитьЛексему(Лексема, Значение, Сдвиг)
СтекЛексем.НоваяСтрока();
СтекЛексем.Лексема = Лексема;
СтекЛексем.Значение = Значение;
НомерСимвола = НомерСимвола + Сдвиг;
КонецПроцедуры
//*****
Процедура ОбвестиОбласть(Обл)
Обл.РамкаСнизу(1);
Обл.РамкаСверху(1);
Обл.РамкаСлева(1);
Обл.РамкаСправа(1);
КонецПроцедуры
//*****
Процедура НапечататьТЗ(Таб, ТЗ, НомС, НомК)
Перем Тип, Обл1, НС, КС, Ключ, Зн, Обл2;
Тип = ТЗ.ПолучитьЗначение(1, 1);
НомС = НомС + 1;
Обл1 = Таб.Область(НомС, НомК);
ОбвестиОбласть(Обл1);
Если Тип = В_Значение Тогда
ТипЗн = ТЗ.ПолучитьЗначение(2, 1);
Обл1.Текст = ТЗ.ПолучитьЗначение(2, 2);
Обл1.ГоризонтальноеПоложение(1);
Если ТипЗн = Л_Число Тогда
Обл1.ГоризонтальноеПоложение(2);
ИначеЕсли ТипЗн = Л_Константа Тогда
Обл1.Полужирный(1);
ИначеЕсли ТипЗн = Л_Строка Тогда
Обл1.Контроль(4);
КонецЕсли;
Возврат;
ИначеЕсли (Тип = В_Объект) Или (Тип = В_Массив) Тогда
Обл1.Текст = Тип;
Обл1.Полужирный(1);
Обл1.ЦветФона(12648447);
Обл1.РамкаСнизу(5);
КС = ТЗ.КоличествоСтрок();
Для НС = 2 По КС Цикл
НомС = НомС + 1;
Обл2 = Таб.Область(НомС, НомК);
Обл2.Текст = ТЗ.ПолучитьЗначение(НС, 1);
Если Тип = В_Массив Тогда
Обл2.ГоризонтальноеПоложение(2);
КонецЕсли;
ОбвестиОбласть(Обл2);
НомС = НомС - 1;
НапечататьТЗ(Таб, ТЗ.ПолучитьЗначение(НС, 2), НомС, НомК + 1);
КонецЦикла;
Иначе
Сообщить("Фигня " + Тип, "!");
КонецЕсли;
КонецПроцедуры
//*****
Процедура ВыравнятьТЗ(Таб, ОграничениеШирины)
Перем НомерКол, НомерСтр, МаксШирина, Обл, ТекШирина, ТекДлина;
Для НомерКол = 1 По Таб.ШиринаТаблицы() Цикл
МаксШирина = 0;
Для НомерСтр = 1 По Таб.ВысотаТаблицы() Цикл
Обл = Таб.Область(НомерСтр, НомерКол);
ТекШирина = Обл.ШиринаСтолбца();
ТекДлина = СтрДлина(СокрЛП(Обл.Текст));
МаксШирина = Макс(МаксШирина, ТекШирина, ТекДлина);
КонецЦикла;
Таб.Область(, НомерКол).ШиринаСтолбца(Мин(МаксШирина, ОграничениеШирины));
КонецЦикла;
КонецПроцедуры
//*****
Процедура Напечатать_ТЗ(ТЗ)
Перем Таб, НС, НК, МаксШирина, ТекДлина, Обл;
Таб = СоздатьОбъект("Таблица");
МаксНК = 1;
НС = 0;
НК = 1;
НапечататьТЗ(Таб, ТЗ, НС, НК);
ВыравнятьТЗ(Таб, 30);
Таб.Область(1, 1, Таб.ВысотаТаблицы(), Таб.ШиринаТаблицы()).ВертикальноеПоложение(2);
Таб.Опции(0, 0);
Таб.Показать("JSON");
КонецПроцедуры
//*****
Функция Ошибка()
ФлагОшибки = 1;
Возврат 0;
КонецФункции
//*****
Функция ЧитатьКонстанту(ПервСимвол)
Перем КонстантаСтр, ДлинаКонстанты;
КонстантаСтр = СписокСтроковыхКонстант.Получить(ПервСимвол);
ДлинаКонстанты = СтрДлина(КонстантаСтр);
Если ТекущиеСимволы(ДлинаКонстанты) = КонстантаСтр Тогда
ДобавитьЛексему(Л_Константа, КонстантаСтр, ДлинаКонстанты);
Возврат 1;
Иначе
Возврат Ошибка();
КонецЕсли;
КонецФункции
//*****
Процедура ДописатьСимвол(Стр)
Стр = Стр + ТекущиеСимволы(1);
НомерСимвола = НомерСимвола + 1;
КонецПроцедуры
//*****
Функция ЧитатьЧисло()
Перем ЧислоСтр;
ЧислоСтр = "";
Если ТекущиеСимволы(1) = "-" Тогда
ДописатьСимвол(ЧислоСтр);
КонецЕсли;
Если Найти(Цифры1_9, ТекущиеСимволы(1)) > 0 Тогда // не с нуля
ДописатьСимвол(ЧислоСтр);
Пока Найти(Цифры0_9, ТекущиеСимволы(1)) > 0 Цикл // любые цыфры
ДописатьСимвол(ЧислоСтр);
КонецЦикла;
ИначеЕсли ТекущиеСимволы(1) = "0" Тогда //с нуля - ничего дальше
ДописатьСимвол(ЧислоСтр);
Иначе
Возврат Ошибка();
КонецЕсли;
Если ТекущиеСимволы(1) = "." Тогда // десятичная точка
ДописатьСимвол(ЧислоСтр);
Пока Найти(Цифры0_9, ТекущиеСимволы(1)) > 0 Цикл // любые цыфры
ДописатьСимвол(ЧислоСтр);
КонецЦикла;
КонецЕсли;
Если ВРег(ТекущиеСимволы(1)) = "E" Тогда // значок e больное или маленькое
ДописатьСимвол(ЧислоСтр);
Если Найти("+-", ТекущиеСимволы(1)) > 0 Тогда // унарный знак для порядка
ДописатьСимвол(ЧислоСтр);
КонецЕсли;
Пока Найти(Цифры0_9, ТекущиеСимволы(1)) > 0 Цикл // любые цыфры
ДописатьСимвол(ЧислоСтр);
КонецЦикла;
КонецЕсли;
ДобавитьЛексему(Л_Число, ЧислоСтр, 0);
Возврат 1;
КонецФункции
//*****
Функция ЧитатьСтроку()
Перем СтрокаСтр;
СтрокаСтр = "";
НомерСимвола = НомерСимвола + 1;
Пока (ТекущиеСимволы(1) <> Л_Кавычка) Или ((ТекущиеСимволы(1) = Л_Кавычка) И (ПрошлыйСимвол(1) = Л_Экран) И (ПрошлыйСимвол(2) <> Л_Экран)) Цикл
ДописатьСимвол(СтрокаСтр);
КонецЦикла;
ДобавитьЛексему(Л_Строка, СтрокаСтр, 1);
Возврат 1;
КонецФункции
//*****
Функция ПрочитатьФайл(ИмяФайла)
Перем Т, НомерСтрокиФайла, СтрокаРез;
Т = СоздатьОбъект("Текст");
Т.Открыть(ИмяФайла);
СтрокаРез = "";
Для НомерСтрокиФайла = 1 По Т.КоличествоСтрок() Цикл
СтрокаРез = СтрокаРез + Т.ПолучитьСтроку(НомерСтрокиФайла);
КонецЦикла;
Возврат СтрокаРез;
КонецФункции
//*****
Функция СледующаяЛексема()
НомЛексемы = НомЛексемы + 1;
СтекЛексем.ПолучитьСтрокуПоНомеру(НомЛексемы);
ТекЛексема = СтекЛексем.Лексема;
Возврат 1;
КонецФункции
//*****
Функция ОшибкаЛексемы()
Перем РезСтр, НомСтр, ТЛ, ТС;
Сообщить("Ошибочная лексема № " + НомЛексемы + " : <" + ТекЛексема + ">", "!");
РезСтр = "";
Для НомСтр = НомЛексемы + 1 По СтекЛексем.КоличествоСтрок() Цикл
СтекЛексем.ПолучитьСтрокуПоНомеру(НомСтр);
ТЛ = СтекЛексем.Лексема;
Если ТЛ = Л_Строка Тогда
ТС = "<" + ТЛ + "(" + СтекЛексем.Значение + ")>";
ИначеЕсли ТЛ = Л_Константа Тогда
ТС = "<" + ТЛ + "(" + СтекЛексем.Значение + ")>";
Иначе
ТС = "<" + ТЛ + ">";
КонецЕсли;
РезСтр = РезСтр + ТС + ",";
КонецЦикла;
Сообщить(Лев(РезСтр, 400), "!");
Возврат 0;
КонецФункции
//*****
Процедура ДобавитьПару(ТЗ, Ключ, Значение)
ТЗ.НоваяСтрока();
ТЗ.Ключ = Ключ;
ТЗ.Значение = Значение;
КонецПроцедуры
//*****
Функция НоваяТЗ(Тип)
Перем _ТЗ;
_ТЗ = СоздатьОбъект("ТаблицаЗначений");
_ТЗ.НоваяКолонка("Ключ");
_ТЗ.НоваяКолонка("Значение");
ДобавитьПару(_ТЗ, Тип, "");
Возврат _ТЗ;
КонецФункции
//*****
Функция ПолучитьПроизвольноеЗначение_ТЗ()
Перем ТЗ;
Если (ТекЛексема = Л_Строка) Или (ТекЛексема = Л_Число) Или (ТекЛексема = Л_Константа) Тогда
ТЗ = НоваяТЗ(В_Значение);
ДобавитьПару(ТЗ, ТекЛексема, СтекЛексем.Значение);
СледующаяЛексема();
Возврат ТЗ;
ИначеЕсли ТекЛексема = Л_Лев_Фиг_Скобка Тогда
Возврат ПолучитьОбъект_ТЗ();
ИначеЕсли ТекЛексема = Л_Лев_Кв_Скобка Тогда
Возврат ПолучитьМассив_ТЗ();
КонецЕсли;
Возврат ОшибкаЛексемы();
КонецФункции
//*****
Функция ДобавитьКлючЗначение(ТЗ)
Перем НовКлюч, НовЗначение;
Если ТекЛексема <> Л_Строка Тогда
Возврат 0;
КонецЕсли;
НовКлюч = СтекЛексем.Значение;
СледующаяЛексема();
Если ТекЛексема <> Л_Двоеточие Тогда
Возврат ОшибкаЛексемы();
КонецЕсли;
СледующаяЛексема();
НовЗначение = ПолучитьПроизвольноеЗначение_ТЗ();
Если НовЗначение = 0 Тогда
Возврат 0;
КонецЕсли;
ДобавитьПару(ТЗ, НовКлюч, НовЗначение);
Возврат 1;
КонецФункции
//*****
Функция ПолучитьОбъект_ТЗ()
Перем ТЗ;
ТЗ = НоваяТЗ(В_Объект);
СледующаяЛексема();
Если ТекЛексема = Л_Прав_Фиг_Скобка Тогда // пустой объект
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
Если ДобавитьКлючЗначение(ТЗ) = 0 Тогда // первая пара ключ-значение
Возврат 0;
КонецЕсли;
Пока ТекЛексема = Л_Запятая Цикл // пока запятые
СледующаяЛексема();
Если ДобавитьКлючЗначение(ТЗ) = 0 Тогда // пара ключ-значение
Возврат 0;
КонецЕсли;
КонецЦикла;
Если ТекЛексема = Л_Прав_Фиг_Скобка Тогда
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
Возврат 0;
КонецФункции
//*****
Функция ПолучитьМассив_ТЗ()
Перем ТЗ, _Ключ, _Значение;
ТЗ = НоваяТЗ(В_Массив);
СледующаяЛексема();
Если ТекЛексема = Л_Прав_Кв_Скобка Тогда
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
_Значение = ПолучитьПроизвольноеЗначение_ТЗ();
Если _Значение = 0 Тогда
Возврат 0;
КонецЕсли;
_Ключ = 0; // JS - индексы массиворв с нуля
ДобавитьПару(ТЗ, _Ключ, _Значение);
Пока ТекЛексема = Л_Запятая Цикл
СледующаяЛексема();
_Значение = ПолучитьПроизвольноеЗначение_ТЗ();
Если _Значение = 0 Тогда
Возврат 0;
КонецЕсли;
_Ключ = _Ключ + 1;
ДобавитьПару(ТЗ, _Ключ, _Значение);
КонецЦикла;
Если ТекЛексема = Л_Прав_Кв_Скобка Тогда
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
Возврат 0;
КонецФункции
//*****
Функция ПрочитатьОбъект_ТЗ()
Перем Рез;
НомЛексемы = 0;
СледующаяЛексема();
Если ТекЛексема = Л_Лев_Фиг_Скобка Тогда
Рез = ПолучитьОбъект_ТЗ();
ИначеЕсли ТекЛексема = Л_Лев_Кв_Скобка Тогда
Рез = ПолучитьМассив_ТЗ();
Иначе
Рез = ПолучитьПроизвольноеЗначение_ТЗ();
КонецЕсли;
Если (Рез = 0) Или (ТекЛексема <> Л_Финиш) Тогда
ОшибкаЛексемы();
Возврат 0;
КонецЕсли;
Возврат Рез;
КонецФункции
//*****
Функция СгенерироватьТЗ(НачАнализируемаяСтрока)
Перем НачальныйСимвол, Рез;
АнализируемаяСтрока = НачАнализируемаяСтрока;
СтекЛексем = СоздатьОбъект("ТаблицаЗначений");
СтекЛексем.НоваяКолонка("Лексема" , "Строка");
СтекЛексем.НоваяКолонка("Значение", "Строка");
ФлагОшибки = 0;
НомерСимвола = 1;
Пока НомерСимвола <= СтрДлина(АнализируемаяСтрока) Цикл
НачальныйСимвол = ТекущиеСимволы(1);
Если Найти(" " + Симв(9), НачальныйСимвол) > 0 Тогда // пробелы и разделители строк пропускаем
НомерСимвола = НомерСимвола + 1;
ИначеЕсли НачальныйСимвол = Л_Кавычка Тогда // кавычка - читаем строку
ЧитатьСтроку();
ИначеЕсли Найти(ОдносимвольныеЛексемы, НачальныйСимвол) > 0 Тогда
ДобавитьЛексему(НачальныйСимвол, "", 1);
ИначеЕсли Найти(ПервыеСимволыКонстант, НачальныйСимвол) > 0 Тогда // первая буква из начала константы - константа null, true, false
Если ЧитатьКонстанту(НачальныйСимвол) = 0 Тогда
Прервать;
КонецЕсли;
ИначеЕсли Найти("-" + Цифры0_9, НачальныйСимвол) > 0 Тогда // число
Если ЧитатьЧисло() = 0 Тогда
Прервать;
КонецЕсли;
Иначе // иных вариантов нет
Сообщить("========= " + НомерСимвола, "!");
Сообщить(НачальныйСимвол, "!");
Сообщить("<" + НачальныйСимвол + "> " + КодСимв(НачальныйСимвол), "!");
Сообщить(ТекущиеСимволы(100), "!");
Возврат 0;
КонецЕсли;
КонецЦикла;
Если ФлагОшибки <> 0 Тогда
Сообщить("Ошибка парсинга JSON - выражения", "!");
Возврат 0;
ИначеЕсли СтекЛексем.КоличествоСтрок() = 0 Тогда
Сообщить("Пустой стек", "!");
Возврат 0;
КонецЕсли;
ДобавитьЛексему(Л_Финиш, "", 0);
Возврат ПрочитатьОбъект_ТЗ();
КонецФункции
//*****
Функция JSON_Error(Стр = "")
Если Стр <> "" Тогда
Сообщить("JSON-ОШИБКА: " + Стр, "!");
КонецЕсли;
Возврат JSON_Error;
КонецФункции
//*****
Функция JSON_Type(Парам)
Если ТипЗначенияСтр(Парам) <> "ТаблицаЗначений" Тогда
Возврат JSON_Error();
ИначеЕсли Парам.КоличествоКолонок() <> 2 Тогда
Возврат JSON_Error();
ИначеЕсли Парам.КоличествоСтрок() < 2 Тогда
Возврат JSON_Error();
КонецЕсли;
Возврат Парам.ПолучитьЗначение(1, 1);
КонецФункции
//*****
Функция JSON_GetValue(Парам, Keys)
Перем Тип, До, После, ПозЗакр, Л1, П2, Инд, ИндСтр, НС, КвоСтрок;
Тип = JSON_Type(Парам);
ПозЗакр = Найти(Keys, "]");
Если ПозЗакр = 0 Тогда
ПозЗакр = СтрДлина(Keys) + 1;
КонецЕсли;
До = Лев(Keys, ПозЗакр);
После = Сред(Keys, ПозЗакр + 1);
Л1 = Лев(До, 1);
П2 = Найти(До, "]");
Если Тип = JSON_Error Тогда
Возврат JSON_Error("Параметра");
КонецЕсли;
КвоСтрок = Парам.КоличествоСтрок();
Если До = "" Тогда // сам объект
Если (Тип = В_Массив) Или (Тип = В_Объект) Тогда
Возврат JSON_Error();
ИначеЕсли Тип = В_Значение Тогда
Возврат Парам.ПолучитьЗначение(2, 2);
Иначе
Возврат JSON_Error("№ 1");
КонецЕсли;
ИначеЕсли До = ".length" Тогда // размер массива или объекта. Для значения - ошибка
Если (Тип = В_Массив) Или (Тип = В_Объект) Тогда
Возврат Парам.КоличествоСтрок() - 1;
Иначе
Возврат JSON_Error("Длина скаляра");
КонецЕсли;
ИначеЕсли Л1 = "[" Тогда // размер массива или объекта. Для значения - ошибка
Если П2 = 0 Тогда
Возврат JSON_Error("Индексация: <" + До + ">");
КонецЕсли;
Инд = Сред(До, 2, П2 - 2);
Если (Найти("'""", Лев(Инд, 1)) > 0) И (Найти("'""", Прав(Инд, 1)) > 0) Тогда // строковый только объект
ИндСтр = Сред(Инд, 2, СтрДлина(Инд) - 2);
Если Тип <> В_Объект Тогда
Возврат JSON_Error("Строковый индекс <" + ИндСтр + "> только для Объекта");
КонецЕсли;
НС = 0;
Если Парам.НайтиЗначение(ИндСтр, НС, 1) = 1 Тогда
Возврат JSON_GetValue(Парам.ПолучитьЗначение(НС, 2), После);
КонецЕсли;
Возврат JSON_Error("Нет индекса <" + ИндСтр + ">");
КонецЕсли;
ИндЧис = 0 + Инд;
Если "" + ИндЧис <> Инд Тогда // защита от <5D>
Возврат JSON_Error("Ошибка 1 числового индекса <" + Инд + ">");
ИначеЕсли Цел(ИндЧис) <> ИндЧис Тогда // защита от неЦелого индекса
Возврат JSON_Error("Ошибка 2 числового индекса <" + Инд + "> (нецелый)");
ИначеЕсли ИндЧис < 0 Тогда
Возврат JSON_Error("Ошибка 3 числового индекса <" + Инд + "> (отрицательный)");
ИначеЕсли ИндЧис > (КвоСтрок - 2) Тогда
Возврат JSON_Error("Ошибка 4 числового индекса <" + Инд + "> (" + ИндЧис + ">" + (КвоСтрок - 2) + ")");
КонецЕсли;
Возврат JSON_GetValue(Парам.ПолучитьЗначение(ИндЧис + 1, 2), После);
Иначе
Возврат JSON_Error("Ошибка 5 <" + До + ">");
КонецЕсли;
КонецФункции
//*****
Процедура ПриОткрытии()
Перем Рез1, ТипУзла1, Зн1, Значение;
ОчиститьОкноСообщений();
СтатусВозврата(0);
Рез1 = СгенерироватьТЗ(ПрочитатьФайл(ТекКаталог + "j1.json"));
Напечатать_ТЗ(Рез1);
ТипУзла1 = JSON_Type(Рез1);
Сообщить("Тип узла: " + ТипУзла1);
Зн1 = JSON_GetValue(Рез1, ".length"); Сообщить("1) Размер: " + Зн1);
Зн3 = JSON_GetValue(Рез1, "['1']"); Сообщить("3) ['1']: <" + Зн3 + ">");
Зн4 = JSON_GetValue(Рез1, "[1]"); Сообщить("4) [1]: <" + Зн4 + ">");
Зн5 = JSON_GetValue(Рез1, "['Массив'][6]"); Сообщить("5) [*]: <" + Зн5 + ">");
Зн6 = JSON_GetValue(Рез1, "['Соответствие']['ДопустимоеИмяСвойства']"); Сообщить("6) [*]: <" + Зн6 + ">");
КонецПроцедуры
//*****
Процедура ДобавитьСтроковуюКонстанту(КонстантаСтр)
Перем ПервыйСимвол;
ПервыйСимвол = Лев(КонстантаСтр, 1);
ПервыеСимволыКонстант = ПервыеСимволыКонстант + ПервыйСимвол;
СписокСтроковыхКонстант.Установить(ПервыйСимвол, КонстантаСтр);
КонецПроцедуры
//*****
РасположениеФайла(ТекКаталог, ТекФайл);
//*****
Л_Лев_Фиг_Скобка = "{";
Л_Прав_Фиг_Скобка = "}";
Л_Лев_Кв_Скобка = "[";
Л_Прав_Кв_Скобка = "]";
Л_Двоеточие = ":";
Л_Запятая = ",";
Л_Экран = "\";
Л_Кавычка = """";
Л_Финиш = "";
Л_Число = "number";
Л_Строка = "string";
Л_Константа = "const";
ОдносимвольныеЛексемы = Л_Лев_Фиг_Скобка + Л_Прав_Фиг_Скобка + Л_Лев_Кв_Скобка + Л_Прав_Кв_Скобка + Л_Двоеточие + Л_Запятая;
//*****
Цифры1_9 = "123456789";
Цифры0_9 = "0" + Цифры1_9;
//*****
В_Массив = "###array";
В_Объект = "###object";
В_Значение = "###value";
//*****
СписокСтроковыхКонстант = СоздатьОбъект("СписокЗначений");
ПервыеСимволыКонстант = "";
ДобавитьСтроковуюКонстанту("null");
ДобавитьСтроковуюКонстанту("false");
ДобавитьСтроковуюКонстанту("true");
JSON_Error = "ERROR";
В качестве примера взят файл j1.json :
{
"999": 88,
"Null": null,
"Сэкраном": "\"",
"Ложь": false,
"ОдинСимв": "1",
"1": "11111",
"Пустышка": "",
"Истина": true,
"Число (плавающая точка)": 1.001e-2,
"Число (плавающая)": -1.001e-2,
"Число (фиксированная точка)": -1000.001,
"Дата": "2011-01-01T12:00:00Z",
"Строка (двойная кавычка)": "Двойная кавычка",
"Строка (одинарная кавычка)": "Одинарная кавычка",
"Маскируемые символы": " \\ \/ \b \t \n \f \r \" ",
"Заковыристая строка": "\\n\\",
"Проблемные символы": "Спец. символы: \u0000, \u0001, \u0002, ... , \u001e, \u001f; Юникод символы: \u0421\u0430\u0448\u0430\u0020\u003a\u0029",
"Кириллические символы": "’АБВГҐДЂЃЕ?ЁЄЖЗЅИ?ІЇЙЈКЛЉМНЊОПРСТЋЌУЎФХЦЧЏШЩЪЫЬЭЮЯ",
"Идентификатор": "a763cfbb-f94f-4c67-8e13-0e96a3a7f353",
"Пустой массив": [],
"Пустой объект": {},
"Массив": [
null,
false,
true,
1.001e-2,
-1000.001,
"2011-01-01T12:00:00Z",
"Двойная кавычка",
"Одинарная кавычка",
"a763cfbb-f94f-4c67-8e13-0e96a3a7f353",
[
"Первый элемент",
"Второй элемент"
],
{
"Имя": "Александр",
"Отчество": "Владимирович",
"Фамилия": "Переверзев"
},
{
"ДопустимоеИмяСвойства": true,
"Недопустимое Имя Свойства": false
}
],
"Структура":
{
"Имя": "Александр",
"Отчество": "Владимирович",
"Фамилия": "Переверзев"
},
"Соответствие":
{
"ДопустимоеИмяСвойства": true,
"Недопустимое Имя Свойства": false
},
"Ссылка":
{
"Ссылка": "00000000-0000-0000-0000-000000000000",
"Представление": "Неизвестная ссылка"
},
"COMSafeArray": [
0,
1,
2,
3,
4,
5
]
}
Категория:
HTML, JS, VML Как отобразить дерево значений на управляемой форме Создадим новую внешнюю обработку.
Добавляем управляемую форму и создаем обработчик ПриСозданииНаСервере(). Никаких реквизитов и элементов “вручную” не добавляем, будем делать это программно.
Код 1C v 8.2 УП &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создание и заполнение "обычного" объекта прикладного типа ДеревоЗначений,
// который будет отображен на управляемой форме
ДеревоОбъект = Новый ДеревоЗначений;
ДеревоОбъект.Колонки.Добавить("Узел", Новый ОписаниеТипов("Строка"));
Для к1 = 1 По 3 Цикл
СтрокаУ1 = ДеревоОбъект.Строки.Добавить();
СтрокаУ1.Узел = "Узел"+к1;
Для к2 = 1 По 3 Цикл
СтрокаУ2 = СтрокаУ1.Строки.Добавить();
СтрокаУ2.Узел = СтрокаУ1.Узел+к2;
Для к3 = 1 По 3 Цикл
СтрокаУ3 = СтрокаУ2.Строки.Добавить();
СтрокаУ3.Узел = СтрокаУ2.Узел+к3;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Создание Реквизита формы типа ДанныеФормыДерево
МассивДобавляемыхРеквизитов = Новый Массив;
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Дерево",
Новый ОписаниеТипов("ДеревоЗначений")));
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
МассивДобавляемыхРеквизитов.Добавить(
Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, "Дерево"));
КонецЦикла;
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
// Преобразование объекта прикладного типа ДеревоЗначений
// в реквизит управляемой формы (данные формы)
ЗначениеВРеквизитФормы(ДеревоОбъект, "Дерево");
// Создание элемента формы типа ТаблицаФормы для отображения дерева
ЭлементДерево = Элементы.Добавить("Дерево", Тип("ТаблицаФормы"));
ЭлементДерево.ПутьКДанным = "Дерево";
ЭлементДерево.Отображение = ОтображениеТаблицы.Дерево;
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"),
ЭлементДерево);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "Дерево." + Колонка.Имя;
КонецЦикла;
КонецПроцедуры
Категория:
Работа с Деревом Значений Как программно изменить текст, цвет, фон ячейки или области табличного документа? Ниже приведено несколько полезных шаблонов кода по работе с табличным документом:
Код 1C v 8.х //Пример получения текста ячейки
ПолеТабДок = ЭлементыФормы.тдПолеТабличногоДокумента;
ПолеТабДок.Область("R1C2").Текст = спрНоменклатура.Наименование;
ПолеТабДок.Область("R2C2").Текст = "Это Строка"; //указываем явно литерал строки
Код 1C v 8.х // Изменение текста в области или ячейке
Для а = 11 по ТабличныйДокумент.ВысотаТаблицы Цикл
//Ячейка = ТабличныйДокумент.Область(а,1,а,1).Текст;
текстЯчейка = ТабличныйДокумент.Область("R"+а+"C2").Текст;
Если Строка(ТабличныйДокумент.Область("R"+а+"C2").ЦветФона)="стиль: Фон кнопки" Тогда
ТабличныйДокумент.Область("R"+а+"C7").Текст="";
ТабличныйДокумент.Область("R"+а+"C11").Текст="";
ТабличныйДокумент.Область("R"+а+"C8").Текст="";
ТабличныйДокумент.Область("R"+а+"C9").Текст="";
ТабличныйДокумент.Область("R"+а+"C10").Текст="";
КонецЕсли;
КонецЦикла;
Код 1C v 8.х // Как раскрасить ячейку или область табличного документа в зависимости от условия
ТабДок = ЭлементыФормы.ПолеТабличногоДокумента; // Получаем табличный документ из формы
ТабДок.Очистить(); // Очищаем табличный документ
Макет = ПолучитьМакет("Макет"); // Получаем макет с именем "Макет" из текущего объекта
ОбластьСтрокаТаб = Макет.ПолучитьОбласть("СтрокаТаб"); // Получаем область из макета
ОбластьСтрокаТаб.Параметры.НашПараметр = 1; // Устанавливаем значение 1 параметру "НашПараметр"
ОбластьОформления = ТабДок.Вывести(ОбластьСтрокаТаб);
// Вот собственно и само оформление ячейки
ТабДок.Область(ОбластьОформления.Верх, ОбластьОформления.Лево, ОбластьОформления.Низ, ОбластьОформления.Лево).ЦветФона = WebЦвета.Красный;
Код 1C v 8.х //Пример изменения цвета текста при выводе данных в табличный документ
Таб.ВывестиСекцию("Контрагент");
// Изменим Текст ячейки, имя которой заранее задали как "ТекстОСостоянии"
Таб.Область("ТекстОСостоянии").Текст = "Хорошо ";
// В зависимости от условия изменим Цвет Текста
Если Раз<0 Тогда
Таб.Область(Таб.ВысотаТаблицы(),9,Таб.ВысотаТаблицы(),9).ЦветТекста(255,0,0);
ИначеЕсли Раз>0 Тогда
Таб.Область(Таб.ВысотаТаблицы(),9,Таб.ВысотаТаблицы(),9).ЦветТекста(0,0,255);
КонецЕсли;
Для того, чтобы появилась возможность использовать свойство "Значение", необходимо явно присвоить свойству ячейки "СодержитЗначение" значение Истина или установить флажок "Содержит значение" в палитре свойств.
Для ячейки, у которой установлен признак "СодержитЗначение", можно задать тип значения, размещаемого в ячейке.
Следующий фрагмент демонстрирует, как можно управлять этими свойствами из встроенного языка://задаем нужный тип с помощью объекта "ОписаниеТипов"
Код 1C v 8.х МассивБулево = Новый Массив;
МассивБулево.Добавить(Тип("Булево"));
ОписаниеТиповБулево = Новый ОписаниеТипов(МассивБулево);
//...
ПолеТабДок = ЭлементыФормы.тдПолеТабличногоДокумента;
ПолеТабДок.Область("R3C3").СодержитЗначение = Истина; //указываем, что в ячейке будет значение
ПолеТабДок.Область("R3C3").ТипЗначения = ОписаниеТиповБулево; //указываем тип значения
ПолеТабДок.Область("R3C3").Значение = СпрНоменклатура.Услуга; //значение, типа "Булево" из справочника
Для ячейки табличного документа можно задавать формат вывода данных. Для этого используется свойство "Формат", которое содержит форматную строку. Приемы работы с форматной строкой полностью совпадают с функцией Формат()
Код 1C v 8.х ПолеТабДок = ЭлементыФормы.тдПолеТабличногоДокумента;
ПолеТабДок.Область("R4C3").ТипЗначения = ОписаниеТиповДата; //указываем тип, ранее заданный для Даты
ПолеТабДок.Область("R4C3").Значение = ТекущаяДата();
//указываем форматную строку
//будет выглядеть как "[031120-2315]-", если текущая дата '20-11-2003 23:15:00')
ПолеТабДок.Область("R4C3").Формат = "ДФ=[ггММдд-ЧЧмм]-";
Элемент управления в табличном документе
Для ячейки, у которой установлен признак "СодержитЗначение", можно также задать элемент управления, который будет использоваться для редактирования этого значения.
Элемент управления можно назначить через палитру свойств или из встроенного языка с помощью метода "УстановитьЭлементУправления()". Чтобы проверить в программе, установлен ли элемент управления для конкретной ячейки, можно использовать свойство "ЭлементУправления", которое возвращает элемент управления, назначенный для ячейки.
Элементы управления, встроенные в ячейку, отображаются только при входе в режим редактирования значения. На приведенном ниже рисунке редактируемая ячейка обведена овалом и в ней отображается флажок:
Ниже показан пример установки элемента управления типа "Флажок" из встроенного языка://задаем нужный тип с помощью объекта "ОписаниеТипов"
Код 1C v 8.х МассивБулево = Новый Массив;
МассивБулево.Добавить(Тип("Булево"));
ОписаниеТиповБулево = Новый ОписаниеТипов(МассивБулево);
...
ПолеТабДок = ЭлементыФормы.тдПолеТабличногоДокумента;
ПолеТабДок.Область("R5C3").СодержитЗначение = Истина; //указываем, что в ячейке будет значение
ПолеТабДок.Область("R5C3").ТипЗначения = ОписаниеТиповБулево; //указываем ранее заданный тип
ПолеТабДок.Область("R5C3").Значение = СпрНоменклатура.Услуга; //значение, типа "Булево" из справочника
//а теперь указываем, что в ячейке будет отображаться флажок
ПолеТабДок.Область("R5C3").УстановитьЭлементУправления(Тип("Флажок"));
Для элементов управления, расположенных в табличном документе, расширяется набор свойств, методов и событий:
Разберем самые важные свойства и методы:
Свойство "ВстроенВЯчейку" имеет тип "булево" и говорит о том, что элемент управления встраивается в ячейку или просто привязывается к ней, о чем было рассказано выше.
Свойство "Видимость" позволяет показать или скрыть элемент управления.
Свойство "Значение" предоставляет доступ к значению, которое редактируется в элементе управления. Оно используется только для элементов управления, поддерживающих связь с данными.
Метод "Расположить" позволяет разместить элемент управления в конкретной области ячеек табличного документа. Именно этот метод был использован в вышеприведенном примере.
Код 1C v 8.х ПолеТабДок = ЭлементыФормы.тдПолеТабличногоДокумента;
ПолеТабДок.Область("R4C3").Защита = Истина;
Категория:
Табличный документ Обмен данными с сайтом используя формат JSON в 1С Формат JSON в 1С до версии 8.3.6 не реализован, но нижет я приведу примеры функций которые можно использовать для полноценной работы JSON в 1С предыдущий версий.
JSON (JavaScript Object Notation) это текстовый формат обмена данными, широко используемый в веб-приложениях. По сравнению с XML он является более лаконичным и занимает меньше места. Кроме этого все браузеры имеют встроенные средства для работы с JSON.
Необходимость работы с этим форматом на уровне платформы обусловлена не только тем, что это «модный современный» формат, который прикладные решения 1С:Предприятия сами по себе могут использовать для интеграции со сторонними приложениями. Другая причина заключается ещё и в том, что JSON активно используется в HTTP интерфейсах. А в 1С:Предприятии как раз есть такие механизмы, в которых хочется использовать этот формат. Это REST интерфейс приложения, автоматически генерируемый платформой, и HTTP-сервисы, которые вы можете создавать самостоятельно.
В платформе с версии 8.3.6: Потоковое чтение и запись JSON:
Объекты потоковой работы - это общие объекты ЧтениеJSON и ЗаписьJSON. Они последовательно читают JSON из файла или строки, или последовательно записывают JSON в файл или строку. Таким образом, чтение и запись JSON происходят без формирования всего документа в памяти.
В качестве иллюстрации потокового чтения JSON можно привести следующий пример:
Код 1C v 8.3 // Пример чтения JSON.
ЧтениеJSON = Новый ЧтениеJSON;
// Либо открыть файл, из которого будет выполняться чтение, // либо установить строку, из которой будет выполняться чтение.
ЧтениеJSON.ОткрытьФайл("ИмяФайла");
//ЧтениеJSON.УстановитьСтроку("СтрокаJSON");
Пока ЧтениеJSON.Прочитать() Цикл
TипJSON = ЧтениеJSON.ТипТекущегоЗначения;
Если TипJSON = ТипЗначенияJSON.Число ИЛИ TипJSON = ТипЗначенияJSON.Строка ИЛИ TипJSON = ТипЗначенияJSON.Булево ИЛИ TипJSON = ТипЗначенияJSON.Null Тогда
// Обработать значение
Значение = ЧтениеJSON.ТекущееЗначение;
ИначеЕсли ТипJSON = ТипЗначенияJSON.Комментарий Тогда
// Обработать комментарий
Комментарий = ЧтениеJSON.ТекущееЗначение;
ИначеЕсли TипJSON = ТипЗначенияJSON.ИмяСвойства Тогда
// Обработать имя свойства
ИмяСвойства = ЧтениеJSON.ТекущееЗначение;
ИначеЕсли TипJSON = ТипЗначенияJSON.НачалоМассива ИЛИ TипJSON = ТипЗначенияJSON.КонецМассива ИЛИ TипJSON = ТипЗначенияJSON.НачалоОбъекта ИЛИ TипJSON = ТипЗначенияJSON.КонецОбъекта ИЛИ TипJSON = ТипЗначенияJSON.Ничего Тогда
// Обработать начало/коней массива/объекта или отсутствие данных, // ТекущееЗначение читать не нужно.
КонеиЕсли;
КокецЦикла;
ЧтениеJSON.Закрыть();
// При записи JSON вы самостоятельно формируете его структуру. Чтобы «подстраховать» вас от ошибок, объект ЗаписьJSON автоматически проверяет правильность записываемой структуры.
// Для увеличения скорости работы эту проверку можно отключить. В примере ниже это строка:
ЗаписьJSON.ПроверятьСтруктуру = Ложь;
// Также при записи вы можете управлять некоторыми параметрами формируемого текста, например использованием двойных кавычек, переносом строк, символами отступа и экранированием символов.
// В примере ниже для форматирования текста используется символ табуляции:
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON( , Символы.Таб) ;
ЗаписьJSON.ОткрытьФайл("ИмяФайла", , , ПараметрыЗаписиJSON);
// Потоковая запись JSON может выглядеть следующим образом. Записывается массив из четырёх элементов. Три из них примитивного типа, а четвёртый элемент - это объект с двумя свойствами:
// Пример записи JSON. ЗаписьJSON = Новый ЗаписьJSON;
// Для увеличения скорости работы можно отключить автоматическую проверку // правильности структуры записываемого документа JSON. ЗаписьиЗСЖ.ПроверятьСтруктуру = Ложь;
// Для красоты результирующего текста можно увеличить "лесенку".
// Стандартный отступ - 1 пробел.
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON( , Символы.Таб);
// Либо открыть файл, в который будет выполнена запись,
// либо указать, что запись будет выполнена в строку, которую вернет метод Закрыть().
ЗаписьJSON.ОткрытьФайл("ИмяФайла", , , ПараметрыЗаписиJSON);
//ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
// Записать массив.
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("СвойствоТипаМассив");
ЗаписьJSON.ЗаписатьНачалоМассива();
// Первый элемент массива - Строка. ЗаписьJSON.ЗаписатьЗначение("Значение строка");
// Второй элемент массива - Число. ЗаписьJSON.ЗаписатьЗначение(12.345, Истина);
// Третий элемент массива - Булево. ЗаписьJSON-ЗаписатьЗначение(Истина);
// Четвертый элемент массива - объект с двумя свойствами. ЗаписьJSON.ЗаписатьНачалоОбъекта();
// Первое свойство объекта - Строка
ЗаписьJSON.ЗаписатьИмяСвойства("СвойствоТипаСтрока");
ЗаписьJSON.ЗаписатьЗначение("Значение строка");
// Второе свойство объекта - Неопределено
ЗаписьJSON.ЗаписатьИмяСвойства("СвойствоТипаНеопределено");
ЗаписьJSON.ЗаписатьЗначение(Неопределено);
ЗаписьJSON.ЗаписатьКонецОбъекта();
Запись JSON. ЗаписатьКонецМассива () ;
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьJSON.Закрыть();
//CTpoKaJSON = ЗаписьJSON.Закрыть();
Результат такой записи:
Код 1C v 8.х
{
"СвойствоТипаМассив": [
"Значение строка",
1.2345E1,
true,
{
"СвойствоТипаСтрока": "Значение строка",
"СвойствоТипаНеопределено": null
}
]
}
Сериализация примитивных типов и коллекций в JSON
Вторая группа средств работы с JSON хороша тем, что избавляет вас от рутинной работы по чтению/записи каждого отдельного значения или свойства. При чтении документы JSON отображаются в фиксированный набор типов платформы: Строка, Число, Булево, Неопределено, Массив, ФиксированныйМассив, Структура, ФиксированнаяСтруктура, Соответствие, Дата. Соответственно, в обратную сторону, композиция объектов этих типов позволяет сформировать в памяти и быстро записать в файл структуру JSON. Таким образом, чтение и запись небольшого объема JSON заранее известной структуры можно производить немногими строчками кода.
Основное назначение этих средств мы видим в обмене информацией с внешними системами, чтении конфигурационных файлов в формате JSON.
Сериализацию вы можете выполнять с помощью методов глобального контекста ПрочитатьJSON() и ЗаписатьJSON(). Они работают в связке с объектами ЧтениеJSON и ЗаписьJSON.
В качестве примера десериализации JSON можно рассмотреть чтение массива из двух объектов:
Код 1C v 8.3 // В качестве примера десериализации JSON можно рассмотреть чтение массива из двух объектов:
[
{
"имя": "Anton",
"фамилия": "Иванов",
"возраст": 25
},
{
"имя": "Ирина",
"фамилия": "Иванова",
"возраст": 20
}
]
// Код 1С:Предприятия, выполняющий десериализацию, может выглядеть следующим образом:
// Пример чтения JSON.
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.ОткрытьФайл("ИмяФайла");
Сотрудники = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Для каждого Сотрудник из Сотрудники Цикл
// Обработать данные сотрудника.
ИмяСотрудника = Сотрудник.имя; ФамилияСотрудника = Сотрудник.фамилия; ВозрастСотрудника = Сотрудник.возраст;
КонецЦикла;
// А пример сериализации (записи) в JSON может выглядеть так:
// Пример записи JSON
Структура = Новый Структура;
Вставить("Фамилия","Иванов");
Зставить("Имя", "Иван");
Вставить("Отчество", "Иванович");
Зставить("Возраст", 40) ;
Зставить("Женат", Истина);
Телефоны = Новый Массив;
Телефоны.Добавить("8-999-999-99-90") ;
Телефоны.Добавить("8-999-999-99-91") ;
Структура.Вставить("Телефоны", Телефены);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл("ИмяФайла", , , Новый ПapaмeтpыЗaпиcиJS0N( , Символы.Таб) ) ;
ЗаписатьJSON(ЗаписьJSON, Структура);
ЗаписьJSON.Закрыть();
// Результат записи:
{
"Фамилия": "Иванов",
"Имя": "Иван",
"Отчество": "Иванович",
"Возраст": 40,
"Женат": true,
"Телефоны": [
"8-999-999-99-90",
"8-999-999-99-91"
]
}
Подробнее вы можете посмотреть здесь
В платформе с версии 8.3.7: Полностью автоматизировали работу с JSON и реализовали в платформе третью группу средств. Они позволяют сериализовать в JSON прикладные типы 1С:Предприятия: ссылки, объекты, наборы записей и вообще любые типы, для которых поддерживается XDTO сериализация. Конечно же, мы обеспечили и обратную операцию - десериализацию. Зачем это нужно!?
Прежде всего, и в основном, XDTO сериализацию в JSON мы рекомендуем использовать при обмене данными между двумя прикладными решениями 1С:Предприятия. По сравнению с XML формат JSON более компактный, сериализация/десериализация в/из JSON выполняется быстрее. Кроме этого мы предприняли дополнительные меры для того, чтобы сократить объём передаваемых данных.
Кроме обмена между приложениями 1С:Предприятия этот механизм можно использовать и для обмена с внешними системами, готовыми принимать типы данных 1С:Предприятия. Например, XDTO сериализацию в JSON можно использовать для организации собственного HTTP интерфейса прикладного решения. Сервис на платформе 1С:Предприятия будет формировать ответ в памяти в виде строки JSON. А затем передавать её при помощи объекта HTTPСервисОтвет. Реализованный нами механизм сериализации полностью соответствует стандарту JSON. Поэтому внешняя система не должна испытывать каких-либо трудностей с десериализацией.
Использование XDTO сериализации в JSON для других задач видится нам маловероятным. Потому что если внешняя система не готова работать с прикладными типами 1С:Предприятия, то зачем их ей передавать? А если предполагается обмениваться только примитивными типами и коллекциями, то для этой задачи хорошо подходят методы ПрочитатьJSON() и ЗаписатьJSON(). Подробнее здесь
ДО платформы версии 8.3.6, т.е. 8.3.5 и ниже: На HelpF уже есть статья где описан пример: Работа с форматом JSON в 1С но не приведены функции, вот они:
Код 1C v 8.х Функция ПреобразоватьвСистему(Число10,система) Экспорт
Если система > 36 или система < 2 тогда
Сообщить("Выбранная система исчисления не поддерживается");
Возврат -1;
КонецЕсли;
СтрокаЗначений = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
СтрокаСистема = "";
Пока Число10 > 0 цикл
РезДеления = Число10/система;
ЧислоСистема = цел(РезДеления);
остатокОтДеления = Число10 - система*(ЧислоСистема);
СтрокаСистема = сред(СтрокаЗначений,остатокОтДеления+1,1)+ СтрокаСистема;
Число10 = ?(ЧислоСистема=0,0,РезДеления);
КонецЦикла;
Нечётное = стрДлина(СтрокаСистема) - цел(стрДлина(СтрокаСистема)/2)*2;
Если Нечётное тогда
СтрокаСистема = "0"+СтрокаСистема;
КонецЕсли;
Возврат СтрокаСистема;
КонецФункции
Функция URLEncode(стр) Экспорт
Длина=СтрДлина(Стр);
Итог="";
Для Н=1 По Длина Цикл
Знак=Сред(Стр,Н,1);
Код=КодСимвола(Знак);
если ((Знак>="a")и(Знак<="z")) или
((Знак>="A")и(Знак<="Z")) или
((Знак>="0")и(Знак<="9")) тогда
Итог=Итог+Знак;
Иначе
Если (Код>=КодСимвола("А"))И(Код<=КодСимвола("п")) Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(208,16)+"%"+ПреобразоватьвСистему(144+Код-КодСимвола("А"),16);
ИначеЕсли (Код>=КодСимвола("р"))И(Код<=КодСимвола("я")) Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(209,16)+"%"+ПреобразоватьвСистему(128+Код-КодСимвола("р"),16);
ИначеЕсли (Знак="ё") Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(209,16)+"%"+ПреобразоватьвСистему(145,16);
ИначеЕсли (Знак="Ё") Тогда
Итог=Итог+"%"+ПреобразоватьвСистему(208,16)+"%"+ПреобразоватьвСистему(129,16);
Иначе
Итог=Итог+"%"+ПреобразоватьвСистему(Код,16);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Итог;
КонецФункции
Функция СформироватьСтрокуJSONИзМассива(Объект)
СтрокаJSON = "[";
Для каждого Элемент Из Объект Цикл
Если ТипЗнч(Элемент) = Тип("Строка") Тогда
СтрокаJSON = СтрокаJSON + """" + Элемент + """";
ИначеЕсли ТипЗнч(Элемент) = Тип("Число") Тогда
СтрокаJSON = СтрокаJSON + СтрЗаменить(Строка(Элемент), Символы.НПП, "");
ИначеЕсли ТипЗнч(Элемент) = Тип("Булево") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент, "БЛ=false; БИ=true");
ИначеЕсли ТипЗнч(Элемент) = Тип("Дата") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент - Дата(1970,1,1,1,0,0), "ЧГ=0");
ИначеЕсли ТипЗнч(Элемент) = Тип("Массив") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент);
ИначеЕсли ТипЗнч(Элемент) = Тип("Структура") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент);
ИначеЕсли ТипЗнч(Элемент) = Тип("ТаблицаЗначений") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент);
Иначе
СтрокаJSON = СтрокаJSON + """" + URLEncode(Строка(Элемент)) + """";
КонецЕсли;
СтрокаJSON = СтрокаJSON + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "]";
КонецФункции
Функция СформироватьСтрокуJSONИзСтруктуры(Объект)
СтрокаJSON = "{";
Для каждого Элемент Из Объект Цикл
Если Элемент.Значение = "" Тогда
Продолжить;
КонецЕсли;
СтрокаJSON = СтрокаJSON + """" + Элемент.Ключ + """" + ":";
Если ТипЗнч(Элемент.Значение) = Тип("Строка") Тогда
СтрокаJSON = СтрокаJSON + """" + Элемент.Значение + """";
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Число") Тогда
СтрокаJSON = СтрокаJSON + СтрЗаменить(Строка(Элемент.Значение), Символы.НПП, "");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Булево") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент.Значение, "БЛ=false; БИ=true");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Дата") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент.Значение - Дата(1970,1,1,1,0,0), "ЧГ=0");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Массив") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Структура") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("ТаблицаЗначений") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
Иначе
СтрокаJSON = СтрокаJSON + """" + URLEncode(Строка(Элемент.Значение)) + """";
КонецЕсли;
СтрокаJSON = СтрокаJSON + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "}";
КонецФункции
Функция СформироватьСтрокуJSON(Объект) Экспорт
СтрокаJSON = "";
Если ТипЗнч(Объект) = Тип("Массив") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзМассива(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("Структура") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("ТаблицаЗначений") Тогда
СоставСтруктуры = "";
Для каждого Колонка Из Объект.Колонки Цикл
СоставСтруктуры = СоставСтруктуры + ?(ЗначениеЗаполнено(СоставСтруктуры), ",", "") + Колонка.Имя;
КонецЦикла;
МассивСтрок = Новый Массив;
Для каждого Строка Из Объект Цикл
СтруктураКолонок = Новый Структура(СоставСтруктуры);
ЗаполнитьЗначенияСвойств(СтруктураКолонок, Строка);
МассивСтрок.Добавить(СтруктураКолонок);
КонецЦикла;
СтрокаJSON = СформироватьСтрокуJSONИзМассива(МассивСтрок);
КонецЕсли;
Возврат СтрокаJSON;
КонецФункции
Процедура ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, ТипДанных)
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
НомерЗначения = 0;
Пока ТекстJSON <> "" Цикл
ПервыйСимвол = Лев(ТекстJSON, 1);
Если ПервыйСимвол = "{" Тогда
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
ИначеЕсли ТипДанных = "Массив" Тогда
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "[" Тогда
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
Иначе
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "}" И ТипДанных = "Структура" Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
ИначеЕсли ПервыйСимвол = "]" И ТипДанных = "Массив" Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
Иначе
Если ТипДанных = "Структура" Тогда
Поз = Найти(ТекстJSON, ":");
Если Поз = 0 Тогда
Прервать;
КонецЕсли;
ИмяЗначения = СокрЛП(Лев(ТекстJSON, Поз-1));
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз+1));
Если Лев(ТекстJSON, 1) = "{" Тогда
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Иначе
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз-1);
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
КонецЕсли;
Результат.Вставить(ИмяЗначения, Значение);
ИначеЕсли ТипДанных = "Массив" Тогда
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз-1);
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
Результат.Добавить(Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЗаполнитьСтруктуруИзОтветаJSON(Знач ТекстJSON) Экспорт
Результат = Новый Структура;
ТекстJSON = СтрЗаменить(ТекстJSON, "\""", """");
ТекстJSON = СтрЗаменить(ТекстJSON, """", "");
Если Лев(ТекстJSON, 1) = "{" Тогда
ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
МассивДанных = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(МассивДанных, ТекстJSON, "Массив");
Результат.Вставить("Значение", МассивДанных);
КонецЕсли;
Возврат Результат;
КонецФункции
Примеры их использования:
Код 1C v 8.х ////////////////////////////////////////////////////////
// преобразование простой структуры
Данные = Новый Структура("server,user,hash",
10234, 3745, "8263ad83ce");
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// {"server":"10234","user":"3745","hash":"8263ad83ce"}
////////////////////////////////////////////////////////
// преобразования массива
Данные = Новый Массив;
Данные.Добавить("Nissan");
Данные.Добавить("Ford");
Данные.Добавить("Audi");
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// ["Nissan","Ford","Audi"]
////////////////////////////////////////////////////////
// преобразование сложной структуры
Данные = Новый Структура;
Данные.Добавить("server", 10234);
Данные.Добавить("users", Новый Массив);
Данные.Добавить("hash", "8263ad83ce");
Данные.users.Добавить(3745);
Данные.users.Добавить(7462);
Данные.users.Добавить(2374);
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// {"server":"10234","users":["3745","7462","2374"],"hash":"8263ad83ce"}
////////////////////////////////////////////////////////
// еще один пример массива
Данные = Новый Структура;
Данные.Вставить("server", 10234);
Данные.Вставить("users", Новый Массив);
Данные.users.Добавить(Новый Структура("id,name", 3745, "Jack"));
Данные.users.Добавить(Новый Структура("id,name", 7246, "Nick"));
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// {"server":"10234","users":[{"id":"3745","name":"Jack"},{"id":"7462","name":"Nick"}>
////////////////////////////////////////////////////////
// преобразование таблицы значений
ТаблПользователей = Новый ТаблицаЗначений;
ТаблПользователей.Колонки.Добавить("id");
ТаблПользователей.Колонки.Добавить("name");
НоваяСтрока = ТаблПользователей.Добавить();
НоваяСтрока.id = 3276;
НоваяСтрока.name = "Jack";
НоваяСтрока = ТаблПользователей.Добавить();
НоваяСтрока.id = 3276;
НоваяСтрока.name = "Nick";
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Данные);
// результатом будет строка
// [{"id":"3745","name":"Jack"},{"id":"7462","name":"Nick"}]
Пишите комменты
Категория:
Работа с Интернет, Почтой (Mail), FTP Как передать таблицу значений с сервера на клиент? Многие спрашиваю, как передать тз с сервера на клиент - ниже несколько вариантов как это можно реализовать:
Через ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр
Код 1C v 8.3 &НаКлиенте
Процедура ПолучитьТаблицу НаСервер(Команд а)
ТЗВСтроке = ПолучитьТЗНаСер вере();
ТЗ = ЗначениеИзСтрокиВнутр(ТЗВСтрок е);
КонецПроцедуры
// Функция получает данные на сервере
&НаСервере
Функция ПолучитьТЗНаСер вере()
// Для примера сформируем ТЗ с данными
ТЗ = ЗаполнитьТЗДанными();
Возврат ЗначениеВСтрокуВнутр(ТЗ);
КонецФункции
Через реквизит Формы
Код 1C v 8.3 // Создаем реквизит формы "ВремТабЗнач" с типом данных: Таблица значений
// Ревкизит будет использоваться для передачи данных с сервера на клиент.
&НаСервере
Функция ПолучитьТЧ(ОбъектСсылка,ИмяТЧ)
ЗначениеОбъекта = ОбъектСсылка.ПолучитьОбъект();
ТабРез = ЗначениеОбъекта[ИмяТЧ].выгрузить();
МассивДобавляемыхРеквизитов = Новый Массив;
МассивУдаляемыхРеквизитов = Новый Массив;
МассивКолонок = Новый Массив;
ИдКоллекции="ВремТабЗнач";
КоллФормы=РеквизитФормыВЗначение(ИдКоллекции);
Для каждого ТекКол из КоллФормы.Колонки Цикл
МассивУдаляемыхРеквизитов.Добавить(ИдКоллекции+"."+ТекКол.Имя);
КонецЦикла;
Для каждого ТекКол из ТабРез.Колонки Цикл
МассивДобавляемыхРеквизитов.Добавить(
Новый РеквизитФормы(ТекКол.Имя,ТекКол.ТипЗначения,ИдКоллекции));
МассивКолонок.Добавить(ТекКол.Имя);
КонецЦикла;
// Добавим новые, удалим старые колонки
ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов,МассивУдаляемыхРеквизитов);
// Поместим значение в реквизит формы
ЗначениеВРеквизитФормы(ТабРез,ИдКоллекции);
// вернем массив колонок в обрабатываемой ТЗ, например для более простого перебора
Возврат МассивКолонок;
КонецФункции
Через Временное хранилище
Код 1C v 8.3
АдресХранилища = ПоместитьВоВременноеХранилище(МассивДанных,ЭтаФорма.УникальныйИдентификатор);
ПротоколПереноса = ПолучитьИзВременногоХранилища(АдресХранилища);
Через обычный возврат
Код 1C v 8.2 УП &НаКлиенте
Процедура ПолучитьТаблицуНаСервер(Команда)
ТЗ = ЗаполнитьТЗДанными();
КонецПроцедуры
//Функция заполняет ТЗ
&НаСервере
Функция ЗаполнитьТЗДанными()
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Поле1");
ТЗ.Колонки.Добавить("Поле2");
ТЗ.Колонки.Добавить("Поле3");
ТЗ.Колонки.Добавить("Поле4");
ТЗ.Колонки.Добавить("Поле5");
Для i = 1 По 3 Цикл
НоваяСтр = ТЗ.Добавить();
НоваяСтр.Поле1 = i;
НоваяСтр.Поле2 = 2*i;
НоваяСтр.Поле3 = 3*i;
НоваяСтр.Поле4 = 4*i;
НоваяСтр.Поле5 = 5*i;
КонецЦикла;
Возврат ТЗ;
КонецФункции
Пробуйте и пишите в комментариях как делаете это Вы
Категория:
Управляемое приложение, Тонкий клиент Сохранение реквизитов и табличных частей объектов в XML Сохранение производится процедурой СохранитьРеквизитыИТабличныеЧасти. В качестве параметров она принимает сохраняемый объект и имя файла. Ссылочные реквизиты сохраняются в виде GUID.
Код 1C v 8.х Процедура СохранитьРеквизитыИТабличныеЧасти (Объект, ИмяФайлаXML=Неопределено) Экспорт
ФайлXML = Новый ЗаписьXML;
ФайлXML.ОткрытьФайл(ИмяФайлаXML);
ФайлXML.ЗаписатьОбъявлениеXML();
ФайлXML.ЗаписатьНачалоЭлемента("Root");
ФайлXML.ЗаписатьАтрибут("Объект",Объект.Метаданные().Имя);
//Сохраняем реквизиты
Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл
ФайлXML.ЗаписатьНачалоЭлемента("Реквизит");
ФайлXML.ЗаписатьАтрибут("Имя", Реквизит.Имя);
ТипЗначения = ТипЗнч(Объект[Реквизит.Имя]);
Если Не ТипЗначения = Тип("Неопределено") Тогда
ФайлXML.ЗаписатьАтрибут("ИмяТипа", XMLТип(ТипЗначения).ИмяТипа);
ФайлXML.ЗаписатьАтрибут("URI", XMLТип(ТипЗначения).URIПространстваИмен);
КонецЕсли;
ФайлXML.ЗаписатьТекст(XMLСтрока(Объект[Реквизит.Имя]));
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
//Сохраняем табличные части
Для Каждого ТЧ из Объект.Метаданные().ТабличныеЧасти Цикл
ФайлXML.ЗаписатьНачалоЭлемента("ТабличнаяЧасть");
ФайлXML.ЗаписатьАтрибут("Имя", ТЧ.Имя);
Для Каждого СтрокаТЧ из Объект[ТЧ.Имя] Цикл
ФайлXML.ЗаписатьНачалоЭлемента("ЭлементКоллекции");
Для Каждого РеквизитТЧ Из ТЧ.Реквизиты Цикл
ФайлXML.ЗаписатьНачалоЭлемента("Реквизит");
ФайлXML.ЗаписатьАтрибут("Имя", РеквизитТЧ.Имя);
ТипЗначения = ТипЗнч(СтрокаТЧ[РеквизитТЧ.Имя]);
Если Не ТипЗначения = Тип("Неопределено") Тогда
ФайлXML.ЗаписатьАтрибут("ИмяТипа", XMLТип(ТипЗначения).ИмяТипа);
ФайлXML.ЗаписатьАтрибут("URI", XMLТип(ТипЗначения).URIПространстваИмен);
КонецЕсли;
ФайлXML.ЗаписатьТекст(XMLСтрока(СтрокаТЧ[РеквизитТЧ.Имя]));
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
Если Не ФайлXML=Null Тогда
ФайлXML.ЗаписатьКонецЭлемента();
ФайлXML.Закрыть();
КонецЕсли;
КонецПроцедуры
За чтение объекта отвечают процедуры ЗагрузитьРеквизитыИТабличныеЧасти и ЗагрузитьОбъектРекурсивно. Чтобы прочитать объект вызывается первая, ей передаются объект, который необходимо заполнить, и имя файла. Вторая является вспомогательной.
Код 1C v 8.х Процедура ЗагрузитьРеквизитыИТабличныеЧасти(Объект, ИмяФайлаXML=Неопределено) Экспорт
Если Не ИмяФайлаXML = Неопределено Тогда
ФайлXML = Новый ЧтениеXML;
ФайлXML.ОткрытьФайл(ИмяФайлаXML);
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ЗагрузитьОбъектРекурсивно(ФайлXML, Объект, ФайлXML.Имя);
КонецЕсли
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ЗагрузитьОбъектРекурсивно(ФайлXML, Объект, знач ИмяУзла)
ИмяТипа = "";
ПространствоИмен = "";
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = "ИмяТипа" Тогда
ИмяТипа = ФайлXML.Значение;
ИначеЕсли ФайлXML.Имя = "URI" Тогда
ПространствоИмен = ФайлXML.Значение;
КонецЕсли;
КонецЦикла;
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ФайлXML.Имя = ИмяУзла Тогда
Возврат;
ИначеЕсли ФайлXML.ТипУзла = ТипУзлаXML.Текст Тогда
ТипОбъекта = ИзXMLТипа(ИмяТипа, ПространствоИмен);
Если НЕ ТипОбъекта = Неопределено тогда
Объект = XMLЗначение(ТипОбъекта, ФайлXML.Значение);
КонецЕсли;
ИначеЕсли ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяТекУзла = ФайлXML.Имя;
Если ФайлXML.Имя = "ЭлементКоллекции" Тогда
ЗагрузитьОбъектРекурсивно(ФайлXML, Объект.Добавить(), ИмяТекУзла);
Иначе
Если ФайлXML.ПрочитатьАтрибут() Тогда
ЗагрузитьОбъектРекурсивно(ФайлXML, Объект[ФайлXML.Значение], ИмяТекУзла);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В приложенном файле -
Скачивать файлы может только зарегистрированный пользователь! - демонстрационная обработка, позволяющая сохранить ссылочный объект БД в файл и заполнить объект из файла. Заполняемый объект должен быть того же типа, что и сохраненный, а также он должен быть предварительно создан, сохранен в ИБ и выбран в поле "Ссылка".
Категория:
Документы Форма ~ Программное добавление элементов на форму ЭлементыФормы (Controls) . Добавить (Add) - Добавляет элемент управления на форму.
Синтаксис: Код 1C v 8.х Добавить(<Тип>, <Имя>, <Видимость>, <ПоместитьНа>)
Параметры:
<Тип> (обязательный)
Тип: Тип. Тип добавляемого элемента управления:
Индикатор; ПолеКалендаря; Кнопка; КоманднаяПанель; Надпись; Панель; Переключатель; ПолеТабличногоДокумента; ПолеHTMLДокумента; ПолеТекстовогоДокумента; ПолеВвода; ПолеВыбора; ПолеСписка; ПолеКартинки; ПолосаРегулирования; Разделитель; РамкаГруппы; ТабличноеПоле; Флажок; ПолеГрафическойСхемы; ПолеГеографическойСхемы.
<Имя> (обязательный)
Тип: Строка. Имя создаваемого элемента управления. Имя должно быть указано в соответсвии с правилами написания имен системы 1С:Предприятие 8. В противном случае выполнение метода вызовет исключение.
<Видимость> (необязательный)
Тип: Булево. Определяет, создавать новый элемент управления формы видимым или нет. Истина - элемент создается видимым.
Значение по умолчанию: Истина
<ПоместитьНа> (необязательный)
Тип: Панель; ПолеТабличногоДокумента. Определяет, какой панели формы или какому табличному документу принадлежит создаваемый элемент. Если указана панель, то добавляемый элемент размещается на текущей странице панели. Если не указан, создаваемый элемент будет принадлежать непосредственно форме.
Код 1C v 8.х
// Расположим на странице табличное поле
ПолеРегистра = ЭлементыФормы.Добавить(Тип("ТабличноеПоле"),
СтрокаТаблицы.Имя,
Истина,
ЭлементыФормы.ОсновнаяПанель);
ПолеРегистра.Данные = "ДокументОбъект.Движения." + СтрокаТаблицы.Имя;
Если НЕ ЭтоНовый() Тогда
ПолеРегистра.Значение.Прочитать();
КонецЕсли;
ПолеРегистра.Верх = 30;
ПолеРегистра.Лево = 6;
ПолеРегистра.Ширина = ЭлементыФормы.ОсновнаяПанель.Ширина - 14;
ПолеРегистра.Высота = ЭлементыФормы.ОсновнаяПанель.Высота - 56;
ПолеРегистра.ТолькоПросмотр = Ложь;
ПолеРегистра.ИзменятьПорядокСтрок = Истина;
ПолеРегистра.ИзменятьСоставСтрок = Истина;
ПолеРегистра.УстановитьПривязку(ГраницаЭлементаУправления.Верх,
КоманднаяПанельРегистра,
ГраницаЭлементаУправления.Низ);
ПолеРегистра.УстановитьПривязку(ГраницаЭлементаУправления.Низ,
ЭлементыФормы.ОсновнаяПанель,
ГраницаЭлементаУправления.Низ);
ПолеРегистра.УстановитьПривязку(ГраницаЭлементаУправления.Право,
ЭлементыФормы.ОсновнаяПанель,
ГраницаЭлементаУправления.Право);
ПолеРегистра.СоздатьКолонки();
Если Метаданные.РегистрыНакопления[СтрокаТаблицы.Имя].ВидРегистра = Метаданные.СвойстваОбъектов.ВидРегистраНакопления.Остатки Тогда
КолонкаВидДвижения = ПолеРегистра.Колонки.Вставить(1, "Вид движения");
КолонкаВидДвижения.Имя = "ВидДвиженияРегистраНакопления";
КолонкаВидДвижения.УстановитьЭлементУправления(Тип("ПолеВвода"));
КолонкаВидДвижения.Данные = "ВидДвижения";
КолонкаВидДвижения.ЭлементУправления.КнопкаВыбора = Истина;
КолонкаВидДвижения.ЭлементУправления.ВыбиратьТип = Ложь;
КонецЕсли;
ПолеРегистра.Колонки.Регистратор.Видимость = Ложь;
ПолеРегистра.Колонки.Период.Видимость = Ложь;
ПолеРегистра.Колонки.НомерСтроки.Видимость = Ложь;
// Поле ввода
ПолеВвода = ЭлементыФормы.Добавить(Тип("ПолеВвода"), "ПолеВвода", Истина);
ПолеВвода.Верх = Надпись.Верх + Надпись.Высота + 5;
ПолеВвода.Лево = ЭлементыФормы.Переключатель1.Лево;
ПолеВвода.Ширина = ЭлементыФормы.Переключатель1.Ширина;
ПолеВвода.Высота = ЭлементыФормы.Переключатель1.Высота;
ПолеВвода.Доступность = Ложь;
// установка привязок
ПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Низ, ПолеВвода, ГраницаЭлементаУправления.Верх);
ПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Лево, ЭтаФорма.Панель, ГраницаЭлементаУправления.Лево);
ПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Право, ЭтаФорма.Панель, ГраницаЭлементаУправления.Право);
//Надпись и поле ввода
ЭлементНадпись = ЭлементыФормы.Добавить(Тип("Надпись"), "Надпись"+ИмяЭлемента, Истина, ЭлементыФормы.ПанельПодбор);
ЭлементНадпись.Заголовок = Синоним + ":";
ЭлементНадпись.Лево = 6;
ЭлементНадпись.Верх = ВерхЭлемента + 6;
ЭлементНадпись.Высота = 19;
ЭлементНадпись.Ширина = 160;
ЭлементНадпись.ЦветФона = ЦветаСтиля.ФонЭпицентра;
ЭлементПолеВвода = ЭлементыФормы.Добавить(Тип("ПолеВвода"), ИмяЭлемента, Истина, ЭлементыФормы.ПанельПодбор);
ЭлементПолеВвода.ТипЗначения = Параметр.Тип;
ЭлементПолеВвода.Верх = ЭлементНадпись.Верх;
ЭлементПолеВвода.Лево = ЭлементНадпись.Лево + ЭлементНадпись.Ширина + 6;
ЭлементПолеВвода.Высота = ЭлементНадпись.Высота;
Если ЭлементПолеВвода.ТипЗначения.СодержитТип(Тип("Дата")) Тогда
ЭлементПолеВвода.Ширина = 80;
Иначе
ЭлементПолеВвода.Ширина = 200;
КонецЕсли;
//Надпись и Поле Выбора
ИмяЭлемента = " Подписывающий";
ЭлементНадпись = ЭлементыФормы.Добавить(Тип("Надпись"), "Надпись"+ИмяЭлемента, Истина,);
ЭлементНадпись.Заголовок = ИмяЭлемента + ":";
ЭлементНадпись.Лево = 250;
ЭлементНадпись.Верх = 33;
ЭлементНадпись.Высота = 19;
ЭлементНадпись.Ширина = 160;
ЭлементНадпись.ЦветФона = ЦветаСтиля.ЦветФонаФормы;
ЭлементПолеВвода = ЭлементыФормы.Добавить(Тип("ПолеВыбора""), ИмяЭлемента, Истина,);
ЭлементПолеВвода.Данные = Подписывающий;
//ЭлементПолеВвода.ТипЗначения = Новый ОписаниеТипов("СправочникСсылка.СотрудникиОрганизаций");
ЭлементПолеВвода.Верх = ЭлементНадпись.Верх;
ЭлементПолеВвода.Лево = ЭлементНадпись.Лево + ЭлементНадпись.Ширина + 6;
ЭлементПолеВвода.Высота = ЭлементНадпись.Высота;
ЭлементПолеВвода.Ширина = 200;
Категория:
Работа с Формой (Диалог) и её элементами Примеры работы с Деревом значений в УП Так как работа с ДеревомЗначений и ТаблицейЗначений в данном контексте практически не отличается, в примере будет использоваться ДеревоЗначений, все тоже самое за исключением иерархии применимо и к ТаблицеЗначений. Как известно, в
платформе 1С 8.1 не составляло никакого труда связать дерево значений с табличным полем на форме, единственное что при этом нужно было не забыть так это СоздатьКолонки() .
В управляемом приложении 1С 8.2 сделать это не так просто как кажется на первый взгляд.
Обращаю внимание, что
ДеревоЗначений доступно только на сервере, в толстом клиенте и внешнем соединение. В данных самой управляемой формы для моделирования дерева используется тип ДанныеФормыДерево. Для преобразования ДеревоЗначений <-> ДанныеФормыДерево используются методы управляемой формы ЗначениеВРеквизитФормы() и РеквизитФормыВЗначение(). Для непосредственного отображения дерева используется элемент формы типа ТаблицаФормы связанный через реквизит ПутьКДанным с реквизитом формы типа ДанныеФормыДерево. Если Вам не очень понятна вышеописанная связь объектов, не огорчайтесь, ниже рассмотрим практический пример и все встанет на свои места.
Задача: Имеется дерево значений, необходимо отобразить его на управляемой форме.
Создаем новую внешнюю обработку (
Скачивать файлы может только зарегистрированный пользователь! ), добавляем управляемую форму и создаем обработчик ПриСозданииНаСервере(). Никаких реквизитов и элементов “вручную” не добавляем, будем делать это программно.
Код 1C v 8.2 УП &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создание и заполнение "обычного" объекта прикладного типа ДеревоЗначений,
// который будет отображен на управляемой форме
ДеревоОбъект = Новый ДеревоЗначений;
ДеревоОбъект.Колонки.Добавить("Узел", Новый ОписаниеТипов("Строка"));
Для к1 = 1 По 3 Цикл
СтрокаУ1 = ДеревоОбъект.Строки.Добавить();
СтрокаУ1.Узел = "Узел"+к1;
Для к2 = 1 По 3 Цикл
СтрокаУ2 = СтрокаУ1.Строки.Добавить();
СтрокаУ2.Узел = СтрокаУ1.Узел+к2;
Для к3 = 1 По 3 Цикл
СтрокаУ3 = СтрокаУ2.Строки.Добавить();
СтрокаУ3.Узел = СтрокаУ2.Узел+к3;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Создание Реквизита формы типа ДанныеФормыДерево
МассивДобавляемыхРеквизитов = Новый Массив;
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Дерево",
Новый ОписаниеТипов("ДеревоЗначений")));
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
МассивДобавляемыхРеквизитов.Добавить(
Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, "Дерево"));
КонецЦикла;
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
// Преобразование объекта прикладного типа ДеревоЗначений
// в реквизит управляемой формы (данные формы)
ЗначениеВРеквизитФормы(ДеревоОбъект, "Дерево");
// Создание элемента формы типа ТаблицаФормы для отображения дерева
ЭлементДерево = Элементы.Добавить("Дерево", Тип("ТаблицаФормы"));
ЭлементДерево.ПутьКДанным = "Дерево";
ЭлементДерево.Отображение = ОтображениеТаблицы.Дерево;
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"),
ЭлементДерево);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "Дерево." + Колонка.Имя;
КонецЦикла;
КонецПроцедуры
Механизм Drag and D_rop (или проще говоря “Перетаскивания”) для ДереваЗначений расположенного на управляемой форме управляемого приложения
Основная сложность реализации механизма перетаскивания заключается в том, что у строки ДереваЗначений платформа не позволяет просто изменить родителя, т.е. переподчинить строку. Единственный способ это сделать – создать новую строку вместе со всеми подчиненными строками, т.е. полностью скопировать всю ветку дерева вместе со всей иерархией и подчинить ее требуемой строке-родителю, после чего удалить исходную ветку. Данная задача распадается на две подзадачи:
1). Перед перетаскиванием необходимо проверить корректность данной операции, узел дерева нельзя переносить в узлы подчиненные ему самому, т.е. родительский узел нельзя переносить в дочерние, т.к. это приведет к “бесконечной рекурсии” и “падению” платформы. Это реализуется с помощью обработчика события ЭлементДеревоПроверкаПеретаскивания(…)
2). Если перетаскивание возможно, то при помощи обработчика ЭлементДеревоПеретаскивание(…) запускается рекурсивная функция, которая создает новую ветку дерева, подчиненную требуемому родителю, а исходную удаляет.
Обращаю особое внимание на то, что в платформе 8.2 реализован механизм множественного выбора элементов, поэтому вышеуказанные операции необходимо произвести для всех выбранных пользователем элементов. (
Скачивать файлы может только зарегистрированный пользователь! )
Код 1C v 8.2 УП &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создание и заполнение "обычного" объекта прикладного типа ДеревоЗначений,
// который будет отображен на управляемой форме
// Здесь необходимо расположить код из предыдущей статьи
// «Работа с деревом значений и таблицей значений. Часть I (Основы)»
// .....................................................
// Добавим обработчики и установим свойства
ЭлементДерево.МножественныйВыбор=Истина;
ЭлементДерево.РазрешитьПеретаскивание=Истина;
ЭлементДерево.РазрешитьНачалоПеретаскивания=Истина;
ЭлементДерево.УстановитьДействие("ПроверкаПеретаскивания",
"ЭлементДеревоПроверкаПеретаскивания");
ЭлементДерево.УстановитьДействие("Перетаскивание",
"ЭлементДеревоПеретаскивание");
КонецПроцедуры
&НаКлиенте
Функция ПроверитьВозможностьПереноса(ПереносимыйЭлемент, Знач НовыйРодитель)
Пока НЕ НовыйРодитель = Неопределено Цикл
Если ПереносимыйЭлемент = НовыйРодитель Тогда
Возврат Ложь;
КонецЕсли;
НовыйРодитель = НовыйРодитель.ПолучитьРодителя();
КонецЦикла;
Возврат Истина;
КонецФункции
&НаКлиенте
Функция СкопироватьСтрокуДерева(РеквизитДерево, Приемник, Источник)
Перем НоваяСтрока, ОбратныйИндекс, КолПодчиненныхСтрок;
// Источник может быть уже перенесен
// Это происходит если выделены несколько элементов
// одной и той же ветви дерева на разных уровнях иерархии
Если Источник = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если Приемник = Неопределено Тогда
// Добавляем в корень
НоваяСтрока = РеквизитДерево.ПолучитьЭлементы().Добавить();
Иначе
НоваяСтрока = Приемник.ПолучитьЭлементы().Добавить();
КонецЕсли;
ЗаполнитьЗначенияСвойств(НоваяСтрока, Источник);
КолПодчиненныхСтрок = Источник.ПолучитьЭлементы().Количество();
Для ОбратныйИндекс = 1 По КолПодчиненныхСтрок Цикл
ПодчиненнаяСтрока = Источник.ПолучитьЭлементы()
[КолПодчиненныхСтрок - ОбратныйИндекс];
СкопироватьСтрокуДерева(РеквизитДерево, НоваяСтрока, ПодчиненнаяСтрока);
КонецЦикла;
Если Источник.ПолучитьРодителя() = Неопределено Тогда
РеквизитДерево.ПолучитьЭлементы().Удалить(Источник);
Иначе
Источник.ПолучитьРодителя().ПолучитьЭлементы().Удалить(Источник);
КонецЕсли;
Возврат НоваяСтрока;
КонецФункции
&НаКлиенте
Процедура ЭлементДеревоПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания,
СтандартнаяОбработка, Строка, Поле)
// Узел нельзя переносить в узлы подчиненные ему самому
// т.е. родительский узел нельзя переносить в дочерние.
// Проверим это условие для всех выделенных элементов
СтандартнаяОбработка = Ложь;
РеквизитДерево = ЭтаФорма["Дерево"];
ИДНовыйРодитель = Строка;
// Если НовыйРодитель = Неопределено => Корень дерева
НовыйРодитель = ?(ИДНовыйРодитель = Неопределено, Неопределено,
РеквизитДерево.НайтиПоИдентификатору(ИДНовыйРодитель));
МассивИДПереносимыхЭлементов = ПараметрыПеретаскивания.Значение;
Для каждого ИДПереносимыйЭлемент из МассивИДПереносимыхЭлементов Цикл
ПереносимыйЭлемент = РеквизитДерево.НайтиПоИдентификатору(
ИДПереносимыйЭлемент);
Если НЕ ПроверитьВозможностьПереноса(ПереносимыйЭлемент,
НовыйРодитель) Тогда
ПараметрыПеретаскивания.Действие=ДействиеПеретаскивания.Отмена;
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЭлементДеревоПеретаскивание(Элемент, ПараметрыПеретаскивания,
СтандартнаяОбработка, Строка, Поле)
СтандартнаяОбработка=Ложь;
РеквизитДерево = ЭтаФорма["Дерево"];
ИДПриемник = Строка;
// Если ИДПриемник = Неопределено => Корень дерева
Приемник = ?(ИДПриемник = Неопределено, Неопределено,
РеквизитДерево.НайтиПоИдентификатору(ИДПриемник));
МассивИДИсточник = ПараметрыПеретаскивания.Значение;
Для Каждого ИДИсточник Из МассивИДИсточник Цикл
Источник = РеквизитДерево.НайтиПоИдентификатору(ИДИсточник);
НоваяСтрока = СкопироватьСтрокуДерева(РеквизитДерево, Приемник, Источник);
// Производится копирование в корень
// Для "красоты" развернем вновь созданную ветвь
Если Приемник = Неопределено и НоваяСтрока<>Неопределено Тогда
Элементы["Дерево"].Развернуть(НоваяСтрока.ПолучитьИдентификатор(),
Истина);
КонецЕсли;
КонецЦикла;
// Для "красоты" развернем ветвь-родителя
Если НЕ Приемник = Неопределено Тогда
Элементы["Дерево"].Развернуть(ИДПриемник, Истина);
КонецЕсли;
КонецПроцедуры
Реализовать трехпозиционный флажок в ДеревеЗначений на управляемой форме
который работает по следующему алгоритму:
* Если у элемента ДереваЗначений нет подчиненных элементов, то флажок может быть либо “включен”, либо “выключен”.
* Если у элемента есть подчиненные, то флажок “включен”, если ВКЛЮЧЕНЫ флажки у ВСЕХ подчиненных элементов, “выключен” если ВЫКЛЮЧЕНЫ флажки у ВСЕХ подчиненных элементов.
Если у некоторых подчиненных элементов флажки включены, а у некоторых выключены, то флажок родительского элемента имеет значение “неопределенно”.
* При включении флажка у родительского элемента, включаются флажки ВСЕХ подчиненных, при выключении флажка у родительского элемента, выключаются флажки ВСЕХ подчиненных.
Возьмем из первой статьи процедуру построения дерева значений и доработаем ее, добавив в дерево еще одну колонку, которая будет содержать элемент управления флажок и реализуем для него обработчик события “ПриИзменении”. Весь алгоритм сводится к обработке изменения флажка: у всех подчиненных элементов необходимо включить/выключить флажки в зависимости от состояния флажка текущего элемента, а у всех родителей текущего элемента (которые расположены на верхних уровнях иерархии) проставить флажки в состояния “включен”/”выключен”/”неопределенно” в соответствии с вышеописанным алгоритмом. (
Скачивать файлы может только зарегистрированный пользователь! )
Код 1C v 8.2 УП &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создание и заполнение "обычного" объекта прикладного типа ДеревоЗначений,
// который будет отображен на управляемой форме
ДеревоОбъект = Новый ДеревоЗначений;
ДеревоОбъект.Колонки.Добавить("Узел", Новый ОписаниеТипов("Строка"));
ДеревоОбъект.Колонки.Добавить("Пометка", Новый ОписаниеТипов("Число"));
Для к1 = 1 По 3 Цикл
СтрокаУ1 = ДеревоОбъект.Строки.Добавить();
СтрокаУ1.Узел = "Узел"+к1;
Для к2 = 1 По 3 Цикл
СтрокаУ2 = СтрокаУ1.Строки.Добавить();
СтрокаУ2.Узел = СтрокаУ1.Узел+к2;
Для к3 = 1 По 3 Цикл
СтрокаУ3 = СтрокаУ2.Строки.Добавить();
СтрокаУ3.Узел = СтрокаУ2.Узел+к3;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Создание Реквизита формы типа ДанныеФормыДерево
МассивДобавляемыхРеквизитов = Новый Массив;
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Дерево",
Новый ОписаниеТипов("ДеревоЗначений")));
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(Колонка.Имя,
Колонка.ТипЗначения, "Дерево"));
КонецЦикла;
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
// Преобразование объекта прикладного типа ДеревоЗначений
// в реквизит управляемой формы (данные формы)
ЗначениеВРеквизитФормы(ДеревоОбъект, "Дерево");
// Создание элемента формы типа ТаблицаФормы для отображения дерева
ЭлементДерево = Элементы.Добавить("Дерево", Тип("ТаблицаФормы"));
ЭлементДерево.ПутьКДанным = "Дерево";
ЭлементДерево.Отображение = ОтображениеТаблицы.Дерево;
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"),
ЭлементДерево);
НовыйЭлемент.ПутьКДанным = "Дерево." + Колонка.Имя;
Если НЕ Колонка.Имя = "Пометка" Тогда
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
Иначе
НовыйЭлемент.Вид = ВидПоляФормы.ПолеФлажка;
НовыйЭлемент.ТриСостояния = Истина;
НовыйЭлемент.УстановитьДействие("ПриИзменении",
"ФлажокПриИзменении");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
ИДТекущейСтроки = Элементы["Дерево"].ТекущаяСтрока;
Если ИДТекущейСтроки <> Неопределено Тогда
ЭлементКоллекции = ЭтаФорма["Дерево"].НайтиПоИдентификатору(
ИДТекущейСтроки);
Если ЭлементКоллекции.Пометка = 2 Тогда
ЭлементКоллекции.Пометка = 0;
КонецЕсли;
УстановкаФлажков(ЭлементКоллекции, ЭлементКоллекции.Пометка);
Родитель = ЭлементКоллекции.ПолучитьРодителя();
Пока Родитель <> Неопределено Цикл
Родитель.Пометка = ?(УстановленноДляВсех(ЭлементКоллекции),
ЭлементКоллекции.Пометка, 2);
ЭлементКоллекции = Родитель;
Родитель = ЭлементКоллекции.ПолучитьРодителя();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура УстановкаФлажков(ЭлементКоллекции, ЗначениеПометки)
ПодчинЭлементы = ЭлементКоллекции.ПолучитьЭлементы();
Для Каждого ТекЭлемент Из ПодчинЭлементы Цикл
ТекЭлемент.Пометка = ЗначениеПометки;
УстановкаФлажков(ТекЭлемент, ТекЭлемент.Пометка);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Функция УстановленноДляВсех(ЭлементКоллекции)
СоседниеЭлементы =
ЭлементКоллекции.ПолучитьРодителя().ПолучитьЭлементы();
Для Каждого ТекЭлемент Из СоседниеЭлементы Цикл
Если ТекЭлемент.Пометка <> ЭлементКоллекции.Пометка Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Источник Категория:
Работа с Деревом Значений Поиск в базе битых ссылок - "объект не найден" В статье
Битая ссылка, <Объект не найден>, Уникальный Идентификатор, GUID мы обсуждали как востановить битые ссылки!
А вот как найти в базе все битые ссылки, которые имеют вид типа "<Объект не найден> (137:8b270030482898d011daad3cc45fc830)"?
Для поиска этого была написана данная обработка:
Скачивать файлы может только зарегистрированный пользователь!
Для поиска: Выбираем объекты метаданных , которые хотим проверить, жмем кнопочку "Выполнить" и наблюдаем в таблице выходные данные. Откуда можем попасть в объекты-источники.
Для программиста:
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
ИспользоватьОграничение = ЗначениеЗаполнено(ОграничениеТипов);
РезультатПоиска.Очистить();
Для Каждого ОбъектыМетаданных Из КоллекцияОбъектов Цикл
Для Каждого ОбъектМетаданных Из ОбъектыМетаданных Цикл
Состояние(ОбъектМетаданных.ПолноеИмя());
ПроверитьОбъектНаБитыеСсылки(ОбъектМетаданных);
КонецЦикла;
КонецЦикла;
Для Каждого ОбъектыМетаданных Из КоллекцияРегистров Цикл
Для Каждого ОбъектМетаданных Из ОбъектыМетаданных Цикл
Состояние(ОбъектМетаданных.ПолноеИмя());
ПроверитьРегистрНаБитыеСсылки(ОбъектМетаданных);
КонецЦикла;
КонецЦикла;
//Анализ последовательностей
//ПроверитьОбъектНаБитыеСсылки(Метаданные.Справочники.СотрудникиОрганизаций);
КонецПроцедуры
Процедура ВывестиДанные(ТекстЗапроса)
Запрос = Новый Запрос(ТекстЗапроса);
Попытка
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
ТЗ = РезультатЗапроса.Выгрузить();
Для Каждого Стр Из ТЗ Цикл
ОбработкаПрерыванияПользователя();
Строка = РезультатПоиска.Добавить();
ЗаполнитьЗначенияСвойств(Строка, Стр);
КонецЦикла;
КонецЕсли;
Исключение
Сообщить(ИнформацияОбОшибке().Описание + " " + ИнформацияОбОшибке().Причина);
КонецПопытки;
КонецПроцедуры
Процедура ПроверитьРегистрНаБитыеСсылки(ОбъектМетаданных)
ИмяТаблицы = ОбъектМетаданных.ПолноеИмя();
Если Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
Если ОбъектМетаданных.РежимЗаписи = НезависимыйРежимЗаписи Тогда
//АнализСвойствРегистраСведений(ОбъектМетаданных, ОбъектМетаданных.Измерения, ИмяТаблицы);
//АнализСвойствРегистраСведений(ОбъектМетаданных, ОбъектМетаданных.Ресурсы, ИмяТаблицы);
//АнализСвойствРегистраСведений(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
Возврат;
КонецЕсли;
АнализСвойствРегистра(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
КонецЕсли;
АнализСвойствРегистра(ОбъектМетаданных, ОбъектМетаданных.Измерения, ИмяТаблицы);
АнализСвойствРегистра(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
АнализРегистратораРегистра(ОбъектМетаданных, ИмяТаблицы);
Если Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда
//Для рег. бухгалтерии анализ субконто
КонецЕсли;
Если Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
//Для регистров расчета доп. анализ
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьОбъектНаБитыеСсылки(ОбъектМетаданных)
ИмяТаблицы = ОбъектМетаданных.ПолноеИмя();
АнализСвойствОбъекта(ОбъектМетаданных, ОбъектМетаданных.Реквизиты, ИмяТаблицы);
Для Каждого ТабЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
Если ТабличныеЧастиИсключения.Найти(ТабЧасть.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
АнализСвойствОбъекта(ОбъектМетаданных, ТабЧасть.Реквизиты, ИмяТаблицы + "." + ТабЧасть.Имя)
КонецЦикла;
//проверка владельца у справочников
Если Метаданные.Справочники.Содержит(ОбъектМетаданных) И ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
МассивВладельцев = Новый Массив;
Для Каждого Элемент Из ОбъектМетаданных.Владельцы Цикл
МассивВладельцев.Добавить(Элемент);
КонецЦикла;
//АнализСвойствВладельцаОбъекта(ОбъектМетаданных, МассивВладельцев, ИмяТаблицы);
КонецЕсли;
//Для задач поле исполнитель
//проверки в журналах
ОбработкаПрерыванияПользователя();
КонецПроцедуры
Процедура АнализСвойствОбъекта(ОбъектМетаданных, Свойства, ИмяТаблицы)
Для Каждого Реквизит Из Свойства Цикл
Если РеквизитыИсключения.Найти(Реквизит.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
Для Каждого моТип Из Реквизит.Тип.Типы() Цикл
ТекстЗапроса = "";
МетаданныеТипа = Метаданные.НайтиПоТипу(моТип);
Если МетаданныеТипа <> Неопределено
И Не Метаданные.Перечисления.Содержит(МетаданныеТипа) Тогда
Если ИспользоватьОграничение Тогда
Если Не ПоискПоТипу(МетаданныеТипа.ПолноеИмя()) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ДобавитьВЗапросОбъект(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, Реквизит.Имя, моТип);
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ВывестиДанные(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура АнализСвойствРегистра(ОбъектМетаданных, Свойства, ИмяТаблицы)
Для Каждого Реквизит Из Свойства Цикл
Если РеквизитыИсключения.Найти(Реквизит.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
Для Каждого моТип Из Реквизит.Тип.Типы() Цикл
ТекстЗапроса = "";
МетаданныеТипа = Метаданные.НайтиПоТипу(моТип);
Если МетаданныеТипа <> Неопределено
И Не Метаданные.Перечисления.Содержит(МетаданныеТипа) Тогда
Если ИспользоватьОграничение Тогда
Если Не ПоискПоТипу(МетаданныеТипа.ПолноеИмя()) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ДобавитьВЗапросРегистр(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, Реквизит.Имя, моТип);
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ВывестиДанные(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура АнализРегистратораРегистра(ОбъектМетаданных, ИмяТаблицы)
МассивРегистраторов = ПолучитьСписокРегистраторов(ОбъектМетаданных);
Для Каждого Регистратор Из МассивРегистраторов Цикл
Если РеквизитыИсключения.Найти("Регистратор") <> Неопределено Тогда
Продолжить;
КонецЕсли;
моТип = Регистратор;
ТекстЗапроса = "";
МетаданныеТипа = Метаданные.НайтиПоТипу(моТип);
Если МетаданныеТипа <> Неопределено
И Не Метаданные.Перечисления.Содержит(МетаданныеТипа) Тогда
Если ИспользоватьОграничение Тогда
Если Не ПоискПоТипу(МетаданныеТипа.ПолноеИмя()) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ДобавитьВЗапросРегистр(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, "Регистратор", моТип);
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ВывестиДанные(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ПолучитьСписокРегистраторов(ОбъектМетаданных)
МассивРегистраторов = Новый Массив;
МенеджерОбъект = ПолучитьМенеджерОбъекта(ОбъектМетаданных);
Если МенеджерОбъект <> Неопределено Тогда
НаборЗаписей = МенеджерОбъект.СоздатьНаборЗаписей();
ЭлементОтбора = НаборЗаписей.Отбор.Регистратор;
МассивРегистраторов = ЭлементОтбора.ТипЗначения.Типы();
КонецЕсли;
Возврат МассивРегистраторов;
КонецФункции
Функция ПолучитьМенеджерОбъекта(ОбъектМетаданных)
Перем МенеджерОбъекта;
Если Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыБухгалтерии[ОбъектМетаданных.Имя];
ИначеЕсли Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыНакопления[ОбъектМетаданных.Имя];
ИначеЕсли Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыСведений[ОбъектМетаданных.Имя];
ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
МенеджерОбъекта = РегистрыРасчета[ОбъектМетаданных.Имя];
КонецЕсли;
Возврат МенеджерОбъекта;
КонецФункции
Функция ПоискПоТипу(ИмяТипа)
Результат = Ложь;
Если ИспользоватьОграничение Тогда
МассивСтрок = ОграничениеТипов.НайтиСтроки(Новый Структура("ТипДанных", ИмяТипа));
Если ЗначениеЗаполнено(МассивСтрок) Тогда
Результат = Истина;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура ДобавитьВЗапросРегистр(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, ИмяРеквизита, ТипРеквизита)
Текст = "ВЫБРАТЬ Об." + ИмяРеквизита + " КАК Объект,
| """ + ИмяТаблицы + "." + ИмяРеквизита + """ КАК ТаблицаИсточник,
| Об.Регистратор КАК ОбъектИсточник,
| " + ДобавитьОписаниеТипа(ИмяРеквизита, ТипРеквизита) + "
|ИЗ
| " + ИмяТаблицы + " КАК Об
|ГДЕ " + ДобавитьУсловия(ИмяРеквизита, ТипРеквизита);
ТекстЗапроса = ТекстЗапроса + ?(ПустаяСтрока(ТекстЗапроса), "", Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС) + Текст;
КонецПроцедуры
Процедура ДобавитьВЗапросОбъект(ТекстЗапроса, ОбъектМетаданных, ИмяТаблицы, ИмяРеквизита, ТипРеквизита)
Текст = "ВЫБРАТЬ Об." + ИмяРеквизита + " КАК Объект,
| """ + ИмяТаблицы + "." + ИмяРеквизита + """ КАК ТаблицаИсточник,
| Об.Ссылка КАК ОбъектИсточник,
| " + ДобавитьОписаниеТипа(ИмяРеквизита, ТипРеквизита) + "
|ИЗ
| " + ИмяТаблицы + " КАК Об
|ГДЕ " + ДобавитьУсловия(ИмяРеквизита, ТипРеквизита);
ТекстЗапроса = ТекстЗапроса + ?(ПустаяСтрока(ТекстЗапроса), "", Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС) + Текст;
КонецПроцедуры
Функция ДобавитьУсловия(ИмяРеквизита, ТипРеквизита)
мдОбъекта = Метаданные.НайтиПоТипу(ТипРеквизита);
ИмяТаблицы = мдОбъекта.ПолноеИмя();
ПроверкаНаПустыеЗначения = " Об." + ИмяРеквизита + " ССЫЛКА " + ИмяТаблицы;
ПроверкаНаПустыеЗначения = ПроверкаНаПустыеЗначения + " И ВЫРАЗИТЬ(Об." + ИмяРеквизита + " КАК " + ИмяТаблицы + ").Ссылка есть null";
Если Не Метаданные.Перечисления.Содержит(мдОбъекта) Тогда
ПроверкаНаПустыеЗначения = ПроверкаНаПустыеЗначения + " И Об." + ИмяРеквизита + " <> Значение(" + ИмяТаблицы + ".ПустаяСсылка)";
КонецЕсли;
Возврат ПроверкаНаПустыеЗначения;
КонецФункции
Функция ДобавитьОписаниеТипа(ИмяРеквизита, ТипРеквизита)
ОбъектТипа = Метаданные.НайтиПоТипу(ТипРеквизита);
ИмяТаблицы = ОбъектТипа.ПолноеИмя();
ОписаниеТипа = """" + ИмяТаблицы + """ КАК ТипДанных";
Возврат ОписаниеТипа;
КонецФункции
Процедура ОграничениеТиповТипДанныхНачалоВыбора(Элемент, СтандартнаяОбработка)
Перем ЭлементСписка;
СтандартнаяОбработка = Ложь;
Строка = ЭлементыФормы.ОграничениеТипов.ТекущиеДанные;
Если Не ПустаяСтрока(Строка.ТипДанных) Тогда
ЭлементСписка = СписокТипов.НайтиПоЗначению(Строка.ТипДанных);
КонецЕсли;
ВыбранныйЭлемент = СписокТипов.ВыбратьЭлемент( , ЭлементСписка);
Если ВыбранныйЭлемент <> Неопределено Тогда
Строка.ТипДанных = ВыбранныйЭлемент.Значение;
КонецЕсли;
КонецПроцедуры
РеквизитыИсключения = Новый Массив;
ТабличныеЧастиИсключения = Новый Массив;
СписокТипов = Новый СписокЗначений;
Для Каждого ОбъектМетаданных Из Метаданные.Справочники Цикл
СписокТипов.Добавить(ОбъектМетаданных.ПолноеИмя(), ОбъектМетаданных.Имя, , БиблиотекаКартинок.СправочникОбъект);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Документы Цикл
СписокТипов.Добавить(ОбъектМетаданных.ПолноеИмя(), ОбъектМетаданных.Имя, , БиблиотекаКартинок.ДокументОбъект);
КонецЦикла;
КоллекцияОбъектов = Новый Массив;
КоллекцияОбъектов.Добавить(Метаданные.ПланыОбмена);
КоллекцияОбъектов.Добавить(Метаданные.Справочники);
КоллекцияОбъектов.Добавить(Метаданные.Документы);
КоллекцияОбъектов.Добавить(Метаданные.ПланыВидовХарактеристик);
КоллекцияОбъектов.Добавить(Метаданные.ПланыСчетов);
КоллекцияОбъектов.Добавить(Метаданные.ПланыВидовРасчета);
КоллекцияОбъектов.Добавить(Метаданные.БизнесПроцессы);
КоллекцияОбъектов.Добавить(Метаданные.Задачи);
КоллекцияРегистров = Новый Массив;
КоллекцияРегистров.Добавить(Метаданные.РегистрыСведений);
КоллекцияРегистров.Добавить(Метаданные.РегистрыНакопления);
КоллекцияРегистров.Добавить(Метаданные.РегистрыБухгалтерии);
КоллекцияРегистров.Добавить(Метаданные.РегистрыРасчета);
Категория:
1С Общие вопросы - Обычные формы Табличное поле ~ Как реализовать в дереве значений флажок с тремя состояниями? 8.2 УП
Необходимо реализовать трехпозиционный флажок в ДеревеЗначений на управляемой форме 1С предприятия 8.2 , который работает по следующему алгоритму:
* Если у элемента ДереваЗначений нет подчиненных элементов, то флажок может быть либо “включен”, либо “выключен”.
* Если у элемента есть подчиненные, то флажок “включен”, если ВКЛЮЧЕНЫ флажки у ВСЕХ подчиненных элементов, “выключен” если ВЫКЛЮЧЕНЫ флажки у ВСЕХ подчиненных элементов.
Если у некоторых подчиненных элементов флажки включены, а у некоторых выключены, то флажок родительского элемента имеет значение “неопределенно”.
* При включении флажка у родительского элемента, включаются флажки ВСЕХ подчиненных, при выключении флажка у родительского элемента, выключаются флажки ВСЕХ подчиненных.
Возьмем из первой статьи процедуру построения дерева значений и доработаем ее, добавив в дерево еще одну колонку, которая будет содержать элемент управления флажок и реализуем для него обработчик события “ПриИзменении”. Весь алгоритм сводится к обработке изменения флажка: у всех подчиненных элементов необходимо включить/выключить флажки в зависимости от состояния флажка текущего элемента, а у всех родителей текущего элемента (которые расположены на верхних уровнях иерархии) проставить флажки в состояния “включен”/”выключен”/”неопределенно” в соответствии с вышеописанным алгоритмом. Пример -
Скачивать файлы может только зарегистрированный пользователь!
Код 1C v 8.2 УП &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создание и заполнение "обычного" объекта прикладного типа ДеревоЗначений,
// который будет отображен на управляемой форме
ДеревоОбъект = Новый ДеревоЗначений;
ДеревоОбъект.Колонки.Добавить("Узел", Новый ОписаниеТипов("Строка"));
ДеревоОбъект.Колонки.Добавить("Пометка", Новый ОписаниеТипов("Число"));
Для к1 = 1 По 3 Цикл
СтрокаУ1 = ДеревоОбъект.Строки.Добавить();
СтрокаУ1.Узел = "Узел"+к1;
Для к2 = 1 По 3 Цикл
СтрокаУ2 = СтрокаУ1.Строки.Добавить();
СтрокаУ2.Узел = СтрокаУ1.Узел+к2;
Для к3 = 1 По 3 Цикл
СтрокаУ3 = СтрокаУ2.Строки.Добавить();
СтрокаУ3.Узел = СтрокаУ2.Узел+к3;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Создание Реквизита формы типа ДанныеФормыДерево
МассивДобавляемыхРеквизитов = Новый Массив;
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Дерево",
Новый ОписаниеТипов("ДеревоЗначений")));
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(Колонка.Имя,
Колонка.ТипЗначения, "Дерево"));
КонецЦикла;
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
// Преобразование объекта прикладного типа ДеревоЗначений
// в реквизит управляемой формы (данные формы)
ЗначениеВРеквизитФормы(ДеревоОбъект, "Дерево");
// Создание элемента формы типа ТаблицаФормы для отображения дерева
ЭлементДерево = Элементы.Добавить("Дерево", Тип("ТаблицаФормы"));
ЭлементДерево.ПутьКДанным = "Дерево";
ЭлементДерево.Отображение = ОтображениеТаблицы.Дерево;
Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"),
ЭлементДерево);
НовыйЭлемент.ПутьКДанным = "Дерево." + Колонка.Имя;
Если НЕ Колонка.Имя = "Пометка" Тогда
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
Иначе
НовыйЭлемент.Вид = ВидПоляФормы.ПолеФлажка;
НовыйЭлемент.ТриСостояния = Истина;
НовыйЭлемент.УстановитьДействие("ПриИзменении",
"ФлажокПриИзменении");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
ИДТекущейСтроки = Элементы["Дерево"].ТекущаяСтрока;
Если ИДТекущейСтроки <> Неопределено Тогда
ЭлементКоллекции = ЭтаФорма["Дерево"].НайтиПоИдентификатору(
ИДТекущейСтроки);
Если ЭлементКоллекции.Пометка = 2 Тогда
ЭлементКоллекции.Пометка = 0;
КонецЕсли;
УстановкаФлажков(ЭлементКоллекции, ЭлементКоллекции.Пометка);
Родитель = ЭлементКоллекции.ПолучитьРодителя();
Пока Родитель <> Неопределено Цикл
Родитель.Пометка = ?(УстановленноДляВсех(ЭлементКоллекции),
ЭлементКоллекции.Пометка, 2);
ЭлементКоллекции = Родитель;
Родитель = ЭлементКоллекции.ПолучитьРодителя();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура УстановкаФлажков(ЭлементКоллекции, ЗначениеПометки)
ПодчинЭлементы = ЭлементКоллекции.ПолучитьЭлементы();
Для Каждого ТекЭлемент Из ПодчинЭлементы Цикл
ТекЭлемент.Пометка = ЗначениеПометки;
УстановкаФлажков(ТекЭлемент, ТекЭлемент.Пометка);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Функция УстановленноДляВсех(ЭлементКоллекции)
СоседниеЭлементы =
ЭлементКоллекции.ПолучитьРодителя().ПолучитьЭлементы();
Для Каждого ТекЭлемент Из СоседниеЭлементы Цикл
Если ТекЭлемент.Пометка <> ЭлементКоллекции.Пометка Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
8.х
На форме имеется табличное поле, источником данных для которого является дерево значений. В одной из колонок расположен элемент управления «Флажок». Необходимо что бы он мог принимать три состояния «Включен», «Выключен» и «Неопределено». При этом состояние «Неопределено» или так называемый «серый флажок», т.е. выбранный частично, устанавливается в том случае, если не у всех подчиненных строк состояние флажка одинаковое. Так же если строка имеет подчиненные строки, то при изменении её флажка, соответствующим образом должны изменяться флажки и всех подчиненных строк.
Во-первых, добавим нашу колонку с флажком в дерево значений:
Код 1C v 8.х Дерево.Колонки.Добавить("Пометка",Новый ОписаниеТипов("Число"));
ЭлементыФормы.Дерево.СоздатьКолонки();
КолонкиДерева=ЭлементыФормы.Дерево.Колонки;
КолонкиДерева.Пометка.ДанныеФлажка="Пометка";
КолонкиДерева.Пометка.УстановитьЭлементУправления(Тип("Флажок"));
КолонкиДерева.Пометка.РежимРедактирования=РежимРедактированияКолонки.Непосредственно;
КолонкиДерева.Пометка.ТриСостоянияФлажка=Истина;
Во-вторых, при изменении флажка нужно устанавливать соответствующие значения в подчиненных строках и контролировать значение флажка в «строке-родителе»:
Код 1C v 8.х Процедура ДеревоПриИзмененииФлажка(Элемент, Колонка)
ТекущаяСтрока=Элемент.ТекущаяСтрока;
Если ТекущаяСтрока.Пометка=2 Тогда
ТекущаяСтрока.Пометка=0;
КонецЕсли;
УстановкаФлажков(ТекущаяСтрока,ТекущаяСтрока.Пометка);
Пока ТекущаяСтрока.Родитель<>Неопределено Цикл
ТекущаяСтрока.Родитель.Пометка=?(УстановленноДляВсех(ТекущаяСтрока),ТекущаяСтрока.Пометка,2);
ТекущаяСтрока=ТекущаяСтрока.Родитель;
КонецЦикла;
КонецПроцедуры
Здесь процедура УстановкаФлажков() рекурсивно устанавливает флажки в подчиненных строках:
Код 1C v 8.х Процедура УстановкаФлажков(ТекущаяСтрока,Значение)
Для Каждого Стр Из ТекущаяСтрока.Строки Цикл
Стр.Пометка=Значение;
УстановкаФлажков(Стр,Стр.Пометка);
КонецЦикла;
КонецПроцедуры
А функция УстановленноДляВсех() проверяет установлено ли одинаковое значение для всех строк на текущем уровне:
Код 1C v 8.х Функция УстановленноДляВсех(Строка)
Для Каждого Стр Из Строка.Родитель.Строки Цикл
Если Стр.Пометка<>Строка.Пометка Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Категория:
Работа с Формой (Диалог) и её элементами Преобразование дерева значений в таблицу значений и обратно Хочу поделиться с посетителями сайта своим подходом к преобразованию таблицы значений в дерево значений и обратно.
Вообще, при разработке отраслевой задачи, была необходимость почти во всех документах, выводить информацию в виде дерева и хранить ее в табличных частях документа, а также в интерактивной обработке данных в виде дерева.
Отсюда появился небольшой модуль для расширения возможности работы с деревом значений, хотя и с некоторыми оговорками.
Основной идеей является использование двух ключевых реквизитов/колонок КлючСтроки и КлючСвязи.
Однако они не всегда необходимы. Код, на мой взгляд достаточно "высушен".
Код 1C v 8.х ////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ И ФУНКЦИИ ДЛЯ РАБОТЫ С ДЕРЕВОМ ЗНАЧЕНИЙ
// Функция формирует значение нового ключа строки табличной части.
//
// Параметры:
// Дерево - дерево значений
//
Функция ПолучитьНовыйКлючСтрокиДерева(Дерево, СписокКлючей = Неопределено) Экспорт
Если СписокКлючей = Неопределено Тогда
СписокКлючей = Новый СписокЗначений;
СписокКлючей.Добавить(0);
КонецЕсли;
Для Каждого СтрокаДерева Из Дерево.Строки Цикл
СписокКлючей.Добавить(СтрокаДерева.КлючСтроки);
ПолучитьНовыйКлючСтрокиДерева(СтрокаДерева, СписокКлючей);
СписокКлючей.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
МаксКлюч = СписокКлючей[0].Значение + 1;
КонецЦикла;
Возврат МаксКлюч;
КонецФункции // ПолучитьНовыйКлючСтрокиДерева()
// Процедура обновляет ключи связи в дереве значений
//
Процедура ОбновитьКлючиСвязиВДеревеЗначений(Дерево) Экспорт
Для Каждого СтрокаДерева Из Дерево.Строки Цикл
Попытка
СтрокаДерева.КлючСвязи = СтрокаДерева.Родитель.КлючСтроки;
Исключение
СтрокаДерева.КлючСвязи = 0;
КонецПопытки;
ОбновитьКлючиСвязиВДеревеЗначений(СтрокаДерева);
КонецЦикла;
КонецПроцедуры // ОбновитьКлючиСвязиВДеревеЗначений()
// Процедура обновляет ключи связи в дереве значений
//
Процедура ОбновитьКлючиСтрокВДеревеЗначений(Дерево, КлючСтроки = 1) Экспорт
Для Каждого СтрокаДерева Из Дерево.Строки Цикл
СтрокаДерева.КлючСтроки = КлючСтроки;
КлючСтроки = КлючСтроки + 1;
ОбновитьКлючиСтрокВДеревеЗначений(СтрокаДерева, КлючСтроки);
КонецЦикла;
КонецПроцедуры // ОбновитьКлючиСвязиВДеревеЗначений()
// Процедура выгружает данные из дерева значений в таблицу значений
// данные выгружаются только в таблицу со сходным набором реквизитов
//
Функция ВыгрузитьДеревоЗначенийВТаблицуЗначений(Дерево, Таблица = Неопределено) Экспорт
Если Таблица = Неопределено Тогда
Таблица = Новый ТаблицаЗначений;
Для Каждого Колонка Из Дерево.Колонки Цикл
Таблица.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
КонецЦикла;
КонецЕсли;
Для Каждого СтрокаДерева Из Дерево.Строки Цикл
ЗаполнитьЗначенияСвойств(Таблица.Добавить(), СтрокаДерева);
ВыгрузитьДеревоЗначенийВТаблицуЗначений(СтрокаДерева, Таблица);
КонецЦикла;
Возврат Таблица;
КонецФункции //ВыгрузитьДеревоЗначенийВТаблицуЗначений()
// Процедура выгружает данные из таблицы значений в дерево значений
// данные выгружаются только в таблицу со сходным набором реквизитов
//
// Параметры:
//
// КлючСтроки - имя колонки ТаблицыЗначений - уникальный идентификатор
// КлючСвязи - имя колонки ТаблицыЗначений - указатель привязки к строке Дерева,
// своего рода указатель на "Родителя"
//
Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений(Таблица, КлючСтроки = "КлючСтроки", КлючСвязи = "КлючСвязи") Экспорт
Дерево = Новый ДеревоЗначений;
Для Каждого Колонка Из Таблица.Колонки Цикл
Дерево.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
КонецЦикла;
Для Каждого СтрокаТаблицы Из Таблица Цикл
СтрокаГруппировки = Дерево.Строки.Найти(СтрокаТаблицы[КлючСвязи], КлючСтроки,Истина);
Если СтрокаГруппировки = Неопределено Тогда
ЗаполнитьЗначенияСвойств(Дерево.Строки.Добавить(), СтрокаТаблицы);
Иначе
ЗаполнитьЗначенияСвойств(СтрокаГруппировки.Строки.Добавить(), СтрокаТаблицы);
КонецЕсли;
КонецЦикла;
Возврат Дерево;
КонецФункции //ВыгрузитьТаблицуЗначенийВДеревоЗначений()
// Процедура устанавливает значение во всем дереве значений
//
Процедура УстановитьЗначениеКолонкиДерева(Дерево, Колонка, Значение) Экспорт
Для каждого СтрокаДерева Из Дерево.Строки Цикл
СтрокаДерева[Колонка] = Значение;
УстановитьЗначениеКолонкиДерева(СтрокаДерева, Колонка, Значение);
КонецЦикла;
КонецПроцедуры //УстановитьЗначениеКолонкиДерева()
// Процедура копирует подчиненные строки дерева значений
//
Процедура СкопироватьПодчиненныеСтроки(СтрокаПриемник, СтрокаИсточник)
Для каждого Строка Из СтрокаИсточник.Строки Цикл
НоваяСтрока = СтрокаПриемник.Строки.Добавить();
НоваяСтрока.КлючСвязи = СтрокаПриемник.КлючСтроки;
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
СкопироватьПодчиненныеСтроки(НоваяСтрока, Строка);
КонецЦикла;
КонецПроцедуры // СкопироватьПодчиненныеСтроки()
// Процедура переносит выделенные строки дерева значений в указанную ветку
//
Процедура ПеренестиСтрокиДереваЗначений(СтрокаПриемник, ВыделенныеСтроки) Экспорт
Если НЕ СтрокаПриемник = Неопределено Тогда
МассивСтрок = Новый Массив;
Для Каждого СтрокаПереноса Из ВыделенныеСтроки Цикл
МассивСтрок.Добавить(СтрокаПереноса);
НоваяСтрока = СтрокаПриемник.Строки.Добавить();
СкопироватьПодчиненныеСтроки(НоваяСтрока, СтрокаПереноса);
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаПереноса);
НоваяСтрока.КлючСвязи = СтрокаПриемник.КлючСтроки;
КонецЦикла;
Для Каждого СтрокаДерева Из МассивСтрок Цикл
Если СтрокаДерева.Родитель = Неопределено Тогда
СтрокаДерева.Строки.Удалить(СтрокаДерева);
Иначе
СтрокаДерева.Родитель.Строки.Удалить(СтрокаДерева);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры //ПеренестиСтрокиДереваЗначений()
Александр Синцов (Sintson) Категория:
Работа с Деревом Значений