PDA

View Full Version : [Excel VBA] accesso alle DLL


Kesslers
16-02-2010, 13:07
Buongiorno a tutti!
Ho scritto alcune dll in fortran e c++ da richiamare in Excel. Purtroppo su alcuni computer tutto funziona bene, mentre spostando il foglio di lavoro e le dll su altri pc, mi ritrovo come errore che non è possibile trovare le dll specificate, sebbene ci siano chiaramente. Da cosa può dipendere? E' un problema di riferimenti di excel? O è un qualche settaggio di windows?
Grazie mille!
Buona giornata...

MarcoGG
16-02-2010, 13:37
Le DLL esterne ovviamente vanno referenziate dal VBE di Excel sulla macchina di sviluppo.
Sulle macchine che danno errore evidentemente c'è bisogno di registrarle a livello di sistema operativo. Il che può essere fatto con il command REGSVR32 :
http://ss64.com/nt/regsvr32.html

Kesslers
17-02-2010, 11:51
Dunque... ho utilizzato il comando regsvr32, ma mi dice DllRegisterServer non trovato, sia sul pc in cui le dll funzionano sia sul pc su cui invece non funzionano. Ho sbagliato qualcosa nel codice fortran delle dll, a livello di intestazione probabilmente?
Grazie di nuovo.

MarcoGG
17-02-2010, 12:04
Dunque... ho utilizzato il comando regsvr32, ma mi dice DllRegisterServer non trovato, sia sul pc in cui le dll funzionano sia sul pc su cui invece non funzionano. Ho sbagliato qualcosa nel codice fortran delle dll, a livello di intestazione probabilmente?
Grazie di nuovo.

Non ho mai utilizzato Fortran, tantomeno per farci delle DLL, perciò su questo non saprei proprio. Ma se su alcuni PC funzionano evidentemente bisogna anche cercare altrove la causa.
Magari fai una piccola casistica dei S.O. usati sui PC dove funziona e su quelli dove non vede le DLL.

Vincenzo1968
17-02-2010, 14:29
Il comando REGSVR32 serve a registrare le dll che implementano un server COM.
Nel caso di dll normali(che non contengono le funzioni per la registrazione-deregistrazione, DllRegisterServer e DllUnregisterServer), dovrebbe essere sufficiente copiarle nella cartella di sistema di Windows(generalmente "c:\windows\system32") o nella stessa cartella dell'eseguibile.

MarcoGG
17-02-2010, 19:38
Esempio che posso portare con una banale DLL di prova creata in VB6 :

> Modulo di classe "ClsSommatore" della DLL :
Option Explicit

Private m_num1 As Integer
Private m_num2 As Integer

Public Property Get num1() As Integer

num1 = m_num1

End Property

Public Property Let num1(ByVal numero1 As Integer)

m_num1 = numero1

End Property

Public Property Get num2() As Integer

num2 = m_num2

End Property

Public Property Let num2(ByVal numero2 As Integer)

m_num2 = numero2

End Property

Public Function somma() As Integer

somma = num1 + num2

End Function

> Compilo in "Sommatore.dll".

> Registro la DLL in locale ( niente copia della stessa in /system32, quindi ) direttamente da Excel VBA :
Dim percorso As String
percorso = ThisWorkbook.Path & "\"
Dim nomeFileDll As String
nomeFileDll = "Sommatore.dll"

Shell "regsvr32 " & """" & percorso & nomeFileDll & """"

> Referenzio la DLL nel VBE, e la utilizzo nel codice VBA :
Dim S As New Sommatore.ClsSommatore
S.num1 = 5
S.num2 = 10
MsgBox S.somma

Quindi con VB6 / VC++ e altro è semplicissimo.
Per quanto riguarda Fortran aspetterei di sentire pareri su chi conosce davvero il linguaggio...

Vincenzo1968
18-02-2010, 14:13
VB6 crea delle DLL ActiveX che sono appunto dei server COM.
Quando crei un progetto DLL ActiveX, in VB6, vengono aggiunte implicitamente quattro funzioni:

DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer

Puoi verificare utilizzando l'utility dumpbin fornita con visual studio. Digitando il seguente comando


dumpbin /exports Sommatore.dll


viene mostrata la lista delle funzioni esportate dalla DLL:

