Excel VBA错误/异常 - ActiveWorkbook.Save更改Workbook_BeforeSave函数

时间:2016-12-01 15:05:44

标签: excel vba excel-vba

在我的代码中,我使用Workbook_BeforeSave函数执行一些文本格式化。

当我点击“保存”按钮时,它会运行并格式化某些单元格的大小和字体类型 以下是执行此任务的代码的一部分:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

Dim c As Range
Dim rng As Range
Set rng = ActiveSheet.UsedRange.Cells

For Each c In rng
    If ispcname(c.Value) = True Or isip(c.Value) = True Then ActiveSheet.Hyperlinks.Add Anchor:=c, Address:="": c.HorizontalAlignment = xlCenter: c = StrConv(c, vbProperCase): c.Font.Name = "Arial": c.Font.Size = "10"
    If Right(c, 1) = "$" Then 
        y = c.Column: x = c.Row

        Dim i As Integer
        For i = 1 To rng.Rows.Count
            If LCase(Cells(i, y).Value) = "backup" Then
                If  Right(c, 1) = "$" Then Cells(x, y) = Cells(x, y - 2) & "$": ActiveSheet.Hyperlinks.Add Anchor:=c, Address:="": c.Font.Name = "Calibri": c.Font.Size = "10": c.HorizontalAlignment = xlCenter: c.Font.Color = RGB(192, 0, 0)
            End If
        Next i
    End If
Next c
End Sub

我最近实现了一个代码,如果它被关闭,它将保存工作簿。

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Application.DisplayAlerts = False
        ActiveWorkbook.Save
    Application.DisplayAlerts = True
End Sub

然后出现了我无法解释的错误。当ActiveWorkbook.Save运行时,应更改为Calibri的单元格将更改为Arial,大小保持不变,颜色正常工作。但是,当我手动点击保存按钮时,它可以正常工作。 (将单元格更改回Calibri

没有其他代码干扰,因为当我注释掉将字体类型更改为Calibri的部分时,ActiveWorkbook.Save也停止将其更改为Arial

我的问题是:

  • 为什么会这样?这是一个错误吗?
  • 有解决方法吗?

我正在使用Excel 2007。

2 个答案:

答案 0 :(得分:1)

根本不确定为什么会发生这种情况,但是一种解决方法似乎是手动调用Workbook_BeforeSave,然后针对ActiveWorkbook.Save调用禁用它:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Application.DisplayAlerts = False
    Application.EnableEvents = False
    Workbook_BeforeSave False, False    'Manual call.
    Me.Save                             'Save without the event firing again.
    Application.EnableEvents = True
    Application.DisplayAlerts = True
End Sub

那就是说,你在Workbook_BeforeSave处理程序中也有一些好奇的逻辑。首先,我不认为For i = 1 To rng.Rows.Count正在按照您的想法行事。它不一定会在整个列上循环,因为UsedRange.Cells不必从第1行开始。如果您使用的范围类似于$A$4:$Z$100,{{1}将是97,你对rng.Rows.Count的所有引用都将被3关闭。

如果Cells(i, y)ispcname(c.Value) = True Or isip(c.Value) = True是互斥的,也不清楚。如果是,Right(c, 1) = "$"实际上应该是If Right(c, 1) = "$"

结合其他事情:

  1. 在一行ElseIf语句中执行5个不同的语句 非常难以阅读,这使它容易出错。使用实际 If阻止,除非行动是微不足道的 If...End If
  2. 第二个Exit Sub始终为真。 它可以完全删除。
  3. 实际格式化代码后 这是一种可读的方式,很明显您使用的是If Right(c, 1) = "$" Then所有属性 在c循环内的位置。我把它放进去了 For Each c In rng阻止。
  4. 您只需使用With一次。之后, 你可以从ActiveSheet获得它,或者(更好)得到它 参考它。
  5. 养成使用rng.Parent返回的习惯 当你需要时,函数而不是String返回函数 Variant。即String代替Right$ - 后者执行 隐式演员。
  6. 完全限定您对Right的所有引用。
  7. 避免隐式使用对象的默认属性,即Cells
  8. 对行计数器使用Range.Value,而不是Long以避免溢出的可能性。
  9. Use vbNullString instead of the literal ""
  10. Integer以分数衡量。它应该是一个数字,而不是一个字符串。
  11. 看起来应该更像这样:

    Font.Size

答案 1 :(得分:0)

如果您正在使用" $"要说单元格是一种货币,不要测试最后一个字符是否为" $"。你必须检查单元格是否有货币格式。

修改行

if right(c,1)= "$"

fc = c.NumberFormat
    If InStr(1, c, "$") = 0 Then ...

你的测试永远不会找到" $"在c。