Skriver (Non Com) Excel Add-ins i Delphi

Writing Excel add-ins med Delphi er et utfordrende prosjekt. Jeg vise hvordan det kan gjøres, og fremheve de ulike fallgruvene venter på uvitende reisende i dette stort sett uutforsket frontier.Writing Excel-tillegg med Delphi er et utfordrende prosjekt. Her hvor jeg viser hvordan det kan gjøres, og fremheve de ulike fallgruvene venter på uvitende reisende i dette stort sett uutforsket frontier.Despite Microsofts tilsynelatende upopularitet i noen kvartaler, Excel virkelig bør plassere høyt på listene for 'beste programvaren noensinne er laget ». Selvfølgelig tar godt over ti år for å få det riktig hjulpet. Jeg tror at en særlig styrke Excel er dens relativt åpent API, slik at utviklere å lage makroer og bruke Visual Basic for Excel /VBA for apps.One av de mindre kjente Excel-funksjoner er add-ins. Selv om du kan lage dem med VBA, men du kan også skrive-tillegget DLLs i C ++ og Delphi. For de som gjør alvorlig utvikling må du kjøpe Excel 97 utviklersett (ISBN 1-57231-498-2) (EDK) bok, men selvfølgelig sin C /C ++ orientert og det er noen feller for Delphi programmerer. I denne artikkelen vil jeg vise deg nok til å få deg i gang. Som utvikler i et Excel-arbeidsmiljøet jeg har utviklet mange add-ins med Delphi 3, og jeg vet om vet om ingen andre gjør dette. Det er Financial CAD, et kanadisk firma som add-ins kan brukes fra Delphi, men jeg tror de er skrevet i C ++. Hei jeg kan være den eneste personen i verden å gjøre dette! Delphi-tillegg gjøre det enkelt for deg å forlenge Excel på mange måter-eksempel datafangst fra serieporter, datafeeder, alle med hastigheten på Delphi kompilert kode som er betydelig raskere enn tolket Excel VBA. Kan komme i gang, theres mye å cover.Huge Strings er en stor MistakeAs tillegget er en DLL og Excel bruker korte strenger, må du sørge for at Huge Strings kompilatoren alternativet er klart (eller $ H- brukes). Du kan sikkert bruke lange strenger internt, men sørg for at du konvertere før passerer dem til Excel. For ytterligere sikkerhetsfunksjon bruk ShortString eller String [n] typer der n er 1-255. Selv om du har Hugestrings aktivert, kan du bruke string [n] for parameteroverføring da disse alltid er av typen shortstring. Bare husk den gylne regel, vil ingen lange strenger i passert parametere eller records.Recognition på lastExcel bare gjenkjenne DLL som en add-in dersom visse funksjoner blir eksportert. Du må alltid gi disse funksjonene, så vel som for brukeren. Disse xlAuto familie av funksjoner er oppført i tabellen nedenfor, og dokumenteres i EDK bok og i eksempelet kode med denne artikkelen. Alle dine eksporterte funksjoner må bruke STDCALL ringer konvensjonen. Funksjon PurposexlAutoFree Kalt av Excel til å frigjøre Addin tildelte memory.XlAutoAdd Kalt når Addin er første registered.XlAutoOpen Kalles når Excel loads.XlAutoClose Kalles når Excel exits.XlAutoRemove Kalt når Addin fjernes fra Excel.XlAutoRegister Bare kalles hvis en funksjon hasn 't vært registered.XlAddInManagerInfo Gir en tekststreng beskrivelse av Addin.To bruke bygget i Excel fungere din funksjon kaller Excel-funksjon Excel4V. Dette er definert asfunction Excel4v (xlfn: ord; operRes: lpxloper; teller: integer; opers: array of lpxloper): integer; STDCALL; ekstern 'xlcall32.dll'; xlfn er "Function antall" av Excel-funksjon called.Operfn er resultatet og er en peker til en xloper kalt en lpxloper (se neste avsnitt) Count er antall elementer i Opers.Opers er en rekke lpxloper, dvs. en rekke pekere til xlopers.Note: For mange funksjonen kan du passere en null matrise for Opers parameter. Under D3, den tom array konstruksjon [] er ikke tillatt, .as det er i D4 så bruk [null] under D3.My utvikling vekt har vært å gi brukerne nye funksjoner. EDK dokumenter hvordan du legger til knapper og kontroller til Excel, men de er litt mer arbeid, og jeg ikke håndtere dem her. Hvis du ønsker å presse data inn i Excel er det to andre tilnærminger, både shareware based- den TadvExcel komponent har svært rask dataoverføring med DDE. Den TxlsReadWrite lese komponenter kan sende data formatering og formler direkte inn i Excel-arbeidsbok files.Before du begynne å ringe Excel-funksjoner, må du vite om XLOper type. Dette er en pascal rekord (C struct) noen 10 byte i størrelse, justert på 16 byte paragrafer i matriser som tilsvarer celler i et Excel-regneark. Definisjonen er vist nedenfor. Klandre Microsoft for de korte feltnavn. Den Tval type bruker den gamle pascal variant oppføringstype, som ikke må forveksles med Windows OLE varianter, men brukt på en lignende måte. Den xltype innen XlOper spesifiserer hvilken av de 9 typer som brukes er i spill. Så hvis det xloper har en type 1, har en gyldig val.num dobbel presisjon number.I've funnet at type 1, 2 og 8 er de mest brukte. Type 4 er returnert av Excel når du får noe galt. Det er et heltall type (5), men num (1) virker langt mer vanlig. Type 6 er brukt for områder, med type 9 for samlinger av separate celler hvor du holder Ctrl-tasten nede når du velger celler. Det er ingen type 7.Xloper DefinitionTVal = pakket Record sak Byte 1: (num: Double); (* XltypeNum *) 2: (str: ^ ShortString); (* XltypeStr *) 3: (bool: Word); (* XltypeBool *) 4: (err: Word); (* XltypeErr *) 5: (w: Integer); (* XltypeInt *) 6: (sref: pakket rekord count: ordet, ref: Xlref; end); 8: (_array: pakket Record (* xltypeMulti *) lparray: LPXLOPERArray; rekker: Ord; kolonner: Ord, End); 9: (mref: pakket posten //xltyperef lpmref: lpxlmref; idsheet: integer; End); Slutt; //Tval XlOper = pakket Record val: TVal; xltype: WORD; dummy: array [0..5] i byte; //Pads til 16 byte størrelse End; lpxloper = ^ xloper; Problem med Excel callsFrom Delphi den store snublestein med add-ins er det ekstra parameter etter returadresse på stakken. Dette kommer gratis med hver samtale til Excel. Jeg har aldri funnet ut hva det holder, men så lenge du kaste det bort, vil tillegget fungerer fint. Legg linjen asm pop variabel; ende; etter hver samtale hvor variable kan være noen global, lokal eller objekt variabel som er minst 4 byte lang heltall er fine. Til gjentatte DENNE må inkluderes etter hvert Excel4v samtale. Ellers er du konstruere en tids bomb.ExampleEresult: = Excel4V (xlfCaller, @ xres, 0, [null]); asm pop vasken; slutt; //Aldri RemoveNote at med Delphi syntaks, hvis xres er en xloper, kan du brukexres å definere en lpxloper.Caution- Etterregning Alert! Hvis inndata til din funksjon regnes i en hvilken som helst måte, bør koden sjekke status for Excel anrop (Eresult i eksemplet ovenfor), så vel som resultatet av Excel-funksjonskall som vil være i xres ovenfor. Husk at du kaller Excel4V å Cals den angitte function.Eresult gir 0 hvis ok, eller litt satt for å indikere feil. Du bør alltid håndtere verdiene 1 og 64. 1 er xlabort indikerer at brukeren trykker på esc-tasten. 64 er en uncalculated cellereferanse. Det er ikke en feil, men skjer når funksjonen bruker funksjoner eller beregninger på regnearket som er fullt evalueres etter rutinen er først kalt. Hvis dette skjer, må du kode frigjøre noe minne allerede bevilget i samtalen og avslutte. Excel vil kalle din funksjon igjen. Strukturere koden som this1. Få Input Parameters2. Hvis det oppstår en feil 64 eller 1 (avbryte nøkkel), exit etter frigjøre noe minne allerede tildelt (hvis noen) i denne function.3. Gjør viktigste funksjon processing.If trinn 3 kommer til å være svært tidkrevende, sier mer enn 1 /10th av et sekund, er koden din bør sjekke abort status ved å ringe xlAbort periodically.StartupWhen Add-in først innført i Excel, hver av de eksporterte funksjoner må registreres. Dette innebærer å kalle Excel Register rutine for hver rutine. Det er åtte parametere som sendes som XlOpers.Parameter Type UseModule tekst String Fullt navn av DLL med pathProcedure String eller nummer Funksjon navn eller nummer til callType Tekst String Argument og returnere typesFunction Tekst String Function navn i funksjon WizardArgument Tekst String Valgfritt tekstlinje som beskriver parameterne i funksjon WizardMacro Type Number 0,1, eller 2Category String eller nummer kategori under hvilke fungere appearsShortcut tekstlinje Kun brukt for kommandoer, passere i null for functionThe viktigste parameteren for å registrere er teksttypen. Dette bruker bokstavene A-R til å representere returverdien og de medfølgende parametere. Verdier sendes som du forventer i en C Api ved henvisning (dvs. peker som alltid er en lpxloper) eller ved value.E.g. Excel regneark = MyFunction (a1: b1) passerer en referanse mens = InterestRate ("GBP") bruker en value.Example DLLName: = getName; //Funksjonen til å returnere navn /sti fra Excel pxModuleText.SetStr (s); //Note (1) pxProcedure.SetStr ('AddDate'); //Funksjon Navn pxTypeText.SetStr ('JJDD!'); //(2) Type Return = J, Input = JDD pxFunctionText.setStr ('AddDate'); //Navn i Fx Wizard pxArgumentText.SetStr ('Dato, Periode, Valuta'); //Parm tekst i FX Wiz pxMacrotype.SetNum (1); //Type = Sinmple funk (3) pxCategory.SetStr (AddInCategory); //Kategori for Func. veiv EResult: = Excel4V (xlfregister, @ res, 8, //Pass på 8 parms [pxModuletext.thelpxloper, pxProcedure.thelpxloper, pxTypeText.thelpxloper, pxFunctionText.thelpxloper, pxArgumentText.thelpxloper, pxMacroType.thelpxloper, pxCategory.thelpxloper, zlpxloper] ); //Null asm pop vasken; slutt; //Aldri Fjern Resultat: = AVKORT (res.val.num); //ID-koden (4) PX variablene er alle av txloper klasse som forenkler Initialiserer xlopers.Notes (1) DLLName og banen skal være hentet fra Excel, via XlGetName funksjons- du kan se dette som brukes i eksempelet kode. Ikke hardcode det som det inkluderer banen. (2) Se Register (side 219 i EDK) for utdypende informasjon Text Type. Den første parameteren er avkastningen parameter (J = 32 bit heltall) neste tre er innganger (JDD = Integer, String, String) og! betyr at Excel alltid kaller funksjonen når den beregner. Uten!, Excel kaller funksjonen en gang, låsene resultatet og bruker den låste resultatet ved senere samtaler. (3) Type 1 = Funksjon. Andre typer inkluderer unoterte funksjon (type 0) og kommandoer (type 2). Hvis du vil ha funksjoner som ikke møter opp i funksjonsveiviseren, bruker 0. (4) Etter vellykket registrering, inneholder den numeriske verdien i res (res.val.num) et heltall id kode for funksjons- håndtaket. Lagre dette og gi det til Avregistrer funksjonen når DLL er stengt. Glem dette og du har problemer med å bruke nyere versjoner av library..Getting verdiene fra en Excel SpreadsheetValues ​​kan sendes inn, i tre-ways.1. Som et pass-by-verdi. Eg = CalcMean (4,5,8); xltypenum eller xltypestr2. Som en enkel referanse, sier en celle a1 eller området A3: B56. xltypesref3. Som et sammensatt Reference. I utgangspunktet en samling av disjunkte cellereferanser. xltypemref1 og 2 er de mest vanlige. 3 er litt rart og mindre virkelig trengs, er det bedre å filtrere ut dette. Hvis du ønsker å bruke den, er inngangen en rekke cellereferanser (type 2), så du må bruke hver one.Excel vil filtrere datatypen hvis du spesifisere det (antall, string etc), men hvis du forventer et utvalg Da bør du fullt sjekke type og verdiområder, rapportering av feil hvis appropriate..Returning ErrorsYour funksjonen må returnere en lpxloper (type R) dersom du ønsker å returnere Excel Feilkoder. Hvis du vil angi en feil i Res (en xloper) bare dores.xltype: = xltypeerr; res.val.err: = nummer, //Returnerer følgende verdier så bare returnereres fra functionNumber Excel Err0 # NULL7 # DIV /015 # VALUE23 # REF29 # NAME36 # NUM42 # N /awith kompliserte, mange parameterfunksjoner Jeg tror at standard utmerke feil er litt uvennlig og så Jeg anbefaler sterkt en GetLastError () funksjon som returnerer den siste feilen strengen. Enhver funksjon som returnerer en feil bør sette feilstreng returnert av GetLastError (). Dette vil spare brukerne for mye tid når de bruker din fungerer for første time.Reading Cell ValuesHaving gått en cellereferanse (xltypeSref) du ønsker å få på verdiene i cellene. For å gjøre dette må du "tvinge" cellen referansen xloper. Dette tvinge (et Excel-funksjon) tvinger Excel å konstruere en vektor av xlopers, med nøyaktig (#Rows * #Cols) xlopers. Dvs. for en 2 x 3 matrise av celler, får du seks xlopers. Målet xloper blir en header med xltype feltet = 64 (xltypearray). Den val._array medlem inneholder antall rader og kolonner, og en peker til legemet xloper.These xlopers er anordnet i rekkefølge, slik at rad de seks celler i to rader med 3 kolonner lagres as1 2 34 5 6Each vil ha den grunnleggende type ( xltype num eller Str) og value.Example av CoercionDesttype.xltype: = xltypeInt; Desttype.val.w: = xltypeMulti; Eresult: = Excel4v (xlcoerce, @ XVerd, 2, [Verdier, @ desttype]); asm pop vasken; slutt; //Aldri fjerne xlopers /lpxlopers brukt her areDesttype - En xloper som spesifiserer tvang reisemålet type (xltypemulti- Utmerker navn for en rekke xlopers) Verdier - Den gikk i celle referanse- en lpxloperXval - Målet xloper. Etter en vellykket tvinge, dette er overskriften på en matrise. Med 2 x 3 matrise, vil det være seks xlopers, som hver eier en celle value.Excel har bevilget minne på dine vegne, og dette har å bli behandlet, men mer om det later..Example av å bruke verdiermed eksempel sjekker theif XVerd .val._array.rows < > en da begynne Error ('Skulle bare ha én rad'); goto myexit; enden, xlar: = xval.val._array.lparray; Indeks: = 0; for col: = 1 til xr.NumCols gjør begynne hvis xlar ^ [index] .xltype < > xltypenum deretter begynne Error ('Element' + inttostr (rad) + 'Ikke et nummer'); gå i stykker; slutt; Verdi [col]: = xlar ^ [index] .val.num; inc (indeks); ende, xlar er en peker til en rekke xlopers. I dette eksempel er dette kontrollerer at det er en rekke av ikke-numeriske data. Deretter kopierer verdiene inn i Verdi [] array.Putting verdier i Excel CellsAlthough det er en tilsvarende (slags) av xlcoerce, kalt xlset, kan det bare kalles fra en kommando (meny eller verktøylinje-knappen), og ikke fra en funksjon . Det er veldig anti sosial allikevel å bare dumpe en haug med verdier i et regneark det kan bare overskrive en morgen ulagret arbeid og vil ikke at forbedre din popularitet! En ikke så godt kjent funksjon i Excel heter Funksjons Arrays (eller formel arrays) er hva trengs. Hvis du ikke er kjent med dem, prøv dette på en tom Excel sheet.1. Velg et rektangulært område med musen. Nå klikker på redigeringslinjen (rett under verktøylinjene, over cellene) og skriv inn = g1. På dette punktet bør du se = g1 i redigeringslinjen og det valgte området bør fortsatt være valgt. Hvis du har fjernet det utvalget ved en feil, gå tilbake og prøve det again.2. Nå holder du nede ctrl og shift-tastene og trykk enter. De = g1 skal limes inn i alle cellene i den tidligere valgte area.You bør også legge merke til noen ting om dette hvis du klikker på en celle i denne area.1. Redigeringslinjen viser ligningen i brackets.2. Du kan ikke endre eller slette cell.3. Det gjorde ikke justere celle reference.This er den eneste måten (så vidt jeg kunne regne ut) for å sette verdier i Excel celler. Excel-funksjon må bygge opp en rekke xlopers, med overskriften peker til kroppen. Hvis funksjonen returnerer en matrise, må du bruke en funksjon Array for å vise resultatet. Excel er ganske flink med dette. Hvis du returnerer en 3 x 5 området og brukeren limer en funksjon Array inn en 4 x 6 rektangel, vil de ekstra cellene viser alle N /A.Memory ManagementIf en Excel4v samtale returnerer en xloper med en peker (strenger eller xltypemulti for eksempel) så, når koden er ferdig med verdien koden må alltid ringe xlfree på xloper. Faktisk som en generell regel, ringer xlfree på noen xloper gjør ingen skade på alt.Det er to minnetildeling tilfeller at koden MÅ handle..1. Du har kalt en rutine som returnerer en xloper med data i den, f.eks xlcoerce å konvertere en xltypesref /xltyperef til en xltypemulti (array). Excel tildeler sin egen hukommelse, og når du er ferdig med dataene, du bør eller i verdien $ 1000 (4096 desimal) til xltype- denne $ 1000 verdi er kjent som xlbitXLfree. Når du ringer xlfree, frigjør det opp "Excel tildelt 'memory.2. Hvis koden returnerer en matrise av xlopers som Excel viser som en funksjon array, du må eller i verdien $ 4000 (16384 desimal) til xltype feltet, før funksjons utganger. Når du har kopiert verdiene Excel vil gjøre en call-back til xlAutoFree funksjon (du gjorde gjennomføre en gjorde du ikke?) Med en lpxloper til dine data. Du kan deretter frigjøre den. Hvis du opprettet array med n elementer, i (n + 1) xlopers, hvor arrayname [0] er overskriften som peker til arrayname [1] deretter pekeren returnert poeng til arrayname [0] og FreeMem (ringe tilbake pekeren) vil deretter frigjøre riktig pointer.An eksempel Add-InThe eksempel følger med denne artikkelen er selvforsynt i ca 650 linjer med kode uten uten Delphi komponenter eller enheter som trengs. Det implementerer en kumulativ fordelingsfunksjon GetCDF som tar et tall i området -4 til 4 som input og returnerer høyden under ogive kurven. Jeg vet at Excel kommer med flere Normal fordelingsfunksjoner, men det fungerer som et eksempel. Det har blitt testet på Excel 95 og 97 med Delphi 3 på seier 95/98 og NT og viste seg å være bunnsolid. Jeg kan ikke understreke hvor viktig det er å sjekke alle innganger og prøve og få koden din så robust som mulig. Noe ekkel vil trolig bombe eller henge Excel og brukere vil raskt bli misbrukere. Ikke glem Stdcalls på alle eksporterte funksjoner! Bortsett fra den obligatoriske xlauto familie av funksjoner, det inkluderer fem andre funksjoner, hvorav to er usynlig. Disse to GetXlStack og FreeRAM er ment for bruk av utbygger bare. De andre tre (GetCDF, LastError og Version) er for brukeren. Du kan bruke begge typer funksjoner direkte, men bare synlige som vil bli sett i funksjonsveiviseren. Og ikke glem brakettene på funksjonskall. Excel vil gjerne ta = Versjon (uten ()) og returnere en verdi av -30408699 (jeg har ingen anelse om) når du faktisk mente = Versjon (). Jeg har tatt med bare de viktigste Excel-funksjon tallene som brukes i programmet, full liste har nesten 400. EDK har hel masse og inkluderer C overskrifter som lett kan edited.In mange måter er dette litt av en gammeldags, ikke-OOP program. Jeg valgte den måten opprinnelig som jeg følte min måte runde Excel-tillegg, og jeg hadde ikke lyst til å ha problemer med objekter på samme tid. Den eneste klassen jeg har brukt her er Txloper for å forenkle skape Xlopers men det var å holde det kortfattet. Send dine spørsmål og arbeids tilbud til [email protected] filen nedenfor er komplett - kilde til en dll. Kontroller at forlengelsen er XLL {$ 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} bibliotek cdfcalc, bruker SysUtils, vinduer, dialogbokser, skjemaer, klasser, Math; //XLREF struktur type xlref = pakket posten rwFirst: SMALLINT; rwLast: smallint; colFirst: byte; colLast: byte; slutt; //Returnerer en rekke utvalg XlRangeRecord = pakket posten Count: ord; //Skal alltid være $ 1 Sref: xlref; slutt; xlmref = pakket rekord count: ord; RefTbl: array [0..1000] av XlRef; slutt; lpxloper = ^ XLOPER; lpxloperArray = ^ XLArray; lpxlmref = ^ xlmref; TVal = pakket Record sak Byte 1: (num: Double); //XltypeNum 2: (str: ^ ShortString); //XltypeStr 3: (bool: Word); //XltypeBool 4: (err: Word); //XltypeErr 5: (w: Integer); //XltypeInt 6: (sref: pakket posten Count: ordet, ref: Xlref; end); 8: (_array: pakket Record //xltypeMulti lparray: lpxloperArray; rader: WORD; kolonner: WORD; End); 9: (mref: pakket posten //xltyperef lpmref: lpxlmref; idsheet: integer; End); Slutt; //Tval XLOPER = pakket Record val: TVal; xltype: WORD; dummy: array [0..5] i byte; //Filler End; xlarray = array [0..1000] av xloper; lpxlarray = ^ xlarray; txloper = klasse //Simple xloper støtte klasse privat fxloper: xloper; fActualStr: ShortString; funksjon Getlpxloper: lpxloper; offentlig konstruktør Opprett; Destructor Destroy; styre; Constructor Create_Str (NewStr: ShortString); Prosedyren SetStr (NewStr: ShortString); Prosedyren SetNum (NYTTNUMMER: Integer); Prosedyren SetInt (NYTTNUMMER: Integer); prosedyre SetErr; Eiendommen thelpxloper: lpxloper lese Getlpxloper; ende; //Excelfunction Excel4v (xlfn: ord; operRes: lpxloper; count: heltall; opers: array of lpxloper): integer; STDCALL; ekstern 'xlcall32.dll'; //XLMREF struktur Beskriver multippel rektangulær references.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 eller xltypeInt; //Feilkoder brukt for val.err innen XLOPER struktur xlerrNull = 0; xlerrDiv0 = 7; xlerrValue = 15; xlerrRef = 23; xlerrName = 29; xlerrNum = 36; xlerrNA = 42; //Returkoder xlretSuccess = 0; //Suksess xlretAbort = 1; //Makro stanset xlretInvXlfn = 2; //Ugyldig funksjon nummer xlretInvCount = 4; //Ugyldig antall argumenter xlretInvXloper = 8; //Ugyldig OPER struktur xlretStackOvfl = 16; //Stack overflow xlretFailed = 32; //Kommandoen mislyktes xlretUncalced = 64; //Uncalced celle //Funksjon antall bits xlCommand = $ 8000; xlSpecial = $ 4000; xlIntl = $ 2000; xlPrompt = $ 1000; //Funksjons tall xlFree = (0 eller xlspecial); xlStack = (1 eller xlspecial); xlCoerce = (2 eller xlspecial); xlSet = (3 eller xlspecial); xlSheetId = (4 eller xlspecial); xlSheetNm = (5 eller xlspecial); xlAbort = (6 eller xlspecial); xlGetInst = (7 eller xlspecial); xlGetHwnd = (8 eller xlspecial); xlGetName = (9 eller xlspecial); xlEnableXLMsgs = (10 eller xlspecial); xlDisableXLMsgs = (11 eller xlspecial); xlDefineBinaryName = (12 eller xlspecial); xlGetBinaryName = (13 eller xlspecial); //brukerdefinerte funksjoner, som trengs for å kalle Excel-funksjoner xlfCaller = 89; xlfRegister = 149; xlfUnregister = 201; //DLLversion: shortstring = 'CDF Calc v1.02'; AddInCategory = 'CDF Calculator'; konst zlpxloper = lpxloper (null); typen retarray = array [0..1000] av xloper; pretarray = ^ retarray; Var //Global data res: xloper; GetCDF_Id: Integer; xlStack_Id: Integer; EResult: Integer; vask: heltall; GetStack_Id: Integer; LastError_Id: Integer; FreeRam_Id: Integer; Version_Id: Integer; LastErrorxl: xloper; LastErrorStr: ShortString; BRC: integer; FuncName: String [64]; pxModuleText, pxProcedure, pxTypetext, pxFunctiontext, pxArgumentText, pxMacroType, pxCategory, pxShortcutText: txloper; HaveRegistered: boolean; xVerdi: xloper; prosedyre setxlcols (VAR hodet: rekke xloper, numRader, numcols: ord); begynne fillchar (head [0], sizeof (hode [0]), 0); fillchar (hodet [1], sizeof (hodet [1]), 0); head [0] .xltype: = 64; head [0] .val._array.rows: = numRader; //Hodet [0] .val._array.columns: = numcols; //Hodet [0] .val._array.lparray: =head [1]; ende; prosedyre setval (var v: xloper; numval: double), begynner fillchar (v, sizeof (v), 0); v.xltype: = 1; v.val.num: = numval; ende; Prosedyren SetFunctionName (S: String); begynne FuncName: = s; slutt; Prosedyren Error (S: ShortString); begynne Hvis LastErrorStr < > s så LastErrorStr: = FuncName + ':' + S; slutt; funksjon GetSheetName: ShortString; Var xres, xsheetname: xloper; ResStr: ShortString; begynne ResStr: = ''; Eresult: = Excel4V (xlfCaller, @ xres, 0, [null]); asm pop vasken; slutt; //Aldri Fjern hvis Eresult = 16 da resStr: = 'Ingen ID' annet begynne eresult: = Excel4V (xlsheetnm, @ xSheetname, 1, [@ Xres]); asm pop vasken; slutt; //Aldri Fjern hvis eresult = 0 da begynne ResStr: = xsheetname.val.str ^; end end; Eresult: = Excel4V (xlfree, nil, 1, [@ xres]); asm pop vasken; slutt; //Aldri Fjern Eresult: = Excel4V (xlfree, nil, 1, [@ xsheetname]); asm pop vasken; slutt; //Aldri Fjern Resultat: = ResStr; slutt; //Returnerer full bane & Navnet på DLL funksjon getName: ShortString; begynne EResult: = Excel4V (xlGetName, @ res, 1, [null]); asm pop vasken; slutt; //Aldri Fjern Resultat: = res.val.str ^; EResult: = Excel4V (xlfree, nil, 1, [@ res]); asm pop vasken; slutt; //Aldri Fjern slutten; CONST X1 = -4,0; //Venstre endepunkt X2 = + 4.0; //Høyre endepunkt NUMINV = 40000; //Antall incrementsTYPE Vector = array [-NUMINV..NUMINV] av Double, VAR K: integer; //Teller DELTA: Double; //Trinn størrelse X: Double; //Faktiske intervall punkt absissen: ^ VECTOR; //Vektor av verdiene i intervallet punkter FX: ^ VECTOR; //Vektor av verdiene av tetthetsfunksjonen CDF: VECTOR; //Vektor av verdiene for kumulativ tetthetsfunksjon //Genererer en verdi av standard gaussisk tetthetsfunksjonen} funksjonen f (x: Dobbel): Dobbelt; BEGIN F: = EXP (X * X /2) /SQRT (PI + PI); SLUTT; PROSEDYRE Gaussian; {Få normal tetthetsfunksjonen} BEGIN fillchar (CDF, ​​sizeof (ED), 0); cdf [0]: = 0,5; ED [1]: = 0.5; cdf [1]: = 0,5; DELTA: = NUMINV * 2; DELTA: = (X2-X1) /DELTA; {Høyest mulig skjermoppløsning} X: = X1-DELTA; K: = - NUMINV; Gjenta økningen (k); X: = X + DELTA; Abscissen ^ [K]: = X; {Verdier av X-aksene} FX ^ [K]: = F (X); {Verdier av Y-aksen} til K = NUMINV; SLUTT; prosedyre generateCDF; Konst gamma = 0.2316419; a1 = 0,319381530; a2 = -0,356563782; a3 = 1,781477937; a4 = -1,821255987; a5 = 1,330274429; VAR k1, k2, k3, k4, k5: DOUBLE; I: INTEGER; BEGIN nye (fx); nye (abscisse); gaussisk; FOR I: = 0 til NUMINV gjøre hvis abscisse ^ [I] > 0,0 da begynne k1: = 1,0 /(1,0 + gamma * absissen ^ [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); SLUTT; for i: = -NUMINV til -1 gjøre cdf [I]: = 1-ED [-i]; kast (abscisse); kast (fx); END; //skriv med -4 < x < 4.0function GetCDF (xd: double): Double, STDCALL, var x: Double, begynner x: = xd; hvis x > 4,0 deretter x: = 4,0; hvis x < -4,0 Deretter x: = - 4,0; Resultatet: = cdf [runde (x * 10000)]; ende; //Hovedfunksjon Funksjon Register_GetCDF: integer; Var s: Shortstring; begynne 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 vasken; slutt; //Aldri Fjern Resultat: = AVKORT (res.val.num); slutt; //Viser verdien av Excel Stack funksjon LastError: lpxloper; STDCALL; begynne LastErrorxl.xltype: = xltypestr; LastErrorxl.val.Str: = @ LastErrorStr; Resultatet: =LastErrorxl; slutt; Funksjon Register_LastError: integer; Var s: Shortstring; begynne 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 vasken; slutt; //Aldri Fjern Resultat: = AVKORT (res.val.num); slutt; //Eksportert Invisible Funksjon Viser verdien av Excel Stack funksjon GetXlStack: lpxloper; STDCALL; begynne EResult: = Excel4V (XlStack, @ res, 1, [null]); asm pop vasken; slutt; //Aldri Fjern Resultat: =res; slutt; Funksjon Register_GetXLStack: integer; Var s: Shortstring; begynne 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 = Usynlig, 1 = synlig 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 vasken; slutt; //Aldri Fjern Resultat: = AVKORT (res.val.num); slutt; //Eksportert Funksjon funksjon Versjon: lpxloper; STDCALL; begynne xvalue.xltype: = xltypeStr; xvalue.val.str: =DLLversion; Resultat: =xvalue; slutt; Funksjon Register_Version: integer; Var s: Shortstring; begynne Res.xltype: = xltypeerr; Res.val.err: = xlerrvalue; s: = getName; pxModuleText.SetStr (s); pxProcedure.SetStr ('versjon'); pxTypeText.SetStr ('R!'); pxFunctionText.setStr ('versjon'); 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 vasken; slutt; //Aldri Fjern Resultat: = AVKORT (res.val.num); slutt; //Eksportert Funksjon funksjon FreeRAM: integer; STDCALL; begynne Resultat: = GetHeapStatus.TotalFree; slutt; Funksjon Register_FreeRam: integer; Var s: Shortstring; begynne Res.xltype: = xltypeerr; Res.val.err: = xlerrvalue; s: = getName; pxModuleText.SetStr (s); pxProcedure.SetStr ('FreeRAM'); pxTypeText.SetStr ('J!'); pxFunctionText.setStr ('FreeRAM'); pxArgumentText.SetStr (''); pxMacrotype.SetNum (0); //0 = usynlig 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 vasken; slutt; //Aldri Fjern Resultat: = AVKORT (res.val.num); slutt; prosedyre Register_All; begynne hvis HaveRegistered og avslutter; HaveRegistered: = true; pxModuleText: = txloper.Create; pxProcedure: = txloper.Create; pxTypetext: = txloper.Create; pxFunctiontext: = txloper.Create; pxArgumentText: = txloper.Create; pxMacroType: = txloper.Create; pxCategory: = txloper.Create; pxShortCutText: = txloper.Create; GetCDF_ID: = register_GetCDF; GetStack_Id: = register_GetXlStack; FreeRam_Id: = register_FreeRam; LastError_Id: = register_LastError; slutt; slutt; slutt; slutt; slutt; slutt; slutt;



Previous:
Next Page: