1. Главная страница » Компьютеры

1С регистр сведений изменить запись

Автор: | 16.12.2019

В 1С:Предприятии 8 все регистры, кроме регистров сведений, всегда связаны с регистраторами. Регистры сведений могут быть независимыми или также подчиненными регистратору. В этом разделе мы опишем работу с регистрами, подчиненными регистраторам.

В большинстве случаев записи регистров, подчиненных регистраторам, создаются при проведении документов. Это наиболее "естественный" способ создания записей. В этом случае в процессе проведения документа формируются записи регистра, и, тем самым, происходит отражение в учете события описываемого документом.

Однако в 1С:Предприятии 8 существует возможность изменять записи регистров без участия документа. При этом следует учитывать, что каждая запись регистра всегда подчинена одному и только одному регистратору (документу). Поэтому с точки зрения "времени жизни" записи всегда подчинены конкретным регистраторам. Однако, записи могут изменяться без участия самого документа. Главное, чтобы в них имелась ссылка на документ.

Для изменения записей регистров, подчиненных регистраторам, используются наборы записей. При этом всегда используется отбор по регистратору. То есть совокупность записей, подчиненных одному регистратору, является "гранулой" изменения регистра. Нельзя добавлять или удалять отдельные записи. Можно только считывать и записывать записи по регистратору.

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

Таким образом, чтобы изменить записи регистра необходимо:

  • создать набор записей;
  • установить отбор по определенному регистратору;
  • прочитать набор;
  • изменить записи набора;
  • записать набор.

Например, чтобы установить значение реквизита во всех записях регистра можно использовать следующий алгоритм.

//Выберем всех регистраторов регистра
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| УчетНоменклатуры.Регистратор
|ИЗ
| РегистрНакопления.УчетНоменклатуры КАК УчетНоменклатуры";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
//Обойдем регистраторов
Пока Выборка.Следующий() Цикл
Сообщить("Изменение записей по регистратору: " + Выборка.Регистратор);
//Для каждого регистратора выполним изменение набора записей
НаборЗаписей = РегистрыНакопления.УчетНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Значение = Выборка.Регистратор;
НаборЗаписей.Прочитать();
Для каждого Запись Из НаборЗаписей Цикл
Запись.Реквизит1 = "Тест";
КонецЦикла;
НаборЗаписей.Записать();
КонецЦикла;

Читайте также:  Cyberpower value 600e ru b rj

В приведенном примере выполнялось изменение записей. Для добавления записей, если их нет у регистратора, можно выполнять запись без считывания. Для удаления записей можно выполнять запись пустого набора без выполнения считывания.

Заметим, что для добавления большого количества записей по одному регистратору существует возможность записывать записи без замещения. Это регулируется параметром метода Записать(). Такая возможность позволяет добавлять записи, не помещая их всех одновременно в оперативную память.

В регистрах расчетов кроме отбора по регистратору для набора записей можно также установить отбор по другим значениям измерений (только по равенству). Это позволяет выполнить изменение части записей, подчиненных одному регистратору.

В этой статье мы научимся программным способом изменять независимые регистры сведений.

Более подробно о регистрах сведений, их видах и о многом другом читайте в моей книге «Программировать в 1С за 11 шагов».

Для того что бы понять и изучить, принципы программной с регистрами сведений, сделаем небольшую задачу на тестовой конфигурации «Управляемое приложение 1С». Создадим обработку, которая будет менять цены определенного вида у всех товаров на определенную дату.

В конфигурации «Управляемое приложение» цены товаров хранятся в независимом периодическом регистре сведений, который имеет следующие данные

Периодичность этого регистра сведений день.

Создадим внешнюю обработку, которую назовем «ИзменитьЦены», и у которой будет один реквизит ВидЦены (тип СправочникСсылка.ВидыЦен), второй реквизит – Процент (тип число), а третий реквизит – Дата (тип Дата). Создадим команду «Изменить цену», которую разместим в командной панели.

Для команды «Изменить цену» создадим обработчики на сервере и на клиенте, где будем изменять данные регистра сведений ЦеныТоваров.

&НаСервере
Процедура ИзменитьЦенуНаСервере ()
РегистрЦены = РегистрыСведений . ЦеныТоваров . СоздатьНаборЗаписей (); //1
РегистрЦены . Отбор . ВидЦен . Установить ( ВидЦены ); //2
РегистрЦены . Отбор . Период . Установить ( НачалоДня ( Дата )); //3
РегистрЦены . Прочитать (); //4
Для Каждого стрНабора из РегистрЦены Цикл
стрНабора . Цена = стрНабора . Цена *(( 100 + Процент )/ 100 ); //5
КонецЦикла;
РегистрЦены . Записать (); //6
КонецПроцедуры
&НаКлиенте
Процедура ИзменитьЦену ( Команда )
ИзменитьЦенуНаСервере ();
КонецПроцедуры

Разберем код на листинге выше. В строке //1 мы создаем набор записей регистра сведений «ЦеныТоваров» с этим набором мы и будем в дальнейшем осуществлять все операции.

Тот набор записей, который мы получили, в принципе, он весь будет содержать все записи регистра сведений, после того как мы его прочтем, а нам нужно обработать только часть этого набора. Поэтому мы в строках //2 и //3 накладываем отборы на регистр сведений. Имейте в виду, что отбор в регистрах сведений можно устанавливать только на равенство! В строка //4 мы прочитали данные регистра сведений, и теперь можем к объекту РегистрЦены обращаться как к коллекции. Что мы и делаем в цикле ниже – мы обходим коллекцию, и в каждой итерации цикла изменяем цену (строка //5). В строке //6 просто записываем объект РегистрЦены, после этого наши изменения появятся в базе.

Теперь поставим более сложную задачу: нам нужно пересчитать цены за какой-то конкретный период. Например, за весь год. В этом случае мы не можем воспользоваться отбором за весь период.

Если мы попробуем так сделать, то возникнет ошибка «Недопустимый тип сравнения».

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

&НаСервере
Процедура ИзменитьЦенуНаСервере ()
Запрос = Новый Запрос ;
Запрос . Текст = «ВЫБРАТЬ
| ЦеныТоваров.Период КАК Период,
| ЦеныТоваров.Товар КАК Товар,
| ЦеныТоваров.ВидЦен КАК ВидЦен,
| ВЫБОР
| КОГДА ЦеныТоваров.Период >= НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ)
| И ЦеныТоваров.Период Запрос . УстановитьПараметр ( «ДатаНачала» , Период . ДатаНачала );
Запрос . УстановитьПараметр ( «ДатаКонца» , Период . ДатаОкончания );
Запрос . УстановитьПараметр ( «ВидЦен» , ВидЦены );
Запрос . УстановитьПараметр ( «ПроцентЦены» , Процент );
Результат = Запрос . Выполнить ();
Если Результат . Пустой () Тогда
Сообщить ( «Нет данных в регистре по заданному отбору» );
Возврат;
КонецЕсли;
Выгрузка = Результат . Выгрузить ();
РегистрЦены = РегистрыСведений . ЦеныТоваров . СоздатьНаборЗаписей ();
РегистрЦены . Отбор . ВидЦен . Установить ( ВидЦены );
РегистрЦены . Прочитать ();
РегистрЦены . Загрузить ( Выгрузка );
РегистрЦены . Записать ();
КонецПроцедуры

Второй способ – будем получать записи регистра сведений с отбором по цене, выгружать их в таблицу значений, потом эту таблицу значений изменим (те записи, которые соответствуют нашему периоду), и загрузим обратно в регистр сведений. Код этого способа ниже. Изменять таблицу значений мы будем с помощью запроса.

&НаСервере
Процедура ИзменитьЦенуНаСервере ()
РегистрЦены = РегистрыСведений . ЦеныТоваров . СоздатьНаборЗаписей ();
РегистрЦены . Отбор . ВидЦен . Установить ( ВидЦены );
РегистрЦены . Прочитать ();
ТаблицаСРегистра = РегистрЦены . Выгрузить ();
Запрос = Новый Запрос ;
Запрос . Текст = «ВЫБРАТЬ
| ТаблицаВыгрузки.Период КАК Период,
| ТаблицаВыгрузки.ВидЦен КАК ВидЦен,
| ТаблицаВыгрузки.Товар КАК Товар,
| ТаблицаВыгрузки.Цена КАК Цена
|ПОМЕСТИТЬ втТаблица
|ИЗ
| &ТаблицаВыгрузки КАК ТаблицаВыгрузки
|
|ИНДЕКСИРОВАТЬ ПО
| ВидЦен,
| Товар
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| втТаблица.Период КАК Период,
| втТаблица.ВидЦен КАК ВидЦен,
| втТаблица.Товар КАК Товар,
| ВЫБОР
| КОГДА втТаблица.Период >= НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ)
| И втТаблица.Период Запрос . УстановитьПараметр ( «ДатаНачала» , Период . ДатаНачала );
Запрос . УстановитьПараметр ( «ДатаКонца» , Период . ДатаОкончания );
Запрос . УстановитьПараметр ( «ТаблицаВыгрузки» , ТаблицаСРегистра );
Запрос . УстановитьПараметр ( «ПроцентЦены» , Процент );
Результат = Запрос . Выполнить ();
Выгрузка = Результат . Выгрузить ();
РегистрЦены . Загрузить ( Выгрузка );
РегистрЦены . Записать ();
КонецПроцедуры

Подробности об использовании таблиц значений в запросах Вы узнаете в моем курсе «Запрос в 1С: от новичка до профи».
Если брать мои замеры производительности, то первый способ в разы быстрее второго.

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

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

&НаСервере
Процедура ИзменитьЦенуНаСервере ()
Запрос = Новый Запрос ;
Запрос . Текст = «ВЫБРАТЬ
| ЦеныТоваровСрезПоследних.Товар КАК Товар,
| ЦеныТоваровСрезПоследних.Цена * ((100 + &ПроцентЦены) / 100) КАК Цена,
| &ВидЦены КАК ВидЦен,
| НАЧАЛОПЕРИОДА(&ТекущаяДата, ДЕНЬ) КАК Период
|ИЗ
| РегистрСведений.ЦеныТоваров.СрезПоследних(, ВидЦен = &ВидЦены) КАК ЦеныТоваровСрезПоследних»;
Запрос . УстановитьПараметр ( «ВидЦены» , ВидЦены );
Запрос . УстановитьПараметр ( «ПроцентЦены» , Процент );
Запрос . УстановитьПараметр ( «ТекущаяДата» , ТекущаяДата ());
Выборка = Запрос . Выполнить (). Выбрать ();
РегистрЦены = РегистрыСведений . ЦеныТоваров . СоздатьНаборЗаписей ();
РегистрЦены . Отбор . Период . Установить ( НачалоДня ( ТекущаяДата ()));
РегистрЦены . Прочитать ();
РегистрЦены . Очистить ();
Пока Выборка . Следующий () Цикл
НоваяЗапись = РегистрЦены . Добавить ();
ЗаполнитьЗначенияСвойств ( НоваяЗапись , Выборка );
КонецЦикла;
РегистрЦены . Записать ();
КонецПроцедуры

В этом коде я при помощи виртуальной таблицы регистра сведений СрезПоследних получаю все товары и цены на текущую дату. Подробно о работе виртуальных таблиц регистров сведений смотрите в моем курсе «Запрос в 1С: от новичка до профи». Потом мы отбираем все записи регистра сведений на текущую дату и очищаем их на всякий случай. А дальше используя функцию Добавить() набора записей регистра, добавляем что нам нужно.

Изучайте основы конфигурирования в 1С и учитесь программировать в «1С: Предприятии» с помощью моих книг: «Программировать в 1С за 11 шагов» и «Основы разработки в 1С: Такси»

