Сохранить табличный документ в хранилище значений 1с

Обновлено: 07.07.2024

ХранилищеЗначения (хранилище значений 1С) – это объект в языке 1С, который позволяет хранить в базе данных прочие значения, например картинки и файлы, структуры и таблицы значений.

Сначала мы создаем значение, например:
Знч = Новый ТаблицаЗначений();
Потом помещаем его в хранилище значений 1С:
Хранилище = Новый ХранилищеЗначения(Знч, Новый СжатиеДанных(9));
Сжатие данных в хранилище значений 1С с параметром «9» означает, что данные будут храниться в архивированном виде, с максимальной степенью сжатия.

Чтобы сохранить такое значение в базу данных, нужно создать объект конфигурации (справочник, документ и т.п.), у которого добавить реквизит с типом ХранилищеЗначения.
СправочникСсылка = Справочники.Хранилище.СоздатьЭлемент();
СправочникСсылка.ХранилищеЗначения = Хранилище;
СправочникСсылка.Записать();
Кроме хранения таких значений в базе данных, с помощью хранилища значений 1С, мы также можем сохранить такое значение в файл, например:
Настройки = Новый Структура();
Настройки.Вставить("ПоУмолчанию", Истина);
Настройки.Вставить("Наименование", "Наименование1");


Хранилище = Новый ХранилищеЗначения(Настройки, Новый СжатиеДанных(9));
ЗначениеВФайл("C:\", Хранилище);

Пример – сохранение значения из файла
//Значение - картинка из файла
Файл = Новый Картинка("C:\ФайлКартинки.jpg");
Хранилище = Новый ХранилищеЗначения(Файл, Новый СжатиеДанных(9));

//Значение - произвольный файл
Файл = Новый ДвоичныеДанные("C:\ИсполняемыйФайл.exe");
Хранилище = Новый ХранилищеЗначения(Файл, Новый СжатиеДанных(9));


//Значение - текстовый файл
Файл = Новый ЧтениеТекста("C:\ТекстовыйФайл.txt");
ТекстовыеДанные = Файл.Прочитать();
Хранилище = Новый ХранилищеЗначения(ТекстовыеДанные, Новый СжатиеДанных(9));
Значение, помещенное в хранилище значений 1С нельзя использовать, пока оно там находится. Чтобы работать с ним, его нужно «распаковать» обратно, например:
Знч = Хранилище.Получить();
Если Знч = Неопределено Тогда
Сообщить("Ошибка получения значения из хранилища");
КонецЕсли;

В табличных частях объектов 8.2 имеется возможность создавать реквизиты типа ХранилищеЗначения но сохранеие этих реквизитов в тонком клиенте отрабатывается некорректно, разве что каждый раз после присваивания вызывать метод записи объекта Записать () , что не очень то удобно использовать каждый раз при изменении отдельной строки. Для корректной работы с реквизитами такого типа предлагаю сохранять значения в соответствия, которое в свой черед помещается в реквизит формы типа ХранилищеЗначения. Ключом соответствия является идентификатор строки табличной части

&НаКлиенте
Процедура ПрикрепленныеФайлыПередУдалением ( Элемент , Отказ )
ТекущаяСтрока = Элементы . ПрикрепленныеФайлы . ТекущаяСтрока ;
ДанныеСтроки = Элементы . ПрикрепленныеФайлы . ДанныеСтроки ( ТекущаяСтрока );

УдалитьДанныеИзСоответствия ( ДанныеСтроки . НомерСтроки );
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере ( Отказ , СтандартнаяОбработка )
Хранилище = Новый ХранилищеЗначения (Новый Соответствие );

Индекс = - 1 ;
Для Каждого Строка Из Объект . ПрикрепленныеФайлы Цикл
Индекс = Макс ( Индекс , Строка . ПолучитьИдентификатор ());
КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ПередЗаписьюНаСервере ( Отказ , ТекущийОбъект , ПараметрыЗаписи )
Соответствие = Хранилище . Получить ();

Для Каждого Строка Из Объект . ПрикрепленныеФайлы Цикл
ИндексТекущейСтроки = Строка . ПолучитьИдентификатор ();
Если Не Соответствие [ ИндексТекущейСтроки ] = Неопределено Тогда
// Записать файл
ТекущийОбъект . ПрикрепленныеФайлы [ Строка . НомерСтроки - 1 ]. Файл = Соответствие [ ИндексТекущейСтроки ];
// Удаление соответствия
Соответствие . Удалить ( ИндексТекущейСтроки );
КонецЕсли;
КонецЦикла;

Хранилище = Новый ХранилищеЗначения ( Соответствие );
КонецПроцедуры

&НаСервере
Процедура ПоместитьФайлыИзВременногоХранилищаВТЗ ( МассивФайлов )
СправочникОбъект = РеквизитФормыВЗначение ( "Объект" );
// . тело модуля
Индекс = Индекс + 1 ;
НоваяСтрокаВложения = СправочникОбъект . ПрикрепленныеФайлы . Добавить ();

Соответствие = Хранилище . Получить ();
Соответствие . Вставить ( Индекс , Новый ХранилищеЗначения ( Файл ));
Хранилище = Новый ХранилищеЗначения ( Соответствие );

ЗначениеВРеквизитФормы ( СправочникОбъект , "Объект" );
КонецПроцедуры

&НаСервере
Процедура УдалитьДанныеИзСоответствия ( ТекущаяСтрока );
ИндексТекущейСтроки = Объект . ПрикрепленныеФайлы [ ТекущаяСтрока - 1 ]. ПолучитьИдентификатор ();

Соответствие = Хранилище . Получить ();
Соответствие . Удалить ( ИндексТекущейСтроки );
Хранилище = Новый ХранилищеЗначения ( Соответствие );
КонецПроцедуры .

Хранение данных в полях типа ХранилищеЗначения

В 1С:Предприятии 8 существует возможность хранения различных данных в полях типа ХранилищеЗначения . В этих полях могут храниться значения типа ХранилищеЗначения . Сам тип ХранилищеЗначения предназначен, прежде всего, для хранения значений различных типов в сериализованном виде, то есть в том виде, который позволяет записывать данные и потом восстанавливать их. В документации по встроенному языку в описании объектов возможность сериализации указывается отметкой "Сериализуется". Эти значения, а также значения примитивных типов, могут помещаться в хранилище значения и таким образом могут записываться в поля базы данных с типом ХранилищеЗначения . Важной особенностью хранилища значений является возможность хранения данных в сжатом виде. Это позволяет существенно сократить объем хранимой информации для больших объектов.

Таким образом, с помощью полей типа ХранилищеЗначения существует возможность хранения в базе данных существенно более широкого перечня типов данных, по сравнению с тем, который может быть в явном виде указан для полей. Однако следует учитывать, что такой способ хранения и возможности манипулирования такими данными существенно отличаются от обычного хранения данных в полях базы данных. Для таких полей система не поддерживает практически никакой функциональности, кроме собственно записи и чтения. Для таких полей не может использоваться индексирование, по ним нельзя упорядочивать данные в запросах и выборках, такие поля не могут суммироваться и т.д. Можно считать, что в этом случае механизм базы данных хранит некоторую информацию, ничего не зная о ее природе.

Соответственно поля типа ХранилищеЗначения следует использовать только в тех случаях, когда это соответствует их назначению и технологическим особенностям.

Одним из основных применений полей типа ХранилищеЗначения является хранение изображений и образов файлов. Для этого используются типа Картинка и ДвоичныеДанные . Это позволяет сохранять в базе данных фотографии сотрудников, документы созданные в различных форматах и т.д. При реализации хранения такой информации можно рекомендовать создавать структуры данных, которые обеспечат отдельное хранение этих полей от основной информации. Например, для хранения фотографий сотрудников можно реализовать отдельный справочник или регистр сведений, а не помещать поля типа ХранилищеЗначения в сами объекты, хранящие список физических лиц. Следует учитывать, что объекты (например, элементы справочника) считываются системой всегда целиком. Поэтому хранение больших объемов информации непосредственно в полях объектов может существенно замедлить работу системы.

В полях типа ХранилищеЗначения допускается, например, хранение таблиц значений и структур. При этом в таблицах значений и структурах могут храниться любые типы данных, в том числе и ссылочные типы. Заметим, что в ХранилищеЗначения коллекция может быть помещена, если в ней содержатся только сериализуемые значения. Однако следует учитывать, что этот вариант хранения данных существенно отличается, от явного хранения значений в отдельных полях и от хранения информации в табличных частях или регистрах сведений. Система не будет поддерживать для таких полей ссылочную целостность, не будет обеспечивать поиск данных в запросах и т.д. Таким образом, хранение коллекций в таких полях нельзя применять для реализации существенных частей прикладного решения отвечающих за бизнес логику. Такое хранение может допускаться только для вспомогательных данных, не имеющих существенного значения для бизнес-логики прикладного решения, например, для хранения каких-либо настроек работы пользователей.

Хотя в системе не существует явного ограничения на размер данных, хранящихся в полях типа ХранилищеЗначения , следует все-таки осмотрительно относиться к объемам хранимой информации. Следует учитывать, что помещение больших объемов в такие поля увеличивает общий объем информационной базы, и это будет негативно сказываться на работе системы при выполнении различных административных операций, таких как создание резервной копии базы данных. Например, при хранении образов файлов, можно рекомендовать хранить в таких полях данные, действительно необходимые в работе, но не использовать их для хранения больших объемов файлов, не используемых в решаемой прикладной задаче.


// Сохранение значения в реквизит объекта конфигурации (тип: ХранилищеЗначения)
СправочникСтранаСсылка = Справочники . Страны . НайтиПоНаименованию ( "Испания" );
СправочникСтранаСсылка . ХранилищеЗначения = Хранилище_Зн ;
СправочникСтранаСсылка . Записать ();

// *** 2.Пример (Табличный документ):
ЗначенияТабДок =Новый ТабличныйДокумент ;
ЗначенияТабДок . Вывести ( ЭлементыФормы . ПолеТабличногоДокумента1 );
Хранилище_ТабДок =Новый ХранилищеЗначения ( ЗначенияТабДок );

// *** 3.Пример (Структура):
ЗначенияСтр = Новый Структура (); // Создание значения "Структура"
ЗначенияСтр . Вставить ( "Код" , "34" );
ЗначенияСтр . Вставить ( "Наименование" , "Испания" );
ЗначенияСтр . Вставить ( "Описание" , "Европейская страна, расположенная на Пиренейском полуострове" );
ЗначенияСтр . Вставить ( "Население" , 46600000 );
// Вставка в хранилище значений
Хранилище_Стр = Новый ХранилищеЗначения ( ЗначенияСтр , Новый СжатиеДанных ( 9 )); // "9" - макс.степень сжатия
ЗначениеВФайл ( "D:\import\" , Хранилище_Стр ); // Сохранение значения в файл

// *** 4.Пример (Любой файл) :
ФайлДвоичныеДанные = Новый ДвоичныеДанные ( "D:\import\КлиентБанк_РБ.exe" );
Хранилище_Файл = Новый ХранилищеЗначения ( ФайлДвоичныеДанные , Новый СжатиеДанных ( 0 )); // "0" - без сжатия

// *** 5.Пример (Файл картинка) :
ФайлФото = Новый Картинка ( "D:\import\ФотоСотрудника.jpg" );
Хранилище_Фото = Новый ХранилищеЗначения ( ФайлФото , Новый СжатиеДанных ( 5 )); // "5" - средн.степень сжатия

// *** 6.Пример (Текстовый файл) :
ФайлТекст = Новый ЧтениеТекста ( "D:\import\Война_и_мир.txt" );
ТекстИзФайла = ФайлТекст . Прочитать ();
Хранилище_Текст = Новый ХранилищеЗначения ( ТекстИзФайла , Новый СжатиеДанных ( 1 )); // "1" - мин.степень сжатия

// *** 7.Пример (Отчет/обработка 1С) :
Хранилище_Epf = Новый ХранилищеЗначения (Новый ДвоичныеДанные ( "D:\import\Otchet_realizacija_2020.epf" , СтепеньСжатия ));

// Двоичные данные можно восстановить из хранилища значения методом Получить и записать в файл методом Записать()
Если ТипЗнч ( РеквизитХранилище ) = Тип ( "ДвоичныеДанные" ) Тогда

// Хранилище.Получить()<>Неопределено Тогда // Процедура извлекает данные из хранилища (требует времени)
// Для больших объемов данных рекомендуется использовать доп.реквизит (Например: Булево) Содержит данные - Истина
ДанныеХранилища = РеквизитХранилище . Получить ();
Если ДанныеХранилища = Неопределено Тогда
Сообщить ( "Ошибка получения данных из хранилища значений 1С" );
КонецЕсли;
ДанныеХранилища . Записать ( ИмяФайла ); // Записываем восстановленые данные в файл

// Восстановление Табличного документа
ЭлементыФормы . ПолеТабличногоДокумента1 . Вывести ( ДанныеХранилища );

// Восстановление и запуск Отчета/обработки 1С
ИмяФайла_Epf = "D:\import\Otchet_realizacija_2020.epf" ;
ДвоичныеДанные = РеквизитХранилище . Получить ();
ДвоичныеДанные . Записать ( ИмяФайла_Epf );
Epf = ВнешниеОбработки . Создать ( ИмяФайла_Epf );
Epf . ПолучитьФорму (). Открыть ();

Иначе
ДанныеХранилища = РеквизитХранилище ;
КонецЕсли;

Читайте также: