Страницы: 1
RSS
Складской учет, Помогите оптимизировать мудреные формулы :)
 
Добрый день, умные люди :)
Для ведения фактических остатков доски на складе используем Excel. Раньше наши девчонки делали все (абсолютно все) в ручном режиме, соответственно очень часто возникали ошибки, которые в большом файле найти было сложнее, чем его заново набрать. Вот решил им помочь. Знания Excel у меня на уровне "Google в помощь", вот, что получилось состряпать.
Задача:
Колонки A, B, C - габаритные размеры доски, D - количество в штуках. A-D забиваются вручную
Получить нужно таблицу (J-M) сортированную от большего к меньшему, в которой при обнаружении одного размера (A&B&C) не создавало новую строку, а добавляла в уже существующую новое количество.
Прикладываю то, что у меня удалось слепить из ***** и палок, оно работает, но хотелось бы как-то более очеловечить, а то аж самому смотреть противно :) Наперед большое спасибо за помощь
 
как то так, но без сортировки. синяя табличка
Вполне такой нормальный кинжальчик. Процентов на 100
 
Спасибо, уже вкуснее :) Буду дальше думать, как теперь это еще и отсортировать
 
Это в модуль листа Склад
Код
Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, ActiveSheet.UsedRange.Columns("A:D")) Is Nothing Then
        Wood
    End If
End Sub
Это в стандартный модуль
Код
Sub Wood()
    With Sheets("Склад")
        Dim arr As Variant
        arr = .Range(.Cells(3, 1), .Cells(.Rows.Count, 1).End(xlUp).Cells(1, 4))
        
        Dim dic As Object
        Set dic = CreateObject("Scripting.Dictionary")
        Dim yy As Long
        Dim sKey As String
        For yy = 1 To UBound(arr, 1)
            sKey = myKey(arr(yy, 1), arr(yy, 2), arr(yy, 3))
            If Not dic.Exists(sKey) Then dic.Item(sKey) = dic.Count + 1
        Next
        If dic.Count > 0 Then
            Dim yo As Long
            Dim brr As Variant
            Dim krr As Variant
            Dim orr As Variant
            ReDim orr(1 To dic.Count, 1 To 4)
            krr = dic.Keys()
            For yy = 1 To dic.Count
                brr = Split(krr(yy - 1), vbTab)
                For yo = 0 To UBound(brr, 1)
                    orr(yy, yo + 1) = brr(yo)
                Next
            Next
            For yy = 1 To UBound(arr, 1)
                sKey = myKey(arr(yy, 1), arr(yy, 2), arr(yy, 3))
                yo = dic.Item(sKey)
                orr(yo, 4) = orr(yo, 4) + arr(yy, 4)
            Next
            
            Application.EnableEvents = False
            Dim Application_Calculation As Long
            Application_Calculation = Application.Calculation
            Application.Calculation = xlCalculationManual
            .Range("J3").Resize(.Rows.Count - 3, UBound(orr, 2)).ClearContents
            Dim rOut As Range
            Set rOut = .Range("J3").Resize(UBound(orr, 1), UBound(orr, 2))
            rOut = orr
            
            With .Sort
                .SortFields.Clear
                .SortFields.Add Key:=rOut.Columns(1), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
                .SortFields.Add Key:=rOut.Columns(2), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
                .SortFields.Add Key:=rOut.Columns(3), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
                .SetRange rOut
                .Header = xlGuess
                .MatchCase = False
                .Orientation = xlTopToBottom
                .SortMethod = xlPinYin
                .Apply
            End With
            
            Application.Calculation = Application_Calculation
            Application.EnableEvents = True
        End If
    End With
End Sub
Private Function myKey(ByVal xx As String, ByVal yy As String, ByVal zz As String) As String
    myKey = Join(Array(xx, yy, zz), vbTab)
End Function

 
Цитата
написал:
от большего к меньшему
по какому столбцу? Один из размеров? Объем? Количество?
Скажи мне, кудесник, любимец ба’гов...
 
Сначала сортировка по J, потом по L, потом по K, все от большего к меньшему
 
Тогда самое то сводной таблицей
Скажи мне, кудесник, любимец ба’гов...
 
формулы не нужно оптимизировать, нужно оптимизировать систему организации данных... а потом уже формулы и все остальное
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Спасибо большое всем за помощь. Отличные советы и варианты решения :) Вариант с макросом больше всего пришелся по душе. Буду внедрять теперь в большой файл склада
 
Цитата
написал:
нужно оптимизировать систему организации данных
Учту :)
 
В PQ (для обновления нажать "Обновить все" на вкладке Данные).
1. Простой вариант:
Код
let
  src   = Excel.CurrentWorkbook(){[ Name = "data" ]}[Content],
  group = Table.Group ( src, { "Размер1", "Размер2", "Размер3" }, { { "Кол-во", each List.Sum ( [#"Кол-во"] ), type number } } ),
  sort  = Table.Sort ( group, { { "Размер1", Order.Descending }, { "Размер2", Order.Descending }, { "Размер3", Order.Descending } } )
in
  sort

2. Вариант с сортировкой размеров в строках перед группировкой (вдруг порядок был перепутан; 250x20x4000 будет заменено на 20x250x4000):
Код
let
  src = Excel.CurrentWorkbook(){[ Name = "data" ]}[Content],
  dimNames = List.Buffer ( List.Select ( Table.ColumnNames ( src ), ( x ) => Text.StartsWith ( Text.Lower ( x ), "размер" ) ) ),
  sortDims = Table.FromRecords (
    Table.TransformRows (
      src,
      ( r ) =>
        [
          dimValues = List.Sort ( Record.FieldValues ( Record.SelectFields ( r, dimNames ) ) ),
          newDims   = Record.FromList ( dimValues, dimNames ),
          result    = Record.Combine ( { newDims, Record.RemoveFields ( r, dimNames ) } )
        ][result]
    )
  ),
  group = Table.Group ( sortDims, dimNames, { { "Кол-во", each List.Sum ( [#"Кол-во"] ), type number } } ),
  sort = Table.Sort ( group, List.Transform ( dimNames, ( x ) => { x } & { Order.Descending } ) )
in
  sort
Страницы: 1
Наверх