Имя: Пароль:
1C
1С v8
Загрузка из excel с использованием ADODB
, , ,
0 Vlaloplo
 
26.05.22
15:43
Всем доброго времени суток! Оговорю сразу, с данным методом загрузки не разу не работал, возможно у кого то уже был опыт с данной технологией
Есть код загрузки файла:

Знач ПодключениеADODB = "MicrosoftJetOLEDB40")
    
    Перем СonnectionString, ADODBConnection, ADODBRecordset, ТекстЗапроса;
    Перем КолвоКолонокExcel, Поле, Колонка, ИмяКолонки;
    Перем НоваяСтрока, НомерСтроки;
    //Перем ТаблицаРезультат;
    
    // Нумерация MS ADODB начинается с 1.
    
    // Переменная "СтрокаЗаголовка", не используется, т.к. HDR=YES, а не HDR=NO.
    //HDR = YES;
    // 1. Считывание заголовков колонок с 1-ой строки.
    // 2. Считываемые данные со 2-ой и последующих строк типизированы. Для варианта HDR=NO: считываемые данные - строка.
    
    // Строка соединения - определение драйвера, который будет использован для подключения к файлу EXCEL.
    Если ПодключениеADODB = "MicrosoftACEOLEDB12" Тогда
        
        // ACE.OLEDB.12.0 - Для использования данного подключения необходимо дополнительное ПО:
        // Microsoft Access Database Engine 2010 Redistributable 32/64 bit.
        СonnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " + СокрЛП(ФайлEXCEL) + ";Extended Properties=""Excel 12.0;HDR=NO;IMEX=1;""";
        
        // Еще один вариант.
        //СтрокаСоединения = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Dbq=" + СокрЛП(ФайлEXCEL) + ";";
        
    Иначе
        
        // Jet.OLEDB.4.0 - Стандартное подключение, как правило, не требующее установки дополнительного ПО.
        // Рекомендуется установить последний Service Pack Windows.
        СonnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= "  + СокрЛП(ФайлEXCEL) + ";Extended Properties=""Excel 8.0;HDR=NO;IMEX=1;""";
        
        // Еще один вариант.
        //СтрокаСоединения = "Driver={Microsoft Excel Driver (*.xls)};Dbq=" + СокрЛП(ФайлEXCEL) + ";";
        
    КонецЕсли;
    
    Попытка
        // Инициализация основного объекта ADODB.Connection. Открытие соединения.
        ADODBConnection = Новый COMОбъект("ADODB.Connection");
        ADODBConnection.ConnectionString =  СonnectionString;
        ADODBConnection.Open();
        // Импирически определенный параметр для правильного определения количества строк листа.
        ADODBConnection.CursorLocation = 3;    // По-умолчанию 2.
    Исключение
        Сообщить(НСтр("ru = '"+ОписаниеОшибки()+"'"), СтатусСообщения.Внимание);
        //Возврат Новый ТаблицаЗначений;    // В случае ошибки возвращаем пустую таблицу значений.
    КонецПопытки;
    
    ТекстЗапроса = "SELECT * FROM [" + ИмяЛиста + "$]";
    
    // Создание Recordset. Дочерний объект ADODBConnection. Набор записей по запросу.
    Попытка
        ADODBRecordset = Новый COMОбъект("ADODB.Recordset");
        ADODBRecordset.Open(ТекстЗапроса, ADODBConnection);
        
        // Проверка заполненности листа.
        Если (ADODBRecordset.EOF ИЛИ ADODBRecordset.BOF) Тогда
            КолвоСтрокExcel = 0;
            Сообщить(НСтр("ru = '" + ИмяЛиста + ": не содержит данных.'"), СтатусСообщения.Внимание);
            
            // Завершение работы.
            // Закрытие Объектов.
            ADODBRecordset.Close();
            ADODBConnection.Close();
            ADODBRecordset   = Неопределено;
            ADODBConnection = Неопределено;
            
            //Возврат Новый ТаблицаЗначений;    // В случае ошибки возвращаем пустую таблицу значений.
        КонецЕсли;
        
        // Импирически определенные параметры для правильного определения количества строк листа.
        ADODBRecordset.AbsolutePage     = 1;
        ADODBRecordset.AbsolutePosition = 1;
    Исключение
        Сообщить(НСтр("ru = '"+ОписаниеОшибки()+"'"), СтатусСообщения.Внимание);
        //Возврат Новый ТаблицаЗначений;    // В случае ошибки возвращаем пустую таблицу значений.
    КонецПопытки;
    
    // Параметр, возвращаемый в вызывающую процедуру.
    КолвоСтрокExcel = ADODBRecordset.RecordCount + 1;    // (+1) - учет Строки-Заголовока, которая "съедается".
    КолвоКолонокExcel = ADODBRecordset.Fields.Count;
    
    // Проверка заполненности листа.
    Если КолвоСтрокExcel <= 2 Тогда
        КолвоСтрокExcel = 0;
        Сообщить(НСтр("ru = '" + ИмяЛиста + ": не содержит данных.'"), СтатусСообщения.Внимание);
        
        // Завершение работы.
        // Закрытие Объектов.
        ADODBRecordset.Close();
        ADODBConnection.Close();
        ADODBRecordset   = Неопределено;
        ADODBConnection = Неопределено;
        
        //Возврат Новый ТаблицаЗначений;    // В случае ошибки возвращаем пустую таблицу значений.
    КонецЕсли;
    
    // Создание результирующей таблицы, в которую будут записываться считанные из EXCEL данные.
    //ТаблицаРезультат = Новый Массив;
    
    НомерСтроки = -1;
    
    ПаспортРФ = ПолучитьВидДокумента("Паспорт гражданина РФ");
    ПаспортИН = ПолучитьВидДокумента("Иностранный паспорт");
    
    Пока ADODBRecordset.EOF() = 0 Цикл
        
        НомерСтроки = НомерСтроки + 1;
        
        Если НомерСтроки = КолвоСтрокExcel - 1 Тогда
            ADODBRecordset.MoveNext();            
            Продолжить;
        КонецЕсли;
        
        Если НомерСтроки < НачСтрока Тогда    // Номер строки вне диапазона считываемых строк.
            ADODBRecordset.MoveNext();             // Следующая строка.
            Продолжить;
        КонецЕсли;
        
        Если КонСтрока > 0 И НомерСтроки > КонСтрока Тогда    // Номер строки вне диапазона считываемых строк.
            Прервать;
        КонецЕсли;

