Как сделать Загрузку Excel (стадия программирования начинающего программиста)

1. DiaDiamond 18.05.22 10:25 Сейчас в теме
Здравствуйте , прошу проверить загрузку из эксель , т.к посмотрел разные сайты, но не нашел как же все таки правильно сделать.

Делаю так:

Создаю обработку. Создаю реквизит формы ПутьКФайлу. Его вытаскиваю в элементы формы.
Указываю в событии НачалоВыбора ПутьКФайлуНачалоВыбора

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


Затем создаю команду загрузить. У нее следующий код:

&НаСервере
Процедура ЗагрузитьНаСервере(ДвоичДанные, Расширение)
    
    ФайлЭксельНаСервере = ПолучитьИмяВременногоФайла(Расширение);
    ДвоичДанные.Записать(ФайлЭксельНаСервере);

    Попытка
        // Создание COM-объекта
        Эксель = Новый COMОбъект("Excel.Application");
        
        // Отключение вывода предупреждений и вопросов        
        Эксель.DisplayAlerts = 0;
        Эксель.Visible = 0;
    Исключение
           Return;
    КонецПопытки;

    // Открываем книгу
    Книга = Эксель.Workbooks.Open(ФайлЭксельНаСервере);
        
    // Открываем лист
    Лист = Книга.Sheets(1);
    
    // Определяем количество строк и столбцов
    ВсегоСтрок = Лист.Cells(1,1).SpecialCells(11).Row;
    ВсегоСтолбцов = Лист.Cells(1,1).SpecialCells(11).Column;
    
    // Перебираем строки
    Для СчетчикСтрок = 2 По ВсегоСтрок Цикл
                            
        Организация = Лист.Cells(СчетчикСтрок,1).Value;
        
        ОрганизацияСпр = Справочники.Организации.НайтиПоНаименованию(Организация);
        Имя = Лист.Cells(СчетчикСтрок,2).Value;
        ФИО = Лист.Cells(СчетчикСтрок,3).Value;
        
        // Создаем нового агента в справочнике Агенты
        Агент = Справочники.Агенты.СоздатьЭлемент();
                
        // Заполняем реквизиты
        Агент.Владелец = ОрганизацияСпр;
        Агент.Наименование = Имя;
        Агент.ФИО = ФИО;
        
        // Записываем
        Агент.Записать();
        
    КонецЦикла;    
        
    // Закрываем книгу
    Эксель.Workbooks.Close();
    
    // Отключаем Эксель
    Эксель.Application.Quit();
    
КонецПроцедуры


// загрузка агентов
&НаКлиенте
Процедура Загрузить(Команда)
    
    ИмяФайла = ЭтаФорма.ПутьКФайлу;
    
    нФайл = Новый Файл(ИмяФайла);
    
    Если Не нФайл.Существует() Тогда
    
        Возврат;    
    
    КонецЕсли; 
    
    ДвоичДанные = Новый ДвоичныеДанные(ИмяФайла);
    
    ЗагрузитьНаСервере(ДвоичДанные, нФайл.Расширение);
    
КонецПроцедуры
Показать


и вроде как то работает но очень плохо , работал с материалами и фурнитурой

(Уважаемые модераторы, прошу не банить данный вопрос , я начинающий программист)
Прикрепленные файлы:
По теме из базы знаний
Найденные решения
11. nomad_irk 76 18.05.22 15:50 Сейчас в теме
(9)так даже на этих объемах нативное 1С чтение *.xls(х) проигрывает по скорости в 10-25 раз чтению с помощью MS Excel(COM)
p.s тест запускать либо в файловом варианте, либо с установленным на сервере MS Excel.
Прикрепленные файлы:
ЗамерВремениЧтенияXLS.epf
ТестовыйЛист_100к_строк_20_колонок.zip
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. PlatonStepan 38 18.05.22 10:32 Сейчас в теме
1С умеет в эксель без всяких COM/OLE.
1) Получаете книгу EXCEL через табличный документ.
2) Переносите данные табличного документа в таблицу значений.
3) профит!
ivan1703; echo77; DesertPunk; Prikum; DiaDiamond; +5 Ответить
3. DiaDiamond 18.05.22 10:33 Сейчас в теме
4. nomad_irk 76 18.05.22 11:10 Сейчас в теме
(2)умеет, но очень медленно, если загружать/выгружать "простынями"
DiaDiamond; +1 Ответить
7. starik-2005 3090 18.05.22 12:26 Сейчас в теме
(4) Простынями - это как?
При большом объеме данных с экселем (непонятно зачем, но все же) работать можно только через ODBC, как с источником данных. А для "бытовых" нужд достаточно табличного документа (99,9% случаев).
unknown181538; DiaDiamond; +2 Ответить
8. nomad_irk 76 18.05.22 12:30 Сейчас в теме
(7)
Простынями - это как?

это скажем 20 колонок при 50к строк
DiaDiamond; +1 Ответить
9. starik-2005 3090 18.05.22 12:31 Сейчас в теме
(8)
это скажем 20 колонок при 50к строк
Это немного.
DiaDiamond; +1 Ответить
11. nomad_irk 76 18.05.22 15:50 Сейчас в теме
(9)так даже на этих объемах нативное 1С чтение *.xls(х) проигрывает по скорости в 10-25 раз чтению с помощью MS Excel(COM)
p.s тест запускать либо в файловом варианте, либо с установленным на сервере MS Excel.
Прикрепленные файлы:
ЗамерВремениЧтенияXLS.epf
ТестовыйЛист_100к_строк_20_колонок.zip
12. PlatonStepan 38 19.05.22 06:33 Сейчас в теме
(11)

А разве автор где-то пишет, что требуется скорость при чтении?
Он учится, а учиться надо на элементарных подходах.
Вот освоит чтение Книги, освоит получение Листов, потом обход табличного документа по ячейкам.
И всё это без магии:
Лист.Cells(1,1).SpecialCells(11).Row - для старого формата
или
Страница.UsedRange.Rows.Count - для нового формата

А когда скорость станет критичной, то тогда и реализует другой подход, например получение данных таблиц через COMSafeArray.
13. starik-2005 3090 19.05.22 10:16 Сейчас в теме
(11)
проигрывает
А при чем тут построитель отчета?
14. nomad_irk 76 19.05.22 10:21 Сейчас в теме
(13)Так простым циклом по ячейкам будет дольше/не быстрее.
15. spacecraft 19.05.22 13:44 Сейчас в теме
(11) в замер времени выполнения через СОМ не включили подключение, получение страницы и создание ТЗ :)
Да, на больших таблицах второй способ будет выигрывать.
Но на не больших будет проигрывать. Хотя там не сильно будет принципиально, если только не загружать много файлов небольшого размера.

Ну и самое важное. Если это необходимо делать на сервере, то не факт, что Excel будет на сервере (а это скорее всего так и будет).
16. nomad_irk 76 19.05.22 13:50 Сейчас в теме
(15)Если вы думаете, что это все драмматичным образом скажется на результате, предлагаю самостоятельно "передвинуть" строку
НачалоЗамера = ........
до нужного места в коде :)
17. spacecraft 19.05.22 13:52 Сейчас в теме
(16) так я и не спорил, что на больших файлах будет выигрывать. Но время выполнения увеличилось вдвое.
18. nomad_irk 76 19.05.22 13:58 Сейчас в теме
(15)
Ну и самое важное. Если это необходимо делать на сервере, то не факт, что Excel будет на сервере (а это скорее всего так и будет)

так посыл именно в том, что не нужно стеснятся использовать Excel в том числе и на сервере.
19. spacecraft 19.05.22 13:59 Сейчас в теме
(18) странный посыл, требовать установку Excel на сервер (если он не терминальный).
20. nomad_irk 76 19.05.22 14:05 Сейчас в теме
(19)пффф...не требовать, а использовать, если возможно.

Если прям совсем невозможно на сервере, можно использовать на клиентах.

Таким же успехом используется на сервере тот же imagick и что-то стонов про него не слышно особо
5. user686924_shipikVV 18.05.22 12:07 Сейчас в теме
Три способа:

1: самый простой:

Функция ЧтениеExcel(ВыбранныйФайл)

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ВыбранныйФайл);

ОбластиТаб = ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, ТабДок.ШиринаТаблицы);

Построитель = Новый ПостроительОтчета
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластиТаб);
Построитель.Выполнить();

ТабДанные = Построитель.Результат.Выгрузить();
Возврат ТабДанные;

КонецФункции

2: Через Com:

Функция ЧтениеExcel(ВыбранныйФайл)

Попытка

ТЗ = Новый ТаблицаЗначений();

Excel = Новый COMОбъект("Excel.Application");
Excel.WorkBooks.Open(ВыбранныйФайл);

//Открыть необходимый лист
Excel.Sheets(1).Select(); //лист 1, по умолчанию

//Получить количество строк и колонок.
//В разных версиях Excel получаются по-разному, поэтому сначала определить версию Excel
Версия = Лев(Excel.Version,Найти(Excel.Version,".")-1);
Если Версия = "8" тогда
МакСтрок = Excel.Cells.CurrentRegion.Rows.Count;
МакСтолб = Макс(Excel.Cells.CurrentRegion.Columns.Count, 13);
Иначе
МакСтрок = Excel.Cells(1,1).SpecialCells(11).Row;
МакСтолб = Excel.Cells(1,1).SpecialCells(11).Column;
Конецесли;

Для Столбец = 1 по МакСтолб цикл
ИмяСтолбца = "Столбец_" + Столбец;
ТЗ.Колонки.Добавить(ИмяСтолбца, Новый ОписаниеТипов("Строка"));
КонецЦикла;

Для НомСтрока = 1 по МакСтрок цикл
СтрТЗ = ТЗ.Добавить();
Для НомСтолбец = 1 по МакСтолб цикл
Данные = Excel.Cells(НомСтрока,НомСтолбец).Value;
СтрТЗ[НомСтолбец-1] = Данные;
КонецЦикла;
КонецЦикла;

Excel.ActiveWorkbook.Close(); Excel.Quit(); Excel = 0;

Возврат ТЗ;

Исключение
Сообщить("Произошла ошибка при обращение к Excel:" + Символы.ПС + ОписаниеОшибки());
Excel.ActiveWorkbook.Close(); Excel = 0;
Возврат Неопределено;
КонецПопытки;

КонецФункции

3: Еще один через Com:

Функция ЧтениеExcel(ВыбранныйФайл)

Попытка

Док = ПолучитьCOMОбъект(ВыбранныйФайл);

ТЗ = Новый ТаблицаЗначений();
Страница = Док.Sheets(1);
МакСтрок = Страница.UsedRange.Rows.Count; // макс. колич. строк
МакСтолб = Страница.UsedRange.Columns.Count; // макс. колич. столбцов

Для Столбец = 1 по МакСтолб цикл
ИмяСтолбца = "Столбец_" + Столбец;
ТЗ.Колонки.Добавить(ИмяСтолбца, Новый ОписаниеТипов("Строка"));
КонецЦикла;

Для НомСтрока = 1 по МакСтрок цикл
СтрТЗ = ТЗ.Добавить();
Для НомСтолбец = 1 по МакСтолб цикл
Данные = Страница.Cells(НомСтрока,НомСтолбец).Value;
СтрТЗ[НомСтолбец-1] = Данные;
КонецЦикла;

КонецЦикла;

Возврат ТЗ;

Исключение
Сообщить("Произошла ошибка при обращение к Excel:" + Символы.ПС + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;

КонецФункции
6. user686924_shipikVV 18.05.22 12:09 Сейчас в теме
Во всех случаях выгружается таблица значений.
А она сама по себе быстрее работает.
DiaDiamond; +1 Ответить
10. igor63 18.05.22 12:36 Сейчас в теме
Там при прочтении бываю сложности с отображениями некоторых символов, доп функции нужны
DiaDiamond; +1 Ответить
21. JetBrain 76 19.05.22 16:57 Сейчас в теме
пример немного более быстрого варианта:
&НаСервере		
Процедура ЗагрузитьНоменклатуру() Экспорт
	
	Connection = Новый COMОбъект("ADODB.Connection");
	Connection.ConnectionString  = "Driver={Microsoft Excel Driver (*.xls)};DBQ="+Объект.ПутьКФайлу+";DriverId=790";
	
	Попытка
		Connection.Open();
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;
	
	Сообщить("Загрузить номенклатуру...");
	
	СтрокаЗапроса = " SEL ECT DISTINCT * FR OM ["+Объект.НомерЛиста+"$A:С]";
				 	
	Попытка
		COMObject     = Connection.Execute(СтрокаЗапроса); 
		COMSafeArray  = COMObject.GetRows(); 
	Исключение
		Сообщить(СтрокаЗапроса + " // " + ОписаниеОшибки());
		Возврат;
	КонецПопытки;
			
    N = COMSafeArray.GetUpperBound();          
	
	Сообщить("Строк в документе:"  + Строка(N));
	
	Для Индекс = Число(Объект.НачСтрока) по ?(Объект.КонСтрока > N, N, Объект.КонСтрока) Цикл 
						 
	 	АртикулИмп 				= ?(Объект.Артикул =0,"",СокрЛП(COMSafeArray.GetValue(Индекс, Объект.Артикул-1)));
		НаименованиеИмп         = СокрЛП(COMSafeArray.GetValue(Индекс, Объект.Наименование-1));				
		КодКИСИмп	          	= ?(Объект.КодКИС  =0,"",СокрЛП(COMSafeArray.GetValue(Индекс, Объект.КодКИС-1)));			
		
		Попытка
			Результат = Справочники.НоменклатураКонтрагентов.НайтиПоКоду(АртикулИмп);
			Если Результат.Ссылка.Пустая() Тогда		
				НовыйТовар = Справочники.НоменклатураКонтрагентов.СоздатьЭлемент();
				НовыйТовар.Код                          = АртикулИмп;
				НовыйТовар.Наименование       = НаименованиеИмп;
				НовыйТовар.НоменклатураКИС = Справочники.Номенклатура.НайтиПоКоду(КодКИСИмп);
				НовыйТовар.Записать();		
			КонецЕсли;    		
		Исключение
			Сообщить(ОписаниеОшибки());
		КонецПопытки;		
	
	КонецЦикла;	    
	
	Сообщить("Обработано строк файла: " + Строка(Индекс));
	Сообщить("Конец загрузки: " + Строка(ТекущаяДата()));
	
	Connection.Close();		
	
КонецПроцедуры
Показать
PlatonStepan; +1 Ответить
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот