Страницы: 1
RSS
Обращение столбца (транспонирование) с группировкой, В моей задаче возникла проблема нужно обратить данные одного столбца в строки, при этом что бы сохранилось целостность (группировка) отчета по главном признакам
 
В примере предоставлена часть данных (исходник) которые нужно обработать с помощью различных функций. А так же рядом готовый результат который нужно получить (сортировал в ручную). Перепробовал различные варианты не получается, если умеет подскажите решение.  Имеется столбец с принадлежностью к определенной смене и дате когда происходило событие. Следующий столбец содержит транспортное средство осуществлявшее работу в течении смены. А в третьем столбце время простоя каждого рейса (выраженное в продолжительности). Так как все отчеты (сверки) формируются в строках по каждой смене, нужно что бы и время простоев занимало только одну определенную строку.
 
gelleris, добрый день. Нужны только формулы, если да, то  какая у вас версия эксель? А так задача для  PQ(power query).  
 
pq
 
Цитата
написал:
Нужны только формулы, если да, то  какая у вас версия эксель? А так задача для  PQ(power query).  
Да решение для PQ(power query) нужно. Я остановился на определенном этапе редактирования отчета где дальше сам не нашел решение. Версия MS Профессиональный плюс 2016
Изменено: gelleris - 06.05.2026 09:38:48
 
Сводная + формула
Код
=ТРАНСП(ФИЛЬТР(Лист1!$F$3:$F$39;(Лист1!$D$3:$D$39=A4)*(Лист1!$E$3:$E$39=B4)))
Согласие есть продукт при полном непротивлении сторон
 
Power Query
ии
Изменено: nilske - 06.05.2026 09:44:18
 
Огромное спасибо за помощь проблема решена. Решение в Power Query с группировкой работает как надо!
 
В строке
05.05.2026.   2 смена отчет для Зайцева.xlsxА500ХВ1420:13:140:11:380:12:590:11:010:11:000:11:240:13:20
значения
0:11:010:11:000:11:240:13:20
ошибочные? Должно быть пусто?

Вариант к заданию из сообщения #1, не подходит к заданию из сообщения #4 "решение для PQ нужно":
Код
Option Explicit

Sub Транспонировать_выделенный()
    If TypeName(Selection) <> "Range" Then Exit Sub
    Transponse_range Selection, Selection.Cells(1, 5)
End Sub

Private Sub Transponse_range(rSource As Range, rTarget As Range)
    On Error Resume Next
    Set rSource = Intersect(rSource.Columns(1).EntireColumn, rSource)
    Set rSource = Intersect(rSource, rSource.Parent.UsedRange)
    On Error GoTo 0
    If rSource Is Nothing Then Exit Sub
    
    Dim dic As Object
    Set dic = CreateObject("Scripting.Dictionary")
    FillDicFromRange rSource, dic
    If dic.Count = 0 Then Exit Sub
    EditDic dic
    
    ClearTargetRange rSource, rTarget, GetColumnsCount(dic)
    PrintDic dic, rTarget
End Sub
    
Private Sub PrintDic(dic As Object, rTarget As Range)
    Dim trr As Variant
    ReDim trr(1 To dic.Count, 1 To 2 + GetColumnsCount(dic))
    
    Dim yt As Long, xt As Long, xs As Long, nrr As Variant
    For yt = 1 To UBound(trr, 1)
        nrr = Split(dic.Keys()(yt - 1), "#")
        trr(yt, 1) = nrr(0)
        trr(yt, 2) = nrr(1)
        
        xt = 2
        nrr = dic.Items()(yt - 1)
        For xs = LBound(nrr) + 1 To UBound(nrr)
            xt = xt + 1
            trr(yt, xt) = nrr(xs)
        Next
    Next
    
    rTarget.Resize(UBound(trr, 1), UBound(trr, 2)).Value = trr
End Sub
    
Private Function GetColumnsCount(dic As Object) As Long
    Dim nn As Long
    Dim vKey As Variant
    For Each vKey In dic.Keys
        nn = UBound(dic(vKey))
        If GetColumnsCount < nn Then GetColumnsCount = nn
    Next
End Function
    
Private Sub EditDic(dic As Object)
    Dim vKey As Variant
    For Each vKey In dic.Keys
        dic(vKey) = Split(dic(vKey), " ")
    Next
End Sub
    
Private Sub FillDicFromRange(rSource As Range, dic As Object)
    Dim rArea As Range, arr As Variant
    For Each rArea In rSource.Areas
        arr = rArea.Resize(, 3).Value
        FillDicFromArray arr, dic
    Next
End Sub

Private Sub FillDicFromArray(arr As Variant, dic As Object)
    Dim ya As Long, xa As Long, sKey As String
    For ya = 1 To UBound(arr, 1)
        For xa = 1 To UBound(arr, 2)
            If IsError(arr(ya, xa)) Then GoTo bad_row
            If IsEmpty(arr(ya, xa)) Then GoTo bad_row
        Next
        If Not arr(ya, 3) Like "#:##:##" Then GoTo bad_row
        sKey = arr(ya, 1) & "#" & arr(ya, 2)
        dic(sKey) = dic(sKey) & " " & arr(ya, 3)
bad_row:
    Next
End Sub

Private Sub ClearTargetRange(rSource As Range, rTarget As Range, columnsCount As Long)
    Dim rEnd As Range
    Set rEnd = rTarget.Cells(1)
    
    Dim rArea As Range
    For Each rArea In rSource.Areas
        Set rArea = rArea.Cells(rArea.Rows.Count, rArea.Columns.Count)
        If rEnd.Row < rArea.Row Then
            Set rEnd = Intersect(rEnd.EntireColumn, rArea.EntireRow)
        End If
    Next
    
    rTarget.Parent.Range(rTarget.Cells(1), rEnd).Resize(, columnsCount).ClearContents
End Sub

 
можно ещё таким макросом
Код
Sub Обращение_транспонирование()
    lr = Cells(Rows.Count, 4).End(xlUp).Row
    arr_1 = Range("D3:F" & lr)
    Set sd = CreateObject("Scripting.Dictionary")
    For n = 1 To UBound(arr_1)
        If Not sd.Exists(arr_1(n, 1) & " | " & arr_1(n, 2)) Then Set sd(arr_1(n, 1) & " | " & arr_1(n, 2)) = CreateObject("Scripting.Dictionary")
        If Not sd(arr_1(n, 1) & " | " & arr_1(n, 2)).Exists(arr_1(n, 3)) Then
            sd(arr_1(n, 1) & " | " & arr_1(n, 2)).Add sd(arr_1(n, 1) & " | " & arr_1(n, 2)).Count, arr_1(n, 3)
            If m < sd(arr_1(n, 1) & " | " & arr_1(n, 2)).Count Then m = sd(arr_1(n, 1) & " | " & arr_1(n, 2)).Count
        End If
    Next
    ReDim arr_rez(1 To sd.Count, 1 To m + 2)
    n = 0
    For Each y In sd
        n = n + 1
        m = 2
        arr_rez(n, 1) = Split(y, " | ")(0)
        arr_rez(n, 2) = Split(y, " | ")(1)
        For Each y1 In sd(y)
            m = m + 1
            arr_rez(n, m) = sd(y)(y1)
        Next
    Next
    lr = Cells(Rows.Count, 8).End(xlUp).Row
    lc = Cells(2, Columns.Count).End(xlToLeft).Column
    If lr > 3 Then Range(Cells(3, 8), Cells(lr, lc)).Clear
    Range("H3").Resize(UBound(arr_rez), UBound(arr_rez, 2)) = arr_rez
End Sub
Страницы: 1
Читают тему
Наверх