13. september 2006 - 14:15Der 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.
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.
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)
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..
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)
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..
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)
Synes godt om
Ny brugerNybegynder
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.