如何检测单元格格式的变化?

时间:2022-01-12 02:27:29

I want to embed a procedure in an Excel sheet that will detect when a cell's format changes, e.g. from Text to Number.

我想在Excel工作表中嵌入一个过程,该过程将检测单元格格式何时发生变化,例如从文本到数字。

But I can't figure out how to get the cell's format type. I tried using the Worksheet_Change event handler to check the data type, as follows:

但我无法弄清楚如何获取单元格的格式类型。我尝试使用Worksheet_Change事件处理程序来检查数据类型,如下所示:

Private Sub worksheet_change(ByVal Target As Range)

If Target.Address = "a1" Then
    If VarType(Target) <> 5 Then
        MsgBox "cell format has been changed"
    End If
End If


End Sub

But with this code in place, if I change cell A1's data type from Number to Text, Worksheet_Change is not triggered; the event handler is only called if I change the contents of the cell.

但是有了这个代码,如果我将单元格A1的数据类型从Number更改为Text,则不会触发Worksheet_Change;只有在我更改单元格的内容时才会调用事件处理程序。

Also, this procedure can detect if the contents are changed from a number to an alphabetical string, e.g. from "35.12" to "abcd", but not Number-type number to Text-type number; if I set cell B1 to text, then enter "40", then paste the contents of cell B1 into cell A1, vartype() still returns "5", so the alert is not triggered.

此外,该过程可以检测内容是否从数字改变为字母串,例如,从“35.12”到“abcd”,但不是Number-type number到Text-type number;如果我将单元格B1设置为文本,然后输入“40”,然后将单元格B1的内容粘贴到单元格A1中,则vartype()仍然返回“5”,因此不会触发警报。

How can I detect that the format has changed, regardless of whether the content type has changed?

无论内容类型是否已更改,如何检测格式是否已更改?

3 个解决方案

#1


2  

Great question!

好问题!

If you are only looking to trigger an event on the NumberFormat change (you appear to be calling this incorrectly the data format, NumberFormat is the attribute you want), the following is a good example.

如果您只想在NumberFormat更改上触发事件(您似乎错误地调用了数据格式,NumberFormat是您想要的属性),以下是一个很好的示例。

I'm intercepting all selection change events and checking if any NumberFormat changed.

我正在拦截所有选择更改事件并检查是否有任何NumberFormat更改。

Option Explicit

'keep track of the previous
Public m_numberFormatDictionary As New dictionary
Public m_previousRange As Range

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    'requires reference to Microsoft Scripting Runtime

    Dim c As Variant
    Dim wasChange As Boolean


    Debug.Print "***********************"

    'make sure you had a previous selection and it was initialized
    If m_numberFormatDictionary.Count > 0 And Not m_previousRange Is Nothing Then

        'Iterate through all your previous formattings and see if they are the same
        For Each c In m_previousRange
            Debug.Print "Found " & c.NumberFormat & " in " & c.Address
            Debug.Print "Stored value is " & m_numberFormatDictionary(c.Address) & " in " & c.Address

            'print out when they are different
            If c.NumberFormat <> m_numberFormatDictionary(c.Address) Then
                Debug.Print "~~~~~~ Different ~~~~~~"
                wasChange = True
            End If

        Next c
    End If

    'clear previous values
    m_numberFormatDictionary.RemoveAll

    'Make sure you don't error out Excel by checking a million things
    If Target.Cells.Count < 1000 Then

        'Add each cell format back into the previous formatting
        For Each c In Target
            Debug.Print "Adding " & c.NumberFormat & " to " & c.Address
            m_numberFormatDictionary.Add c.Address, c.NumberFormat
        Next c

        'reset the range to what you just selected
        Set m_previousRange = Target
    End If

    'simple prompt now, not sure what your use case is
    If wasChange Then
        MsgBox "There was at least one change!"
    End If

End Sub

I'm not exactly sure what you are looking for, you'll have to modify the print/msgbox statements appropriately. Depending on your use case you may have to modify this slightly but it works in all my test examples.

我不确定你在寻找什么,你必须适当地修改print / msgbox语句。根据您的使用情况,您可能需要稍微修改它,但它适用于我的所有测试示例。

#2


1  

there does not appear to be an event that fires when a cells format type changes.

当单元格格式类型更改时,似乎没有触发的事件。

however, I got this info from another forum site.

但是,我从另一个论坛网站获得了这个信息。

To edit a cells format without the use of a macro the cells must be selected (via left click then an icon, or right click). so, using the worksheets SelectionChanged, whenever a cell is selected you grab the format and address of that cell as well as check the address and format of the previous cell VS what the format of the previous cell is now. thus, if the format of the previous cell is different now than it was when last captured, it has been changed.

要在不使用宏的情况下编辑单元格格式,必须选择单元格(通过左键单击,然后单击图标或右键单击)。因此,使用工作表SelectionChanged,每当选择一个单元格时,您将获取该单元格的格式和地址,并检查前一个单元格的地址和格式VS前一个单元格的格式。因此,如果前一个单元格的格式现在与上次捕获的格式不同,则它已被更改。

You can use this in conjuction with the change event, to see if the format has been changed between now (after the cells contents have changed) and when the cell was selected.

您可以将此与变更事件结合使用,以查看格式是否已在现在(单元格内容更改后)和选择单元格之间进行了更改。

