Avatar billede clement Nybegynder
13. september 2006 - 14:15 Der er 7 kommentarer og
1 løsning

Eksekvering af C# program fra VBA

Hej eksperter!

Jeg har et excel regneark, hvori jeg udfører nogle udregninger, der tager data fra et sæt filer, der bliver genereret af et C# program jeg har skrevet. Mit ønske er at eksekvere dette C# program i starten af min VBA kode.

Jeg har forsøgt at køre programmet som en exe-fil vha Shell kommandoen, men dette giver problemer, da C# programmet ikke når at køre færdigt, inden VBA koden skal bruge filerne. Dette kan afhjælpes, men efter hvad jeg har læst mig til, er det ikke sådan lige til at lave - i hvert fald ikke hvis det skal være bare nogenlunde elegant :o)

Jeg har endvidere læst lidt om COM interop, som jeg forestiller mig er løsningen på mit problem, men da jeg er rimelig grøn i både C# og VBA, så er det ikke noget jeg har kunne få til at virke.

Håber I kan hjælpe mig,
Clement
Avatar billede learningvba Nybegynder
13. september 2006 - 14:39 #1
Brug eventuel en "flag-fil" (semaphore file) som "budbringer" mellem de 2 "programmer".
Sålænge flag-filen ikke findes så er C# ikke færdig med at køre.

VBA-"programmet" kan så køre i en løkke hvor det hele tiden checker om flag-filen findes, og sålænge den ikke findes, så bliver VBA-"programmet" inde i sin løkke.
C# opretter flag-filen når det er færdigt, VBA "ser" flag-filen og forsætter sin behandling.


Alternativt så kan du lade C# programmet holde filerne åbne og dermed nægte VBA-"programmet" adgang til filerne, dvs. så længe VBA opfatter filerne som låste, sålænge bliver det i en løkke.
Avatar billede clement Nybegynder
13. september 2006 - 15:04 #2
Første forslag lyder som en ganske god idé, dog ville jeg helst undgå at skulle lave specielle forbehold i de to programmer, da de også gerne skulle kunne fungere seperat.

Det andet forslag vil ikke fungere da VBA koden blot tjekker hvilke filer, der ligger i det pågældende bibliotek og derefter læser disse ind.

Jeg giver den lige lidt tid inden jeg lægger mig fast på 'flag-filen' :o)
Avatar billede clement Nybegynder
13. september 2006 - 15:10 #3
Evt hvis der er nogen der kan forklare, hvis det ellers er muligt, hvorledes man kan kalde C# programmet direkte vha en eller anden smart .Net funktion..
Avatar billede clement Nybegynder
18. september 2006 - 23:47 #4
Lukker tråden; endte med at bruge et 'hack', der muliggør en "wait"-parameter i VBA funktionen "Shell", som det også kendes fra VB funktionen.
Avatar billede learningvba Nybegynder
19. september 2006 - 07:26 #5
Bare af nysgerrighed, hvilket 'hack' ? :-)

En anden mulighed havde også været at lade C# skrive til en fil med et midlertidigt navn, og så først når alt var skrevet, rename outputfilen til et navn som kan genkendes fra VBA. (VBA kører så i et loop med DoEvents og check på om filen findes)

Anyway, godt det lykkedes :-)
Avatar billede clement Nybegynder
20. september 2006 - 09:29 #6
Brugte dette:

Sub WaitUntilAppClose(fullexepath)
    Dim lngRtn As Long
    Dim lngProID As Long
    Dim lngProHn As Long
   
    lngProID = Shell(fullexepath, vbHide)
    lngProHn = OpenProcess(SYNCHRONIZE, True, lngProID)
    lngRtn = WaitForSingleObject(lngProHn, INFINITE)
    lngRtn = CloseHandle(lngProHn)
End Sub

hvilket var hvad jeg beskrev som noget snask i mit oprindelige spgm.. grunden til at jeg gruer lidt for at bruge dette, er at når man arbejder med to sprog der begge ligger under .NET (eller gør VBA egentlig det?), så burde man kunne kalde dem på tværs uden at være nødsaget til at kompilere det ene til en .exe fil.

Hvis du smider et svar så kan vi dele pointene. Det var jo trods alt en mulig løsning du foreslog..
Avatar billede learningvba Nybegynder
20. september 2006 - 12:41 #7
Takker!

Enig med dig at det er lidt "snasket" :-)

Jeg mener ikke at VBA har noget somhelst med .net at gøre, da VBA ikke har ændret sig alverden siden Office97.

Pyt med point, du brugte jo din egen løsning :-), men tak aligevel.
Avatar billede clement Nybegynder
20. september 2006 - 13:24 #8
Hovsa.. glemte lige følgende der er påkrævet for at ovenstående virker:

Option Explicit
Public Declare Function OpenProcess Lib "kernel32" ( _
                                    ByVal dwDesiredAccess As Long, _
                                    ByVal bInheritHandle As Long, _
                                    ByVal dwProcessId As Long _
                                    ) As Long
Public Declare Function WaitForSingleObject Lib "kernel32" ( _
                                            ByVal hHandle As Long, _
                                            ByVal dwMilliseconds As Long _
                                            ) As Long
Public Declare Function CloseHandle Lib "kernel32" ( _
                                    ByVal hObject As Long _
                                    ) As Long
Public Const SYNCHRONIZE = &H100000
Public Const INFINITE = &HFFFF


Så alt i alt noget værre snask :o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi har et stort udvalg af Excel kurser. Find lige det kursus der passer dig lige her.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester