vb6parse 1.0.0

vb6parse is a library for parsing and analyzing VB6 code, from projects, to controls, to modules, and forms.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="VB6Parse Library Reference - npv - Financial">
    <title>npv - Financial - VB6Parse Library Reference</title>
    <link rel="stylesheet" href="../../../assets/css/style.css">
    <link rel="stylesheet" href="../../../assets/css/docs-style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
    <script src="../../../assets/js/theme-switcher.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/vbnet.min.js"></script>
    <script>hljs.highlightAll();</script>
</head>
<body>
    <header class="docs-header">
        <div class="container">
            <h1><a href="../../../index.html">VB6Parse</a> / <a href="../../../library/index.html">Library</a> / <a href="../../../library/functions/financial/index.html">Financial</a> / npv</h1>
            <p class="tagline">VB6 Library Reference</p>
        </div>
    </header>

    <nav class="docs-nav">
        <div class="container">
            <a href="../../../index.html">Home</a>
            <a href="../../../library/index.html">Library Reference</a>
            <a href="../../../documentation.html">Documentation</a>
            <a href="https://docs.rs/vb6parse" target="_blank">API Docs</a>
            <a href="https://github.com/scriptandcompile/vb6parse" target="_blank">GitHub</a>
            <button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
                <span class="theme-icon">🌙</span>
            </button>
        </div>
    </nav>

    <main class="container">
        
        <article class="library-item">
            <h1 id="npv-function">NPV Function</h1>
