Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
956to960
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
956to960
956to960
Aktuelles Verzeichnis
Verzeichnis Index
Verzeichnis Index
Übersicht Verzeichnisse
Inhaltsverzeichnis

Dynamic Link Library

Dynamic Link Library
29.02.2008 11:35:00
Helmut
Liebe Forumsmitglieder!
ich möchte eine DLL in Excel 03 einbinden. Wie gehe ich vor, dass ich aus der DLL eine Funktion machen kann? Unter Excel 97 konnte man die DLL direkt aus einer Zelle mit =CALL(...) aufrufen. Ab Excel 00 gibt es diese Möglichkeit nicht mehr. Weiß wer ob es für "CALL" einen Nachfolger gibt bzw. kann jemand ein Makro zum Aufruf einer DLL ins Forum stellen?

18
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Dynamic Link Library
29.02.2008 12:18:01
Nepumuk
Hallo Helmut,
ein Paar große Stiefel für VBA-bescheiden. Mal ein Beispielcode mit dem du einen Screenshot als .bmp speichern kannst.
' **********************************************************************
' Modul: Modul1 Typ: Allgemeines Modul
' **********************************************************************

Option Explicit

Private Declare Sub Sleep Lib "kernel32.dll" ( _
    ByVal dwMilliseconds As Long)
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" ( _
    ByRef PicDesc As PicBmp, _
    ByRef RefIID As GUID, _
    ByVal fPictureOwnsHandle As Long, _
    ByRef IPic As IPicture) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
    ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" ( _
    ByVal hdc As Long, _
    ByVal nWidth As Long, _
    ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" ( _
    ByVal hdc As Long, _
    ByVal hObject As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" ( _
    ByVal hdc As Long, _
    ByVal iCapabilitiy As Long) As Long
Private Declare Function GetSystemPaletteEntries Lib "gdi32.dll" ( _
    ByVal hdc As Long, _
    ByVal wStartIndex As Long, _
    ByVal wNumEntries As Long, _
    ByRef lpPaletteEntries As PALETTEENTRY) As Long
Private Declare Function CreatePalette Lib "gdi32.dll" ( _
    ByRef lpLogPalette As LOGPALETTE) As Long
Private Declare Function SelectPalette Lib "gdi32.dll" ( _
    ByVal hdc As Long, _
    ByVal hPalette As Long, _
    ByVal bForceBackground As Long) As Long
Private Declare Function RealizePalette Lib "gdi32.dll" ( _
    ByVal hdc As Long) As Long
Private Declare Function BitBlt Lib "gdi32.dll" ( _
    ByVal hDestDC As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal nWidth As Long, _
    ByVal nHeight As Long, _
    ByVal hSrcDC As Long, _
    ByVal xSrc As Long, _
    ByVal ySrc As Long, _
    ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" ( _
    ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32.dll" ( _
    ByVal hWnd As Long) As Long
Private Declare Function GetWindowRect Lib "user32.dll" ( _
    ByVal hWnd As Long, _
    ByRef lpRect As RECT) As Long
Private Declare Function GetSystemMetrics Lib "user32.dll" ( _
    ByVal nIndex As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32.dll" () As Long

Private Const SM_CXSCREEN = 0&
Private Const SM_CYSCREEN = 1&
Private Const RC_PALETTE As Long = &H100
Private Const SIZEPALETTE As Long = 104
Private Const RASTERCAPS As Long = 38
Private Const vbSrcCopy = &HCC0020

Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type

Private Type PALETTEENTRY
peRed As Byte
peGreen As Byte
peBlue As Byte
peFlags As Byte
End Type

Private Type LOGPALETTE
palVersion As Integer
palNumEntries As Integer
palPalEntry(255) As PALETTEENTRY
End Type

Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type

Private Type PicBmp
Size As Long
Type As Long
    hBmp As Long
    hPal As Long
    Reserved As Long
End Type

Public Sub prcSave_Picture_Screen() 'ganzer bildschirm
    stdole.SavePicture hDCToPicture(GetDC(0&), 0&, 0&, _
        GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)), _
        "D:\Eigene Dateien\Screenshot.bmp" 'anpassen !!!
End Sub

