Excel-add-ins in Delphi schreiben (nicht-com)


Schreiben von Excel-add-ins mit Delphi ist ein anspruchsvolles Projekt. Ich zeigen, wie es möglich ist, und die verschiedenen Fallstricke warten auf die ahnungslosen Reisenden in dieser weitgehend unerforschtes Grenze zu markieren.
Schreiben von Excel-add-ins mit Delphi ist ein anspruchsvolles Projekt. Hier, wo ich zeigen, wie es möglich ist, und die verschiedenen Fallstricke warten auf die ahnungslosen Reisenden in dieser weitgehend unerforschtes Grenze zu markieren.
Trotz Microsofts scheinbaren Unbeliebtheit in einigen Kreisen sollten Excel wirklich hoch auf Listen für 'beste jemals erstellt Software platzieren. Natürlich nehmen weit über zehn Jahre um es richtig zu machen half. Ich denke, dass eine besondere Stärke von Excel seine relativ offene API ist, sodass Entwickler zum Erstellen von Makros und Visual Basic für Excel/VBA für apps verwenden.
Ist eines der weniger bekannten Excel-Funktionen-add-ins. Aber Sie können sie mit VBA erstellen, aber du kannst auch schreiben-add-in-Dlls in C++ und Delphi. Für diejenigen, die ernste Entwicklung Sie das Excel 97 Developer's Kit (ISBN 1-57231-498-2) zu kaufen müssen (EDK) zu buchen, aber natürlich die C/C++ orientiert und es gibt einige fallen für den Delphi-Programmierer. In diesem Artikel zeige ich Ihnen genug um Sie gehen. Als Entwickler in einer Excel-Arbeitsumgebung habe ich viele Add-Ins mit Delphi 3 erfolgreich entwickelt, und ich kenne niemanden sonst auf diese Weise kennen. Es gibt finanzielle CAD, eine kanadische Firma, deren-add-ins von Delphi verwendet werden kann, aber ich denke, dass sie in C++ geschrieben sind. Hey könnte ich die einzige Person in der Welt auf diese Weise sein!
Delphi-add-ins erleichtern es Ihnen, Excel in vielen Möglichkeiten-wie Datenerfassung von seriellen Anschlüssen zu verlängern Datenfeeds, alle mit der Geschwindigkeit von Delphi kompiliert Code, die schneller als die interpretiert Excel-VBA. Können loslegen, Theres viel zu decken.
Riesige Zeichenfolgen sind ein großer Fehler
Da das Add-in ist eine DLL und Excel werden kurze Zeichenfolgen verwendet, müssen Sie sicherstellen, dass die riesige Zeichenfolgen-Compiler-Option ist klar (oder $H - verwendet). Sie könnte wahrscheinlich verwenden lange Zeichenfolgen intern aber stellen Sie sicher, dass Sie konvertieren, bevor sie Excel übergeben. Für weitere Sicherheits-Feature verwenden ShortString oder Zeichenfolgentypen [n], wobei n ist 1-255. Auch wenn Sie Hugestrings aktiviert haben, können Sie [n] Zeichenfolge für Parameter übergeben, da diese immer der Typ Shortstring sind. Denken Sie daran, die goldene Regel, keine langen Strings in den übergebenen Parametern oder Datensätze.
Anerkennung endlich
Excel erkennt nur die DLL als ein Add-in wenn bestimmte Funktionen exportiert werden. Sie müssen immer diese Funktionen, sowie die für den Benutzer bereitstellen. Diese XlAuto-Familie von Funktionen sind in der nachstehenden Tabelle aufgeführten und in dem Edk-Buch und im Beispielcode zu diesem Artikel dokumentiert. Alle Ihre exportierten Funktionen müssen die STDCALL-Aufrufkonvention verwenden.

FunctionPurpose
XlAutoFreeCalled von Excel des Addin befreien reservierten Arbeitsspeicher.
XlAutoAddCalled, wenn das Addin zuerst registriert wird.
XlAutoOpenCalled, wenn Excel geladen.
XlAutoCloseCalled, wenn Excel beendet wird.
XlAutoRemoveCalled, wenn das Add-in aus Excel entfernt wird.
XlAutoRegisterOnly aufgerufen, wenn eine Funktion noch nicht registriert wurde.
XlAddInManagerInfoProvides eine Textbeschreibung der Zeichenfolge für das Add-in.
Um eine Excel-Funktion verwenden ruft Ihre Funktion die Excel-Funktion Excel4V. Dies ist definiert als
Funktion Excel4v)
Xlfn: Wort;
OperRes: Lpxloper;
Anzahl: Integer;
Opers: Array von Lpxloper): Integer;
Stdcall; externe 'xlcall32.dll';
Xlfn ist die 'Funktion Anzahl' der Excel-Funktion aufgerufen.
Operfn ist das Ergebnis und ist ein Zeiger auf eine Xloper, eine Lpxloper genannt (siehe nächster Abschnitt)
Count ist die Anzahl der Elemente in Opers.
Oper ist ein Array von Lpxloper, d. h. ein Array von Zeigern auf XLOPER.
Hinweis: Für viele Funktion können Sie eine null-Array für den Opers-Parameter übergeben. Unter D3 die leeres Array Bau [] ist nicht zulässig, ...so ist es in D4 so verwenden [null] unter D3.
Mein Schwerpunkt der Entwicklung war es, Benutzern neue Funktionen geben. Die EDK dokumentiert wie Hinzufügen von Schaltflächen und Steuerelemente in Excel, sondern diejenigen ein bisschen mehr Arbeit sind und ich nicht behandeln sie hier. Möchten Sie Daten in Excel zu drängen, gibt es zwei andere Ansätze, beide Shareware basiert - die TadvExcel-Komponente verfügt über sehr übertragen schnelle Daten mithilfe von DDE. Die TxlsReadWrite lesen Sie Komponenten Formatierungen und Formeln direkt in Excel-Arbeitsmappendateien ausgeben können.
Bevor Sie beginnen, Excel-Funktionen aufrufen, müssen Sie wissen, über den XLOper-Typ. Dies ist ein Pascal-Rekord (C-Struktur) einige 10 Byte groß, ausgerichtet auf 16-Byte-Absätze in Arrays der Zellen in einer Excel-Tabelle entspricht. Die Definition wird unten gezeigt. Die Schuld von Microsoft für die kurzen Feldnamen. Tval-Typ verwendet den alten Pascal Variante Datensatztyp, um nicht zu verwechseln mit Windows OLE Varianten, aber in ähnlicher Weise verwendet. Xltype Bereich der XlOper gibt der 9 Typen verwendet im Spiel. Also wenn die Xloper einen Typ von 1 hat, hat val.num eine gültige für double Precision-Reihe.
Ich habe festgestellt, dass die Typen 1, 2 und 8 sind die am häufigsten verwendete. Typ 4 wird von Excel zurückgegeben, wenn man etwas falsch. Es gibt ein Integer-Datentyp (5) aber Num (1) scheint weitaus häufiger. Typ 6 ist für Bereiche mit 9 für Sammlungen separate Zellen verwendet wo Sie die STRG-Taste gedrückt Wenn Sie Zellen auswählen. Es gibt keinen Typ 7.
XLOPER Definition
TVal = packed Record
RS-Byte des
1: (Num: Double); (* XltypeNum *)
2: (str: ^ ShortString); (* XltypeStr *)
3: (Bool: Word); (* XltypeBool *)
4: (äh: Word); (* XltypeErr *)
5: (w: Integer); (* XltypeInt *)
6: (Sref: Datensatz verpackt
Graf: Wort;
Ref: Xlref;
Ende);
8: (_array: verpackt Datensatz (* XltypeMulti *)
LPArray: LPXLOPERArray;
Zeilen: WORD;
Spalten: WORD;
Ende);
9: (Mref: verpackt Datensatz / / Xltyperef
Lpmref: Lpxlmref;
Idsheet: Integer;
Ende);
Ende; TVal
XlOper = packed Record
Val: TVal;
Xltype: WORD;
Dummy: Byte-Array [0.. 5]; Beläge auf 16-Byte-Größe
Ende;
Lpxloper = ^ Xloper;
Problem mit Excel aufrufen
Von Delphi ist der großen Stolperstein mit Add-Ins die zusätzlichen Parameter nach die Rücksprungadresse auf dem Stack. Dies kommt kostenlos mit jedem Aufruf von Excel. Ich habe nie herausgefunden, was es hält, aber so lange, wie Sie es wegwerfen, das add-in wird funktionieren. Fügen Sie die Zeile Asm pop Variable; End; 4 Byte lange ganze Zahl ist nach jedem Anruf wo Variable, global, lokal sein kann oder Objektvariable, die zumindest ist in Ordnung. Zur Wiederholung - dieser muss aufgenommen werden nach jedem Aufruf von Excel4v. Ansonsten sind Sie eine Zeitbombe konstruieren.
Beispiel
Eresult: = Excel4V(xlfCaller,@xres,0,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Beachten Sie, dass mit der Delphi-Syntax, wenn Xres eine Xloper ist können Sie @xres verwenden, um ein Lpxloper zu definieren.
Vorsicht-Neuberechnung-Alarm!
Wenn die Eingaben in Ihrer Funktion in keiner Weise berechnet werden, sollten Code überprüfen Sie den Status der Excel-Aufruf (Eresult im obigen Beispiel) sowie das Ergebnis des Funktionsaufrufs Excel in Xres oben sein wird. Nicht vergessen Sie, dass Sie die angegebene Funktion Excel4V zu Cals aufrufen.
Eresult ergibt 0 Wenn ok, oder legen Sie ein bisschen auf Fehlern. Sie sollten immer die Werte 1 und 64 behandeln. 1 ist Xlabort, die angibt, dass der Benutzer die esc-Taste gedrückt. 64 ist eine nicht berechnete Zellbezug. Es ist kein Fehler, aber passiert, wenn Ihre Funktion verwendet Funktionen oder Berechnungen auf dem Arbeitsblatt, die vollständig ausgewertet werden, nachdem Ihre Routine wird aufgerufen. In diesem Fall müssen Sie Code Arbeitsspeichers, die bereits in den Aufruf und die Ausfahrt frei. Excel wird die Funktion erneut aufrufen.

Strukturieren Sie Ihren Code wie folgt
1. Holen Sie Eingabeparameter
2. Tritt ein Fehler 64 oder 1 (Abbruch-Taste), Ausfahrt nach dem Freigeben von Speicher bereits reserviert (falls vorhanden) in dieser Funktion.
3. nicht Hauptaufgabe der Verarbeitung.
Wenn Schritt 3 wird sehr zeitaufwändig sein, sagen mehr als 1/10 einer Sekunde Code sollte Statusüberprüfung Abbruch durch Aufrufen XlAbort in regelmäßigen Abständen.
Start
Wenn das Add-in für Excel zuerst hinzugefügt wird, muss jeder exportierten Funktionen registriert werden. Dies beinhaltet die Excel registrieren-Routine für jede Routine aufrufen. Es gibt acht Parameter als XLOPER übergeben.
ParameterTypeUse
Modul TextStringFull Name der DLL mit Pfad
ProcedureString oder NumberFunction Name oder Nummer aufrufen
Geben Sie TextStringArgument und Rückgabetypen
TextStringFunction Funktionsnamen in Funktion Assistenten
TextStringOptional Text Argumentzeichenfolge, die Parameter in Funktion Assistenten beschreibt
Makro-TypeNumber0, 1 oder 2
CategoryString oder NumberCategory, unter denen Funktion angezeigt
Kontextmenü TextStringOnly für Befehle verwendet, übergeben Sie Null für Funktion
Der wichtigste Parameter zu registrieren ist der Texttyp. Dies verwendet die Buchstaben A-R den Rückgabewert und die angegebenen Parameter darstellen. Werte werden wie zu in einer C-Api erwarten durch Verweis (d. h. Zeiger – das ist immer ein Lpxloper) oder durch Wert übergeben.
Z.B. übergibt Excel-Tabellenkalkulation-=MyFunction(a1:b1) einen Verweis, während =InterestRate('GBP') einen Wert verwendet.
Beispiel
DLLName: = GetName; Funktion Name/Pfad von Excel zurück
pxModuleText.SetStr(s) Anmerkung ;// (1)
pxProcedure.SetStr('AddDate'); / / Name der Funktion
pxTypeText.SetStr('JJDD!'); / / (2) Return type = J, Input = JDD
pxFunctionText.setStr('AddDate'); Name im Fx-Assistenten
pxArgumentText.SetStr('Date,Period,Currency'); Parm Text im FX-Wiz
pxMacrotype.SetNum(1); / / Type = Sinmple func(3)
pxCategory.SetStr(AddInCategory); / / Kategorie für Func. Wiz
EResult: = Excel4V (Xlfregister, @res, 8 / / 8 Parameter übergeben
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]) ;// Null
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num); / / ID-Code (4)
Die px-Variablen sind alle von der Txloper-Klasse die Initialisierend XLOPER vereinfacht.
Hinweise
(1) die DLLName und Pfad sollte aus Excel, über die XlGetName-Funktion abgerufen werden, die Sie im Beispielcode verwendet sehen können. Nicht hartcodieren tun es als es enthält den Pfad.
(2) siehe Register (Seite 219 im EdK) für umfassendere Informationen über den Datentyp 'Text'. Der erste Parameter ist der return-Parameter (J = 32-Bit-Ganzzahl) die nächsten 3 sind Eingänge (JDD = Integer, String, String) und der! bedeutet, dass die immer Excel Ruft die Funktion, wenn es neu berechnet wird. Ohne die!, Excel aufrufen die Funktion einmal das Ergebnis die Riegel und verriegelten Ergebnis auf spätere Aufrufe verwendet.
(3) Typ 1 = Funktion. Andere Arten gehören nicht aufgelistete Funktion (Typ 0) und Kommandos (Typ 2). Verwenden Sie Funktionen, die nicht im Funktions-Assistenten zeigen, 0.
(4) nach der erfolgreichen Registrierung enthält den numerische Wert in Res (res.val.num) einen ganzzahlige Id Code für diese Funktion das Handle. Speichern Sie diese, und übergeben Sie sie an die Unregister-Funktion, wenn die DLL geschlossen wird. Vergessen und Sie haben Schwierigkeiten bei der Verwendung von neuerer Versionen der Bibliothek...
Abrufen von Werten aus einer Excel-Kalkulationstabelle
Werte können auf drei Arten, übergeben werden.
1. als eine übergebene Wert. ZB = CalcMean(4,5,8); XltypeNum oder xltypestr
(2) als einfache Referenz eine Zelle a1 sagen oder A3:b56 reichen. xltypeSRef
(3) als zusammengesetzte Referenz. Im Grunde eine Sammlung von nicht zusammenhängenden Zellbezüge. xltypemref
1 und 2 sind die häufigsten. 3 ist ein wenig seltsam und, wenn wirklich gebraucht, es ist besser, diese herauszufiltern. Wenn Sie es verwenden möchten, die Eingabe ist ein Array von Zellbezügen (Typ 2), so Sie jeweils verwenden müssen.
Excel wird den Datentyp filtern, wenn Sie es (Zahl, String usw.) angeben, aber wenn erwartet eine Reihe, dann vollständig Art und Wertebereiche, Sie überprüfen sollten, Fehler melden, ggf....
Wiederkehrende Störungen
Ihre Funktion muss ein Lpxloper (Typ R) zurück, wenn Sie Excel-Fehlercodes zurückgeben möchten. Tun Sie einfach um einen Fehler im Res (eine Xloper) festzulegen
res.xltype: = Xltypeerr;
res.Val.err: = Anzahl; Gibt zurück, die folgenden Werte dann nur @res aus der Funktion zurück
Äh NumberExcel
0 #NULL
7 #DIV/0
15 #VALUE
23 #REF
29 #NAME
36 #NUM
42 #NV
Mit kompliziert, viele Parameter-Funktionen, die ich denke, dass Standard übertreffen Störungen sind ein wenig unfreundlich und also empfehle ich eine GetlastError()-Funktion, die den letzten Fehlerstring zurückgibt. Jede Funktion, die einen Fehler zurückgibt, sollte die Fehlerzeichenfolge von GetLastError() zurückgegeben festgelegt. Diese sparen Benutzer viel Zeit wenn sie zum ersten Mal Ihre Funktionen verwenden.
Lesung von Zellwerten
Sie möchten bestandener einen Zellbezug (XltypeSref) in den Zellen enthaltenen Werte zu erhalten. Dazu müssen Sie 'die Zelle Verweis Xloper zwingen'. Diese Kräfte umwandeln (eine Excel-Funktion) Excel, einen Vektor von XLOPER, mit genau zu konstruieren (#Rows * #Cols) XLOPER. Dh bei einem Array 2 x 3 Zellen erhalten Sie sechs XLOPER. Die Ziel-Xloper wird eine Kopfzeile mit dem Feld Xltype = 64 (Xltypearray). Das Val._array-Element enthält die Anzahl der Zeilen und Spalten und einen Zeiger auf den Körper Xloper.
Diese XLOPER sind in der Reihenfolge der Zeilen angeordnet, so dass die sechs Zellen in zwei Zeilen und 3 Spalten werden als
1 2 3
4 5 6
Jede wird die grundlegende Art (Xltype Num oder Str) und den Wert haben.
Beispiel der Nötigung
DestType.xltype: = XltypeInt;
DestType.Val.w: = XltypeMulti;
Eresult: = Excel4v(xlcoerce,@Xval,2,[Values,@desttype]) aus;
ASM pop Waschbecken; Ende; Nie entfernen

Die hier verwendete XLOPER/Lpxlopers sind
DestType - eine Xloper, die Nötigung Ziel angibt (Xltypemulti - zeichnet sich für ein Array von XLOPER)
Werte - die übergebene in Zelle Verweis-ein Lpxloper
Xval - die Ziel-Xloper. Nach einer erfolgreichen umwandeln ist der Header eines Arrays. Mit dem 2 x 3-Array gibt es sechs XLOPER, jede holding einen Zellenwert.
Excel hat reservierten Arbeitsspeicher in Ihrem Namen und dies muss behandelt werden, aber dazu später mehr...
Beispiel für die Verwendung der Werte
In diesem Beispiel überprüft die
Wenn dann xval.val._array.rows <> 1
beginnen
Fehler sollte ('nur eine Zeile haben');
GOTO Myexit;
Ende;
Xlar: = xval.val._array.lparray;
Index: = 0;
für Col: = 1 bis Xr. NumCols tun
beginnen
Wenn Xlar ^ [Index] .xltype <> Xltypenum dann
beginnen
Fehler ('Element ' + inttostr(row) + 'Not a Number');
zu brechen;
Ende;
Wert [Col]: = Xlar ^.val.num [Index];
Inc(Index);
Ende;
Xlar ist ein Zeiger auf ein Array von XLOPER. In diesem Beispiel überprüft dies, gibt es eine Zeile nicht numerische Daten. Dann werden die Werte in den Wert []-Array kopiert.
Setzen von Werten in Excel-Zellen
Zwar gibt es eine Entsprechung (Art von) des Xlcoerce, genannt Xlset, kann es nur von einem Befehl (Menü- oder Symbolleisten-Schaltfläche) und nicht aus einer Funktion aufgerufen werden. Seine sehr Anti-sozialen sowieso um nur ein paar Werte in eine Tabelle dump könnte es nur überschreiben einer morgens ungespeicherte Arbeit und wird nicht, die Ihre Popularität verbessern!
Eine nicht so bekannte Funktion von Excel Funktion Arrays (oder Formel Arrays) bezeichnet wird, was gebraucht wird. Wenn Sie nicht vertraut sind, versuchen Sie diese auf ein leeres Excelblatt.
1. Wählen Sie einen rechteckigen Bereich mit der Maus. Jetzt klicken Sie auf die Bearbeitung Linie (gerade unterhalb der Symbolleisten über die Zellen) und geben Sie = g1. An diesem Punkt sollten Sie sehen = g1 Bearbeiten Zeile und den ausgewählten Bereich noch ausgewählt werden. Wenn Sie die Auswahl aus Versehen gelöscht haben, gehen Sie zurück und versuchen Sie es erneut.
2. nun STRG-UMSCHALT-Taste gedrückt und drücken Sie enter. Die = g1 sollte in alle Zellen in den zuvor ausgewählten Bereich eingefügt werden.
Sie sollten auch einige Dinge über diese beachten, wenn Sie auf eine beliebige Zelle in diesem Bereich.
1. die bearbeiten-Linie zeigt die Gleichung in Klammern.
2. Sie können nicht ändern oder löschen die Zelle.
3. es passen nicht Sie den Zellbezug.
Dies ist die einzige Möglichkeit (soweit ich arbeiten könnte), Werte in Excel-Zellen zu setzen. Excel-Funktion muss ein Array von XLOPER, mit dem Header verweist auf den Körper aufbauen. Wenn Ihre Funktion ein Array zurückgibt, müssen Sie ein Array-Funktion verwenden, um das Ergebnis anzuzeigen. Excel ist mit diesem sehr clever. Wenn Sie einen 3 x 5-Bereich zurück und der Benutzer eine Funktion-Array in ein Rechteck 4 x 6 fügt, zeigen die zusätzlichen Zellen alle N/A.
Speicherverwaltung
Wenn ein Excel4v-Aufruf zurückgegeben wird eine Xloper mit einem Zeiger (Strings oder Xltypemulti zum Beispiel) dann, wenn Ihr Code mit dem Wert abgeschlossen hat Code muss immer aufrufen Xlfree auf die Xloper. In der Tat wie in der Regel schadet aufrufenden Xlfree auf alle Xloper nicht überhaupt.
Es gibt zwei Speicher Zuweisung-Fälle, die Ihr Code behandeln muss...
1. Sie haben eine Routine aufgerufen, die eine Xloper mit Daten, drin, zB Xlcoerce zurückgibt, ein Xltypesref/Xltyperef in ein Xltypemulti (Array) zu konvertieren. Excel weist seinen eigenen Speicher und wenn Sie fertig mit den Daten, sollten Sie oder im Wert $1000 (4096 dezimal) zum Xltype - dieser Wert $1000 als XlbitXLfree bekannt ist. Wenn Sie Xlfree aufrufen, gibt es die 'Excel zugeordnete' Speicher frei.
2. wenn Code ein Array von XLOPER, die Excel zeigt als Array Funktion, Sie müssen oder im Wert $4000 (16384 dezimal) auf das Xltype Feld, gibt bevor die Funktion beendet wird. Nach dem Kopieren der Werte wird Excel tun einen Rückruf an der XlAutoFree-Funktion (Sie eine implementieren nicht wahr?) mit einem Lpxloper auf Ihre Daten. Sie können es dann kostenlos. Wenn Sie das Array mit n Elementen, in der (n + 1) erstellt XLOPER, wo Arrayname [0] ist der Header der Arrayname [1] dann Punkte auf Arrayname [0] zurückgegebenen Zeiger verweist und Freemem (Aufruf Rückwärtszeiger) gibt den korrekten Zeiger dann frei.
Ein Beispiel-Add-In
Das Beispiel zu diesem Artikel ist in ca. 650 Codezeilen ohne nicht Delphi Komponenten oder benötigte eigenständig. Sie implementiert eine kumulative Verteilung Funktion GetCDF, die eine Anzahl in der Palette 03:56 als Eingabe akzeptiert und gibt die Höhe unter der Spitzbogen-Kurve. Ich weiß, dass Excel mit zahlreichen Funktionen der Normalverteilung kommt, aber es als Beispiel dient. Es wurde getestet auf Excel 95 und 97 mit Delphi 3 auf win 95/98 und NT und erwies sich als Fels in der Brandung. Ich kann nicht betonen, wie wichtig es ist, alle Eingaben überprüfen und versuchen, Ihren Code so robust wie möglich zu erhalten. Alles Böse wird wahrscheinlich zu bombardieren oder hängen Sie Excel, und Benutzer werden rasch Täter. Vergessen Sie nicht, die Stdcalls auf allen exportierten Funktionen!
Es beinhaltet neben der obligatorischen Xlauto-Familie von Funktionen fünf andere Funktionen, von die zwei nicht sichtbar sind. Diese beiden GetXlStack und FreeRam sind für die Verwendung durch den Entwickler nur gedacht. Die anderen drei (GetCDF, LastError und Version) sind für den Benutzer. Können Sie beide Typen von Funktionen direkt, sondern nur sichtbar, die denen im Funktions-Assistenten gesehen werden. Und vergessen Sie nicht die Klammern auf Funktionsaufrufe. Excel nimmt glücklich = Version (ohne ()) und ein Rückgabewert von-30408699 (Ich habe keine Ahnung) als Sie eigentlich gemeint = Version().
Ich habe nur die wichtigsten Excel-Funktion Zahlen verwendet, die im Programm enthalten, die vollständige Liste hat fast 400. Die EDK hat die gesamte Partie und enthält C-Header, die leicht bearbeitet werden können.
Dies ist in vielerlei Hinsicht ein bisschen wie eine altmodische, nicht-OOP-Programm. Ich entschied mich, dass so ursprünglich, wie ich meinen Weg Runde fühlte excel-add-ins und ich nicht, Probleme mit Objekten gleichzeitig zu haben wollte. Die einzige Klasse, die ich hier verwendet habe ist Txloper zur Vereinfachung der Erstellung von XLOPER, aber das war es kurz zu halten. Senden Sie Ihre Abfragen und Arbeit bietet [email protected].
Die folgende Datei ist abgeschlossen - Quelle für eine Dll. Stellen Sie sicher, dass die Erweiterung XLL ist

{$A+,B-,C+,D+,E-,F-,G+,H-,I+,J+,K-,L+,M-,N+,O-,P+,Q+,R-,S-,T-,U-,V+,W+,X+,Y-,Z1}
Bibliothek Cdfcalc;
verwendet
SysUtils,
Windows,
Dialoge,
Formen,
Klassen,
Math;
XLREF Struktur
Geben Sie Xlref = packed Record
RwFirst: Smallint;
RwLast: Smallint;
ColFirst: Byte;
ColLast: Byte;
Ende;
Liefert eine Auswahl
XlRangeRecord = packed Record
Count: Wort; $1 sollte immer sein werden.
Sref: Xlref;
Ende;
Xlmref = packed Record
Graf: Wort;
RefTbl: Array [0..1000] von XlRef;
Ende;
Lpxloper = ^ XLOPER;
LpxloperArray = ^ XLArray;
Lpxlmref = ^ Xlmref;
TVal = packed Record
RS-Byte des
1: (Num: Double); xltypeNum
2: (str: ^ ShortString); xltypeStr
3: (Bool: Word); xltypeBool
4: (äh: Word); xltypeErr
5: (w: Integer); xltypeInt
6: (Sref: Datensatz verpackt
Count: Wort;
Ref: Xlref;
Ende);
8: (_array: verpackt Record / / XltypeMulti
LPArray: LpxloperArray;
Zeilen: WORD;
Spalten: WORD;
Ende);
9: (Mref: verpackt Datensatz / / Xltyperef
Lpmref: Lpxlmref;
Idsheet: Integer;
Ende);
Ende; TVal
XLOPER = packed Record
Val: TVal;
Xltype: WORD;
Dummy: Byte-Array [0.. 5]; Füller
Ende;
Xlarray = Array [0..1000] der Xloper;
Lpxlarray = ^ Xlarray;
Txloper = Class / / einfache Xloper support Klasse
Private
Fxloper: Xloper;
fActualStr: ShortString;
Funktion Getlpxloper:lpxloper;
öffentliche
Konstruktor erstellen;

Destruktor Destroy; außer Kraft setzen;
Konstruktor Create_Str(NewStr: ShortString);
Prozedur SetStr(NewStr: ShortString);
Prozedur SetNum(NewNumber: Integer);
Prozedur SetInt(NewNumber: Integer);
Prozedur SetErr;
Eigenschaft Thelpxloper: Lpxloper lesen Getlpxloper;
Ende;
Excel
Funktion Excel4v(xlfn:word;operRes:lpxloper;count:integer;opers:array of lpxloper):integer;
Stdcall; externe 'xlcall32.dll';
XLMREF Struktur beschreibt mehrere rechteckige Verweise.
const
XltypeNum = $0001;
XltypeStr = $0002;
XltypeBool = $0004;
XltypeRef = $0008;
XltypeErr = $0010;
XltypeFlow = $0020;
XltypeMulti = $0040;
XltypeMissing = $0080;
XltypeNil = $0100;
XltypeSRef = $0400;
XltypeInt = $0800;
XlbitXLFree = $1000;
XlbitDLLFree = $4000;
XltypeBigData = XltypeStr oder XltypeInt;
Fehlercodes verwendet für val.err Feld der XLOPER-Struktur
XlerrNull = 0;
xlerrDiv0 = 7;
XlerrValue = 15;
XlerrRef = 23;
XlerrName = 29;
XlerrNum = 36;
XlerrNA = 42;
Return-codes
XlretSuccess = 0; Erfolg
XlretAbort = 1; Makro angehalten
XlretInvXlfn = 2; Ungültige Funktion Anzahl
XlretInvCount = 4; Ungültige Anzahl von Argumenten
XlretInvXloper = 8; Ungültige OPER-Struktur
XlretStackOvfl = 16; Stack-Überlauf
xlretFailed zurück = 32; Befehl fehlgeschlagen
XlretUncalced = 64; Uncalced Zelle
Funktion Anzahl bits
XlCommand = $8000;
XlSpecial = $4000;
Xlintl32 = $2000;
XlPrompt = $1000;
Sonderfunktion-Nummern
XlFree = (0 oder Xlspecial);
XlStack = (1 oder Xlspecial);
XlCoerce = (2 oder Xlspecial);
XlSet = (3 oder Xlspecial);
XlSheetId = (4 oder Xlspecial);
XlSheetNm = (5 oder Xlspecial);
XlAbort = (6 oder Xlspecial);
XlGetInst = (7 oder Xlspecial);
XlGetHwnd = (8 oder Xlspecial);
XlGetName = (9 oder Xlspecial);
XlEnableXLMsgs = (10 oder Xlspecial);
XlDisableXLMsgs = (11 oder Xlspecial);
XlDefineBinaryName = (12 oder Xlspecial);
XlGetBinaryName = (13 bzw. Xlspecial);
Benutzerdefinierte Funktionen, für die Excel-Funktionen aufrufen
XlfCaller = 89;
XlfRegister = 149;
XlfUnregister = 201;
//
DLLversion:shortstring = 'CDF Calc v1. 02';
AddInCategory = 'CDF-Rechner';
const zlpxloper=lpxloper(nil);
Geben Sie Retarray = Array [0..1000] der Xloper;
Pretarray = ^ Retarray;
Var / / globale Daten
Res: Xloper;
GetCDF_Id: Integer;
XlStack_Id: Integer;
EResult: Integer;
Waschbecken: Ganzzahl;
GetStack_Id: Integer;
LastError_Id: Integer;
FreeRam_Id: Integer;
Version_Id: Integer;
LastErrorxl: Xloper;
LastErrorStr: ShortString;
BRC: Ganzzahl;
FuncName: String [64];
PxModuleText, PxProcedure, PxTypetext, PxFunctiontext,
PxArgumentText, PxMacroType, PxCategory, PxShortcutText: Txloper;
HaveRegistered: Boolean;
xValue:XLOPER;
Procedure Setxlcols (Var Kopf: Array von Xloper Numrows, Numcols:word);
beginnen
fillchar(Head[0],sizeof(Head[0]),0);
fillchar(Head[1],sizeof(Head[1]),0);
Kopf [0] .xltype: = 64;
Kopf [0].val._array.rows: = Numrows; //
Kopf [0].val._array.columns: = Numcols; //
Kopf [0].val._array.lparray: = [1];-@head
Ende;
Procedure Setval (Var V: Xloper; Numval:double);
beginnen
fillchar(v,sizeof(v),0);
v.xltype:=1;
v.Val.num:=numval;
Ende;
Prozedur SetFunctionName(S:String);
beginnen
FuncName: = s;
Ende;
Prozedur Error(S:ShortString);
beginnen
Wenn LastErrorStr <> s dann
LastErrorStr: = FuncName + ':' + S;
Ende;
Funktion GetSheetName:ShortString;
Var Xres, Xsheetname:xloper;
ResStr:ShortString;
beginnen
ResStr: ='';
Eresult: = Excel4V(xlfCaller,@xres,0,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Wenn Eresult = 16 dann
ResStr: = 'No Caller ID'
sonst
beginnen
Eresult: = Excel4V(xlsheetnm,@xSheetname,1,[@Xres]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
& nbsp Wenn Eresult = 0 then
beginnen
ResStr: = xsheetname.val.str^;
Ende
Ende;
Eresult: = Excel4V(xlfree,nil,1,[@xres]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Eresult: = Excel4V(xlfree,nil,1,[@xsheetname]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = ResStr;
Ende;
Gibt vollständigen Pfad und Namen der DLL
Funktion GetName:ShortString;
beginnen
EResult:=Excel4V(xlGetName,@res,1,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Result:=Res.Val.Str^;
EResult: = Excel4V(xlfree,nil,1,[@res]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Ende;

CONST
X 1 =-4.0; linken Endpunkt
X 2 = + 4.0; rechten Endpunkt
NUMINV = 40000; Anzahl von Schritten
Typ Vector = ARRAY [-NUMINV.. NUMINV] Double;
VAR
K:Integer; Zähler
DELTA: Double; Schrittgröße
X:Double; tatsächliche Intervall Punkt
ABSZISSE: ^ VEKTOR; Vektor der Werte der Intervall Punkte
FX: ^ VEKTOR; Vektor der Werte der Dichtefunktion der
CDF:VECTOR; Vektor der Werte der kumulative Dichtefunktion
Generiert einen Wert der Normdichte Gaußsche Funktion}
Funktion F(X:Double):Double;
BEGIN
F:=EXP(-X*X/2)/SQRT(PI+PI);
ENDE;
Verfahren Gauß; {erhalten Sie Dichtefunktion der Normalverteilung}
BEGIN
fillchar(CDF,sizeof(CDF),0);
CDF [0]: = 0,5;
CDF-[1]: = 0,5;
CDF [1]: = 0,5;
DELTA: = NUMINV * 2;
DELTA: =(X2-X1)/DELTA; {höchste mögliche Bildschirmauflösung}
X: = X 1-DELTA;
K: = NUMINV;
WIEDERHOLEN SIE DIE
Inc(k);
X: = X + DELTA;
ABSZISSE ^ [K]: = X; {die X-Achsen Werte}
FX^[K]:=F(X); {die Y-Achsen-Werte}
BIS K = NUMINV;
ENDE;
Prozedur GenerateCDF;
Const Gamma = 0.2316419; a1 = 0.319381530;
a2 =-0.356563782; A3 = 1.781477937;
A4 =-1.821255987; A5 = 1.330274429;
VAR
K1, K2, k3, k4, k5: doppelte;
ICH: INTEGER;
BEGIN
New(FX);
New(Abscissa);
Gauß;
FOR I: = 0 TO NUMINV-DO
IF ABSCISSA ^ [I] > 0.0 dann
BEGIN
K1: = 1.0/(1.0+gamma*ABSCISSA^[I]);
K2: = SQR(k1);
K3: = k1 * K2;
K4: = SQR(k2);
K5: = k4 * k1;
CDF [I]: = 1.0 - FX ^ [I] * (a1 * k1 + a2 * K2 + a3 * k3 + a4 * k4 + a5 * k5);
ENDE;
for i: = - NUMINV-1 do
CDF [I]: = 1-Cdf [-ich];
Dispose(Abscissa);
Dispose(FX);
ENDE;
Geben Sie mit-4 < x < 4.0
Funktion GetCDF(xd:double):Double; Stdcall;
Var X: Double;
beginnen
X: = xd;
Wenn x > 4.0 dann
X: = 4.0;
Wenn x <-4.0 dann
X: = 4.0;
Ergebnis: = cdf[round(x*10000)];
Ende;
Main-Funktion
Funktion Register_GetCDF:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;
Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('GetCDF');
pxTypeText.SetStr('BB!'); Double, Double
pxFunctionText.setStr('GetCDF');
pxArgumentText.SetStr('Value');
pxMacrotype.SetNum(1);
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]);
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num);
Ende;
Wert der Excel-Stack wird
Funktion LastError:lpxloper; Stdcall;
beginnen
LastErrorxl.xltype:=xltypestr;
Die LastErrorxl.val.Str:=@LastErrorStr;
Ergebnis: = die @LastErrorxl;
Ende;
Funktion Register_LastError:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;
Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('LastError');
pxTypeText.SetStr('R!'); lpxloper
pxFunctionText.setStr('LastError');
pxArgumentText.SetStr (');
pxMacrotype.SetNum(1);
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]);
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num);
Ende;
Exportierte unsichtbare Funktion zeigt Wert des Excel-Stack
Funktion GetXlStack:lpxloper; Stdcall;
beginnen
EResult: = Excel4V(XlStack,@res,1,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = die @res;
Ende;
Funktion Register_GetXLStack:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;
Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('GetXlStack');
pxTypeText.SetStr('R!');
pxFunctionText.setStr('GetXlStack');
pxArgumentText.SetStr (');
pxMacrotype.SetNum(0); 0 = unsichtbar, 1 = sichtbar
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]);
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num);
Ende;
Exportierte Funktion
Stdcall Funktion Version: Lpxloper;
beginnen
xValue.xltype: = XltypeStr;
xValue.Val.str: = die @DLLversion;
Ergebnis: = die @xvalue;
Ende;
Funktion Register_Version:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;

Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('Version');
pxTypeText.SetStr('R!');
pxFunctionText.setStr('Version');
pxArgumentText.SetStr (');
pxMacrotype.SetNum(1);
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.








Excel-add-ins in Delphi schreiben (nicht-com)


Excel-add-ins in Delphi schreiben (nicht-com) : Mehreren tausend Tipps, um Ihr Leben einfacher machen.


Schreiben von Excel-add-ins mit Delphi ist ein anspruchsvolles Projekt. Ich zeigen, wie es möglich ist, und die verschiedenen Fallstricke warten auf die ahnungslosen Reisenden in dieser weitgehend unerforschtes Grenze zu markieren.
Schreiben von Excel-add-ins mit Delphi ist ein anspruchsvolles Projekt. Hier, wo ich zeigen, wie es möglich ist, und die verschiedenen Fallstricke warten auf die ahnungslosen Reisenden in dieser weitgehend unerforschtes Grenze zu markieren.
Trotz Microsofts scheinbaren Unbeliebtheit in einigen Kreisen sollten Excel wirklich hoch auf Listen für 'beste jemals erstellt Software platzieren. Natürlich nehmen weit über zehn Jahre um es richtig zu machen half. Ich denke, dass eine besondere Stärke von Excel seine relativ offene API ist, sodass Entwickler zum Erstellen von Makros und Visual Basic für Excel/VBA für apps verwenden.
Ist eines der weniger bekannten Excel-Funktionen-add-ins. Aber Sie können sie mit VBA erstellen, aber du kannst auch schreiben-add-in-Dlls in C++ und Delphi. Für diejenigen, die ernste Entwicklung Sie das Excel 97 Developer's Kit (ISBN 1-57231-498-2) zu kaufen müssen (EDK) zu buchen, aber natürlich die C/C++ orientiert und es gibt einige fallen für den Delphi-Programmierer. In diesem Artikel zeige ich Ihnen genug um Sie gehen. Als Entwickler in einer Excel-Arbeitsumgebung habe ich viele Add-Ins mit Delphi 3 erfolgreich entwickelt, und ich kenne niemanden sonst auf diese Weise kennen. Es gibt finanzielle CAD, eine kanadische Firma, deren-add-ins von Delphi verwendet werden kann, aber ich denke, dass sie in C++ geschrieben sind. Hey könnte ich die einzige Person in der Welt auf diese Weise sein!
Delphi-add-ins erleichtern es Ihnen, Excel in vielen Möglichkeiten-wie Datenerfassung von seriellen Anschlüssen zu verlängern Datenfeeds, alle mit der Geschwindigkeit von Delphi kompiliert Code, die schneller als die interpretiert Excel-VBA. Können loslegen, Theres viel zu decken.
Riesige Zeichenfolgen sind ein großer Fehler
Da das Add-in ist eine DLL und Excel werden kurze Zeichenfolgen verwendet, müssen Sie sicherstellen, dass die riesige Zeichenfolgen-Compiler-Option ist klar (oder $H - verwendet). Sie könnte wahrscheinlich verwenden lange Zeichenfolgen intern aber stellen Sie sicher, dass Sie konvertieren, bevor sie Excel übergeben. Für weitere Sicherheits-Feature verwenden ShortString oder Zeichenfolgentypen [n], wobei n ist 1-255. Auch wenn Sie Hugestrings aktiviert haben, können Sie [n] Zeichenfolge für Parameter übergeben, da diese immer der Typ Shortstring sind. Denken Sie daran, die goldene Regel, keine langen Strings in den übergebenen Parametern oder Datensätze.
Anerkennung endlich
Excel erkennt nur die DLL als ein Add-in wenn bestimmte Funktionen exportiert werden. Sie müssen immer diese Funktionen, sowie die für den Benutzer bereitstellen. Diese XlAuto-Familie von Funktionen sind in der nachstehenden Tabelle aufgeführten und in dem Edk-Buch und im Beispielcode zu diesem Artikel dokumentiert. Alle Ihre exportierten Funktionen müssen die STDCALL-Aufrufkonvention verwenden.

FunctionPurpose
XlAutoFreeCalled von Excel des Addin befreien reservierten Arbeitsspeicher.
XlAutoAddCalled, wenn das Addin zuerst registriert wird.
XlAutoOpenCalled, wenn Excel geladen.
XlAutoCloseCalled, wenn Excel beendet wird.
XlAutoRemoveCalled, wenn das Add-in aus Excel entfernt wird.
XlAutoRegisterOnly aufgerufen, wenn eine Funktion noch nicht registriert wurde.
XlAddInManagerInfoProvides eine Textbeschreibung der Zeichenfolge für das Add-in.
Um eine Excel-Funktion verwenden ruft Ihre Funktion die Excel-Funktion Excel4V. Dies ist definiert als
Funktion Excel4v)
Xlfn: Wort;
OperRes: Lpxloper;
Anzahl: Integer;
Opers: Array von Lpxloper): Integer;
Stdcall; externe 'xlcall32.dll';
Xlfn ist die 'Funktion Anzahl' der Excel-Funktion aufgerufen.
Operfn ist das Ergebnis und ist ein Zeiger auf eine Xloper, eine Lpxloper genannt (siehe nächster Abschnitt)
Count ist die Anzahl der Elemente in Opers.
Oper ist ein Array von Lpxloper, d. h. ein Array von Zeigern auf XLOPER.
Hinweis: Für viele Funktion können Sie eine null-Array für den Opers-Parameter übergeben. Unter D3 die leeres Array Bau [] ist nicht zulässig, ...so ist es in D4 so verwenden [null] unter D3.
Mein Schwerpunkt der Entwicklung war es, Benutzern neue Funktionen geben. Die EDK dokumentiert wie Hinzufügen von Schaltflächen und Steuerelemente in Excel, sondern diejenigen ein bisschen mehr Arbeit sind und ich nicht behandeln sie hier. Möchten Sie Daten in Excel zu drängen, gibt es zwei andere Ansätze, beide Shareware basiert - die TadvExcel-Komponente verfügt über sehr übertragen schnelle Daten mithilfe von DDE. Die TxlsReadWrite lesen Sie Komponenten Formatierungen und Formeln direkt in Excel-Arbeitsmappendateien ausgeben können.
Bevor Sie beginnen, Excel-Funktionen aufrufen, müssen Sie wissen, über den XLOper-Typ. Dies ist ein Pascal-Rekord (C-Struktur) einige 10 Byte groß, ausgerichtet auf 16-Byte-Absätze in Arrays der Zellen in einer Excel-Tabelle entspricht. Die Definition wird unten gezeigt. Die Schuld von Microsoft für die kurzen Feldnamen. Tval-Typ verwendet den alten Pascal Variante Datensatztyp, um nicht zu verwechseln mit Windows OLE Varianten, aber in ähnlicher Weise verwendet. Xltype Bereich der XlOper gibt der 9 Typen verwendet im Spiel. Also wenn die Xloper einen Typ von 1 hat, hat val.num eine gültige für double Precision-Reihe.
Ich habe festgestellt, dass die Typen 1, 2 und 8 sind die am häufigsten verwendete. Typ 4 wird von Excel zurückgegeben, wenn man etwas falsch. Es gibt ein Integer-Datentyp (5) aber Num (1) scheint weitaus häufiger. Typ 6 ist für Bereiche mit 9 für Sammlungen separate Zellen verwendet wo Sie die STRG-Taste gedrückt Wenn Sie Zellen auswählen. Es gibt keinen Typ 7.
XLOPER Definition
TVal = packed Record
RS-Byte des
1: (Num: Double); (* XltypeNum *)
2: (str: ^ ShortString); (* XltypeStr *)
3: (Bool: Word); (* XltypeBool *)
4: (äh: Word); (* XltypeErr *)
5: (w: Integer); (* XltypeInt *)
6: (Sref: Datensatz verpackt
Graf: Wort;
Ref: Xlref;
Ende);
8: (_array: verpackt Datensatz (* XltypeMulti *)
LPArray: LPXLOPERArray;
Zeilen: WORD;
Spalten: WORD;
Ende);
9: (Mref: verpackt Datensatz / / Xltyperef
Lpmref: Lpxlmref;
Idsheet: Integer;
Ende);
Ende; TVal
XlOper = packed Record
Val: TVal;
Xltype: WORD;
Dummy: Byte-Array [0.. 5]; Beläge auf 16-Byte-Größe
Ende;
Lpxloper = ^ Xloper;
Problem mit Excel aufrufen
Von Delphi ist der großen Stolperstein mit Add-Ins die zusätzlichen Parameter nach die Rücksprungadresse auf dem Stack. Dies kommt kostenlos mit jedem Aufruf von Excel. Ich habe nie herausgefunden, was es hält, aber so lange, wie Sie es wegwerfen, das add-in wird funktionieren. Fügen Sie die Zeile Asm pop Variable; End; 4 Byte lange ganze Zahl ist nach jedem Anruf wo Variable, global, lokal sein kann oder Objektvariable, die zumindest ist in Ordnung. Zur Wiederholung - dieser muss aufgenommen werden nach jedem Aufruf von Excel4v. Ansonsten sind Sie eine Zeitbombe konstruieren.
Beispiel
Eresult: = Excel4V(xlfCaller,@xres,0,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Beachten Sie, dass mit der Delphi-Syntax, wenn Xres eine Xloper ist können Sie @xres verwenden, um ein Lpxloper zu definieren.
Vorsicht-Neuberechnung-Alarm!
Wenn die Eingaben in Ihrer Funktion in keiner Weise berechnet werden, sollten Code überprüfen Sie den Status der Excel-Aufruf (Eresult im obigen Beispiel) sowie das Ergebnis des Funktionsaufrufs Excel in Xres oben sein wird. Nicht vergessen Sie, dass Sie die angegebene Funktion Excel4V zu Cals aufrufen.
Eresult ergibt 0 Wenn ok, oder legen Sie ein bisschen auf Fehlern. Sie sollten immer die Werte 1 und 64 behandeln. 1 ist Xlabort, die angibt, dass der Benutzer die esc-Taste gedrückt. 64 ist eine nicht berechnete Zellbezug. Es ist kein Fehler, aber passiert, wenn Ihre Funktion verwendet Funktionen oder Berechnungen auf dem Arbeitsblatt, die vollständig ausgewertet werden, nachdem Ihre Routine wird aufgerufen. In diesem Fall müssen Sie Code Arbeitsspeichers, die bereits in den Aufruf und die Ausfahrt frei. Excel wird die Funktion erneut aufrufen.

Strukturieren Sie Ihren Code wie folgt
1. Holen Sie Eingabeparameter
2. Tritt ein Fehler 64 oder 1 (Abbruch-Taste), Ausfahrt nach dem Freigeben von Speicher bereits reserviert (falls vorhanden) in dieser Funktion.
3. nicht Hauptaufgabe der Verarbeitung.
Wenn Schritt 3 wird sehr zeitaufwändig sein, sagen mehr als 1/10 einer Sekunde Code sollte Statusüberprüfung Abbruch durch Aufrufen XlAbort in regelmäßigen Abständen.
Start
Wenn das Add-in für Excel zuerst hinzugefügt wird, muss jeder exportierten Funktionen registriert werden. Dies beinhaltet die Excel registrieren-Routine für jede Routine aufrufen. Es gibt acht Parameter als XLOPER übergeben.
ParameterTypeUse
Modul TextStringFull Name der DLL mit Pfad
ProcedureString oder NumberFunction Name oder Nummer aufrufen
Geben Sie TextStringArgument und Rückgabetypen
TextStringFunction Funktionsnamen in Funktion Assistenten
TextStringOptional Text Argumentzeichenfolge, die Parameter in Funktion Assistenten beschreibt
Makro-TypeNumber0, 1 oder 2
CategoryString oder NumberCategory, unter denen Funktion angezeigt
Kontextmenü TextStringOnly für Befehle verwendet, übergeben Sie Null für Funktion
Der wichtigste Parameter zu registrieren ist der Texttyp. Dies verwendet die Buchstaben A-R den Rückgabewert und die angegebenen Parameter darstellen. Werte werden wie zu in einer C-Api erwarten durch Verweis (d. h. Zeiger – das ist immer ein Lpxloper) oder durch Wert übergeben.
Z.B. übergibt Excel-Tabellenkalkulation-=MyFunction(a1:b1) einen Verweis, während =InterestRate('GBP') einen Wert verwendet.
Beispiel
DLLName: = GetName; Funktion Name/Pfad von Excel zurück
pxModuleText.SetStr(s) Anmerkung ;// (1)
pxProcedure.SetStr('AddDate'); / / Name der Funktion
pxTypeText.SetStr('JJDD!'); / / (2) Return type = J, Input = JDD
pxFunctionText.setStr('AddDate'); Name im Fx-Assistenten
pxArgumentText.SetStr('Date,Period,Currency'); Parm Text im FX-Wiz
pxMacrotype.SetNum(1); / / Type = Sinmple func(3)
pxCategory.SetStr(AddInCategory); / / Kategorie für Func. Wiz
EResult: = Excel4V (Xlfregister, @res, 8 / / 8 Parameter übergeben
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]) ;// Null
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num); / / ID-Code (4)
Die px-Variablen sind alle von der Txloper-Klasse die Initialisierend XLOPER vereinfacht.
Hinweise
(1) die DLLName und Pfad sollte aus Excel, über die XlGetName-Funktion abgerufen werden, die Sie im Beispielcode verwendet sehen können. Nicht hartcodieren tun es als es enthält den Pfad.
(2) siehe Register (Seite 219 im EdK) für umfassendere Informationen über den Datentyp 'Text'. Der erste Parameter ist der return-Parameter (J = 32-Bit-Ganzzahl) die nächsten 3 sind Eingänge (JDD = Integer, String, String) und der! bedeutet, dass die immer Excel Ruft die Funktion, wenn es neu berechnet wird. Ohne die!, Excel aufrufen die Funktion einmal das Ergebnis die Riegel und verriegelten Ergebnis auf spätere Aufrufe verwendet.
(3) Typ 1 = Funktion. Andere Arten gehören nicht aufgelistete Funktion (Typ 0) und Kommandos (Typ 2). Verwenden Sie Funktionen, die nicht im Funktions-Assistenten zeigen, 0.
(4) nach der erfolgreichen Registrierung enthält den numerische Wert in Res (res.val.num) einen ganzzahlige Id Code für diese Funktion das Handle. Speichern Sie diese, und übergeben Sie sie an die Unregister-Funktion, wenn die DLL geschlossen wird. Vergessen und Sie haben Schwierigkeiten bei der Verwendung von neuerer Versionen der Bibliothek...
Abrufen von Werten aus einer Excel-Kalkulationstabelle
Werte können auf drei Arten, übergeben werden.
1. als eine übergebene Wert. ZB = CalcMean(4,5,8); XltypeNum oder xltypestr
(2) als einfache Referenz eine Zelle a1 sagen oder A3:b56 reichen. xltypeSRef
(3) als zusammengesetzte Referenz. Im Grunde eine Sammlung von nicht zusammenhängenden Zellbezüge. xltypemref
1 und 2 sind die häufigsten. 3 ist ein wenig seltsam und, wenn wirklich gebraucht, es ist besser, diese herauszufiltern. Wenn Sie es verwenden möchten, die Eingabe ist ein Array von Zellbezügen (Typ 2), so Sie jeweils verwenden müssen.
Excel wird den Datentyp filtern, wenn Sie es (Zahl, String usw.) angeben, aber wenn erwartet eine Reihe, dann vollständig Art und Wertebereiche, Sie überprüfen sollten, Fehler melden, ggf....
Wiederkehrende Störungen
Ihre Funktion muss ein Lpxloper (Typ R) zurück, wenn Sie Excel-Fehlercodes zurückgeben möchten. Tun Sie einfach um einen Fehler im Res (eine Xloper) festzulegen
res.xltype: = Xltypeerr;
res.Val.err: = Anzahl; Gibt zurück, die folgenden Werte dann nur @res aus der Funktion zurück
Äh NumberExcel
0 #NULL
7 #DIV/0
15 #VALUE
23 #REF
29 #NAME
36 #NUM
42 #NV
Mit kompliziert, viele Parameter-Funktionen, die ich denke, dass Standard übertreffen Störungen sind ein wenig unfreundlich und also empfehle ich eine GetlastError()-Funktion, die den letzten Fehlerstring zurückgibt. Jede Funktion, die einen Fehler zurückgibt, sollte die Fehlerzeichenfolge von GetLastError() zurückgegeben festgelegt. Diese sparen Benutzer viel Zeit wenn sie zum ersten Mal Ihre Funktionen verwenden.
Lesung von Zellwerten
Sie möchten bestandener einen Zellbezug (XltypeSref) in den Zellen enthaltenen Werte zu erhalten. Dazu müssen Sie 'die Zelle Verweis Xloper zwingen'. Diese Kräfte umwandeln (eine Excel-Funktion) Excel, einen Vektor von XLOPER, mit genau zu konstruieren (#Rows * #Cols) XLOPER. Dh bei einem Array 2 x 3 Zellen erhalten Sie sechs XLOPER. Die Ziel-Xloper wird eine Kopfzeile mit dem Feld Xltype = 64 (Xltypearray). Das Val._array-Element enthält die Anzahl der Zeilen und Spalten und einen Zeiger auf den Körper Xloper.
Diese XLOPER sind in der Reihenfolge der Zeilen angeordnet, so dass die sechs Zellen in zwei Zeilen und 3 Spalten werden als
1 2 3
4 5 6
Jede wird die grundlegende Art (Xltype Num oder Str) und den Wert haben.
Beispiel der Nötigung
DestType.xltype: = XltypeInt;
DestType.Val.w: = XltypeMulti;
Eresult: = Excel4v(xlcoerce,@Xval,2,[Values,@desttype]) aus;
ASM pop Waschbecken; Ende; Nie entfernen

Die hier verwendete XLOPER/Lpxlopers sind
DestType - eine Xloper, die Nötigung Ziel angibt (Xltypemulti - zeichnet sich für ein Array von XLOPER)
Werte - die übergebene in Zelle Verweis-ein Lpxloper
Xval - die Ziel-Xloper. Nach einer erfolgreichen umwandeln ist der Header eines Arrays. Mit dem 2 x 3-Array gibt es sechs XLOPER, jede holding einen Zellenwert.
Excel hat reservierten Arbeitsspeicher in Ihrem Namen und dies muss behandelt werden, aber dazu später mehr...
Beispiel für die Verwendung der Werte
In diesem Beispiel überprüft die
Wenn dann xval.val._array.rows <> 1
beginnen
Fehler sollte ('nur eine Zeile haben');
GOTO Myexit;
Ende;
Xlar: = xval.val._array.lparray;
Index: = 0;
für Col: = 1 bis Xr. NumCols tun
beginnen
Wenn Xlar ^ [Index] .xltype <> Xltypenum dann
beginnen
Fehler ('Element ' + inttostr(row) + 'Not a Number');
zu brechen;
Ende;
Wert [Col]: = Xlar ^.val.num [Index];
Inc(Index);
Ende;
Xlar ist ein Zeiger auf ein Array von XLOPER. In diesem Beispiel überprüft dies, gibt es eine Zeile nicht numerische Daten. Dann werden die Werte in den Wert []-Array kopiert.
Setzen von Werten in Excel-Zellen
Zwar gibt es eine Entsprechung (Art von) des Xlcoerce, genannt Xlset, kann es nur von einem Befehl (Menü- oder Symbolleisten-Schaltfläche) und nicht aus einer Funktion aufgerufen werden. Seine sehr Anti-sozialen sowieso um nur ein paar Werte in eine Tabelle dump könnte es nur überschreiben einer morgens ungespeicherte Arbeit und wird nicht, die Ihre Popularität verbessern!
Eine nicht so bekannte Funktion von Excel Funktion Arrays (oder Formel Arrays) bezeichnet wird, was gebraucht wird. Wenn Sie nicht vertraut sind, versuchen Sie diese auf ein leeres Excelblatt.
1. Wählen Sie einen rechteckigen Bereich mit der Maus. Jetzt klicken Sie auf die Bearbeitung Linie (gerade unterhalb der Symbolleisten über die Zellen) und geben Sie = g1. An diesem Punkt sollten Sie sehen = g1 Bearbeiten Zeile und den ausgewählten Bereich noch ausgewählt werden. Wenn Sie die Auswahl aus Versehen gelöscht haben, gehen Sie zurück und versuchen Sie es erneut.
2. nun STRG-UMSCHALT-Taste gedrückt und drücken Sie enter. Die = g1 sollte in alle Zellen in den zuvor ausgewählten Bereich eingefügt werden.
Sie sollten auch einige Dinge über diese beachten, wenn Sie auf eine beliebige Zelle in diesem Bereich.
1. die bearbeiten-Linie zeigt die Gleichung in Klammern.
2. Sie können nicht ändern oder löschen die Zelle.
3. es passen nicht Sie den Zellbezug.
Dies ist die einzige Möglichkeit (soweit ich arbeiten könnte), Werte in Excel-Zellen zu setzen. Excel-Funktion muss ein Array von XLOPER, mit dem Header verweist auf den Körper aufbauen. Wenn Ihre Funktion ein Array zurückgibt, müssen Sie ein Array-Funktion verwenden, um das Ergebnis anzuzeigen. Excel ist mit diesem sehr clever. Wenn Sie einen 3 x 5-Bereich zurück und der Benutzer eine Funktion-Array in ein Rechteck 4 x 6 fügt, zeigen die zusätzlichen Zellen alle N/A.
Speicherverwaltung
Wenn ein Excel4v-Aufruf zurückgegeben wird eine Xloper mit einem Zeiger (Strings oder Xltypemulti zum Beispiel) dann, wenn Ihr Code mit dem Wert abgeschlossen hat Code muss immer aufrufen Xlfree auf die Xloper. In der Tat wie in der Regel schadet aufrufenden Xlfree auf alle Xloper nicht überhaupt.
Es gibt zwei Speicher Zuweisung-Fälle, die Ihr Code behandeln muss...
1. Sie haben eine Routine aufgerufen, die eine Xloper mit Daten, drin, zB Xlcoerce zurückgibt, ein Xltypesref/Xltyperef in ein Xltypemulti (Array) zu konvertieren. Excel weist seinen eigenen Speicher und wenn Sie fertig mit den Daten, sollten Sie oder im Wert $1000 (4096 dezimal) zum Xltype - dieser Wert $1000 als XlbitXLfree bekannt ist. Wenn Sie Xlfree aufrufen, gibt es die 'Excel zugeordnete' Speicher frei.
2. wenn Code ein Array von XLOPER, die Excel zeigt als Array Funktion, Sie müssen oder im Wert $4000 (16384 dezimal) auf das Xltype Feld, gibt bevor die Funktion beendet wird. Nach dem Kopieren der Werte wird Excel tun einen Rückruf an der XlAutoFree-Funktion (Sie eine implementieren nicht wahr?) mit einem Lpxloper auf Ihre Daten. Sie können es dann kostenlos. Wenn Sie das Array mit n Elementen, in der (n + 1) erstellt XLOPER, wo Arrayname [0] ist der Header der Arrayname [1] dann Punkte auf Arrayname [0] zurückgegebenen Zeiger verweist und Freemem (Aufruf Rückwärtszeiger) gibt den korrekten Zeiger dann frei.
Ein Beispiel-Add-In
Das Beispiel zu diesem Artikel ist in ca. 650 Codezeilen ohne nicht Delphi Komponenten oder benötigte eigenständig. Sie implementiert eine kumulative Verteilung Funktion GetCDF, die eine Anzahl in der Palette 03:56 als Eingabe akzeptiert und gibt die Höhe unter der Spitzbogen-Kurve. Ich weiß, dass Excel mit zahlreichen Funktionen der Normalverteilung kommt, aber es als Beispiel dient. Es wurde getestet auf Excel 95 und 97 mit Delphi 3 auf win 95/98 und NT und erwies sich als Fels in der Brandung. Ich kann nicht betonen, wie wichtig es ist, alle Eingaben überprüfen und versuchen, Ihren Code so robust wie möglich zu erhalten. Alles Böse wird wahrscheinlich zu bombardieren oder hängen Sie Excel, und Benutzer werden rasch Täter. Vergessen Sie nicht, die Stdcalls auf allen exportierten Funktionen!
Es beinhaltet neben der obligatorischen Xlauto-Familie von Funktionen fünf andere Funktionen, von die zwei nicht sichtbar sind. Diese beiden GetXlStack und FreeRam sind für die Verwendung durch den Entwickler nur gedacht. Die anderen drei (GetCDF, LastError und Version) sind für den Benutzer. Können Sie beide Typen von Funktionen direkt, sondern nur sichtbar, die denen im Funktions-Assistenten gesehen werden. Und vergessen Sie nicht die Klammern auf Funktionsaufrufe. Excel nimmt glücklich = Version (ohne ()) und ein Rückgabewert von-30408699 (Ich habe keine Ahnung) als Sie eigentlich gemeint = Version().
Ich habe nur die wichtigsten Excel-Funktion Zahlen verwendet, die im Programm enthalten, die vollständige Liste hat fast 400. Die EDK hat die gesamte Partie und enthält C-Header, die leicht bearbeitet werden können.
Dies ist in vielerlei Hinsicht ein bisschen wie eine altmodische, nicht-OOP-Programm. Ich entschied mich, dass so ursprünglich, wie ich meinen Weg Runde fühlte excel-add-ins und ich nicht, Probleme mit Objekten gleichzeitig zu haben wollte. Die einzige Klasse, die ich hier verwendet habe ist Txloper zur Vereinfachung der Erstellung von XLOPER, aber das war es kurz zu halten. Senden Sie Ihre Abfragen und Arbeit bietet [email protected].
Die folgende Datei ist abgeschlossen - Quelle für eine Dll. Stellen Sie sicher, dass die Erweiterung XLL ist

{$A+,B-,C+,D+,E-,F-,G+,H-,I+,J+,K-,L+,M-,N+,O-,P+,Q+,R-,S-,T-,U-,V+,W+,X+,Y-,Z1}
Bibliothek Cdfcalc;
verwendet
SysUtils,
Windows,
Dialoge,
Formen,
Klassen,
Math;
XLREF Struktur
Geben Sie Xlref = packed Record
RwFirst: Smallint;
RwLast: Smallint;
ColFirst: Byte;
ColLast: Byte;
Ende;
Liefert eine Auswahl
XlRangeRecord = packed Record
Count: Wort; $1 sollte immer sein werden.
Sref: Xlref;
Ende;
Xlmref = packed Record
Graf: Wort;
RefTbl: Array [0..1000] von XlRef;
Ende;
Lpxloper = ^ XLOPER;
LpxloperArray = ^ XLArray;
Lpxlmref = ^ Xlmref;
TVal = packed Record
RS-Byte des
1: (Num: Double); xltypeNum
2: (str: ^ ShortString); xltypeStr
3: (Bool: Word); xltypeBool
4: (äh: Word); xltypeErr
5: (w: Integer); xltypeInt
6: (Sref: Datensatz verpackt
Count: Wort;
Ref: Xlref;
Ende);
8: (_array: verpackt Record / / XltypeMulti
LPArray: LpxloperArray;
Zeilen: WORD;
Spalten: WORD;
Ende);
9: (Mref: verpackt Datensatz / / Xltyperef
Lpmref: Lpxlmref;
Idsheet: Integer;
Ende);
Ende; TVal
XLOPER = packed Record
Val: TVal;
Xltype: WORD;
Dummy: Byte-Array [0.. 5]; Füller
Ende;
Xlarray = Array [0..1000] der Xloper;
Lpxlarray = ^ Xlarray;
Txloper = Class / / einfache Xloper support Klasse
Private
Fxloper: Xloper;
fActualStr: ShortString;
Funktion Getlpxloper:lpxloper;
öffentliche
Konstruktor erstellen;

Destruktor Destroy; außer Kraft setzen;
Konstruktor Create_Str(NewStr: ShortString);
Prozedur SetStr(NewStr: ShortString);
Prozedur SetNum(NewNumber: Integer);
Prozedur SetInt(NewNumber: Integer);
Prozedur SetErr;
Eigenschaft Thelpxloper: Lpxloper lesen Getlpxloper;
Ende;
Excel
Funktion Excel4v(xlfn:word;operRes:lpxloper;count:integer;opers:array of lpxloper):integer;
Stdcall; externe 'xlcall32.dll';
XLMREF Struktur beschreibt mehrere rechteckige Verweise.
const
XltypeNum = $0001;
XltypeStr = $0002;
XltypeBool = $0004;
XltypeRef = $0008;
XltypeErr = $0010;
XltypeFlow = $0020;
XltypeMulti = $0040;
XltypeMissing = $0080;
XltypeNil = $0100;
XltypeSRef = $0400;
XltypeInt = $0800;
XlbitXLFree = $1000;
XlbitDLLFree = $4000;
XltypeBigData = XltypeStr oder XltypeInt;
Fehlercodes verwendet für val.err Feld der XLOPER-Struktur
XlerrNull = 0;
xlerrDiv0 = 7;
XlerrValue = 15;
XlerrRef = 23;
XlerrName = 29;
XlerrNum = 36;
XlerrNA = 42;
Return-codes
XlretSuccess = 0; Erfolg
XlretAbort = 1; Makro angehalten
XlretInvXlfn = 2; Ungültige Funktion Anzahl
XlretInvCount = 4; Ungültige Anzahl von Argumenten
XlretInvXloper = 8; Ungültige OPER-Struktur
XlretStackOvfl = 16; Stack-Überlauf
xlretFailed zurück = 32; Befehl fehlgeschlagen
XlretUncalced = 64; Uncalced Zelle
Funktion Anzahl bits
XlCommand = $8000;
XlSpecial = $4000;
Xlintl32 = $2000;
XlPrompt = $1000;
Sonderfunktion-Nummern
XlFree = (0 oder Xlspecial);
XlStack = (1 oder Xlspecial);
XlCoerce = (2 oder Xlspecial);
XlSet = (3 oder Xlspecial);
XlSheetId = (4 oder Xlspecial);
XlSheetNm = (5 oder Xlspecial);
XlAbort = (6 oder Xlspecial);
XlGetInst = (7 oder Xlspecial);
XlGetHwnd = (8 oder Xlspecial);
XlGetName = (9 oder Xlspecial);
XlEnableXLMsgs = (10 oder Xlspecial);
XlDisableXLMsgs = (11 oder Xlspecial);
XlDefineBinaryName = (12 oder Xlspecial);
XlGetBinaryName = (13 bzw. Xlspecial);
Benutzerdefinierte Funktionen, für die Excel-Funktionen aufrufen
XlfCaller = 89;
XlfRegister = 149;
XlfUnregister = 201;
//
DLLversion:shortstring = 'CDF Calc v1. 02';
AddInCategory = 'CDF-Rechner';
const zlpxloper=lpxloper(nil);
Geben Sie Retarray = Array [0..1000] der Xloper;
Pretarray = ^ Retarray;
Var / / globale Daten
Res: Xloper;
GetCDF_Id: Integer;
XlStack_Id: Integer;
EResult: Integer;
Waschbecken: Ganzzahl;
GetStack_Id: Integer;
LastError_Id: Integer;
FreeRam_Id: Integer;
Version_Id: Integer;
LastErrorxl: Xloper;
LastErrorStr: ShortString;
BRC: Ganzzahl;
FuncName: String [64];
PxModuleText, PxProcedure, PxTypetext, PxFunctiontext,
PxArgumentText, PxMacroType, PxCategory, PxShortcutText: Txloper;
HaveRegistered: Boolean;
xValue:XLOPER;
Procedure Setxlcols (Var Kopf: Array von Xloper Numrows, Numcols:word);
beginnen
fillchar(Head[0],sizeof(Head[0]),0);
fillchar(Head[1],sizeof(Head[1]),0);
Kopf [0] .xltype: = 64;
Kopf [0].val._array.rows: = Numrows; //
Kopf [0].val._array.columns: = Numcols; //
Kopf [0].val._array.lparray: = [1];-@head
Ende;
Procedure Setval (Var V: Xloper; Numval:double);
beginnen
fillchar(v,sizeof(v),0);
v.xltype:=1;
v.Val.num:=numval;
Ende;
Prozedur SetFunctionName(S:String);
beginnen
FuncName: = s;
Ende;
Prozedur Error(S:ShortString);
beginnen
Wenn LastErrorStr <> s dann
LastErrorStr: = FuncName + ':' + S;
Ende;
Funktion GetSheetName:ShortString;
Var Xres, Xsheetname:xloper;
ResStr:ShortString;
beginnen
ResStr: ='';
Eresult: = Excel4V(xlfCaller,@xres,0,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Wenn Eresult = 16 dann
ResStr: = 'No Caller ID'
sonst
beginnen
Eresult: = Excel4V(xlsheetnm,@xSheetname,1,[@Xres]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
& nbsp Wenn Eresult = 0 then
beginnen
ResStr: = xsheetname.val.str^;
Ende
Ende;
Eresult: = Excel4V(xlfree,nil,1,[@xres]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Eresult: = Excel4V(xlfree,nil,1,[@xsheetname]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = ResStr;
Ende;
Gibt vollständigen Pfad und Namen der DLL
Funktion GetName:ShortString;
beginnen
EResult:=Excel4V(xlGetName,@res,1,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Result:=Res.Val.Str^;
EResult: = Excel4V(xlfree,nil,1,[@res]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Ende;

CONST
X 1 =-4.0; linken Endpunkt
X 2 = + 4.0; rechten Endpunkt
NUMINV = 40000; Anzahl von Schritten
Typ Vector = ARRAY [-NUMINV.. NUMINV] Double;
VAR
K:Integer; Zähler
DELTA: Double; Schrittgröße
X:Double; tatsächliche Intervall Punkt
ABSZISSE: ^ VEKTOR; Vektor der Werte der Intervall Punkte
FX: ^ VEKTOR; Vektor der Werte der Dichtefunktion der
CDF:VECTOR; Vektor der Werte der kumulative Dichtefunktion
Generiert einen Wert der Normdichte Gaußsche Funktion}
Funktion F(X:Double):Double;
BEGIN
F:=EXP(-X*X/2)/SQRT(PI+PI);
ENDE;
Verfahren Gauß; {erhalten Sie Dichtefunktion der Normalverteilung}
BEGIN
fillchar(CDF,sizeof(CDF),0);
CDF [0]: = 0,5;
CDF-[1]: = 0,5;
CDF [1]: = 0,5;
DELTA: = NUMINV * 2;
DELTA: =(X2-X1)/DELTA; {höchste mögliche Bildschirmauflösung}
X: = X 1-DELTA;
K: = NUMINV;
WIEDERHOLEN SIE DIE
Inc(k);
X: = X + DELTA;
ABSZISSE ^ [K]: = X; {die X-Achsen Werte}
FX^[K]:=F(X); {die Y-Achsen-Werte}
BIS K = NUMINV;
ENDE;
Prozedur GenerateCDF;
Const Gamma = 0.2316419; a1 = 0.319381530;
a2 =-0.356563782; A3 = 1.781477937;
A4 =-1.821255987; A5 = 1.330274429;
VAR
K1, K2, k3, k4, k5: doppelte;
ICH: INTEGER;
BEGIN
New(FX);
New(Abscissa);
Gauß;
FOR I: = 0 TO NUMINV-DO
IF ABSCISSA ^ [I] > 0.0 dann
BEGIN
K1: = 1.0/(1.0+gamma*ABSCISSA^[I]);
K2: = SQR(k1);
K3: = k1 * K2;
K4: = SQR(k2);
K5: = k4 * k1;
CDF [I]: = 1.0 - FX ^ [I] * (a1 * k1 + a2 * K2 + a3 * k3 + a4 * k4 + a5 * k5);
ENDE;
for i: = - NUMINV-1 do
CDF [I]: = 1-Cdf [-ich];
Dispose(Abscissa);
Dispose(FX);
ENDE;
Geben Sie mit-4 < x < 4.0
Funktion GetCDF(xd:double):Double; Stdcall;
Var X: Double;
beginnen
X: = xd;
Wenn x > 4.0 dann
X: = 4.0;
Wenn x <-4.0 dann
X: = 4.0;
Ergebnis: = cdf[round(x*10000)];
Ende;
Main-Funktion
Funktion Register_GetCDF:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;
Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('GetCDF');
pxTypeText.SetStr('BB!'); Double, Double
pxFunctionText.setStr('GetCDF');
pxArgumentText.SetStr('Value');
pxMacrotype.SetNum(1);
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]);
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num);
Ende;
Wert der Excel-Stack wird
Funktion LastError:lpxloper; Stdcall;
beginnen
LastErrorxl.xltype:=xltypestr;
Die LastErrorxl.val.Str:=@LastErrorStr;
Ergebnis: = die @LastErrorxl;
Ende;
Funktion Register_LastError:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;
Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('LastError');
pxTypeText.SetStr('R!'); lpxloper
pxFunctionText.setStr('LastError');
pxArgumentText.SetStr (');
pxMacrotype.SetNum(1);
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]);
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num);
Ende;
Exportierte unsichtbare Funktion zeigt Wert des Excel-Stack
Funktion GetXlStack:lpxloper; Stdcall;
beginnen
EResult: = Excel4V(XlStack,@res,1,[nil]) aus;
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = die @res;
Ende;
Funktion Register_GetXLStack:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;
Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('GetXlStack');
pxTypeText.SetStr('R!');
pxFunctionText.setStr('GetXlStack');
pxArgumentText.SetStr (');
pxMacrotype.SetNum(0); 0 = unsichtbar, 1 = sichtbar
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.thelpxloper,
pxTypeText.thelpxloper,
pxFunctionText.thelpxloper,
pxArgumentText.thelpxloper,
pxMacroType.thelpxloper,
pxCategory.thelpxloper,
Zlpxloper]);
ASM pop Waschbecken; Ende; Nie entfernen
Ergebnis: = trunc(res.val.num);
Ende;
Exportierte Funktion
Stdcall Funktion Version: Lpxloper;
beginnen
xValue.xltype: = XltypeStr;
xValue.Val.str: = die @DLLversion;
Ergebnis: = die @xvalue;
Ende;
Funktion Register_Version:integer;
Var S:Shortstring;
beginnen
Res.xltype: = Xltypeerr;

Res.Val.err: = Xlerrvalue;
s: = GetName;
pxModuleText.SetStr(s);
pxProcedure.SetStr('Version');
pxTypeText.SetStr('R!');
pxFunctionText.setStr('Version');
pxArgumentText.SetStr (');
pxMacrotype.SetNum(1);
pxCategory.SetStr(AddInCategory);
EResult: = Excel4V (Xlfregister, @res, 8,
[pxModuletext.thelpxloper,
pxProcedure.

Excel-add-ins in Delphi schreiben (nicht-com)

Excel-add-ins in Delphi schreiben (nicht-com) : Mehreren tausend Tipps, um Ihr Leben einfacher machen.
Excel-add-ins in Delphi schreiben (nicht-com)
Wiezutun
Freunden empfehlen
  • gplus
  • pinterest

Kommentar

Einen Kommentar hinterlassen

Wertung