Учимся программно изменять независимый регистр сведений

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

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

Регистры сведений 1С
Периодические регистры сведений 1С
Подчиненные регистры сведений 1С

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

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

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

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

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

 

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

 

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

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

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

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

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

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

Замерим производительность этого способа.

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

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

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

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

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

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

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

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

Книга «Программировать в 1С за 11 шагов»

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

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

Книга «Основы разработки в 1С: Такси»

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

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

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


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

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

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

Вступайте в мои группы:

Вконтакте: https://vk.com/1c_prosto
Фейсбуке: https://www.facebook.com/groups/922972144448119/
ОК: http://ok.ru/group/52970839015518
Твиттер: https://twitter.com/signum2009

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

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

11 − один =