На строчке КолвоСтрокExcel = ADODBRecordset.RecordCount + 1; вылетает ошибка: "Произошла исключительная ситуация (ADODB.Recordset): Операция не допускается, если объект закрыт.". Работа проходит на сервере по rdp, но у некоторых пользователей (сервера) эта ошибка возникает, а у кого то нет. Загружается одна и та же excel. В чем предположительно может быть дело? Или может есть понимание, что за объект нужно открыть? пробовал открывать сам файл excel и загружать так, не сработало
1 Vlaloplo
 
26.05.22
15:44
Данных код писал не я, поэтому сложно понять, что тут вообще происходит ..
2 Vlaloplo
 
26.05.22
16:06
UP
3 Kassern
 
26.05.22
16:10
Новый табличный документ вам в помощь) 1ска умеет без всяких адобов читать эксельки
4 Kassern
 
26.05.22
16:11
*адодбов)
5 Vlaloplo
 
26.05.22
16:14
(3) Да я тоже это это никогда не юзал) Но интерес, а так же лень переделки кода загрузки заново взяла вверх и завела сюда)
6 sandal_r
 
26.05.22
16:17
а ошибка "%ИмяЛиста% не содержит данных" не вылазит?
7 Vlaloplo
 
26.05.22
16:18
(6) нет, имя Листа это реквизит на форме, который заполнен
8 Vlaloplo
 
26.05.22
16:19
Ну или я до неё не до хожу
9 sandal_r
 
26.05.22
16:29
судя по империческим вставкам - код писался методом тыка.
поддержку (3), переписать будет быстрее, чем отловить баги (тем более не всегда повторяющиеся)
10 Vlaloplo
 
26.05.22
17:21
Ещё раз UP, что то уже может под вечер туплю..
Пишу:
табДок = Новый ТабличныйДокумент;
табДок.Прочитать(ИмяФайла); (имя файла - полный путь к файлу с его названием, тип строка естественно)
На что получаю ошибку "Ошибка при выполнении файловой операции". Пробовал и на стороне сервера и на стороне клиента - однотипно. Думал может с файлом что то не то, пересоздал файл заново, сохранил и всё равно так
11 Kassern
 
26.05.22
17:24
(10) файл случайно не открыт у вас? Файл на сервере 1с доступен? На клиенте вы его и не откроете. Через клиент вы можете получить двоичные данные файла и передать через временное хранилище на сервер. А там уже получить с хранилища и записать во временный файл на сервере. С ним уже работать
12 Vlaloplo
 
26.05.22
17:26
(11),Файл закрыт. Как я могу проверить, что файл на сервере доступен?
13 Kassern
 
26.05.22
17:29
(12) зайти на сам сервер и попробовать на нем открыть. Либо поместить на физический диск сервера файл и прописать путь к нему
14 Kassern
 
26.05.22
17:31
опять же может служба 1с под системной записью запущена, тогда по сети вряд ли сможет 1ска на сервере получать файлы. Поэтому либо через клиент передавайте ДД, либо кидайте файлы на сервер, либо запускайте службу 1с с правами для папки где файлы лежат
15 NorthWind
 
26.05.22
17:57
(0) у вас возврат из процедуры должен быть в том случае, если лист не заполнен. Но возврат этот закомменчен

     //Возврат Новый ТаблицаЗначений;    // В случае ошибки возвращаем пустую таблицу значени

а в данной ветке перед возвратом происходит закрытие рекордсета. Соответственно исполнение идет дальше. Оно пытается сделать

КолвоСтрокExcel = ADODBRecordset.RecordCount + 1;

эта манипуляция требует открытого рекордсета, а он у вас ранее был закрыт. Вот и ошибка.
16 NorthWind
 
26.05.22
17:58
в принципе, простейший код и откомментирован нормально
17 тук-тук
 
26.05.22
20:11
(0) предлагаю заменить твою простынь на 8 строчек

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПолноеИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
ПЗ = Новый ПостроительЗапроса;
ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
ПЗ.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
ПЗ.ЗаполнитьНастройки();
ПЗ.Выполнить();
ТЗ = ПЗ.Результат.Выгрузить();
18 yopQua
 
26.05.22
20:22
ну по рекордсету инфы много, старый он уже, как и все кто с ним работал
когда то видел таблицу со всеми свойствами и методами и нормальным к ним описаниям.. на каком то желтом фоне было)
19 NorthWind
 
26.05.22
21:37
(18) MSDN
Требовать и эффективности, и гибкости от одной и той же программы — все равно, что искать очаровательную и скромную жену... по-видимому, нам следует остановиться на чем-то одном из двух. Фредерик Брукс-младший