1С вам об этом не скажет: 20 ошибок, которые не ловит ни конфигуратор, ни тесты

22.09.26

Разработка - Инструментарий разработчика

Ошибки, которые падают, находит кто угодно за пять минут. Опаснее те, что возвращают правдоподобный результат: код компилируется, синтаксический контроль проходит, BSL Language Server молчит, тесты зеленые, а цифры неверные. Двадцать таких мест. Минус из Excel, который тихо становится нулем. Реквизит формы, который на 8.3 падает, а на 8.5 работает. Пересобранная обработка, которая выполняет старый код. Состояние() на сервере: в толстом клиенте молчит, в тонком не дает собрать модуль. Все выполнимое выполнено на живой Бухгалтерии 3.0 и повторено на двух платформах, 8.3.27.2214 и 8.5.1.1343. Пять пунктов черновика не подтвердились. Они не выброшены, а переписаны по тому, что показала платформа, и в двух местах правда оказалась интереснее заготовки. К статье приложены две обработки: восемь проверок по XML-выгрузке и та, которой проверялись утверждения статьи, двадцать шесть проверок на вашей базе одной кнопкой.

Бесплатные

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Узнавайте о новых бесплатных решениях в нашей телеграм-группе Инфостарт БЕСПЛАТНО

Наименование Скачано Бесплатно
Тихие ошибки: восемь проверок по XML-выгрузке
. 16,15Kb
35 Скачать бесплатно
Проверка поведения платформы: 26 проверок на вашей базе
.epf 15,24Kb
39 Скачать бесплатно

Вы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

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

Искали втроём. Нашли случайно: в имени переменной затесалась латинская o. КоличествoПроводки и КоличествоПроводки — на экране это одно слово, для платформы два разных. Одно получало значение, второе оставалось пустым.

С тех пор мы у себя делим ошибки не на «простые и сложные», а на две категории: те, которые падают, и те, которые возвращают правдоподобный результат. Вторые страшнее, но и первые попали в список: часть из них падает не там и не тогда, когда вы этого ждёте, и текст ошибки причины не называет. Первые находит кто угодно за пять минут. Вторые живут в базе месяцами, потому что о них никто не сообщает: код компилируется, синтаксический контроль проходит, BSL Language Server ничего не говорит, тесты зелёные. Узнаете вы о них от бухгалтера, и не сразу.

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

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

Сначала о том, что изменилось после первой публикации

Читатели нашли в первой редакции две фактические ошибки, и обе оказались в утверждениях вида «так нельзя». Это, как выяснилось, мой систематический промах: всё, что формулируется как «работает так», я прогнал на живой базе, а всё, что формулируется как «не работает никак», проверял рассуждением. Рассуждение — не проверка: чтобы доказать «нельзя», надо перебрать все способы, а чтобы опровергнуть, читателю хватает одного.

Что поправлено:

  • bulpi — пункт 5.2. Прочитать() действительно раскладывает листы

в коллекцию Области, границы достаются оттуда, никакой zip для этого не нужен. Перепроверил на двух платформах, добавил то, чего не было и в замечании.

  • DmitryKSL, ixijixi, NeLyubluSKD — пункт 4.1. Фоновые задания

внешней обработке доступны. Пункт переписан целиком, с прогоном.

  • vadim1011985 — пункт 2.4. Латинская буква в имени видна по подсветке

идентификатора прямо в конфигураторе, без всякого разбора выгрузки.

  • coollerinc — новый пункт 1.5 про ЗаполнитьЗначенияСвойств без третьего

параметра и про то, как чужое значение молча уходит в ссылочный реквизит.

Спасибо всем шестерым, ветка вышла полезнее самой статьи )) Что до доверия к остальному тексту: всё выполнимое я выполнил на живых базах, Бухгалтерии 3.0 и Управлении торговлей 11.5, на 8.3.27.2214 и 8.5.1.1343, а проверки по выгрузке гонял ещё и по ERP. К статье приложены две обработки. Где проверить не удалось, я это говорю прямо в пункте.


1. Молчаливая потеря данных

Худшая категория. Программа работает, данные портятся.

1.1. Минус из Excel превращается в ноль

Читаем число из текста ячейки — так, как это делают в каждой второй загрузке из файла:

Попытка
    Сумма = Число(ТекстЯчейки);
Исключение
    Сумма = 0;
КонецПопытки;

Минус в выгрузке из Excel — это часто не дефис (-, U+002D), а типографский знак минуса (−, U+2212) или короткое тире (–, U+2013): так его расставляет сам Excel при форматировании. Число() на такой строке падает, и обёртка Попытка честно превращает падение в ноль. Все отрицательные суммы становятся нулями, ни одна строка не сообщает об ошибке, итог не сходится ровно на сумму всех минусов.

Какой символ ломает преобразование, надо знать поимённо, потому что интуиция тут ошибается. Шесть вариантов, прогнанных в живой базе:

Сообщить(Число("-1500"));                      // -1500, обычный дефис
Сообщить(Число("W22;1500"));                      // исключение: знак минуса U+2212
Сообщить(Число("–1500"));                      // исключение: короткое тире U+2013
Сообщить(Число("-1" + Символ(160) + "500"));   // -1500, неразрывный пробел проходит
Сообщить(Число("-1 500"));                     // исключение: обычный пробел не проходит
Сообщить(Число("-1500,25"));                   // -1500,25, запятая проходит

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

Лечится нормализацией до преобразования, и без глотания исключения в ноль:

Текст = СтрЗаменить(ТекстЯчейки, Символ(8722), "-");   // минус U+2212
Текст = СтрЗаменить(Текст, Символ(8211), "-");         // тире U+2013
Текст = СтрЗаменить(Текст, Символ(160), "");           // неразрывный пробел, на всякий случай
Текст = СтрЗаменить(Текст, " ", "");                   // а вот этот обязателен
Сумма = Число(Текст);   // без Попытки: пусть падает, если всё ещё не число

А у вас в тестовых данных вообще есть отрицательные суммы?

Увидеть это можно только тестом на файле с отрицательными значениями, сохранённом из настоящего Excel, а не набранном руками в блокноте. Нет минусов в тестовых данных — не увидите никогда.

1.2. Реквизит с ограничением знака обнуляет минус

Движение.Сумма = -1500;
Набор.Записать();

Если у реквизита в конфигураторе стоит галка «Неотрицательное» (в XML выгрузки это AllowedSign со значением Nonnegative), записанное отрицательное значение становится нулём. Без сообщения, без исключения, без отметки в журнале.

И обнуляется, как оказалось, не при записи, а уже при присваивании: Объект.Реквизит = -1500; Сообщить(Объект.Реквизит); печатает 0 ещё до всякого Записать(). Проверяли в типовой Бухгалтерии на реквизите справочника с таким ограничением, в транзакции с откатом: ноль появляется в ту же секунду, что и присваивание.

В выгрузке это ищется по AllowedSign. В типовой Бухгалтерии таких реквизитов 233 в 119 справочниках, так что наткнуться проще, чем кажется. Считать надо именно реквизиты объектов: у реквизитов форм ограничение знака тоже встречается, но там оно безобидное, в базу они не пишутся.

1.3. КонецДня() делает пустую дату заполненной

Границу периода приводят к концу дня, а где-то раньше по коду ДатаПо уже прошла через КонецДня() или через арифметику с секундами.

Пустая = '00010101';
Сообщить(ЗначениеЗаполнено(Пустая));              // Ложь
Сообщить(ЗначениеЗаполнено(КонецДня(Пустая)));    // Истина
Сообщить(ЗначениеЗаполнено(Пустая + 5));          // Истина

Пустая дата в 1С — это 01.01.0001 00:00:00. После КонецДня() она становится 01.01.0001 23:59:59, а это уже заполненная дата. Проверка «пользователь не указал период» перестаёт работать, и запрос молча отбирает пустоту.

Проверять заполненность надо до любых преобразований, а результат запоминать в отдельную переменную. В ручном тестировании период обычно заполняют — поэтому и не всплывает.

1.4. Субконто в виртуальной таблице роняет счёт из выборки

В виртуальную таблицу остатков добавляют субконто, рассчитывая просто получить его в выборке:

ВЫБРАТЬ
    Остатки.Счет,
    Остатки.Субконто1,
    Остатки.СуммаОстатокДт
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(
        &Дата,
        Счет В ИЕРАРХИИ(&Счета),
        &ВидыСубконто           // <- вот здесь
    ) КАК Остатки

Счета, у которых такого вида субконто нет, пропадают из результата целиком. Не с нулями — их просто не будет. Отчёт выглядит нормальным: строки есть, суммы правдоподобные, итог меньше настоящего ровно на те счета, о которых вы не узнали. По коду это не видно, запрос синтаксически безупречен. Ловится только сверкой итога с оборотно-сальдовой ведомостью.

Либо не указывайте виды субконто в параметрах виртуальной таблицы и получайте разрез отдельным соединением, либо собирайте две выборки и объединяйте.

1.5. ЗаполнитьЗначенияСвойств без третьего параметра

Этот пункт появился из комментария coollerinc к первой редакции, и он хорошо ложится в раздел: типичная тихая потеря.

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтараяСтрока);

Пока имена совпадают, всё хорошо. Кто-то переименовал реквизит в источнике — и заполнение этого реквизита просто перестаёт происходить. Ни ошибки, ни предупреждения: процедура копирует то, что нашла по совпадению имён, а чего не нашла, о том и не скажет. Месяц спустя выясняется, что колонка пустая.

Если перечислить свойства третьим параметром, платформа честно упадёт с «Поле 'X' не обнаружено», и вы узнаете об этом в первую же минуту. Проверил на БП 3.0 и УТ 11.5: с третьим параметром падает, без него молчит.

Универсальное заполнение — законный приём, и coollerinc в комментарии это оговаривает: если вы осознанно допускаете, что какой-то реквизит не заполнится, всё в порядке. Беда начинается, когда третий параметр не написали не по решению, а по привычке.

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


2. Падает там, где не ждёшь

Эти как раз падают, но в момент, когда вы этого не ожидаете, и с текстом, который не подсказывает причину.

2.1. XMLСтрока не берёт наборы записей

Снимок = СериализаторXDTO.XMLСтрока(НаборЗаписей);

Исключение: «Отсутствует отображение для типа РегистрСведенийНаборЗаписей.<Имя>». Сериализатор пишет значение без явного указания типа, а для набора записей такого отображения нет.

Снимок = ОбщегоНазначения.ЗначениеВСтрокуXML(НаборЗаписей);

Эта функция БСП делает то же самое с явным назначением типа — так БСП версионирует наборы записей у себя. Коварство в том, что на объектных типах XMLСтрока работает прекрасно, и переход на набор записей выглядит безобидным рефакторингом.

2.2. Обращение к члену у результата Новый не компилируется

ИмяФайла = Новый Файл(Путь).ПолноеИмя;

Это не ошибка выполнения, это ошибка компиляции модуля: «Неопознанный оператор». Модуль не собирается целиком, обработка не откроется вовсе. И не подсвечивает ни редактор, ни BSL Language Server: проверил специально — на этой конструкции линтер ничего не показывает. Не путайте с пунктом 5.1: там платформа отвечает так же, «Неопознанный оператор», но конструкция другая, и её линтер как раз ловит. Здесь же всё выглядит нормально для человека, пришедшего из любого другого языка.

Через переменную, всегда. Если конструкция попала в редко используемую ветку большого модуля, узнаете нескоро.

2.3. Имя глобального объекта в переменной

Называем локальную переменную удачным по смыслу словом:

ДопустимаяДлина = Метаданные.Справочники.Номенклатура.ДлинаНаименования;

Компилятор ничего не говорит. BSL Language Server тоже. В рантайме: «Поле объекта недоступно для записи (ДопустимаяДлина)». Имя занято системным перечислением платформы.

У меня на этом не записалось 49 элементов из 49: цикл падал на первой же итерации, а сообщение про длину наименования не говорило ничего.

Имена занимает не только платформа. Пока я собирал проверки к этой статье, дважды поймал себя на том же: переменная Знач не компилируется вообще (это модификатор параметра «по значению»), а процедура с именем Открыть в модуле управляемой формы даёт «Процедура или функция с указанным именем уже определена» — так называется собственный метод формы.

Списка таких имён нигде нет одним куском, и построить его автоматически по коду конфигурации, как выяснилось, не получается: эвристика «имя всегда употребляется с точкой и ни разу не присваивается» на типовой даёт десятки тысяч кандидатов и при этом теряет настоящие платформенные объекты. Так что ловится только запуском.

2.4. Латинская буква внутри кириллического имени

Буква попадает сама — при копировании из письма, из документа, из чужого кода, при переключении раскладки. КоличествoПроводки с латинской o — это другое имя, чем КоличествоПроводки. Два разных идентификатора, визуально неотличимых.

Вставьте в консоль как есть:

ИтогоКоличество = 0;
Для Счетчик = 1 По 3 Цикл
    ИтогoКоличество = ИтогоКоличество + Счетчик;   // слева латинская o
КонецЦикла;
Сообщить(ИтогоКоличество);                          // 0, а не 6

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

Самый простой способ увидеть это — прямо в конфигураторе, и подсказал его в комментариях vadim1011985. Сервис → Параметры → Модули → Редактирование, выделение цветом синтаксических конструкций: «Текущий идентификатор» и «Выбранный идентификатор». Ставите курсор на имя — конфигуратор подсвечивает все его вхождения. Двойник с латинской буквой не подсветится, и это видно мгновенно, без всякого разбора выгрузки. Приём стоит включить один раз и забыть.

Автоматически, по всей конфигурации, работает другой признак. Ругаться на любую латиницу внутри кириллического имени нельзя: СебестоимостьERP, ЗначениеВСтрокуXML, СохранитьВExcel совершенно законны, и такое правило на типовой ERP даёт тысячи ложных срабатываний. Точный признак — одно имя встречается в файле в двух написаниях. Нормализуйте латинские буквы-двойники в кириллические (ABCEHKMOPTXY → АВСЕНКМОРТХУ, acekmoptxy → асекмортху) и ищите нормализованные формы, у которых набралось больше одного исходного написания. Пока написание одно, код работает и имя просто выглядит странно. Вред начинается со второго.

Нормализацию делайте до понижения регистра: пары B/В и H/Н неразличимы только в верхнем регистре, а b/в и h/н — уже разные буквы.

2.5. Подстановка в закомментированную строку запроса

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

ТекстЗапроса = СтрЗаменить(ТекстЗапроса,
    "//ВСТАВИТЬ_ПОЛЯ", ДополнительныеПоля);

Если подставляемый текст многострочный, под комментарием остаётся только его первая строка. Хвост выходит из-под // и становится частью запроса, в произвольном месте. Запрос либо падает с невнятной ошибкой синтаксиса, либо, что хуже, выполняется и возвращает не то.

Якорь ставьте не в комментарии, а в самом теле запроса, и подставляйте в том порядке, в котором части запроса идут: сначала группировка, потом выборка. И распечатайте получившийся текст — отладчик показывает его уже собранным, достаточно один раз посмотреть.


3. Формы

3.1. Реквизит формы ХранилищеЗначения: на 8.3 не работает, на 8.5 работает

Добавляем на форму реквизит типа ХранилищеЗначения, чтобы положить туда картинку, таблицу или произвольные данные. Дальше зависит от версии платформы, и это самое неприятное. Собрали одну и ту же обработку и запустили на двух платформах.

На младшей платформе реквизит объявляется, обработка открывается, но реквизитом он только называется. ТипЗнч у него не ХранилищеЗначения, а ДанныеФормыСтруктура. Присвоить нельзя:

Ошибка при установке значения атрибута контекста (Хранилище):
Нельзя изменять поле, содержащее объект данных формы

а на клиенте у него нет и метода: «Метод объекта не обнаружен (Получить)».

На старшей тот же файл работает как задумано: присваивание проходит, ТипЗнч возвращает «Хранилище значения», значение доезжает до клиента, Получить() отдаёт то, что положили на сервере.

То есть код, написанный и проверенный на 8.5, у заказчика на 8.3 упадёт, и упадёт не там, где вы его писали, а при первом же присваивании.

Не зависеть от версии просто: держите данные во временном хранилище, а на форме только адрес строкой.

АдресДанных = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);
// ...
Данные = ПолучитьИзВременногоХранилища(АдресДанных);

Так, судя по всему, и поступают все: в выгрузке типовой Бухгалтерии мы просмотрели 7981 управляемую форму и не нашли ни одного реквизита типа ХранилищеЗначения. В своей выгрузке ищите реквизиты, у которых тип оканчивается на ValueStorage.

3.2. Расширение элемента формы адресуется не так, как выглядит в справке

В первой редакции этот пункт был написан неверно, и я его переписал.

Пишут по аналогии с другими свойствами:

Элементы.Поле.РасширениеПоляВвода.КнопкаВыбора = Ложь;

Так не работает, но не потому, что «такого объекта нет», как я писал раньше. В справке платформы есть целое семейство типов «Расширение поля ввода …» (справочника, документа, перечисления, цвета, шрифта и так далее), а для управляемых форм есть тип «Расширение поля формы для поля ввода». КнопкаВыбора описана именно там, а не в карточке ПолеФормы.

Разница в адресации. Свойства расширения платформа подмешивает прямо к элементу формы, когда его вид это позволяет. Отдельного вложенного объекта, через который к ним можно обратиться, у элемента нет, поэтому строка выше и не компилируется. А вот так всё в порядке:

Элементы.Поле.КнопкаВыбора = Ложь;

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

3.3. Булева колонка, которая рисуется текстом «Да»/«Нет»

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

Что я видел. В таблице на форме колонка булева типа выводится полем ввода, а не флажком. На экране пользователь видит слова «Да» и «Нет», читает их как вид операции или как статус и не догадывается, что по колонке можно щёлкнуть. Платформа при этом ничего не нарушила: просто вид поля оказался не тем, которого ждали.

В Form.xml признак однозначный. Две колонки одного и того же булева типа выглядят так:

<!-- рисуется галкой -->
<CheckBoxField name="Пометить" id="52">
    <DataPath>Дубли.Пометить</DataPath>
</CheckBoxField>

<!-- рисуется текстом «Да»/«Нет» -->
<InputField name="ЕстьВЭРП" id="70">
    <DataPath>Дубли.ЕстьВЭРП</DataPath>
</InputField>

Тип реквизита при этом один и тот же, и лежит он не рядом с элементом, а в разделе <Attributes>: для колонок таблиц и деревьев значений — внутри <Columns> у самого реквизита таблицы. Ищите InputField, чей путь к данным ведёт на реквизит с типом xs:boolean.

У себя мы нашли пять таких колонок, и все пять пользователь всё это время читал как текст. Подозреваю, причина в том, что формы у меня собираются генератором из XML, а не руками в конфигураторе: вид поля там надо задать явно, иначе останется поле ввода. А у вас так же выходит в чистом конфигураторе?

Напишите в комментариях, самому интересно.


4. Внешние обработки и отчёты

4.1. Фоновые задания внешней обработке доступны, но не через платформу напрямую

Пункт полностью переписан. В первой редакции он назывался «Фоновые задания внешней обработке недоступны» и был неверен. На это указали DmitryKSL, ixijixi и NeLyubluSKD, причём последний сразу назвал механизм. Спасибо, я прогнал и теперь могу показать, где именно проходит граница.

Прогон: живая БП 3.0, файловая база, обработка открыта файлом, обе платформы, результаты совпали.

Что пробовал Итог
ВнешниеОбработки.Подключить по файлу получилось, имя на сервере вернулось
ФоновыеЗадания.Выполнить("ВнешняяОбработка.<имя>.МодульОбъекта.Метод") не работает: «Метод задания не найден»
ДлительныеОперации.ВыполнитьВФоне без доп. параметра отказ с подсказкой: заполните ВнешнийОтчетОбработка
То же, но с заполненным ВнешнийОтчетОбработка выполнилось, статус «Выполнено»

Проверяли не по статусу задания, а по следу: метод внутри пишет файл. Файл появился, в нём номер сеанса, отличный от моего. То есть код действительно выполнился в фоне, а не «стартовал и тихо ничего не сделал».

Рабочий вариант целиком:

ПараметрыФона = ДлительныеОперации.ПараметрыВыполненияВФоне(Новый УникальныйИдентификатор);
ПараметрыФона.ОжидатьЗавершение = 60;
ПараметрыФона.ВнешнийОтчетОбработка = Новый ДвоичныеДанные(ПутьКФайлуОбработки);

ИмяМетода = "ВнешняяОбработка." + ИмяНаСервере + ".МодульОбъекта.ФоновыйМетод";
Результат = ДлительныеОперации.ВыполнитьВФоне(ИмяМетода, Параметры, ПараметрыФона);

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

Что остаётся правдой: голое платформенное ФоновыеЗадания.Выполнить метод внешней обработки не находит, даже если обработка подключена на сервере в текущем сеансе. Фоновое задание выполняется в другом сеансе, и подключение туда не переезжает. Именно на этом я и ошибся в первой редакции: проверил платформенный вызов, увидел отказ и распространил его на всё.

Отдельно признаю методическую ошибку. Прогон, которым я «проверял» этот пункт в первой редакции, передавал имя метода в формате общего модуля (ФоновыеЗадания.ФоновыйМетод) и поэтому измерял заведомо неправильное имя. Я оставил этот вариант в новой пробе отдельным опытом: он и сейчас падает, как и должен.

Если фоновое задание всё-таки недоступно (скажем, у вас не БСП), работает старый добрый способ: резать работу на порции и гонять их с клиента, подключая себя обработчиком ожидания. Прогресс и прерывание при этом живут на клиенте — там, где им и положено.

4.2. Состояние() в серверном коде: где молчит, а где не компилируется

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

&НаКлиентеНаСервереБезКонтекста
Процедура ОбработатьВсе(Данные)
    Счетчик = 0;
    Для Каждого Строка Из Данные Цикл
        Счетчик = Счетчик + 1;
        Состояние("Обработано: " + Счетчик);
        ОбработкаПрерыванияПользователя();
    КонецЦикла;
КонецПроцедуры

Состояние() и ОбработкаПрерыванияПользователя() — клиентские методы, сервера в списке их доступности нет. А вот что из этого выходит на практике, зависит от клиента, и я развёл это опытом: одна обработка, две директивы, два клиента.

Директива Толстый клиент Тонкий клиент
&НаСервере компилируется, отрабатывает молча ошибка компиляции
&НаКлиентеНаСервереБезКонтекста компилируется, с сервера молча ошибка компиляции

В тонком клиенте это громко и сразу:

{ВнешняяОбработка.Проба.Форма.Форма.Форма(36,2)}:
Процедура или функция с указанным именем не определена (Состояние)
        <<?>>Состояние("проба индикатора");

Модуль не собирается целиком, и вы узнаёте об этом при первом же открытии. Неприятно, зато сразу.

В толстом всё иначе: компилируется, вызов с сервера проходит без единого звука, прогресс не появляется, «Прервать» ни к чему не приводит, цикл крутится до конца. Пользователь видит зависшее окно и снимает сеанс. Отсюда обратная ловушка: написали и проверили в толстом — у заказчика на тонком обработка просто не откроется.

4.3. Пересобрали обработку, а выполняется прежняя версия

Правим обработку, пересобираем файл, открываем заново, и видим старое поведение. Правим ещё раз. Снова старое. Народное объяснение: платформа кэширует внешнюю обработку по имени объекта, поэтому надо версионировать имя объекта внутри файла.

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

А залипает уже открытое окно формы. В одном сеансе:

// шаг 1: подключили версию 1, открыли форму - ПриСозданииНаСервере отработала
ОткрытьФорму("ВнешняяОбработка." + Имя + ".Форма");

// шаг 2: подключили версию 2 тем же именем, открыли ту же форму
ОткрытьФорму("ВнешняяОбработка." + Имя + ".Форма");

На втором шаге модуль объекта уже отвечает «версия 2», а ПриСозданииНаСервере формы не выполняется вообще: платформа не создаёт вторую форму с тем же ключом, а показывает ту, что уже открыта, со старым кодом внутри. Добавьте признак уникальности, и та же строка создаст новую форму:

ОткрытьФорму("ВнешняяОбработка." + Имя + ".Форма", , , Истина);

Симптом знакомый, правда?

Добавили Сообщить("сюда дошли"), перезапустили, сообщения нет. Вывод «код не вызывается» верен буквально, но не потому, что выполняется прежняя версия файла, а потому что форму никто не создавал заново. Так что закрывайте окно перед тем, как открыть пересобранный файл, а переименовывать объект внутри не нужно — это лечение несуществующей болезни ))

4.4. ТекущаяДата() на клиенте, и почему замена на ТекущаяДатаСеанса() не компилируется

&НаКлиенте
Процедура СформироватьИмяФайла()
    Имя = "выгрузка_" + Формат(ТекущаяДата(), "ДФ='yyyyMMdd_HHmmss'");
КонецПроцедуры

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

BSL Language Server на эту строку ругается и предлагает замену на ТекущаяДатаСеанса(). Совет разумный и повсеместный. Только если ему последовать прямо здесь, модуль перестанет компилироваться в тонком клиенте:

{ВнешняяОбработка.Проверка.Форма.Форма.Форма(28,16)}:
Процедура или функция с указанным именем не определена (ТекущаяДатаСеанса)
        ДатаСеанса = <<?>>ТекущаяДатаСеанса();

ТекущаяДатаСеанса() объявлена доступной на сервере, в толстом клиенте, во внешнем соединении и на мобильном сервере. Тонкого и веб-клиента в этом списке нет. Поймали это на себе ровно так: обработка, собранная и проверенная запуском через 1cv8.exe (а это толстый клиент), открылась и отработала; та же обработка в 1cv8c.exe не скомпилировалась вовсе.

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

База 1cv8.exe, толстый 1cv8c.exe, тонкий
Бухгалтерия 3.0.206.19 доступна недоступна
Управление торговлей 11.5.22.149 доступна недоступна

Дело не в конфигурации и не в режиме совместимости, а ровно в клиенте. ТекущаяДата() при этом доступна везде.

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

Правильный ход — не подставлять одну функцию вместо другой, а перенести вычисление туда, где ему место:

&НаКлиенте
Процедура СформироватьИмяФайла()
    Имя = "выгрузка_" + Формат(ДатаСеансаССервера(), "ДФ='yyyyMMdd_HHmmss'");
КонецПроцедуры

&НаСервереБезКонтекста
Функция ДатаСеансаССервера()
    Возврат ТекущаяДатаСеанса();
КонецФункции

Лишний вызов сервера — цена того, что в данных не окажется времени с чужих часов. А если очень нужно проверить доступность функции, не ломая модуль, оберните её в Выполнить(): он компилируется в момент выполнения.


5. Файлы и выгрузка

5.1. Конфигуратор не проверяет модули форм, и молчит об этом

Сборку и проверку внешней обработки ставят на поток:

1cv8 DESIGNER /LoadExternalDataProcessorOrReportFromFiles src\Обработка.xml Обработка.epf
1cv8 DESIGNER /CheckModules -ExternalDataProcessor Обработка.epf
1cv8 ENTERPRISE /Execute Обработка.epf

Положим в модуль формы ошибку, которая не видна глазами: присваивание переменной с именем Знач. Это зарезервированное слово, модификатор параметра «по значению», и переменной с таким именем быть не может.

Знач = 1;
Сообщить(Знач);

Сборка: «Загрузка завершена», файл создан. Проверка: «Синтаксических ошибок не обнаружено!». Модули форм внешних обработок /CheckModules не компилирует, и тишина тут ничего не значит.

Запуск: процесс не завершается, файл с результатом не появляется, код возврата взять неоткуда. Снаружи это неотличимо от зависания в вашем коде, и искать вы будете бесконечный цикл. А на экране в это время висит окно:

Ошибка инициализации модуля: ВнешняяОбработка.ПробаСломанная.Форма.Форма.Форма
по причине:
{ВнешняяОбработка.ПробаСломанная.Форма.Форма.Форма(6,2)}: Неопознанный оператор
	<<?>>Знач = 1;

Беда в том, что окно видно только тому, кто сидит перед машиной. Если сборку ведёт билд-сервер или вы свернули лишнее, диагноза нет ни в логе, ни в коде возврата.

Проверять модули форм надо тем, что их разбирает: BSL Language Server на этом же файле ругается ровно на тех строках, где ошибка. Получается вопреки привычному: сторонний линтер видит то, чего не видит родная проверка платформы, и ставить его в сборку надо до конфигуратора, а не после.

И не доверяйте тишине. Если запуск ключом /Execute не завершился за разумное время, это не «долго считает», это чаще всего окно с ошибкой, которого вы не видите.

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

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

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу);
Значение = ТабДок.Область("R2C3").Значение;

Начнём с того, что верно. Ходовое объяснение «читается только первый лист» неверно: книга читается целиком, платформа кладёт листы в одну таблицу подряд, второй под первым. В самих ячейках граница между листами никак не отмечена. Если на первом листе двести строк, а на втором своя шапка и ещё сто, вы получите триста строк подряд, где двести первая внезапно окажется заголовком. Разбор, написанный в расчёте на один лист, не упадёт: он просто прочитает шапку второго листа как строку данных.

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

Для Каждого Обл Из ТабДок.Области Цикл
    Сообщить(Обл.Имя + ": строки " + Обл.Верх + ".." + Обл.Низ);
КонецЦикла;

ОбластьЛиста = ТабДок.Области.Найти("Отгрузки");   // имя листа, а не "Лист1"

Две ловушки в самой коллекции, обе нашлись при перепроверке. Порядок областей не совпадает с порядком листов: в моём прогоне на книге из трёх листов Б, А, В коллекция отдала их как А, Б, В, тогда как строки в документе идут Б, А, В. Индекс в коллекции ничего не говорит о положении листа в книге, ориентироваться надо на имя или на Верх/Низ. И второе: имена — это имена листов книги, поиск по Лист1 или Sheet1 вернёт Неопределено.

Проверил на .xlsx и .xls, на обеих платформах — во всех четырёх случаях одинаково.

Что до второй половины пункта, она подтвердилась: Значение у прочитанной ячейки недоступно для чтения, платформа отвечает «Поле объекта недоступно для чтения (Значение)». Доступен только Текст. То есть числа и даты вы разбираете из строк, и пункт 1.1 этой статьи начинается ровно здесь.

NeLyubluSKD в комментариях предложил короткую форму для обхода по листам — она удобнее моего цикла:

ТабличныйДокумент.ПолучитьОбласть(ТабличныйДокумент.Области.Найти(НазваниеЛиста).Имя);

5.3. Когда за листом xlsx всё-таки лезут в zip

После правки предыдущего пункта этот надо читать иначе. Zip нужен не потому, что до листов иначе не добраться — добраться можно через Области. Он нужен там, где имена листов заранее неизвестны в удобном виде, где важны типы значений, а не текст, или где нужно то, чего в табличном документе нет вовсе.

xlsx — это zip-архив с XML внутри, и он читается штатными средствами платформы, без единой внешней компоненты. Функция ниже берёт путь и номер листа, отдаёт таблицу непустых ячеек. Проверена на книге из двух листов на обеих платформах.

// Читает один лист книги xlsx и возвращает таблицу его непустых ячеек.
//
// Возвращаемое значение:
//   ТаблицаЗначений - колонки Строка, Колонка (числа с единицы) и Значение
//                     (Число или Строка - так, как значение лежит в книге).
Функция ПрочитатьЛистXLSX(Знач ПутьКниги, Знач НомерЛиста) Экспорт

    Каталог = ПолучитьИмяВременногоФайла();
    СоздатьКаталог(Каталог);

    Попытка
        Архив = Новый ЧтениеZipФайла(ПутьКниги);
        Архив.ИзвлечьВсе(Каталог, РежимВосстановленияПутейФайловZIP.Восстанавливать);
        Архив.Закрыть();

        // Строковые значения лежат общим списком, в самом листе - только номера.
        Общие = ОбщиеСтроки(Каталог + "\xl\sharedStrings.xml");
        Ячейки = ЯчейкиЛиста(Каталог + "\xl\worksheets\sheet"
            + Формат(НомерЛиста, "ЧГ=") + ".xml", Общие);
    Исключение
        УдалитьФайлы(Каталог);
        ВызватьИсключение;
    КонецПопытки;

    УдалитьФайлы(Каталог);
    Возврат Ячейки;

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

Плюс этого пути в том, что отрицательное число приходит из файла как есть: в самом xlsx оно записано как -1500, всегда с точкой в качестве разделителя и без пробелов между разрядами, независимо от того, что видел в Excel пользователь. То есть пункт 1.1 сюда не приходит.

Две оговорки. Имя sheet с номером совпадает с порядком вкладок только в простых книгах: строго говоря, соответствие надо брать из xl/workbook.xml и xl/_rels/workbook.xml.rels. И даты в xlsx хранятся числом дней от 30.12.1899, отличить дату от обычного числа можно только по стилю ячейки из xl/styles.xml.

5.4. Есть ли такой метод у платформы

Метод, который «точно был». Или которого не было никогда. Модуль не компилируется, и вы теряете время, гадая, перепутали вы имя или версию платформы.

Самый прямой ответ даёт справка платформы: карточка типа показывает все его методы и свойства, и там же видно, где свойство описано — у самого типа или у его расширения (пункт 3.2 ровно про это). Если справки под рукой нет, имена лежат в библиотеках каталога bin в кодировке UTF-16LE:

имя = 'ОбходФайловЦиклом'.encode('utf-16-le')
for п in glob.glob(r'C:\Program Files\1cv8\<версия>\bin\*.dll'):
    if имя in open(п, 'rb').read():
        print('есть'); break

Файл справки .hbk для этого не годится, он сжат и поиском не берётся.

Одна оговорка, без которой способ подводит. Имя в библиотеке означает, что платформа его знает, но не означает, что оно доступно вам. Живой пример из этой же статьи: ТекущаяДатаСеанса() платформа знает, а в тонком клиенте компилятор отвечает «Процедура или функция с указанным именем не определена» (пункт 4.4). Отсутствие имени (приговор, наличие) только основание посмотреть справку.

Мы проверили так 16 имён перед тем, как писать код, и одно из них, ОбходФайловЦиклом, в платформе отсутствует: его нет ни в одной из 279 библиотек каталога bin, тогда как НайтиФайлы находится сразу в нескольких. Пять минут проверки против часа отладки — размен, по-моему, честный )


Два мифа

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

Переменная с именем Строка не мешает вызвать функцию Строка(). Раздражает (да, читается плохо) да, но кода не ломает. Переименовывать имеет смысл ради читаемости, а не ради корректности.

Совпадение номеров в Form.xml — не коллизия. Пулы идентификаторов раздельные для элементов, реквизитов и команд. Элемент с id="19" и реквизит с id="19" прекрасно уживаются: в типовой Бухгалтерии такие совпадения есть в 3462 формах из первых 4000, на которых я остановил проход, то есть почти в каждой. Полный обход всех 7981 формы я делал только для пункта 3.1. Если вы «чините» это вручную, вы ломаете рабочую форму.


Шпаргалка

№ Признак Что ломается Как увидеть
1.1 Попытка Число(...) Исключение 0 на данных из Excel минусы становятся нулями тест на файле с отрицательными из настоящего Excel
1.2 галка «Неотрицательное» у реквизита минус превращается в ноль при присваивании поиск AllowedSign в выгрузке
1.3 КонецДня() или + секунды до проверки заполненности пустой период считается заданным сценарий с незаполненной датой
1.4 виды субконто в параметрах виртуальной таблицы счета без этого субконто выпадают сверка итога с ОСВ
1.5 ЗаполнитьЗначенияСвойств без третьего параметра после переименования реквизит перестаёт заполняться перечислить свойства явно: платформа упадёт
2.1 СериализаторXDTO.XMLСтрока(Набор) исключение на наборе записей первый запуск на наборе
2.2 Новый Тип(...).Свойство модуль не компилируется попытка открыть обработку
2.3 ИмяПлатформенногоОбъекта = ... падение в рантайме только запуск
2.4 одно имя в двух написаниях накопление уходит в другую переменную подсветка идентификатора в конфигураторе
2.5 многострочная вставка в //якорь запроса хвост вставки выходит из-под комментария печать собранного текста запроса
3.1 реквизит формы ХранилищеЗначения на 8.3 падает при присваивании, на 8.5 работает поиск ValueStorage в Form.xml
3.2 Элемент.РасширениеПоляВвода.Свойство не компилируется: свойства расширения пишутся на элементе карточка типа в справке
3.3 булева колонка без явного вида рисуется текстом «Да»/«Нет» InputField на xs:boolean в Form.xml
4.1 длительная операция из внешней обработки платформенный вызов метод не находит запустить через БСП с ВнешнийОтчетОбработка
4.2 Состояние() в серверном контексте в толстом клиенте молчит, в тонком модуль не компилируется запуск в 1cv8c.exe
4.3 пересобрали обработку, окно не закрыли форма не создаётся заново, работает старый код Сообщить() не печатается
4.4 ТекущаяДатаСеанса() в клиентском коде в тонком клиенте модуль не компилируется запуск в 1cv8c.exe, а не в 1cv8.exe
5.1 ошибка компиляции в модуле формы обработки /CheckModules пропускает, /Execute виснет без следов BSL LS до сборки, живой запуск после
5.2 ТабличныйДокумент.Прочитать(xlsx) листы склеиваются, Значение недоступно обойти коллекцию Области и сверить с книгой
5.3 нужен тип значения, а не текст текст ячейки не отличает дату от числа ЧтениеZipФайла + ЧтениеXML, дата только через xl/styles.xml
5.4 метод, который «точно был» не компилируется карточка типа в справке, затем bin\*.dll

Что со всем этим делать

Ошибкой редактор конфигуратора не помечает ничего из этого списка. Один приём всё же есть, но работает он от обратного: подсветка идентификатора из пункта 2.4 не загорается там, где имя написано двумя алфавитами. Большая часть не находится никаким статическим анализом в принципе: это свойства выполнения или вопросы к смыслу кода, а не к его форме.

Но кое-что видно прямо в выгрузке: ограничение знака у реквизита, два написания одного имени, реквизит формы с хранилищем значения, булева колонка без явного вида. Под такие вещи я написал восемь проверок по XML-выгрузке и прошёл ими по типовым ERP и Бухгалтерии: 17 ГБ выгрузки, 47 тыс. модулей. Обработка приложена: открывается в любой конфигурации через «Файл → Открыть», на вход каталог выгрузки, на выход таблица находок и TSV.

Вторым файлом приложена «Проверка поведения платформы» — та самая обработка, которой я проверял утверждения этой статьи. Кнопка «Проверить все» выполняет проверки на вашей базе и показывает, что ответила ваша платформа. Два пункта осознанно трогают базу, и об этом написано прямо в форме: проверка по пункту 1.2 пишет элемент справочника в транзакции и откатывает её, а проверка по пункту 4.1 запускает фоновое задание и дожидается его завершения. Следов не остаётся.

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

И последнее, уже не про 1С. Если после этой статьи вы проверите у себя хотя бы один пункт и он не подтвердится — напишите в комментариях. Первая редакция стала заметно лучше ровно так.

Вступайте в нашу телеграмм-группу Инфостарт

отладка подводные камни качество кода стандарты разработки ошибки разработчика BSL Language Server внешние обработки управляемые формы директивы компиляции тонкий клиент ошибка компиляции загрузка из Excel xlsx ТабличныйДокумент ЧтениеZipФайла ТекущаяДатаСеанса фоновые задания XML-выгрузка рефакторинг Бухгалтерия предприятия 3.0

См. также

Разработка Инструментарий разработчика Групповая разработка (Git, хранилище) Разработчик Платные (руб)

Практический курс по работе с AI-агентами для разработчиков 1С уровня middle и senior, а также тимлидов команд: от постановки задач и передачи контекста до создания расширений, интеграций, MCP-инструментов, тестов и проверки готового решения.

50000 руб.

10.09.2026    13554    115    0    

81

Инструментарий разработчика Чистка данных Свертка базы Инструменты администратора БД Системный администратор Разработчик Руководитель проекта 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Россия Платные (руб)

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP, УНФ, КА и т.д.). Поддерживаются серверные и файловые базы, управляемые и обычные формы, интерфейс 8.5. Может выполнять свертку одновременно в несколько потоков, а также без непосредственного участия пользователя. Решение в Реестре отечественного ПО.

24900 руб.

20.08.2024    83293    432    171    

362

Инструментарий разработчика Роли и права Запросы СКД Разработчик Руководитель проекта 1С:Предприятие 8 Платные (руб)

Инструменты для разработчиков 1С 8.3 и 8.5: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

16500 руб.

02.09.2020    285738    1606    423    

1220

Инструментарий разработчика Разработка Администрирование веб-серверов Системный администратор Разработчик Аналитик Руководитель проекта 1С 8.3 Платные (руб)

Analyzer 1C сводит выгрузку 1С — основную конфигурацию и все расширения — в единый граф знаний. Любой запрос по связям за доли секунды, с пометками «Доб.» / «Заимств.» / «Переопределено». Новое в 2.0 — обновление поставки: сравнение и объединение версий деревом «как в Конфигураторе» с выгрузкой плана решений; поиск конфликтов из-за перехватов расширений и висячих ссылок; загрузка из бинарных .cf/.cfe; циклические зависимости. Плюс анализ влияния, запросы BSL, роли и RLS, граф вызовов. Минута на развёртывание через Docker без необходимости подключения к Интернет. Любая 1С:Предприятие 8.3+.

14000 руб.

17.04.2026    16807    63    62    

74

Пакетная печать Печатные формы Инструментарий разработчика Разработчик 1С:Предприятие 8 Платные (руб)

Расширение для создания и редактирования печатных форм в системе 1С:Предприятие 8.3. Благодаря конструктору можно значительно снизить затраты времени на разработку печатных форм, повысить качество и прозрачность разработки, а также навести порядок в многообразии корпоративных печатных форм. Обновление версии от 21.04.26

22570 руб.

06.10.2023    44214    122    54    

135

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданным 1С, справке синтакс-помощника и проверки синтаксиса.

15250 руб.

25.08.2025    76950    147    41    

154

Разработка Инструментарий разработчика Разработчик Руководитель проекта 1С 8.3 Платные (руб)

Pilot 1C превращает задачу, поставленную обычными словами, в техническое задание, код на встроенном языке и сценарии проверки. Прежде чем что-то предложить, он сверяется с устройством вашей конфигурации через граф Analyzer 1C: существует ли объект, из чего он состоит, кто его вызывает, какие роли дают права. Чего найти не удалось – спрашивает, а не выдумывает. Готовый код проходит более полутора сотен проверок по справочнику языка и стандартам разработки, который приезжает вместе с продуктом. Модель – ваша: любой сервер, совместимый с программным интерфейсом OpenAI, в том числе локальный. Правки в конфигурацию Pilot не вносит – их применяет разработчик.

18300 руб.

11.09.2026    3738    5    0    

10

