Имя: Пароль:
1C
1С v8
Excel +ADO: вопрос
,
0 Маленький Вопросик
 
14.07.11
09:04
Создал ручкам лист в Эксель файле "Таблица"

ИмяФайлаЭксельНовый = "C:\MyExcel.xls";    
   
СтрокаПодключения = "
|Provider=Microsoft.Jet.OLEDB.4.0;
|Data Source="+ИмяФайлаЭксельНовый+";
|Extended Properties=""Excel 8.0;HDR=YES"";";

Connection = Новый COMОбъект("ADODB.Connection");

Connection.ConnectionString = СтрокаПодключения;

Попытка
   Connection.Open();
Исключение
   Сообщить(ОписаниеОшибки());
КонецПопытки;

Command = Новый COMОбъект("ADODB.Command");
Command.ActiveConnection = Connection;

Command.CommandText = "SELECT * FROM [Таблица]";
А=Command.Execute();

Сообщить(ТипЗнч(А));

выдает ошибку:

{Форма.Форма(25)}: Ошибка при вызове метода контекста (Execute): Произошла исключительная ситуация (Microsoft JET Database Engine): Объект 'Таблица' не найден ядром базы данных Microsoft Jet.  Проверьте существование объекта и правильность имени и пути.
А=Command.Execute();
по причине:
Произошла исключительная ситуация (Microsoft JET Database Engine): Объект 'Таблица' не найден ядром базы данных Microsoft Jet.  Проверьте существование объекта и правильность имени и пути.
1 Маленький Вопросик
 
14.07.11
09:11
хотя если я создам предварительно таблицу (лист) в экселе вот так:

Command.CommandText = "CREATE TABLE [Таблица2] (Символьный char(255), Дата date, Целый int, Дробный float)";
Command.Execute();

то запрос select - работает
2 manyak
 
14.07.11
09:22
Создал ручкам лист в Эксель файле "Таблица"
а запрос делаешь же к листу!

у тебя
Command.CommandText = "SELECT * FROM [Таблица]";

нужно:
Command.CommandText = "SELECT * FROM [имя_листа]";
3 Маленький Вопросик
 
14.07.11
09:33
(2) нет-нет...
файл Эксель - C:\MyExcel.xls

в нем я ручками сделал лист [Таблица]
к [Таблица] идет запрос...

или я что-то не догоняю....
4 manyak
 
14.07.11
09:34
не запутывай :)
как у тебя лист называется конкретно?
[Таблица]
или
Таблица

?
5 Маленький Вопросик
 
14.07.11
09:37
Command.CommandText = "SELECT * FROM Таблица";
А=Command.Execute();

так тоже не работает...
6 Маленький Вопросик
 
14.07.11
09:37
название листа - Таблица
7 GANR
 
14.07.11
09:41
8 rs_trade
 
14.07.11
09:42
адоТекстЗапроса = "SELECT * FROM [Лист1$];";
9 manyak
 
14.07.11
09:46
запрос = Новый COMОбъект("ADODB.Recordset");
запрос.ActiveConnection = Connection;
запрос.Source = "SELECT * FROM [Таблица$]";
запрос.open
10 Маленький Вопросик
 
14.07.11
09:51
Вот так сработало... теперь как данные в массив запихнуть???

Connection = Новый COMОбъект("ADODB.Connection");

Connection.ConnectionString = СтрокаПодключения;

Попытка
   Connection.Open();
Исключение
   Сообщить(ОписаниеОшибки());
КонецПопытки;

Command = Новый COMОбъект("ADODB.Command");
Command.ActiveConnection = Connection;

Command.CommandText = "SELECT * FROM [Таблица$]";
А=Command.Execute();

Сообщить(ТипЗнч(А)); //Ком объект - как вытащить SafeComArray ????
11 zdas
 
14.07.11
10:01
нубский вопрос - через адо быстрее чем через ком?
12 rs_trade
 
14.07.11
10:31
(11) гораздо. на порядок, два.
13 Маленький Вопросик
 
14.07.11
11:04
и все-таки, апаю тему в связи с (10)
14 rs_trade
 
14.07.11
12:06
(13) там строка возвращается. какой ты тип там хочешь?
15 Маленький Вопросик
 
14.07.11
12:07
в продолжении темы:

Command = Новый COMОбъект("ADODB.Command");
Command.ActiveConnection = Connection;
Command.CommandText = "SELECT * FROM [Таблица$]";
RecordSet=Command.Execute();
//RecordSet.MoveNext();
ДанныеСтроки = RecordSet.Fields(0).Value;
Сообщить(ДанныеСтроки);

строка включает в себя 4 ячейки (колонки) и читает их правильно.
ДанныеСтроки = RecordSet.Fields(от 0 до 3).Value;


возникли вопросы:
1.Почему считывает только цифры?
2.Почему пропускает первую строку (т.е. у меня всего 5 строк), код начинает считывать со второй строки.
16 Маленький Вопросик
 
14.07.11
12:08
в экселе формат ячейки установлен "общий"
17 Маленький Вопросик
 
14.07.11
12:22
ну апну для порядка...
18 smaharbA
 
14.07.11
12:24
(12) заспор, что через ком быстрее ?
19 smaharbA
 
14.07.11
12:25
(15) так и будет
20 Маленький Вопросик
 
14.07.11
12:26
(19) а как же тогда считать текстовую информацию??? не числа, а строки (наименования например)
21 smaharbA
 
14.07.11
12:27
я про первую строку
22 zdas
 
14.07.11
12:29
(18) всегда? или в определенных ситуациях?:)
23 guitar_player
 
14.07.11
12:32
(18) расскажите пожалуйста в чем отличие технологий и почему через com||ADODB будет быстрее?
24 Маленький Вопросик
 
14.07.11
12:34
(21) ну ладно, первую строку пропустил - это хорошо допустим (можно название колонки влепить)
давайте разберемся лучше почему только числа считывает????
25 smaharbA
 
14.07.11
12:37
(22) всегда
26 smaharbA
 
14.07.11
12:38
(23) только на спор
для сабжевого случая вообще одна строка кода
27 smaharbA
 
14.07.11
12:56
ок, измеряйте (для сабжа еще просче)


Процедура Сформировать()
   Перем Имя, Путь;
   Если ФС.ВыбратьФайл(0,Имя,Путь,"","Ексель|*.xls","*")=0 Тогда
       Возврат;
   КонецЕсли;
   ТЗ=СоздатьОбъект("ТаблицаЗначений");
   т1=_GetPerformanceCounter();
   Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
   Скрипт.language="javascript";
   Ексель=СоздатьОбъект("Excel.Application");
   Книги=Ексель.Workbooks;
   Книга=Книги.Open(Путь+Имя);
   Листы=Книга.Worksheets;
   Лист=Листы.Item(1);
   Скрипт.addobject("Диапазон",Лист.UsedRange);
   Массив=Скрипт.eval("new VBArray(Диапазон.Value)");
   Книга.Close(0);
   ТЗ.КоличествоКолонок(Массив.ubound(2));
   Для Стр=Массив.lbound(1) По Массив.ubound(1) Цикл
       ТЗ.НоваяСтрока();
       Для Кол=Массив.lbound(2) По Массив.ubound(2) Цикл
           ТЗ.УстановитьЗначение(Стр,Кол,Массив.getItem(Стр,Кол));
       КонецЦикла;
   КонецЦикла;
   Сообщить(_GetPerformanceCounter()-т1);
   ТЗ.ВыбратьСтроку();
КонецПроцедуры
28 rs_trade
 
14.07.11
13:18
(27) ну давай замеряем.
29 smaharbA
 
14.07.11
13:19
(28) замеряй, код в (27)
+ еще в адо есть маленькая неприятность с количеством колонок
30 FN
 
14.07.11
13:24
ставлю на smaharbA :)
31 rs_trade
 
14.07.11
13:29
(27) а че для 8 нету кода?
(30) я таким способом не грузил никогда данные. возьмем если что на вооружение.
32 smaharbA
 
14.07.11
13:34
(31) для восьмерки сразу
Массив=Диапазон.Value;

далее работаем как с COMSafe массивом
(могу немного ошибаться, ибо туг в восьмерке)
33 rs_trade
 
14.07.11
13:43
(32) поподробнее пожалуйста. мне гуглить надо что бы переписать этот код на 8
34 rs_trade
 
14.07.11
13:47
или пример на другом языке каком нить.
35 rs_trade
 
14.07.11
14:07
Загрузка через АДО 65 000 строк, 7 колонок, везде гуиды заняла 3 сек на моем тормозном компе.
36 rs_trade
 
14.07.11
14:10
+(35) это без перегона в тз. сам запрос. результат в рекордсете.
37 smaharbA
 
14.07.11
14:47
Пляха муха, восьмерку не знаю
все, что накропал


Процедура КнопкаВыполнитьНажатие(Кнопка)
   Перем Имя,Путь;
   Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
   Диалог.Заголовок = "Выберите файл";
   Диалог.ПолноеИмяФайла = "";
   Диалог.ПредварительныйПросмотр = Истина;
   Диалог.Фильтр = "Ексель|*.xls";
   Если Не Диалог.Выбрать() Тогда
       Возврат;
   КонецЕсли;
   ХТМЛ = СоздатьОбъект("htmlfile");
   ХТМЛ.Open("text/html");
   //<-- Подготовим нужные методы
   ХТМЛ.Write("<script type='text/javascript'>Дата=function(){return new Date().getTime()}</script>");
   Док=ХТМЛ.documentElement.document;
   Начало=Док.script.Дата(0);
   Ексель=Новый COMОбъект("Excel.Application");
   Книги=Ексель.Workbooks;
   Книга=Книги.Open(Диалог.ПолноеИмяФайла);
   Листы=Книга.Worksheets;
   Лист=Листы.Item(1);
   Массив=Лист.UsedRange.Value;
   ТЗ=Новый ТаблицаЗначений;
   Для Сч=1 По Массив.GetLength(0) Цикл
       ТЗ.Колонки.Добавить();
   КонецЦикла;
   Для Стр=1 По Массив.GetLength(1) Цикл
       НС=ТЗ.Добавить();
       Для Кол=1 По Массив.GetLength(0) Цикл
           НС.Установить(Кол-1,Массив.GetValue(Кол,Стр));
       КонецЦикла;
   КонецЦикла;
   Сообщить(Док.script.Дата(0)-Начало);
   ТЗ.ВыбратьСтроку();
КонецПроцедуры
38 smaharbA
 
14.07.11
15:03
(35)(36) вместе с перегоном в ТЗ - 9 сек, сам "запрос" по оле - 2 сек
39 rs_trade
 
14.07.11
15:04
У меня АДО выигрывает. в твоем коде замеры поставил здесь:


   ВремНач = ТекущаяДата();
   
   ХТМЛ = Новый COMОбъект("htmlfile");
   ХТМЛ.Open("text/html");
   //<-- Подготовим нужные методы

   ХТМЛ.Write("<script type='text/javascript'>Дата=function(){return new Date().getTime()}</script>");
   Док=ХТМЛ.documentElement.document;
   Начало=Док.script.Дата(0);
   Ексель=Новый COMОбъект("Excel.Application");
   Книги=Ексель.Workbooks;
   Книга=Книги.Open(ПутьКФайлу);
   Листы=Книга.Worksheets;
   Лист=Листы.Item(1);
   Массив=Лист.UsedRange.Value;
   
   ВремКон = ТекущаяДата();


Через АДО данные получаются от 0 до 3 секунд. Твой способ 5-6 секунд. Много времени уходит на создание ком объекта.
40 rs_trade
 
14.07.11
15:08
(38) у меня сейчас вообще 0 показывает. первое получение данных было 3 сек.
41 rs_trade
 
14.07.11
15:10
Время получения данных: 5
Твой секундомер: 4 768
42 rs_trade
 
14.07.11
15:25
Перем адоРезультат;
   
   Таблица = Новый ТаблицаЗначений;
   
   ТипыАДО = Новый Структура();
   ТипыАДО.Вставить("adUseServer", 2); // adUseServer
   ТипыАДО.Вставить("adOpenDynamic", 2); // adOpenDynamic
   ТипыАДО.Вставить("adLockReadOnly", 1); // adLockReadOnly
   ТипыАДО.Вставить("adCmdText", 1); // adCmdText
   
   СтрокаСоединения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="+ПутьКФайлу+";Extended Properties=""Excel 12.0 Xml;HDR=YES""";
   
   Попытка
       адоСоединение = Новый COMОбъект("ADODB.Connection");
       адоСоединение.ConnectionTimeout = 15;
       адоСоединение.CommandTimeout = 30;
       адоСоединение.Open(СтрокаСоединения);
   Исключение
       Сообщить(ОписаниеОшибки());    
       Возврат;    
   КонецПопытки;
   
   адоТекстЗапроса = "SELECT * FROM [Query$];";
   
   ВремНач = ТекущаяДата();
   
   Попытка
       адоРезультат = Новый COMОбъект("ADODB.RecordSet");
       адоРезультат.CursorLocation = 2;
       адоРезультат.Open(адоТекстЗапроса, адоСоединение, ТипыАДО.adOpenDynamic, ТипыАДО.adLockReadOnly, ТипыАДО.adCmdText);
   Исключение
       Сообщить(ОписаниеОшибки());    
       Возврат;
   КонецПопытки;
   
   ВремКон = ТекущаяДата();
   
   Сообщить("Время получения данных: "+Строка(ВремКон-ВремНач));
43 smaharbA
 
14.07.11
15:37
(41)(42) а ты внимательно код свои и (39)
44 smaharbA
 
14.07.11
15:38
и напиши правильно, по лубому оле будет быстрее
45 rs_trade
 
14.07.11
15:50
(44) ты про время начала замера? это я когда переписывал код что бы сюда выложить просто на место не вернул. у меня через функции вся работа с АДО. если подвинуть выше, результат тот же.

НО. перекачка данных в ТЗ по твоему способу в разы быстрее. учитывая что разница между получением данных всего несколько секунд, то в целом твой способ быстрее будет
46 rs_trade
 
14.07.11
16:03
в общем вот:

---------------- ADO ----------------
Время получения данных: 0
Время наполнения таблицы значений: 143
Количество строк: 65 000
---------------- COM ----------------
Время получения данных: 5
Время наполнения таблицы значений: 9(14 359)
Количество строк: 65 001
47 rs_trade
 
14.07.11
16:04
+(46) в 10 раз быстрее
48 zdas
 
14.07.11
16:14
(46) даже если и одна лишняя строка через КОМ - все равно быстрее)))
49 rs_trade
 
14.07.11
16:21
(48) только способ правильный знать надо.
50 BladeWorld
 
14.07.11
16:25
(21) В строке подключения напиши "HDR=NO", иначе считается, что в первой строке названия колонок
51 smaharbA
 
14.07.11
16:36
(45) у рекордсета тоже есть метод GetRows(x)
с ним как бы немного быстрее чем оле, но при малом количестве колонок
52 smaharbA
 
14.07.11
16:38
+(51) и для восьмерки при большом количестве колонок не выгодно пользовать, как и не выгодно сразу загонять в комсафемассив из оле - надо использовать обертку
53 Torquader
 
13.08.11
00:01
В общем, как оказалось, если формат Excel нормальный, то или через массив или через ADO всё читается.
Если в ячейках длинные строки перемешаны с цифрами, то ADO начинает чудить и приходится перевыбирать.
А если пользователь какие-то свойства отобразил текстом или типом шрифта (что очень часто бывает и хорошо видно), то ADO сразу идёт лесом, а метод с массивом "догоняет" АДО в том же направлении.
И потом при импорте приходится "покурить", если не писать преобразователь на самом VBA в Excel, который не лазит через границы процесса и работает максимально быстро получается:
Excel->Text
Текст через границу процесса в 1С
в 1С текст->Данные.
Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа. Фредерик Брукс-младший