Numfmt: a negative number that rounds to zero shows no minus sign (fixes #729)
This commit is contained in:
parent
fc45b7f6d8
commit
ea5db94fe3
|
|
@ -261,7 +261,8 @@ impl NumberFormat {
|
|||
let Some(mut out) = out else {
|
||||
return (Formatted { text: OVERFLOW.into(), color: sec.color, fill: None, numeric: true }, true);
|
||||
};
|
||||
if minus && sec.kind != SecKind::Text {
|
||||
// Excel drops the minus sign when the first section shows a negative number as all zeros.
|
||||
if minus && sec.kind != SecKind::Text && !out.zero {
|
||||
out.prepend("-");
|
||||
}
|
||||
(Formatted { text: out.text, color: sec.color, fill: out.fill, numeric: true }, false)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use crate::parse::{DatePart, Section, Tok};
|
|||
pub(crate) struct Out {
|
||||
pub text: String,
|
||||
pub fill: Option<(char, usize)>,
|
||||
/// True when every digit shown is zero (a number section that rounded to zero).
|
||||
pub zero: bool,
|
||||
}
|
||||
|
||||
impl Out {
|
||||
|
|
@ -247,6 +249,7 @@ pub(crate) fn render_number(sec: &Section, v: f64) -> Out {
|
|||
let mut pieces: Vec<String> = vec![String::new(); n];
|
||||
let mut before: Vec<String> = vec![String::new(); n + 1];
|
||||
let mut lits: Vec<Option<String>> = Vec::new();
|
||||
let mut zero = false;
|
||||
if sec.fraction {
|
||||
lits = vec![None; n];
|
||||
render_fraction(sec, x, &mut pieces, &mut lits);
|
||||
|
|
@ -310,6 +313,7 @@ pub(crate) fn render_number(sec: &Section, v: f64) -> Out {
|
|||
} else {
|
||||
fixed(x, frac_idx.len())
|
||||
};
|
||||
zero = int_s.chars().chain(frac_s.chars()).all(|c| c == '0');
|
||||
fill_int(toks, &int_idx, &int_s, sec.thousands, false, &mut pieces);
|
||||
if int_idx.is_empty()
|
||||
&& !int_s.is_empty()
|
||||
|
|
@ -338,6 +342,7 @@ pub(crate) fn render_number(sec: &Section, v: f64) -> Out {
|
|||
_ => out.push(pieces.get(i).map(String::as_str).unwrap_or("")),
|
||||
}
|
||||
}
|
||||
out.zero = zero;
|
||||
out
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ fn numbers() {
|
|||
assert_eq!(f("0", -2.5), "-3");
|
||||
assert_eq!(f("0.00", 2.675), "2.68");
|
||||
assert_eq!(f("0.00", 1.005), "1.01");
|
||||
assert_eq!(f("0.0", -0.04), "-0.0");
|
||||
assert_eq!(f("0.0", -0.04), "0.0");
|
||||
assert_eq!(f("00000", 123.0), "00123");
|
||||
assert_eq!(f("000-00-0000", 123456789.0), "123-45-6789");
|
||||
assert_eq!(f("#.##", 0.5), ".5");
|
||||
|
|
@ -105,6 +105,29 @@ fn scientific() {
|
|||
assert_eq!(f("0.00E+00", -12345.0), "-1.23E+04");
|
||||
}
|
||||
|
||||
/// A negative number that rounds to zero in the first section shows no minus sign; a negative
|
||||
/// section of its own keeps its text (observed Excel results).
|
||||
#[test]
|
||||
fn negative_rounding_to_zero_drops_the_sign() {
|
||||
let cases: &[(&str, f64, &str)] = &[
|
||||
("0.00", -0.0033, "0.00"),
|
||||
("0.00", -2.89e-9, "0.00"),
|
||||
("0.00", -0.005, "-0.01"),
|
||||
("0", -0.4, "0"),
|
||||
("0", -0.5, "-1"),
|
||||
("0.0", -0.004, "0.0"),
|
||||
("#,##0.00", -0.004, "0.00"),
|
||||
("0.00%", -2.89e-9, "0.00%"),
|
||||
("0.00%", -0.0033, "-0.33%"),
|
||||
("0.00;(0.00)", -0.0033, "(0.00)"),
|
||||
("0.00;-0.00;\"zero\"", -0.0033, "-0.00"),
|
||||
("0.00E+00", -2.89e-9, "-2.89E-09"),
|
||||
];
|
||||
for &(code, n, want) in cases {
|
||||
assert_eq!(f(code, n), want, "{code} with {n}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fractions() {
|
||||
assert_eq!(f("# ?/?", 1.5), "1 1/2");
|
||||
|
|
@ -340,6 +363,8 @@ fn text_fn() {
|
|||
assert_eq!(text_function(&Value::Number(5.0), "", S), Ok("".into()));
|
||||
assert_eq!(text_function(&Value::Number(-1.0), "m/d/yyyy", S), Err(CellError::Value));
|
||||
assert_eq!(text_function(&Value::Bool(true), "0", S), Ok("TRUE".into()));
|
||||
assert_eq!(text_function(&Value::Number(-0.0033), "0", S), Ok("0".into()));
|
||||
assert_eq!(text_function(&Value::Number(-0.4), "0", S), Ok("0".into()));
|
||||
// Booleans go through the text section as TRUE/FALSE (observed Excel results).
|
||||
let cases: &[(bool, &str, &str)] = &[
|
||||
(true, ";;;@", "TRUE"),
|
||||
|
|
|
|||
Loading…
Reference in New Issue