Интересно сравнить аналогичное с работой PowerQuery
Ну пока anvg молчит попробую я чего-нить путного изобразить [vba]
Код
let Источник = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content], Отбор = Table.AddColumn( Источник, "Строка", each let клиент=[Номер клиента], закрыто=[Дата закрытия], тема=[Тема обращения] in Table.First( Table.SelectRows( Источник, each [Номер клиента]=клиент and [Дата создания]>закрыто and [Тема обращения]=тема ) ) ), Повтор = Table.FromRecords( Table.TransformRows( Отбор, each Record.TransformFields( _ , let r = _ in { "Повтор", each try if ((r[Строка][Дата создания]-r[Дата закрытия]))<#duration(0,48,1,0) then "Повторное" else "Единичное" otherwise "Единичное" } ) ) ), #"Удаленные столбцы" = Table.RemoveColumns(Повтор,{"Строка"}), #"Измененный тип" = Table.TransformColumnTypes(#"Удаленные столбцы",{{"Код.обращения", Int64.Type}, {"Номер клиента", Int64.Type}, {"Дата создания", type datetime}, {"Дата закрытия", type datetime}, {"Тема обращения", type text}, {"Повтор", type text}}) in #"Измененный тип"
Интересно сравнить аналогичное с работой PowerQuery
Ну пока anvg молчит попробую я чего-нить путного изобразить [vba]
Код
let Источник = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content], Отбор = Table.AddColumn( Источник, "Строка", each let клиент=[Номер клиента], закрыто=[Дата закрытия], тема=[Тема обращения] in Table.First( Table.SelectRows( Источник, each [Номер клиента]=клиент and [Дата создания]>закрыто and [Тема обращения]=тема ) ) ), Повтор = Table.FromRecords( Table.TransformRows( Отбор, each Record.TransformFields( _ , let r = _ in { "Повтор", each try if ((r[Строка][Дата создания]-r[Дата закрытия]))<#duration(0,48,1,0) then "Повторное" else "Единичное" otherwise "Единичное" } ) ) ), #"Удаленные столбцы" = Table.RemoveColumns(Повтор,{"Строка"}), #"Измененный тип" = Table.TransformColumnTypes(#"Удаленные столбцы",{{"Код.обращения", Int64.Type}, {"Номер клиента", Int64.Type}, {"Дата создания", type datetime}, {"Дата закрытия", type datetime}, {"Тема обращения", type text}, {"Повтор", type text}}) in #"Измененный тип"
[moder]Андрей, спасибо за то, что ты указал автору на нарушение Правил, но это вовсе не означает, что прямо здесь можно и ответ давать Удалил я его, ты уж извиняй
ComiC, для оформления формул в постах есть кнопка
[moder]Андрей, спасибо за то, что ты указал автору на нарушение Правил, но это вовсе не означает, что прямо здесь можно и ответ давать Удалил я его, ты уж извиняйkrosav4ig
Всем привет! Набросал я тут код для формирования сортированного списка уникальных значений для проверки данных, в планах по такому же принципу реализовать каскадные выпадающие списки, но как-то времени все нет.
[vba]
Код
'--------------------------------------------------------------------------------------- ' Module : DistinctListDataValidation ' Author : Андрей Лящук aka krosav4ig http://www.excelworld.ru/index/8-krosav4ig ' Date : 27.02.2019 ' Purpose : Генерация сортированного списка уникальных значений для проверки данных '--------------------------------------------------------------------------------------- '--------------------------------------------------------------------------------------- ' function : DistinctValues ' Purpose : Возвращает диапазон со списком уникальных значений ' Arguments : R1 - Верхняя ячейка диапазона с исходным списком ' R2 - Верхняя ячейка диапазона, в который будет помещен список уникальных значений '--------------------------------------------------------------------------------------- Function DistinctValues(R1 As Range, R2 As Range) As Range Dim sR1$, sR2$, sR3$ If IsEmpty(R1) Then Exit Function With Application .Volatile True sR1 = R1.Address(, , .ReferenceStyle, 1) sR2 = R2.Address(, , .ReferenceStyle, 1) sR3 = .Caller.Address(, , .ReferenceStyle, 1) Evaluate "DistinctListDataValidation.PopulateRange(" & sR1 & "," & sR2 & "," & sR3 & ")" .ScreenUpdating = 0 Set DistinctValues = ExtendDown(R2) DoEvents .ScreenUpdating = 1 End With End Function '--------------------------------------------------------------------------------------- ' Procedure : PopulateRange ' Purpose : Заполняет диапазон сгенерированным списком уникальных значений ' Arguments : R1 - Верхняя ячейка диапазона с исходным списком ' R2 - Верхняя ячейка диапазона, в который будет помещен список уникальных значений ' R3 - Application.Caller, в текущем контексте - активная ячейка с выпадающим списком '--------------------------------------------------------------------------------------- Private Sub PopulateRange(R1 As Range, R2 As Range, R3 As Range) Dim v As Variant With ExtendDown(R1) If .Cells.Count = 1 Then ExtendDown(R2).Value = Empty R2 = R1: Exit Sub End If End With With CreateObject("scripting.dictionary") For Each v In ExtendDown(R1).Value .Item(v) = "" Next v = BubbleSort(.keys()) If R3.Value <> "" Then v = Filter(v, R3.Value, False) End With ExtendDown(R2).Value = Empty Application.EnableEvents = 0 R2.Resize(UBound(v) + 1).Value = Application.Transpose(v) Application.EnableEvents = 1 End Sub '--------------------------------------------------------------------------------------- ' Function : BubbleSort ' Purpose : Возвращает массив, отсортированный пузырьковым алгоритмом ' Arguments : v - Исходный массив '--------------------------------------------------------------------------------------- Private Function BubbleSort(v As Variant) As Variant Dim i&, j& For i = LBound(v) To UBound(v) - 1: For j = i To UBound(v) Swap v(i), v(j) Next j, i BubbleSort = v End Function Private Sub Swap(ByRef a As Variant, ByRef b As Variant) If a > b Then: Dim c: c = a: a = b: b = c End Sub '--------------------------------------------------------------------------------------- ' Function : ExtendDown ' Purpose : Возвращает диапазон расширенный вниз до последней непустой ячейки ' Arguments : R - верхняя ячейка диапазона '--------------------------------------------------------------------------------------- Private Function ExtendDown(r As Range) As Range If IsEmpty(r.Offset(1)) Then Set ExtendDown = r Else Set ExtendDown = r.Resize(r.End(xlDown).Row - r.Row + 1) End If End Function
Проверка данных ссылается на эти имена. Тестировал в версиях Excel с 2003 по 2013, во всех работает.
UPD. Убрал лишнюю строку и массив из процедуры PopulateRange
Всем привет! Набросал я тут код для формирования сортированного списка уникальных значений для проверки данных, в планах по такому же принципу реализовать каскадные выпадающие списки, но как-то времени все нет.
[vba]
Код
'--------------------------------------------------------------------------------------- ' Module : DistinctListDataValidation ' Author : Андрей Лящук aka krosav4ig http://www.excelworld.ru/index/8-krosav4ig ' Date : 27.02.2019 ' Purpose : Генерация сортированного списка уникальных значений для проверки данных '--------------------------------------------------------------------------------------- '--------------------------------------------------------------------------------------- ' function : DistinctValues ' Purpose : Возвращает диапазон со списком уникальных значений ' Arguments : R1 - Верхняя ячейка диапазона с исходным списком ' R2 - Верхняя ячейка диапазона, в который будет помещен список уникальных значений '--------------------------------------------------------------------------------------- Function DistinctValues(R1 As Range, R2 As Range) As Range Dim sR1$, sR2$, sR3$ If IsEmpty(R1) Then Exit Function With Application .Volatile True sR1 = R1.Address(, , .ReferenceStyle, 1) sR2 = R2.Address(, , .ReferenceStyle, 1) sR3 = .Caller.Address(, , .ReferenceStyle, 1) Evaluate "DistinctListDataValidation.PopulateRange(" & sR1 & "," & sR2 & "," & sR3 & ")" .ScreenUpdating = 0 Set DistinctValues = ExtendDown(R2) DoEvents .ScreenUpdating = 1 End With End Function '--------------------------------------------------------------------------------------- ' Procedure : PopulateRange ' Purpose : Заполняет диапазон сгенерированным списком уникальных значений ' Arguments : R1 - Верхняя ячейка диапазона с исходным списком ' R2 - Верхняя ячейка диапазона, в который будет помещен список уникальных значений ' R3 - Application.Caller, в текущем контексте - активная ячейка с выпадающим списком '--------------------------------------------------------------------------------------- Private Sub PopulateRange(R1 As Range, R2 As Range, R3 As Range) Dim v As Variant With ExtendDown(R1) If .Cells.Count = 1 Then ExtendDown(R2).Value = Empty R2 = R1: Exit Sub End If End With With CreateObject("scripting.dictionary") For Each v In ExtendDown(R1).Value .Item(v) = "" Next v = BubbleSort(.keys()) If R3.Value <> "" Then v = Filter(v, R3.Value, False) End With ExtendDown(R2).Value = Empty Application.EnableEvents = 0 R2.Resize(UBound(v) + 1).Value = Application.Transpose(v) Application.EnableEvents = 1 End Sub '--------------------------------------------------------------------------------------- ' Function : BubbleSort ' Purpose : Возвращает массив, отсортированный пузырьковым алгоритмом ' Arguments : v - Исходный массив '--------------------------------------------------------------------------------------- Private Function BubbleSort(v As Variant) As Variant Dim i&, j& For i = LBound(v) To UBound(v) - 1: For j = i To UBound(v) Swap v(i), v(j) Next j, i BubbleSort = v End Function Private Sub Swap(ByRef a As Variant, ByRef b As Variant) If a > b Then: Dim c: c = a: a = b: b = c End Sub '--------------------------------------------------------------------------------------- ' Function : ExtendDown ' Purpose : Возвращает диапазон расширенный вниз до последней непустой ячейки ' Arguments : R - верхняя ячейка диапазона '--------------------------------------------------------------------------------------- Private Function ExtendDown(r As Range) As Range If IsEmpty(r.Offset(1)) Then Set ExtendDown = r Else Set ExtendDown = r.Resize(r.End(xlDown).Row - r.Row + 1) End If End Function
конструкция ( ... , ... ) - это кортеж, представляющий пересечение двух размерностей куба/множеств/кортежей [Код], он же [Код].[All] - непосредственно поле Код, [Код].children - значения поля Код Кстати, такая формула тоже работает [vba]
конструкция ( ... , ... ) - это кортеж, представляющий пересечение двух размерностей куба/множеств/кортежей [Код], он же [Код].[All] - непосредственно поле Код, [Код].children - значения поля Код Кстати, такая формула тоже работает [vba]
Sub fffff() dim r as Range With ActiveSheet On Error Resume Next .Outline.ShowLevels 1 Set r = .Columns(1).SpecialCells(2, 23).SpecialCells(12) Set r = Union(.Rows("1:25"), r, r.Offset(1)) .Outline.ShowLevels 8: r.EntireRow.Hidden = True .UsedRange.SpecialCells(12).EntireRow.Delete: r.EntireRow.Hidden = 0 Application.Goto .[A26], 1 End With End Sub
[/vba]
[vba]
Код
Sub fffff() dim r as Range With ActiveSheet On Error Resume Next .Outline.ShowLevels 1 Set r = .Columns(1).SpecialCells(2, 23).SpecialCells(12) Set r = Union(.Rows("1:25"), r, r.Offset(1)) .Outline.ShowLevels 8: r.EntireRow.Hidden = True .UsedRange.SpecialCells(12).EntireRow.Delete: r.EntireRow.Hidden = 0 Application.Goto .[A26], 1 End With End Sub
Sub sortirovka() 'Раскрытие таблицы Dim b As Boolean, r As Range, col as range With [Таблица1].ListObject Set r = .Range.CurrentRegion For Each col In r.Columns If col.Column = r.Column Then .Resize col.Next.Resize(2) ElseIf Not b Then b = True .Resize r.Resize(2, 2) .Resize r.Resize(2, 1) End If With Intersect(.Parent.UsedRange, col.EntireColumn) .sort .Cells(1), xlAscending, Header:=1 End With Next .Resize r.Resize(r.Rows.Count - IsEmpty(r.Cells(2, 1))) End With End Sub
[/vba]
[vba]
Код
Sub sortirovka() 'Раскрытие таблицы Dim b As Boolean, r As Range, col as range With [Таблица1].ListObject Set r = .Range.CurrentRegion For Each col In r.Columns If col.Column = r.Column Then .Resize col.Next.Resize(2) ElseIf Not b Then b = True .Resize r.Resize(2, 2) .Resize r.Resize(2, 1) End If With Intersect(.Parent.UsedRange, col.EntireColumn) .sort .Cells(1), xlAscending, Header:=1 End With Next .Resize r.Resize(r.Rows.Count - IsEmpty(r.Cells(2, 1))) End With End Sub
Sub Obj1ToObj2_1(Obj1, Obj2, Optional Steps = 20) Const dt# = 0.02 Dim x1#, x2#, y1#, y2#, x#, y#, t! Dim l1#, t1#, w1#, h1#, l2#, t2#, w2#, h2# Do: t = Timer: Do: DoEvents: Loop While Timer < t + dt: Loop While b With Obj1 l1 = .Left: t1 = .Top: w1 = .Width: h1 = .Height End With l2 = Obj2(1, 1): t2 = Obj2(1, 2) ' With Obj2 ' l2 = .Left: t2 = .Top: w2 = .Width: h2 = .Height ' End With x1 = l1 + w1 / 2 y1 = t1 + h1 / 2 x2 = l2 ' + w2 / 2 y2 = t2 ' + h2 / 2 With Obj1 For x = x1 To x2 Step (x2 - x1) / Steps y = (x2 * y1 - x1 * y2 - (y1 - y2) * x) / (x2 - x1) .Left = x - w1 / 2 .Top = y - h1 / 2 t = Timer + dt While Timer < t: Wend DoEvents: Next x = x2: y = y2: .Left = x - w1 / 2: .Top = y - h1 / 2 End With b = True End Sub Sub test() Dim lr&, i&, sTmp$ On Error Resume goto err With Evaluate(Application.Caller) sTmp$ = .OnAction .OnAction = "toggle" With Лист1 lr = .Cells(Rows.Count, "n").End(xlUp).Row For i = 6 To lr Obj1ToObj2_1 .Shapes("Oval 1"), .Cells(i, "n").Resize(, 2).Value Next i End With err: .OnAction = sTmp End With MsgBox "Конец" End Sub Private Sub toggle() b = Not b End Sub
[/vba]
Здравствуйте. Как-то так [vba]
Код
Option Explicit Dim b As Boolean
...
Sub Obj1ToObj2_1(Obj1, Obj2, Optional Steps = 20) Const dt# = 0.02 Dim x1#, x2#, y1#, y2#, x#, y#, t! Dim l1#, t1#, w1#, h1#, l2#, t2#, w2#, h2# Do: t = Timer: Do: DoEvents: Loop While Timer < t + dt: Loop While b With Obj1 l1 = .Left: t1 = .Top: w1 = .Width: h1 = .Height End With l2 = Obj2(1, 1): t2 = Obj2(1, 2) ' With Obj2 ' l2 = .Left: t2 = .Top: w2 = .Width: h2 = .Height ' End With x1 = l1 + w1 / 2 y1 = t1 + h1 / 2 x2 = l2 ' + w2 / 2 y2 = t2 ' + h2 / 2 With Obj1 For x = x1 To x2 Step (x2 - x1) / Steps y = (x2 * y1 - x1 * y2 - (y1 - y2) * x) / (x2 - x1) .Left = x - w1 / 2 .Top = y - h1 / 2 t = Timer + dt While Timer < t: Wend DoEvents: Next x = x2: y = y2: .Left = x - w1 / 2: .Top = y - h1 / 2 End With b = True End Sub Sub test() Dim lr&, i&, sTmp$ On Error Resume goto err With Evaluate(Application.Caller) sTmp$ = .OnAction .OnAction = "toggle" With Лист1 lr = .Cells(Rows.Count, "n").End(xlUp).Row For i = 6 To lr Obj1ToObj2_1 .Shapes("Oval 1"), .Cells(i, "n").Resize(, 2).Value Next i End With err: .OnAction = sTmp End With MsgBox "Конец" End Sub Private Sub toggle() b = Not b End Sub
Sub sortirovka() 'Раскрытие таблицы Dim r As Range, i&, j&, v As Variant, arr() As Variant With [Таблица1].ListObject With .Range.CurrentRegion If .Rows.Count < 2 Then Exit Sub ReDim Preserve arr(1 To .Rows.Count - 1, 1 To .Columns.Count) For j = 1 To .Columns.Count For Each r In .Columns(j) i = 1 For Each v In BubbleSort(Intersect(r, r.Offset(1)).Value) arr(i, j) = v i = i + 1 Next v, r, j Intersect(.Offset(1), .Cells).ClearContents .Cells(2, 1).Resize(i - 1, j - 1) = arr End With .Resize .Range.CurrentRegion End With End Sub Function BubbleSort(v As Variant) As Variant Dim i&, j&, b As Boolean If Not IsArray(v) Then BubbleSort = Array(v): Exit Function b = UBound(v) >= UBound(v, 2) For i = 1 To UBound(v, IIf(b, 1, 2)) - 1: For j = i To UBound(v, IIf(b, 1, 2)) swap v(IIf(b, i, 1), IIf(b, 1, i)), v(IIf(b, j, 1), IIf(b, 1, j)) Next j, i BubbleSort = v End Function Sub swap(ByRef a As Variant, b As Variant) If a < b Xor (a <> "") And (b <> "") Then: Dim c: c = a: a = b: b = c End Sub
[/vba]
[vba]
Код
Sub sortirovka() 'Раскрытие таблицы Dim r As Range, i&, j&, v As Variant, arr() As Variant With [Таблица1].ListObject With .Range.CurrentRegion If .Rows.Count < 2 Then Exit Sub ReDim Preserve arr(1 To .Rows.Count - 1, 1 To .Columns.Count) For j = 1 To .Columns.Count For Each r In .Columns(j) i = 1 For Each v In BubbleSort(Intersect(r, r.Offset(1)).Value) arr(i, j) = v i = i + 1 Next v, r, j Intersect(.Offset(1), .Cells).ClearContents .Cells(2, 1).Resize(i - 1, j - 1) = arr End With .Resize .Range.CurrentRegion End With End Sub Function BubbleSort(v As Variant) As Variant Dim i&, j&, b As Boolean If Not IsArray(v) Then BubbleSort = Array(v): Exit Function b = UBound(v) >= UBound(v, 2) For i = 1 To UBound(v, IIf(b, 1, 2)) - 1: For j = i To UBound(v, IIf(b, 1, 2)) swap v(IIf(b, i, 1), IIf(b, 1, i)), v(IIf(b, j, 1), IIf(b, 1, j)) Next j, i BubbleSort = v End Function Sub swap(ByRef a As Variant, b As Variant) If a < b Xor (a <> "") And (b <> "") Then: Dim c: c = a: a = b: b = c End Sub