Public Sub prcSave_Picture_Active_Window() 'aktives Fenster
    Dim hWnd As Long
    Dim udtRect As RECT
    ' Call Sleep 3000 '3 sekunden pause um ein anderes Fenster zu aktivieren
    hWnd = GetForegroundWindow
    GetWindowRect hWnd, udtRect
    stdole.SavePicture hDCToPicture(GetDC(0&), udtRect.Left, udtRect.Top, _
        udtRect.Right - udtRect.Left, udtRect.Bottom - udtRect.Top), _
        "D:\Eigene Dateien\Screenshot.bmp" 'anpassen !!!
End Sub

Private Function CreateBitmapPicture(ByVal hBmp As Long, ByVal hPal As Long) As Object
    Dim Pic As PicBmp, IPic As IPicture, IID_IDispatch As GUID
    With IID_IDispatch
        .Data1 = &H20400
        .Data4(0) = &HC0
        .Data4(7) = &H46
    End With
    With Pic
        .Size = Len(Pic)
        .Type = 1
        .hBmp = hBmp
        .hPal = hPal
    End With
    Call OleCreatePictureIndirect(Pic, IID_IDispatch, 1, IPic)
    Set CreateBitmapPicture = IPic
End Function

Private Function hDCToPicture(ByVal hDCSrc As Long, ByVal LeftSrc As Long, _
        ByVal TopSrc As Long, ByVal WidthSrc As Long, ByVal HeightSrc As Long) As Object

    Dim hDCMemory As Long, hBmp As Long, hBmpPrev As Long
    Dim hPal As Long, hPalPrev As Long, RasterCapsScrn As Long, HasPaletteScrn As Long
    Dim PaletteSizeScrn As Long, LogPal As LOGPALETTE
    hDCMemory = CreateCompatibleDC(hDCSrc)
    hBmp = CreateCompatibleBitmap(hDCSrc, WidthSrc, HeightSrc)
    hBmpPrev = SelectObject(hDCMemory, hBmp)
    RasterCapsScrn = GetDeviceCaps(hDCSrc, RASTERCAPS)
    HasPaletteScrn = RasterCapsScrn And RC_PALETTE
    PaletteSizeScrn = GetDeviceCaps(hDCSrc, SIZEPALETTE)
    If HasPaletteScrn And (PaletteSizeScrn = 256) Then
        LogPal.palVersion = &H300
        LogPal.palNumEntries = 256
        Call GetSystemPaletteEntries(hDCSrc, 0, 256, LogPal.palPalEntry(0))
        hPal = CreatePalette(LogPal)
        hPalPrev = SelectPalette(hDCMemory, hPal, 0)
        Call RealizePalette(hDCMemory)
    End If
    Call BitBlt(hDCMemory, 0, 0, WidthSrc, HeightSrc, hDCSrc, LeftSrc, TopSrc, vbSrcCopy)
    hBmp = SelectObject(hDCMemory, hBmpPrev)
    If HasPaletteScrn And (PaletteSizeScrn = 256) Then
        hPal = SelectPalette(hDCMemory, hPalPrev, 0)
    End If
    Call DeleteDC(hDCMemory)
    Set hDCToPicture = CreateBitmapPicture(hBmp, hPal)
End Function

Gruß
Nepumuk

Anzeige
AW: Dynamic Link Library
29.02.2008 13:48:00
Helmut
Super. Allerdings hätte mich eher interessiert, wie man aus einer externen DLL (!keine Windows DLL), sondern eine DLL wo Koeffizienten (Gewichtungen) für eine Regression gespeichert sind), eine aufrufbare Funktion macht. Hast du eine Idee?
By the way, warum verwendest du eigentlich Private Declare ... ist hier ein Klassenmodul zwingend, reicht nicht auch ein einfaches Modul?

AW: Dynamic Link Library
29.02.2008 13:59:02
Nepumuk
Hallo Helmut,
ich kenn ja deine DLL nicht, aber aus den "normalen" DLL's musst du per Private Declare die entsprechende Funktion / Sub nach Excel erst importieren bevor du sie benutzen kannst. Die ganzen DLL's die in dem Beispiel angesprochen werden sind extern, sprich nicht Bestandteil von Excel sondern liegen irgendwo im Systemverzeichnis. Ich könnte sie aber auch in einen anderen Ordner verschieben, ich muss sie dann nur neu im System anmelden (registrieren, aber das kann man auch aus Excel selbst heraus). Es gibt auch die Möglichkeit einen Pfad anzugeben. Mit einem Klassenmodul hat das ganze nichts zu tun. Eine Klasse ist ein Objekt. Das kann real sein, wie eine Tabelle, oder virtuell wie z.B. ein Rais-Event.
Gruß
Nepumuk

Anzeige
AW: Dynamic Link Library
29.02.2008 15:19:00
Helmut
Vielen Dank! Den Programmcode, der in der DLL kompiliert ist habe ich unten eingefügt. Wäre ganz toll, wenn du mir aufgrund des Codes (ich nehme an besonders die ersten Zeilen des C-Codes sind für die Einbindung in das Makro relevant) sagen könntest, wie genau der Befehlssatz des VBA Makros aussehen muss, damit sich die DLL als Funktion aufrufen lässt. Ganz unten steht mein "Programmierversuch" dazu, der allerdings nicht ganz funktioniert. Vielleicht entdeckst du ja den Fehler.
#include windows.h (jeweils in eckigen Klammern)
#include stdio.h
#include stdlib.h
#include math.h
#include "recall.h"
__declspec(dllexport) double iris (long int whichclass, double in1,
double in2, double in3, double in4) {
float input[4];
float output[3];
double out;
input[0] = in1;
input[1] = in2;
input[2] = in3;
input[3] = in4;
NN_Recall ( (void*)0, input, output);
if (whichclass == 1) return ((double)output[0]);
else if (whichclass == 2) return ((double)output[1]);
else return ((double)output[2]);
out = (double)output[0];
return (out);
}
/* Thu Feb 28 09:16:03 2008 (recall.c) */
/* Header file is */
/* Recall-Only Run-time for */
/* Control Strategy is: */
#if defined(__STDC__) || defined(__cplusplus)
#define ARGS(x) x
#else
#define ARGS(x) ()
#endif /* __STDC__ */
#if defined(__cplusplus)
extern "C" {
#endif
/* --- External Routines --- */
extern double tanh ARGS((double));
/* *** MAKE SURE TO LINK IN YOUR COMPILER's MATH LIBRARIES *** */
#if defined(STATIC_WTS)
typedef struct _pewts {
short sPEFlag; /* Flag for weight type */
unsigned short usPESrc; /* index of source PE */
float fPEWt; /* value of weight for PE */
} PEWTS;
#define CN_VAR 0 /* variable weight */
#define CN_SET 2 /* set weight */
#define CN_MOD 3 /* mod weight */
#define ASof(x) (sizeof(x)/sizeof(x[0]))
#define SWC(x) x
#else
#define SWC(x)
#endif /* #if defined(STATIC_WTS) */
/* --- NOTE: Network has (Yin[4]) inputs and (Yout[3]) outputs --- */
#if defined(__STDC__) || defined(__cplusplus)
int NN_Recall( const void *NetPtr, const double *Yin, double *Yout )
#else
int NN_Recall( NetPtr, Yin, Yout )
void *NetPtr; /* Network Pointer (not used) */
double *Yin, *Yout; /* Data In=4 Out=3 */
#endif /* __STDC__ */
{
double Xout[13], Xsum[13]; /* work arrays */
long ICmpT=0; /* temp for comparisons */
/* *** WARNING: Code generated assuming Recall = 0 *** */
/* Read and scale input into network */
Xout[2] = (double)(Yin[0] * (2) + (-1));
Xout[3] = (double)(Yin[1] * (2) + (-1));
Xout[4] = (double)(Yin[2] * (2) + (-1));
Xout[5] = (double)(Yin[3] * (2) + (-1));
LAB107:
/* Generating code for PE 0 in layer (3) */
Xsum[6] = (-0.94772547) + (-0.98690498) * Xout[2] + (-0.47397092) * Xout[3] + 1.3767525 * Xout[4] +
0.77097577 * Xout[5];
/* Generating code for PE 1 in layer (3) */
Xsum[7] = 1.3693793 + 0.43019372 * Xout[2] + (-1.035066) * Xout[3] + 1.370787 * Xout[4] + 1.4604141 * Xout[5];
/* Generating code for PE 2 in layer (3) */
Xsum[8] = 0.59802961 + (-0.67472422) * Xout[2] + 0.0067717968 * Xout[3] + (-0.098248005) * Xout[4] +
(-1.4808481) * Xout[5];
/* Generating code for PE 3 in layer (3) */
Xsum[9] = 3.0767488 + 1.0973973 * Xout[2] + 0.27670342 * Xout[3] + (-5.163259) * Xout[4] + (-5.0406961) * Xout[5];
/* Generating code for PE 0 in layer (3) */
Xout[6] = (double)(tanh( Xsum[6] ));
/* Generating code for PE 1 in layer (3) */
Xout[7] = (double)(tanh( Xsum[7] ));
/* Generating code for PE 2 in layer (3) */
Xout[8] = (double)(tanh( Xsum[8] ));
/* Generating code for PE 3 in layer (3) */
Xout[9] = (double)(tanh( Xsum[9] ));
/* Generating code for PE 0 in layer (4) */
Xsum[10] = (-0.057100281) + (-0.21855229) * Xout[6] + (-1.1194284) * Xout[7] + 0.075954795 * Xout[8] +
(-0.15848683) * Xout[9];
Xout[10] = (double)(tanh( Xsum[10] ));
/* Generating code for PE 1 in layer (4) */
Xsum[11] = (-1.0244384) + 0.10323889 * Xout[6] + 1.1238164 * Xout[7] + (-0.68130648) * Xout[8] +
1.7236693 * Xout[9];
Xout[11] = (double)(tanh( Xsum[11] ));
/* Generating code for PE 2 in layer (4) */
Xsum[12] = (-0.043892719) + 0.053954735 * Xout[6] + 0.0030997731 * Xout[7] + 0.59573656 * Xout[8] +
(-1.5831093) * Xout[9];
Xout[12] = (double)(tanh( Xsum[12] ));
/* De-scale and write output from network */
Yout[0] = (double)(Xout[10] * (0.625) + (0.5));
Yout[1] = (double)(Xout[11] * (0.625) + (0.5));
Yout[2] = (double)(Xout[12] * (0.625) + (0.5));
/* Generating code for PE 2 in layer (4) */
return( 0 );
}
#if defined(__cplusplus)
}
#endif
Jetzt mein Makro dazu (um obige DLL in Excel aufzurufen):
Private Declare

