【问题标题】:How can I use advanced filtering row wise如何明智地使用高级过滤行
【发布时间】:2023-04-11 09:04:02
【问题描述】:

人员任职日期的excel文件如图所示。将职责标记为 X

如何使用过滤获取特定人员的职责日期?

有没有什么方法可以将每个人的姓名和他们的工作日期放在单独的表格中?

【问题讨论】:

  • ..你的目标是只显示 1 个人?
  • @ashleedawg 你的照片是一样的.. 我试图删除第二张但我不能
  • @ashleedawg 我需要每个人的职责日期。例如.. 过滤后我需要这样的过滤工具,我得到了 Tessy Paul- 26 April 18,27 April 18, 30 April 18, 2-May 18 Fr。 Joy PT- 2018 年 4 月 26 日 对其他老师也是如此。
  • 添加了一种通过数组过滤的方法,因为 IMO 高级过滤还不够 - @seena

标签: excel filtering vba


【解决方案1】:

我认为你想要做的是:

反透视:

  1. 选择数据并在Insert 菜单上选择Table
  2. 在Data 菜单上单击From Table/Range
  3. 查询窗口将打开。选择您需要提取的列。对于您的数据,要突出显示的列是“Type”和“案例数”
  4. 在Tranform 菜单上选择Unpivot Columns
  5. 如果数据看起来正确,请关闭查询编辑器(接受更改)。

另一个例子:

如果你的目标是从这个:

...到这个(或那个):

...那么您要做的就是Unpivot。


如何取消透视“交叉表样式”数据:

你可以在a question I answered here上找到写的步骤,还有一个detailed explanation and steps over here。

【讨论】:

  • @ashleedwag。先生,我没有从数据菜单中的表格/范围中获取信息
【解决方案2】:

通过数组过滤的方法

您需要逐行过滤结果(例如,Tessy Paul- 4 月 18 日 26 日、4 月 18 日 27 日、4 月 18 日 30 日、18 年 2 月 2 日),但 IMO 您不会通过 高级过滤器获得它们方法。相反,我演示了一种替代方法,使用 arrays 来获取源数据(通过 VBA 循环遍历范围很慢)并通过 提取重新排列的 (=recoded) 数据>Application.Filter 匹配由 "x" 标记为 duty 的项目。

基本步骤

首先,您只需分配一个预定义的范围引用,即可将所有数据写入一个变体二维数据字段数组 - 请参阅第 [2] 节:

Dim v   As Variant  ' or simply: Dim v
Dim rng As Range    
'set rng = ...
v = rng.Value2  ' or simply: v = rng

此外,可以通过 Application.Filter 过滤数组,但有一些限制:

  • a) 除了孤立的细胞数据之外,您还需要更多信息,并且
  • b) 你需要一个一维数组。

  • ad a) 为了在过滤时识别姓名和工作日期,只需将这些信息与分隔符一起添加(例如“#”,参见第 [3] 节)。 这允许您稍后通过循环遍历每个数组项来拆分过滤后的数据 - 请参阅第 [4] 和 [5] 节。

  • ad b) 要从 2-dim 数组中获取 1-dim 数组,您可以通过 Application.Index 函数提取一行或一列。 在下面的示例中,我将结果分配给另一个名为 vi 的数组。 例如:如果要提取一行,如4.1节所示,第二个参数标识从1开始的行号,第三个参数列号简单地获取0: 然后,您可以将Filter 函数与这个新维度的源数组和匹配字符串“x#”一起应用,以获取由 x 字符和所选字符定义为 Duty 的所有数据分隔符 #.

    vi = VBA.filter(Application.Index(v, i, 0), "x#",​​ True, False)

注意事项:

匹配字符串由两个字符(“x#”)组成,因为单独的“x”也可以是名称的一部分(例如 Alexander)。

作为逐行过滤的补充:
要提取列,请参阅第 5.1 节,因为这需要通过 Application.Transpose 进行额外调整。

每个提取的行或列数组都将写回目标工作表,并通过 Visual Basic 编辑器 (VBE) 的即时窗口中的 Debug.Print 中的 Join 函数显示

代码示例

Option Explicit

Sub DutiesPerName()
' Site: https://stackoverflow.com/questions/50083149/how-can-i-use-advance-filtering-row-wise
' [0] Declare variables
  Dim a()
  Dim ws    As Worksheet, ws2 As Worksheet
  Dim rng   As Range, i As Long, j As Long, r As Long, c As Long
  Dim v, vi, temp
' [1] define sheetname and data range
' 1.0 set worksheet object to memory
  Set ws = ThisWorkbook.Worksheets("MyDataSheet")  ' << change to your data sheet name
  Set ws2 = ThisWorkbook.Worksheets("MyDutySheet") ' << change to your target sheet name
' 1.1 get rows and columns
  r = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
  c = ws.Range("A1").End(xlToRight).Column
' 1.2 Alternative code line: Set rng = ws.UsedRange
  Set rng = ws.Range(ws.Range(ws.Cells(1, 1), ws.Cells(r, c)).Address)
' [2] create a variant 1-based 2-dim datafield array
  v = rng.Value2
' [3] CODE duty items by appending "#" plus date and name info
  For i = 2 To UBound(v)                ' start loop from 2nd row
      v(i, 1) = "x#" & v(i, 1)          ' mark name captions to get them filtered, too
      For j = 3 To UBound(v, 2)         ' start inner loop from 3rd column
          If v(i, j) = "x" Then         ' code found duty items
             v(i, j) = v(i, j) & "#" & Format(v(1, j), "dd-mmm-yy") & "#" & v(i, 1) & "#" & j
             'Debug.Print "v(" & i & "," & j & ")=""" & v(i, j) & """"
          End If
      Next j
  Next i
' mark date captions with "x#" to get them filterd, too
  For j = 3 To UBound(v, 2)
        v(1, j) = "x###" & Format(Val(v(1, j)), "dd-mmm-yy")
  Next j
' -----------------------
' [4] Duty Dates per Name:
' -----------------------
  ws2.Cells.Clear: ws2.Range("A1") = "Name": ws2.Range("B1") = "Duty Dates ..."
  For i = 2 To UBound(v, 1)             ' start loop from 2nd row
  ' 4.1 filter redimensioned 1-dim ROW array via "x#"
    vi = VBA.filter(Application.Index(v, i, 0), "x#", True, False)
    For j = LBound(vi) To UBound(vi)
        vi(j) = Split(vi(j), "#")(1)    ' extracts date from e.g. "x#15-Jan-19#x#Paul#2"
    Next j
    ' write dates per name into target worksheet ws2
    ws2.Range("A1").Offset(i - 1, 0).Resize(1, UBound(vi) + 1) = vi
    Debug.Print "Row# " & i & " (" & _
                ws2.Range("A1").Offset(i - 1, 0).Resize(1, UBound(vi) + 1).Address & ") 1 Name + " & UBound(vi) & " Dates: " & _
                Join(vi, ", ")
   Next i
   Debug.Print
' -----------------------
' [5] Names per Duty Date:
' -----------------------
  ws2.Range("A1").Offset(r + 2, 0) = "Duty Date": ws2.Range("A1").Offset(r + 2, 1) = "Names ..."
  For i = 3 To UBound(v, 2)             ' start loop from 3rd column
  ' 5.1 filter redimensioned 1-dim COLUMN array via "x#"
    vi = VBA.filter(Application.Transpose(Application.Index(v, 0, i)), "x#", True, False)
    For j = LBound(vi) To UBound(vi)
        temp = Split(vi(j), "#")
        vi(j) = temp(3)                  ' extracts Name from e.g. "x#15-Jan-19#x#Albert#3"
    Next j
    ' write each names per date into target worksheet ws2
    If UBound(vi) > -1 Then
       ws2.Range("A1").Offset(r + i, 0).Resize(1, UBound(vi) + 1) = vi
       Debug.Print "Col# " & i & " (" & _
                   ws2.Range("A1").Offset(r + i, 0).Resize(1, UBound(vi) + 1).Address & ") 1 Date + " & UBound(vi) & " Names: " & _
                   Join(vi, ", ")
    End If
   Next i

End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多