First Letter Upper Case In Every Word After The Space

Hi Everyone

I wonder is this possible in Appsheet in the following date input expression: If I want to force and entry string to be, mandatory first letter of the word has to be upper case and the following letter mandatory to be lower case is that possible ? Example data entry at form :

the quick brown fox jump over the lazy dog.

Valid_if : The Quick Brown Fox Jump Over The Lazy Dog

2 Likes

For the first letter to be in upper case , please try a valid_if of

FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS])))=1

For the other letters to be lower case, it could be possibly done with a very long expression with the current available AppSheet expressions.

If the text will be small like say just “The Quick Brown Fox” , meaning if the text is at the most 3 or 4 words, an expression could be possibly stitched together but I believe that too will be a long expression.

1 Like

Hi Suvrutt

The second letter is mandatory lower case. Example John Anderson - OK. JOhn Anderson - Not OK JOHN Anderson - Not OK

1 Like

This would test the first three words to make sure that the first letter of each word is capitalized and the second letter of each word is lower case.

AND(
  IF(LEN([_THIS]) > 0,
    IF(COUNT(SPLIT([_THIS], " ")) >= 1,
      AND(
        FIND(LEFT(INDEX(SPLIT([_THIS], " "), 1), 1), UPPER(LEFT(INDEX(SPLIT([_THIS], " "), 1), 1))) = 1,
        IF(LEN(INDEX(SPLIT([_THIS], " "), 1)) > 1,
          FIND(MID(INDEX(SPLIT([_THIS], " "), 1), 2, 1), LOWER(MID(INDEX(SPLIT([_THIS], " "), 1), 2, 1))) = 1,
          TRUE
        )
      ),
      TRUE
    ),
    FALSE
  ),
  
  IF(COUNT(SPLIT([_THIS], " ")) >= 2,
    AND(
      FIND(LEFT(INDEX(SPLIT([_THIS], " "), 2), 1), UPPER(LEFT(INDEX(SPLIT([_THIS], " "), 2), 1))) = 1,
      IF(LEN(INDEX(SPLIT([_THIS], " "), 2)) > 1,
        FIND(MID(INDEX(SPLIT([_THIS], " "), 2), 2, 1), LOWER(MID(INDEX(SPLIT([_THIS], " "), 2), 2, 1))) = 1,
        TRUE
      )
    ),
    TRUE
  ),
  
  IF(COUNT(SPLIT([_THIS], " ")) >= 3,
    AND(
      FIND(LEFT(INDEX(SPLIT([_THIS], " "), 3), 1), UPPER(LEFT(INDEX(SPLIT([_THIS], " "), 3), 1))) = 1,
      IF(LEN(INDEX(SPLIT([_THIS], " "), 3)) > 1,
        FIND(MID(INDEX(SPLIT([_THIS], " "), 3), 2, 1), LOWER(MID(INDEX(SPLIT([_THIS], " "), 3), 2, 1))) = 1,
        TRUE
      )
    ),
    TRUE
  )
)
2 Likes

Thanks anywhere it’s does not work. I target is from second letter onwards on any word MUST be small letter. See the expression does not word in evidence below

Sorry. I wonder if this is better:

