При работе в программной среде 1С:Предприятие 7.7 разработчики регулярно сталкиваются с необходимостью форматирования номеров документов. Это требуется для вывода красивых номеров в печатных формах (счетах-фактурах, накладных), построения читаемых реестров или интеграции со сторонними информационными системами.
Типовые механизмы автонумерации платформы 1С 7.7 устроены так, что они дополняют номер лидирующими нулями для сохранения фиксированной длины строки (например, 00000124). Кроме того, в распределенных базах данных или крупных организациях часто используются буквенные префиксы (например, К0001571 или ГК00326). Бухгалтерам и внешним контрагентам такие громоздкие обозначения в печатных формах не нужны — им требуется видеть «чистый» номер.
В этой статье мы подробно разберем несколько эффективных способов решения этой задачи на платформе 1С 7.7: от классических циклов разбора строки до использования регулярных выражений и встроенных глобальных функций типовых конфигураций. Мы вместе проанализируем преимущества и недостатки каждого подхода, чтобы вы смогли выбрать оптимальный вариант для своей конфигурации.
Рассмотрим возможные варианты входящих строк, с которыми нам предстоит работать:
Наша цель — написать универсальный или специализированный алгоритм, который вернет очищенную строку, начинающуюся со значащей цифры (от 1 до 9).
Давайте разберем классический алгоритм, который обсуждался разработчиками на форуме. Основная идея заключается в том, чтобы последовательно проверять первый символ строки слева. Если он не является значащей цифрой (то есть не входит в диапазон от "1" до "9"), мы его удаляем и переходим к следующему символу. Цикл продолжается до тех пор, пока первым символом строки не станет цифра от 1 до 9 или пока строка полностью не опустеет.
Посмотрим на практическую реализацию этого метода:
// Очищаем пробелы по краям строки
СтрокаНомера = СокрЛП(ТаблицаДекларации.НомерСчетаФактуры);
// Запускаем цикл проверки первого левого символа
Пока Найти("123456789", Лев(СтрокаНомера, 1)) = 0 Цикл
// "Откусываем" первый символ слева, заменяя строку её частью со второго символа
СтрокаНомера = Сред(СтрокаНомера, 2);
// Предотвращаем бесконечный цикл в случае пустой строки или строки без цифр
Если СтрДлина(СтрокаНомера) = 0 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Проанализируем детально, как работает этот код по шагам на примере строки ГК00326:
Лев(СтрокаНомера, 1) возвращает букву Г. Функция Найти("123456789", "Г") возвращает 0, так как буквы Г нет в строке поиска. Условие цикла выполняется. Строка преобразуется в К00326 (символы со 2-го до конца).К. Найти снова возвращает 0. Строка сокращается до 00326.0. Он также отсутствует в поисковой строке "123456789". Результат Найти равен 0. Строка становится 0326.0. Строка усекается до 326.Лев(СтрокаНомера, 1) возвращает 3. Функция Найти("123456789", "3") возвращает её позицию (равную 3), что не равно 0. Цикл завершается.Этот метод полностью универсален для платформы 1С 7.7, так как использует самые базовые функции работы со строками, которые гарантированно доступны в любой конфигурации.
Иногда операции со строками (такие как Найти) могут работать медленнее, чем прямое сравнение числовых кодов символов. Давайте рассмотрим альтернативный вариант решения, использующий функцию КодСимв. В кодовой таблице цифры от "1" до "9" идут последовательно и имеют коды от 49 до 57 соответственно.
СтрокаНомера = СокрЛП(ТаблицаДекларации.НомерСчетаФактуры);
// Будем убирать символы, пока код первого символа не попадет в диапазон [49; 57]
Пока (СтрДлина(СтрокаНомера) > 0) И ((КодСимв(Лев(СтрокаНомера, 1)) < 49) Или (КодСимв(Лев(СтрокаНомера, 1)) > 57)) Цикл
СтрокаНомера = СокрЛП(Сред(СтрокаНомера, 2));
КонецЦикла;
Этот подход лаконичен и работает достаточно быстро, так как платформа сравнивает обычные целые числа вместо поиска одной строки внутри другой. Обратите внимание на важную деталь: мы добавили проверку СтрДлина(СтрокаНомера) > 0 непосредственно в условие цикла Пока, чтобы избежать критических ошибок при работе с пустыми значениями.
Очень часто программисты 1С начинают изобретать собственные алгоритмы, забывая о том, что разработчики типовых решений (таких как «Бухгалтерский учет» или «Торговля и Склад» для 1С 7.7) уже заложили мощный инструментарий в Глобальный модуль. Рассмотрим функцию глПреобразоватьНомерДок.
Эта функция предназначена специально для форматирования номеров перед выводом на печать или использованием в отчетах. Она имеет следующую структуру вызова:
// Синтаксис: глПреобразоватьНомерДок(НомерДок, ВыводитьНули, ВыводитьПрефикс)
// Где:
// НомерДок - исходная строка номера
// ВыводитьНули - 1 (оставить нули) или 0 (убрать нули)
// ВыводитьПрефикс - 1 (оставить префикс) или 0 (убрать префикс)
СтрокаНомера = глПреобразоватьНомерДок(ТаблицаДекларации.НомерСчетаФактуры, 0, 0);
Данный метод является наиболее предпочтительным в типовых конфигурациях по нескольким причинам:
Если вам необходимо обрабатывать огромные массивы данных (например, десятки тысяч строк в таблице значений при формировании книги продаж или декларации), стандартные циклы 1С 7.7 могут вызвать заметные задержки интерфейса. В таких случаях на помощь приходит COM-технология и библиотека регулярных выражений Windows.
Давайте посмотрим, как решить задачу в несколько строк без единого цикла:
// Создаем объект для работы с регулярными выражениями
RegExp = СоздатьОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
RegExp.MultiLine = Ложь;
// Задаем шаблон поиска: находим все символы от начала строки (^),
// которые НЕ являются цифрами от 1 до 9 ([^1-9]+)
RegExp.Pattern = "^[^1-9]+";
// Производим замену найденного префикса на пустую строку
СтрокаНомера = RegExp.Replace(ТаблицаДекларации.НомерСчетаФактуры, "");
Давайте детально разберем регулярное выражение ^[^1-9]+:
^ — этот символ в самом начале шаблона означает привязку к началу строки. Поиск будет производиться строго с первого символа.[^1-9] — квадратные скобки со знаком каретки внутри означают отрицание. То есть мы ищем любой символ, который НЕ является цифрой от 1 до 9. Сюда попадают нули (0), буквы русского и латинского алфавитов, знаки дефиса, косой черты и т.д.+ — квантификатор, означающий "один или более раз". Он позволяет захватить всю группу неподходящих символов сразу (например, сразу всю подстроку ГК00 или 00000).Этот способ работает невероятно быстро, так как компиляция и выполнение регулярного выражения происходят на уровне оптимизированных системных библиотек Windows, минуя медленный интерпретатор встроенного языка 1С 7.7.
Если у вас гарантированно отсутствуют буквенные префиксы, а нужно удалить только ведущие нули (например, из номера 00000104 получить 104), существует очень хитрый и красивый алгоритм, который не задействует циклы и внешние компоненты.
Давайте изучим этот изящный прием:
ИсходныйНомер = ТаблицаДекларации.НомерСчетаФактуры; // Пример: "00000104"
// Выполняем двойную замену с удалением пробелов слева
Результат = СтрЗаменить(СокрЛ(СтрЗаменить(ИсходныйНомер, "0", " ")), " ", "0");
Выясним причину работоспособности этого алгоритма по шагам:
СтрЗаменить(ИсходныйНомер, "0", " ") заменяет все нули на пробелы. Строка 00000104 превращается в 1 4 (пять пробелов в начале, единица, пробел вместо внутреннего нуля, четверка).СокрЛ удаляет все пробелы только с левой стороны строки. На выходе мы получаем строку 1 4. Заметьте, что пробел между единицей и четверкой остался нетронутым!СтрЗаменить возвращает все пробелы обратно, превращая их в нули. На выходе получается чистый номер 104.Важное ограничение: этот способ применим только тогда, когда в исходном номере не может быть законных пробелов (например, пробелов-разделителей серий или кодов подразделений), иначе они также будут ошибочно заменены на нули. Также он не очистит буквенные префиксы.
Напоследок рассмотрим самый простой способ, который подходит для элементарных ситуаций. Если номер состоит исключительно из цифр и лидирующих нулей (например, 00000124), самым быстрым решением будет его преобразование в число и обратно в строку:
СтрокаНомера = Строка(Число(ТаблицаДекларации.НомерСчетаФактуры));
При конвертации строки в число платформа 1С автоматически отбрасывает незначащие нули слева. Однако помните, что если в строке встретится буква (К0001571) или спецсимвол (0000012/2), этот метод выдаст ошибку преобразования типа или вернет неверный результат. Используйте его с большой осторожностью.
Давайте обобщим полученные знания в виде кратких рекомендаций: