VB宏来识别不同的细胞组合

时间:2016-09-09 23:20:39

标签: vba excel-vba excel

我有4列数据。

  • A是流程步骤
  • C是风险编号
  • D是风险评级(高,中或低)
  • F是风险主持人(控制,监控,测试或空白)。

我需要使用不同的组合填充演示文稿。

  • 有多少风险控制,有多少没有?
  • 有控件的人,有多少有监视器或测试,有多少没有?
  • 没有控件的人有多少有监视器或测试,有多少没有?
  • 在这些不同类别中,有多少是高,中,低?
  • 对于那些没有控件,监视器或测试的最终框,风险属于哪些流程步骤?

每个风险实际上都有一个包含缓解的F列占用的块。可以有几个包含不同项目的盒子,如果没有缓解器,它们可以是空白的。

下面是使用或不使用控件进行识别的代码,但我仍然坚持下一部分(计算不同的风险等级并将其进一步分解为/不进行监控或测试。

Sub CountWithWithoutControlsv6()
    Const RiskColumn As String = "C"
    Const ControlColumn As String = "F"
    Const StartAtRow As Long = 7

    Dim r As Long
    Dim ControlFound As Boolean
    Dim control As Long
    Dim WoControl As Long

    Dim lastRow As Long

    With ActiveSheet
        lastRow = .Range(RiskColumn & .Rows.Count).End(xlUp).row
        r = .Range(ControlColumn & .Rows.Count).End(xlUp).row
        If lastRow < r Then
            lastRow = r
        End If

        ControlFound = False
        For r = StartAtRow To lastRow
            If UCase(Trim(CStr(.Cells(r, ControlColumn).Value))) = "CONTROL" Then
                ControlFound = True
            End If
            If Not IsEmpty(.Cells(r + 1, RiskColumn)) Then
                'Store info for previous block each time we encounter a new "risk"
                If ControlFound Then
                    control = control + 1
                Else
                    WoControl = WoControl + 1
                End If
                ControlFound = False
            End If
        Next
        'Store info for final "block"
        If ControlFound Then
            control = control + 1
        Else
            WoControl = WoControl + 1
        End If
    End With

    MsgBox control & "  = number of risks with controls, " & WoControl & "  = number of risks without controls"
End Sub

2 个答案:

答案 0 :(得分:1)

我建议您“扁平化”您的数据,以便A列包含流程步骤,C为风险编号,D为风险评级(高,中或低),F表示是否存在“控制”风险审核人, G表示是否存在“监控”风险主持人,H表示是否存在“测试”风险主持人。

所以不要使用

之类的数据
A      C         D        F
Step1  Risk7     High     control
                          monitor
                          test
Step2  Risk8     Low      (blank)

你会改为

A      C         D        F       G       H
Step1  Risk7     High     Yes     Yes     Yes
Step2  Risk8     Low      No      No      No

使用该格式后,使用Excel公式(例如=COUNTIFS(F:F,"Yes",G:G,"Yes",H:H,"No")

)会很简单

答案 1 :(得分:0)

如果您按照目前的方法解决了这个问题,那么最终会实现目标 - 代码本身就可以直接编写。但是,编写这些内容需要花费很长时间才能涵盖所有案例,而且编写起来会非常乏味。 (你只是产生了一些线条,说实话,这是一项非常简单的任务,这可能是你投票的原因。)

但是,在启动代码的其余部分之前,您可能会考虑使用ADO。它非常适合这项任务,可以在几行内完成您的项目。我不想为您解决问题,但我想提供一些代码,让您一起开始使用几个查询示例。我已经使用了早期绑定,这意味着我已经引用了Microsoft ActiveX Data Objects 6.1库(工具〜&gt;引用...),但如果您愿意,可以进行后期绑定。

查看下面的代码,看看是否可以使用它:

Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim connStr As String
Dim sqlStr As String
Dim tableName As String
Dim procField As String
Dim numField As String
Dim levelField As String
Dim controlField As String

connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
          "Data Source='C:\Users\User\Documents\StackOverflow\ADOexample.xlsm';" & _
          "Extended Properties=""Excel 12.0;HDR=YES;"";"

'Define the table and field names
With Sheet1 'change to your sheet
    tableName = .Name
    procField = CStr(.Cells(1, "A").Value)
    numField = CStr(.Cells(1, "C").Value)
    levelField = CStr(.Cells(1, "D").Value)
    controlField = CStr(.Cells(1, "F").Value)
End With

'Open the connection
Set conn = New ADODB.Connection
conn.Open connStr

'Some sample queries
'Sample 1
Set rs = New Recordset
sqlStr = "SELECT * FROM [" & tableName & "$]" & _
         " WHERE [" & controlField & "] IS NOT NULL;"

rs.Open sqlStr, conn
Do While Not rs.EOF
    Debug.Print rs.Fields(numField)
    rs.MoveNext
Loop

'Sample 2
Set rs = New Recordset
sqlStr = "SELECT * FROM [" & tableName & "$]" & _
         " WHERE [" & levelField & "] = 'H'" & _
         " AND ([" & controlField & "] = 'MONITOR'" & _
         " OR [" & controlField & "] = 'TEST');"

rs.Open sqlStr, conn
Do While Not rs.EOF
    Debug.Print rs.Fields(numField)
    rs.MoveNext
Loop

'Clean up objects
rs.Close
Set rs = Nothing

conn.Close
Set conn = Nothing