AND(
  IF(LEN([_THIS]) > 0,
    IF(COUNT(SPLIT([_THIS], " ")) >= 1,
      AND(
        FIND(LEFT(INDEX(SPLIT([_THIS], " "), 1), 1), UPPER(LEFT(INDEX(SPLIT([_THIS], " "), 1), 1))) = 1,
        IF(LEN(INDEX(SPLIT([_THIS], " "), 1)) > 1,
          RIGHT(INDEX(SPLIT([_THIS], " "), 1), LEN(INDEX(SPLIT([_THIS], " "), 1)) - 1) = 
          LOWER(RIGHT(INDEX(SPLIT([_THIS], " "), 1), LEN(INDEX(SPLIT([_THIS], " "), 1)) - 1)),
          TRUE
        )
      ),
      TRUE
    ),
    FALSE
  ),
  
  IF(COUNT(SPLIT([_THIS], " ")) >= 2,
    AND(
      FIND(LEFT(INDEX(SPLIT([_THIS], " "), 2), 1), UPPER(LEFT(INDEX(SPLIT([_THIS], " "), 2), 1))) = 1,
      IF(LEN(INDEX(SPLIT([_THIS], " "), 2)) > 1,
        RIGHT(INDEX(SPLIT([_THIS], " "), 2), LEN(INDEX(SPLIT([_THIS], " "), 2)) - 1) = 
        LOWER(RIGHT(INDEX(SPLIT([_THIS], " "), 2), LEN(INDEX(SPLIT([_THIS], " "), 2)) - 1)),
        TRUE
      )
    ),
    TRUE
  ),
  
  IF(COUNT(SPLIT([_THIS], " ")) >= 3,
    AND(
      FIND(LEFT(INDEX(SPLIT([_THIS], " "), 3), 1), UPPER(LEFT(INDEX(SPLIT([_THIS], " "), 3), 1))) = 1,
      IF(LEN(INDEX(SPLIT([_THIS], " "), 3)) > 1,
        RIGHT(INDEX(SPLIT([_THIS], " "), 3), LEN(INDEX(SPLIT([_THIS], " "), 3)) - 1) = 
        LOWER(RIGHT(INDEX(SPLIT([_THIS], " "), 3), LEN(INDEX(SPLIT([_THIS], " "), 3)) - 1)),
        TRUE
      )
    ),
    TRUE
  )
)
2 Likes

Another technique would be to just let them type it in any way they want and then use UPPER() and LOWER() to reformat it for them.

2 Likes

That would be reactive method but I like more on proactive method

1 Like

I wasn’t able to test my second try. Did it work?

1 Like

No I did not trying because that is not my intention

The second is what you asked for, I believe.

This part

RIGHT(INDEX(SPLIT([_THIS], " "), 1), LEN(INDEX(SPLIT([_THIS], " "), 1)) - 1) = 

checks to see if ALL letters of the word after the first one are lower case, which I believe is what you asked for. After I made the first expression, this method occurred to me.

Hi thanks for the expression but I think something is missing there is an error. The first expression FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS])))=1 is correct and it works for all word. See evidence below. It’s only the second letter and onwards to force input MUST be lower case

desmond_lee_0-1743803828072.png

I’m not sure. I haven’t been able to test the expression on my side. The screenshot you gave me, however, seems correct. The second one is wrong because the A and “Anderson” is lower case. So, the expression worked as far as I can see.

Hello everyone

this expression works for me, but it is triggered by a bot (set row values)

CONCATENATE(
UPPER(LEFT(INDEX(SPLIT([Name ], " "), 1), 1)) & LOWER(MID(INDEX(SPLIT([Name ], " "), 1), 2, LEN(INDEX(SPLIT([Name ], " "), 1)))) & " ",
UPPER(LEFT(INDEX(SPLIT([Name ], " "), 2), 1)) & LOWER(MID(INDEX(SPLIT([Name ], " "), 2), 2, LEN(INDEX(SPLIT([Name ], " "), 2)))) & " ",
UPPER(LEFT(INDEX(SPLIT([Name ], " "), 3), 1)) & LOWER(MID(INDEX(SPLIT([Name ], " "), 3), 2, LEN(INDEX(SPLIT([Name ], " "), 3)))) & " ",
UPPER(LEFT(INDEX(SPLIT([Name ], " "), 4), 1)) & LOWER(MID(INDEX(SPLIT([Name ], " "), 4), 2, LEN(INDEX(SPLIT([Name ], " "), 4)))) & " ",

)

If necessary, you can add more lines for longer names
I hope this helps
 
1 Like

HI Marco

Thank very much for the expression and it works in the BOT but this is not my intention. At the moment this expression FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS])))=1 is the closest that mandatory every first letter of every word and second letter cannot be controlled.

Please try the below expression in valid_if of the text or name column. The expression is constructed to work for 3 word text or name.

AND(
FIND(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE([_THIS], LEFT(INITIALS([_THIS]),1), LOWER(LEFT(INITIALS([_THIS]),1))), MID(INITIALS([_THIS]),2,1), LOWER(MID(INITIALS([_THIS]),2,1))), RIGHT(INITIALS([_THIS]),1), LOWER(RIGHT(INITIALS([_THIS]),1))),

LOWER([_THIS]))=1 ,

FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS])))=1

)

