人员履行职责日期的excel文件如图所示。标记职责为X
如何使用过滤获取特定人员的职责日期?
有没有办法让每个人的姓名连同他们的工作日期在一张单独的表格中?
答案 0 :(得分:0)
我认为你要做的是:
Insert
菜单上选择Table
Data
菜单上点击From Table/Range
Tranform
菜单上选择Unpivot Columns
https://getbootstrap.com/docs/4.0/components/forms/
您可以找到上写出的步骤,还有更多a question I answered here。
答案 1 :(得分:0)
通过数组过滤方法
你需要逐行过滤结果(例如Tessy Paul- 4月18日,4月27日,4月30日,4月2日,5月18日),但IMO你不会通过高级过滤器获取它们方法。相反,我展示了一种使用数组获取源数据的替代方法(通过VBA循环一个范围很慢)并通过(=重新编码)数据> Application.Filter
将“x”标记的项目匹配为职责。
基本步骤
首先,只需分配预定义的范围参考,即可将所有数据写入变量二维数据字段数组 - 请参阅第[2]节:
Dim v As Variant ' or simply: Dim v
Dim rng As Range
'set rng = ...
v = rng.Value2 ' or simply: v = rng
此外,可以通过Application.Filter
过滤数组,但有一些限制:
b)你需要一个1-dim数组。
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”也可以是名称的一部分(例如亚历山大)。
作为行式过滤的补充:
要提取列,请参阅第5.1节,因为这需要通过Application.Transpose
进行额外调整。
每个提取的行或列数组将写回到目标工作表,并通过Visual Basic编辑器(VBE)中即时窗口中Join
中的Debug.Print
函数显示
代码示例
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