Function iris Lib "C:\Programme\NeuralWare\NeuralWorks\Professional\xyz.dll" (ByVal whichclass  _
As Long, ByVal in1 As Double, ByVal in2 As Double, ByVal in3 As Double, ByVal in4 As Double) As Double


Sub DLL()
Dim test As Double
Dim arg1 As Long
Dim arg2 As Double
Dim arg3 As Double
Dim arg4 As Double
test = iris(1, arg1, arg2, arg3, arg4)
End Sub


Anzeige
AW: Dynamic Link Library
29.02.2008 20:25:45
Nepumuk
Hallo Helmut,
ich beherrsche C++ nur rudimentär und eine DLL hab ich damit noch nicht geschrieben (ich bin schon froh, dass ich "Hello World" raus bekomme). Das ganze hat aber auch nur bedingt was mit Excel zu tun. Frag doch erst mal in einem C Forum nach, wie die DLL auszusehen hat. Den Rest können wir dann wieder hier machen.
Gruß
Nepumuk

AW: Dynamic Link Library
01.03.2008 10:09:51
Helmut
Nepomuk!
Ich bin mir absolut sicher dass der C Code zur DLL richtig ist ... da sich dieser aus einem Softwareprodukt heraus als Flash Code automatisch erstellt. Das Kompilieren der DLL funktioniert ebenfalls problemlos. D.h. ich habe die fertig kompilierte xyz.dll und brauche jetzt lediglich noch ein Makro welches mir die DLL in Excel 03 aufruft.

Anzeige
AW: Dynamic Link Library
01.03.2008 12:02:12
Nepumuk
Hallo Helmut,
kannst du die mal hochladen? So ohne selber testen ist das stochern im Nebel.
Gruß
Nepumuk

AW: Dynamic Link Library
01.03.2008 13:53:00
Helmut
https://www.herber.de/bbs/user/50329.zip
hier müsste die xyz.dll in gezippter Form liegen.
Besten Dank im voraus! Wäre genial wenn du den Fehler finden würdest.
Schöne Grüße, Helmut

AW: Dynamic Link Library
01.03.2008 20:22:00
Nepumuk
Hallo Helmut,
irgendwas ist faul an der DLL die reißt mir sämtliche Programme in der ich sie anspreche in den Abgrund.
Gruß
Nepumuk

AW: Dynamic Link Library
01.03.2008 22:45:00
Helmut
o.k. gut zu wissen, dann liegt es wahrscheinlich an der DLL selbst ... sie erstellt sich automatisch ... evtl. stimmt irgendwas mit den ersten Zeilen im C-Code nicht ... auf jeden Fall Danke für deine Bemühungen!

Anzeige
AW: Dynamic Link Library
02.03.2008 13:26:57
Helmut
https://www.herber.de/bbs/user/50354.zip
Nepomuk! Hab den Fehler in der DLL korrigiert (unter obigen Link findest du die neue DLL) ... sie stürzt jetzt nicht mehr ab...jetzt bräuchte ich nur noch den Makrobefehl dazu ... kannst du mit den hier rein stellen?
Besten Dank!

AW: Dynamic Link Library
02.03.2008 14:05:04
Nepumuk
Hallo Helmut,
hast du an den Parametern was geändert? Die Funktion erwartet nämlich keine. Damit hat sie natürlich auch wenig Sinn. Kannst es ja mal testen:
' **********************************************************************
' Modul: Modul1 Typ: Allgemeines Modul
' **********************************************************************

Option Explicit

Private Declare Function iris Lib "C:\xyz.dll" () As Double

Public Sub Call_DLL()
    MsgBox iris()
End Sub

Gruß
Nepumuk

Anzeige
AW: Dynamic Link Library
02.03.2008 15:06:28
Helmut
Hallo Nepomuk!
Erstmals bekomme ich einen Ausgabewert von der DLL zurück! 1,4190E-02. An den Paremetern habe ich nichts geändert; allerdings: für die Berechnung des Ausgabewertes sind vier verschiedene Inputs (4 verschiedene Datenwerte) notwendig. Wie mache ich Excel klar, dass ich aus einer Zelle mit der Funktion =iris(1,a1,b1,c1,d1) auf vier verschiedene Zellen (wo Werte drin stehen) verweise und die Zelle wo die Funktion drinsteht mir den Ausgabewert anzeigen soll.
Wär' toll wenn du das hinbekommen würdest.

AW: Dynamic Link Library
02.03.2008 15:08:45
Helmut
Hallo Nepomuk!
Erstmals bekomme ich einen Ausgabewert von der DLL zurück! 1,4190E-02. An den Paremetern habe ich nichts geändert; allerdings: für die Berechnung des Ausgabewertes sind vier verschiedene Inputs (4 verschiedene Datenwerte) notwendig. Wie mache ich Excel klar, dass ich aus einer Zelle mit der Funktion =iris(1,a1,b1,c1,d1) auf vier verschiedene Zellen (wo Werte drin stehen) verweise und die Zelle wo die Funktion drinsteht mir den Ausgabewert anzeigen soll.
Wär' toll wenn du das hinbekommen würdest.

Anzeige
AW: Dynamic Link Library
03.03.2008 08:47:00
Nepumuk
Hallo Helmut,
der aufruf der DLL funktioniert ja reibungslos. Was nicht passt, sind deine Parameter. Das liegt aber nicht an VBA, sondern an der DLL.
Gruß
Nepumuk

AW: Dynamic Link Library
03.03.2008 19:58:00
Volti
Hallo Nepumuk,
da bin ich aber froh, dass Du das genauso siehst wie ich. Helmut hat einen Parallelthread hier laufen, bei dem ich mich auch mal mit dem Problem befasst habe. Nach der Reparatur der DLL, die war ja kaputt, funktioniert das alles schon sauber auch mit den Parametern. Nämlich dann, wenn ich sie mit PowerBasic aufrufe. Da ist alles ok und easy.
Problem ist der Aufruf unter VBA, da kommt Error 49 Falsche Aufrufkonventition und das liegt m.E. am C-Code. Aus Deinem Link da oben kann man irgendwie entnehmen, dass mit stdcall zu arbeiten ist und nicht mit cdecl. Das hat irgendwie mit der Reihenfolge der Ablage der Parameter auf den Stack zu tun.
Da ich C auch nur rudimentär beherrsche oder noch weniger, kann ich dem Helmut jetzt allerdings nicht weiterhelfen.
So long
Karl-Heinz

Anzeige
AW: Dynamic Link Library
03.03.2008 22:03:00
Helmut
Ich denke auch, dass es irgendwie an "cdecl" liegt ... die Frage ist nur wie und wo "stdcall" zu implementieren ist ... werd' mich mal in einem C-Forum schlau machen ... trotzdem dank Euch allen!
Wenn wer noch Vorschläge hat, kann er mir gern ein Email an xpdefault@hotmail.com schicken ...
So long, Helmut

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige