интерфейс VB с Excel

Для неординарных вопросов. Если вы опытный программист, попавший в трудную ситуацию, — вам сюда.

Модератор: gaidar

Правила форума
Этот раздел не предназначен для того, чтобы вы адресовали свою проблему профессионалам.
Этот раздел предназначен для профессионалов, которые столкнулись с проблемой и не могут решить ее самостоятельно.
Если вы считаете себя профессионалом, а свою проблему сложной — вам сюда.
Если модератор посчитает, что вы ошиблись, то на первый раз он перенесет ваше сообщение в основной раздел без последствий для автора. Во второй раз тема будет закрыта, а автору будет выписано нарушение. В третий раз автор будет забанен.
Yuryl
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 20.10.2005 (Чт) 16:37

интерфейс VB с Excel

Сообщение Yuryl » 23.09.2007 (Вс) 12:10

Делаю на VB надстройку для Эксель...

в Workbook_Open() вызываю процедуру VB формирования интерфейса в которой строки типа

vbc.CodeModule.InsertLines 2, "sub " & myProc
vbc.CodeModule.InsertLines 3, s1
vbc.CodeModule.InsertLines 4, "end sub"

т.е. динамически формируются процедуры в экселе, могу их даже сразу запустить из VB, типа xlapp.Run "myProc". Все работает.
Но после этого вызова из Workbook_Open() связь VB с экселем теряется,
переменная в которой хранился Excel.Application равна Nothing и приходится повторно передавать Excel.Application в VB.

Что не так? Или эксель(2000) глючит?

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 24.09.2007 (Пн) 10:35

Выложи весь код создания, формирования и запускания.
Лучший способ понять что-то самому — объяснить это другому.

Yuryl
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 20.10.2005 (Чт) 16:37

Сообщение Yuryl » 24.09.2007 (Пн) 19:31

в экселе

Private Sub Workbook_Open()
test ThisWorkbook
End Sub

в VB ActiveX Dll class GlobalMultyUse

Private xl As Excel.Application

Sub test(wb As Excel.Workbook)
Dim vbc As VBComponent

Set xl = wb.Application

On Error Resume Next
wb.VBProject.VBComponents.Remove wb.VBProject.VBComponents("intrfc")

Set vbc = wb.VBProject.VBComponents.Add(vbext_ct_StdModule)
vbc.Name = "intrfc"

vbc.CodeModule.InsertLines 2, "sub test2"
vbc.CodeModule.InsertLines 3, "check"
vbc.CodeModule.InsertLines 4, "end sub"

xl.Run "test2"

End Sub

Sub check()

If xl Is Nothing Then
MsgBox "Nothing"
Else
MsgBox xl.Caption
End If

End Sub

xl.Run отрабатывает нормально, но если из экселя запустить check - увидим, что xl=Nothing

т.е. вставка строк как-то инициализирует Dll, что обнуляются переменные

можно, конечно, передать потом объект Excel в Dll, но хотелось бы, чтобы пользователь не делал дополнительной команды инициализации Dll

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 25.09.2007 (Вт) 14:02

Очевидно для процедуры test2 создается новый экземпляр глобального класса. Чтобы старый не терялся, создай в экселе в модуле публичную пременную, а в Workbook_Open() присваивай ей значение, хотя бы New MyGlobalMultyUse, и вызывай MyVar.test ThisWorkbook. Соответственно vbc.CodeModule.InsertLines 3, "MyVar.check".

Еще лучше создать публичную переменную в модуле Workbook ("эта книга"), все равно в ней уже будет Workbook_Open, и обращаться к ней из экселя через ThisWorkbook.MyVar.
Лучший способ понять что-то самому — объяснить это другому.

Yuryl
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 20.10.2005 (Чт) 16:37

Сообщение Yuryl » 25.09.2007 (Вт) 19:35

похоже ты не правильно понял, теряется переменная xl в VB, в которой хранился объект excel.application(а также и все другие переменные Dll, вроде). Вызов из экселя функций VB работает.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 25.09.2007 (Вт) 20:19

Я-то как раз понял правильно, объяснил только видимо не очень...

Переменная xl не теряется, ее никогда не было.
test ThisWorkbook вызывается для одного экземпляра твоей dll, в него передается ThisWorkbook, а процедура test2 запускает check, который выполняется в другом экземпляре, в который ThisWorkbook ты никогда не передавал! Это такая особенность свойства Global MultiUse, что система сама выбирает, создавать экземпляр, не создавать, какому объекту какой экземпляр подсунуть... Поэтому либо избавляйся от Global, либо делай описанные выше телодвижения чтобы быть уверенным, что ты работа происходит в одном-единственном экземпляре твоего класса.

ADD: Можно без всяких телодвижений объявить переменную xl не в классе, а в модуле как public, тогда она будет одна для всех экземпляров класса. Но тогда будут проблемы при работе нескольких экземпляров самого экселя - в переменной будет ссылка на последний экземпляр (если конечно он вызовет test).
Лучший способ понять что-то самому — объяснить это другому.

Yuryl
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 20.10.2005 (Чт) 16:37

Сообщение Yuryl » 26.09.2007 (Ср) 19:45

не работает ни так ни так,

в Экселе:

Private Sub Workbook_Open()
Set t = New tst
t.test0 ThisWorkbook
End Sub

в Модуле:
Public t As tst
(пробовал и в ЭтаКнига)

в VB:
(в классе tst)
Public Sub test0(wb As Excel.Workbook)
Dim vbc As VBComponent

Set xl = wb.Application

On Error Resume Next
wb.VBProject.VBComponents.Remove wb.VBProject.VBComponents("intrfc")
Set vbc = wb.VBProject.VBComponents.Add(vbext_ct_StdModule)
vbc.Name = "intrfc"

vbc.CodeModule.InsertLines 2, "sub test2"
vbc.CodeModule.InsertLines 3, "t.check"
vbc.CodeModule.InsertLines 4, "end sub"
xl.Run "test2" //работает
End Sub

Public Sub check()
If xl Is Nothing Then
MsgBox "Nothing"
Else
MsgBox xl.Caption
End If
End Sub

в Модуле:

Public xl As Excel.Application

--

в Экселе обнуляется t после вставки строк, после вставки модуля не обнуляется.

в VB теряется xl.
Если в Экселе создать новый экземпляр tst
t=new tst,
то t.check дает Nothing,
т.е. глобальная переменная(из Модуля) обнуляется.

Если запустить Dll через дебагер, все работает как надо!


Вернуться в Раздел для Профессионалов

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

    TopList