如何使此代码更简单?

时间:2019-04-18 19:55:09

标签: excel vba

我对VBA还是很陌生,我想知道如何简化此代码? 该代码基本上将字段添加到数据透视表中的值。

Dim pt As PivotTable
Dim pf As PivotField
Dim SField As String

'Set Variable
Set pt = ActiveSheet.PivotTables(1)
SField = ActiveSheet.Shapes(Application.Caller).TextFrame.Characters.Text

'Remove Existing Fields
For Each pf In pt.DataFields
If pf.Name <> "Values" Then
    pf.Orientation = xlHidden
End If
Next pf

ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2016"), "Sum of 2016", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2017"), "Sum of 2017", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2018"), "Sum of 2018", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2019"), "Sum of 2019", xlSum

End Sub

2 个答案:

答案 0 :(得分:2)

ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2016"), "Sum of 2016", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2017"), "Sum of 2017", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2018"), "Sum of 2018", xlSum
ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields("2019"), "Sum of 2019", xlSum

U可以创建一个函数

Public Sub PvSumByYear(year As String)
    ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
    "PivotTable1").PivotFields(year), "Sum of " & year, xlSum
End Sub 

现在使用

for i = 6 to 9
    call  PvSumByYear(Vba.cstr(2010+ i))
next i  

答案 1 :(得分:1)

Dim pt As PivotTable
Dim pf As PivotField
Dim SField As String

首先从不在程序顶部的单块声明变量开始,而是在尽可能接近其首次使用/赋值的位置声明变量。并使用清楚表达的,可读的标识符传达语义含义,而不仅仅是它们的数据类型。

Dim target As PivotTable
Set target = ActiveSheet.PivotTables(1)

RemoveExistingFields target

通知SField已消失-已分配,但从未在任何地方引用。注释“在XYZ之下执行代码”几乎总是错失更好抽象的机会:​​

Private Sub RemoveExistingFields(ByVal target As PivotTable)
    Dim currentField As PivotField
    For Each currentField In target.DataFields
        If currentField.Name <> "Values" Then currentField.Orientation = xlHidden
    Next
End Sub

单手提取此过程就无需在原始范围内声明pf / currentField,从而大大减少了认知负担。

与第二个块相同-因此最终的重构过程可能如下所示:

Public Sub ResetPivotDataFields()

    Dim target As PivotTable
    Set target = ActiveSheet.PivotTables(1)

    RemoveExistingFields target

    Dim currentYear As Long
    currentYear = GetCurrentYear

    AddYearDataFields target, currentYear - 3, currentYear

End Sub

GetCurrentYear可能像这样简单:

Private Function GetCurrentYear() As Long
    'TODO confirm year logic correctness (currently assumes regular calendar years)
    GetCurrentYear = Year(Date)
End Function

AddYearDataFields可能看起来像这样:

Private Sub AddYearDataFields(ByVal target As PivotTable, ByVal fromYear As Long, ByVal toYear As Long)
    If fromYear > toYear Then Err.Raise 5, , "FromYear must be less than or equal to ToYear."

    Dim currentYear As Long
    For currentYear = fromYear To toYear
        target.AddDataField target.PivotFields(fieldName), "Sum of " & fieldName, xlSum
    Next
End Sub

将过程保持小而专业,给它们起好名字,并且毫不犹豫地将过程的依赖项作为参数传递;您的代码将很快变得清晰和简单。始终验证您的输入,过时的关键字和构造(例如Call语句)始终使用显式且适当的访问修饰符(如果不需要,请不要创建过程Public;隐式默认为Public),并传递参数ByVal(默认值为ByRef)。