Инструменты администратора БД Инструментарий разработчика Роли и права Разработчик 1С:Предприятие 8 1C:Бухгалтерия Россия Платные (руб)

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

17000 руб.

10.11.2023    28763    103    46    

107
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. coollerinc 189 22.09.26 17:23 Сейчас в теме
Вообще частая ошибка использование ЗаполнитьЗначениеСвойств, где надо и не надо, без указания нужного набора свойств. Если нет цели, универсального заполнения, лучше явно указать, какие свойства должны заполнятся или просто по классике, присваивать через Равно. Сэкономив 2-3 строчки кода, можно, получить много неочевидных багов.
Если свойства явно не указать, то вы и не узнаете, что это какое то свойство уже переименовали и заполнение уже как месяц не происходит. Если описать свойства в 3 параметре, то будет ошибка и вы сразу это заметите.

Так же бесит, что 1с не выдает ошибку, когда в один ссылочный реквизит, пытаются записать, что то другое. То реквизит просто очищается. Лучше бы исключение выходило бы.
ShiningPhoenix; KonMa; +2 – Ответить
7. Vasvas05 27 23.09.26 11:16 Сейчас в теме
(1)
ЗаполнитьЗначениеСвойств
она для этого и используется, чтобы ошибки не выпадали при изменение свойств.
Ninel_S; ubnkfl; +2 – Ответить
8. coollerinc 189 23.09.26 11:37 Сейчас в теме
(7) Я написал, что она используется где надо и не надо. Если вы осознано понимаете, что допустимо, что какой то из реквизитов не заполнится, то вы используете по назначению эту процедуру.
2. bulpi 219 22.09.26 19:07 Сейчас в теме
Автору RTFM по методу табличного документа Прочитать(). Нормально он читает разные листы xls в коллецию Области.
Dach; RocKeR_13; SerVer1C; ixijixi; KonMa; gml; +6 – Ответить
3. KonMa 116 22.09.26 23:05 Сейчас в теме
(2) Спасибо, проверил. Книга из трёх листов, платформы 8.3.27.2214 и 8.5.1.1343, форматы .xlsx и .xls — во всех четырёх прогонах одинаково: Прочитать() создаёт именованную область на каждый лист, имя области совпадает с именем листа книги, Области.Найти("<имя листа>") возвращает область, границы читаются из Верх/Низ. Вы правы, лист так выделяется без всякого zip. Формулировку в пункте поправлю.
Заодно два наблюдения из того же прогона, к общей картине. Первое: коллекция упорядочена по имени области, а не по порядку листов — книга с листами Б, А, В отдаёт Области в порядке А, Б, В, тогда как строки в документе идут Б, А, В. Индекс в коллекции ничего не говорит о положении листа в книге, ориентироваться надо на имя или на Верх/Низ. Второе: Значение у прочитанной ячейки недоступно для чтения на обеих платформах — «Поле объекта недоступно для чтения (Значение)», доступен только Текст, поэтому числа дальше разбираются из строк.
4. KonMa 116 22.09.26 23:19 Сейчас в теме
(1) Проверил оба пункта прогоном на БП 3.0 (8.3.27.2214) и УТ 11.5 (8.5.1.1343) — всё так. С третьим параметром платформа честно падает с «Поле 'X' не обнаружено», без него молчит. И в ссылочный реквизит одинаково беззвучно уходят и чужая ссылка, и строка, и число — остаётся пустая ссылка нужного типа. Обязательно добавлю это в статью, спасибо!
coollerinc; +1 – Ответить
5. vadim1011985 103 23.09.26 09:00 Сейчас в теме
П. 2.4 спокойно ловиться через настройку выделения текущего идентификатора
Прикрепленные файлы:
gimalaj; RocKeR_13; SerVer1C; ixijixi; +4 – Ответить
6. DmitryKSL 187 23.09.26 11:15 Сейчас в теме
"Фоновые задания внешней обработке недоступны"
Вообще-то доступны.
Трактор; +1 – Ответить
9. ixijixi 2177 23.09.26 12:24 Сейчас в теме
Фоновые задания внешней обработке недоступны
Хорошо, что я об этом не знаю, и спокойно запускаю ФЗ во внешних обработках.
Трактор; Dach; RocKeR_13; 0x00; +4 – Ответить
10. NeLyubluSKD 23.09.26 12:25 Сейчас в теме
Для преобразования строки в число использую СтроковыеФункцииКлиентСервер.СтрокаВЧисло
Работает надежно, исключений не вызывает. Глючит/отказывает крайне редко, рекомендую

Помимо пропадающих счетов при отборе по субконто из ВТ, еще любят пропадать позиции номенклатуры с нулевыми остатками)) да, это известный глюк ВТшек, лечится соединением с "нормальной" таблицей

Процедуры и функции модуля внешней обработки запускаются в фоне на раз два. Для этого сама обработка в коде грузится на сервак и затем имена функций маппятся уже с учетом имени epf-ника на сервере. Инфы море на том же инфостарте, лично я спасаюсь такой методой когда надо сделать на коленке мега ресурсоемкий обработчик или загрузку данных, а конфигуратор закрыт от слова совсем (и расширение поставить не дают).

Табличный документ прекрасно обходится по отдельным листам:
ТабличныйДокумент.ПолучитьОбласть(ТабличныйДокумент.Области.Найти(НазваниеЛиста).Имя);
не благодарите)
11. RocKeR_13 1490 23.09.26 16:17 Сейчас в теме
12. Dach 440 23.09.26 18:46 Сейчас в теме
(0) читать этот нейрослоп очень тяжело

Просьба на будущее хотя бы какой-то навык-хуманайзер своим нейрошнырям подключать
r2d255; orakool2; mrChOP93; RocKeR_13; ixijixi; +5 – Ответить
13. RocKeR_13 1490 24.09.26 08:51 Сейчас в теме
в тонком перевернется пункт 4.4б, а на конфигурации без подходящего реквизита и без бухгалтерских итогов

Ну хоть перечитывайте что ли...
orakool2; +1 – Ответить
14. Трактор 1297 24.09.26 14:55 Сейчас в теме
Фоновые задания внешней обработке недоступны

Вот два способа выполнить метод внешней обработки в фоне:
https://infostart.ru/1c/tools/2302643/
Для отправки сообщения требуется регистрация/авторизация