PERCENTOF(data_subset,data_all) sums the first set and divides by the sum of the second. It is useful as a two-argument aggregation callback in GROUPBY and PIVOTBY. The result is a fraction; percentage cell formatting changes its display.
Try it
=PERCENTOF({2,3},{2,3,5,10}) returns 0.25, displayed as 25 percent with percentage formatting. The subset sums to five and the full set to twenty.
The denominator is a supplied comparison set. In a pivot cell with amount three, PERCENTOF(3,{3,5}) gives 0.375, while PERCENTOF(3,{3,7}) gives 0.3. The same numerator can therefore describe a column share or a row share. PIVOTBY's relative_to argument chooses that second set for a callback.
Quirks
The function does not verify that the first set is a literal subset of the second; supplied totals can produce a value above one or below zero. A zero denominator gives #DIV/0!. In recorded build-20527 controls, direct numeric text/logicals convert, while errors held in a reference or array collapse to #NUM!; a direct error retains its own code.
How to implement
Read each argument under its aggregate admission rules, accumulating each total with the established arithmetic-site addition. Divide subset total by whole total at a stored site and apply zero-denominator/error policy. In a grouping callback the caller supplies both the local values and the appropriate comparison set; the latter need not be the entire original data table. The example gives 5/20=0.25. Keep collection origin so direct and held error handling do not become indistinguishable.
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.
/// PERCENTOF (dc-h9u): the sum of data_subset divided by the sum of data_all, each summed as SUM/// sums its one argument; #DIV/0! when the second sum is 0.fnpercentof(
arguments: &[CalcValue],
services: &mutEvalServices<'_>,
) -> Result<CalcValue, FunctionFault> {
let site = Site::new(PERCENTOF, services);
letmut sums = [0.0f64; 2];
letmut read = Ok(());
for (index, total) in sums.iter_mut().enumerate() {
let one = std::slice::from_ref(&arguments[index]);
let held = matches!(one[0].core_ref(), CoreRef::Reference(_) | CoreRef::Array(_));
read = read
.and_then(|()| direct_first(&site, one).map_err(|exit| reindex(exit, index)))
.and_then(|()| {
each_number(&site, one, services, Held::Numbers, &mut |n| {
*total = site.add(*total, n)?;
Ok(())
})
.map_err(|exit| match exit {
// An error a reference or an array holds is #NUM! (Excel 16.0.20527:// PERCENTOF(C1,4) over C1 = #N/A, PERCENTOF({1,#N/A},4) are #NUM!).Exit::Error(_) if held => Exit::Error(WorksheetErrorCode::Num),
other => reindex(other, index),
})
});
}
Site::finish(read.and_then(|()| site.number(site.divide(sums[0], sums[1])?)))
}
No implementation has been published with a Handbook test suite for this function.
Version differences
The current implementation comments retain COM readings from Excel 16.0 build 20527 on 30 October 2026. They cover direct versus held coercion/errors, including PERCENTOF(1,4)=0.25. No same-input comparison with another named build is recorded here. Microsoft’s opened page lists Excel for Microsoft 365; that is product availability, not a measured build comparison.
Excel 16.0 build 20527
Windows through COM; bitness and CPU not stated in these comments
COM controls retained in the implementation on 30 October 2026 include PERCENTOF(1,4)=0.25 and direct-versus-held coercion/error cases. No same-input other-build comparison is recorded.
Alternatives
SUM(subset)/SUM(all) expresses the documented arithmetic relationship. GROUPBY and PIVOTBY supply grouping context.