Почему при загрузке таблицы Excel в 1С возникают ошибки?

Публикация № 616875

Управление - Не имеет значения

загрузка Excel ADODB

9
При загрузке из EXCEL в 1С методом MS ADODB.Connection столкнулся с некоторыми проблемами, которые попытался устранить в ниже приведенной статье. Надеюсь, что статья поможет вам сократить время разработки.  Особая благодарность Андрею М. за публикацию //infostart.ru/public/163640/

В данной статье приведен функционал, с помощью которого в обработке
"Импорт из EXCEL (xls) в 1С"
производится считывание данных из файлов табличного типа *xls.

Есть множество статей на эту тему:

Метод "MS ADO" (Чтение файлов xls, xlsx средствами Microsoft ADO): //infostart.ru/public/163640/
- Метод "MS EXCEL" (Чтение файлов xls, xlsx с картинками средствами Microsoft Office): //infostart.ru/public/163641/
- Метод "LO CALC" (Чтение файлов xls, xlsx, ods, sxc с картинками средствами LibreOffice): //infostart.ru/public/163642/
- Метод "NativeXLSX" (Чтение файлов xlsx с картинками средствами 1С. ПостроительDOM): //infostart.ru/public/300092/
- Метод "NativeXLSX". Предыдущий вариант (Чтение файлов xlsx средствами 1С. ЧтениеXML)://infostart.ru/public/225624/
- Метод "Excel1C" (Загрузка на платформе 8.3.6 с картинками. Чтение файлов xls, xlsx, ods): //infostart.ru/public/341855/
- Список листов файла: //infostart.ru/public/163724/

Но всегда возникают какие-то проблемы:

При загрузке из EXCEL в 1С методом MS ADODB.Connection столкнулся со следующим:

  • пользователь выделил цветом всю таблицу Excel, что привело к считыванию всего листа книги.  

  • EOF() оказался гораздо дальше чем реально пользователь видел при визуальном осмотре таблицы Excel, т. е. загружались пустые строки

  • необходимо было очищать таблицу от строк  с наименованиями колонок

Это моя первая публикация. Буду рад вашим исправлениям и комментариям. P.S. Код написан только для расширения .xls. 

 

&НаКлиенте
Процедура ЗагрузитьExcel(Команда)
	
	Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
	Диалог.Заголовок = "Выберите файл";
	Диалог.Фильтр = "|*.xls";
	Диалог.МножественныйВыбор = Ложь;
	
	Если Диалог.Выбрать() Тогда
		
		Адрес = "";
		ПоместитьФайл(Адрес,Диалог.ПолноеИмяФайла,,Ложь);
		ЗагрузитьНаСервере(Адрес);
		
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗагрузитьНаСервере(Адрес)

	ТЗ = ЗагрузитьТаблицуExcelНаСервере(Адрес);
    //далее код работы с ТЗ ....
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ЗагрузитьТаблицуExcelНаСервере(Адрес)
	
	ФайлИзХранилища =  ПолучитьИзВременногоХранилища(Адрес);
	ВременныйФайл = ПолучитьИмяВременногоФайла("xls");
	//Сохранение во временнный файл на диске
	ФайлИзХранилища.Записать(ВременныйФайл);
	//Если опущен, тогда 1-й лист
	еБаза=Новый COMОбъект("ADODB.Connection");
	СтрокаПодключения = "
	|Provider=Microsoft.Jet.OLEDB.4.0;
	|Data Source="+ВременныйФайл+";
	|Extended Properties=""Excel 8.0;IMEX=1;HDR=NO;"";";
	
	Попытка 
		еБаза.Open(СтрокаПодключения);	
	Исключение
		
		СтрокаПодключения = "
		|Provider=Microsoft.ACE.OLEDB.12.0;
		|Data Source="+ПутьКФайлу+";
		|Extended Properties=""Excel 12.0;IMEX=1;HDR="+?(HDR,"Yes","No")+";"";";
		
		Попытка                        		
			еБаза.Open(СтрокаПодключения);		
		Исключение                     		
			Сообщить(ОписаниеОшибки());
		КонецПопытки;
		
	КонецПопытки;
	
	Catalog = Новый COMОбъект("ADOX.Catalog");
	Catalog.ActiveConnection = еБаза;
	лСпис=Новый СписокЗначений;
	лИмяЛиста="";
		
	Для iCount = 0 По Catalog.Tables.Count-1 Цикл
		Если Catalog.Tables.Item(iCount).Type <> "VIEW" Тогда
			лСпис.Добавить(Catalog.Tables.Item(iCount).Name);	
		КонецЕсли;
	КонецЦикла;
	
	Если лСпис.Количество()>0 И лИмяЛиста="" тогда
		лИмяЛиста = лСпис[0];
	Конецесли;
	
		
	Catalog=Неопределено;
	лСтрВнЗапроса="select * from ["+лИмяЛиста+"]";
	
	RS = Новый  COMОбъект("ADODB.Recordset");
	
	rs.Open(лСтрВнЗапроса,еБаза,0);
	
	лТз=Новый ТаблицаЗначений;
	
	ЕстьОшибкиВИмениКолонки=Ложь;
	
	Для iCount = 0 По rs.Fields.Count-1 Цикл
		
		Если СокрЛП(rs.Fields.Item(iCount).Value) = "" Тогда //прервём на пустой ячейке имени колонки
			Прервать;
		КонецЕсли; 
		
		Попытка
			лТз.Колонки.Добавить(rs.Fields.Item(iCount).Value,, rs.Fields.Item(iCount).Name); // Считаем что в первой строке заголовки колонок
		Исключение
		    Сообщить(ОписаниеОшибки()+" «"+(rs.Fields(iCount).Value)+"»");
			ЕстьОшибкиВИмениКолонки = Истина;
		КонецПопытки;	
		
	КонецЦикла;
	
	Если ЕстьОшибкиВИмениКолонки Тогда //прерываем, чтобы исправили
		Возврат лТз;
	КонецЕсли;
	
	// Перебор данных
	Строк=0;
	rs.MoveFirst();                 
	
	//пользователь выделил цветом весь лист Excel, в том числе и пустые ячейки
	//добавим переменную для счета количества пустых ячеек, 
	//как только будет 10 пустых ячеек, считаем, что уже закончились строки в таблице
	
	СчПустых = 0;
	ПустыеСтроки = 0;
	
	Пока rs.EOF() = 0 Цикл
		
		СчПустых = 0;
		Строк=Строк+1;
		//как только будет 10 пустых ячеек, считаем, что уже закончились строки в таблице
		Если ПустыеСтроки = 10 Тогда
			Прервать;
		КонецЕсли;
		
		лТз.Добавить();
		
		Для iCount = 0 По rs.Fields.Count-1 Цикл
			
			Если СчПустых = 3 Тогда //подряд три пустых ячейки, прервём
				СчПустых = 0;//уменьшим
				ПустыеСтроки = ПустыеСтроки+1;
				//Если три первые ячейки строки пустые, то удаляем строку
				Если лТз[лтз.Количество()-1][0]=Неопределено И лТз[лтз.Количество()-1][0] = лТз[лтз.Количество()-1][1] И лТз[лтз.Количество()-1][1] = лТз[лтз.Количество()-1][2] Тогда
					лТз.Удалить(лТз[лтз.Количество()-1]);
				КонецЕсли;	
				Прервать;
			КонецЕсли;
		
			Если Строка(rs.Fields(iCount).Value) = "" Тогда
				СчПустых = СчПустых+1;
				Продолжить;
			КонецЕсли; 
			
			Попытка
				лТз[лтз.Количество()-1][iCount]=Строка(rs.Fields(iCount).Value);
				ПустыеСтроки = 0;
			Исключение
				Прервать;
			КонецПопытки;					
		КонецЦикла;
		rs.MoveNext();  
	КонецЦикла;
	rs=Неопределено;
	еБаза.Close();
	еБаза=Неопределено;
	УдалитьИзВременногоХранилища(Адрес);
	//Удалим первую строку с наименованием колонок
	Если лТз[0][0] = лТз.Колонки[0].Имя Тогда
		лТз.Удалить(лТз[0]);
	КонецЕсли; 
	
	Возврат лТз;
	
КонецФункции

 

9

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. CheBurator 3395 03.05.17 00:52 Сейчас в теме
на загрузку через ADO я плюнул много лет назад, когда при первой же попытке применить сей инструмент на первом же файле (а я промучался часа четыре) - выяснилось что из прайса ~10тысяч строк возвращается тупо порядка ~4000, хотя при обычном открытии экселем и обычным чтением из экселя все нормально проходило. и ADO на ДРУГИХ файлах - нормально проходило. А вот на этом - фигушки. так как я не спец в этих делах, а загрузку надо было ставить в автомат в продакшен - ADO благословеннно почил в бозе.. так я его и не освоил...
2. unichkin 1183 16.05.17 23:15 Сейчас в теме
Можно было лишние поля прямо в запросе отсеять.. Собственно, возможность указывать фильтр в запросе - одна из фишек ADO. Еще его используют когда:
- надо работать с Excell на сервере (а устанавливать его на сервер нельзя)
- надо читать большие объемы, без загрузки их в память (recordset) - в этом случае быстрее работает, чем перебор строк в Excell.Application
Но не всегда ADO выгоднее - его минусы в том, что всякий раз надо муздыкаться с драйверами. Локально у себя - все отлично, только передал клиенту, начинаются вопросы "что это он про какой-то драйвер спрашивает".. Поэтому для себя определился так, что ADO применять только в двух выше описанных случаях. А если файл небольшой, и работа идет на клиенте - вполне можно использовать чтение через Excell, работая с диапазонами (http://infostart.ru/public/20090/). Если все делать через range - в случае небольших книг по скорости не уступает ADO. Кстати, через range можно и записывать.
3. dakork 14 05.06.17 15:15 Сейчас в теме
Для использования ADO нет необходимости в установке msoffice.
4. KazanKokos 8 05.06.17 15:17 Сейчас в теме
сам когда делал выбор адо-неадо столкнулся с тем что не нашел в АДО уровень группировки строк, который есть в ексель.аппликейшн, а мне надо было загруженную номенклатуру раскидывать по папкам + еще прибавлять к имени номенклатуры названия папок двух верхних уровней и пришлось от АДО отказываться
Оставьте свое сообщение