Имя: Пароль:
1C
 
Поиск из 1С в Excel строго соответствующего значения ячейки методами Excel
0 uwscsi
 
03.08.06
17:43
Такая получилась загвоздка:
Надо из 1С в таблице Excel найти ячейку со значением.
Взаимодействую с Excel через OLE.

Что получилось- есть у Excel метод Find- очень шустро но из
1с- так и не получилось заставить его искать полную строчку
-------------------------------------------------
     ЭлТ="Smtn..."
   Попытка
       Tst=Xls.Selection.Find(ЭлТ).activate();
       Result=-1;
   Исключение
       Result=0;
   КонецПопытки;
--------------------------------------------------
Такая конструкция ищет в экселе все ячейки, куда входит искомая подстрока...

Если смотреть на синтаксис VB в Excel, то там работает строчка:

Cells.Find(What:="Smth...", LookAt:=xlWhole).Activate

Но при попытке это впихнуть в 1с в любом виде начинается ругань...

Кто-нить знает, как заставить работать метод из 1С с поиском по полному соответствию?


Пробовал ещё один вариант- из 1С создать макрос непосредственно в Excel и запускать уже не метод, а макрос, но
по первой же попытке обратиться к VB Excel из 1С

vbc=Xls.vbe.ActiveVBProject.VBComponents;

был получен отлуп:
"Microsoft Office Excel: Программный доступ к проекту Visual Basic не является доверенным"

Винды- XP Sp2
Excel- 2003

В общем спасибо заранее за любые идеи по этому поводу.
1 ТелепатБот
 
гуру
03.08.06
17:43
2 Рупор2
 
03.08.06
18:27
3 asady
 
03.08.06
18:56
(0) можно включить доступ: понизить уровень безопасности: Сервис-Параметры-Безопасность.
Это позволит записать и выполнить макрос.

Но ИМХО можно сделать это скриптом.
4 asady
 
03.08.06
20:30
(3)+ например вот так...

Процедура НайтиСтроку(Application,СтрокаПоиска)  
   Selection=Application.Selection;
     Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
     Скрипт.Language="vbscript";
     Скрипт.AddObject("Selection",Selection);
     Скрипт.AddObject("ActiveCell",Application.ActiveCell);
   res=Скрипт.Eval("Selection.Find("+СтрокаПоиска+",ActiveCell,-4163,1).activate()");
   Сообщить("результат "+res);
КонецПроцедуры

это будет поиск целой строки в помеченной области активной книги.
5 smaharbA
 
03.08.06
22:12
За селект по рукамбы долбал...
(4) Ненада мсскрипт контрола...
6 asady
 
04.08.06
09:59
(5) Тогда покажи как надо.
7 uwscsi
 
04.08.06
10:32
(2)- Спасибо, про этот вариант в курсе, просто хотелось одной командой получить результат, наверно придётся действовать таким образом.

(3,4)- Попробовал, работает однако, но не до конца, или я что-то не понимаю...
В переменную "res" возвращается -1, что указывает на успешное завершение
функции, но при попытке получить адрес найденной ячейки- ничего не получается-
адрес её всегда равено "$1$A1"...
Получаю таким образом:

Adr=Scprt.Eval("ActiveCell.Address");

Или там какой-то другой хитрый метод получения значений полей объектов должен быть?

(5)- а что такое в MSScript control плохого? Почему его не стоит пользовать?
8 asady
 
04.08.06
12:29
(7) скрипт (4) работает так как ты просил (0) если теперь хочешь получить адрес, то достаточно
Строки
Сообщить("Адрес="+Application.ActiveCell.Address);
9 asady
 
04.08.06
12:33
(7) в (5) имелось ввиду наверное то, что поиск в отмеченной области не есть хорошо. И с этим я могу согласиться. ИМХО такой поиск надо делать независимо от Selection. Но методика остается примерно такой-же.
10 uwscsi
 
04.08.06
12:49
(8) В том-то и дело, что не работает:(

Может я что не понимаю но код:

-----------------------------------
Xls=СоздатьОбъект("Excel.Application");
       Xls.Visible=1;
       Xls.Workbooks.Open(КаталогИБ()+"Tst.xls");
Xls.Columns("A:B").Select(); //Возвращаем на место выделение для поиска
Selection=Xls.Selection;
ActiveCell=Xls.ActiveCell;
What="a";
Scprt=СоздатьОбъект("MSScriptControl.ScriptControl");
Scprt.Language="vbscript";
Scprt.AddObject("Selection",Selection);
Scprt.AddObject("ActiveCell",ActiveCell);
Res=Scprt.Eval("Selection.Find("+What+",ActiveCell,-4163,1).Activate()"); (a)

adr=xls.ActiveCell.Address; (b)
adr=Scprt.Eval("ActiveCell.Address");    (c)
----------------------------------------------

Строчка (a) возвращает -1, что казывает, что элемент найден,
Строчка (b) возвращент $A$1
Строчка (с) возвращает $A$1

При этом элемент "а" находится в ячейке по адресу $B$2

В общем я наверо что-то не понимаю...
11 asady
 
04.08.06
12:59
Xls=СоздатьОбъект("Excel.Application");
       Xls.Visible=1;
       Xls.Workbooks.Open(КаталогИБ()+"Tst.xls");
Xls.Columns("A:B").Select(); //Возвращаем на место выделение для поиска

Selection=Xls.Selection;
ActiveCell=Xls.ActiveCell;
What="a";
Scprt=СоздатьОбъект("MSScriptControl.ScriptControl");
Scprt.Language="vbscript";
Scprt.AddObject("Selection",Selection);
Scprt.AddObject("ActiveCell",ActiveCell);
Res=Scprt.Eval("Selection.Find("+What+",ActiveCell,-4163,1)"); (a)
adr=Res.Address;
12 uwscsi
 
04.08.06
13:15
(11) И в этом варианте в adr возвращается $A$1
:(
Мистика какая-то.
Что интересно- в Excel- указатель не перемещается на найденную ячейку...
13 asady
 
04.08.06
13:27
Процедура НайтиСтроку(Application,СтрокаПоиска)  
   Selection=Application.Selection;
     Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
     Скрипт.Language="vbscript";
     Скрипт.AddObject("Selection",Selection);
     Скрипт.AddObject("ActiveCell",Application.ActiveCell);
   //res=Скрипт.Eval("Selection.Find("+СтрокаПоиска+",ActiveCell,-4163,1).activate()");
   res=Скрипт.Eval("Selection.Find("+СтрокаПоиска+",ActiveCell,-4163,1)");
   Сообщить("результат "+res.Address);
КонецПроцедуры
                                                   
Процедура Сформировать()  
   Путь="C:\test.xls";
   Str="567";
   Попытка
       Application=СоздатьОбъект("Excel.Application");
   Исключение
       Сообщить(ОписаниеОшибки(),"!!!");
       Сообщить("Возможно, MS Excel не установлен на этом компьютере.");
       Возврат;
   КонецПопытки;
   НайтиСтроку(Application,Str);
КонецПроцедуры

у меня это код работает правильно!
14 uwscsi
 
04.08.06
13:34
Чёрт, а у меня не пашет.
Проверил вплоть до последней буквы...
Нагло так с издёвкой в Res.Address помещается значение $A$1

Всё. Делаю по методу (2).
Всем спасибо!
15 asady
 
04.08.06
13:53
(13) Есть особенность:
Цифири так ищет легко. А вот строки не ищет совсем. Похоже строка в Экселе целиком не совпадает со строкой в 1С. Эксель видимо какой-то служебный символ в конец строки пихает. Поэтому поиск по полному соответствию не пашет.
16 uwscsi
 
04.08.06
14:16
(15) Спасибо!
Теперича всё понятно.
Ох уж эти мелкомягкие...
17 Рупор2
 
04.08.06
16:04
(5)+1

(0) Перевод кода из (2):


Функция ПоискВЭксель(Область,Объект,Точность=1,Колонка=0) Экспорт
 //поиск в ole-excel
 //
 //возвращает число - номер строки в excel, содержащей найденную ячейку
 //или 0, если ничего не найдено
 //
 //Область - (ole-объект), область (range) в excel, по которой производится поиск
 //Объект - (число, строка, или дата), что ищем
 //Точность - 0-первое вхождение, 1-равенство Объект и значения ячейки
 //Колонка - отсюда можно считать номер колонки, с найденной ячейкой
 //
 Попытка Ячейка=Область.Find(Объект) Исключение Возврат 0 КонецПопытки;
 Если СокрЛП(Объект)=СокрЛП(Ячейка.Value) Тогда Возврат Ячейка.Row КонецЕсли;
 Если ПустоеЗначение(Ячейка)=0 Тогда
   Если Точность=0 Тогда
     Графа=Ячейка.Графа;
     Возврат Ячейка.Row;
   КонецЕсли;
   НачАдрес=Ячейка.Address;
   Пока ПустоеЗначение(Ячейка)=0 Цикл
     Ячейка=Область.FindNext(Ячейка);
     Если Ячейка.Address=НачАдрес Тогда Возврат(0); Прервать; КонецЕсли;
     Если Объект=Ячейка.Значение Тогда
       Колонка=Ячейка.Column;
       Возврат Ячейка.Row;
       Прервать;
     КонецЕсли;
   КонецЦикла;
 КонецЕсли;
 Возврат 0;
КонецФункции
18 asady
 
04.08.06
16:40
(17) через FindNext перебором по частичным вхождениям и дурак найдет.
Вопрос в сабже был поставлен конкретно: найти строку по полному соответсвию одной командой Find как это реализовано в Экселе.

вот переделал без Селекта, но и так не рулит...

Процедура НайтиСтроку(Application,СтрокаПоиска)  
   Selection=Application.Selection;
     Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
     Скрипт.Language="vbscript";
     Скрипт.AddObject("Cells",Application.Cells);
     Скрипт.AddObject("ActiveCell",Application.ActiveCell);
   res=Скрипт.Eval("Cells.Find("+СтрокаПоиска+",ActiveCell,-4123,1)");
   Сообщить("результат "+res.Address);
КонецПроцедуры

но грабли в том, что поиск по полному (подчеркнуто именно полному) соответсвию никак не рулит из 1Сины.
19 Рупор2
 
04.08.06
17:55
(18) Чем плох тот код, который доступен даже дураку и при этом работает ни чуть не медленнее кода, доступного только гениям?
20 asady
 
04.08.06
18:01
(19) да ничем не плох. Вопрос стоял по другому. Решение (17) не отвечает на вопрос сабжа.
21 Рупор2
 
04.08.06
18:40
(20) Вот и показал бы челу, как найти нужную строчку в эксель однострочной командой, вместо того чтоб два дня парить мозги себе и окружающим ...
22 smaharbA
 
04.08.06
19:11
Надо точное соответствие ? Или вхождение ?
23 mx-daemon
 
04.08.06
19:29
Была у меня хорошая книжка MS - пресс и называлась программирование VBA.
Девушке подарил её.
К чему, да вот там было ну просто разжевано как извне искать и т.п.
И еще: метод Find возвращает объект типа Range (диапазон) и вовсе не факт, что это именно одна ячейка.
24 smaharbA
 
04.08.06
19:30
Если точное, то...
...Попытка
   Найдено = Книга.Cells.Find("цу",,,1);
   Истина=-1;
Исключение
   Истина=0;
КонецПопытки;
Если Истина=-1 Тогда
       Сообщить(Найдено.Address);
Иначе
       Сообщить("Шняга какаято длин...");
КонецЕсли;
...
Если все...
...
//*******************************************
Процедура Сформировать()
   Екскел=СоздатьОбъект("Excel.Application");
   Книга=Екскел.WorkBooks.Open("C:\Ищем.xls");
   Книга.Worksheets(1).Unprotect ("1qaz");
   Для к=1 По Книга.Worksheets.Count Цикл
       Диапазон = Книга.Worksheets(к).UsedRange;
       Попытка
           Найдено = Диапазон.Find("цу");
           Истина=-1;
       Исключение
           Истина=0;
       КонецПопытки;
       Если Истина=-1 Тогда
       АдресПреж = Найдено.Address;
       Пока Истина=-1 Цикл
           Сообщить(""+Книга.Worksheets(к).Name+"; "+Найдено.Address);
           Попытка
               Найдено = Диапазон.FindNext(Найдено);
               Истина=-1;
           Исключение
               Истина=0;
           КонецПопытки;
           Истина=?((Истина=-1) И (Найдено.Address <> АдресПреж),-1,0);
       КонецЦикла;
       КонецЕсли;
   КонецЦикла;
   Сообщить(Книга.Worksheets(1).Cells(1, 1).Text);
КонецПроцедуры
25 mx-daemon
 
04.08.06
19:36
(15) Нормально ищет строки.
Впрочем, легко проверить - сначала записать в ячейку, а потом искать методом Find
26 uwscsi
 
07.08.06
10:03
---------------------------------------
Найдено = Книга.Cells.Find("цу",,,1);
---------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Вот только если бы работала такая конструкция.

У меня она выдаёт ошибку, как только пытаешься внести ещё хоть
какие нить параметры на вход метода Find после искомой строки.
27 Рупор2
 
07.08.06
10:07
НомерСтроки=Эксель.WorksheetFunction.Match("цу",Эксель.Columns(НомерКолонкиВКоторойСледуетИскать),0);