VDB(cost, salvage, life, start_period, end_period, [factor], [no_switch]) returns the
depreciation of an asset over the span from start_period to end_period, by a declining
balance method. The name stands for variable declining balance.
Two things set it apart from DDB. It covers a span and not one period, and that span
can start and end at fractions of a period. And it switches to straight line when the declining
charge falls behind, unless told not to.
The underlying schedule works period by period from a book value that starts at cost:
Microsoft states the switch in one sentence: Excel switches to straight line when depreciation is
greater than the declining balance calculation. Once the schedule has switched it stays on the
straight line, because the remaining basis is then spread evenly over the remaining life.
start_period and end_period are elapsed time, not period numbers. The first full period is
the span from 0 to 1:
VDB(c, s, l, 0, 1) is the first period's charge.
VDB(c, s, l, 1, 1) is 0, an empty span. It is not the first period.
VDB(c, s, l, 0, l) is the whole life.
A worked schedule, by the rule above, for cost 1000, salvage 0, life 5, factor 2:
Period
Book at start
Declining
Straight line
Charge with switch
Charge with no_switch TRUE
1
1000.00
400.00
200.00
400.00
400.00
2
600.00
240.00
150.00
240.00
240.00
3
360.00
144.00
120.00
144.00
144.00
4
216.00
86.40
108.00
108.00
86.40
5
108.00
43.20
108.00
108.00
51.84
Total
1000.00
922.24
The book and declining columns follow the charge with the switch. The switch lands in period 4, and
with it the asset is depreciated down to salvage exactly. Without it 77.76 is never charged. That
shortfall is why the switch exists. This table is the Handbook's arithmetic from the rule, not a
reading.
Microsoft's six examples, for cost 2400, salvage 300 and a life of 10 years, all follow the
schedule, with fractional spans prorated inside a period as described below:
Formula
Meaning
Result
=VDB(2400, 300, 3650, 0, 1)
First day
1.32
=VDB(2400, 300, 120, 0, 1)
First month
40.00
=VDB(2400, 300, 10, 0, 1)
First year
480.00
=VDB(2400, 300, 120, 6, 18)
Month 6 to month 18
396.31
=VDB(2400, 300, 120, 6, 18, 1.5)
The same at factor 1.5
311.81
=VDB(2400, 300, 10, 0, 0.875, 1.5)
First fiscal year, part year, factor 1.5
315.00
The last example shows the proration: a full first year at factor 1.5 is 360, and seven eighths of
that is 315.
Arguments
Argument
Meaning
Default
cost
The initial cost of the asset. Required.
none
salvage
The value at the end of the depreciation. Can be 0. Required.
none
life
The number of periods over which the asset is depreciated. Required.
none
start_period
The start of the span, in the same units as life. Required.
none
end_period
The end of the span, in the same units as life. Required.
none
factor
The rate at which the balance declines. Optional.
2 if left off the end of the call
no_switch
TRUE to stay on declining balance; FALSE to allow the switch. Optional.
FALSE
An empty factor slot is not the default. Microsoft says an omitted factor is 2. The notes
below record that this holds only when the argument is left off the end of the call. An empty
slot, as in VDB(c, s, l, a, b, , FALSE), is read as 0, which gives the straight-line amount.
To reach no_switch while keeping double declining, write the 2.
A blank cell as factor behaves like the empty slot. In the note's example a blank cell, and
a cell holding 0, both give the same 90 as the empty slot. A cell holding -1 gives #NUM!.
Text in factor and no_switch is treated differently in each slot.factor reads "2" as 2,
and gives #VALUE! for "TRUE", "FALSE" and "". In the no_switch slot of the same recorded
run, "TRUE" and "FALSE" are accepted, and "2" and "" give #VALUE!.
Units must match.life, start_period and end_period are in the same units. Monthly
depreciation of a ten-year asset uses life 120, as in the examples above.
Try it
Quirks
Result and edge cases
Returns Number.
Recorded behaviour, from readings on Excel 16.0 build 20430, Windows 64-bit, CPU not recorded,
classified for this page:
start_period = end_period gives 0 when the span lies inside the life.
factor = 0 gives straight line. With no_switch FALSE and cost above salvage, 10,427 of
10,686 recorded answers are within 1e−9 relative of (cost − salvage) / life × (end − start).
The other 259 all have cost below 1e−38. With no_switch TRUE, all 9,322 recorded answers are
0, because there is nothing to switch to and the declining rate is zero.
salvage above cost gives a negative number, not an error:
VDB(1, 1000, 1, 0, 0.5, 2, FALSE) is -499.5.
cost = 0 is admitted, and with a positive salvage also gives a negative number:
VDB(0, 1, 1, 0, 0.5, 2, FALSE) is -0.5.
salvage = 0 is admitted, as Microsoft's parameter table says.
Inputs near the limits of the number range can give #NUM! with no other condition met, for
example with an enormous factor.
The span is not additive. This is the most important behaviour on the page, and the arithmetic
of the schedule would not lead you to expect it. For cost 1000, salvage 100, life 1.5 and
factor 1:
Span
Excel
0 to 1.25
783.3333333333333
1.25 to 1.5
146.66666666666669
Sum of the two
930.0
0 to 1.5
900.0
Splitting a span and adding the pieces does not give the whole. The recorded research on these
readings concludes that a fractional part of start_period is applied first, which changes the
basis on which later whole periods decline. So a depreciation schedule built from consecutive
fractional spans need not total cost − salvage.
Where this applies can be read from the recorded answers. Taking every case where a span and its
two pieces were all read, and calling a split additive when the pieces sum to the whole within 1e−9
relative:
Path
First piece starts
Split point
Additive
no_switch TRUE
any
any
374 of 374
switch allowed
whole period
whole period
837 of 837
switch allowed
whole period
fraction
715 of 1,002
switch allowed
fraction
whole period
410 of 456
switch allowed
fraction
fraction
161 of 286
So the behaviour belongs to the switching path, and appears only when one of the pieces starts at a
fraction. A schedule of whole periods adds up.
Errors
Microsoft documents no error values for VDB. It says only that "All arguments except no_switch
must be positive numbers", which is contradicted in the same place by the statement that salvage
can be 0, and by readings: cost, salvage, start_period and factor can each be 0.
An empty factor slot in VDB is 0, not the default 2
VDB defaults factor to 2 only when the argument is left off the end of the call. An empty slot, as in VDB(c,s,l,a,b,,FALSE), is read as 0, and the result is the straight-line amount: 90 here, where factor 2 gives 160. Text factors other than numbers give #VALUE!, including "TRUE" and "FALSE", while "2" is read as 2.
Formula
Excel
Mathematical value
=VDB(A100,A101,A102,A103,A104,,FALSE) Excel build not recorded in this run; bulk captures of the same date (2026-09-29) record Excel 16.0 build 20430, Windows 64-bit, workbook compatibility 2Inputs and reference value
Number supplied through a cell.
cost: 1000 0x408f400000000000
salvage: 100 0x4059000000000000
life: 10 0x4024000000000000
start_period: 1 0x3ff0000000000000
end_period: 2 0x4000000000000000
90 0x4056800000000000
—
=VDB(A100,A101,A102,A103,A104,"2",FALSE) Excel build not recorded in this run; bulk captures of the same date (2026-09-29) record Excel 16.0 build 20430, Windows 64-bit, workbook compatibility 2Inputs and reference value
Number supplied through a cell.
cost: 1000 0x408f400000000000
salvage: 100 0x4059000000000000
life: 10 0x4024000000000000
start_period: 1 0x3ff0000000000000
end_period: 2 0x4000000000000000
160 0x4064000000000000
—
=VDB(A100,A101,A102,A103,A104,"TRUE",FALSE) Excel build not recorded in this run; bulk captures of the same date (2026-09-29) record Excel 16.0 build 20430, Windows 64-bit, workbook compatibility 2Inputs and reference value
The notes below cover how the arguments are read. They say nothing about the arithmetic of the
result, so this section gives the shape of that arithmetic and the last-unit questions remain open.
The schedule is a recurrence. Period k needs the book value after k − 1 charges, so the cost
grows with the period and each earlier rounding is inherited. In exact arithmetic the declining
part has a closed form, cost × (1 − factor/life)^k, but it is not the same floating-point
number as the recurrence, and it does not know about the limit at salvage or the switch.
Tiny values. With factor 0 and very small costs, recorded answers depart from the straight-line
amount, and some are 0 where that amount would be a subnormal number. This is consistent with
intermediate results being published as zero when they fall below the normal range, but the
arithmetic is not established here.
No transcendental functions. Unlike DB, VDB needs only addition, subtraction,
multiplication, division and comparison. Any last-unit difference is therefore about the order and
precision of those operations.
Rust code
Show the CalcFunc source of this function
Quoted from the public repository DnaCalc/DnaCalc, crates calc-func and calc-fml, at commit 9e1884369a67. Comments are the source's own. A kernel shared with other functions appears once, on its module page.
fndeclining_interval_depreciation(
cost: f64,
salvage: f64,
life: f64,
start_period: f64,
end_period: f64,
factor: f64,
no_switch: bool,
) -> Result<f64, WorksheetErrorCode> {
validate_finite(&[cost, salvage, life, start_period, end_period, factor])?;
if cost < 0.0 || salvage < 0.0 || life <= 0.0 || factor < 0.0 {
returnErr(WorksheetErrorCode::Num);
}
if start_period < 0.0 || end_period < start_period || end_period > life {
returnErr(WorksheetErrorCode::Num);
}
if no_switch {
if start_period == end_period {
returnOk(0.0);
}
letmut year = start_period.floor();
letmut total = 0.0;
while year < end_period {
let dep = ddb_period_depreciation(cost, salvage, life, year + 1.0, factor)?;
// Excel rounds these partial products separately, even when both// bounds lie in the same year. The final fraction is formed by// subtracting the unused tail from one; end-year loses observed// cancellation, including tiny negative intervals. The final year uses the same// annual amount, without rescaling it by the remaining year length.let final_fraction = 1.0 - ((year + 1.0) - end_period).max(0.0);
// Both products pass through an extended-precision store. Their// separate rounding is visible when adjacent endpoints cancel.let final_part =
publish_depreciation(crate::ported::excel_numeric::excel_x87_mul(dep, final_fraction))?;
let initial_part = publish_depreciation(crate::ported::excel_numeric::excel_x87_mul(
dep,
(start_period - year).max(0.0),
))?;
total += final_part - initial_part;
if dep == 0.0 {
break;
}
year += 1.0;
}
// The partial products publish subnormals as zero, but subtraction// of two normal products may return a nonzero subnormal Value2.returnif total.is_finite() {
Ok(total)
} else {
Err(WorksheetErrorCode::Num)
};
}
switched_interval_depreciation(cost, salvage, life, start_period, end_period, factor)
}
No implementation has been published with a Handbook test suite for this function.
Version differences
The recorded environments below distinguish a reading from a same-input comparison. Counts describe captured inputs in each environment; overlapping captures and comparisons are not totals of unique worksheet calls.
Excel 16.0 build
Platform and CPU
Captured inputs
20430
Windows, bitness not recorded, CPU not recorded
106
20430
Windows, 64-bit, CPU not recorded
166,843
The record contains no same-input comparison between these environments. Reading different inputs on different builds does not establish either a version change or cross-build agreement.
106 captured inputs are indexed for this environment. Capture dates: 2026-09-29 to 2026-09-29. This is a reading count, not a comparison with another build.
Excel 16.0 build 20430
Windows, 64-bit, CPU not recorded
166,843 captured inputs are indexed for this environment. Capture dates: 2026-09-29 to 2026-09-29. This is a reading count, not a comparison with another build.
Alternatives
Relationships
SLN is the straight line. VDB with factor 0 and the switch allowed gives the SLN amount
times the length of the span, as above.
DB is declining balance at a derived, rounded rate, with no factor and no
switch, and a partial first year set in months.
SYD is sum-of-years digits, the other accelerated method in the family.
AMORLINC and AMORDEGRC are the French accounting
pair, which prorate on a different basis.
Confused with: tax depreciation tables, which fix their own conventions for the year of
purchase. VDB with a fractional span can approximate one, and is not the same thing.