Text functions

PROPER

Matches all 8 recorded answers

Recorded: 3 in the answer bank and 5 workbook cells. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
ArabicPROPER
BulgarianPROPER
CzechVELKÁ2
DanishSTORT.FORBOGSTAV
GermanGROSS2
GreekPROPER
English (Australia)PROPER
English (United Kingdom)PROPER
English (United States)PROPER
SpanishNOMPROPIO
EstonianPROPER
FinnishERISNIMI
FrenchNOMPROPRE
HebrewPROPER
CroatianPROPER
HungarianTNÉV
IndonesianPROPER
ItalianMAIUSC.INIZ
JapanesePROPER
KoreanPROPER
LithuanianPROPER
LatvianPROPER
NorwegianSTOR.FORBOKSTAV
DutchBEGINLETTERS
PolishZ.WIELKIEJ.LITERY
Portuguese (Brazil)PRI.MAIÚSCULA
Portuguese (Portugal)INICIAL.MAIÚSCULA
RomanianPROPER
RussianПРОПНАЧ
SlovakPROPER
SlovenianPROPER
Serbian (Latin)PROPER
SwedishINITIAL
ThaiPROPER
TurkishYAZIM.DÜZENİ işlevi
UkrainianPROPER
VietnamesePROPER
Chinese (Simplified)PROPER
Chinese (Hong Kong)PROPER
Chinese (Traditional)PROPER

Names from Microsoft's support site.

What it does

PROPER(text)

PROPER(text) rewrites the case of every letter in text according to one rule, applied character by character:

A letter is uppercased if it is the first character of text or if the character before it is not a letter. Every other letter is lowercased.

That is Microsoft's documented rule, and reading it literally is the whole story — because what it says is not "capitalize each word". It says "capitalize after any non-letter". The two descriptions diverge constantly, and the divergences are the reason this function has a reputation:

InputResult under the documented rule
"o'brien"O'Brien — the apostrophe is not a letter
"2nd place"2Nd Place — the digit is not a letter
"e-mail"E-Mail
"McDonald"Mcdonald — the interior capital is lowercased
"IBM"Ibm

None of these is a bug. All five follow from one rule with no word list, no dictionary, and no exceptions. PROPER is a character classifier, not a name formatter, and it should not be used as one.

The rule is also unconditional on the rest of the string: PROPER lowercases letters it did not capitalize, so it destroys existing casing rather than preserving it. This is what separates it from a "capitalize first letters" transformation.

Arguments

ArgumentMeaning
textThe string whose case is rewritten. Required, and the only argument.

Try it

Input cells (optional)

Example: {"B2": 3, "B3": 4}. A1 holds the formula. Other cells need values before a formula can read them.

Enter a formula, then calculate.

Runs locally in your browser with OneCalc. Its answer may differ from Excel. Use English function names and commas between arguments.

Quirks

Result and edge cases

Returns Text.

  • Empty text returns the empty string.
  • Non-letter characters pass through unchanged; only letters are rewritten.
  • Numbers and logicals arriving in the argument slot are converted to text first under the shared coercion rules, then processed — see Coercion and lifting. What the resulting text looks like for a number is a to-text question, not a PROPER question, and the shared chapter is explicit that to-text behaviour is only outlined, not pinned.
  • Error values propagate.

Errors

Microsoft's PROPER page documents no error conditions of its own. The errors reachable here are the shared ones: an error value in the argument propagates, and a value that cannot be converted to text surfaces #VALUE! under the shared coercion rules. The Handbook has not verified either against Excel.

LOWER leaves letters above U+FFFF alone, and a combining mark stops the final sigma

LOWER did not change the Deseret capital U+10400, a cased letter above U+FFFF, either alone or inside other text: LOWER("A𐐀Σ") is "a𐐀ς", where the Greek capital sigma at the end becomes the final form. Greek sigma depends on what follows: followed by a full stop it takes the final form ς, and followed by a combining mark, U+0300 or U+0301, it takes the medial form σ. PROPER treats a character above U+FFFF as a word boundary, so PROPER("a𐐀b") is "A𐐀B", with the B capitalised and the Deseret letter unchanged.

Explanation (inferred): The readings cover one Deseret letter and two combining marks. That every letter above U+FFFF and every mark behave the same is inferred.

FormulaExcelMathematical value
LOWER(A1)
Excel 16.0.20527.20088, Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2
Inputs and reference value

Number supplied through a cell.

text: 𐐀

𐐀—
LOWER(A1)
Excel 16.0.20527.20088, Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2
Inputs and reference value

Number supplied through a cell.

text: A𐐀Σ

a𐐀ς—
LOWER(A1)
Excel 16.0.20527.20088, Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2
Inputs and reference value

Number supplied through a cell.

text: ΑΣ̀

ασ̀—
LOWER(A1)
Excel 16.0.20527.20088, Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2
Inputs and reference value

Number supplied through a cell.

text: ΑΣ.

ας.—
PROPER(A1)
Excel 16.0.20527.20088, Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2
Inputs and reference value

Number supplied through a cell.

text: a𐐀b

A𐐀B—
PROPER(A1)
Excel 16.0.20527.20088, Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2
Inputs and reference value

Number supplied through a cell.

text: aΣ́

Aσ́—

Inputs, build details and evidence

How to implement

Notes for implementers

The whole function is a one-pass scan with one bit of state (was the previous character a letter?), so the interest is entirely in the character classification.

Three decisions have to be made, and Microsoft's documentation makes none of them:

  1. What "is a letter" means. ASCII A-Za-z, the Unicode L* general categories, and the host code page's letter table are three different answers, and they differ on accented characters, on the Latin Extended blocks, and on modifier letters.
  2. What case mapping is applied. Simple per-character mapping and full case mapping disagree — ß uppercases to SS under full mapping, which changes the string's length.
  3. Whether the mapping is locale-sensitive. Turkish i/İ is the standing example. A locale-invariant mapping is the safer default but is a decision, not a neutral choice.

Record whichever you pick as unverified. All three are the sort of thing that silently agrees with Excel on English data and silently disagrees on everything else.

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.

PROPER · 1 lines · calc-func/src/catalogue/text_functions.rs on GitHub
15 proper_fn "PROPER" (1, 1) [V "text"] |s, a, sv| { cased(s, a, k::proper) }
adjacent_letter · 4 lines · calc-func/src/ported/text_kernels.rs on GitHub
fn adjacent_letter(chars: &[char], index: usize, offset: isize) -> bool {
    let adjacent = index as isize + offset;
    adjacent >= 0 && (adjacent as usize) < chars.len() && chars[adjacent as usize].is_alphabetic()
}
proper · 24 lines · calc-func/src/ported/text_kernels.rs on GitHub
pub(crate) fn proper(text: &ExcelText) -> ExcelText {
    let chars = text.to_string_lossy().chars().collect::<Vec<_>>();
    let mut out = String::new();
    let mut start_of_word = true;
    for (index, ch) in chars.iter().copied().enumerate() {
        // PROPER treats a supplementary pair as a word boundary (fn3-proper-002).
        if ch as u32 <= 0xFFFF && ch.is_alphabetic() {
            if start_of_word {
                push_upper(&mut out, ch);
            } else {
                let is_final_sigma = ch == 'Σ'
                    && adjacent_letter(&chars, index, -1)
                    && !chars.get(index + 1).is_some_and(|&next|
                        next.is_alphabetic() || calc_value::is_combining_mark(next));
                push_lower(&mut out, ch, is_final_sigma);
            }
            start_of_word = false;
        } else {
            out.push(ch);
            start_of_word = true;
        }
    }
    text_from_str(&out)
}

Kernels shared with other functions

Argument and result plumbing

No implementation has been published with a Handbook test suite for this function.

Version differences

No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.

Excel 16.0.20527.20088

Windows 64-bit, AMD Ryzen 7 4800H, workbook compatibility version 2

PROPER(A1) returned A𐐀B. PROPER(A1) returned Aσ́. Inputs were supplied through cells using Value2. These are controls from this environment, not a same-input comparison with another build.

Observed formulas and results
  • PROPER(A1) → A𐐀B (cell-value2)
  • PROPER(A1) → Aσ́ (cell-value2)

Alternatives

Relationships

  • UPPER and LOWER are the unconditional case transforms. All three lowercase by default; PROPER differs only in which characters it raises back up.
  • TEXTSPLIT / TEXTBEFORE / TEXTAFTER are what you actually want if the task is "capitalize each word" with a definition of "word" that is not "run of letters" — PROPER cannot be configured, so word-level work has to be done around it.
  • There is no compatibility-replacement pair here: PROPER is neither superseded nor a retained legacy name.
  • Readers confuse PROPER with TRIM, because both are reached for while cleaning imported names. They share no behaviour: TRIM deals in spaces, PROPER in case.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents