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



在我的代码中,我使用了一个执行一些文本格式的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。

根本不知道为什么会发生这种情况,但一种解决方法似乎是手动调用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$100rng.Rows.Count将是 97,并且您对Cells(i, y)的所有引用都将偏离 3。

目前还不清楚ispcname(c.Value) = True Or isip(c.Value) = TrueRight(c, 1) = "$"是否相互排斥。 如果是,If Right(c, 1) = "$"实际上应该是一个ElseIf

其他几件事:

  1. 在一行语句中执行 5 个不同的语句If是 难以置信地难以阅读,这使得它容易出错。使用实际If...End If块,除非动作是微不足道的Exit Sub.
  2. 第二If Right(c, 1) = "$" Then总是正确的。 它可以完全删除。
  3. 实际格式化代码后 一种可读的方式,很明显您正在使用call 的属性 在For Each c In rng环内的地方。 我会把它放在一个With块。
  4. 您只需要使用一次ActiveSheet。 然后 您可以从rng.Parent获得它,或者(更好)获得 引用它。
  5. 养成使用String退货的习惯 函数而不是在需要时Variant返回函数String. J.F.Right$而不是Right- 后者执行 隐式演员表。
  6. 完全限定您对Cells的所有引用。
  7. 避免隐式使用对象的默认属性,即Range.Value.
  8. 对行计数器使用Long,而不是Integer以避免溢出的可能性。
  9. 使用vbNullString而不是文字""
  10. Font.Size以点为单位。 它应该是一个数字,而不是一个字符串。

它应该看起来更像这样:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim c As Range
Dim sh As Worksheet
Set sh = ActiveSheet    'Tip 4
Dim rng As Range
Set rng = sh.UsedRange.Cells
For Each c In rng
With c  'Tip 3
If ispcname(.Value) Or isip(.Value) Then  'Tip 1
sh.Hyperlinks.Add Anchor:=c, Address:=vbNullString    'Tips 4 and 9
.HorizontalAlignment = xlCenter
.Value = StrConv(.Value, vbProperCase)  'Tip 7
.Font.Name = "Arial"
.Font.Size = 10     'Tip 10
End If  'Pretty sure this should be an ElseIf structure here.
If Right$(.Value, 1) = "$" Then  'Tips 5 and 7.
y = .Column
x = .Row
Dim i As Long   'Tip 8
For i = 1 To rng.Rows.Count     'This is most likely wrong.
'Tip 2 used to be here.
If LCase$(sh.Cells(i, y).Value) = "backup" Then     'Tips 1, 5, and 6
.Value = sh.Cells(x, y - 2).Value & "$"   'Tips 4, 6, and 7
sh.Hyperlinks.Add Anchor:=c, Address:=vbNullString    'Tips 4 and 9
.Font.Name = "Calibri"
.Font.Size = 10     'Tip 10
.HorizontalAlignment = xlCenter
.Font.Color = RGB(192, 0, 0)
End If
Next i
End If
End With
Next c
End Sub

如果使用"$"表示单元格是货币,请不要测试最后一个字符是否为"$"。 您必须检查单元格是否具有货币格式。

修改行

if right(c,1)= "$"

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

您的测试永远不会在 C 中找到"$"。

最新更新