В процессе разработки на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью обработки и сравнения текстовых данных. Типичный пример — импорт данных из XML или строка, в которой несколько значений записаны через точку с запятой, запятую или другой символ. Для эффективной работы с такими данными их нужно «разбить» на отдельные элементы и поместить в структуру, удобную для перебора (например, в СписокЗначений с выводом в отчет).
Рассмотрим подробнее несколько способов реализации этой задачи, разберем их преимущества и выясним, как правильно работать с результатами разделения.
Этот метод считается классическим для версии 7.7. Мы создадим функцию, которая в цикле ищет вхождение разделителя, «откусывает» часть строки до него и добавляет её в специальный объект СписокЗначений.
Проанализируем программный код такой функции:
Функция глРазложить(Знач Стр, Разделитель = ";") Экспорт
СЗ = СоздатьОбъект("СписокЗначений");
// Если разделитель — пробел, удалим лишние пробелы по краям
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
КонецЕсли;
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1 = 1 Цикл
Поз = Найти(Стр, Разделитель);
Если Поз = 0 Тогда
// Если разделитель больше не найден, добавляем остаток строки
СЗ.ДобавитьЗначение(Стр);
Возврат СЗ;
КонецЕсли;
// Извлекаем значение до разделителя
ЗначениеЧасти = Лев(Стр, Поз - 1);
СЗ.ДобавитьЗначение(ЗначениеЧасти);
// Отрезаем обработанную часть вместе с разделителем
Стр = Сред(Стр, Поз + ДлинаРазделителя);
// Обработка случая, если разделитель был в самом конце строки
Если СтрДлина(Стр) = 0 Тогда
Возврат СЗ;
КонецЕсли;
КонецЦикла;
КонецФункции
Разберем, как работает этот алгоритм. Функция использует встроенную команду Найти, чтобы определить позицию разделителя. С помощью Лев мы получаем текст до разделителя, а с помощью Сред обновляем исходную строку, удаляя из неё уже обработанный фрагмент. Цикл продолжается до тех пор, пока функция Найти не вернет 0, что означает отсутствие разделителей в остатке строки.
Существует более изящный способ, который часто оказывается быстрее в написании и удобнее в отладке. Мы можем временно заменить наш разделитель (например, ;) на встроенный в 1С символ переноса строки. После этого 1С начнет воспринимать нашу строку как многострочный текст.
Рассмотрим реализацию этого метода по шагам:
; на РазделительСтрок.СтрКоличествоСтрок, чтобы узнать, сколько фрагментов у нас получилось.СтрПолучитьСтроку.Посмотрим на пример кода:
Процедура РазборСтрокиЧерезПеренос(ИсходнаяСтрока)
// Заменяем ";" на системный разделитель
ТекстСПереносами = СтрЗаменить(ИсходнаяСтрока, ";", РазделительСтрок);
Колво = СтрКоличествоСтрок(ТекстСПереносами);
Для Ном = 1 По Колво Цикл
ТекущееЗначение = СтрПолучитьСтроку(ТекстСПереносами, Ном);
// Здесь мы можем работать с каждым значением отдельно
Сообщить("Элемент №" + Ном + ": " + ТекущееЗначение);
КонецЦикла;
КонецПроцедуры
Важный нюанс: этот метод идеально подходит, если внутри самих значений гарантированно нет символов переноса строки. В противном случае количество строк будет рассчитано неверно.
Объект СписокЗначений в 1С 7.7 обладает встроенным методом ИзСтрокиСРазделителями. Он работает очень быстро, так как реализован на уровне платформы, но имеет специфические требования к формату строки. Платформа ожидает, что элементы разделены запятыми, а значения, содержащие пробелы или спецсимволы, заключены в кавычки.
Если ваши данные — это набор цифр или простых кодов (как в примере 00114069;00114070), мы можем подготовить строку и использовать этот метод:
// Предположим, Стр = "00114069;00114070;00083046"
ПодготовленнаяСтр = СтрЗаменить(Стр, ";", ",");
СЗ = СоздатьОбъект("СписокЗначений");
СЗ.ИзСтрокиСРазделителями(ПодготовленнаяСтр);
Проанализируем ситуацию: этот метод хорош своей лаконичностью, однако он может некорректно сработать, если внутри ваших данных уже есть запятые или кавычки. Используйте его с осторожностью.
Часто начинающие разработчики успешно разделяют строку, но испытывают трудности с тем, как извлечь данные из полученного объекта СписокЗначений. Выясним, как правильно это сделать.
Предположим, мы использовали Способ 1 и получили объект СЗ. Чтобы перебрать все его элементы, нам нужно использовать цикл Для:
Для Ном = 1 По СЗ.РазмерСписка() Цикл
Значение = СЗ.ПолучитьЗначение(Ном);
Сообщить("Обработка значения: " + Значение);
// Здесь можно выполнять любые действия, например:
// Если Спр.НайтиПоКоду(Значение) = 1 Тогда ...
КонецЦикла;
В этом примере функция РазмерСписка() возвращает общее количество элементов, а ПолучитьЗначение(Ном) извлекает конкретный элемент по его индексу (в 7.7 индексация списков начинается с 1).
В сложных случаях, когда разделителей может быть несколько (например, и запятая, и точка с запятой одновременно), можно прибегнуть к помощи внешних объектов. В ОС Windows доступен объект VBScript.RegExp, который позволяет выполнять разделение строк (метод Split) по сложным правилам.
Рассмотрим пример подключения этого объекта:
RegExp = СоздатьОбъект("VBScript.RegExp");
RegExp.Global = Истина;
RegExp.IgnoreCase = Истина;
RegExp.Pattern = "[;|, ]"; // Разделители: точка с запятой, запятая или пробел
// Далее используется метод Replace для нормализации или Execute для поиска
Однако для большинства повседневных задач в 1С 7.7 достаточно первых двух способов. Метод с использованием РазделительСтрок является наиболее рекомендуемым благодаря своей простоте и отсутствию необходимости писать длинные функции разбора.
Подведем итог: для быстрого разделения простых строк используйте СтрЗаменить на РазделительСтрок. Если же логика требует создания универсального инструмента, который будет работать в разных частях конфигурации, лучше один раз добавить функцию глРазложить в Глобальный модуль.