Excel VBA SUMIF或SUMIFS用于多个条件

时间:2015-08-04 19:53:01

标签: excel vba excel-vba

我正在尝试从用户提供的日期范围中提取唯一的工作申请编号。将这些唯一的工作请求编号放在J列中(与A列中的WR#比较后)。然后为列J中找到的每个唯一WR#(与列A值比较)和第I列中的值添加所有值。对于此计算,我不必显示日期,只需要日期范围的唯一WR#显示第I列的总和值。例如,如果整个数据集包含2015年1月1日到2015年8月4日的值,并且用户输入的开始日期为2015年7月1日,结束日期为2015年7月31日,唯一值列(" J")应仅输出在列I中找到的唯一工作请求值的总和到列K.到目前为止我的努力不成功。代码如下所示,带有数据和代码的excel文件可以从以下链接找到:https://drive.google.com/file/d/0BzLiHD7QMfVldm1pSG1XaUdpcTQ/view?usp=sharing

Sub SumIfTest()

Worksheets("AccessExtract").Activate

Dim startDate As Date
Dim endDate As Date

startDate = InputBox("Enter Start Date")
endDate = InputBox("Enter End Date")

' Extract unique WR#

Dim d2 As Object, c2 As Variant, i2 As Long, lr2 As Long
Set d2 = CreateObject("Scripting.Dictionary")
lr2 = Cells(Rows.Count, 1).End(xlUp).Row
c2 = Range("A2:A" & lr2)
For i2 = 1 To UBound(c2, 1)
  d2(c2(i2, 1)) = 1
Next i2
Range("J2").Resize(d2.Count) = Application.Transpose(d2.keys)

Dim rowIndex As Long
Dim calcFormula10 As Double

For rowIndex = 2 To lr2

    If ((Cells(rowIndex, "G").Value >= startDate) And (Cells(rowIndex, "G").Value <= endDate)) Then
    calcFormula10 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Text, Range("I:I"))

    End If

Cells(rowIndex, "K").value = calcFormula10

Next rowIndex

End Sub

1 个答案:

答案 0 :(得分:0)

以下是符合要求的更新代码:

Option Explicit

Sub Report1()

Application.DisplayAlerts = False

ActiveWorkbook.Worksheets.Add
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:=Array( _
        "OLEDB;Provider=Microsoft.ACE.OLEDB.12.0;Password="""";User ID=Admin;Data Source=C:\tmp\ReportLocation\data1.mdb" _
        , _
        "racker.mdb;Mode=Share Deny Write;Extended Properties="""";Jet     OLEDB:System database="""";Jet OLEDB:Registry Path="""";Jet OLEDB:Databa" _
        , _
        "se Password="""";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking     Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bu" _
        , _
        "lk Transactions=1;Jet OLEDB:New Database Password="""";Jet     OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet" _
        , _
        " OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without    Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support C" _
        , _
        "omplex Data=False;Jet OLEDB:Bypass UserInfo Validation=False;Jet   OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Val" _
        , "idation=False"), Destination:=Range("$A$1")).QueryTable
        .CommandType = xlCmdTable
        .CommandText = Array("2015 Activites")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .SourceDataFile = _
            "C:\tmp\ReportLocation\data1.mdb"
        .ListObject.DisplayName = "Activity_Tracker1"
        .Refresh BackgroundQuery:=False

    End With

' The following code renames the Active sheet to AccessImport
ActiveSheet.Name = "AccessImport"


' ****************************************
' The following code update column G with required Date format

Worksheets("AccessImport").Activate

Range("G:G").NumberFormat = "mm-dd-yyyy"


' Get the start and end date from the user

Dim TheString1 As String, TheString2 As String, TheStartDate As Date,    TheEndDate As Date
Dim TotalDaysEntered As Integer


    TheString1 = Application.InputBox("Enter the start date:")
    TheString2 = Application.InputBox("Enter the end date:")

    If IsDate(TheString1) And IsDate(TheString2) Then
        TheStartDate = DateValue(TheString1)
        TheEndDate = DateValue(TheString2)
    Else
        MsgBox "Invalid date entered"
        Exit Sub
    End If

 ' The following code extracts the data for a specific date range provided by    the user.

     ActiveSheet.ListObjects("Activity_Tracker1").Range.AutoFilter field:=7, Criteria1:=">=" & TheStartDate, Operator:=xlAnd, Criteria2:="<=" & TheEndDate


' Copy data from active sheet to another sheet

ActiveWorkbook.Worksheets.Add
ActiveSheet.Name = "Report1"
Worksheets("AccessImport").Activate

Dim mainworkBook As Workbook
Set mainworkBook = ActiveWorkbook
mainworkBook.Sheets("AccessImport").UsedRange.Copy

mainworkBook.Sheets("Report1").Select

mainworkBook.Sheets("Report1").Range("A1").Select

mainworkBook.Sheets("Report1").Paste


' The next block of code fills up all the blank cells found in column A with E4486 or 004486.

Worksheets("Report1").Activate

    Dim c As Integer

    For c = 1 To Range("A" & Rows.Count).End(xlUp).Row
        If Range("A" & c).value = vbNullString Then
            Range("A" & c).value = 4486
        End If
    Next c


