VBA中的动态数字格式

时间:2016-12-10 06:13:29

标签: vba excel-vba excel

我试图用十进制数字将单位从ug / Kg更改为mg / Kg。为此,我使用一个函数来传递具有原始单位(ug / Kg)的单元格,并返回修改后的单位(mg / Kg)。该问题一直试图保持相同的有效数字。我已经弄清楚如何计算sig figs,但是我无法动态地将单元格修改为正确的位数。我在网上看到的例子看起来像这个Range(A1).NumberFormat =" 0.000"但这引用了单元格A1,我需要它来影响我试图返回的单元格。

下面的代码是我尝试做的一个例子,如果有人可以提供帮助我会很感激。

Function ToMg(rng As Range)

Dim OrigNumb As Double    
Dim NewNumb As Double

OrigNumb = rng.Cells(1).Value

' Converts ug/Kg to mg/Kg    
NewNumb = OrigNumb / 1000

' **Assume that this stared comment code represents code that calculates that  
' **the format for the new mg/Kg cell needs to be "0.000" dynamically

' The following command is what I need help with.  
' I don't know either how
' to reference the cell ToMg is returning data too, or how to correctly change  
' the number format to for example "0.000"

Me.NumberFormat = "0.000"

'This passes the modified data into the cell as desired,(but sig figs are wrong)

ToMg = NewNumb

End Function

**** ****编辑

测试

目标是拥有以下

Link to example

在我的脑海中,我看到左列(让我们说C),被列D调用。因此D的内容将是" = ToMg(C1)" (其中C1是左列中的第一个数据条目),其中D的数字格式是动态设置的。我不认为任何非动态数字格式将适用于我上面列出的所有情况。

2 个答案:

答案 0 :(得分:1)

可以使用以下VBA来设置数字格式,但每次计算时都会设置格式,因此可能会给计算带来明显的延迟,并且它是这不是推荐的做法

Function ToMg(rng As Range) As Double 'Use an explicit return type

  Dim OrigNumb As Double

  'Assuming the passed range is a single cell, you can omit the "Cells(1)"
  OrigNumb = rng.Value

  ' Converts ug/Kg to mg/Kg
  ToMg = OrigNumb / 1000

' **Assume that this stared comment code represents code that calculates that
' **the format for the new mg/Kg cell needs to be "0.000" dynamically
  Dim callingCell As Range
  Set callingCell = Application.Caller
  callingCell.NumberFormat = "0.000"

End Function

在格式化单元格时(但不在单元格中应用格式),最好是为所有结果设置一致的小数位数,或使用特殊数字格式#字符。

例如,假设我在单元格A1:A3中有3个值1,2,12.34和123.456

如果我应用##0.0##的自定义数字格式,则数字会按原样显示:

    1.2
  12.34
123.456

但是如果我将至少 2个整数位和至少2个十进制数字的格式应用为自定义格式#00.00#,则Excel会将数据显示为:

  01.20
  12.34
123.456

您尚未指定您所使用的确切格式,但如果您浏览Excel提供的自定义数字格式,您应该能够提供满足所有要求的格式,哪些可以是在之前设置,开始计算数字,不需要重复设置。

答案 1 :(得分:1)

正如已经指出的那样,如果你将该函数用作UDF,那么不应该达到格式化单元格本身的目标

我写了不应该因为有解决方法

例如:

  • 按如下方式更改您的功能

    Function ToMg(rng As Range) As String 'Use an explicit return type
      ToMg = (rng.Value / 1000) & "|" '<--| change the passed range content to the concatenation of wanted number and a "|" mark
    End Function
    
  • 在工作表代码窗格中添加以下代码

    Private Sub Worksheet_Change(ByVal Target As Range)
        If Right(Target.Value, 1) = "|" Then '<--| if changed cell is the one "marked" by 'ToMg()' function
            With Target '<--| reference changed cell
                .NumberFormat = "0.000" '<--| set its number format
                .Value = CDbl(Left(.Value, Len(.Value) - 1)) '<--| remove the "|" mark from its value
            End With
        End If
    End Sub
    

作为一项原则,您应该在更改Application.EnableEvents = False Target之前添加Value语句,以便在可能无限循环中再次触发相同的Worksheet_Change()

但在这种情况下它不会这样做,因为If Right(Target.Value, 1) = "|"检查将返回False,从而中止第一个(和最后一个)内部循环