如何在 Excel 中使用小法语单词获得正确的大小写,例如 "sur" NOT "Sur" "de" NOT "De"

How to get proper case in Excel with small French words, such as "sur" NOT "Sur" "de" NOT "De"

我正在尝试使用 VBA 更正 Excel 工作表的多次调用中法语专有名词首字母的大小写。我有很多不同的人输入的数据,有些是小写的,有些是大写的,有些是混合的,等等。

我正在寻找比 PROPER() 函数更好的函数。虽然在单元格的公式中使用 PROPER() 可以为大多数名称提供正确的结果(通过将单词中的第一个字母设置为大写并将其余字母设置为小写),但当名称包含介词时会给出错误的结果。

在法语中,简单名称通常以大写字母开头,但介词通常以小写字母开头。这就是我想要实现的。

法语专有名词的正确大小写示例:

  1. 让·德维伦纽夫
  2. 罗曼尼康帝庄园
  3. Cellier des Rois

PROPER() 函数的结果是错误的::

  1. 让·德维伦纽瓦
  2. 罗曼尼康帝庄园
  3. Cellier Des Rois

有什么简单的方法可以使用 VBA 将正确的法语大小写应用于专有名词吗?

如果可能的话,我希望所有单词的单元格首字母大写。

为此您需要一个自定义函数,因为如您所述,PROPER 仅将给定字符串中每个单词的第一个字母大写。

标准模块(例如Module1)添加到您的VBA项目中,并在其中实现一个用户定义的函数:

Option Explicit

Public Function ProperFR(ByVal Value As String) As String

    ' let's start with an array of all words in the input value.
    Dim words As Variant
    ' we use the VBA.Strings.Split function to split the string at each space.
    words = Split(Value, " ")

    ' now let's identify all words we do not want to capitalize:
    Dim nocaps() As Variant
    nocaps = Array("le", "la", "les", "du", "de", "des", "sur")

    ' now we can iterate each word; we know how many there are so we use a For loop.
    Dim i As Long
    For i = LBound(words) To UBound(words) ' never assume array lower/upper bounds

        ' let's copy the current word into a local variable:
        Dim word As String
        word = words(i)

        If i > LBound(words) Then ' always capitalize the first word
            If ArrayContains(nocaps, word) Then
                ' lowercase word
                word = LCase$(word)
            Else
                word = Application.WorksheetFunction.Proper(word)
            End If
        Else
            ' Proper function works fine otherwise
            word = Application.WorksheetFunction.Proper(word)
        End If
        
        ' store the cased word back into the array:
        words(i) = word
        
    Next

    ' assemble the words array back into a string, and return it:
    ProperFR = Join(words, " ")

End Function

Private Function ArrayContains(ByRef Values As Variant, ByVal Value As String) As Boolean
    Debug.Assert IsArray(Values)
    Dim i As Long
    For i = LBound(Values) To UBound(Values)
        ' we use StrComp for an explicit case-insensitive match:
        If StrComp(Values(i), Value, vbTextCompare) = 0 Then
            ArrayContains = True
            Exit Function ' no need to keep looping
        End If
    Next
End Function

现在您可以执行 =ProperFR("Domaine De La Romanée-Conti") 并获得 Domaine de la Romanée-Conti 作为输出。