Excel - Формат значения (маска) - PullRequest
1 голос
/ 15 декабря 2011

Я бы хотел отформатировать значение ячейки следующим образом:

1234,980 -> 1,234,980

12237119867,761 -> 12,237.119,867,761

Как подготовить общую маску, которая будет устанавливать точки как тысячи разделителей и запятую для десятичных знаков Маска должна работать для любого заданного значения.

1 Ответ

5 голосов
/ 15 декабря 2011

Определить первый сегмент слева от десятичной точки.При необходимости он будет автоматически продублирован.
Количество окто-верп после точки задает максимальное количество знаков после запятой после точки, будет использоваться только необходимое число.

Что-то вроде:

#.###,0##

(я предполагаю, что это будет допустимо для вашей текущей локали).

В соответствии с комментарием phoog , независимый от локали формат будет:

#,###.0##

(используйте это для установки формата, используя Cell.NumberFormat = "#,###.0##")


Что касается некоторого кода VBA, у вас может быть расширенная версия функции Format, которая принимает два языка,тот, в котором находится строка формата, а другой - для форматирования результата.

Поместите следующее в отдельный модуль:

Option Explicit

Private Declare Function VarTokenizeFormatString Lib "oleaut32.dll" (ByVal pstrFormat As Long, ByRef rgbTok As Any, ByVal cbTok As Long, ByVal iFirstDay As VbDayOfWeek, ByVal iFirstWeek As VbFirstWeekOfYear, ByVal lcid As Long, ByRef pcbActual As Long) As Long
Private Declare Function VarFormatFromTokens Lib "oleaut32.dll" (ByRef pvarIn As Variant, ByVal pstrFormat As Long, ByRef pbTokCur As Any, ByVal dwFlags As Long, ByRef pbstrOut As Long, ByVal lcid As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Const S_OK As Long = 0
Private Const E_INVALIDARG As Long = &H80070057
Private Const E_OUTOFMEMORY As Long = &H8007000E
Private Const DISP_E_BUFFERTOOSMALL As Long = &H80020013
Private Const DISP_E_TYPEMISMATCH As Long = &H80020005


Public Function FormatForLocale(ByVal Expression As Variant, Optional ByVal Format As String, Optional ByVal FirstDayOfWeek As VbDayOfWeek = vbUseSystemDayOfWeek, Optional ByVal FirstWeekOfYear As VbFirstWeekOfYear = vbUseSystem, Optional ByVal PatternLocaleID As Long = 0, Optional ByVal TargetLocaleID As Long = 0) As String
  Dim b() As Byte, t As Long
  Dim hResult As Long
  Dim pBstrResult As Long, res As String

  Const CHUNK_SIZE As Long = 256


  If TypeOf Expression Is Excel.Range Then
    Expression = Expression.Value
  End If


  ReDim b(1 To CHUNK_SIZE)

  Do
    hResult = VarTokenizeFormatString(StrPtr(Format), b(LBound(b)), UBound(b) - LBound(b) + 1, FirstDayOfWeek, FirstWeekOfYear, PatternLocaleID, t)

    Select Case hResult
    Case S_OK
      Exit Do
    Case E_INVALIDARG
      Err.Raise 5, , "Some arguments are invalid."
    Case DISP_E_BUFFERTOOSMALL
      ReDim b(LBound(b) To UBound(b) + CHUNK_SIZE)
    Case Else
      Err.Raise 5, , "Internal error. Unexpected error code returned from system."
    End Select
  Loop

  Select Case VarFormatFromTokens(Expression, StrPtr(Format), b(LBound(b)), 0, pBstrResult, TargetLocaleID)
  Case S_OK
    CopyMemory ByVal VarPtr(res), pBstrResult, 4
  Case E_OUTOFMEMORY
    Err.Raise 7
  Case E_INVALIDARG
    Err.Raise 5, , "Some arguments are invalid."
  Case DISP_E_TYPEMISMATCH
    Err.Raise 5, , "The argument could not be coerced to the specified type."
  Case Else
    Err.Raise 5, , "Internal error. Unexpected error code returned from system."
  End Select

  FormatForLocale = res
End Function

Теперь у вас есть функция, FormatForLocale, которая имитирует функцию VBA Format по умолчанию, но добавляет два дополнительных параметра.Чтобы получить желаемый результат, вы можете сделать:

result = FormatForLocale(123456789, "#,###.0##", , , LOCALE_INVARIANT, LOCALE_GERMAN)

, где LOCALE_INVARIANT и LOCALE_GERMAN - это константы, которые вы можете посмотреть здесь .

Вы можететакже вызовите его с рабочего листа:

=FormatForLocale(123456789,"#,###.0##",,,127,3079)
...