http://www.guidealgoritmi.it/images/ImgForums/sommatore.jpg

Ecco perché è possibile, nel tuo esempio, utilizzare REGSVR32: la tua DLL è un componente ActiveX e contiene la funzione DllRegisterServer che viene richiamata da REGSVR32 per la registrazione.

Con una DLL normale(non ActiveX) questo non si può fare. Bisogna copiare la DLL nella cartella di sistema di Windows o nella stessa cartella dell'eseguibile.

Kesslers
18-02-2010, 17:45
Sono abbastanza disorientato... Le dll che ho scritto non coinvolgono alcun controllo ActiveX, faccio semplicemente dei calcoli. Ho provato a spostare le dll sia nella cartella dove risiede il file excel che deve richiamare le dll medesime, sia nella cartella system32.. I risulati sono sempre i soliti: le dll non vengono trovate. Non riesco a capire proprio perchè su alcuni pc riesco ad avere accesso alle dll indipendentemente dalla cartella in cui si trovano e invece con questo continua a dare problemi...

Vincenzo1968
18-02-2010, 18:42
È strano che non trovi la dll se questa si trova nella cartella di sistema di Windows. A meno che tu non abbia specificato il path completo nel codice del foglio excel nel quale vengono referenziate le dll.

Puoi postare questa parte di codice?

Kesslers
18-02-2010, 19:34
Al momento non posso postare alcun codice perché ce l'ho nel pc dell'ufficio..
In effetti nella definizione delle dll ho riportato il path completo dove excel dovrebbe cercarle. Provo allora a metterle nella cartella system32 e referenziarle con il solo nome.
Vi terrò aggiornati.
Grazie!!

MarcoGG
19-02-2010, 10:16
VB6 crea delle DLL ActiveX che sono appunto dei server COM.


Lo so anch'io. Infatti volevo dimostrare che con Dll ActiveX da VB6 o VC++, il problema non si pone con regsvr32.
Non so invece se con Fortran si possa ottenere o meno una DLL che funzioni con regsvr32, perchè è proprio un linguaggio che non ho mai usato.
Quindi se non si fa vivo qualcuno di esperto in Fortran, su questo non ho altro da dire.

Sono abbastanza disorientato... Le dll che ho scritto non coinvolgono alcun controllo ActiveX, faccio semplicemente dei calcoli.

Nemmeno la mia è un "controllo" ActiveX. Forse qui fai confusione tra controlli ActiveX e librerie ActiveX. Io parlavo di DLL ActiveX, che non è altro che una raccolta di moduli di classe, senza alcuna parte "grafica".
Poi le tue, ovviamente, non sono "ActiveX" in quanto scritte in Fortran.

È strano che non trovi la dll se questa si trova nella cartella di sistema di Windows. A meno che tu non abbia specificato il path completo nel codice del foglio excel nel quale vengono referenziate le dll.



In effetti nella definizione delle dll ho riportato il path completo dove excel dovrebbe cercarle. Provo allora a metterle nella cartella system32 e referenziarle con il solo nome.


Secondo me qui ci sono idee poco chiare su come si Referenzia una DLL in un progetto VBA.
Ciò che intendevo è questo :
-> Editor VBA
-> Menu Strumenti / Riferimenti
-> Se il nome della nostra DLL non è in lista, va aggiunto con "Sfoglia..."
A questo punto basta andare a cercare manualmente il file .dll da referenziare, e NON è affatto necessario che sia in system32.

Perciò non capisco questo problema sul "path completo o incompleto dove excel dovrebbe cercarle". Sarei curioso di vedere il codice che usi per fare questo.
Esistono alcuni tips sul web dove c'è chi mostra tecniche per referenziare direttamente nel codice VBA. Personalmente lo trovo inutile, e potenzialmente dannoso, anche perchè se la DLL non è già in lista nelle ThisWorkbook.VBProject.References, pare non funzioni affatto...
Il modo migliore per referenziare è quello manuale che ho mostrato e, ripeto, va fatto una volta sola sulla macchina di sviluppo. Non ha alcun senso ripeterlo per ogni distribuzione, e men che meno farlo eseguire ad ogni avvio da VBA.

Kesslers
19-02-2010, 13:04
Ho utilizzato Denpendency Walker per risalire alle dll che in qualche modo servono alla mia per essere eseguita. E' risultato che ne mancava una, che ritengo venga installata da visual fortran nella cartella system32.
Lanciando ora la dll scritta da me, il nuovo messaggio che ottengo è il seguente:

Errore di run-time '453':
Impossibile trovare il punto di ingresso SolverAx della DLL in SolverAx.dll

Questo messaggio mi arriva indipendentemente dalla cartella in cui metto SolverAX.dll, indicandone eventualmente il corretto path nella dichiarazione.

Ho provato per altro a referenziare la dll manualmente, come suggeriva MarcoGG, tramite Strumenti/Riferimenti, ma stavolta il messaggio che riecevo è: Impossibile aggiungere un riferimento al file specificato.

Mah... buona giornata a tutti!

MarcoGG
19-02-2010, 13:31
Ho provato per altro a referenziare la dll manualmente, come suggeriva MarcoGG, tramite Strumenti/Riferimenti, ma stavolta il messaggio che riecevo è: Impossibile aggiungere un riferimento al file specificato.


Anzitutto prova a dare un'occhiata qui :
http://support.microsoft.com/kb/123841/en-us

Se sei tu l'autore di queste DLL scritte in Fortran, e se è praticabile la cosa ( ad es. se non si tratta di una gran mole di codice ), considera anche l'ipotesi di :

1. Riscrivere le stesse in VB6 ( certo, se hai un VS6 a portata di mano ).

2. Meglio ancora, lasciar perdere le DLL e tradurre/riportare le Funzioni ( dal momento che dici che sono pure raccolte di procedure ) direttamente in moduli VBA. A quel punto, già che lo devi usare, approfondisci la conoscenza di VBA e inoltre risolvi il problema alla radice.

Vincenzo1968
19-02-2010, 16:59
Ho utilizzato Denpendency Walker per risalire alle dll che in qualche modo servono alla mia per essere eseguita. E' risultato che ne mancava una, che ritengo venga installata da visual fortran nella cartella system32.
Lanciando ora la dll scritta da me, il nuovo messaggio che ottengo è il seguente:

Errore di run-time '453':
Impossibile trovare il punto di ingresso SolverAx della DLL in SolverAx.dll

Questo messaggio mi arriva indipendentemente dalla cartella in cui metto SolverAX.dll, indicandone eventualmente il corretto path nella dichiarazione.

Ho provato per altro a referenziare la dll manualmente, come suggeriva MarcoGG, tramite Strumenti/Riferimenti, ma stavolta il messaggio che riecevo è: Impossibile aggiungere un riferimento al file specificato.

Mah... buona giornata a tutti!

L'entry point in una dll è case sensitive.
Se nella tua DLL in fortran la funzione è dichiarata. per esempio, tutta in minuscolo, solverax, la seguente dichiarazione darà l'errore 453:

Declare Function SolverAx Lib "SolverAx.dll" () As Long

Così, invece, dovrebbe funzionare:

Declare Function solverax Lib "SolverAx.dll" () As Long

Kesslers
22-02-2010, 14:54
Che stupido...lo sapevo, ma non ci avevo fatto caso. E' bastato scrivere correttamente il nome della function contenuta nella dll perché funzionasse alla perfezione.
Un'ultima osservazione.
Ho notato che il foglio excel (e quindi la dll che viene richiamata) funziona correttamente indipendentemente dalla posizione della dll all'interno delle cartelle: se specifico solo il nome della dll, questa viene cercata in system32, altrimenti devo specificare il path completo.
Tuttavia è indispensabile che in system32 ci sia "Dforrt.dll" altrimenti ricevo di nuovo un messaggio di errore. Questa dll viene installata con visual fortran, quindi se voglio utilizzare il foglio excel su un pc dove VF non è installato, mi devo portare dietro la Dforrt.
Non c'è modo di svincolarsi completamente da quest'ultima dll, da non doverla sempre copiare sui vari pc, ma magari inglobarla o riferirla già in quella che ho scritto io?
Peccato che sul mio pc, anche se ad esempio rinomino tutte le Dforrt.dll presenti in modo che siano inaccessibili, il programma gira ugualmente e correttamente.
Grazie ancora...
Buona giornata!