В данном примере хочу привести несколько универсальных функций по выгрузке таблицы значений в файл и дальнейшего чтения из файла:
П орядок программных действий при выгрузке в файл выглядит так:
Подготавливаем таблицу значений (выгружаем из табличной части, выбираем колонки); Конвертируем таблицу значений в табличный документ; Сохраняем табличный документ в 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 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
]
}
В теме форма: v8: Получение данных из ХралищаЗначений
Bell в управляемом интерфейсе пробует сохранить выбранные картинки в базу 1С, но возникли сложности с сохранением в хранилище значений. как пример Bell приложил CF файл с мини конфигурацией, за что ему большое спасибо, т.к. большая часть материалов этой статьи написана им, я лишь поправил небольшие участки кода связанные с передачей файлов и сохранение в хранилище значений.
Так как везде уже Такси, то CF я перевел в этот режим и в нем демонстрирую.
Имеется справочник Хранилище данных :
Основная Форма Элемента:
Ее код:
Код 1C v 8.3 // ПРОЦЕДУРЫ ФОРМЫ
//======================================================================================================
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Объект.Ссылка.Пустая() Тогда
Объект.Наименование = ".";
КонецЕсли;
Если НЕ Параметры.Ключ.Пустая() Тогда
ДанныеАдрес = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ДанныеХЗ");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Объект.Ссылка.Пустая() Тогда
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Если ЭтоАдресВременногоХранилища(ДанныеАдрес) Тогда
РежимСжатия = Новый СжатиеДанных(9);
ДанныеСохранения = ПолучитьИзВременногоХранилища(ДанныеАдрес);
ТекущийОбъект.ДанныеХЗ = Новый ХранилищеЗначения(ДанныеСохранения, РежимСжатия);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Если ЭтоАдресВременногоХранилища(ДанныеАдрес) Тогда
УдалитьИзВременногоХранилища(ДанныеАдрес);
ДанныеАдрес = ПолучитьНавигационнуюСсылку(ТекущийОбъект.Ссылка, "ДанныеХЗ");
КонецЕсли;
КонецПроцедуры
// ПРОЦЕДУРЫ ЭЛЕМЕНТОВ ФОРМЫ
//======================================================================================================
&НаКлиенте
Процедура ВыбратьДанные(Команда)
ДанныеВыбрать();
КонецПроцедуры
&НаКлиенте
Процедура СохранитьДанные(Команда)
Если НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
Предупреждение(НСтр("ru = 'Элемент не записан !!!'"));
Возврат;
КонецЕсли;
ДанныеСохранения = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ДанныеХЗ");
ИмяСохранения = Объект.Наименование;
//ИмяСохранения = Объект.Наименование + Объект.ДанныеРасширение;
ПолучитьФайл(ДанныеСохранения, ИмяСохранения, Истина);
КонецПроцедуры
// ПРОЦЕДУРЫ ПРОЧИЕ
//======================================================================================================
&НаКлиенте
Процедура ДанныеВыбрать()
ПолученныеДанныеАдрес = "";
Если ПоместитьФайл(ПолученныеДанныеАдрес, , Объект.ДанныеПуть, Истина, УникальныйИдентификатор)Тогда
ДанныеАдрес = ПолученныеДанныеАдрес;
ВыбранныйФайл = Новый Файл(Объект.ДанныеПуть);
Объект.Наименование = ВыбранныйФайл.Имя;
Объект.ДанныеТекущаяДата = ТекущаяДата();
Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
так же имеется общая форма ФормаЗагрузкиФайлов
При помощи ее выбираются файлы изображений и загружаются в справочник - одновременно можно загружать несколько файлов
код формы:
Код 1C v 8.3 // ПРОЦЕДУРЫ ЭЛЕМЕНТОВ ФОРМЫ
//======================================================================================================
&НаКлиенте
Процедура СписокФайловПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа)
Отказ = Истина;
ДобавитьФайлы();
КонецПроцедуры
// ПРОЦЕДУРЫ ПРОЧИЕ
//======================================================================================================
&НаКлиенте
Процедура ДобавитьФайлы()
ВыборФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ВыборФайла.МножественныйВыбор = Истина;
ВыборФайла.Заголовок = НСтр("ru = 'Выбор файла'", "ru");
ВыборФайла.Фильтр = НСтр("ru = 'Все файлы'", "ru") + " (*.*)|*.*";
ВыборФайла.ПредварительныйПросмотр = Истина;
Если ВыборФайла.Выбрать() Тогда
Для каждого СтрокаФайл Из ВыборФайла.ВыбранныеФайлы Цикл
ОписаниеФайла = Новый Файл(СтрокаФайл);
НВС = СписокФайлов.Добавить();
НВС.ПолноеИмяФайла = СтрокаФайл;
НВС.РазмерФайла = ОписаниеФайла.Размер();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура Загрузить()
Если НЕ ПроверитьЗаполнение() Тогда
Возврат;
КонецЕсли;
ОчиститьСообщения();
Если СписокФайлов.Количество() = 0 Тогда
Сообщить("Файлы не выбраны !!!'");
Возврат;
КонецЕсли;
ПомещаемыеФайлы = Новый Массив;
Для каждого СтрокаФайл Из СписокФайлов Цикл
Описание = Новый ОписаниеПередаваемогоФайла(СтрокаФайл.ПолноеИмяФайла, "");
ПомещаемыеФайлы.Добавить(Описание);
КонецЦикла;
// -------------------------------------------------------------------------------
ПомещенныеФайлы = Новый Массив;
СписокЗагруженныхФайлов = Новый СписокЗначений;
Если ПоместитьФайлы(ПомещаемыеФайлы, ПомещенныеФайлы, , Ложь, УникальныйИдентификатор) Тогда
Закрыть(Истина);
Иначе
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = НСтр("ru = 'Файлы не загружены'", "ru");
Сообщение.Сообщить();
КонецЕсли;
ОповеститьОВыборе(ПомещенныеФайлы);
КонецПроцедуры
&НаСервере
Функция ПоместитьВыбранныеФайлыВХранилище(ПомещаемыеФайлы)
АдресХЗ = ПоместитьВоВременноеХранилище(ПомещаемыеФайлы, УникальныйИдентификатор);
Возврат АдресХЗ;
КонецФункции
в коде вызывается ОповеститьОВыборе(ПомещенныеФайлы) и срабатывает обработчик в ФормаСпискаДополнительно
Код 1C v 8.3 &НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ИсточникВыбора.ИмяФормы = "ОбщаяФорма.ФормаЗагрузкиФайлов" Тогда
ОбработкаВыбораПодборНаСервере(ВыбранноеЗначение);
КонецЕсли;
КонецПроцедуры
и следующим кодом идет создание элементов справочника и загрузка изображений из временного хранилища
Код 1C v 8.3 &НаСервере
Процедура ОбработкаВыбораПодборНаСервере(ВыбранноеЗначение)
Для Каждого СтрокаФайл Из ВыбранноеЗначение Цикл
Файл = Новый Файл(СтрокаФайл.Имя);
ХранимыйФайл = Справочники.ХранилищеДанныхСправочники.СоздатьЭлемент();
ХранимыйФайл.Наименование = Файл.Имя;
ХранимыйФайл.ДанныеПуть = Файл.Путь;
ХранимыйФайл.ДанныеТекущаяДата = ТекущаяДата();
ХранимыйФайл.ДанныеХЗ = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(СтрокаФайл.Хранение), Новый СжатиеДанных());
ХранимыйФайл.Записать();
КонецЦикла;
Элементы.Список.Обновить();
КонецПроцедуры
Скачать DT - Платформа 8.3.4
Все чаще и чаще встречаются обмены, используя технологию Web-Сервисов. Это удобно, т.к для хостовой базы данных достаточно установить расширение Web-Сервиса и обработчик данных, а для клинтского решения подключиться к Web-Сервису. Технология является мультиплатформенной и на данный момент ее использование весьма актуально.
Примерами таких веб-сервисов можно назвать:
http://www.cbr.ru/scripts/Root.asp?Prtid=DWS веб-сервис Центробанка, для получения ежедневных данных.
http://api.yandex.ru/speller/doc/dg/concepts/api-overview.xml веб-сервис Яндекса проверки правописания.
https://www.flightstats.com/developers/bin/view/Web+Services/WSDL ряд веб сервисов авиастатистики, для мониторинга полетов, сведений о погоде, и.т.п.
WSDL (Web Services Description Language) — язык описания веб-сервисов и доступа к ним, основанный на языке XML. (спецификация http://www.w3.org/TR/wsdl).
SOAP (Simple Object Access Protocol — простой протокол доступа к объектам) — протокол обмена структурированными сообщениями в распределенной вычислительной среде. SOAP используется для обмена произвольными сообщениями в формате XML и удалённого вызова процедур (RPC). (спецификация http://www.w3.org/TR/soap/).
XDTO (XML Data Transfer Objects) — механизм объектного моделирования данных, описываемых с помощью схемы XML (подробнее http://v8.1c.ru/overview/xdto.htm).
Большинство примитивных типов сериализованных объектов разработана компание W3 и их описание находится в пространстве имен «http://www.w3.org/2001/XMLSchema».
 
и так:
Задание 1: Установка платформы 1С: Предприятие, установка компоненты IIS сервера, связь Web-Расширения 1С с сервером IIS.
При установке платформы 1С: Предприятие необходимо установить Web-Расширение.
Рис. 1. Выбранные компоненты в момент установки 1С
В меню «Панель управленияВсе элементы панели управленияПрограммы и компоненты» Необходимо выполнить установку дополнительных компонентов Windows «Включение или отключение компонентов Windows» где указать все компоненты IIS (за исключением FTP, для текущей работы он не требуется). После установки рекомендуется перезапустить операционную систему.
Рис. 2. Выбранные компоненты в момент установки IIS
В меню «Панель управленияВсе элементы панели управленияАдминистрирование» запустить консоль «Диспетчер служб IIS», где открыть элемент «Пулы приложений» открыть пул «DefaultAppPool» в контекстном меню выбрать «Дополнительные параметры…» где элемент «Разрешены 32-рязрядные приложения» надо установить «True». Это необходимо для работы Web-Расширения 1С, т.к. оно является 32-битным прилодением.
В той же консоли «Диспетчер служб IIS», выбрать элемент «Default Web Site», выбрать действие «Проверка подлинности» где необходимо включить варианты: «Анонимная проверка подлинности», «Обычная проверка подлинности», «Проверка подлинности Windows».
Теперь возможна публикация Web-Сервисов 1С на сервере IIS. Но для того, чтобы было возможно выполнить эту публикацию, необходимо запустить Конфигуратор 1С: Предприятия от имени пользователя «Администратор».
Задание 2: Создание простой конфигурации 1С.
Считаем, что в базе данных есть информация информации обо всех заказах, содержащая количество и тип номенклатуры, который был заказан, в одном заказе может быть список, содержащий номенклатуру и количество, заказ так же имеет свой номер и дату его создания. Информацию обо всех заказах надо передать через Web-Сервис.
Для описания этого необходимо создать объекты базы данных:
Рис. 3. Структура данных в созданной конфигурации 1С
Справочник «Номенклатура», без дополнительных реквизитов. В реквизитах «по умолчанию» содержится информацию о наименовании и коде номенклатуры.
Документ «Заказ покупателя», который будет содержать табличную часть «Товары», каждая строка которой будет иметь информацию о номенклатуры (элемент типа «СправочникСсылка.Номенклатура») и количестве (элемент «Количество» типа «Число» беззнаковое с 15 знаками до запятой и 3 после).
Далее можно запустить 1С в режиме предприятия и создать несколько документов, заполненных созданными нами же номенклатурами и соответствующим количеством.
Задание 3: Создание и публикация Веб-Сервиса 1С.
В группировке «Общие» конфигурации создать новый элемент типа «XDTO-пакеты», первоначально для передачи номенклатуры. Его можно назвать, например «NomenclatureXDTO». URL пространство имен, в соответствии со спецификацией WSDL необходимо назначить в виде URL адреса спецификации данного пакета, например
«company.com/1C/Nomenclature». В этом пакете необходимо создать тип объекта, например «Nomenclature», в котором есть реквизиты «Code» и «Name», с соответствующим типом «string (http://www.w3.org/2001/XMLSchema)».
Теперь надо создать второй XDTO пакет, который будет содержать информацию о заказах покупателей, его можно назвать «ClientOrderXDTO» в пространсте имен «company.com/1C/ClientOrder». В первую очередь необходимо подключить директиву импорта «company.com/1C/Nomenclature», для того, чтобы можно было использовать созданный нами пакет сериализации номенклатуры. Это необходимо для передачи номенклатуры, содержащейся в табличной части документа «Заказы покупателей».
Теперь надо создать тип объекта «ClientOrderRow», содержащий одну строку табличной части. Этот тип будет состоять из совокупности реквизитов «Nomenclature» и «Count», соответственно для номенклатуры необходимо указать тип объекта «Nomenclature (http://company.com/1C/Nomenclature)», а для количества, «double (http://www.w3.org/2001/XMLSchema)».
Тип объекта, содержащий сам заказ можно назвать «ClientOrder» должен содержать номер заказа, дату создания и массив элементов из табличной части заказа. «Number» типа строка, «Date» типа «dateTime (http://www.w3.org/2001/XMLSchema)» и «Products» типа «ClientOrderRow (http://company.com/1C/ClientOrder)», при этом необходимо указать, что минимальное количество «0», а максимальное количество «-1», это говорит о том, что этот объект будет массивом.
Но, поскольку необходимо возвращить список заказов, то необходимо создать тип объекта, содержащий этот массив, потому надо создать еще один элемент, называемый «ArrayOfClientOrders», у которого будет всего один реквизит, называемый «ClientOrder» типа «ClientOrder (http://company.com/1C/ClientOrder)».
Рис 4. Структуры XDTO пакетов в 1С
На этом создание описания передаваемых значений можно считать оконченным. Необходимо описать сам веб сервис и его методы.
В группировке «Общие» конфигурации надо создать объект, Web-Сервиса. Его можно назвать «Service». Во вкладке «Прочее» надо указать пространство имен, которому принадлежит веб-сервис, например «company.com/1C», а так же список XDTO пакетов, содержащий только что созданные пакеты «company.com/1C/Nomenclature, company.com/1C/ClientOrder». Во вкладке «Операции» создать метод «GetClientOrders», который будет возвращать значения «ArrayOfClientOrders (http://company.com/1C/ClientOrder )», при этом установить возможность возвращать пустые значения и нажать на поле с лупой, называемое «Имя метода», тем самым в модуле веб-сервиса будет создана функция, который будет вызвана при обращении к данному методу веб-сервиса.
Для того, чтобы корректно описать функцию, получающую из базы данных и возвращающую список заказов покупателей, необходимо знать внутренний язык 1С, потому код этой функции находится в приложении 1. В пояснении нуждается то, что «ФабрикаXDTO», это некоторый менеджер, который выполняет сериализацию объектов, и этот сериализованный объект необходимо возвратить. При этом происходит выборка всех заказов, содержащихся в базе данных, сериализация полей номера, даты, и строк табличной части, при этом номенклатура, нуждается в дополнительной сериализации, и уже упакованный объект вставляется в общую структуру. Собирается массив упакованных объектов, сериализуется в пакет массива. И отправляется клиенту, как результат вызванной функции.
Для публикации веб-сервиса в меню конфигуратора 1С выбрать «АдминистрированиеПубликация на веб-сервере…», после чего указать название публикации веб-сервиса, например «Company», имя сервиса, например «Service» и адрес «service.1cws», а так же указать путь для публикации, например «C:\inetpub\www\root\Company».
После этого WSDL структура Web-Сервиса будет доступна по адресу
«localhost/Company/ws/service.1cws?wsdl»
Задание 4: Создание клиента на C# платформы .NET 4.0.
В Visual Studio создать новое консольное приложение C#.
Далее вызвать контекстное меню над элементом проекта «Reference», и выполнить действие «Add service reference…», в открывшемся меню нажать на кнопку «Advanced…», откроется окно, где необходимо нажать на кнопку «Add Web Reference…».
Откроется меню, в которое необходимо вставить ссылку на WSDL описание веб-сервиса.
Рис. 5. Подключение веб-сервиса к проекту на C#
Для созданного в 1С веб-сервиса эта ссылка будет иметь вид «localhost/Company/ws/service.1cws?wsdl», после корректного получения описания веб-сервиса надо указать название пространства имен .NET, из под которого будет доступно обращение к веб-сервису, например «CompanyService», затем нажать на кнопку «Add Reference…», Visual Studio автоматически сгенерирует классы по этому описанию. В проекте достаточно будет вызывать методы сгенерированного класса, при этом сериализация и вызов будут выполнять платформой .NET.
Далее необходимо написать программу, которая будет обращаться к веб сервису, и выводить пользователю полученные данные. Для этого необходимо знать язык C#, код программы представлен в приложении 2. Из этого кода надо пояснить, то, что создание объекта «Service», есть не что иное, как создание менеджера обращения к сервису. От этого имени будут вызывать методы веб-сервиса.
«_1CWebServiceClientConsole» — это общее пространство имени проекта, оно выбирается при создании. Пространство имени веб-сервиса, полученное из WSDL структуры полностью включено в пространство имени проекта, что позволяет вызывать удаленные методы «как свои».
Построение такой архитектуры является прозрачной для программистов, но при этом необходимо понимать в какие моменты и что проходит сериализацию для последующей передачи. Подобная архитектура клиент-серверных приложений на данный момент самая популярная.
Приложение 1: код функции GetClientOrders на языке 1С
Код 1C v 8.2 УП Функция GetClientOrders()
МассивЗаказовПокупателейТип = ФабрикаXDTO.Тип("http://company.com/1C/ClientOrder", "ArrayOfClientOrders");
ЗаказПокупателяТип = ФабрикаXDTO.Тип("http://company.com/1C/ClientOrder", "ClientOrder");
ЗаказПокупателяСтрокаТип = ФабрикаXDTO.Тип("http://company.com/1C/ClientOrder", "ClientOrderRow");
НоменклатураТип = ФабрикаXDTO.Тип("http://company.com/1C/Nomenclature", "Nomenclature");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказПокупателя.Ссылка,
| ЗаказПокупателя.Номер,
| ЗаказПокупателя.Дата
|ИЗ
| Документ.ЗаказПокупателя КАК ЗаказПокупателя";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Количество() = 0 Тогда
Возврат Null;
КонецЕсли;
МассивЗаказовПокупателей = ФабрикаXDTO.Создать(МассивЗаказовПокупателейТип);
Пока Выборка.Следующий() Цикл
ЗаказПокупателя = ФабрикаXDTO.Создать(ЗаказПокупателяТип);
ЗаказПокупателя.Number = Выборка.Номер;
ЗаказПокупателя.Date = Выборка.Дата;
Для каждого Строка Из Выборка.Ссылка.Товары Цикл
ЗаказПокупателяСтрока = ФабрикаXDTO.Создать(ЗаказПокупателяСтрокаТип);
Номенклатура = ФабрикаXDTO.Создать(НоменклатураТип);
Номенклатура.Code = Строка.Номенклатура.Код;
Номенклатура.Name = Строка.Номенклатура.Наименование;
ЗаказПокупателяСтрока.Nomenclature = Номенклатура;
ЗаказПокупателяСтрока.Count = Строка.Количество;
ЗаказПокупателя.Products.Добавить(ЗаказПокупателяСтрока);
КонецЦикла;
МассивЗаказовПокупателей.ClientOrder.Добавить(ЗаказПокупателя);
КонецЦикла;
Возврат МассивЗаказовПокупателей;
КонецФункции
Приложение 2: код программы на C# осуществляющий обращение к веб-сервису
Код using System;
using _1CWebServiceClientConsole.CompanyService;
namespace _1CWebServiceClientConsole
{
class Program
{
static void Main(string[] args)
{
using (Service service = new Service())
{
var arrayOfClientOrders = service.GetClientOrders();
if (arrayOfClientOrders == null)
Console.WriteLine("Не найдена");
foreach (var clientOrder in arrayOfClientOrders)
{
Console.WriteLine("Заказ покупателя №" + clientOrder.Number + " от " + clientOrder.Date);
Console.WriteLine("*****************************************************");
foreach (var clientOrderRow in clientOrder.Products)
{
Console.WriteLine(clientOrderRow.Nomenclature.Name + " " + clientOrderRow.Count);
}
Console.WriteLine("*****************************************************n");
}
}
Console.ReadKey();
}
}
}
Автор:
ZEEGIN Пошаговый рабочий алгоритм выгрузки в EXCEL на примере выгрузки отчетов производства за смену(Автор статьи:
Funny ):
(1) Нарисовать форму обработки и к кнопке запуска прицепить процедуру:
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Кнопка)
Если ПроверкаДат() Тогда
Состояние("Запущена выгрузка данных");
ПолучитьДанныеВТаблице();
Если чОтчетов<>0 Тогда
СортироватьТаблицу();
ВыгрузитьТаблицуВФайл();
ЗакрытьСистему();
Состояние("Выгрузка завершена");
Иначе
//ЗакрытьСистемуАварийно();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
(2) Создадим функцию ПроверкаДат() корректного указания дат обработки
(3) Создадим процедуру ПолучитьДанныеВТаблице() выборки требуемых данных из документов в таблицу значений
(4) Создадим процедуру СортироватьТаблицу() для сортировки таблицы значений как нам нужно
(5) Создадим процедуру ВыгрузитьТаблицуВФайл() выгрузки ТЗ в Excel-файл:
Код 1C v 8.х Процедура ВыгрузитьТаблицуВФайл()
//1. Open Excel-file
Если FileOfReports = Неопределено Тогда
Попытка
FileOfReports = Новый COMОбъект("Excel.Application");
MyBook=FileOfReports.WorkBooks.Add(истина); //вместо истина можно вставить имя шаблона
FirstSheet=MyBook.Worksheets(1);
FirstSheet.Name = ОпределитьДату(НачПериода)+"-"+ОпределитьДату(КонПериода);
FirstSheet.Activate();
MyBook.SaveAs(КаталогDBF+"ОтчетыПроизводства.xls");
Исключение
Сообщить("ОШИБКА ЗАПИСИ В EXCEL-ФАЙЛ:"+ОписаниеОшибки());
Сообщить("Совет: Возможно файл, в который должна быть произведена запись, Вами открыт для просмотра");
Сообщить("Если это так, то закройте файл и запустите данную обработку повторно!");
КонецПопытки;
FileOfReports.Visible = 0;
Иначе
FileOfReports.Visible = 0;
//FileOfReports.Visible = 1;
КонецЕсли;
//2.=========================================================================
//Состояние("Анализ структуры файла...");
чОтчетов = ТаблицаОтчетов.Количество();
ЭлементыФормы.ИндикаторЗагрузки.МинимальноеЗначение = 0;
ЭлементыФормы.ИндикаторЗагрузки.МаксимальноеЗначение = чОтчетов;
ЭлементыФормы.Logo.Заголовок = "Выгружаю документы";
лСчетчикИндикатора = 0;
ВыгрузитьЗаголовокТаблицы(26);
//ВЫГРУЖАЮ ТАБЛИЦУ В ФАЙЛ ПО СТРОКАМ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
фСтарт=истина; //флаг первого прохода
чОт=2; //номер первой строки с данными
Пока чОтчетов >= 1 Цикл //Цикл по строкам Таблицы отчетов
чОтчетов = чОтчетов -1;
СтрокаОтчетов = ТаблицаОтчетов.Получить(чОтчетов);
Если (СтрокаОтчетов.ДатаВыпуска=ДатаВыпускаПред)
И (СтрокаОтчетов.Принадлежность=ПринадлежностьПред)
И (СтрокаОтчетов.Типоразмер=ТипоразмерПред)
И (СтрокаОтчетов.ТипОсновы=ТипОсновыПред)
Тогда
Иначе
ДатаВыпускаПред=СтрокаОтчетов.ДатаВыпуска;
ПринадлежностьПред=СтрокаОтчетов.Принадлежность;
ТипоразмерПред=СтрокаОтчетов.Типоразмер;
ТипОсновыПред=СтрокаОтчетов.ТипОсновы;
Если фСтарт Тогда
фСтарт = ложь; //Уже не первый проход
Иначе
чДо=глСчетчикСтрок;
ВыгрузитьСтрокуИтог(чОт,чДо,26);
КонецЕсли;
чОт=глСчетчикСтрок;
КонецЕсли;
ВыгрузитьСтрокуОтчетовВФайл(СтрокаОтчетов,26);
лСчетчикИндикатора = лСчетчикИндикатора + 1;
ЭлементыФормы.ИндикаторЗагрузки.Значение = лСчетчикИндикатора;
ОбработкаПрерыванияПользователя();
КонецЦикла;
чДо=глСчетчикСтрок;
ВыгрузитьСтрокуИтог(чОт,чДо,26);
//КОНЕЦ ВЫГРУЗКИ СТРОК В ФАЙЛ
Состояние("Данные файла выгружены");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libСообщитьНК1("ИНФО: ШАГ 1 ВЫПОЛНЕН. Данные файла Отчеты.DBF успешно считаны",1);
//Состояние("Создание сводных таблиц");
ЭлементыФормы.Logo.Заголовок = "Создание сводных таблиц";
//РазделитьОбласти();
//Range("A2").S_elect
//ActiveWindow.FreezePanes = True
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"наим","Дата","Наим","","К");
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"ЮВ","Дата","Наим,Каркас,Вид","","К");
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"В пр(2)","Дата","Наим,Каркас,Основа","","К");
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"В пр","Дата","Каркас,Основа","","К");
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"Основа","Дата","Основа","","кг основы");
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"Напыление","","Напылен","","кг напылен");
СоздатьТаблицуЛист(MyBook.Worksheets(1).Name,"Клей","","Дата","","кг клея");
КонецПроцедуры
Процедура СоздатьТаблицуЛист(стрДанные,стрСводнаяТаблица,стрПоле1,стрПоле2,стрПоле3,стрПоле4);
//Создает сводную таблицу стрСводнаяТаблица с полями (стрПоле4 - поле реквизита)
//и размещает ее на одноименном листе
//Заполняет сводную таблицу данными, взятыми с листа стрДанные
//Поле стрПоле2 может быть полем списка через запятую
//0. Вспомогательный разбор списка значений в стрПоле2 и определение числа значений
лПоля.Очистить(); //сбросим все значения, если таковые весели в памяти
стрПоля=стрПоле2;
i=1;//число значений в списке
Пока Найти(стрПоля,",")<>0 Цикл
n=Найти(стрПоля,",");
лПоля.Добавить(Сред(стрПоля,1,n-1));
стрПоля=Сред(стрПоля,n+1);
i=i+1;
КонецЦикла;
лПоля.Добавить(стрПоля);
//1. Установить диапазон выборки данных
FirstSheet.Activate();
дДиапазонДанных=FirstSheet.UsedRange.Address;
ДиапазонДанных=FirstSheet.Name+"!"+Строка(дДиапазонДанных);
//2. Создать кэш под сводную таблицу
// аргументы не переменные, а текст с именем переменных (crazy)
SourceType = xlDatabase;
SourceData = ДиапазонДанных;
Cache = MyBook.PivotCaches().Add(SourceType, SourceData);
//для отладки: FileOfReports.Visible = 1;
//3. Породить из кэша сводную таблицу с именем стрСводнаяТаблица
TableDestination="";
TableName=стрСводнаяТаблица;
Cache.CreatePivotTable(TableDestination,TableName);
//4. Определить представление данных в сводной таблице
//стрПоле1
Если СокрЛП(стрПоле1)<>"" Тогда
MyBook.ActiveSheet.PivotTables(TableName).PivotFields(стрПоле1).Orientation = 3; //xlRowField=1 то, что указывается справа у таблицы
КонецЕсли;
//стрПоле2
чНомер=0;
Пока чНомер<i Цикл
Если СокрЛП(лПоля[чНомер].Значение)<>"" Тогда
MyBook.ActiveSheet.PivotTables(TableName).PivotFields(лПоля[чНомер].Значение).Orientation = 1;
КонецЕсли;
чНомер = чНомер + 1;
КонецЦикла;
//стрПоле3
Если СокрЛП(стрПоле3)<>"" Тогда
MyBook.ActiveSheet.PivotTables(TableName).PivotFields(стрПоле3).Orientation = 2; //xlColumnField=2 то, что указывается в вепрхней части таблицы
КонецЕсли;
//стрПоле4
Если СокрЛП(стрПоле4)<>"" Тогда
MyBook.ActiveSheet.PivotTables(TableName).PivotFields(стрПоле4).Orientation = 4; //xlCount=4 data
КонецЕсли;
//5. Скрыть пустые строки в стрПоле2, предварительно проверив, что таковые СУЩЕСТВУЮТ!!!!
//стрПоле2
чНомер=0;
Пока чНомер<i Цикл
Если СокрЛП(лПоля[чНомер].Значение)<>"" Тогда
Если IfPivotItemExists(TableName,лПоля[чНомер].Значение,"(пусто)")Тогда
MyBook.ActiveSheet.PivotTables(TableName).PivotFields(лПоля[чНомер].Значение).PivotItems("(пусто)").Visible = False;
КонецЕсли;
КонецЕсли;
чНомер = чНомер + 1;
КонецЦикла;
//6. Закрыть вспомогательные панели
MyBook.ShowPivotTableFieldList = False;
FileOfReports.CommandBars("PivotTable").Visible = False;
//7. Присвоить активному листу имя, заданное в параметрах процедуры
MyBook.ActiveSheet.Name = стрСводнаяТаблица;
//8. Сохранить файл
MyBook.Save();
КонецПроцедуры
Функция IfPivotItemExists(strTableName,strFieldName,strItemName)
//Проверяет существование позиции поля сводной таблицы со значением strItemName
nItems = MyBook.ActiveSheet.PivotTables(strTableName).PivotFields(strFieldName).PivotItems().Count;
i = 1;
Пока i <= nItems Цикл
Если strItemName=MyBook.ActiveSheet.PivotTables(strTableName).PivotFields(strFieldName).PivotItems(i).Name Тогда
//Искомая позиция strItemName существует:
//Сообщить("Позиция "+strItemName+" найдена");
Возврат True;
КонецЕсли;
i=i+1;
КонецЦикла;
//Сообщить("Позиция "+strItemName+" не найдена");
Возврат False;
КонецФункции
Код 1C v 7.x РабочаяКнига = СоздатьОбъект("Excel.Application");
РабочаяКнига.SheetsInNewWorkbook = 1;
РабочаяКнига.Caption = "Отчет по договорам отгрузки";
NewBook = РабочаяКнига.Workbooks;
List = NewBook.Add;
СписокСтолбцов = СоздатьОбъект("СписокЗначений");
СписокСтолбцов.ДобавитьЗначение("Модель");
СписокСтолбцов.ДобавитьЗначение("Разнорядка");
СписокСтолбцов.ДобавитьЗначение("По договору");
СписокСтолбцов.ДобавитьЗначение("Отгрузили");
СписокСтолбцов.ДобавитьЗначение("Осталось");
//Заполним наименование столбцов: Модель, Разнорядка, Количество
Для Столбец = 1 По СписокСтолбцов.РазмерСписка() Цикл
Ячейка = РабочаяКнига.Cells(1,Столбец);
Ячейка.Value = СписокСтолбцов.ПолучитьЗначение(Столбец);
КонецЦикла;
//Формируем запрос по регистру
// //Создание объекта типа Запрос
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с ДатаНач по ДатаКон;
|Разнорядка = Регистр.УчетДоговоров.Разнорядка;
|Модель = Регистр.УчетДоговоров.Модель.Группа;
|Колво = Регистр.УчетДоговоров.Количество;
|Функция КолвоПриход = Приход(Колво);
|Функция КолвоРасход = Расход(Колво);
|Функция КолвоОст = КонОст(Колво);
|Группировка Разнорядка;
|Группировка Модель;
|"//}}ЗАПРОС
;
// Если ошибка в запросе, то выход из процедуры
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
НомерСтроки = 1;
Пока Запрос.Группировка("Разнорядка") = 1 Цикл
Пока Запрос.Группировка("Модель") = 1 Цикл
Модель = Запрос.Модель;
Разнорядка = Запрос.Разнорядка;
КолПоДоговору = Запрос.КолвоПриход;
КолОтгрузили = Запрос.КолвоРасход;
КолОсталось = Запрос.КолвоОст;
НомерСтроки = НомерСтроки + 1;
//Организум заполнение ячеек Excel
Для Ст = 1 По СписокСтолбцов.РазмерСписка() Цикл
Ячейка = РабочаяКнига.Cells(НомерСтроки,Ст);
Если Ст = 1 Тогда
Ячейка.Value = Модель;
ИначеЕсли Ст = 2 Тогда
Ячейка.Value = Строка(Разнорядка);
ИначеЕсли Ст = 3 Тогда
Ячейка.Value = КолПоДоговору;
ИначеЕсли Ст = 4 Тогда
Ячейка.Value = КолОтгрузили;
ИначеЕсли Ст = 5 Тогда
Ячейка.Value = КолОсталось;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
СводнаяТаблица = РабочаяКнига.ActiveSheet.PivotTableWizard;
//Метод СводнаяТаблица.Name возвращает имя сводной таблицы
//Можно задать имя таблицы СводнаяТаблица.Name = "МояТаблица"
СводнаяТаблица.SmallGrid = 0;
//Разворачивает макет сводной таблицы
//Обращение к ячейкам сводной таблицы возможно по номеру
//Например, СводнаяТаблица.PivotFields(1).Value
//возвращает значение "Модель"
//Попробуем с другого конца
//1 - Row
//2 - Column
//3 - Page
//4 - Data
СводнаяТаблица.PivotFields(1).Orientation = 1; //Модель
СводнаяТаблица.PivotFields(2).Orientation = 3; //Разнорядка
СводнаяТаблица.PivotFields(3).Orientation = 4; //По договору
СводнаяТаблица.PivotFields(4).Orientation = 4; //Отгрузили
СводнаяТаблица.PivotFields(5).Orientation = 4; //Осталось
//Пройдемся по форме отчета
СводнаяТаблица.Format(1);
//Попробуем закрыть панель инструментов сводной таблицы
РабочаяКнига.CommandBars("PivotTable").Visible = 0;
РабочаяКнига.Visible = 1;