' Aligning column A to W as Center horizontally.

Columns("A:W").HorizontalAlignment = xlCenter
Columns("F:F").EntireColumn.AutoFit
Columns("G:G").EntireColumn.AutoFit
Columns("H:H").EntireColumn.AutoFit

'Determines the last row that contains data in column A

Dim LastRowFrom As Long
LastRowFrom = Range("A" & Rows.Count).End(xlUp).Row


' Find the unique values and place these identified unique values from Column   A into Column J

Dim d2 As Object, c2 As Variant, i2 As Long, lr2 As Long
Set d2 = CreateObject("Scripting.Dictionary")
lr2 = Cells(Rows.Count, 1).End(xlUp).Row
c2 = Range("A2:A" & lr2)
For i2 = 1 To UBound(c2, 1)
  d2(c2(i2, 1)) = 1
Next i2
Range("J2").Resize(d2.Count) = Application.Transpose(d2.keys)

' Calculation

    Dim i As Long
    Dim token As String
    Dim value As Double
Dim lastI As Long
    token = Worksheets(ActiveSheet.Name).Range("A2").value
    value = 0
    For i = 2 To lastRow(ActiveSheet.Name)
        If token = Worksheets(ActiveSheet.Name).Range("A" & CStr(i)).value   Then
            If CDate(Worksheets(ActiveSheet.Name).Range("G" & CStr(i)).value) >= TheStartDate And CDate(Worksheets(ActiveSheet.Name).Range("G" & CStr(i)).value) <= TheEndDate Then
                value = value + (Worksheets(ActiveSheet.Name).Range("B" & CStr(i)).value + Worksheets(ActiveSheet.Name).Range("C" & CStr(i)).value + Worksheets(ActiveSheet.Name).Range("D" & CStr(i)).value +    Worksheets(ActiveSheet.Name).Range("E" & CStr(i)).value) * 0.008 + 0.08
            End If
        Else

            Worksheets(ActiveSheet.Name).Range("I" & CStr(i - 1)).value = value
            lastI = i
            If CDate(Worksheets(ActiveSheet.Name).Range("G" & CStr(i)).value) >= TheStartDate And CDate(Worksheets(ActiveSheet.Name).Range("G" & CStr(i)).value) <= TheEndDate Then
                value = (Worksheets(ActiveSheet.Name).Range("B" & CStr(i)).value + Worksheets(ActiveSheet.Name).Range("C" & CStr(i)).value + Worksheets(ActiveSheet.Name).Range("D" & CStr(i)).value + Worksheets(ActiveSheet.Name).Range("E" & CStr(i)).value) * 0.008 + 0.08
            End If
            token = Worksheets(ActiveSheet.Name).Range("A" & CStr(i)).value
        End If
    Next i

    If lastI = lastRow(ActiveSheet.Name) Then
        If CDate(Worksheets(ActiveSheet.Name).Range("G" & CStr(lastI)).value) >= TheStartDate And CDate(Worksheets(ActiveSheet.Name).Range("G" & CStr(lastI)).value) <= TheEndDate Then
            value = value + (Worksheets(ActiveSheet.Name).Range("B" & CStr(lastI)).value + Worksheets(ActiveSheet.Name).Range("C" & CStr(lastI)).value + Worksheets(ActiveSheet.Name).Range("D" & CStr(lastI)).value + Worksheets(ActiveSheet.Name).Range("E" & CStr(lastI)).value) * 0.008 + 0.08
        End If
    End If
    Worksheets(ActiveSheet.Name).Range("I" &   CStr(lastRow(ActiveSheet.Name))).value = value * 0.008 + 0.08

' ****************************************
' The following code matches WR # between Column J and A and for the matched  WR# it sums up values in column I.

Dim calcFormula10 As Double
Dim rowIndex As Long

For rowIndex = 2 To lr2


    calcFormula10 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Text, Range("I:I"))


    Cells(rowIndex, "K").value = calcFormula10

Next rowIndex


' Autofit column J, K and L

Columns("J:J").EntireColumn.AutoFit
Columns("K:K").EntireColumn.AutoFit
Columns("L:L").EntireColumn.AutoFit

' Inserting title of the columns

Cells(1, "J").value = "WR#"
Cells(1, "K").value = "Total"

' Bolds texts in Cell(1, 10), (1, 11) and (1, 12)

Cells(1, 10).Font.Bold = True
Cells(1, 11).Font.Bold = True
Cells(1, 12).Font.Bold = True

' Hide columns
Columns("A:I").Hidden = True

' Delete empty cells based on values on J column
Dim WS4 As Worksheet
Dim LastCell As Range
Dim LastCellRowNumber As Long

Set WS4 = Worksheets("Report1")

    With WS4
    Set LastCell = .Cells(.Rows.Count, "J").End(xlUp)
    LastCellRowNumber = LastCell.Row
    Rows(LastCellRowNumber + 1 & ":" & Rows.Count).Delete
End With


End Sub

Private Function lastRow(sheet As String) As Long
    Dim ix As Long
    ix = Worksheets(sheet).UsedRange.Row - 1 + Worksheets(sheet).UsedRange.Rows.Count
    lastRow = ix
End Function