Мы сталкиваемся с задачей хранения различных событий, которые могут поступать от внешних устройств, таких как сканеры штрихкодов. Эти события могут включать, например, фиксацию времени прохода сотрудников через турникет, отметку начала или окончания выполнения операций, регистрацию перемещения товаров и многое другое. В системе 1С 7.7, где нет такого объекта, как РегистрСведений, выбор оптимального способа хранения таких данных требует внимательного подхода. Рассмотрим подробно доступные варианты и их применение.
В рамках 1С 7.7 мы можем использовать несколько различных объектов конфигурации для хранения информации о событиях. Каждый из этих подходов имеет свои особенности, преимущества и недостатки, которые мы тщательно проанализируем. Среди основных кандидатов на хранение событий выделяются:
Выбор конкретного решения будет зависеть от таких факторов, как объем данных, требования к производительности, сложность необходимых отчетов и удобство дальнейшей обработки информации.
Объект Справочник в 1С 7.7 является одним из наиболее гибких и часто используемых объектов для хранения структурированных данных, не привязанных к конкретным документам и не требующих сложного учета остатков или оборотов. Для хранения событий, когда нам нужна по сути "простая табличка" с набором реквизитов, справочник подходит очень хорошо.
Мы создаем новый справочник, который будет хранить каждую запись о событии как отдельный элемент. Например, каждое сканирование штрихкода сотрудника будет новым элементом этого справочника. Этот подход широко применяется, когда не требуются периодические данные в прямом смысле или независимые измерения, характерные для регистров. Форумчане в сообщениях 7 и 9 активно рекомендуют этот способ. В частности, сообщение 7 приводит пример использования справочника для "дата-время-объект события, инфострока события", а сообщение 9 отмечает, что для "простой таблички" это лучший кандидат.
Рассмотрим шаги по созданию и использованию справочника для фиксации событий от сканера штрихкодов.
Справочник, например, с именем СобытияСканера.Автонумерация в Нет, так как нам не нужен автоматический код для событий.ДлинаКода и ДлинаНаименования в 0. Это устранит ненужные поля и сделает справочник максимально "легким".ДатаВремяСобытия: тип Дата (обязательно с включенным временем), для точной фиксации момента сканирования.Штрихкод: тип Строка, достаточной длины (например, 20-50 символов), для хранения отсканированного штрихкода.Сотрудник: тип Справочник.Сотрудники (если в нашей системе уже есть справочник сотрудников), для привязки события к конкретному человеку. Если штрихкод идентифицирует не сотрудника, а другой объект, мы можем использовать соответствующий тип.ТипСобытия: тип Перечисление.ТипыСобытийСканера (если типы событий фиксированы, например, "Вход", "Выход", "НачалоРаботы") или Строка (если типы событий могут быть произвольными или их много).ДополнительнаяИнформация: тип Строка, для хранения любых дополнительных сведений о событии, как предложил один из участников форума (сообщение 7, "инфострока").ДатаВремяСобытия, Штрихкод и Сотрудник для ускорения поиска и выборки данных.Представим, что у нас есть обработка, которая получает штрихкод от сканера. Мы можем записать это событие следующим образом:
Перем ОтсканированныйШтрихкод; // Переменная, в которую попадает штрихкод со сканера
Перем СотрудникОбъект; // Объект справочника Сотрудники
// Предположим, что ОтсканированныйШтрихкод уже получен
// и СотрудникОбъект определен по этому штрихкоду
// Например: СотрудникОбъект = Справочник.Сотрудники.НайтиПоРеквизиту("Штрихкод", ОтсканированныйШтрихкод);
Если ПустаяСтрока(ОтсканированныйШтрихкод) = 1 Тогда
Сообщить("Штрихкод не может быть пустым!", "!");
Возврат;
КонецЕсли;
Попытка
НовоеСобытие = СоздатьОбъект("Справочник.СобытияСканера");
НовоеСобытие.Новый(); // Создаем новый элемент справочника
НовоеСобытие.ДатаВремяСобытия = ТекущаяДата(); // Записываем текущую дату и время
НовоеСобытие.Штрихкод = ОтсканированныйШтрихкод;
// Если мы нашли сотрудника по штрихкоду, привязываем его
Если СотрудникОбъект.Выбран() = 1 Тогда
НовоеСобытие.Сотрудник = СотрудникОбъект.ТекущийЭлемент();
НовоеСобытие.ДополнительнаяИнформация = "Сотрудник "+СокрЛП(СотрудникОбъект.Наименование)+" отсканировал штрихкод";
Иначе
НовоеСобытие.ДополнительнаяИнформация = "Неизвестный сотрудник отсканировал штрихкод: "+ОтсканированныйШтрихкод;
КонецЕсли;
// Определяем тип события (можно получить из настроек или из самого штрихкода)
// Например, если есть перечисление "ТипыСобытийСканера" с значениями "Вход", "Выход"
// НовоеСобытие.ТипСобытия = Перечисление.ТипыСобытийСканера.Вход;
НовоеСобытие.ТипСобытия = "Вход"; // Если ТипСобытия - строка
НовоеСобытие.Записать(); // Записываем элемент справочника
Сообщить("Событие успешно записано!");
Исключение
Сообщить("Ошибка при записи события: "+ОписаниеОшибки(), "!");
КонецПопычка;
Объект Документ в 1С 7.7 является основным инструментом для фиксации фактов хозяйственной деятельности. Мы можем использовать его для регистрации каждого события от сканера как отдельный документ. Этот подход был предложен в сообщении 4 и подтвержден опытом в сообщениях 25-27.
Мы создаем новый вид документа, который будет выступать в роли "акта" фиксации события. Каждое сканирование штрихкода будет приводить к созданию и, возможно, проведению нового экземпляра этого документа. Документы особенно удобны, когда каждое событие является дискретным фактом, который может иметь свою сложную структуру (например, шапку и табличные части), хотя для простых событий сканера обычно достаточно только шапки. Сообщения 25 и 26 описывают примеры такого подхода для учета входа/выхода по штрихкодам или отпечаткам пальцев.
ДатуДок, ВремяДок и пользователя, который его создал. Это очень удобно для аудита и отслеживания событий.Давайте рассмотрим создание и использование документа для регистрации событий.
Документ, например, с именем ФиксацияСобытияСканера.Штрихкод: тип Строка, для хранения отсканированного штрихкода.Сотрудник: тип Справочник.Сотрудники, для привязки события к сотруднику.ТипСобытия: тип Перечисление.ТипыСобытийСканера или Строка, для указания характера события (например, "Вход", "Выход", "Проверка").Комментарий: тип Строка, для любых дополнительных пояснений.ДатаДок и ВремяДок.
Перем ОтсканированныйШтрихкод;
Перем СотрудникОбъект; // Объект справочника Сотрудники
// Предположим, что ОтсканированныйШтрихкод уже получен
// и СотрудникОбъект определен
Если ПустаяСтрока(ОтсканированныйШтрихкод) = 1 Тогда
Сообщить("Штрихкод не может быть пустым!", "!");
Возврат;
КонецЕсли;
Попытка
НовыйДокумент = СоздатьОбъект("Документ.ФиксацияСобытияСканера");
НовыйДокумент.Новый(); // Создаем новый документ
// Заполняем стандартные реквизиты даты и времени
НовыйДокумент.ДатаДок = ТекущаяДата();
НовыйДокумент.ВремяДок = ТекущееВремя();
НовыйДокумент.Штрихкод = ОтсканированныйШтрихкод;
// Привязываем сотрудника, если он найден
Если СотрудникОбъект.Выбран() = 1 Тогда
НовыйДокумент.Сотрудник = СотрудникОбъект.ТекущийЭлемент();
НовыйДокумент.Комментарий = "Зафиксировано событие для сотрудника " + СокрЛП(СотрудникОбъект.Наименование);
Иначе
НовыйДокумент.Комментарий = "Зафиксировано событие по неизвестному штрихкоду: " + ОтсканированныйШтрихкод;
КонецЕсли;
НовыйДокумент.ТипСобытия = "Вход"; // Например, тип события "Вход"
НовыйДокумент.Записать(); // Записываем документ
// Если документ не формирует движений, проведение не обязательно, но можно вызвать:
// НовыйДокумент.Провести();
Сообщить("Событие успешно зафиксировано документом!");
Исключение
Сообщить("Ошибка при создании документа события: "+ОписаниеОшибки(), "!");
КонецПопытка;
В 1С 7.7 отсутствует такой объект, как РегистрСведений, который предоставляет гибкие возможности для хранения непериодических или периодических срезов данных. Однако его функционал можно частично эмулировать, используя РегистрНакопления. Этот подход упомянут в сообщении 1 как возможность, хотя и требует некоторой доработки.
Мы создаем РегистрНакопления, который, по своей сути, предназначен для учета остатков и оборотов. Однако, если мы создадим его с одним или несколькими измерениями и одним или без ресурсов (или с ресурсом, который просто отмечает факт записи, например, числовым значением 1), он может работать как хранилище срезов. При этом нам потребуется создать "фиктивный" документ-регистратор, который не будет иметь видимой формы, но будет служить для записи движений в этот регистр.
РегистрНакопления, например, с именем СостоянияСотрудников.Периодичность в ПоСекундно, если нам нужна максимальная точность и возможность получать срез на конкретный момент времени.ТипРегистра в Остатки (для хранения срезов) или Обороты (если каждое событие - это просто факт, а не изменение состояния).Сотрудник: тип Справочник.Сотрудники, ключевое измерение.Штрихкод: тип Строка, для дополнительной привязки.ТипСобытия: тип Перечисление.ТипыСобытийСканера или Строка, для классификации события.ФактСобытия: тип Число, длина 1, точность 0. Этот ресурс будет просто служить индикатором того, что запись существует. Его значение всегда будет 1.Документ, например, РегистраторСобытийСканера. Этот документ будет иметь минимум реквизитов (возможно, только дату и время) и не будет иметь собственной формы, но будет использоваться исключительно для записи движений в наш регистр СостоянияСотрудников.
Перем ОтсканированныйШтрихкод;
Перем СотрудникОбъект; // Объект справочника Сотрудники
// Предположим, что ОтсканированныйШтрихкод уже получен
// и СотрудникОбъект определен
Если ПустаяСтрока(ОтсканированныйШтрихкод) = 1 Тогда
Сообщить("Штрихкод не может быть пустым!", "!");
Возврат;
КонецЕсли;
Попытка
// 1. Создаем "фиктивный" документ-регистратор
ДокРег = СоздатьОбъект("Документ.РегистраторСобытийСканера");
ДокРег.Новый();
ДокРег.ДатаДок = ТекущаяДата();
ДокРег.ВремяДок = ТекущееВремя();
// Возможно, можно добавить какие-то реквизиты в документ для общего понимания,
// например, ШтрихкодИлиСотрудник
// ДокРег.ШтрихкодСобытия = ОтсканированныйШтрихкод;
ДокРег.Записать(); // Записываем документ, чтобы он стал регистратором
// 2. Делаем движения по регистру
Рег = СоздатьОбъект("Регистр.СостоянияСотрудников");
Рег.УстановитьДокумент(ДокРег); // Связываем движения с нашим документом
// Удаляем предыдущие движения этого документа, если он ранее проводился
Рег.УдалитьСтроки();
Рег.НоваяСтрока(); // Добавляем новую строку движения
Рег.Сотрудник = СотрудникОбъект.ТекущийЭлемент(); // Привязка к сотруднику
Рег.Штрихкод = ОтсканированныйШтрихкод;
Рег.ТипСобытия = "Вход"; // Тип события
Рег.ФактСобытия = 1; // Просто индикатор факта
// Записываем движения по регистру
Рег.Записать();
// 3. Проводим документ, чтобы движения были записаны в базу
ДокРег.Провести();
Сообщить("Событие успешно записано в регистр!");
Исключение
Сообщить("Ошибка при записи события в регистр: "+ОписаниеОшибки(), "!");
КонецПопытка;
ЖурналРегистрации — это встроенный механизм 1С, предназначенный для логирования системных и пользовательских событий. Он автоматически фиксирует множество полезной информации, такой как дата, время, пользователь, метаданные. Форумчане обсуждают этот вариант в сообщениях 11-15.
Мы можем использовать функцию ЗаписатьЖурналРегистрации() для добавления информации о событии от сканера. Система автоматически сохранит эту запись вместе с другой системной информацией.
Перем ОтсканированныйШтрихкод;
Перем СотрудникИмя; // Имя сотрудника
// Предположим, что ОтсканированныйШтрихкод и СотрудникИмя уже определены
Если ПустаяСтрока(ОтсканированныйШтрихкод) = 1 Тогда
Сообщить("Штрихкод не может быть пустым!", "!");
Возврат;
КонецЕсли;
Попытка
// Записываем событие в журнал регистрации
ЗаписатьЖурналРегистрации(
"СобытиеСканера", // Вид события
"Информация", // Уровень события
ТекущийПользователь(), // Пользователь, который инициировал событие
"Сотрудник", // Метаданные (например, имя объекта)
СотрудникОбъект, // Объект метаданных (ссылка на элемент справочника Сотрудники)
"Отсканирован штрихкод: " + ОтсканированныйШтрихкод + " сотрудником: " + СотрудникИмя + ". Тип события: Вход." // Подробное описание
);
Сообщить("Событие записано в журнал регистрации.");
Исключение
Сообщить("Ошибка при записи события в журнал регистрации: "+ОписаниеОшибки(), "!");
КонецПопытка;
Несмотря на простоту записи, мы повторно подчеркиваем, что извлечение и систематизация этих данных для формирования бизнес-отчетов будет крайне трудоемкой.
Этот метод является наиболее простым с точки зрения реализации, так как не требует изменений конфигурации 1С. Он был упомянут в сообщении 10.
При каждом событии от сканера мы записываем соответствующую строку информации (например, дата, время, штрихкод) в обычный текстовый файл на диске.
Перем ОтсканированныйШтрихкод;
Перем СотрудникИмя; // Имя сотрудника
Перем ТипСобытияСтрока; // Строковое представление типа события
// Предположим, что ОтсканированныйШтрихкод, СотрудникИмя, ТипСобытияСтрока уже определены
Если ПустаяСтрока(ОтсканированныйШтрихкод) = 1 Тогда
Сообщить("Штрихкод не может быть пустым!", "!");
Возврат;
КонецЕсли;
Попытка
ИмяКаталога = "C:\Events\";
// Проверяем существование каталога, если нет - создаем
Если ФС.СуществуетКаталог(ИмяКаталога) = 0 Тогда
ФС.СоздатьКаталог(ИмяКаталога);
КонецЕсли;
ИмяФайла = ИмяКаталога + "Log" + Формат(ТекущаяДата(), "ДДММГГГГ") + ".csv"; // Имя файла для текущего дня
ТекстФайла = СоздатьОбъект("Текст");
// Проверяем, существует ли файл, чтобы добавить заголовок только один раз
Если ФС.СуществуетФайл(ИмяФайла) = 0 Тогда
ТекстФайла.Новая();
ТекстФайла.ДобавитьСтроку("ДатаВремя;Штрихкод;Сотрудник;ТипСобытия"); // Заголовок CSV
Иначе
// Открываем существующий файл для добавления в конец
ТекстФайла.Прочитать(ИмяФайла);
КонецЕсли;
// Формируем строку события в CSV формате
СтрокаСобытия = Формат(ТекущаяДата(), "ДФ=дд.ММ.гггг ЧЧ:мм:сс") + ";" + ОтсканированныйШтрихкод + ";" + СотрудникИмя + ";" + ТипСобытияСтрока;
ТекстФайла.ДобавитьСтроку(СтрокаСобытия); // Добавляем новую строку
ТекстФайла.Записать(ИмяФайла); // Записываем изменения в файл
Сообщить("Событие записано в текстовый файл: " + ИмяФайла);
Исключение
Сообщить("Ошибка при записи события в текстовый файл: "+ОписаниеОшибки(), "!");
КонецПопытка;
Этот способ является крайне нежелательным для долгосрочного хранения и интеграции с 1С, так как он создает "изолированный" массив данных, который сложно обрабатывать программными средствами 1С.
При выборе оптимального способа хранения событий в 1С 7.7 мы рекомендуем основываться на следующих критериях:
Как мы выяснили, в 1С 7.7 существует несколько жизнеспособных подходов к хранению событий от сканеров штрихкодов. Для большинства типовых задач, таких как учет времени прихода/ухода сотрудников или фиксация простых операций, создание отдельного справочника или документа с необходимыми реквизитами будет самым простым, эффективным и поддерживаемым решением. Если же ваша задача требует высокопроизводительных выборок, работы с периодическими данными или сложной аналитики по состояниям объектов, и вы готовы к более сложной реализации, то эмуляция регистра сведений на базе регистра накопления предоставит вам максимальную гибкость и производительность. Важно тщательно оценить требования вашего проекта, объем ожидаемых данных и возможности по дальнейшей поддержке системы, прежде чем принимать окончательное решение.