7

I'm working on porting some classic VB6 code to C# and just stumbled across a usage of the PV function.

I feels wrong including a reference to the Microsoft.VisualBasic Assembly. Is this something that is commonly done, or should I explore further options. The next idea that pops into my mind is exploring this PV function in Reflector.

Christopher Bottoms
  • 11,218
  • 8
  • 50
  • 99
David
  • 19,389
  • 12
  • 63
  • 87

4 Answers4

11

The use of Microsoft.VisualBasic from C# and VB.NET has been discussed thoroughly under this question. The Microsoft.VisualBasic namespace is fully supported, and will be around as long as .Net is around. There's no reason to avoid it.

EDIT: It's telling that at the time of typing, the other answers for this question are an incorrect reimplementation of the function, and a one-man-band unsupported library from Code Galleries. Come on guys, it would take a real major event for Microsoft to drop the financial functions from VB.

It's a different story for Microsoft.VisualBasic.Compatibility, which is exclusively for use by the VB6 upgrade wizard, EDIT has now been marked obsolete in .Net 4 (my prediction came true), and should not be used for new development. There would be some advantages in removing references to this, but personally I'd probably try to achieve a fully working port first referencing.Net 3.5.

Community
  • 1
  • 1
MarkJ
  • 30,070
  • 5
  • 68
  • 111
  • 3
    Agree 100% with this. Where does this reluctance to use Microsoft's supported library come from? Is it just the "ewwww... it says VB" mentality? WTF? Microsoft wrote VB6, C#, and then provided (for free) the Microsoft.VisualBasic namespace for JUST THIS PURPOSE. And still people hesitate to use it. Whatever--Take your chances with some other "non-VB, therefore better" option. – JeffK Oct 01 '09 at 19:01
  • 1
    Just to add: At the end of the day, it's all IL. I can write stuff in C#, Visual Basic.NET, IronPython and Boo and throw it all into the Blender (=compilers) and retrieve IL that doesn't know what it was before. – Michael Stum Mar 22 '10 at 20:34
  • 5
    There is a stigma against using VB amongst C# developers and so because this have VisualBasic in the name they don't like it because they think they are programming in VB. Maybe MS should rename this to `Microsoft.ReallyUsefulAndFullySupportedFunctions` and everyone will be happy – Matt Wilko Jul 19 '12 at 08:03
3

Pretty straight forward to replicate in C#

    public static double PV(double Rate, int nPer, double Pmt, double FV, bool Type)
    {
        double ann = Math.Pow(1 + Rate, nPer);
        return -(FV + Pmt * (1 + (Type ? Rate : 0)) * ((ann - 1) / Rate)) / ann;
    }

Just a re-arrangement of the formula Microsoft provides.

JDunkerley
  • 12,355
  • 5
  • 41
  • 45
  • 4
    It's almost a rearrangement of Microsoft's formula, except when rate=0. That's when your version divides by zero, and VB6 and Microsoft.VisualBasic return `-fv -(pmt*nper)`. There are pitfalls even in coding up a formula from a webpage. This reinforces my answer - for pity's sake just **use Microsoft.VisualBasic** and move on to implement something other functionality for the poor old users. – MarkJ Sep 25 '09 at 08:08
1

You could use this library that duplicates excel functions in f#

Library

It has PV which is present value. I have used it once or twice. Just drop it in and add the reference.

Gratzy
  • 9,164
  • 4
  • 30
  • 45
  • 1
    hmmm seems kind of risky relying on a CTP language but I think I'd rather do that than reference the Microsoft.VisualBasic library – David Sep 24 '09 at 14:25
  • Exactly, when I've used it, it was to avoid excel automation and referencing Excel – Gratzy Sep 24 '09 at 14:26
  • The "NotStandAlone" version is almost 1 meg... almost tempted to just snag the PV function from Reflector, but I'll give this a shot – David Sep 24 '09 at 14:40
  • I prefer JDunkerley's solution - I'd rather add a 2 line function to my code rather than reference a whole assembly. – Tom Bushell Sep 24 '09 at 16:11
  • 1
    @Dave - -2 ( -1 because I don't agree, and another -1 because I'm a clueless SO noob and accidentally upvoted your comment, and can't undo it. Doh! ;-) Seriously, there's some good stuff in the VB libraries (Shapes, for example). I think it's short sighted to not take advantage because of anti-VB snobbery. – Tom Bushell Sep 24 '09 at 16:19
  • @Tom Bushell I agree in this case if the function is accurate however the library also offers other functions like YTM which is much more difficult to replicate and was what I needed at the time. – Gratzy Sep 24 '09 at 16:20
  • @Tom you've twisted my arm, I'll just use it. – David Sep 24 '09 at 17:55
  • So you suggest using a one-man-band unsupported library from Code Galleries, just to avoid using a fully supported core library from the .NET framework? And this has received upvotes? Stack Overflow has blown a fuse. (Using it to get YTM might make sense but that wasn't the question in this case.) – MarkJ Sep 25 '09 at 11:19
  • @MarkJ I'm not suggesting he doesn't use Microsoft.VisualBasic I simply pointed him to an alternative. Unless I'm mistaken I believe that was what he was asking for. I was pointed to that library myself from a similar question I posted. – Gratzy Sep 25 '09 at 12:44
  • Question was " Is this [avoiding Microsoft.VisualBasic] something that is commonly done, or should I explore further options". So if you point him to another library, you're implicitly advising removing Microsoft.VisualBasic. Or that's how I read it anyway. – MarkJ Sep 26 '09 at 07:14
0

I tried using the accepted answer, but I couldn't get it to work in .NET Core. I did some looking around and ran across this code on github that appears to be Microsoft's implementation of PV:

https://github.com/microsoft/referencesource/blob/master/Microsoft.VisualBasic/runtime/msvbalib/Financial.vb#L662

    Public Function PV(ByVal Rate As Double, ByVal NPer As Double, ByVal Pmt As Double, Optional ByVal FV As Double = 0, Optional ByVal Due As DueDate = DueDate.EndOfPeriod) As Double

        Dim dTemp As Double
        Dim dTemp2 As Double
        Dim dTemp3 As Double

        If Rate = 0.0# Then
            Return (-FV - Pmt * NPer)
        Else
            If Due <> 0 Then
                dTemp = 1.0# + Rate
            Else
                dTemp = 1.0#
            End If
            dTemp3 = 1.0# + Rate

            '       WARSI Using the exponent operator for pow(..) in C code of PV. Still got
            '       to make sure that they (pow and ^) are same for all conditions
            dTemp2 = dTemp3 ^ NPer

            'Do divides before multiplies to avoid OverFlowExceptions
            Return (-(FV + Pmt * dTemp * ((dTemp2 - 1.0#) / Rate)) / dTemp2)
        End If

    End Function

You'd still need to transpile it to C#. If I have a general enough implementation at the end of this I'll post that too.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Drew Delano
  • 1,421
  • 16
  • 21