Как найти строку в Excel по значению без перебора всех строк

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Метод 1: Использование встроенного метода Find через COM-объект

Самый распространенный способ взаимодействия с Excel — это использование COMОбъект ("Excel.Application"). У этого объекта есть мощный встроенный метод Find, который работает аналогично функции "Найти" (Ctrl+F) в самом приложении Excel. Основное преимущество этого метода в том, что сам движок Excel оптимизирует поиск, избавляя нас от необходимости писать циклы в коде 1С. Для ускорения написания программного кода при работе с таблицами можно использовать шаблон с готовыми фрагментами кода для интеграции с Excel.

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


Попытка
    Эксель = Новый COMОбъект("Excel.Application");
    Книга = Эксель.Workbooks.Open("C:\PriceList.xls");
    Лист = Книга.Worksheets(1);
    Диапазон = Лист.UsedRange;
    
    // Параметры метода Find:
    // 1. Искомое значение ("123")
    // 2. После какой ячейки искать (Cells(1,1))
    // 3. LookIn: -4123 (xlValues — искать в значениях)
    // 4. LookAt: 1 (xlWhole — полное совпадение)
    // 5. SearchOrder: 1 (xlByRows — по строкам)
    // 6. SearchDirection: 1 (xlNext — следующий)
    
    Поиск = Диапазон.Find("123", Диапазон.Cells(1, 1), -4123, 1, 1, 1);
    
    Если Поиск = Неопределено Тогда
        Сообщить("Значение не найдено");
    Иначе
        Сообщить("Значение найдено в ячейке: " + Поиск.Address);
        Сообщить("Номер строки: " + Поиск.Row);
    КонецЕсли;
    
    Книга.Close(Ложь);
    Эксель.Quit();
Исключение
    Сообщить("Ошибка при работе с Excel: " + ОписаниеОшибки());
КонецПопытки;

Выясним важные нюансы работы этого метода. Во-первых, обратите внимание на параметр xlWhole (значение 1) или xlPart (значение 2). Если мы установим xlWhole, 1С найдет только ту ячейку, содержимое которой полностью совпадает с искомым текстом. Если же нужно найти вхождение (подстроку), следует использовать xlPart.

Во-вторых, важно помнить замечание опытных разработчиков: поиск всегда начинается после ячейки, указанной во втором параметре. Если вы укажете Cells(1, 1), поиск фактически начнется со второй ячейки. Если искомое значение находится в самой первой ячейке, метод может его "пропустить" в первом цикле поиска.

Метод 2: Высокоскоростной поиск через ADO (SQL-запрос)

Если файл Excel очень большой, а установка самого Microsoft Office на сервере нежелательна, мы можем рассмотреть метод доступа к данным через ADODB.Connection. В этом случае файл Excel рассматривается как база данных, а поиск осуществляется с помощью стандартного SQL-запроса SELECT.

Этот способ работает значительно быстрее, чем COM-объект, так как не требует запуска графической оболочки Excel. Разберем пример реализации:


СтрокаСоединения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Data.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1;""";
Connection = Новый COMОбъект("ADODB.Connection");
Connection.Open(СтрокаСоединения);

RS = Новый COMОбъект("ADODB.Recordset");
// Ищем строку, где значение в колонке 'Артикул' равно '555'
ТекстЗапроса = "SELECT * FROM [Лист1$] WHERE [Артикул] = '555'";

Попытка
    RS.Open(ТекстЗапроса, Connection);
    Если НЕ RS.EOF Тогда
        Сообщить("Данные найдены!");
        // Читаем значение из первой колонки найденной строки
        Результат = RS.Fields.Item(0).Value;
    КонецЕсли;
    RS.Close();
Исключение
    Сообщить("Ошибка запроса: " + ОписаниеОшибки());
КонецПопытки;

Connection.Close();

Проанализируем параметры строки соединения. Параметр HDR=YES означает, что первая строка файла содержит заголовки колонок, которые можно использовать в блоке WHERE. Параметр IMEX=1 заставляет драйвер читать данные в смешанном режиме, что помогает избежать проблем, когда в одной колонке встречаются и числа, и текст.

Метод 3: Использование функции MATCH (ПОИСКПОЗ)

Если нам не нужен сам объект ячейки Range, а достаточно только узнать номер строки, мы можем вызвать встроенную функцию Excel MATCH. Это работает быстрее, чем полноценный метод Find, так как возвращает просто числовой индекс.

Рассмотрим реализацию через объект WorksheetFunction:


// Предположим, Лист уже определен как COM-объект
Попытка
    НомерСтроки = Эксель.WorksheetFunction.Match("ИскомоеЗначение", Лист.Range("A:A"), 0);
    Сообщить("Значение найдено в строке №: " + Формат(НомерСтроки, "ЧГ=0"));
Исключение
    Сообщить("Значение в колонке не найдено");
КонецПопытки;

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

Метод 4: Нативный поиск средствами 1С (Табличный документ)

Начиная с версии платформы 8.3.6, разработчики 1С получили возможность читать файлы Excel напрямую, без использования COM-технологий. Это особенно актуально для серверов на базе Linux, где COM-объекты недоступны. Проанализируем этот современный подход.

Алгоритм действий следующий: мы загружаем файл во временный ТабличныйДокумент и используем его встроенный метод НайтиТекст. Этот метод работает чрезвычайно быстро и поддерживает различные направления поиска.

Разберем пример кода:


ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать("C:\Price.xlsx");

// НайтиТекст(Значение, ТекущаяОбласть, Ориентация, ЧастичноеСовпадение)
НайденнаяОбласть = ТабДок.НайтиТекст("1236", , , Истина);

Если НайденнаяОбласть <> Неопределено Тогда
    Сообщить("Найдено в строке: " + НайденнаяОбласть.Верх);
КонецЕсли;

Важные рекомендации по выбору метода:

  1. Если задача выполняется на клиентском компьютере с Windows и установленным Excel — используйте Find (Метод 1).
  2. Если нужно обработать огромный массив данных (десятки тысяч строк) как таблицу — выбирайте ADO (Метод 2).
  3. Если код должен выполняться на сервере 1С (особенно под Linux) или вы хотите избежать зависимости от установленного Microsoft Office — используйте ТабличныйДокумент.Прочитать() (Метод 4).
  4. Для простых проверок существования значения в конкретной колонке идеально подходит Match (Метод 3).

Выясним также вопрос очистки памяти. При работе с любыми COM-объектами (Excel или ADO) крайне важно корректно завершать сеанс. Если вы просто закроете процедуру, процесс EXCEL.EXE может остаться висеть в памяти сервера, что со временем приведет к утечке ресурсов. Всегда вызывайте Quit() для приложения и обнуляйте переменные, присваивая им Неопределено.

Таким образом, мы проанализировали четыре эффективных способа поиска данных в Excel, каждый из которых превосходит стандартный перебор в цикле по скорости и надежности. Выбор конкретного инструмента зависит от архитектуры вашей задачи и условий эксплуатации системы.

← На главную