The following should work for a 4 word text or name.

AND(
FIND(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE([_THIS], LEFT(INITIALS([_THIS]),1), LOWER(LEFT(INITIALS([_THIS]),1))), MID(INITIALS([_THIS]),2,1), LOWER(MID(INITIALS([_THIS]),2,1))), MID(INITIALS([_THIS]),3,1), LOWER(MID(INITIALS([_THIS]),3,1))), RIGHT(INITIALS([_THIS]),1), LOWER(RIGHT(INITIALS([_THIS]),1))),

LOWER([_THIS]))=1 ,

FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS])))=1

)

Why not just add a column in your google sheet and put an =PROPER() function in that cell? You can put the cell to convert in the brackets. With some error checking and an array formula, the spreadsheet will do all the work and you can just read that value back in Appsheet?

Wow amazing ! It works. I think 6 words is more secure n case…

1 Like

I’m glad @Suvrutt_Gurjar 's response worked. Did the expression I posted here not work?

To be honest, @desmond_lee , I think you gave my expression (my second version, not my first one) short shrift. I asked ChatGPT to compare them (to save time). Here’s what I got:

? What Both Expressions Aim to Do

Both expressions appear to validate that each word in a multi-word input (like a name) starts with an uppercase letter and is followed by all lowercase letters. In other words, they check for title case formatting — e.g., "John Smith" or "Mary Ann Doe".


? Expression 1 (Suvrutt: Initials-based approach)

This version uses:

INITIALS([_THIS])

INITIALS([_THIS])

…to get the first letter of each word, then uses SUBSTITUTE() to replace each of those uppercase initials with their lowercase version in [_THIS], and compares the result to LOWER([_THIS]). If all initials are properly capitalized (and the rest is lowercase), the transformation should match LOWER([_THIS]):

SUBSTITUTE... → lowercase the initials only
LOWER([_THIS]) → fully lowercase

Also, it uses:

FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS]))) = 1
``…to confirm that all initials are already uppercase.

:warning: Limitation:
The first version must be manually extended to handle 4 or more words (as shown with the second variation of Expression 1). This makes it less scalable.


? Expression 2 (Kirk: Word-by-word approach)

This version manually processes each word using INDEX(SPLIT(...)), checking for:

  • First character is uppercase (with FIND(..., UPPER(...)) = 1)

  • Remainder of the word is lowercase

It repeats this check for the first 3 words, and allows input with fewer than 3 words. It’s wrapped in IF() logic to avoid errors on short or empty inputs.

:white_check_mark: Advantages:

  • More readable

  • Explicit logic for each word

  • Easier to extend (you can copy/paste a block to handle a 4th, 5th word, etc.)

  • Avoids reliance on INITIALS(), which could have odd behavior if there are non-alphabetic characters


:white_check_mark: Are They Functionally the Same?

Yes, for inputs with up to 3 or 4 words (depending on how far Expression 1 is extended), both expressions perform the same validation goal:

Each word starts with a capital letter and the remaining letters are lowercase.### :repeat_button: Key Differences

Aspect Expression 1 Expression 2
Approach Uses INITIALS() and SUBSTITUTE() Processes words individually with SPLIT()
Scalability Manual additions required Easier to scale by duplicating logic
Readability Complex and hard to maintain Clearer and more maintainable
Edge-case handling Less robust to non-standard names More precise, handles short/empty input better

Please try the expression below for a 6 word string

AND(
FIND(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE([_THIS], LEFT(INITIALS([_THIS]),1), LOWER(LEFT(INITIALS([_THIS]),1))), MID(INITIALS([_THIS]),2,1), LOWER(MID(INITIALS([_THIS]),2,1))),MID(INITIALS([_THIS]),3,1), LOWER(MID(INITIALS([_THIS]),3,1))),MID(INITIALS([_THIS]),4,1), LOWER(MID(INITIALS([_THIS]),4,1))), MID(INITIALS([_THIS]),5,1), LOWER(MID(INITIALS([_THIS]),5,1))), RIGHT(INITIALS([_THIS]),1), LOWER(RIGHT(INITIALS([_THIS]),1))),

LOWER([_THIS]))=1 ,

FIND(INITIALS([_THIS]), UPPER(INITIALS([_THIS])))=1

)

1 Like