Re: Extending T-SQL with COM

From: Tim (Tim_at_NoSpam)
Date: 06/13/04


Date: Mon, 14 Jun 2004 11:39:44 +1200

Bob,

Using Excel for this is an extremely heavy weight way of performing what
should be an otherwise simple function. IE load and call Excel @ humpteen
megabytes to call one function of a few kbytes at most in size.

I would suggest you look at using a purpose built COM object instead. Visual
Basic includes the PMT function along with many others that may be useful to
you in financials. It would take a VB programmer only a few minutes to write
a COM object to expose the PMT function via COM. (I have one here).

Similarly you could code it as an extended stored procedure writing the ext
proc in C, but then it may be best to re-write the PMT function manually in
C. This would take a lot longer but would result in a very tiny memory foot
print / extremely fast executing ext proc (milliseconds at most ).

The attached zip file contains a simple vb project that produces a DLL
containing 1 function PMTIF and is executed as detailed below. Don't forget
to regsvr32 the dll before use.

declare @rate float
declare @nPer float
declare @pv float
declare @fv float
declare @due float
declare @ret float
declare @fh int
declare @hr int

EXEC @hr = sp_oaCreate 'MyPMT.SimplePMT', @fh output, 1
if @hr <> 0
BEGIN
 EXEC sp_OAGetErrorInfo @fh
 RETURN
END
else
BEGIN

set @rate = 0.0088
set @nPer = 10.0
set @pv = 1000
set @fv = 50000
set @due = 0

EXEC @hr = sp_oaMethod @fh, 'PMTIF', @ret out, @rate, @nPer, @pv, @fv, @due
if @hr <> 0
BEGIN
 EXEC sp_OAGetErrorInfo @fh --, @src OUT, @desc OUT
     RETURN
END

SELECT 'HR = ' + convert(varchar(12), @hr)
SELECT 'Ret = ' + convert(varchar, @ret)

EXEC @hr = sp_oaDestroy fh
END

- Tim