Изучайте программирование в 1С в месте с моей книги «Программировать в 1С за 11 шагов»

  1. Книга написана понятным и простым языком — для новичка.
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Научитесь понимать архитектуру 1С;
  4. Станете писать код на языке 1С;
  5. Освоите основные приемы программирования;
  6. Закрепите полученные знания при помощи задачника;

Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.

  1. Очень доступный и понятный язык изложения
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Поймете идеологию управляемого приложения 1С
  4. Узнаете, как разрабатывать управляемое приложение;
  5. Научитесь разрабатывать управляемые формы 1С;
  6. Сможете работать с основными и нужными элементами управляемых форм
  7. Программирование под управляемым приложением станет понятным

Промо-код на скидку в 15% — 48PVXHeYu


Если Вам помог этот урок решить какую-нибудь проблему, понравился или оказался полезен, то Вы можете поддержать мой проект, перечислив любую сумму:

можно оплатить вручную:

Яндекс.Деньги — 410012882996301
Web Money — R955262494655

— при этом, как видно из этой процедуры, запись передается в обработку «РедактированиеКонтактнойИнформации», где дальше и редактируется (интерактивно):

Автор 1С

12 thoughts on “ Как в 1С v8 изменить запись регистра сведений с помощью метода СоздатьМенеджерЗаписи (1С: v8: Программисту: Язык программирования: Регистр сведений) ”

Используя ваш пример, пытаюсь спозиционироваться на одной записи регистра и изменить один ресурс. Но почему-то не получается. В отладчике МенеджерЗаписи.Выбран() все время равно Ложь, Хотя в регистре сведений ОСОЛицевыеСчета, есть запись с измерением Объект равным Спр.Ссылка. В регистре одно измерение Объект и несколько ресурсов, в том числе СОТипПлиты. Помогите пожалуйста разобраться почему так происходит? Вот то, что я написала:

МенеджерЗаписи=РегистрыСведений.ОСОЛицевыеСчета.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект= Спр.Ссылка;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.СОТипПлиты=ТипПлиты; Иначе
Сообщить(«Возникла проблема определения записи по лиц счету» +Спр+ » в регистре ОСОЛицевыесчета»);
КонецЕсли;
МенеджерЗаписи.Записать();

Марина, добрый день!
Уточните, пожалуйста, сколько у вашего регистра измерений?
Команда МенеджерЗаписи.Объект= Спр.Ссылка; — это определение позиции по одному измерению, т.е. у вашего регистра «ОСОЛицевыеСчета» одно измерение — «Объект»?
Если больше, то для каждого нужно задать значение аналогичной командой (через точку с запятой)

У регистра одно измерение — Объект(тип -СправочникСсылка.ЛицевыеСчета)

Спр = Справочники.ЛицевыеСчета.Выбрать();
Пока Спр.Следующий() Цикл
—-тут то, что я писала выше—-
КонецЦикла

Пока идей нет, почему так происходит. Есть возможность выслать базу? Какой объем у базы?
С удовольствием попробую помочь. Интересно разобраться в проблеме.

Если нужно поменять одну запись в регистре сведений то лучше воспользоваться НаборомЗаписей.

работать будет быстрее, особенно на больших объемах данных.

Serg, спасибо за комментарий.
Вот тут пример кода, иллюстрирующего вариант, который вы предлагаете http://www.1c-h.ru/?p=1038

Наверное, уже никого здесь нет, но точно такая же проблема:
У регистра одно измерение-Документ(Ссылка на документ) и на запись не становится, хотя она в регистре очевидно есть. Выбран() — стабильно = Ложь, хотя метод ПолучитьПоследнее прекрасно работает, но по нему я не могу узнать, каково же точное значение Периода. Какова же истина?

Александр, поясните свою задачу поподробнее, что именно нужно сделать?
Возможно, для решения вашей задачи не хватает установки отбора.
Посмотрите пример вот тут: http://www.1c-h.ru/?p=1674

Александр, ваш регистр сведений подчинен регистратору? И не периодический ли регистр?

жаль, что такой удобный метод работает только с регистрами сведений с установленным параметром «Независимый»

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *