Содержание статьи
Виды регистров сведений
Регистры сведений делятся на два основных вида – независимые и подчиненные регистратору. Уже из названия понятно, что запись в подчиненный регистр происходит при проведении документа-регистратора. Таким образом, создание, изменение и удаление записей в таком регистре происходит с помощью движений документа. Добавление и изменение происходит при проведении документа, а вот удаление записи при отмене проведения. По сути, этот процесс уже автоматизирован компанией 1С, нужно только прописать механизм записи движений в регистр.
Независимый же регистр сведений не подчинен никому, он сам по себе. Да-да, прямо как кот, который гуляет сам по себе. Он хранит какие то информационные сведения, не привязанные к какому то документу. В нем создание, изменение и удаление записей происходит вручную.
Создание записи
Создание записи в независимом регистре сведений
Для создания одной записи в независимый регистр сведений, который не подчинен регистратору, можно использовать менеджер записи. Для его создания используется метод СоздатьМенеджерЗаписи(). Давайте для большего понимания приведем пример. Пусть у нас будет периодический регистр сведений ДневнаяТемператураВКвартирах. Там мы будем хранить информацию о средней температуре за день в квартирах многоквартирного дома. Ниже приведен пример кода создания записи в этот регистр:
МенеджерЗаписи = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ДатаЗаписи;
МенеджерЗаписи.НомерДома = НомерДома;
МенеджерЗаписи.НомерКвартиры = НомерКвартиры;
МенеджерЗаписи.СредняяТемпература = СредняяТемпература;
МенеджерЗаписи.Записать();
После выполнения этого кода новая запись будет добавлена в регистр. Если же в регистре уже существует запись с заданным значением измерения “НомерКвартиры” и “НомерДома” на эту дату, то она будет заменена на новую.
Это мы привели пример, как создать одну запись в регистре сведений. А что, если нам нужно записывать данные сразу по всем квартирам? Для этого можно воспользоваться набором записей (метод СоздатьНаборЗаписей()). Предположим, что данные по квартирам уже сформированы в таблицу значений ТемператураВКвартирах специальным прибором. Тогда код создания набора записей будет выглядеть следующим образом:
НаборЗаписей = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Период.Уставноить(ДатаЗаписи);
Для Каждого СтрокаТаблицы Из ТемператураВКвартирах Цикл
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ДатаЗаписи;
НоваяЗапись.НомерДома = СтрокаТаблицы.НомерДома;
НоваяЗапись.НомерКвартиры = СтрокаТаблицы.НомерКвартиры;
НоваяЗапись.СредняяТемпература = СтрокаТаблицы.СредняяТемпература;
КонецЦикла;
НаборЗаписей.Записать();
В результате выполнения кода новые записи будут добавлены в регистр. Если же регистр уже содержит записи с указанным значением измерения ДатаЗаписи (по которому установлен отбор в наборе записей), то существующие записи будут заменены новыми.
Создание записи в подчиненном регистре сведений
Обычно запись в такой регистр происходит при проведении документа-регистратора. Но, наверное, может возникнуть ситуация, когда нужно добавить запись в подчиненный регистр из какого то места в коде. Сделать это можно методом СоздатьНаборЗаписей(). Причем этот метод применяется как при создании одной записи, так и при создании коллекции. Для начала делаем отбор по регистратору, затем создаем запись в наборе записей. В данном случае создании одной записи практически ничем не отличается от создании сразу нескольких записей. Отличие лишь в том, что во втором случае код происходит в цикле. Поэтому для примера приведен один код для двух случаев. Представим, что если у нас нет записей в таблице, то формируем одну запись, в противном случае – коллекцию.
НаборЗаписей = РегистрыСведений.ДневнаяТемператураКвартирПоДокументу.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаРегистратор);
// если в таблице нет записей, то создаем одну запись в регистр, в противном случае две
Если ТемператураВКвартирах.Количество() = 0 Тогда
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ДатаЗаписи;
НоваяЗапись.НомерДома = НомерДома;
НоваяЗапись.НомерКвартиры = НомерКвартиры;
НоваяЗапись.СредняяТемпература = СредняяТемпература;
НаборЗаписей.Записать();
Иначе
Для каждого СтрокаТаблицы Из ТемператураВКвартирах Цикл
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ДатаЗаписи;
НоваяЗапись.НомерДома = СтрокаТаблицы.НомерДома;
НоваяЗапись.НомерКвартиры = СтрокаТаблицы.НомерКвартиры;
НоваяЗапись.СредняяТемпература = СтрокаТаблицы.СредняяТемпература;
НаборЗаписей.Записать();
КонецЦикла;
КонецЕсли;
Изменение записей
Изменение записей в независимом регистре сведений
Итак, для того, чтобы изменить запись в независимом регистре сведений будем использовать все тот же менеджер записи. После этого найдем конкретную запись. Для этого сделаем отбор по периоду и измерениям (НомерДома, НомерКвартиры). Далее проверим методом Выбран(), существует ли такая запись в регистре или нет. Если существует, то меняем среднюю температуру. Ниже приведем пример кода:
Запись = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьМенеджерЗаписи();
Запись.Период = '20241212';
Запись.НомерДома = 1;
Запись.НомерКвартиры = 12;
Запись.Прочитать();
Если Запись.Выбран() Тогда
Запись.СредняяТемпература = 23.1;
Запись.Записать();
КонецЕсли;
Для изменения набора записей можно придумать разные варианты. Все зависит от конкретной задачи. Наша задача довольно простая – мы имеем таблицу с корректировкой средней температуры на конкретный день. Тогда мы просто делаем отбор во всем наборе записей регистра по каждой строке таблицы. После этого просто меняем значение температуры в одной строке набора записей и записываем его. Ниже приведен код:
НаборЗаписей = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьНаборЗаписей();
Для каждого СтрокаТаблицы Из ТемператураВКвартирах Цикл
НаборЗаписей.Отбор.НомерДома.Установить(СтрокаТаблицы.НомерДома);
НаборЗаписей.Отбор.НомерКвартиры.Установить(СтрокаТаблицы.НомерКвартиры);
НаборЗаписей.Отбор.Период.Установить(ДатаЗаписи);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 0 Тогда
Запись = НаборЗаписей[0];
Запись.СредняяТемпература = СтрокаТаблицы.СредняяТемпература;
НаборЗаписей.Записать();
КонецЕсли;
КонецЦикла;
Изменение записей в подчиненном регистре сведений
Изменение одной записи регистра
Вот при изменении записей в подчиненном регистре сведений стоит отдельно поговорить про работу с одной записью и с коллекцией. Позже вы поймете почему. Итак, чтобы изменить одну запись в подчиненном регистре сведений необходимо выполнить следующие шаги:
- создать набор записей;
- установить отбор по регистратору;
- прочитать набор записей;
- перебрать все записи набора, сравнивая их с изменяемыми сведениями до тех пор, пока не будет найдена подходящая запись в регистре;
- записать модифицированный набор записей (чтобы лишний раз не записывать набор, вдруг мы не найдем совпадений).
И уже здесь мы видим, что алгоритм не особо то эффективный. В независимом регистре сведений мы просто выставляли отборы, чтобы найти нужную запись. Вы спросите, почему нельзя сделать также? Дело в том, что в подчинённом регистре сведений отбор можно делать только по регистратору. Именно поэтому приходится перебирать все записи набора. Код изменения температуры в одной квартире в нашем примере будет иметь следующий вид:
НаборЗаписей = РегистрыСведений.ДневнаяТемператураКвартирПоДокументу.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаРегистратор);
НаборЗаписей.Прочитать();
Для каждого ЗаписьНабора Из НаборЗаписей Цикл
Если НачалоДня(ЗаписьНабора.Период) = НачалоДня(ДатаЗаписи)
И ЗаписьНабора.НомерДома = НомерДома
И ЗаписьНабора.НомерКвартиры = НомерКвартиры Тогда
ЗаписьНабора.СредняяТемпература = СредняяТемпература;
КонецЕсли;
КонецЦикла;
Если НаборЗаписей.Модифицированность() Тогда
НаборЗаписей.Записать();
КонецЕсли;
Заметьте, что при сравнении даты мы приводим обе даты в начало дня. Почему? Так как у нас периодичность регистра День, то мы все делаем в разрезе дня, то есть время в дате нам не важно. Но время в дате может не совпадать в изменяемой дате и в дате, которая в регистре. Поэтому мы приводим все в один формат. Если бы у нас была периодичность месяц, то мы бы приводили все к одному месяцу и т.д.
Изменение нескольких записей регистра
Изменение коллекции записей происходит по сути по той же схеме, но в чем же вопрос? А вопрос в том, как более эффективно это сделать. Если смотреть по аналогии, то мы перебираем все записи набора записей и ищем совпадения с изменяемыми данными. Но изменяемых то данных может быть много. Если у нас всего 1000 квартир, а изменять данные мы будем в 500 записях, то нужно каждую запись из 1000 сравнить с 500 измененными. Получается нужно пройти 1000*500 = 500 000 итераций цикла. А если записей еще больше? Поэтому здесь все зависит от задачи и ситуации. Если данных не много, то можно просто перебрать их с помощью вложенных циклов как описано выше. Вот как это будет выглядеть (первые 3 строки будет как и при изменении одной записи):
...
Для каждого ЗаписьНабора Из НаборЗаписей Цикл
Для каждого СтрокаТаблицы Из ТемператураВКвартирах Цикл
Если НачалоДня(ЗаписьНабора.Период) = НачалоДня(ДатаЗаписи)
И ЗаписьНабора.НомерДома = СтрокаТаблицы.НомерДома
И ЗаписьНабора.НомерКвартиры = СтрокаТаблицы.НомерКвартиры Тогда
ЗаписьНабора.СредняяТемпература = СтрокаТаблицы.СредняяТемпература;
КонецЕСли;
КонецЦикла;
КонецЦикла;
Если НаборЗаписей.Модифицированность() Тогда
НаборЗаписей.Записать();
КонецЕсли;
Вы можете придумать свой вариант поиска совпадений. Например, можно каждый раз начинать поиск не с начала, а с места, где нашли первое совпадение. Или можно воспользоваться такими методами набора записей как Выгрузить() и Загрузить(). Таким образом мы можем выгрузить набор записей, отредактировать его каким то более эффективным способом и загрузить обратно. Но это уже тема немного другой статьи. Я думаю сама суть понятна.
Удаление записей
Удаление записей в независимом регистре сведений
В независимом регистре сведений удаление одной записи происходит по тому же принципу, что и изменение. Мы по сути “утверждаем”, что в регистре существует запись с такими измерениями и пытаемся ее прочитать. Если она действительно существует (что мы проверяем методом Выбран()), то мы ее меняем. Ну или в данном случае удаляем. Ниже приведен пример кода:
Запись = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьМенеджерЗаписи();
Запись.Период = ДатаЗаписи;
Запись.НомерДома = НомерДома;
Запись.НомерКвартиры = НомерКвартиры;
Запись.Прочитать();
Если Запись.Выбран() Тогда
Запись.Удалить();
КонецЕсли;
Удаление из набора записей также очень похоже на изменение. Мы указываем в таблице данные каких квартир нужно удалить за день. После этого для каждой строки таблицы мы ищем записи в регистре. Если запись найдена, то мы удаляем ее из набора записей и перезаписываем его.
НаборЗаписей = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьНаборЗаписей();
Для каждого СтрокаТаблицы Из ТемператураВКвартирах Цикл
НаборЗаписей.Отбор.НомерДома.Установить(СтрокаТаблицы.НомерДома);
НаборЗаписей.Отбор.НомерКвартиры.Установить(СтрокаТаблицы.НомерКвартиры);
НаборЗаписей.Отбор.Период.Установить(ДатаЗаписи);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 0 Тогда
Запись = НаборЗаписей[0];
НаборЗаписей.Удалить(Запись);
НаборЗаписей.Записать();
КонецЕсли;
КонецЦикла;
Удаление записей в подчиненном регистре сведений
Удаление одной записи в подчиненном регистре происходит также как и изменение. Только вместо изменения средней температуры в записи мы удаляем найденную запись. Получается такой код (меняется только одна строка):
...
Если НачалоДня(ЗаписьНабора.Период) = НачалоДня(ДатаЗаписи)
И ЗаписьНабора.НомерДома = НомерДома
И ЗаписьНабора.НомерКвартиры = НомерКвартиры Тогда
НаборЗаписей.Удалить(ЗаписьНабора);
КонецЕсли;
...
А вот удаление коллекции записей из подчиненного регистра сведений снова немного отличается. Скорее всего снова можно придумать разные варианты. Здесь будет представлен тот, который мне ближе. Суть его в том, что мы вначале ищем записи, которые нужно удалить и добавляем из в массив. Далее мы обходим получившийся массив записей, удаляя их из набора. Если удалять сразу из набора, то при смещении индекса цикла могут быть пропущены записи. Пропустим часть кода, где устанавливается отбор и читается набор. Ее можно найти выше в статье. Таким образом, получаем следующий код:
...
УдаляемыеЗаписи = Новый Массив;
Для каждого ЗаписьНабора Из НаборЗаписей Цикл
Для каждого СтрокаТаблицы Из ТемператураВКвартирах Цикл
Если НачалоДня(ЗаписьНабора.Период) = НачалоДня(ДатаЗаписи)
И ЗаписьНабора.НомерДома = СтрокаТаблицы.НомерДома
И ЗаписьНабора.НомерКвартиры = СтрокаТаблицы.НомерКвартиры Тогда
УдаляемыеЗаписи.Добавить(ЗаписьНабора);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для каждого УдаляемаяЗапись Из УдаляемыеЗаписи Цикл
НаборЗаписей.Удалить(УдаляемаяЗапись);
КонецЦикла;
Если НаборЗаписей.Модифицированность() Тогда
НаборЗаписей.Записать();
КонецЕсли;
Очистка регистра сведений
Если вы хотите удалить вообще все записи регистре сведений, то можно создать пустой набор записей и записать его:
НаборЗаписей = РегистрыСведений.ДневнаяТемператураВКвартирах.СоздатьНаборЗаписей();
НаборЗаписей.Записать();
Заключение
Надеемся, что эта статья оказалась для вас полезной. Если у вас остались какие то вопросы или есть свое видение каких то моментов мы ждем вас в комментариях. Также будем рады вам помочь с внедрением, доработкой, сопровождением или консультацией по продуктам 1С. Мы также являемся официальным представителем 1С. Поэтому вы можете приобрести лицензии 1С у нас. Мы поможем вам с установкой и проведем первичную консультацию по продукту. Телефон отдела продаж вы найдете в шапке сайта. Желаем развития вам и вашему бизнесу.