<p>Returns a Double specifying the net present value of an investment based on a series of periodic cash flows (payments and receipts) and a discount rate.</p>
<h2 id="syntax">Syntax</h2>
<pre><code class="language-vbnet">NPV(rate, values())</code></pre>
<h2 id="parameters">Parameters</h2>
<ul>
<li><strong>rate</strong> (Required) - Double specifying discount rate over the length of the period, expressed as a decimal. For example, use 0.10 for 10 percent.</li>
<li><strong><code>values()</code></strong> (Required) - Array of Double specifying cash flow values. The array must contain at least one negative value (a payment) and one positive value (a receipt). The values must be equally spaced in time and occur at the end of each period.</li>
</ul>
<h2 id="return-value">Return Value</h2>
<p>Returns a <strong>Double</strong> specifying the net present value of the investment.</p>
<h2 id="remarks">Remarks</h2>
<p>The NPV (Net Present Value) function calculates the present value of a series of future cash flows, discounted at a specified rate. It's a fundamental tool in capital budgeting and investment analysis.</p>
<h3 id="key-characteristics">Key Characteristics:</h3>
<ul>
<li>Returns present value of future cash flows</li>
<li>All cash flows must be equally spaced in time</li>
<li>Cash flows occur at the end of each period</li>
<li>First cash flow (period 0) is NOT included - use separate calculation for initial investment</li>
<li>Negative values represent cash outflows (payments)</li>
<li>Positive values represent cash inflows (receipts)</li>
<li>Rate should match the period of cash flows (e.g., monthly rate for monthly cash flows)</li>
<li>Higher discount rates result in lower NPV</li>
<li>NPV &gt; 0 generally indicates a good investment</li>
<li>NPV = 0 means investment breaks even</li>
<li>NPV &lt; 0 indicates investment loses money</li>
</ul>
<h3 id="important-note-on-initial-investment">Important Note on Initial Investment:</h3>
<p>Unlike some implementations, VB6's NPV does NOT include an initial investment (period 0) in the values array.
If you have an initial investment, subtract it from the NPV result:</p>
<pre><code class="language-vbnet">netPV = NPV(rate, cashFlows()) - initialInvestment</code></pre>
<h3 id="common-use-cases">Common Use Cases:</h3>
<ul>
<li>Capital budgeting decisions</li>
<li>Investment project evaluation</li>
<li>Equipment purchase analysis</li>
<li>Real estate investment analysis</li>
<li>Business valuation</li>
<li>Compare alternative investments</li>
<li>Determine project profitability</li>
<li>Calculate present value of future revenues</li>
</ul>
<h2 id="typical-uses">Typical Uses</h2>
<ol>
<li><strong>Investment Evaluation</strong> - Determine if an investment is worthwhile</li>
<li><strong>Project Comparison</strong> - Compare multiple investment opportunities</li>
<li><strong>Capital Budgeting</strong> - Decide which projects to fund</li>
<li><strong>Equipment Purchases</strong> - Evaluate equipment vs. leasing decisions</li>
<li><strong>Real Estate</strong> - Analyze property investment returns</li>
<li><strong>Business Acquisition</strong> - Value businesses based on projected cash flows</li>
<li><strong>Cost-Benefit Analysis</strong> - Compare costs and benefits over time</li>
<li><strong>Break-even Analysis</strong> - Find discount rate where NPV = 0 (IRR)</li>
</ol>
<h2 id="basic-examples">Basic Examples</h2>
<pre><code class="language-vbnet">&#x27; Example 1: Simple investment with 5-year cash flows
Dim cashFlows(1 To 5) As Double
Dim npvResult As Double
Dim initialInvestment As Double
initialInvestment = 10000
cashFlows(1) = 3000
cashFlows(2) = 3000
cashFlows(3) = 3000
cashFlows(4) = 3000
cashFlows(5) = 3000
&#x27; Calculate NPV at 10% discount rate
npvResult = NPV(0.1, cashFlows) - initialInvestment
&#x27; Result: approximately $1,372 (good investment)</code></pre>
<pre><code class="language-vbnet">&#x27; Example 2: Evaluate equipment purchase
Dim savings(1 To 3) As Double
Dim equipmentCost As Double
Dim netValue As Double
equipmentCost = 5000
savings(1) = 2000 &#x27; Year 1 savings
savings(2) = 2500 &#x27; Year 2 savings
savings(3) = 3000 &#x27; Year 3 savings
netValue = NPV(0.08, savings) - equipmentCost
If netValue &gt; 0 Then
    MsgBox &quot;Good investment: NPV = $&quot; &amp; Format(netValue, &quot;#,##0.00&quot;)
End If</code></pre>
<pre><code class="language-vbnet">&#x27; Example 3: Compare two projects
Dim project1(1 To 4) As Double
Dim project2(1 To 4) As Double
Dim npv1 As Double, npv2 As Double
&#x27; Project 1: Higher initial investment, steady returns
project1(1) = 4000: project1(2) = 4000: project1(3) = 4000: project1(4) = 4000
npv1 = NPV(0.1, project1) - 12000
&#x27; Project 2: Lower investment, increasing returns
project2(1) = 2000: project2(2) = 3000: project2(3) = 4000: project2(4) = 5000
npv2 = NPV(0.1, project2) - 10000
If npv2 &gt; npv1 Then
    MsgBox &quot;Project 2 has better NPV&quot;
End If</code></pre>
<pre><code class="language-vbnet">&#x27; Example 4: Real estate investment analysis
Dim rentalIncome(1 To 10) As Double
Dim purchasePrice As Double
Dim i As Integer
purchasePrice = 200000
&#x27; Annual rental income for 10 years
For i = 1 To 10
    rentalIncome(i) = 24000 &#x27; $2,000/month
Next i
Dim propertyNPV As Double
propertyNPV = NPV(0.08, rentalIncome) - purchasePrice
MsgBox &quot;Property NPV: $&quot; &amp; Format(propertyNPV, &quot;#,##0.00&quot;)</code></pre>
<h2 id="common-patterns">Common Patterns</h2>
<pre><code class="language-vbnet">&#x27; Pattern 1: Basic NPV calculation with initial investment
Function CalculateInvestmentNPV(initialCost As Double, _
                               cashFlows() As Double, _
                               discountRate As Double) As Double
    CalculateInvestmentNPV = NPV(discountRate, cashFlows) - initialCost
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 2: Investment decision helper
Function ShouldInvest(initialInvestment As Double, _
                     cashFlows() As Double, _
                     requiredReturn As Double) As Boolean
    Dim npvResult As Double
    npvResult = NPV(requiredReturn, cashFlows) - initialInvestment
    ShouldInvest = (npvResult &gt; 0)
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 3: Sensitivity analysis
Sub AnalyzeNPVSensitivity(initialCost As Double, cashFlows() As Double)
    Dim rate As Double
    Dim npvResult As Double
    Debug.Print &quot;NPV Sensitivity Analysis&quot;
    Debug.Print String(40, &quot;-&quot;)
    For rate = 0.05 To 0.20 Step 0.01
        npvResult = NPV(rate, cashFlows) - initialCost
        Debug.Print Format(rate * 100, &quot;0.0&quot;) &amp; &quot;%: $&quot; &amp; Format(npvResult, &quot;#,##0.00&quot;)
    Next rate
End Sub</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 4: Profitability Index
Function CalculateProfitabilityIndex(initialInvestment As Double, _
                                     cashFlows() As Double, _
                                     discountRate As Double) As Double
    Dim presentValue As Double
    presentValue = NPV(discountRate, cashFlows)
    If initialInvestment = 0 Then
        CalculateProfitabilityIndex = 0
    Else
        CalculateProfitabilityIndex = presentValue / initialInvestment
    End If
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 5: Compare multiple projects
Function SelectBestProject(projects As Collection, discountRate As Double) As String
    Dim project As Variant
    Dim bestNPV As Double
    Dim bestProject As String
    Dim currentNPV As Double
    bestNPV = -999999
    For Each project In projects
        currentNPV = NPV(discountRate, project.CashFlows) - project.InitialCost
        If currentNPV &gt; bestNPV Then
            bestNPV = currentNPV
            bestProject = project.Name
        End If
    Next project
    SelectBestProject = bestProject
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 6: Break-even discount rate (approximation of IRR)
Function FindBreakEvenRate(initialInvestment As Double, _
                          cashFlows() As Double) As Double
    Dim rate As Double
    Dim npvResult As Double
    Dim increment As Double
    increment = 0.001
    For rate = 0 To 1 Step increment
        npvResult = NPV(rate, cashFlows) - initialInvestment
        If npvResult &lt;= 0 Then
            FindBreakEvenRate = rate
            Exit Function
        End If
    Next rate
    FindBreakEvenRate = -1 &#x27; Not found
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 7: NPV with growing cash flows
Function NPVWithGrowth(initialInvestment As Double, _
                       firstYearCashFlow As Double, _
                       growthRate As Double, _
                       years As Integer, _
                       discountRate As Double) As Double
    Dim cashFlows() As Double
    Dim i As Integer
    ReDim cashFlows(1 To years)
    For i = 1 To years
        cashFlows(i) = firstYearCashFlow * ((1 + growthRate) ^ (i - 1))
    Next i
    NPVWithGrowth = NPV(discountRate, cashFlows) - initialInvestment
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 8: Payback period with NPV
Function CalculateDiscountedPayback(initialInvestment As Double, _
                                    cashFlows() As Double, _
                                    discountRate As Double) As Double
    Dim i As Integer
    Dim cumulativeNPV As Double
    Dim periodCashFlows() As Double
    For i = LBound(cashFlows) To UBound(cashFlows)
        ReDim periodCashFlows(LBound(cashFlows) To i)
        Dim j As Integer
        For j = LBound(cashFlows) To i
            periodCashFlows(j) = cashFlows(j)
        Next j
        cumulativeNPV = NPV(discountRate, periodCashFlows) - initialInvestment
        If cumulativeNPV &gt;= 0 Then
            CalculateDiscountedPayback = i
            Exit Function
        End If
    Next i
    CalculateDiscountedPayback = -1 &#x27; Never pays back
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 9: NPV with terminal value
Function NPVWithTerminalValue(initialInvestment As Double, _
                              cashFlows() As Double, _
                              terminalValue As Double, _
                              discountRate As Double) As Double
    Dim i As Integer
    Dim modifiedCashFlows() As Double
    ReDim modifiedCashFlows(LBound(cashFlows) To UBound(cashFlows))
    For i = LBound(cashFlows) To UBound(cashFlows) - 1
        modifiedCashFlows(i) = cashFlows(i)
    Next i
    &#x27; Add terminal value to final period
    modifiedCashFlows(UBound(cashFlows)) = cashFlows(UBound(cashFlows)) + terminalValue
    NPVWithTerminalValue = NPV(discountRate, modifiedCashFlows) - initialInvestment
End Function</code></pre>
<pre><code class="language-vbnet">&#x27; Pattern 10: Risk-adjusted NPV
Function RiskAdjustedNPV(initialInvestment As Double, _
                        expectedCashFlows() As Double, _
                        riskFreeRate As Double, _
                        riskPremium As Double) As Double
    Dim adjustedRate As Double
    adjustedRate = riskFreeRate + riskPremium
    RiskAdjustedNPV = NPV(adjustedRate, expectedCashFlows) - initialInvestment
End Function</code></pre>
<h2 id="advanced-usage">Advanced Usage</h2>
<h3 id="example-1-investment-analyzer-class">Example 1: Investment Analyzer Class</h3>
<pre><code class="language-vbnet">&#x27; Class: InvestmentAnalyzer
&#x27; Comprehensive investment analysis with NPV and related metrics
Option Explicit
Private m_initialInvestment As Double
Private m_cashFlows() As Double
Private m_discountRate As Double
Public Sub Initialize(initialInvestment As Double, _
                     cashFlows() As Double, _
                     discountRate As Double)
    m_initialInvestment = initialInvestment
    m_cashFlows = cashFlows
    m_discountRate = discountRate
End Sub
Public Function GetNPV() As Double
    GetNPV = NPV(m_discountRate, m_cashFlows) - m_initialInvestment
End Function
Public Function GetProfitabilityIndex() As Double
    Dim pvCashFlows As Double
    pvCashFlows = NPV(m_discountRate, m_cashFlows)
    GetProfitabilityIndex = pvCashFlows / m_initialInvestment
End Function
Public Function IsAcceptable() As Boolean
    IsAcceptable = (GetNPV() &gt; 0)
End Function
Public Function GetApproximateIRR() As Double
    Dim rate As Double
    Dim npvResult As Double
    Dim lastRate As Double
    Dim lastNPV As Double
    &#x27; Binary search for IRR
    Dim lowRate As Double, highRate As Double
    lowRate = 0
    highRate = 1
    Do While (highRate - lowRate) &gt; 0.0001
        rate = (lowRate + highRate) / 2
        npvResult = NPV(rate, m_cashFlows) - m_initialInvestment
        If npvResult &gt; 0 Then
            lowRate = rate
        Else
            highRate = rate
        End If
    Loop
    GetApproximateIRR = rate
End Function
Public Function GenerateReport() As String
    Dim report As String
    Dim npvValue As Double
    Dim pi As Double
    Dim irr As Double
    npvValue = GetNPV()
    pi = GetProfitabilityIndex()
    irr = GetApproximateIRR()
    report = &quot;Investment Analysis Report&quot; &amp; vbCrLf
    report = report &amp; String(50, &quot;=&quot;) &amp; vbCrLf &amp; vbCrLf
    report = report &amp; &quot;Initial Investment: $&quot; &amp; Format(m_initialInvestment, &quot;#,##0.00&quot;) &amp; vbCrLf
    report = report &amp; &quot;Discount Rate: &quot; &amp; Format(m_discountRate * 100, &quot;0.00&quot;) &amp; &quot;%&quot; &amp; vbCrLf
    report = report &amp; &quot;Number of Periods: &quot; &amp; UBound(m_cashFlows) &amp; vbCrLf &amp; vbCrLf
    report = report &amp; &quot;Net Present Value: $&quot; &amp; Format(npvValue, &quot;#,##0.00&quot;) &amp; vbCrLf
    report = report &amp; &quot;Profitability Index: &quot; &amp; Format(pi, &quot;0.00&quot;) &amp; vbCrLf
    report = report &amp; &quot;Approx. IRR: &quot; &amp; Format(irr * 100, &quot;0.00&quot;) &amp; &quot;%&quot; &amp; vbCrLf &amp; vbCrLf
    If IsAcceptable() Then
        report = report &amp; &quot;Recommendation: ACCEPT - Positive NPV&quot;
    Else
        report = report &amp; &quot;Recommendation: REJECT - Negative NPV&quot;
    End If
    GenerateReport = report
End Function
Public Function RunSensitivityAnalysis() As String
    Dim result As String
    Dim rate As Double
    Dim npvValue As Double
    result = &quot;NPV Sensitivity to Discount Rate&quot; &amp; vbCrLf
    result = result &amp; String(40, &quot;-&quot;) &amp; vbCrLf
    For rate = 0.05 To 0.25 Step 0.05
        npvValue = NPV(rate, m_cashFlows) - m_initialInvestment
        result = result &amp; Format(rate * 100, &quot;0.0&quot;) &amp; &quot;%: $&quot; &amp; _
                 Format(npvValue, &quot;#,##0.00&quot;) &amp; vbCrLf
    Next rate
    RunSensitivityAnalysis = result
End Function</code></pre>
<h3 id="example-2-project-portfolio-manager">Example 2: Project Portfolio Manager</h3>
<pre><code class="language-vbnet">&#x27; Class: ProjectPortfolioManager
&#x27; Manages and ranks multiple investment projects
Option Explicit
Private Type Project
    name As String
    initialInvestment As Double
    cashFlows() As Double
    npv As Double
    pi As Double
    rank As Integer
End Type
Private m_projects As Collection
Private m_discountRate As Double
Public Sub Initialize(discountRate As Double)
    Set m_projects = New Collection
    m_discountRate = discountRate
End Sub
Public Sub AddProject(name As String, _
                     initialInvestment As Double, _
                     cashFlows() As Double)
    Dim proj As Project
    proj.name = name
    proj.initialInvestment = initialInvestment
    proj.cashFlows = cashFlows
    proj.npv = NPV(m_discountRate, cashFlows) - initialInvestment
    Dim pvCashFlows As Double
    pvCashFlows = NPV(m_discountRate, cashFlows)
    proj.pi = pvCashFlows / initialInvestment
    m_projects.Add proj, name
End Sub
Public Sub RankByNPV()
    &#x27; Simple ranking based on NPV
    Dim projects() As Project
    Dim i As Integer, j As Integer
    ReDim projects(1 To m_projects.Count)
    For i = 1 To m_projects.Count
        projects(i) = m_projects(i)
    Next i
    &#x27; Sort by NPV (descending)
    For i = 1 To UBound(projects) - 1
        For j = i + 1 To UBound(projects)
            If projects(j).npv &gt; projects(i).npv Then
                Dim temp As Project
                temp = projects(i)
                projects(i) = projects(j)
                projects(j) = temp
            End If
        Next j
    Next i
    &#x27; Assign ranks
    For i = 1 To UBound(projects)
        projects(i).rank = i
    Next i
End Sub
Public Function GetPortfolioNPV() As Double
    Dim proj As Project
    Dim totalNPV As Double
    Dim i As Integer
    totalNPV = 0
    For i = 1 To m_projects.Count
        proj = m_projects(i)
        totalNPV = totalNPV + proj.npv
    Next i
    GetPortfolioNPV = totalNPV
End Function
Public Function SelectProjectsWithBudget(budget As Double) As Collection
    Dim selectedProjects As New Collection
    Dim remainingBudget As Double
    Dim proj As Project
    Dim i As Integer
    RankByNPV
    remainingBudget = budget
    For i = 1 To m_projects.Count
        proj = m_projects(i)
        If proj.npv &gt; 0 And proj.initialInvestment &lt;= remainingBudget Then
            selectedProjects.Add proj
            remainingBudget = remainingBudget - proj.initialInvestment
        End If
    Next i
    Set SelectProjectsWithBudget = selectedProjects
End Function
Public Function GenerateRankingReport() As String
    Dim report As String
    Dim proj As Project
    Dim i As Integer
    RankByNPV
    report = &quot;Project Portfolio Ranking&quot; &amp; vbCrLf
    report = report &amp; String(80, &quot;=&quot;) &amp; vbCrLf
    report = report &amp; &quot;Rank  Project Name          Investment       NPV          PI&quot; &amp; vbCrLf
    report = report &amp; String(80, &quot;-&quot;) &amp; vbCrLf
    For i = 1 To m_projects.Count
        proj = m_projects(i)
        report = report &amp; Format(proj.rank, &quot;0&quot;) &amp; &quot;     &quot;
        report = report &amp; Left(proj.name &amp; String(20, &quot; &quot;), 20) &amp; &quot;  &quot;
        report = report &amp; Format(proj.initialInvestment, &quot;$#,##0&quot;) &amp; &quot;  &quot;
        report = report &amp; Format(proj.npv, &quot;$#,##0&quot;) &amp; &quot;  &quot;
        report = report &amp; Format(proj.pi, &quot;0.00&quot;) &amp; vbCrLf
    Next i
    report = report &amp; vbCrLf &amp; &quot;Total Portfolio NPV: $&quot; &amp; _
             Format(GetPortfolioNPV(), &quot;#,##0.00&quot;)
    GenerateRankingReport = report
End Function</code></pre>
<h3 id="example-3-real-estate-investment-analyzer">Example 3: Real Estate Investment Analyzer</h3>
<pre><code class="language-vbnet">&#x27; Module: RealEstateAnalyzer
&#x27; Analyzes real estate investments using NPV
Option Explicit
Public Function AnalyzeRentalProperty(purchasePrice As Double, _
                                     annualRent As Double, _
                                     annualExpenses As Double, _
                                     holdingYears As Integer, _
                                     appreciationRate As Double, _
                                     discountRate As Double) As String
    Dim cashFlows() As Double
    Dim i As Integer
    Dim salePrice As Double
    Dim npvValue As Double
    Dim result As String
    ReDim cashFlows(1 To holdingYears)
    &#x27; Calculate annual net cash flows
    For i = 1 To holdingYears - 1
        cashFlows(i) = annualRent - annualExpenses
    Next i
    &#x27; Final year includes property sale
    salePrice = purchasePrice * ((1 + appreciationRate) ^ holdingYears)
    cashFlows(holdingYears) = (annualRent - annualExpenses) + salePrice
    npvValue = NPV(discountRate, cashFlows) - purchasePrice
    result = &quot;Real Estate Investment Analysis&quot; &amp; vbCrLf
    result = result &amp; String(50, &quot;=&quot;) &amp; vbCrLf
    result = result &amp; &quot;Purchase Price: $&quot; &amp; Format(purchasePrice, &quot;#,##0&quot;) &amp; vbCrLf
    result = result &amp; &quot;Annual Rent: $&quot; &amp; Format(annualRent, &quot;#,##0&quot;) &amp; vbCrLf
    result = result &amp; &quot;Annual Expenses: $&quot; &amp; Format(annualExpenses, &quot;#,##0&quot;) &amp; vbCrLf
    result = result &amp; &quot;Holding Period: &quot; &amp; holdingYears &amp; &quot; years&quot; &amp; vbCrLf
    result = result &amp; &quot;Appreciation Rate: &quot; &amp; Format(appreciationRate * 100, &quot;0.0&quot;) &amp; &quot;%&quot; &amp; vbCrLf
    result = result &amp; &quot;Discount Rate: &quot; &amp; Format(discountRate * 100, &quot;0.0&quot;) &amp; &quot;%&quot; &amp; vbCrLf
    result = result &amp; &quot;Estimated Sale Price: $&quot; &amp; Format(salePrice, &quot;#,##0&quot;) &amp; vbCrLf &amp; vbCrLf
    result = result &amp; &quot;Net Present Value: $&quot; &amp; Format(npvValue, &quot;#,##0.00&quot;) &amp; vbCrLf
    If npvValue &gt; 0 Then
        result = result &amp; &quot;Recommendation: Good investment opportunity&quot;
    Else
        result = result &amp; &quot;Recommendation: Consider other opportunities&quot;
    End If
    AnalyzeRentalProperty = result
End Function
Public Function CompareBuyVsLease(equipmentCost As Double, _
                                 leaseCosts() As Double, _
                                 buyingCashFlows() As Double, _
                                 discountRate As Double) As String
    Dim buyNPV As Double
    Dim leaseNPV As Double
    Dim result As String
    buyNPV = NPV(discountRate, buyingCashFlows) - equipmentCost
    leaseNPV = NPV(discountRate, leaseCosts)
    result = &quot;Buy vs. Lease Analysis&quot; &amp; vbCrLf
    result = result &amp; String(40, &quot;-&quot;) &amp; vbCrLf
    result = result &amp; &quot;Buying NPV: $&quot; &amp; Format(buyNPV, &quot;#,##0.00&quot;) &amp; vbCrLf
    result = result &amp; &quot;Leasing NPV: $&quot; &amp; Format(leaseNPV, &quot;#,##0.00&quot;) &amp; vbCrLf
    result = result &amp; vbCrLf
    If buyNPV &gt; leaseNPV Then
        result = result &amp; &quot;Recommendation: BUY (NPV advantage: $&quot; &amp; _
                 Format(buyNPV - leaseNPV, &quot;#,##0.00&quot;) &amp; &quot;)&quot;
    Else
        result = result &amp; &quot;Recommendation: LEASE (NPV advantage: $&quot; &amp; _
                 Format(leaseNPV - buyNPV, &quot;#,##0.00&quot;) &amp; &quot;)&quot;
    End If
    CompareBuyVsLease = result
End Function</code></pre>
<h3 id="example-4-business-valuation-tool">Example 4: Business Valuation Tool</h3>
<pre><code class="language-vbnet">&#x27; Class: BusinessValuationTool
&#x27; Values businesses using discounted cash flow (DCF) method
Option Explicit
Private m_projectedCashFlows() As Double
Private m_terminalValue As Double
Private m_discountRate As Double
Public Sub ProjectCashFlows(baseCashFlow As Double, _
                           growthRate As Double, _
                           years As Integer)
    Dim i As Integer
    ReDim m_projectedCashFlows(1 To years)
    For i = 1 To years
        m_projectedCashFlows(i) = baseCashFlow * ((1 + growthRate) ^ i)
    Next i
End Sub
Public Sub CalculateTerminalValue(finalYearCashFlow As Double, _
                                 perpetualGrowthRate As Double, _
                                 discountRate As Double)
    &#x27; Terminal value using Gordon Growth Model
    m_terminalValue = (finalYearCashFlow * (1 + perpetualGrowthRate)) / _
                      (discountRate - perpetualGrowthRate)
End Sub
Public Function GetEnterpriseValue(discountRate As Double) As Double
    Dim i As Integer
    Dim cashFlowsWithTerminal() As Double
    m_discountRate = discountRate
    &#x27; Create array including terminal value
    ReDim cashFlowsWithTerminal(1 To UBound(m_projectedCashFlows))
    For i = 1 To UBound(m_projectedCashFlows) - 1
        cashFlowsWithTerminal(i) = m_projectedCashFlows(i)
    Next i
    &#x27; Add terminal value to final year
    cashFlowsWithTerminal(UBound(m_projectedCashFlows)) = _
        m_projectedCashFlows(UBound(m_projectedCashFlows)) + m_terminalValue
    GetEnterpriseValue = NPV(discountRate, cashFlowsWithTerminal)
End Function
Public Function GetEquityValue(enterpriseValue As Double, _
                              debt As Double, _
                              cash As Double) As Double
    GetEquityValue = enterpriseValue - debt + cash
End Function
Public Function GenerateValuationReport(companyName As String, _
                                       debt As Double, _
                                       cash As Double) As String
    Dim report As String
    Dim ev As Double
    Dim equity As Double
    ev = GetEnterpriseValue(m_discountRate)
    equity = GetEquityValue(ev, debt, cash)
    report = &quot;Business Valuation: &quot; &amp; companyName &amp; vbCrLf
    report = report &amp; String(60, &quot;=&quot;) &amp; vbCrLf &amp; vbCrLf
    report = report &amp; &quot;Discounted Cash Flow Analysis&quot; &amp; vbCrLf
    report = report &amp; &quot;Discount Rate (WACC): &quot; &amp; Format(m_discountRate * 100, &quot;0.00&quot;) &amp; &quot;%&quot; &amp; vbCrLf
    report = report &amp; &quot;Projection Period: &quot; &amp; UBound(m_projectedCashFlows) &amp; &quot; years&quot; &amp; vbCrLf
    report = report &amp; vbCrLf
    report = report &amp; &quot;Enterprise Value: $&quot; &amp; Format(ev, &quot;#,##0,000&quot;) &amp; vbCrLf
    report = report &amp; &quot;Less: Debt: $&quot; &amp; Format(debt, &quot;#,##0,000&quot;) &amp; vbCrLf
    report = report &amp; &quot;Plus: Cash: $&quot; &amp; Format(cash, &quot;#,##0,000&quot;) &amp; vbCrLf
    report = report &amp; String(60, &quot;-&quot;) &amp; vbCrLf
    report = report &amp; &quot;Equity Value: $&quot; &amp; Format(equity, &quot;#,##0,000&quot;)
    GenerateValuationReport = report
End Function</code></pre>
<h2 id="error-handling">Error Handling</h2>
<pre><code class="language-vbnet">On Error Resume Next
Dim npvResult As Double
npvResult = NPV(rate, cashFlows())
If Err.Number &lt;&gt; 0 Then
    MsgBox &quot;Error calculating NPV: &quot; &amp; Err.Description &amp; vbCrLf &amp; _
           &quot;Ensure cash flows array is properly dimensioned and rate is valid.&quot;
End If
On Error GoTo 0</code></pre>
<h2 id="performance-considerations">Performance Considerations</h2>
<ul>
<li>NPV calculation is relatively fast</li>
<li>Performance scales linearly with number of cash flows</li>
<li>For large arrays (1000+ periods), consider optimization</li>
<li>Caching results when using same inputs repeatedly</li>
<li>More efficient than manually discounting each period</li>
</ul>
<h2 id="best-practices">Best Practices</h2>
<ol>
<li><strong>Remember initial investment</strong> - Subtract it from NPV result (not in array)</li>
<li><strong>Use appropriate discount rate</strong> - Match to risk and period</li>
<li><strong>Validate cash flow array</strong> - Ensure proper dimensioning</li>
<li><strong>Check for mixed signs</strong> - Need both positive and negative flows</li>
<li><strong>Consider risk</strong> - Use higher discount rate for riskier investments</li>
<li><strong>Document assumptions</strong> - State discount rate rationale</li>
<li><strong>Sensitivity analysis</strong> - Test multiple discount rates</li>
<li><strong>Compare to alternatives</strong> - Use NPV to rank projects</li>
<li><strong>Account for inflation</strong> - Use real rates or inflate cash flows</li>
<li><strong>Validate results</strong> - Ensure NPV makes sense given inputs</li>
</ol>
<h2 id="comparison-with-related-functions">Comparison with Related Functions</h2>
<table>
<thead>
<tr>
<th>Function</th>
<th>Purpose</th>
<th>Key Difference</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>NPV</strong></td>
<td>Net present value</td>
<td>Assumes end-of-period cash flows</td>
</tr>
<tr>
<td><strong>PV</strong></td>
<td>Present value</td>
<td>Single/annuity payments only</td>
</tr>
<tr>
<td><strong>IRR</strong></td>
<td>Internal rate of return</td>
<td>Finds rate where NPV = 0</td>
</tr>
<tr>
<td><strong>MIRR</strong></td>
<td>Modified IRR</td>
<td>Uses separate financing/reinvestment rates</td>
</tr>
<tr>
<td><strong>FV</strong></td>
<td>Future value</td>
<td>Calculates future amount, not present</td>
</tr>
</tbody>
</table>
<h2 id="platform-notes">Platform Notes</h2>
<ul>
<li>Available in VBA (Excel, Access, Word, etc.)</li>
<li>Available in VB6</li>
<li><strong>Not available in <code>VBScript</code></strong></li>
<li>Equivalent to Excel's NPV function</li>
<li>Part of VBA financial functions library</li>
<li>Requires array parameter (not <code>ParamArray</code>)</li>
</ul>
<h2 id="limitations">Limitations</h2>
<ul>
<li>Assumes equally spaced time periods</li>
<li>Cash flows occur at end of each period</li>
<li>Does NOT include initial investment in values array</li>
<li>Cannot handle irregular time periods (use XNPV in Excel for that)</li>
<li>Assumes constant discount rate</li>
<li>Does not account for taxes directly</li>
<li>Requires at least one positive and one negative value</li>
</ul>
<h2 id="related-functions">Related Functions</h2>
<ul>
<li><strong>IRR</strong> - Finds internal rate of return (discount rate where NPV = 0)</li>
<li><strong>MIRR</strong> - Modified internal rate of return</li>
<li><strong>PV</strong> - Present value of annuity or lump sum</li>
<li><strong>FV</strong> - Future value of investment</li>
<li><strong>PMT</strong> - Payment amount for loan/investment</li>
<li><strong>Rate</strong> - Interest rate per period</li>
</ul>
<h2 id="vb6-parser-notes">VB6 Parser Notes</h2>
<p>NPV is parsed as a regular function call (<code>CallExpression</code>). This module exists primarily
for documentation purposes to provide comprehensive reference material for VB6 developers
working with financial analysis, investment evaluation, capital budgeting, and discounted
cash flow calculations.</p>
        </article>
        
        <div style="margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--border-color);">
            <p>
                <a href="index.html">← Back to Financial</a> |
                <a href="../index.html">View all functions</a>
            </p>
        </div>

    </main>

    <footer>
        <div class="container">
            <p>&copy; 2024-2026 VB6Parse Contributors. Licensed under the MIT License.</p>
        </div>
    </footer>
</body>
</html>