Загрузка в 1С:7.7 (далее просто 1С) из Excel, казалось бы, что может быть проще? Создаем объект «Excel.Application», открываем в нем необходимый файл и загружаем все необходимы данные. Но есть одно маленькое но: чтобы создать этот объект, на компьютере должен быть установле Excel. А если Excel-я нет, что делать? Уже несколько раз сталкивался с такими организациями: на компьютерах пользователей, разумеется, стоит все необходимое, в т.ч. и MS Office, нет только 1С, а вот на сервере терминалов все наоборот: только 1С:7.7 и все. На предложение установить хотя бы только Excel отвечают категорическим отказом, мотивируя это проблемами безопасности или отсутствием свободных лицензий, или и тем, и другим. В таком случае открыть файл через объект «Excel.Application» оказывается невозможно, что же делать? Но выход есть! Наша любимая Microsoft все предусмотрела! Чтобы извлечь данные из файлов Excel можно использовать специальные объекты ACE.OLEDB или более старые JET.OLEDB.
Итак, если у Вас возникла необходимость обратится из 1С к книге Excel на машине, где неустановлен этот самый Excel, то порядок действий следующий:
-
Проверяем, что у нас установлено и каких версий, для этого смотрим в реестре ветку HKEY_CLASSES_ROOTMicrosoft.ACE.х.х. Если этого раздела нет, то там же может быть такая ветка: HKEY_CLASSES_ROOTMicrosoft.JET.х.х, где «х.х» — это номера версий. Если ничего нет, то гуглим в Яндексе «скачать microsoft ace.oledb» и переходим на сайт Microsoft, где эта штука называется как «Microsoft Access Database Engine 2010 Redistributable», кто не хочет долго искать может сразу скачать по #здесьссылке https://download.microsoft.com/download/f/d/8/fd8c20d8-e38a-48b6-8691-542403b91da1/AccessDatabaseEngine.exe
-
Переходим к написанию процедуры импорта. Сначала формируем строку подключения. Для JET.OLEDB 4-ой версии она будет выглядеть следующим образом:
ИмяФайла = "C:AAAfile123.xls"; //Имя файла, для импорта СтрокаПодключения = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source = " + ИмяФайла; СтрокаПодключения = СтрокаПодключения + "; Extended Properties = "+"""Excel 8.0"+";HDR=NO;IMEX=1"";";
А для ACE.OLEDB 12-ой так:
ИмяФайла = "C:AAAfile123.xls"; //Имя файла, для импорта СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = " + ИмяФайла; СтрокаПодключения = СтрокаПодключения + "; Extended Properties = "+"""Excel 12.0"+";HDR=NO;IMEX=1"";";
Описание тонкостей данных настроек — это тема для отдельной публикации. Для наших целей достаточно тех, что указаны здесь. Но интересующиеся могут воспользоваться поисковыми запросами «подключение к microsoft.jet.oledb» или «подключение к microsoft.Ace.oledb».
-
Подключаемся к файлу:
// Подключаемся Екс = СоздатьОбъект("ADODB.Connection"); Екс.Open(СтрокаПодключения); //Таблица EXCEL
Файл открыт. Для получения из него данных необходимо будет использовать объект RecordSet, если Вы работали в VB или VBA, то знаете что это такое, для остальных буду в процессе пояснять. Теперь таблица Excel представляется обычной таблицей базы данных, у которой есть строки, есть колонки, чтобы прочитать данные из этой таблицы необходимо сформировать SQL-запрос и передать его объекту RecordSet. Сейчас мы сформируем запрос, который откроет доступ к диапазону строк с 10 до 120 и колонок с A по S:
НачСтрока = 10; КонСтрока = 120; СтрокаЗапроса = " |SELECT * |FROM [A" + Строка(НачСтрока) + ":S" + Строка(КонСтрока) + "] |"; //Выбираются необходимые ячейки листа //Для наложения условия используется синтаксис SQL //РабЛ = СоздатьОбъект("ADODB.RecordSet"); Объект этого типа мы сейчас получим РабЛ = Екс.Execute(СтрокаЗапроса);
Последовательно читаем все строки объекта RecordSet с помощью методов MoveFirst (ПолучитьПервуюЗапись) и MoveNext (ПолучитьСледующуюЗапись). Внутри строки перемещаемся с помощью коллекции Fields:
СтрТекст = ""; СчСтрок = 0; РабЛ.MoveFirst(); //Получить первую строку набора Пока Число(РабЛ.EOF()) = 0 Цикл //Выполняем цикл пока флаг окончания набора записей (Метод EOF) //не будет установлен в значение Истина (перебираем строки таблицы) СчСтрок = СчСтрок + 1; Сообщить(СтрТекст); СтрТекст = "Строка № " + СчСтрок + ": "; Для Сч = 1 По РабЛ.Fields.Count() Цикл //Перебор элементов коллекции Fields (колонки внутри строки) ТекЗначение = СокрЛП(РабЛ.Fields(Сч - 1).Value); СтрТекст = СтрТекст + ТекЗначение + "!"; КонецЦикла; РабЛ.MoveNext(); //Получить следующую строку набора КонецЦикла; Сообщить(СтрТекст); //Закрываем объекты Оле РабЛ.Close(); Екс.Close();
Вот так, с помощью нехитрых методов и обрывочных знаний по Visual Basic можно обращаться к информации, хранящейся в недоступных, казалось бы, файлах. Если фрагменты представленного здесь кода собрать вместе, то получим процедуру, читающую данные в книге Excel и выводящую их в виде сообщений пользователю. Для тех, кто ценит свое время, прилагаю уже готовую обработку, которая воспроизводит описанные здесь дейтсвия. Её Вы можете взять за основу и доработать под свои нужды.
Как определить КонСтрока?
(1) CheBurator, вероятно, с помощью ADOX.Catalog, ADOX.Tables
(1) CheBurator, определить количество заполненных строк в файле Excel не открывая самого файла — задача еще та… Можно упростить задачу: задавать значение переменной КонСтрока как заведомо большое, чтобы в диапазон попала вся необходимая информация или предоставить эту возможность самому пользователю, выведя на форму соответствующее поле.
Есть еще 3-ий вариант: считывать информацию из файла в цикле небольшими блоками по N строк в каждом, когда в очередном блоке не оказалось нужной информации — выход из цикла.
На самом деле строку запроса можно составить таким образом, чтобы в него попали все данные или только необходимые, например, если СтрокаЗапроса = «Select * FROM [Лист1$]», то в выборке окажется весь лист с именем «Лист1». Если лист Excel именно таблица, т.е. в первой строке его находятся заголовки столбцов, а ниже — данные, то к нему (листу) можно обращаться как к таблице базы данных с использованием имен столбцов и фильтров. Например запрос «Select * FROM [Лист1$] Where Количество = 2» отфильтрует строки на листе «Лист1» по колонке «Количество» = 2.
Причем меня терзают смутные подозрения, что если в запросе обратиться к пустому листу, то выборка также окажется пустой, но времени на проверку данного подозрения не было. Отпишитесь, у кого будет желание