При работе в 1С пользователи часто сталкиваются с необходимостью вручную отредактировать печатную форму документа (например, добавить примечание, скорректировать адрес или спецификацию) непосредственно перед выводом на принтер. Однако при повторном открытии печатной формы все ручные изменения теряются, и пользователю приходится вносить их заново.
В этой статье мы подробно разберем, как реализовать механизм сохранения отредактированного табличного документа в базе данных 1С, проанализируем различные архитектурные подходы, рассмотрим готовые решения на базе БСП и разберем технические нюансы работы с СУБД и клиент-серверным взаимодействием.
Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП) — например, «1С:Бухгалтерия», «1С:Управление торговлей», «1С:ERP» или «1С:Комплексная автоматизация» — в ней уже есть готовый функционал для решения этой задачи.
Рассмотрим, как это работает на практике для пользователя:
.mxl, .pdf или другом выбранном формате в специальном справочнике присоединенных файлов (например, РеализацияТоваровУслугПрисоединенныеФайлы).Если типовой механизм БСП вам не подходит или требуется реализовать автоматическое открытие сохраненной версии формы при стандартном нажатии кнопки «Печать», лучшим решением будет создание собственного независимого регистра сведений.
Проанализируем структуру такого регистра. Создадим непериодический независимый регистр сведений со следующими реквизитами:
Документ (тип: ДокументСсылка на нужные виды документов).ИмяПечатнойФормы (тип: Строка, длина 100 — для идентификации конкретного макета).ДанныеПечати (тип: ХранилищеЗначения — сюда мы будем помещать сериализованный табличный документ).Автор (тип: СправочникСсылка.Пользователи).ДатаСохранения (тип: Дата).Рассмотрим пример кода для сохранения измененного табличного документа в созданный регистр сведений:
// Процедура выполняется на сервере
Процедура СохранитьПечатнуюФормуВБазу(ДокументСсылка, ИмяФормы, ТабличныйДокумент) Экспорт
// Помещаем табличный документ напрямую в ХранилищеЗначения
// Платформа автоматически сериализует объект ТабличныйДокумент со всем форматированием
ХранилищеДанных = Новый ХранилищеЗначения(ТабличныйДокумент, Новый СжатиеДанных(9));
МенеджерЗаписи = РегистрыСведений.СохраненныеПечатныеФормы.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Документ = ДокументСсылка;
МенеджерЗаписи.ИмяПечатнойФормы = ИмяФормы;
// Заполняем ресурс и реквизиты
МенеджерЗаписи.ДанныеПечати = ХранилищеДанных;
МенеджерЗаписи.Автор = Пользователи.ТекущийПользователь();
МенеджерЗаписи.ДатаСохранения = ТекущаяДатаСеанса();
МенеджерЗаписи.Записать(Истина);
КонецПроцедуры
Для восстановления сохраненной формы перед выводом на экран или печать используем следующий код:
Функция ПолучитьСохраненнуюПечатнуюФорму(ДокументСсылка, ИмяФормы) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СохраненныеПечатныеФормы.ДанныеПечати КАК ДанныеПечати
|ИЗ
| РегистрСведений.СохраненныеПечатныеФормы КАК СохраненныеПечатныеФормы
|ГДЕ
| СохраненныеПечатныеФормы.Документ = &Документ
| И СохраненныеПечатныеФормы.ИмяПечатнойФормы = &ИмяПечатнойФормы";
Запрос.УстановитьПараметр("Документ", ДокументСсылка);
Запрос.УстановитьПараметр("ИмяПечатнойФормы", ИмяФормы);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// Извлекаем табличный документ из хранилища значений
Возврат Выборка.ДанныеПечати.Получить();
КонецЕсли;
Возврат Неопределено;
КонецФункции
В процессе обсуждения часто всплывает идея сериализовать ТабличныйДокумент в строку с помощью устаревших функций ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр. Настоятельно рекомендуем отказаться от этой практики по следующим причинам:
ХранилищеЗначения поддерживает сжатие данных (включается через параметр Новый СжатиеДанных), что экономит место в СУБД в разы.ХранилищеЗначения является стандартным и поддерживаемым механизмом.При реализации хранения печатных форм обязательно учитывайте следующие архитектурные особенности платформы «1С:Предприятие»:
1. Ограничения Хранилища Значений на уровне СУБД:
Поля базы данных, в которых хранятся двоичные данные (BLOB), невозможно проиндексировать средствами СУБД. По ним нельзя производить поиск запросом или накладывать условия сортировки. Поэтому всегда выносите метаданные (ссылку на документ, имя формы, автора, дату) в отдельные измерения и реквизиты вашего регистра сведений, как это показано в примере выше. Поиск нужной записи должен осуществляться только по проиндексированным измерениям.
2. Ограничения клиент-серверного взаимодействия (проблема больших документов):
При нестабильном сетевом подключении прямая передача тяжелого табличного документа с клиента на сервер через параметры функций может вызывать сбои сети или приводить к записи поврежденной структуры. Надежнее использовать временное хранилище:
// Сначала записываем табличный документ во временный файл на клиенте
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("mxl");
ТабличныйДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.MXL);
// Передаем файл во временное хранилище
АдресХранилища = "";
ПоместитьФайл(АдресХранилища, ИмяВременногоФайла,, Ложь, УникальныйИдентификатор);
// На сервере получаем двоичные данные из хранилища и записываем в БД
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ЗаписьРегистра = РегистрыСведений.СохраненныеПечатныеФормы.СоздатьМенеджерЗаписи();
// ... заполнение ключевых полей ...
ЗаписьРегистра.ДанныеПечати = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
ЗаписьРегистра.Записать();
3. Кроссплатформенность и проблемы со шрифтами:
Если сервер 1С работает под управлением Linux, а пользователи работают на Windows-клиентах, при повторном формировании или открытии сохраненного макета на сервере могут поплыть границы ячеек и размеры шрифтов. Это происходит из-за того, что на сервере Linux отсутствуют шрифты семейства Microsoft (Arial, Calibri, Times New Roman). Чтобы избежать этой проблемы, обязательно установите пакет шрифтов msttcorefonts на сервере 1С.
4. Использование PDF/A для неизменяемых копий:
Если вашей задачей является фиксация состояния документа "в момент отправки клиенту" без возможности последующего редактирования, сохраняйте табличный документ в формате PDF/A (архивный формат PDF):
ТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.PDF);
Этот формат гарантирует 100% идентичность отображения на любом устройстве и защищает документ от случайного редактирования сотрудниками.