Страницы: 1 2 След.
RSS
Преобразовать таблицу к виду "шахматка" (или наоборот?), Преобразовать таблицу для отчета
 
Здравствуйте всем!
Второй день пытаюсь решить эту задачу. Пробовал ВПР, ГПР, ИНДЕКС+ПОИСКПОЗ - что-то не идет. Пользовался поиском, не нашёл, Честно говоря, даже сформулировать вопрос не могу. Возможно термин "шахматка" использую не правильно.
В файле - как есть и как надо.
 
ФОрмула массива
Код
=--ИЛИ(J$13=$C3:$H3)
Если в мире всё бессмысленно, — сказала Алиса, — что мешает выдумать какой-нибудь смысл? ©Льюис Кэрролл
 
Быстро!
А если коды таблицы у одного (нескольких) человек повторятся?
Забыл, простите, отметить такую возможность.
 
Макросом на словарях можно сделать, уже делал не раз такое. Но работы не на 5 минут, их нет.
Алгоритм такой -
1. циклами по исходникам получаем словарь ключей петя|11, словарь или коллекцию имён и словарь или коллекцию дат.
2. сортитровка дат.
3. выгрузка имён и дат на лист (или создание и заполнение массива, но для большого массива может не хватить памяти).
4. циклами по листу (массиву) собираем ключ, проверяем наличие словаря, пишем (или нет) метку.
 
Вот вам пример
 
Цитата
Yuri KUB написал:
А если коды таблицы у одного (нескольких) человек повторятся?
Какой результат нужен в таком случае? И еще момент уточнить нужно. У Вас список имен в исходной таблице в той же последовательности, что и в итоговой. В реальных данных это соблюдается?
Если в мире всё бессмысленно, — сказала Алиса, — что мешает выдумать какой-нибудь смысл? ©Льюис Кэрролл
 
Bema, спасибо! Попробовал, но если коды повторяются - не учитывает
.Hugo, спасибо! Алгоритм вроде понятен, но воплотить в код мне не хватает знаний.
skais675, спасибо! Работает. Может мне на этом остановиться?
Изменено: Yuri KUB - 30.10.2017 23:23:30
 
Yuri KUB, что нужно если коды повторяются? Повторять 1?
Если в мире всё бессмысленно, — сказала Алиса, — что мешает выдумать какой-нибудь смысл? ©Льюис Кэрролл
 
Цитата
Bema написал:
У Вас список имен в исходной таблице в той же последовательности, что и в итоговой.
В общем случае порядок имен произвольный. Но можно их, я думаю, синхронизировать вручную.
 
Цитата
Bema написал:
что нужно если коды повторяются? Повторять 1?
Нет. Нужно считать кол-во повторений.
 
Так?
Код
=СЧЁТЕСЛИ($C3:$H3;J$13)
Если в мире всё бессмысленно, — сказала Алиса, — что мешает выдумать какой-нибудь смысл? ©Льюис Кэрролл
 
Цитата
Yuri KUB написал:
Нужно считать кол-во повторений
- в моём алгоритме в п.1. каждому ключу считаем количество его повторов. Чтоб зазря итем не простаивал :)
 
Bema,
Совсем просто получилось - неожиданно!
Работает, считает повторы.
Попробую на рабочей таблице.
 
Мой макрос. Но лень делать шаг2.
Для работы убрать заголовок и перетащить таблицу чтоб начиналась с A1 !!!
Код
'1. циклами по исходникам получаем словарь ключей петя|11,  коллекцию имён и  коллекцию дат.
'2. сортировка дат.
'3. выгрузка имён и дат на лист.
'4. циклами по листу собираем ключ, проверяем наличие в словаре, пишем (или нет) метку.


Sub tt()
Dim a, i&, ii&, col1 As New Collection, col2 As New Collection, ws As Worksheet

Application.ScreenUpdating = False

With CreateObject("Scripting.Dictionary"): .comparemode = 1

On Error Resume Next
a = [a1].CurrentRegion.Value
'1
For i = 1 To UBound(a, 2)
a(i, 1) = Trim(a(i, 1))
col1.Add a(i, 1), a(i, 1)
For ii = 2 To UBound(a)
If Len(a(i, ii)) = 0 Then Exit For
col2.Add a(i, ii), Trim(a(i, ii))
t = a(i, 1) & "|" & a(i, ii)
.Item(t) = .Item(t) + 1
Next
Next
On Error GoTo 0

Set ws = Workbooks.Add.Sheets(1)

'3
For i = 1 To col1.Count
ws.Cells(i + 1, 1) = col1(i)
Next
For i = 1 To col2.Count
ws.Cells(1, i + 1) = col2(i)
Next

'4
For i = 2 To col1.Count + 1
For ii = 2 To col2.Count + 1
t = ws.Cells(i, 1) & "|" & ws.Cells(1, ii)
If .exists(t) Then ws.Cells(i, ii) = .Item(t)
Next
Next
End With

Application.ScreenUpdating = True

End Sub
 
Цитата
Yuri KUB написал:
В общем случае порядок имен произвольный.
Если Пети-Васи идут вразнобой,попробуйте такой вариант:
=СЧЁТЕСЛИ(ИНДЕКС($C$3:$H$8;ПОИСКПОЗ($I14;$B$3:$B$8;0);0);J$13)
Если в мире всё бессмысленно, — сказала Алиса, — что мешает выдумать какой-нибудь смысл? ©Льюис Кэрролл
 
Bema,
Отлично! Все работает, спасибо
Hugo,
Меня заинтересовало Ваше решение.
Создавать новый файл-отчёт, наверное, правильнее.
Не могли бы Вы прокомментировать код. Что делать, если исходный диапазон C3:X125
Изменено: Yuri KUB - 30.10.2017 20:08:51
 
еще один вариант
=СУММПРОИЗВ(($B$3:$B$8=$I14)*($C3:$H3=J$22))
 
Цитата
Yuri KUB написал:
Что делать, если исходный диаразон C3:X125
- пробовать заменить в коде А1 на С3. Если результат будет кривой - читать что такое currentregion :)
Для сортировки дат нужно в код добавить выгрузку коллекции в массив и его сортировку, ну или может прямо в коллекции элементы двигать, но думаю с массивом проще, есть готовые функции. Ну и затем отсортированное выгружать на лист.
А по поводу комментария - там ведь шаги в коде обозначены, ещё мельче хотите?
 
Hugo написал:
Цитата
А по поводу комментария - там ведь шаги в коде обозначены, ещё мельче хотите?
Мельче не надо - мне неудобно Вас напрягать. А по поводу currentregion - у меня кроме вышеуказанного диапазона (C3:X125) есть ещё много разной информации.
 
Нашёл в сети сортировку пузырьком коллекции, добавил.
Там есть и побыстрее вариант, но сильно наворочен, вроде тут особо в скорости сортировки нужды нет...
Скрытый текст
 
Цитата
Alexanderr написал:
=СУММПРОИЗВ(($B$3:$B$8=$I14)*($C3:$H3=J$22))
Не работает. Или это формула массива? Нет, как массив тоже не работает.
 
вот так будет работать
=СУММПРОИЗВ(($B$3:$B$8=$I14)*($C3:$H3=J$13))
Изменено: Alexanderr - 30.10.2017 20:50:42 (не прикрепил файл)
 
Да, так работает. Порядок людей д.б. одинаков.
 
Решение с Суммпроизв() косячит - замените например в исходнике тима на петю...
Они ведь уже могут повторяться!
P.S. Или повторяться могут только цифры? Ну моему решению всё равно что повторяется...
Изменено: Hugo - 30.10.2017 21:44:30
 
тогда так:
=СУММПРОИЗВ(($B$3:$B$8=$I14)*($C3:$H8=J$13))
 
Не, тогда так :)
Код
=SUMPRODUCT(($B$3:$B$8=$I14)*($C$3:$H$8=J$13))
 
точно!))
 
Hugo,
Попробовал Ваше решение (#20) на файле, близком к рабочему (см. вложение). Во вложенном файле список из 32 человек - формирует новую книгу (здесь на Лист1) на 21-го человека. Искал в коде ограничения по строкам - не нашёл.
 
Я пока пас - не могу качать файлы с макросами.
 
Спасибо всем, кто принял участие в обсуждении этой темы!
Сейчас у меня работает вариант из постов #25 и #26
Продолжаю пробовать вариант от Hugo,  пост 20: не могу найти в коде ограничения на количество обрабатываемых строк см. пост #28
Код от Hugo, :

Код
Option Explicit
 '1. циклами по исходникам получаем словарь ключей петя|11,  коллекцию имён и  коллекцию дат.
'2. сортировка дат.
'3. выгрузка имён и дат на лист.
'4. циклами по листу собираем ключ, проверяем наличие в словаре, пишем (или нет) метку.
 
 
Sub tt()
    Dim a, i&, ii&, j&, col1 As New Collection, col2 As New Collection, ws As Worksheet, t$
    Dim vTemp As Variant
 
    Application.ScreenUpdating = False
 
    With CreateObject("Scripting.Dictionary"): .comparemode = 1
 
        On Error Resume Next
        a = [a1].CurrentRegion.Value
        '1
        For i = 1 To UBound(a, 2)
            a(i, 1) = Trim(a(i, 1))
            col1.Add a(i, 1), a(i, 1)
            For ii = 2 To UBound(a)
                If Len(a(i, ii)) = 0 Then Exit For
                col2.Add a(i, ii), Trim(a(i, ii))
                t = a(i, 1) & "|" & a(i, ii)
                .Item(t) = .Item(t) + 1
            Next
        Next
        On Error GoTo 0
 
        Set ws = Workbooks.Add.Sheets(1)
 
        '2
        'Two loops to bubble sort
        For i = 1 To col2.Count - 1
            For j = i + 1 To col2.Count
                If col2(i) > col2(j) Then
                    'store the lesser item
                    vTemp = col2(j)
                    'remove the lesser item
                    col2.Remove j
                    're-add the lesser item before the
                    'greater Item
                    col2.Add vTemp, Trim(vTemp), i
                End If
            Next j
        Next i
 
        '3
        For i = 1 To col1.Count
            ws.Cells(i + 1, 1) = col1(i)
        Next
 
        For i = 1 To col2.Count
            ws.Cells(1, i + 1) = col2(i)
        Next
 
        '4
        For i = 2 To col1.Count + 1
            For ii = 2 To col2.Count + 1
                t = ws.Cells(i, 1) & "|" & ws.Cells(1, ii)
                If .exists(t) Then ws.Cells(i, ii) = .Item(t)
            Next
        Next
    End With
 
    Application.ScreenUpdating = True
 
End Sub

Перевложил файл:

Изменено: Yuri KUB - 02.11.2017 09:26:56
Страницы: 1 2 След.
Читают тему
Наверх