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

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

1. Примитивные типы данных

Примитивные (простые) типы — это базовые "кирпичики", из которых строятся все остальные структуры данных в . Они не имеют внутренней структуры и хранят одно значение. К этой категории относятся Число, Строка, Дата, Булево и Null.

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

  • 🔢 Число — используется для хранения целых и дробных значений. Поддерживает арифметические операции (+, -, *, /) и функции округления (Окр(), Цел()). Пример: Сумма = 1000.50.
  • 📜 Строка — последовательность символов в кодировке Unicode. Операции включают конкатенацию (+), поиск подстрок (Найти()) и форматирование (СтрШаблон()). Пример: Приветствие = "Добрый день, " + ИмяПользователя.
  • 📅 Дата — хранит дату и время с точностью до секунды. Поддерживает арифметику дат (добавление дней, месяцев) и форматирование (Формат()). Пример: СрокИстекает = ТекущаяДата() + 30.
  • Булево — логический тип с двумя значениями: Истина или Ложь. Используется в условиях (Если...) и циклах. Пример: ДокументПроведен = Истина.
  • Null — специальное значение, обозначающее "ничего" или "неопределённость". Возвращается, если переменная не инициализирована или функция не вернула результат. Пример: Если Значение = Null Тогда....
⚠️ Внимание: При сравнении значений типа Null с другими типами всегда возвращается Ложь, даже если сравниваются два Null. Для проверки на Null используйте конструкцию Значение = Null или функцию ЗначениеЗаполнено().
📊 Какой примитивный тип данных вы используете чаще всего?
Число
Строка
Дата
Булево

2. Сложные типы данных: коллекции и структуры

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

Наиболее востребованные сложные типы:

  • 📋 Массив — упорядоченный список элементов с доступом по индексу (начинается с 0). Пример: СписокТоваров = Новый Массив(3); СписокТоваров[0] = "Молоко".
  • 🔗 Структура — набор пар "ключ-значение", где ключом выступает строка. Удобна для хранения настроек или параметров. Пример: Параметры = Новый Структура("Цвет, Размер", "Красный", 42).
  • 🔄 Соответствие — аналогично структуре, но ключи могут быть любыми типами (не только строками). Пример: Сопоставление = Новый Соответствие; Сопоставление.Вставить(1, "Один").
  • 📊 СписокЗначений — коллекция с возможностью хранения не только значений, но и их представлений (отображаемых имен). Пример: Список = Новый СписокЗначений; Список.Добавить(1, "Первый элемент").
  • 🔍 ТаблицаЗначений — двумерная структура с колонками и строками, аналогичная таблице в базе данных. Пример: Таблица = Новый ТаблицаЗначений; Таблица.Колонки.Добавить("Наименование").

Особое внимание заслуживает ТаблицаЗначений — этот тип часто используется для временного хранения данных перед записью в базу или для обработки результатов запросов. Например, вы можете загрузить данные из Excel в таблицу значений, а затем перенести их в документ .

Тип данных Пример создания Типичное использование
Массив Новый Массив(5) Хранение однотипных данных (например, список ID документов)
Структура Новый Структура("Ключ1, Ключ2", Значение1, Значение2) Передача параметров в функции, конфигурационные настройки
ТаблицаЗначений Новый ТаблицаЗначений; Таблица.Колонки.Добавить("Поле1") Обработка результатов запросов, импорт/экспорт данных
💡

Для ускорения работы с большими коллекциями используйте метод Индексировать() для массивов и таблиц значений. Это значительно сокращает время поиска элементов по значению.

3. Ссылочные типы: работа с объектами метаданных

Ссылочные типы данных в представляют собой ссылки на объекты метаданных: документы, справочники, регистры и т.д. Они позволяют манипулировать данными базы без прямого обращения к SQL. Например, переменная типа СправочникСсылка.Номенклатура хранит ссылку на конкретный элемент справочника "Номенклатура".

Ключевые особенности ссылочных типов:

  • 🔗 Они всегда ссылаются на существующий объект в базе (или на Null, если ссылка пустая).
  • 🔄 Поддерживают методы для получения и изменения данных объекта (например, ПолучитьОбъект(), Записать()).
  • 📌 Имеют уникальный идентификатор (УникальныйИдентификатор()), который не меняется при переносе данных между базами.

Пример работы со ссылочным типом:

// Получаем ссылку на элемент справочника "Контрагенты" по наименованию

СсылкаНаКонтрагента = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");

// Проверяем, найден ли элемент

Если СсылкаНаКонтрагента.Пустая() Тогда

Сообщить("Контрагент не найден!");

Иначе

ОбъектКонтрагента = СсылкаНаКонтрагента.ПолучитьОбъект();

ОбъектКонтрагента.Адрес = "ул. Ленина, 10";

ОбъектКонтрагента.Записать();

КонецЕсли;

⚠️ Внимание: При работе со ссылочными типами избегайте "висячих ссылок" — ситуаций, когда в коде остаются ссылки на удалённые объекты. Это может привести к ошибкам при выполнении операций. Всегда проверяйте ссылки на пустоту с помощью метода Пустая().

4. Типы данных для работы с файлами и двоичными данными

Для обработки файлов, изображений и других двоичных данных в предусмотрены специализированные типы:

  • 📄 ДвоичныеДанные — хранит произвольные байты (например, содержимое файла). Пример: Данные = Новый ДвоичныеДанные(ФайлПрочитать("C:\image.png")).
  • 📎 ХранилищеЗначения — контейнер для хранения любых данных (включая объекты) в двоичном виде. Используется для сериализации. Пример: Хранилище = Новый ХранилищеЗначения(ОбъектДокумента).
  • 🖼️ Картинка — специализированный тип для работы с изображениями (JPEG, PNG, BMP). Поддерживает масштабирование и сохранение. Пример: Логотип = Новый Картинка("C:\logo.jpg").

ДвоичныеДанные и ХранилищеЗначения часто путают, но их назначение принципиально разное: ДвоичныеДанные хранят "сырые" байты (например, PDF-файл), а ХранилищеЗначения предназначено для сериализации объектов 1С (документов, справочников) с возможностью последующего восстановления.

Пример сохранения и восстановления объекта через ХранилищеЗначения:

// Сериализация документа в хранилище

Хранилище = Новый ХранилищеЗначения(ДокументОбъект);

ДвоичныеДанные = Хранилище.ПолучитьДвоичныеДанные();

// Сохранение в файл

ДвоичныеДанные.Записать("C:\backup.doc");

// Восстановление из файла

ВосстановленныеДанные = Новый ДвоичныеДанные("C:\backup.doc");

Хранилище = Новый ХранилищеЗначения(ВосстановленныеДанные);

ВосстановленныйДокумент = Хранилище.Получить();

Как отличить ДвоичныеДанные от ХранилищеЗначения в коде?

Оба типа могут хранить двоичную информацию, но ХранилищеЗначения имеет методы Получить() и Установить() для работы с объектами 1С, тогда как ДвоичныеДанные оперирует только байтами и поддерживает методы Записать()/Прочитать() для файлов.

5. Типы данных для работы с запросами и результатами

При выполнении запросов к базе данных возвращает результаты в виде специализированных типов:

  • 📋 РезультатЗапроса — содержит данные, полученные после выполнения запроса. Поддерживает итерацию по строкам. Пример: Результат = Запрос.Выполнить().Выбрать().
  • 🔍 ВыборкаДанных — используется для пострчного чтения больших наборов данных (экономит память). Пример: Пока Выборка.Следующий() Цикл ... КонецЦикла.
  • 📊 ТаблицаРезультата — альтернативный формат результата запроса, аналогичный ТаблицаЗначений, но оптимизированный для чтения.

Пример обработки результата запроса:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Наименование КАК Товар,