"Bob Zagars" <Bob Zagars@discussions.microsoft.com> wrote in message
news:22039BAB-10DD-4D9E-9EED-A7B113BF37AF@microsoft.com...
>I am trying to use Excel financial formulas in a stored procedure and can
>not resolve a problem.
>
> I read an White Paper article by Dan Jurden that showed how to use the PMT
> function in Excel which seemed logical to fit my needs for a project I
> have to develop.
>
> I used primary all the syntax and can not get past an error by the system.
> I wrote an extended error display procedure to know as much information as
> possible. My code which you can copy/paste is.
> ***************************************************
> IF Exists( SELECT *
> FROM sysobjects
> WHERE id = object_id(N'dbo.sp_payment')
> AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
> DROP PROCEDURE dbo.sp_payment
> GO
>
> SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON
> GO
>
> CREATE PROCEDURE dbo.sp_payment
> @MemberID int
>
> AS
> /****************************************************************************************
> /
> / Procedure: dbo.sp_payment
> /
> / Author: Bob Zagars
> /
> / Version: 1.0
> /
> / Creation Date: June 11, 2004
> /
> / Arguments: None
> /
> / Return: None
> /
> / ResultSet: None
> /
> / Description: This procedure uses Excel to compute a financial
> formula using COM
> / objects.
> /
> */
> /***************************************************************************************/
> /* Copyright © 2004 Zagars & Evans, Inc. All rights reserved. Any
> distribution */
> /* of the source code by other than Zagars & Evans, Inc is
> prohibited. */
> /***************************************************************************************/
> BEGIN
>
> SET NOCOUNT ON
>
> DECLARE @ProcName varchar(20),
> @Rate numeric(6,4),
> @Term int,
> @Principal int,
> @Object int,
> @Formula char(50),
> @Workbooks int,
> @Workbook int,
> @Hr int,
> @Result float,
> @Output varchar(255)
>
> SET @ProcName = 'sp_payment'
>
> EXEC @Hr = sp_OACreate 'Excel.Application', @Object OUT
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10001
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> EXEC @Hr = sp_OAGetProperty @Object, 'workbooks', @Workbooks OUT
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10002
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> EXEC @Hr = sp_OAMethod @Workbooks, 'Add'
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10003
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> SET @Term = 48
>
> SELECT @Rate = interest_rate,
> @Principal = balance
> FROM dbo.LOANS
> WHERE member_id = 1
> AND seq = 3
>
> SET @Formula = '=pmt (' + Convert(char(10), @Rate) + ',' +
> Convert(char(3), @Term) + Convert(char(10), @Principal) + ')*-1'
>
> EXEC @Hr = sp_OASetProperty @Object, 'Active***.range("a1").formula',
> @Formula
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10004
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> EXEC @Hr = sp_OAGetProperty @Object, 'Active***.range("a1").formula',
> @Result OUT
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10005
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> EXEC @Hr = sp_OASetProperty @Object, 'displayalerts', 'false'
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10006
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> EXEC @Hr = sp_OAMethod @Object, 'quit'
>
> IF @Hr <> 0
> BEGIN
> EXEC sp_DisplayOAErrorInfo @Object, @Hr, 10007
>
> EXEC sp_OADestroy @Object
>
> RETURN
> END
>
> EXEC sp_OADestroy @Object
>
> SELECT @Result AS payment
>
>
> END
> GO
>
> GRANT EXECUTE ON dbo.sp_payment TO Public
> GO
>
> SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON
> GO
>
> ******************************************************
>
> IF Exists( SELECT *
> FROM sysobjects
> WHERE id = object_id(N'dbo.sp_hexadecimal')
> AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
> DROP PROCEDURE dbo.sp_hexadecimal
> GO
>
> SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON
> GO
>
> CREATE PROCEDURE dbo.sp_hexadecimal
> @binvalue varbinary(255),
> @hexvalue varchar(255) OUTPUT
> AS
> /****************************************************************************************
> /
> / Procedure: dbo.sp_hexadecimal
> /
> / Author: Bob Zagars
> /
> / Version: 1.0
> /
> / Creation Date: June 10, 2004
> /
> / Arguments: None
> /
> / Return: None
> /
> / ResultSet: None
> /
> / Description:
> /
> */
> /***************************************************************************************/
> /* Copyright © 2004 Zagars & Evans, Inc. All rights reserved. Any
> distribution */
> /* of the source code by other than Zagars & Evans, Inc is
> prohibited. */
> /***************************************************************************************/
> BEGIN
>
> SET NOCOUNT ON
>
> DECLARE @ProcName varchar(20)
> DECLARE @charvalue varchar(255)
> DECLARE @i int
> DECLARE @length int
> DECLARE @hexstring char(16)
>
> SET @ProcName = 'sp_hexadecimal'
>
> SELECT @charvalue = '0x'
> SELECT @i = 1
> SELECT @length = DATALENGTH(@binvalue)
> SELECT @hexstring = '0123456789abcdef'
>
> WHILE (@i <= @length)
> BEGIN
> DECLARE @tempint int
> DECLARE @firstint int
> DECLARE @secondint int
> SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
> SELECT @firstint = FLOOR(@tempint/16)
> SELECT @secondint = @tempint - (@firstint*16)
> SELECT @charvalue = @charvalue + SUBSTRING(@hexstring, @firstint+1,
> 1) + SUBSTRING(@hexstring, @secondint+1, 1)
> SELECT @i = @i + 1
> END
>
> SELECT @hexvalue = @charvalue
>
> END
> GO
>
> GRANT EXECUTE ON dbo.sp_hexadecimal TO Public
> GO
>
> SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON
> GO
>
> *******************************************************
>
> IF Exists( SELECT *
> FROM sysobjects
> WHERE id = object_id(N'dbo.sp_displayoaerrorinfo')
> AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
> DROP PROCEDURE dbo.sp_displayoaerrorinfo
> GO
>
> SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON
> GO
>
> CREATE PROCEDURE dbo.sp_displayoaerrorinfo
> @object int,
> @hresult int,
> @ErrorID int
>
> AS
> /****************************************************************************************
> /
> / Procedure: dbo.sp_DisplayOAErrorInfo
> /
> / Author: Bob Zagars
> /
> / Version: 1.0
> /
> / Creation Date: June 10, 2004
> /
> / Arguments: None
> /
> / Return: None
> /
> / ResultSet: None
> /
> / Description: This procedure displays the HEX COM handle and error
> code
> /
> */
> /***************************************************************************************/
> /* Copyright © 2004 Zagars & Evans, Inc. All rights reserved. Any
> distribution */
> /* of the source code by other than Zagars & Evans, Inc is
> prohibited. */
> /***************************************************************************************/
> BEGIN
>
> SET NOCOUNT ON
>
> DECLARE @ProcName varchar(20)
> DECLARE @output varchar(255)
> DECLARE @hrhex char(10)
> DECLARE @hr int
> DECLARE @source varchar(255)
> DECLARE @description varchar(255)
> DECLARE @HelpFile varchar(255)
> DECLARE @HelpID int
>
> SET @ProcName = 'sp_displayoaerrorinfo'
>
> PRINT 'OLE Automation Error Information'
>
> EXEC sp_hexadecimal @hresult, @hrhex OUT
>
> SELECT @output = ' HRESULT: ' + @hrhex
>
> PRINT @output
>
> EXEC @hr = sp_OAGetErrorInfo @object, @source OUT, @description OUT,
> @HelpFile OUT, @HelpID OUT
>
> IF @hr = 0
> BEGIN
> SELECT @output = ' Source: ' + @source
> PRINT @output
> SELECT @output = ' Description: ' + @description
> PRINT @output
> SELECT @output = ' Help File: ' + @HelpFile
> PRINT @output
> SELECT @output = ' Help ID: ' + Convert( varchar(255), @HelpID )
> PRINT @output
> SELECT @output = ' Section Error Code ID: ' + Convert(
> varchar(255), @ErrorID )
> PRINT @output
> END
> ELSE
> BEGIN
> PRINT ' sp_OAGetErrorInfo failed.'
> RETURN
> END
>
> END
> GO
>
> GRANT EXECUTE ON dbo.sp_displayoaerrorinfo TO Public
> GO
>
> SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON
> GO
>
> ********************************************************
>
> The error I am receiving is:
>
> OLE Automation Error Information
> HRESULT: 0x80042732
> Source: ODSOLE Extended Procedure
> Description: Output values of type Object are not allowed in result sets.
>
> Help ID: 0
> Section Error Code ID: 10003
>
> *****************************************************
>
> I have search for answer to this error code but have not found anything.
> I do not know if it is COM or SQL Server 2000 that is causing the problem.
> Can anyone give me a suggestion on how to resolve this problem?
>
> Bob Zagars
> Software Engineer
> Zagars & Evans, Inc.

begin 666 SimplePMT.zip
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
M(4 AI;@B-H6.!%,H:2L8-QIW;GT(G\8'<.&SB&>&,D)AH2<]?_]^<SKWDA"
MUZ^/]*<`L 4L!(D8NJL#CW=,`W--&']O8*;QD0S2O&]':Y.Z:\P7`68B#9$+
M^J9C3!@M"7GYOQ @`$&H=;I]DU3+JF28)N1,,ZOWZCW3T@W9&M+O*^)F3=UQ
M*LT[TG(I44B[X[C$KA%[0&Q*ZCU[EM%5!3##L(<:9$[T9AF&*.H2<S&Z$\PE
M49>9.T9=9R[%E&;<VZDPW2M882Z!NLE<#G65.3KF`?,`^]GSADH<M\&7^.LD
M\M"/P4XD[,T.O-%'XG:YT[(MQ[IUQ9AR*)8*<A'2+:O;ESK&2 S!:$3_F#Y5
M@?7A/,IZEP!4.;';_0%MCTV1<55RB@PK-EZ'/"=1.8YQ`C<^<@H]'SF#9Q])
MP!LG-%)3IQU@NCM'CN9(:(9\HRXZX3_>C)G;I&FX_]JBWGC+XGK?2)PK_EX*
MY6I%4;7<92VK%*IJ1='XD6.K7"^5YDO@B=>,*]1\72YJN8R:@1]02P,$% ``
M``@`#%C.,"T`#RN.`@``0@H```T```!3:6UP;&50350N;&EBQ5;-;M- $!X[
M3O-30!%P!4S50^DA=9WF!X%02H(@:O[D)%P=-S%MD!M73H C4F](/ A''H!#
M#QPYY,"!`ZH03Y W".NUU[&==9I (U::W=GQYYW9;V:]OO]8,3K'3^([O+?M
M"KGL;B:;$=->NV"/XL.<K;7C`+ .P%X`A,<`D6V V,B2Z-B26-N2Z)DILERJ
MU&M24RX^:Q2D4KU9D^1&[^144^N5)LARM54NST+@O8.Q$,T7K>J!7-QO[D-1
MTUI]0SWJ#8:JT5"-MZJ!UD%PF?8$V9ZKPX*F# :UP]=J9SC%^NS((@6L*LVL
M65#ZK;ZF*]VJ_FZ*\UB793DE3%F.()HO6(!Q&& ;348QI$<!VF@\B^(40 3"
ML 8<,, Z>F@FMD7V26?TK_)&IR*(\B""@],YIRZ<)\FNINU<SG=6S#A\EYD0
M?/CY+3]F4,TB;G\!,.O,&LQM"20H1YP]Y2B0$ $FW*,S_->6[*J';XXV&V1>
M1*(Q7DP>$D^3O:XR5#9%8KN-Y#/"?;6Q(8P3SFU<AN!N(/GMPEGK\><L7B.&
MY]<]2=N"6XD($-8`3/XG_,U*KV/H`_W5D-^2'O#E4O6 NI]K]IL1/..P9O(<
MQIK'$>0[^LDI"GC"<S"9$(\D@RP6LN\\`([Y&-P[#&&Q+7LF!MR8]-1BM@U7
MG"SN'WDL+U%_]5_*94^$F$ZY3@2+3\07)V)@:!73]67!53$I8C,KYM,,3EA9
M)2R2W3N8\0!.XTLSEW,S9WU+?ES"W,=@YM+$9L8\HC!'ZLZ-^[YBAA=A]1[J
MYQ3DTKRFB8+_/$RO9<;D]J[MVW_1>$_YTMY$NC?>3*'ES7>!K<X?:_GS78S_
MZ&^/[F\#UP%'_0_P>OP#4$L#!!0````(`+M<SC"+%<GSBP```+X````,````
M35-30T-04DHN4T-#;8[!"H,P$$3O0OYAO\ OJ(7BV1*H-RDAC6M5- F;3:E_
MWZ2!G@K##"S,VQEN;7L75?*FGY<`21J"BV00C!NS62:WP;1L**JA.V37UZ^'
M+R4ER:UH6%WUC@UG@B^73+*.(=H1Z1^Q]"_QK:3FN3G]WEO W?,!@6FQ3Y@<
M`<\(>PC&>%KK%-\U9U%]`%!+`P04````" "[7,XP6!+8Z<0!``#E`@``"0``
M`$UY4$U4+G9B<%U2RVZ;0!3=6^(?++Q)*A5A'&71BD4*=HM4'BK4J52Z&.#:
MGG0>:&9P[%;]]\X%UU&*$#KWG#OW<8;JW$.8,X@9<V81(UJ')>4]@R*MWL^O
MT&N9=F9?8 <*1 OAF_KC;]_W`_]NY;^UX/*)_J'IN;O_LP@\?^$O/*^V[V.2
MQ?EC69=G;8"O@EJ;3C((/,.:1?YY/7\8C.3$4"F<66F(,D,?NC>9%'#K.K/U
M"3+"816$[LM@'6-6BB3G1'0HV0BS0C<]6]U&GX#UD10&3B:)0]>?TGO;IF&0
MRLZF+E]QZV]K+!2]JRO0IK[VJO_OFI(GJ;:@PJ7%5$S81Y^.5-LE+B%NE8A6
M`0=A+EP)Z@BJ'/I>*K.A##2R5L1SXRCB/*VQ5GMI#;M,2-EH3X779@_DO:&<
M_GK%;<A1JL*VH@,OE+PQ_!;IR&ZZI? <0S/L$[&32&;R@5&BJ=AC]$$.HM/1
M`=J?8W$[X8[)YRNQ886DPKS$<;*]!E^%PN/0;8IQ0;R^T=TE:L080'&RQQ J
M)EP=%)"N`)4W3] :I%)RR@;>6&HWJ1I+3- .BC49,L[L>UK.*T6$)BT:,)],
M_3$Y;G]6!?J =_,74$L!`A0`"@``````O%S.,(X<CA<A````(0````D`````
M`````0`@( ```````$UY4$U4+G9B=U!+`0(4`!0````(``-8SC "VU1!7 $`
M`*<"```-``````````$`(" ``$@```!3:6UP;&50350N8VQS4$L!`A0`% ``
M``@`#%C.,'=B"(0I# ```% ```T````````````@( ``SP$``%-I;7!L95!-
M5"YD;&Q02P$"% `4````" `,6,XP4=1$^ZH!``#2`P``#0```````````" @
M```C#@``4VEM<&QE4$U4+F5X<%!+`0(4`!0````(``Q8SC M``\KC@(``$(*
M```-````````````(" ``/@/``!3:6UP;&50350N;&EB4$L!`A0`% ````@`
MNUS.,(L5R?.+````O@````P``````````0`!````L1(``$U34T-#4%)*+E-#
M0U!+`0(4`!0````(`+M<SC!8$MCIQ $``.4"```)``````````$`(" ``&83
A``!->5!-5"YV8G!02P4&``````<`!P"4`0``414`````
`
end


Loading