我正在使用 VBA 将粘贴内容从 Excel 复制到 PowerPoint。它正在工作,但我需要清理我的代码。问题是,当涉及在多个过程中使用的变量(或对象)时,我不知道什么是好的做法。我想我在这方面缺乏一些基本的了解。
将变量从一个过程传递到另一个过程时,在两个过程中使用相同的名称是否是一个坏主意?所以例如
Sub 1()
Dim a As Long, b As Long
Call Sub2(a, b)
'...
End Sub
Sub2(a As Long, b As Long)
'...
End Sub
是否应该Sub2
以不同的方式调用变量,例如 x 和 y?如果没有,我将回到问题 1):直接从Sub1
to传递这些变量Sub2
而不是全局声明它们的原因是什么?当我打算在调用后使用a
and b
in的原始值时我得到了它(所以基本上将它作为to传递),但在我的情况下并非如此。Sub1
Sub2
ByVal
Sub2
是否有理由限制全局变量的使用?我留在了我的代码的地方,但我应该定义lRowAn
,lRowData
等全球?
我什么时候应该将一个变量从一个 sub 传递给另一个?在我下面的代码中,这样做iSlides
对我来说很有意义,但对于wsEm
.
以下是我的实际代码的一部分。SubsEmData
和EmDataAn
非常相似,我会看看是否可以合并它们,但它们很好地说明了我遇到的问题,因为它们使用了许多相同的变量。
Public mySlide As PowerPoint.Slide
Public PowerPointApp As PowerPoint.Application
Public myPresentation As PowerPoint.Presentation
Public MonatNum As String, JahrNum As String, MonatStr As String
Sub CreateReport()
Dim DestinationPPT As String
Dim iSlides As Integer
Dim fRowAn As Long, lRowAn As Long, lRowData As Long
Dim wbEm As Workbook
Dim wsEm As Worksheet
Set PowerPointApp = New PowerPoint.Application
DestinationPPT = "C:\VBA\ReportTemplate.pptm"
Set myPresentation = PowerPointApp.Presentations.Open(DestinationPPT)
Set wbEm = Workbooks.Open("C:\VBA\Report.xlsx")
Set wsEm = wbEm.Sheets("Sheet1")
lRowAn = wsEm.Cells(Rows.Count, 3).End(xlUp).Row
fRowAn = wsEm.Cells(Rows.Count, 3).End(xlUp).End(xlUp).Row + 1
If lRowAn >= 127 Then
If lRowData <= 127 Then '4 Slides, but separate Annotations from Data
iSlides = 1
Call EmData(wsEm, iSlides)
Call EmDataAn(wsEm, iSlides)
Else '4 Slides
iSlides = 3
Call EmData(wsEm, iSlides)
End If
Else '3 Slides
Call EmData(wsEm, iSlides)
End If
Application.DisplayAlerts = False
wbEm.Close SaveChanges:=False
Application.DisplayAlerts = True
PowerPointApp.Visible = True
PowerPointApp.Activate
Application.CutCopyMode = False
End Sub
Sub EmData(wsEm As Worksheet, iSlides As Integer)
Dim i As Integer
Dim fRowDataCalc As Long, lRowDataCalc As Long, lRowCopy As Long
Dim rowHght As Long
Dim rng As Range
For i = 0 To iSlides
fRowDataCalc = 4 + 40 * i + i * 1
lRowDataCalc = 4 + 40 * (i + 1) + i * 1
With wsEm
.Range("B2:K3").Copy .Range("B500")
.Range("B" & fRowDataCalc & ":K" & lRowDataCalc).Copy .Range("B502")
rowHght = .Range("B3").EntireRow.Height
.Range("B501").RowHeight = rowHght
lRowCopy = .Cells(Rows.Count, "C").End(xlUp).Row
Set rng = .Range("B500:K" & lRowCopy)
End With
Set mySlide = myPresentation.Slides.AddSlide(myPresentation.Slides.Count + 1, PPLayout("LayoutEmittenten"))
mySlide.Shapes.Placeholders(1).TextFrame.TextRange.Text = "Headline (" & i + 1 & ")"
Call PasteEm(mySlide, rng)
rng.Clear
Next i
End Sub
Sub EmDataAn(wsEm As Worksheet, iSlides As Integer)
Dim lRowAn As Long, fRowAn As Long, lRowData As Long, fRowDataCalc As Long, lRowDataCalc As Long
Dim rng As Range
Dim rowHght As Long, lRowCopy As Long
lRowAn = wsEm.Cells(Rows.Count, 3).End(xlUp).Row
fRowAn = wsEm.Cells(Rows.Count, 3).End(xlUp).End(xlUp).Row - 1
lRowData = wsEm.Cells(Rows.Count, 10).End(xlUp).Row
iSlides = iSlides + 1
fRowDataCalc = 4 + 40 * iSlides + iSlides * 1
lRowDataCalc = lRowData
'Last sheet with data
With wsEm
.Range("B2:K3").Copy .Range("B500")
.Range("B" & fRowDataCalc & ":K" & lRowDataCalc).Copy .Range("B502")
rowHght = .Range("B3").EntireRow.Height
.Range("B501").RowHeight = rowHght
lRowCopy = .Cells(Rows.Count, "C").End(xlUp).Row
Set rng = .Range("B500:K" & lRowCopy)
End With
Set mySlide = myPresentation.Slides.AddSlide(myPresentation.Slides.Count + 1, PPLayout("LayoutEmittenten"))
mySlide.Shapes.Placeholders(1).TextFrame.TextRange.Text = "Headline (" & iSlides + 2 & ")"
Call PasteEm(mySlide, rng)
rng.Clear
'Annotations
Set rng = wsEm.Range("B" & fRowAn & ":K" & lRowAn)
rng.Copy
Set mySlide = myPresentation.Slides.AddSlide(myPresentation.Slides.Count + 1, PPLayout("LayoutEmittenten"))
mySlide.Shapes.Placeholders(1).TextFrame.TextRange.Text = "Headline (" & iSlides + 2 & ")"
Call PasteEm(mySlide, rng)
End Sub
Sub PasteEm(mySlide As PowerPoint.Slide, rng As Range)
Dim myShape As PowerPoint.Shape
rng.Copy
DoEvents
mySlide.Shapes.PasteSpecial DataType:=ppPasteEnhancedMetafile ' = 2
Set myShape = mySlide.Shapes(mySlide.Shapes.Count)
With myShape
.Width = 683
.Top = 70
.Left = 5
End With
End Sub
这不是关于代码功能,而是如何使用变量。
首先,尽可能将每个变量声明为局部变量。例如,如果仅在一个过程/函数中需要它,请在那里声明它。
如果您需要在多个过程/函数中访问变量,那么最好将它作为参数传递给下一个函数。这可以完成ByRef
(这是默认设置)或ByVal
.
Sub ProcedureA()
Dim ParamA As String
ParamA = "AAA"
Dim ParamB As String
ParamB = "BBB"
ProcedureB ParamA, ParamB
Debug.Print ParamA 'returns 111
Debug.Print ParamB 'returns BBB
End Sub
Sub ProcedureB(ByRef Param1 As String, ByVal Param2 As String)
Param1 = "111" 'this will change ParamA in ProcedureA too
Param2 = "222" 'this value will only be changed in ProcedureB
End Sub
虽然使用ByRef
(按引用)可以更改 中的参数ProcedureB
并使其也在 中更改ProcedureA
,但ByVal
(按值)传递的参数不会更改 中的参数ProcedureA
。
如果您以不同的方式命名变量或使用相同的名称,从技术上讲,这里没有任何区别。使用在每个过程中最有意义的名称将是一个好习惯(请参阅下面的标题变量名称)。
其实我觉得这也是一个很好的做法,始终指定如果ByRef
还是ByVal
不使用默认值。使用默认值时,您始终必须记住它ByRef
在 VBA 中是默认值,但在 VB.NET 中,默认值ByVal
很容易让人感到困惑(至少我是)。
结束后ProcedureA
变量不再可用(数据丢失)。
如果您希望数据在多个函数中持久且可访问,请使用全局变量(尽可能少地使用它们)。
Dim GlobalVarA As String
Sub ProcedureA()
GlobalVarA = "AAA"
End Sub
Sub ProcedureB()
Debug.Print GlobalVarA 'return AAA (if ProcedureA was run before)
End Sub
请注意,在这种情况下,任何过程都可以更改 的值GlobalVarA
。如果如上所述将其作为参数传递,则只有传递该变量的过程才能访问该变量。
Excel VBA 结束(或文件关闭)时,全局变量将丢失其数据。
在过程中使用全局变量的缺点是,您需要在第一次使用之前检查它的值。因为如果它尚未初始化,它就是Empty
or Nothing
。例如(上图)运行时,ProcedureB
您不能依赖ProcedureA
之前已经运行过的。所以你需要GlobalVarA
在使用它之前检查它的值,ProcedureB
特别是如果它是一个你必须测试的对象,Nothing
否则你很容易遇到错误。
所以我们可以总结一下,尽可能多地限制对变量的访问可以使您的代码更安全、更可靠(如果仅在本地声明,则没有其他函数可以意外更改它)。仅在您确实需要时才使用全局变量。
如果变量名是在本地声明的,那么重用变量名通常没有问题。但是,如果您对全局变量和局部变量使用相同的名称(那么 VBA 更喜欢本地变量!)
Dim VarA As String 'global
Sub ProcedureA()
Dim VarA As String 'same name local
VarA = "AAA" 'this uses always the local variable!
End Sub
Sub ProcedureB()
Debug.Print VarA 'this uses the global variable and it is empty (after ProcedureA is run)
End Sub
一般来说,只使用有意义的变量名是一个很好的做法。这意味着不要调用变量rng1
并rng2
调用它们,例如InputRange
and OutputRange
。此外,如果您经常需要一个计数器(例如循环遍历行和列)i
并经常j
使用,但如果您使用 egiRow
和iCol
作为变量名,它会更具可读性。
为了强制正确的变量声明,我建议始终激活Option Explicit
:在 VBA 编辑器中,转到工具›选项›需要变量声明。这可以防止您输入错误的变量名称和意外引入新变量。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句