Каталог решений - Неограниченное количество строк в табличной части документа

Неограниченное количество строк в табличной части документа

Неограниченное количество строк в табличной части документа

В наличии

Как быть, если вам нужно загрузить в документ более 99999 строк? Существуют различные решения от пересмотра архитектуры конфигурации и разбивки документа на несколько более мелких, до помещения на форму документа таблицы значений и записи её содержимого в регистр сведений. В данной публикации я рассматриваю наиболее лаконичный и простой для понимания на мой взгляд вариант.

Категория:

Описание

На днях возникла задача по загрузке файлов, содержащих сведения об оплате физическими лицами некой коммунальной услуги. Информацию предоставлял расчетный центр, ведущий учет начислений и платежей физических лиц в небольшом городе с населением чуть более 1 млн. жителей. Каждый файл в среднем содержал по 300 тысяч записей о поступивших оплатах по лицевым счетам физ.лиц. Условием заказчика было, что файл должен один-к-одному загружаться в документ 1С, чтобы пользователи видели однозначное соответствие между исходным файлом и результатом загрузки в виде документа 1С.

Задача вроде бы простая, если бы не один нюанс: как известно, табличная часть документа 1С может содержать максимум 99999 строк. Это ограничение во многом искусственное и призвано обеспечить соблюдение некоторых критериев производительности в типовых решениях. Для меня же оно означало, что либо придется отступить от требований заказчика и загружать исходные файлы с разбивкой по нескольким результирующим документам, либо искать нестандартное решение.

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

 

 

После чего транзакция записи документа прерывается. А что если на момент этой проверки мы временно переложим все данные из табличной части в какое-то иное хранилище, а уже после проверки снова вернем их в табличную часть. Давайте попробуем?

Для начала добавим в документ реквизит ХранилищеТабличнойЧастиДокумента, тип — хранилище значений.

Создаем в модуле формы документа серверную процедуру ПередЗаписьюНаСервере(), в которую добавляем следующий код:

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

Смысл в том, чтобы выгрузить табличную часть в реквизит документа ХранилищеТабличнойЧастиДокумента и затем удалить все строки из неё. Таким образом на момент выполнения платформенной проверки на количество записей в табличной части — она у нас будет пустая.

Далее уже в модуле документа в процедуре ПриЗаписи() нам необходимо повторно прочитать состояние табличной части до её очистки.

Процедура ПриЗаписи(Отказ)
	
	ТабличнаяЧастьСписок.Загрузить(ХранилищеТабличнойЧастиДокумента.Получить());

КонецПроцедуры

К этому моменту все проверки пройдены и документ уже записан в БД, а в нашей табличной части нет вообще ни одной строки. Однако транзакция записи еще не завершена. Документ существует в виде двух сущностей. Первая — это записи в sql-таблицах на сервере базы данных, вторая — это объект документа в оперативной памяти сервера 1С. На содержимое первой сущности мы никак повлиять не можем. Что бы мы ни делали, записанный в БД документ так и останется с пустой табличной частью. Но вот на вторую сущность — а именно на объект документа на сервере 1С мы в этот момент всё еще можем влиять. Так давайте восстановим нашу табличную часть и загрузим данные из хранилища значений, куда мы их предварительно поместили.

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

При таком подходе в процедуру ОбработкаПроведения попадет уже объект документа, который вновь содержит всю ранее удаленную из табличной части информацию, а значит все алгоритмы проведения могут спокойно отработать именно так, как если бы они были разработаны для документа с непустой табличной частью. Никаких дополнительных хитростей и вмешательств не нужно, всё сработает штатно так, как будто бы мы никаких манипуляций и не делали вовсе.

Хочу обратить ваше внимание, что в результате возникает очень странная и неочевидная для многих ситуация. В базу данных записан документ с пустой табличной частью, но его движения сформированы на основании объекта, в котором мы перед процедурой проведения восстановили содержимое ТЧ. Я не знаю, насколько такую ситуацию можно назвать багом платформы или недокументированной особенностью, но это работает на сегодняшний день именно так. На этом можно было бы и поставить точку. Все 300 тысяч строк мы загрузили в документ, провели его, и сформировали нужные нам движения. Но остался еще один момент… Что делать, если пользователь захочет открыть документ и отредактировать его? Ведь табличная часть после считывания документа из БД будет пустой! Как быть?

Элементарно. У нас же есть сохраненные в реквизите ХранилищеТабличнойЧастиДокумента данные. Так давайте при чтении содержимого документа на сервере вновь загрузим их в табличную часть. 

В модуле формы документа создаем серверную процедуру: 

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)

	Объект.ТабличнаяЧастьСписок.Загрузить(ТекущийОбъект.ТабличнаяЧастьДокумента.Получить());
	
КонецПроцедуры

На этом всё!

Поделитесь, пожалуйста, вашим мнением: какие подводные камни и ограничения могут быть при эксплуатации такого решения? И какие альтернативные варианты записи объектов с табличной частью, содержащей большое количество записей, превышающие лимиты платформы 1С, используете вы?

has been added to your cart:
Оформление заказа