Как использовать расширенную фильтрацию строк - PullRequest
0 голосов
/ 29 апреля 2018

Файл Excel для дат выполнения обязанностей людьми показан на рисунке. Помеченные обязанности как X

pic

Как я могу получить дату выполнения обязанностей, взятых конкретным человеком с помощью фильтрации?

Есть ли какой-нибудь способ получить имя каждого человека вместе с датой его работы на отдельном листе?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Подход через фильтрацию массива

Вам нужно фильтровать результаты по строкам (например, Тесси Пол - 26 апреля 18, 27 апреля 18, 30 апреля 18, 2 мая 18), но IMO вы не получите их с помощью расширенного фильтра метод , Вместо этого я демонстрирую альтернативный подход, использующий массивы для получения исходных данных (медленный цикл по диапазону через VBA) и извлечения переставленных (= перекодированных) данных через Application.Filter соответствующих элементов, помеченных "x" как обязанность .

Основные шаги

Сначала вы записываете все свои данные в вариант 2-мерного массива полей данных, просто назначая предопределенную ссылку на диапазон - см. Раздел [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) вам потребуется дополнительная информация помимо данных об изолированных ячейках и
  • б) вам понадобится 1-мерный массив.

  • ad a) Чтобы определить имя и дату обязанности при фильтрации, просто добавьте эту информацию вместе с разделителем (например, "#", см. Раздел [3]). Это позволяет позже разделить отфильтрованные данные, просматривая каждый элемент массива - см. Разделы [4] и [5].

  • ad b) Чтобы получить массив с 1 дим из массива с 2 димами, вы можете извлечь строку или столбец с помощью функции Application.Index. В приведенном ниже примере я присваиваю результаты другому массиву с именем vi. Например: если вы хотите извлечь строку, как показано в разделе 4.1, второй параметр идентифицирует номер строки, начиная с 1, третий аргумент номер столбца просто получает 0: Затем вы можете применить функцию Filter с этим новым исходным массивом и строкой соответствия "x #", чтобы получить все данные, определенные как Duty с помощью символа x и выбранного разделителя # .

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

Примечания:

Строка соответствия состоит из обоих символов ("x #"), так как только "x" также может быть частью имени (например, Alexander).

В качестве дополнения к строчной фильтрации:
Чтобы извлечь столбец, см. Раздел 5.1, так как для этого требуется дополнительная настройка с помощью Application.Transpose.

Каждый извлеченный массив строк или столбцов будет записан обратно на целевой лист и показан с помощью функции Join в Debug.Print в вашем непосредственном окне в редакторе Visual Basic (VBE)

Пример кода

Option Explicit

Sub DutiesPerName()
' Site: /10132497/kak-ispolzovat-rasshirennuy-filtratsiy-strok
' [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
0 голосов
/ 29 апреля 2018

Я думаю, что вы пытаетесь сделать:

UNPIVOT:

  1. Выберите данные и в меню Insert выберите Table
  2. В меню Data нажмите From Table/Range
  3. Откроется окно запроса. Выберите столбцы, которые нужно извлечь. С вашими данными выделяются следующие столбцы: " Тип " и " Количество дел "
  4. В меню Tranform выберите Unpivot Columns
  5. Если данные выглядят прямо сейчас, закройте редактор запросов (примите изменения).

Другой пример:

Если ваша цель - получить от , то :

unpivot1

... до это (или то ):

unpivot2

... тогда то, что вы хотите сделать, называется Unpivot .


Как отключить данные в стиле кросс-таблицы:

UnPivot demo

Вы можете найти шаги, записанные на вопрос, на который я ответил , и есть более подробное объяснение и шаги здесь .

...