Pascal Case in Appsheet

Hello all,

I am struggling to find a valid_if expression, which to push the user to fill a form field with "Pascal Case" method only:

Example: Correct should be - "Samuel Smith Smith". The wrong must be: "Samuel smith Smith".

Every new word (it will be used for the customer name field) must start with the capital letter. 

I found a way to push the users to use only Upper case, but with this one I stucked.

Thanks in advance.

Solved Solved
0 13 958
2 ACCEPTED SOLUTIONS

With two words I have used this method with the Valid_IF which checks the first upper letter and small letters after that.

AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),1),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),1),2,10)),
INDEX(SPLIT([_THIS]," "),1)
)
>0,
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),2),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),2),2,10)),
INDEX(SPLIT([_THIS]," "),2)
)
>0
)

@MultiTech This came from AleksiAI ๐Ÿ˜‰

View solution in original post

Thanks,

This is what I was able to do with your help. It it almost as a PROPER function and works for 1 word OR 2 words OR 3 words:

OR(AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),1),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),1),2,15)),
INDEX(SPLIT([_THIS]," "),1)
)
>0,COUNT(SPLIT([_THIS]," "))=1),
AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),2),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),2),2,15)),
INDEX(SPLIT([_THIS]," "),2)
)
>0,COUNT(SPLIT([_THIS]," "))=2),
AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),3),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),3),2,15)),
INDEX(SPLIT([_THIS]," "),3)
)
>0,COUNT(SPLIT([_THIS]," "))=3)
)

 

Thanks again,

BR

View solution in original post

13 REPLIES 13

Aurelien
Google Developer Expert
Google Developer Expert

Hi @e4omir 

What about:

 

SWITCH(COUNT(SPLIT([_THIS], " ")),
  1,
  FIND( LEFT([_THIS],1) , UPPER( LEFT([_THIS],1) ) ) = 1,

  2,
  AND(
    FIND( LEFT(INDEX(SPLIT([_THIS]," "),1),1) , UPPER( LEFT(INDEX(SPLIT([_THIS]," "),1),1) ) ) = 1,  
    FIND( LEFT(INDEX(SPLIT([_THIS]," "),2),1) , UPPER( LEFT(INDEX(SPLIT([_THIS]," "),2),1) ) ) = 1  
  ),

  3,
  AND(
    FIND( LEFT(INDEX(SPLIT([_THIS]," "),1),1) , UPPER( LEFT(INDEX(SPLIT([_THIS]," "),1),1) ) ) = 1,  
    FIND( LEFT(INDEX(SPLIT([_THIS]," "),2),1) , UPPER( LEFT(INDEX(SPLIT([_THIS]," "),2),1) ) ) = 1,
    FIND( LEFT(INDEX(SPLIT([_THIS]," "),3),1) , UPPER( LEFT(INDEX(SPLIT([_THIS]," "),3),1) ) ) = 1  
  ),

  [and so on],

  FALSE (this is the default result)
)

 

For reference:

INDEX() - AppSheet Help

SPLIT() - AppSheet Help

LEFT() - AppSheet Help

SWITCH() - AppSheet Help

Inspired by this:

https://www.googlecloudcommunity.com/gc/AppSheet-Q-A/Force-data-entry-at-Form-to-be-all-UPPER-case/m...

EDIT:

minor correction for adding the default result to the SWITCH() expression.

Hi Aurelien,

It works for checking the First letter of each new word, however it is possible to be filled:

example - "SaMuel SmiTH SMITH".

The Pascal case basically is capital letter only for the first letter of the word, the rest letters should be in lower case. The excel function for this is PROPER, but the appsheet does not have it.

Thank you very much for your help.

BR

Complicated, as you've no doubt found so far.

  • I asked my AppSheet Ai assistant (code name Appster) how it might accomplish this; below is the exchange.

----------------------------------------------------------------------------------------------------------------------

[ME]
The Pascal case basically is capital letter only for the first letter of the word, the rest letters should be in lower case. The excel function for this is PROPER, but the AppSheet does not have it. Please give me an AppSheet formula that I could use in a valid-if that would enforce this text schema.
 

[Appster]
In AppSheet, there is no built-in function for the PROPER or Pascal case format. But, you can use a combination of other functions to achieve your goal.

You can first split the text at the spaces, then capitalize each separate word, and finally combine the words back together. Here's a general formula you can use as a starting point:

TEXT(  
  CONCATENATE(  
    UPPER(LEFT([Your_Column], 1)),  
    LOWER(MID([Your_Column], 2, LEN([Your_Column]) - 1))  
  ) 
)

This formula first separates the first letter of the input and turns it to uppercase, then extracts the rest of the string, turns it to lowercase, and finally combines them back together.

Here is where it gets more complicated: if you have more than one word (with spaces involved), then the formula would have to be enhanced significantly.

Unfortunately manipulating text in AppSheet to the degree needed for this functionality would be difficult, as you need to cycle through each word in your string and apply the formula to each.

In many cases, it might be more efficient to handle this kind of transformation in the data source (like Google Sheets or Excel) before fetching the data into AppSheet.

For specifically enforcing the Pascal case, you might want to create an assessment logic that checks if the first character in the string is not equal to its capital counterpart then shows an error message to the user. Keep in mind that AppSheet does not have the capability to transform a text string into Pascal case automatically.

[ME]
What if I wanted to check the first 4 words? Is there a way to accomplish this?

Yes, it is definitely possible to check the first four words within AppSheet. Here is how you can do it using a rather slightly more complex formula:

TEXT(
CONCATENATE(
UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 1), 1)),
LOWER(MID(INDEX(SPLIT([Your_Column], " "), 1), 2))
)
) & " " &
TEXT(
CONCATENATE(
UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 2), 1)),
LOWER(MID(INDEX(SPLIT([Your_Column], " "), 2), 2))
)
) & " " &
TEXT(
CONCATENATE(
UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 3), 1)),
LOWER(MID(INDEX(SPLIT([Your_Column], " "), 3), 2))
)
) & " " &
TEXT(
CONCATENATE(
UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 4), 1)),
LOWER(MID(INDEX(SPLIT([Your_Column], " "), 4), 2))
)
) & " " &
IF(COUNT(SPLIT([Your_Column], " ")) >= 5, MID([Your_Column], FIND(INDEX(SPLIT([Your_Column], " "), 5), [Your_Column]), LEN([Your_Column])), "")

Please replace `[Your_Column]` with the name of the actual column containing your data.

This formula splits up the first four words in your column ([Your_Column]), and then for each word, it changes the first character to uppercase and the rest of the word to lowercase.

Notice the "IF" at the end, which checks if there are more than 4 words. If there are 5 or more words in the text string, this piece will return everything starting with the 5th word (in the original case).

This solution is still a bit complicated and might be resource intensive if used on large texts, thus you should consider the balance between usability and formula complexity.

Also this does not force the Pascal case, but it would check if the first characters of initial four words are uppercase and rest lowercase. You might want to contact Matt at MultiTech Visions for additional support in optimizing your formula based on your specific requirements.

--------------------------------------------------------------------------------------------------------------------------

Thanks for the shout out my little Ai friend! (^_^)  ๐Ÿค–๐Ÿง ๐Ÿ’ช

Taking a critical look at that last formula... I'm not sure if the MID() would work.

  • I think mid() REQUIRES two numbers.
  • Confirmed; the documentation does not state any of these parameters are optional

--------------------------------------------------------------------------------------------------------------------------

[ME]

MID() requires that you specify the 3rd parameter; the length of text to select. Here's the documentation:
Syntax
MID(text, begin-at, length)

text - Any textual type.
begin-at - Number that specifies the position, equal to or greater than 1, of the first character in text to return. A non-Number value may be accepted but may produce unexpected results.
length -Non-negative number of characters from text to return. A non-Number value may be accepted but may produce unexpected results.

[Appster]

You're right, I apologize for the oversight. For the MID() function, the third argument, which signifies the length of the substring, must be specified.

Here is the revised formula for the first 4 words ensuring the third parameter of MID() function, the length, is properly defined:

TEXT( 
 CONCATENATE( 
 UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 1), 1)), 
 LOWER(MID(INDEX(SPLIT([Your_Column], " "), 1, MID(LEN(INDEX(SPLIT([Your_Column], " "), 1))-1))) 
 )
) & " " & 
TEXT( 
 CONCATENATE( 
 UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 2), 1)), 
 LOWER(MID(INDEX(SPLIT([Your_Column], " "), 2, MID(LEN(INDEX(SPLIT([Your_Column], " "), 2))-1))) 
 )
) & " " &
TEXT( 
 CONCATENATE( 
 UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 3), 1)), 
 LOWER(MID(INDEX(SPLIT([Your_Column], " "), 3, MID(LEN(INDEX(SPLIT([Your_Column], " "), 3))-1))) 
 )
) & " " & 
TEXT( 
 CONCATENATE( 
 UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 4), 1)), 
 LOWER(MID(INDEX(SPLIT([Your_Column], " "), 4, MID(LEN(INDEX(SPLIT([Your_Column], " "), 4))-1))) 
 )
) & " " &
IF(COUNT(SPLIT([Your_Column], " ")) >= 5, SUBSTR([Your_Column], LEN(LEFT([Your_Column], FIND(INDEX(SPLIT([Your_Column], " "), 5), [Your_Column]))+1), "")

This formula splits up the first four words in your string, then for each word, it changes the first character to uppercase and the rest of the character in that word to lowercase.

If there are 5 or more words in the text string, this piece of the formula will return everything starting with the 5th word onward, in the original case using the SUBSTR() function.

Remember, there is complexity and significant computational overhead associated with this formula. If you're dealing with a large volume of data, you may want to consider optimizing this process, possibly on the spreadsheet side.

However, this is already quite complex. Providing a perfect custom formula will depend on your exact requirements, you might want to discuss this problem with Matt at MultiTech Visions or someone who can guide you through building a more optimized AppSheet formula based on your exact needs.

I think it's really getting lost here... ๐Ÿคฃ๐Ÿคฃ๐Ÿคฃ

  • Indeed... it's starting to make very poor syntax errors now.
  • It did not put the closing parenthesis after the index:

MultiTech_0-1693433224546.png

Well... that's why it's still a prototype. haha

-------------------------------------------------------------------------------------------------------------------

[ME]

If you take a critical look at the formula you provided, there are some very basic syntax errors; such as the closing parenthesis for the 2nd index() formula:

CONCATENATE( 
 UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 1), 1)), 
 LOWER(MID(INDEX(SPLIT([Your_Column], " "), 1, MID(LEN(INDEX(SPLIT([Your_Column], " "), 1))-1))) 
 )
)

You also did not indicate a number for the length property for the MID() function; you started another mid(), but the syntax for this is incorrect as well.

Let's take things slower; please give me a formula that would work for 2 words, from there we can expand and work further.

[Appster]

I apologize for the confusion earlier, you're correct in noticing the error. Here is how you can break down the formula to process the first two words:

CONCATENATE(
    UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 1), 1)), 
    LOWER(MID(INDEX(SPLIT([Your_Column], " "), 1), 2, LEN(INDEX(SPLIT([Your_Column], " "), 1)) - 1))
) & " " &
CONCATENATE(
    UPPER(LEFT(INDEX(SPLIT([Your_Column], " "), 2), 1)),
    LOWER(MID(INDEX(SPLIT([Your_Column], " "), 2),  2, LEN(INDEX(SPLIT([Your_Column], " "), 2)) - 1))
)

Replace `[Your_Column]` with the name of the actual column containing your string. This formula splits the string into words, then for each of the first two words, it changes the first character to uppercase and the rest of the word to lowercase.

Still, understand that this function doesn't validate whether a string is in Pascal Case or not; it simply attempts to convert the first two words into Pascal Case. This function does not solve multi-word strings that have hyphen separated words or other non-space delimiters.

-------------------------------------------------------------------------------------------------------------------------

Well at least you can continue to work with it, pointing out specifics like that, and it will eventually figure it out.   There might have been  a way to word this at the beginning that might have accomplished the output we were hoping for (that being some monster formula that would work like 99% of the time).

With two words I have used this method with the Valid_IF which checks the first upper letter and small letters after that.

AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),1),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),1),2,10)),
INDEX(SPLIT([_THIS]," "),1)
)
>0,
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),2),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),2),2,10)),
INDEX(SPLIT([_THIS]," "),2)
)
>0
)

@MultiTech This came from AleksiAI ๐Ÿ˜‰

Thanks AleksiAlkio,

Your expression is working fine, but it should contain exact 2 names "Smith Smith", however you can fill "Smith Smith smiTH" with no problems. I changed it and added 3th name into the expression, but still the problem will be if someone fill 4 words into that field.

If someone from google is looking in this, please add the PROPER function to the appsheet. 

BR

You can add another validation like COUNT(SPLIT([_THIS]," "))<4 and then the user is not able to add more than 3 words.

Thanks,

This is what I was able to do with your help. It it almost as a PROPER function and works for 1 word OR 2 words OR 3 words:

OR(AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),1),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),1),2,15)),
INDEX(SPLIT([_THIS]," "),1)
)
>0,COUNT(SPLIT([_THIS]," "))=1),
AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),2),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),2),2,15)),
INDEX(SPLIT([_THIS]," "),2)
)
>0,COUNT(SPLIT([_THIS]," "))=2),
AND(
FIND(
UPPER(LEFT(INDEX(SPLIT([_THIS]," "),3),1))&LOWER(MID(INDEX(SPLIT([_THIS]," "),3),2,15)),
INDEX(SPLIT([_THIS]," "),3)
)
>0,COUNT(SPLIT([_THIS]," "))=3)
)

 

Thanks again,

BR

You need to wrap the COUNT() inside of the AND(), Now the validation will accept what ever word if there are 3 of them because of the OR().

This is exactly what I want, since the user could fill the name with only First Name OR with First and Last OR First, Second and Last Name. That's why I used OR at the beginning.

BR 

Okay ๐Ÿ™‚