| СУММА(Документ.Количество) КАК Итого

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Документ

| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

| ПО Документ.Номенклатура = Номенклатура.Ссылка

|ГДЕ

| Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

|СГРУППИРОВАТЬ ПО

| Номенклатура.Наименование";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(СтрШаблон("Товар: %1, Количество: %2", Выборка.Товар, Выборка.Итого));

КонецЦикла;

⚠️ Внимание: При работе с большими выборками данных (тысячи строк) всегда используйте ВыборкаДанных вместо загрузки всего результата в память через Выгрузить(). Это предотвратит переполнение памяти и зависание системы.

Использовать индексированные поля в условиях (ГДЕ)

Ограничивать период выборки параметрами

Избегать SELECT * — указывать только нужные поля

Применять СГРУППИРОВАТЬ ПО вместо обработки дублей в коде

Для больших данных использовать ПАКЕТНЫЙ режим-->

6. Пользовательские типы данных: перечисления и определения типов

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

  • 🔖 Перечисление — набор предопределённых значений (например, "ВидыОплаты": Наличные, Безналичные, Карта). Пример: Если ВидОплаты = Перечисления.ВидыОплаты.Наличные Тогда....
  • 📌 ОпределениеТипов — позволяет создавать псевдонимы для сложных типов. Пример: Тип МояСтруктура = Новый ОписаниеТипов("Структура", Новый ОписаниеТипов("Число", "Строка")).

Пример использования Перечисления:

// Создание перечисления в конфигураторе

Перечисление ВидыДоставки

{

Самовывоз,

Курьер,

Почта,

ТранспортнаяКомпания

}

// Использование в коде

Если ВидДоставки = Перечисления.ВидыДоставки.Курьер Тогда

СтоимостьДоставки = 300;

КонецЕсли;

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

7. Особенности работы с типами данных в разных режимах 1С

Поведение типов данных может отличаться в зависимости от режима работы 1С:Предприятие:

  • 🖥️ Толстый клиент — поддерживает все типы данных без ограничений, включая работу с файлами и двоичными данными.
  • 🌐 Тонкий клиент — имеет ограничения на работу с файловой системой (например, нельзя прочитать файл с диска без диалога выбора).
  • 📱 Веб-клиент — аналогично тонкому клиенту, плюс ограничения на размер передаваемых данных (например, большие двоичные данные могут не передаваться).
  • 🤖 Сервер — оптимизирован для работы с базами данных, но не имеет доступа к файловой системе напрямую.

Пример кода, который будет работать по-разному в тонком и толстом клиенте:

// Этот код вызовет ошибку в тонком клиенте

ПутьКФайлу = "C:\temp\data.txt";

Текст = Новый ЧтениеТекста(ПутьКФайлу);

Содержимое = Текст.Прочитать();

// Альтернатива для тонкого клиента (с диалогом выбора файла)

ПутьКФайлу = ОткрытьФайлДиалог("Выберите файл");

Если Не ПутьКФайлу = Неопределено Тогда

Текст = Новый ЧтениеТекста(ПутьКФайлу);

Содержимое = Текст.Прочитать();

КонецЕсли;

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

8. Практические рекомендации по выбору типов данных

Выбор правильного типа данных — залог эффективной и надёжной работы системы. Вот ключевые рекомендации:

  • 🔢 Для денежных расчётов всегда используйте Число с указанием точности (например, Число(10, 2) для рублей и копеек). Избегайте типа Дробь, так как он может приводить к ошибкам округления.
  • 📅 Для хранения дат без времени используйте формат Дата(Год, Месяц, День), а не строки. Это позволит корректно сравнивать даты и выполнять арифметические операции.
  • 📋 Для больших наборов данных отдавайте предпочтение ТаблицаЗначений вместо массивов — она оптимизирована для работы с памятью и поддерживает колонки с разными типами.
  • 🔗 При передаче данных между системами (например, через JSON) используйте Структура или Массив, так как они легко сериализуются.