here's the link to the other forum as I cant claim this as my own invention: http://www.mrexcel.com/forum/excel-questions/3704-calculate-format-change.html

这里是其他论坛的链接,因为我不能将其称为我自己的发明:http://www.mrexcel.com/forum/excel-questions/3704-calculate-format-change.html

#3


0  

Based on this response on * here is some code that might work for you, assuming the change will be user generated and the selected range will change after they make the change...

根据*上的这个响应,这里有一些代码可能适用于您,假设更改将由用户生成,并且所选范围将在进行更改后更改...

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    Static LastRange As Range
    Static LastNumberFormat As String

    If Not LastRange Is Nothing Then
        If LastRange.Cells(1).NumberFormat <> LastNumberFormat Then
            'Your action or message box notification goes here
        End If
    End If

    Set LastRange = Target
    LastNumberFormat = Target.NumberFormat

End Sub

#1


2  

Great question!

好问题!

If you are only looking to trigger an event on the NumberFormat change (you appear to be calling this incorrectly the data format, NumberFormat is the attribute you want), the following is a good example.

如果您只想在NumberFormat更改上触发事件(您似乎错误地调用了数据格式,NumberFormat是您想要的属性),以下是一个很好的示例。

I'm intercepting all selection change events and checking if any NumberFormat changed.

我正在拦截所有选择更改事件并检查是否有任何NumberFormat更改。

Option Explicit

'keep track of the previous
Public m_numberFormatDictionary As New dictionary
Public m_previousRange As Range

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    'requires reference to Microsoft Scripting Runtime

    Dim c As Variant
    Dim wasChange As Boolean


    Debug.Print "***********************"

    'make sure you had a previous selection and it was initialized
    If m_numberFormatDictionary.Count > 0 And Not m_previousRange Is Nothing Then

        'Iterate through all your previous formattings and see if they are the same
        For Each c In m_previousRange
            Debug.Print "Found " & c.NumberFormat & " in " & c.Address
            Debug.Print "Stored value is " & m_numberFormatDictionary(c.Address) & " in " & c.Address

            'print out when they are different
            If c.NumberFormat <> m_numberFormatDictionary(c.Address) Then
                Debug.Print "~~~~~~ Different ~~~~~~"
                wasChange = True
            End If

        Next c
    End If

    'clear previous values
    m_numberFormatDictionary.RemoveAll

    'Make sure you don't error out Excel by checking a million things
    If Target.Cells.Count < 1000 Then

        'Add each cell format back into the previous formatting
        For Each c In Target
            Debug.Print "Adding " & c.NumberFormat & " to " & c.Address
            m_numberFormatDictionary.Add c.Address, c.NumberFormat
        Next c

        'reset the range to what you just selected
        Set m_previousRange = Target
    End If

    'simple prompt now, not sure what your use case is
    If wasChange Then
        MsgBox "There was at least one change!"
    End If

End Sub

I'm not exactly sure what you are looking for, you'll have to modify the print/msgbox statements appropriately. Depending on your use case you may have to modify this slightly but it works in all my test examples.

我不确定你在寻找什么,你必须适当地修改print / msgbox语句。根据您的使用情况,您可能需要稍微修改它,但它适用于我的所有测试示例。

#2


1  

there does not appear to be an event that fires when a cells format type changes.

当单元格格式类型更改时,似乎没有触发的事件。

however, I got this info from another forum site.

但是,我从另一个论坛网站获得了这个信息。

To edit a cells format without the use of a macro the cells must be selected (via left click then an icon, or right click). so, using the worksheets SelectionChanged, whenever a cell is selected you grab the format and address of that cell as well as check the address and format of the previous cell VS what the format of the previous cell is now. thus, if the format of the previous cell is different now than it was when last captured, it has been changed.

要在不使用宏的情况下编辑单元格格式,必须选择单元格(通过左键单击,然后单击图标或右键单击)。因此,使用工作表SelectionChanged,每当选择一个单元格时,您将获取该单元格的格式和地址,并检查前一个单元格的地址和格式VS前一个单元格的格式。因此,如果前一个单元格的格式现在与上次捕获的格式不同,则它已被更改。

You can use this in conjuction with the change event, to see if the format has been changed between now (after the cells contents have changed) and when the cell was selected.

您可以将此与变更事件结合使用,以查看格式是否已在现在(单元格内容更改后)和选择单元格之间进行了更改。

here's the link to the other forum as I cant claim this as my own invention: http://www.mrexcel.com/forum/excel-questions/3704-calculate-format-change.html

这里是其他论坛的链接,因为我不能将其称为我自己的发明:http://www.mrexcel.com/forum/excel-questions/3704-calculate-format-change.html

#3


0  

Based on this response on * here is some code that might work for you, assuming the change will be user generated and the selected range will change after they make the change...

根据*上的这个响应,这里有一些代码可能适用于您,假设更改将由用户生成,并且所选范围将在进行更改后更改...

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    Static LastRange As Range
    Static LastNumberFormat As String

    If Not LastRange Is Nothing Then
        If LastRange.Cells(1).NumberFormat <> LastNumberFormat Then
            'Your action or message box notification goes here
        End If
    End If

    Set LastRange = Target
    LastNumberFormat = Target.NumberFormat

End Sub