Пример оптимизированного кода для работы с денежными значениями:

// Плохо: использование строк для денежных расчётов

СуммаСтрокой = "1000.50";

Итог = СуммаСтрокой + 10; // Ошибка! Нельзя складывать строку и число

// Правильно: явное приведение к числу с указанием точности

Сумма = Число(1000.50);

Итог = Окр(Сумма + 10, 2); // 1010.50

💡

Всегда проверяйте типы данных на границе систем (при обмене с внешними сервисами, чтении из файлов, работе с API). Неявное приведение типов — частая причина ошибок в интеграционных решениях.

FAQ: Частые вопросы о типах данных в 1С

Как преобразовать строку в число, если строка содержит разделители тысяч?

Используйте функцию Число() с предварительной очисткой строки от лишних символов:

СтрокаСуммы = "1 234 567,89";

ЧистаяСтрока = СтрЗаменить(СтрокаСуммы, " ", "");

ЧислоСуммы = Число(ЧистаяСтрока);

Или используйте СтрЗаменить() для замены запятой на точку, если требуется англоязычный формат:

ЧислоСуммы = Число(СтрЗаменить(СтрокаСуммы, ",", "."));
Почему при сравнении двух дат в 1С получаю неожиданный результат?

Убедитесь, что сравниваемые значения имеют один и тот же тип. Например, Дата(2023, 1, 1) и "01.01.2023" (строка) не будут равны. Всегда приводите строки к типу Дата:

Дата1 = Дата(2023, 1, 1);

Дата2 = Дата(СтрокаДата); // Преобразуем строку в дату

Если Дата1 = Дата2 Тогда...

Как сохранить в 1С данные произвольного типа (например, настройки формы)?

Используйте ХранилищеЗначения для сериализации сложных данных:

// Сохранение

Настройки = Новый Структура("Цвет, РазмерШрифта", "Синий", 12);

Хранилище = Новый ХранилищеЗначения(Настройки);

ДвоичныеДанные = Хранилище.ПолучитьДвоичныеДанные();

ДвоичныеДанные.Записать("C:\settings.dat");

// Восстановление

Данные = Новый ДвоичныеДанные("C:\settings.dat");

Хранилище = Новый ХранилищеЗначения(Данные);

ВосстановленныеНастройки = Хранилище.Получить();

Можно ли в 1С создать свой тип данных, аналогичный классу в OOP?

Полноценных классов, как в объектно-ориентированных языках, в 1С нет. Однако вы можете:

  1. Использовать Структуру для хранения данных и набор функций для их обработки.
  2. Создавать Общие модули с процедурами и функциями, имитирующими методы класса.
  3. В новых версиях платформы (8.3.20+) доступны Классы в языке 1С:Enterprise, но их поддержка ограничена.

Пример имитации класса:

// В общем модуле "МойКласс"

Перем Данные Экспорт;

Процедура Инициализировать(Знач Параметры) Экспорт

Данные = Новый Структура;

Данные.Вставить("Имя", Параметры.Имя);

Данные.Вставить("Возраст", Параметры.Возраст);

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

Функция ПолучитьИмя() Экспорт

Возврат Данные.Имя;

КонецФункции

// Использование

МойКласс.Инициализировать(Новый Структура("Имя, Возраст", "Иван", 30));

Имя = МойКласс.ПолучитьИмя();

Как узнать тип переменной в 1С во время выполнения?

Используйте функцию ТипЗнч() или ТипЗначения():

Переменная = 100;

Тип = ТипЗнч(Переменная); // Вернёт "Число"

Если Тип = Тип("Число") Тогда

Сообщить("Это число!");

КонецЕсли;

Для проверки сложных типов (например, ссылок на справочники) используйте конструкцию:

Если ТипЗнч(Ссылка) = Тип("СправочникСсылка.Контрагенты") Тогда

Сообщить("Это ссылка на контрагента!");

КонецЕсли;