1с Ведомость оборотная Excel Макрос VBA

2. Подгрузка в Оборотную ведомость категорий и сроков годности Из файла подгружаем значение срока годности для каждого товара и категории 5 уровней.

3. Простановка сроков годности для каждой Приходной накладной Для каждой приходной накладной устанавливается срок годности ДО по формуле: Дата накладной + Срок годности товара.

4. Формирование строки с остатком по срокам годности Обычно в учетной системе (1С и других) можно посмотреть товародвижение по каждому товару. Приход на склад (Приходная накладная) и расход (в данном случае Z-отчёт). В столбце конечный остаток можно посмотреть сколько единиц товара осталось на складе (Столбец конечный остаток) после каждой операции. Идея состоит в том, чтобы мы видели не просто общий остаток по каждому товару, но и условный срок годности по каждой единице товара. В новом столбце Остаток по срокам, который мы делаем отображается: 2 до 10.08, 5 до 15.08 Это значит 2 батона колбасы сроком до 10 августа 2018 и 5 батонов сроком до 15 августа 2018 г. Товары расходуются по методу FIFO (сначала продаются самые старые из всех что есть и тд). Z-отчёт — это продажи.

' FIFO ФИФО оборотная ведомость
 
Option Explicit
 
Private bDebug As Boolean
Private AppCalc As Variant, AppScr As Boolean, AppDispAl As Boolean    'для Excel-Speed
 
Public Function arr_2d_Copy_2_New(arr_2d(), _
                                  Optional ByVal Row_Start As Long, _
                                  Optional ByVal Row_End As Long, _
                                  Optional ByVal Col_Start As Long, _
                                  Optional ByVal Col_End As Long) As Variant
'https://drakonhub.com/ide/doc/pme/93
 
    arr_2d_Copy_2_New = arr_2d_Copy(arr_2d, _
                                    Row_Start, Row_End, Col_Start, Col_End)
End Function
 
Private Sub arr_2d_Copy_test()
 
    Dim ws As Worksheet: Set ws = ActiveSheet
    Dim arr_2d_Sour() As Variant, arr_2d_Dest() As Variant
    With ws
        ' плацдарм очистить
        .Columns("K:S").ClearContents
 
        arr_2d_Sour = .Cells(1, 1).CurrentRegion.Value
 
        Dim Row_Start As Long, Row_End As Long, _
            Col_Start As Long, Col_End As Long
        ' массив границы генерирую
        Row_End = Случ_Между(LBound(arr_2d_Sour), _
                             UBound(arr_2d_Sour))
        Row_Start = Случ_Между(LBound(arr_2d_Sour), Row_End)
 
        Col_End = Случ_Между(LBound(arr_2d_Sour, 2), _
                             UBound(arr_2d_Sour, 2))
        Col_Start = Случ_Между(LBound(arr_2d_Sour, 2), Col_End)
        ' массив создаю копированием
        arr_2d_Dest = arr_2d_Copy(arr_2d_Sour, Row_Start, Row_End, _
                                  Col_Start, Col_End)
 
        Массив_Вставить arr_2d_Dest, .Cells(1, 11)
    End With    'ws
End Sub
 
Public Function arr_2d_Copy(arr_2d_Sour() As Variant, _
                            Optional ByVal Row_Start As Long, Optional ByVal Row_End As Long, _
                            Optional ByVal Col_Start As Long, Optional ByVal Col_End As Long) _
                            As Variant
' Часть массива скопировать в новымй массив, _
  а если не заданы аргументы, то один в один
 
'Подставляю значения границ, если они пустые
    If Row_Start = 0 Then Row_Start = LBound(arr_2d_Sour)
    If Row_End = 0 Then Row_End = UBound(arr_2d_Sour)
    If Col_Start = 0 Then Col_Start = LBound(arr_2d_Sour, 2)
    If Col_End = 0 Then Col_End = UBound(arr_2d_Sour, 2)
 
 
    ' Делаю границы нового массива
    Dim Row_End_Dest As Long, Col_End_Dest As Long
    Row_End_Dest = Row_End - Row_Start + 1
    Col_End_Dest = Col_End - Col_Start + 1
 
    ' Массив создаю
    Dim arr_2d_Dest() As Variant
    ReDim arr_2d_Dest(LBound(arr_2d_Sour) To Row_End_Dest, _
                      LBound(arr_2d_Sour, 2) To Col_End_Dest)
 
    Dim y As Long, x As Long
 
    On Error Resume Next    ' для ошибок в "ячейках"
 
    For y = LBound(arr_2d_Dest) To UBound(arr_2d_Dest)
        For x = LBound(arr_2d_Dest, 2) To UBound(arr_2d_Dest, 2)
 
            arr_2d_Dest(y, x) = arr_2d_Sour(Row_Start + y - 1, Col_Start + x - 1)
 
        Next
        If Row_Start + y > Row_End And _
           Col_Start + y > Col_End Then _
           Exit For
    Next
 
    If IsArray(arr_2d_Dest) Then _
       arr_2d_Copy = arr_2d_Dest
 
End Function
 
Public Function arr_2d_Границы_Проверка(arr_2d() As Variant, _
                                        ByVal Row_Start As Long, _
                                        ByVal Row_End As Long, _
                                        Optional ByVal Col_Start As Long, _
                                        Optional ByVal Col_End As Long) As Boolean
 
    arr_2d_Границы_Проверка = True
 
    If Row_End < LBound(arr_2d) And _
       Row_End > UBound(arr_2d) Then _
       arr_2d_Границы_Проверка = False
 
    If Row_Start < LBound(arr_2d) And _
       Row_Start > UBound(arr_2d) Then _
       arr_2d_Границы_Проверка = False
 
    If Row_Start > Row_End Then Row_Start = Row_End
 
    If Col_End < LBound(arr_2d) And _
       Col_End > UBound(arr_2d) Then _
       arr_2d_Границы_Проверка = False
 
    If Col_Start < LBound(arr_2d) And _
       Col_Start > UBound(arr_2d) Then _
       arr_2d_Границы_Проверка = False
 
    If Col_Start > Col_End Then Col_Start = Col_End
 
    ' потом дописать для столбцов
End Function
 
Public Sub Excel_Speed_off(Optional ByVal DeMand As Boolean = False)    ' ускорение убрать
' Если Demand = True, то  принудительно вернуть
 
'Тест
'     Excel_Speed_off 1
    With Application
        If DeMand Then
            .Calculation = xlCalculationAutomatic
            .ScreenUpdating = True
            .DisplayAlerts = True
        Else
            If IsEmpty(AppCalc) = False Then
                .Calculation = AppCalc
                .ScreenUpdating = AppScr
                .DisplayAlerts = AppDispAl
            End If
        End If
 
        .CutCopyMode = False
        .StatusBar = vbNullString
    End With
End Sub
 
Public Sub Excel_Speed_ON()                        'ускорить excel
'В начало модуля:
' Public AppCalc As Variant, AppScr As Boolean, AppDispAl As Boolean 'для Excel-Speed
    With Application
        If IsEmpty(AppCalc) Then
            AppCalc = .Calculation
            AppScr = .ScreenUpdating
            AppDispAl = .DisplayAlerts
        End If
        If .Calculation <> xlCalculationManual Then _
           .Calculation = xlCalculationManual
        If .ScreenUpdating <> False Then _
           .ScreenUpdating = False
        If .DisplayAlerts <> False Then _
           .DisplayAlerts = False
    End With
End Sub
 
Public Function extract_Between(ByVal txt As Variant, _
                                ByVal sLeft As String, _
                                ByVal sRight As String) As String
'извлечь между
    If Len(txt) > 0 And Len(txt) > 0 And Len(txt) > 0 And _
       InStr(txt, sLeft) > 0 And InStr(txt, sRight) > 0 Then
        Dim s
        s = Split(txt, sLeft)
        s = Split(s(1), sRight)
        extract_Between = s(0)
    Else
        'обработка ошибки
        ' Err.Raise 567, "extract_Between", "Ошибка"
    End If
End Function
 
Public Sub MsgBox4Debug(Optional ByVal sPrompt As String = vbNullString, _
                        Optional ByVal sTitle As String = vbNullString)
    Select Case MsgBox(sPrompt _
                       & vbCrLf & "Да = Продолжить" _
                       & vbCrLf & "Нет = Отладка" _
                       & vbCrLf & "Отмена = Выход из макроса" _
                       , vbYesNoCancel Or vbCritical Or vbDefaultButton1, _
                       sTitle)
    Case vbYes
        'ничего
    Case vbNo
        Debug.Print sPrompt, sTitle
        Stop
    Case vbCancel
        End                          '===>>>
    End Select
End Sub
 
 
Public Sub ProgressBar_Turbo(ByRef txt As String, _
                             ByRef i As Long, _
                             ByRef max As Long)
' dim Турбо as long 'в начало модуля
    Dim Турбо As Long
    Турбо = Len(CStr(max)) * Len(CStr(max))
 
    If bDebug Then
        Application.StatusBar = Right$(txt, 123) & " прогресс: " & Format$(i, "# ### ###") & _
                                " из " & Format$(max, "# ### ###") & ": " & _
                                Format$(i / max, "Percent")
 
    Else
 
        If Турбо = Int((Турбо * Rnd) + 1) Then
            Application.StatusBar = txt & " прогресс: " & Format$(i, "# ### ###") & _
                                    " из " & Format$(max, "# ### ###") & ": " & _
                                    Format$(i / max, "Percent")
            With Application
 
                If Second(Time) > 5 Then
 
                    If .ScreenUpdating = False Then .ScreenUpdating = True
                    DoEvents
                Else
 
                    If .ScreenUpdating = True Then .ScreenUpdating = False
                End If
            End With
        End If
    End If
End Sub
 
Public Function ИмяФайлаБезПути(ByRef s As String) As String
    ИмяФайлаБезПути = Right$(s, Len(s) - InStrRev(s, "\"))
End Function
 
Public Sub Массив_Вставить(arr_Xd(), rng As Range)
' массив вставить на лист  1 или 2 размерные
 
    If IsArray(arr_Xd) = False Then MsgBox4Debug    ''IsArray(arr_Xd) = False ","Массив_Вставить"
    If rng Is Nothing Then MsgBox4Debug    ''rng Is Nothing ","Массив_Вставить"
 
    Dim Option_Base_Offset
    Option_Base_Offset = IIf(Option_Base = 0, 1, 0)
 
    With rng
 
        Select Case Массив_Размерность(arr_Xd)
        Case 1
            .Resize(UBound(arr_Xd) + Option_Base_Offset, 1) = _
            Application.WorksheetFunction.Transpose(arr_Xd)
        Case 2
            .Resize(UBound(arr_Xd), _
                    UBound(arr_Xd, 2)) = arr_Xd
        Case Else
            Err.Raise 567, "Массив_Вставить", "Массив размерность не 1 и на 2"
        End Select
    End With
End Sub
 
Public Function Массив_2d_Найти_в_Столбце(arr_2d, ByVal iCol As Long, _
                                          ByVal vVar As Variant, ByVal Целиком_1_Часть_2 As Long, _
                                          Optional ByVal Вхождение_Номер As Long = 1) _
                                          As Long
    Dim y As Long
 
    If Целиком_1_Часть_2 = 1 Then
 
        For y = LBound(arr_2d) To UBound(arr_2d)
 
            'If InStr(arr_2d(y, iCol), "102314") Then Stop
 
 
            If CStr(arr_2d(y, iCol)) = vVar Then _
               Exit For
        Next
    Else
 
        For y = LBound(arr_2d) To UBound(arr_2d)
 
            If InStr(arr_2d(y, iCol), vVar) > 0 Then _
               Exit For
        Next
    End If
 
    Массив_2d_Найти_в_Столбце = y
 
    'счётчик вышел за предел цикла = не найдено
    If y > UBound(arr_2d) Then _
       Массив_2d_Найти_в_Столбце = 0
 
End Function
 
Public Sub Массив_2d_Найти_в_Столбце_test()
    Dim rng As Range, arr_2d() As Variant
    Dim vStr As Variant, vVar As Variant, vLong As Long
 
    Set rng = Application.Intersect(ActiveSheet.Columns(1), _
                                    ActiveSheet.UsedRange)
 
    arr_2d = rng.Value
 
    With ActiveCell
        vLong = CVar(.Value)
        vStr = CVar(.Value)
        vVar = CVar(.Value)
    End With
 
    Debug.Print Массив_2d_Найти_в_Столбце(arr_2d(), 1, CVar(vLong), 1)
    Debug.Print Массив_2d_Найти_в_Столбце(arr_2d(), 1, CVar(vStr), 1)
    Debug.Print Массив_2d_Найти_в_Столбце(arr_2d(), 1, vVar, 1)
 
End Sub
 
Public Function Массив_Размерность(arr()) As Long   'возвращает количество измерений массива Arr
    Dim i As Long, x As Long
    On Error GoTo eXX
    ' увеличиваю i пока не получим ошибку _
      попытки получить UBound по данному измерению
    Do: i = i + 1
        x = UBound(arr, i)
    Loop
eXX:
    Массив_Размерность = i - 1
End Function
 
'простой и сортировка по любому количеству столбцов в любом порядке.
' Кому надо направление сортировки и произвольные границы,
'можете доработать сами.
' Последняя строка массива передается, потому что массив
'может быть заполнен не весь
'Вызов: SortArray ar, 5, 2, 0, 1
'Ar - массив, 5 - последняя строка, 2, 0, 1 - столбцы для сортировки
Private Sub Массив_Сортировка(myArray, countRows, ParamArray sortC())
    Dim cRA%, cR%, minR%, cS%, cE%, countC%, tempV
 
    countRows = UBound(myArray)
 
    For cRA = 0 To countRows - 1
        minR = cRA
 
        For cR = cRA + 1 To countRows - 1
 
            For cS = 0 To UBound(sortC)
 
                If myArray(cR, sortC(cS)) <> myArray(minR, sortC(cS)) Then
 
                    If myArray(cR, sortC(cS)) < myArray(minR, sortC(cS)) Then _
                       minR = cR
                    Exit For
                End If
            Next
        Next
 
        If minR > cRA Then
            Dim cC As Long
            'меняем местами строки
            For cC = 0 To UBound(myArray, 2)
 
                tempV = myArray(cRA, cC)
 
                myArray(cRA, cC) = myArray(minR, cC)
 
                myArray(minR, cC) = tempV
            Next
        End If
    Next
End Sub
 
Private Sub Массив_Сортировка_test()
    Dim arr()
    arr = Selection
    Массив_Сортировка arr, 1
End Sub
 
Public Function _
       Массив_Столбец_Ячейка_не_Пустая_Одиночная _
       (arr_Xd(), _
        ByVal iCol As Long, ByVal iRow As Long) _
        As Long
 
    If IsArray(arr_Xd) = False Then _
       MsgBox4Debug "IsArray(arr_Xd) = False", "Массив_Столбец_Ячейка_не_Пустая_Одиночная"
 
    If iRow < LBound(arr_Xd) Or iRow > UBound(arr_Xd) Then _
       MsgBox4Debug " iRow < LBound(arr_Xd) Or iRow > UBound(arr_Xd) ", "Массив_Столбец_Ячейка_не_Пустая_Одиночная"
 
    Dim y As Long
 
    Select Case Массив_Размерность(arr_Xd)
    Case 1
        For y = iRow To UBound(arr_Xd)
 
            If y < UBound(arr_Xd) Then
 
                If arr_Xd(y) <> vbNullString And _
                   arr_Xd(y + 1) = vbNullString Then
 
                    Массив_Столбец_Ячейка_не_Пустая_Одиночная = y
                End If
            End If
        Next
 
    Case 2
 
        If iCol < LBound(arr_Xd, 2) Or iCol > UBound(arr_Xd, 2) Then _
           MsgBox4Debug " iCol < LBound(arr_Xd, 2) Or iCol > UBound(arr_Xd, 2)", "Массив_Столбец_Ячейка_не_Пустая_Одиночная"
 
        For y = iRow To UBound(arr_Xd)
 
            If y < UBound(arr_Xd) Then
 
                If arr_Xd(y, iCol) <> vbNullString And _
                   arr_Xd(y + 1, iCol) = vbNullString Then
 
                    Массив_Столбец_Ячейка_не_Пустая_Одиночная = y
                    Exit For
                End If
            End If
        Next
 
    Case Else
        MsgBox4Debug "Массив_Столбец_Ячейка_не_Пустая_Одиночная"
    End Select
 
    If y >= UBound(arr_Xd) Then _
       Массив_Столбец_Ячейка_не_Пустая_Одиночная = UBound(arr_Xd)    'не найдено, поэтому последняя
End Function
 
Public Function ОткрытаЛиКнига(ByVal wbName As String) As Boolean
' вызов If Not ОткрытаЛиКнига(ИмяФайла) Then Workbooks.Open ИмяФайла
    wbName = Right$(wbName, Len(wbName) - InStrRev(wbName, "\"))    ' отсечь путь
    Dim wbBook As Workbook
    For Each wbBook In Workbooks
        If wbBook.Name = wbName Then
            ОткрытаЛиКнига = True
            Exit For
        End If
    Next wbBook
End Function
 
Public Function Столбец_Крайний(ws As Worksheet) As Long
' Найти последний столбец с данными, непустой
    On Error Resume Next
    Столбец_Крайний = _
    ws.Cells.Find(What:="*", SearchOrder:=xlByColumns, _
                  SearchDirection:=xlPrevious).Column
    If Столбец_Крайний = 0 Then Столбец_Крайний = 1
End Function
 
Public Function Строка_Крайняя(ws As Worksheet) As Long
' Найти последняя строку  с данными, непустую
    On Error Resume Next
    Строка_Крайняя = _
    ws.Cells.Find(What:="*", SearchOrder:=xlByRows, _
                  SearchDirection:=xlPrevious).Row
    If Строка_Крайняя = 0 Then Строка_Крайняя = 1
End Function
 
Public Sub Уровень_Отступа_в_массив(ws As Worksheet, _
                                    Столбец As Long, Строка As Long, arr_2d(), _
                                    arr_Col As Long, arr_Row As Long)
'Для таблиц из 1С
'  заполнить столбец массива уровнями отступа в ячейках столбца листа
 
' ToDo: сделать необходимые проверки
 
    Dim rng As Range, eL As Range
 
    With ws
        Set rng = .Range(.Cells(Строка, Столбец), _
                         .Cells(Строка_Крайняя(ws), Столбец))    '
    End With
 
    Dim y As Long, x As Long
    y = arr_Row: x = arr_Col
 
    For Each eL In rng
        If eL.Value <> vbNullString Then
 
            arr_2d(y, x) = eL.IndentLevel
 
            y = y + 1
 
            ProgressBar_Turbo "Уровень_Отступа_в_массив ", arr_Row, rng.Rows.Count
        End If
    Next
 
    Application.StatusBar = vbNullString
End Sub
 
Public Function Случ_Между(ByVal ОграничНижн As Variant, _
                           ByVal ОграничВерх As Variant, _
                           Optional ByVal StopOnError As Boolean = True) As Long
'Для сокращения кода, чтобы не читать _
  Application.WorksheetFunction.RandBetween(ОграничНижн, _
  ОграничВерх)
'Возвращает случайное целое число, находящееся _
  в диапазоне между двумя заданными числами.
    If IsNumeric(ОграничНижн) = False Or _
       IsNumeric(ОграничВерх) = False Then
 
        If StopOnError Then _
           MsgBox4Debug "Есть НЕ числа", "Случ_Между"
    Else
        ' ничего
    End If
 
    Randomize
 
    Случ_Между = Application.WorksheetFunction. _
                 RandBetween(ОграничНижн, _
                             ОграничВерх)
End Function
 
Public Function Лист_Получить(ByVal Путь As String, _
                              ByVal Файл As String, ByVal Лист As String) _
                              As Worksheet
    Dim wb As Workbook
 
    Путь = Путь & "\" & Файл
 
    If Not ОткрытаЛиКнига(Файл) Then _
       Workbooks.Open Путь
 
    Set wb = Workbooks(Файл)
 
    Set Лист_Получить = wb.Worksheets(Лист)
End Function
 
Public Function Файл_Расширение_без_Имени(str As String) As String
'Возвращает имя файла без расширения
    Dim iPos As Long
    iPos = Len(str) - InStrRev(str, ".")
 
    Файл_Расширение_без_Имени = Right$(str, iPos)
End Function
 
Public Function Файл_Имя_без_Расширения(str As String)
' Возвращает расширение без имени файла
    Dim iPos As Long
    iPos = InStr(str, ".") - 1
 
    Файл_Имя_без_Расширения = Left$(str, iPos)
End Function
 
Public Function Массив_Копировать(arr_Xd(), _
                                  Optional ByVal Row_Start As Long, _
                                  Optional ByVal Row_End As Long, _
                                  Optional ByVal Col_Start As Long, _
                                  Optional ByVal Col_End As Long)
'Накопировать часть массива в массив поменьше
' Баунды нового массива могут начинаться с Row_Start и Col_Start
    Dim Проверка As String
    Проверка = Массив_Копировать_Проверка(arr_Xd, Row_Start, Row_End, _
                                          Col_Start, Col_End)
 
    '    If Проверка <> vbNullString Then _
         '       Err.Raise 567, "Проверка", "Массив_Копировать"
 
    If Row_Start = 0 Then Row_Start = LBound(arr_Xd)
    If Row_End = 0 Then Row_End = UBound(arr_Xd)
 
    Dim y As Long, x As Long
 
    Select Case Массив_Размерность(arr_Xd())
    Case 1
        MsgBox4Debug "для 1d пока не сделал", "Массив_Копировать"
    Case 2
 
        Dim arr_2d_New() As Variant
        ReDim arr_2d_New(Row_Start To Row_End, _
                         Col_Start To Col_End)
 
        Dim Row_Offset As Long, Col_Offset As Long
        Col_Offset = 0: Row_Offset = 0
 
        '            Row_Offset = UBound(arr_Xd) - UBound(arr_2d_New)
        '
        '            If UBound(arr_2d_New, 2) > UBound(arr_Xd, 2) Then
        '                Col_Offset = UBound(arr_Xd, 2) - UBound(arr_2d_New, 2)
        '            Else
        '                Col_Offset = 0
        '            End If
 
        On Error Resume Next
 
        For y = Row_Start To Row_End
 
            For x = Col_Start To Col_End
 
                arr_2d_New(y, x) = arr_Xd(y + Row_Offset, x + Col_Offset)
            Next
        Next
    Case Else
        Err.Raise 567, "Массив_Копировать", _
                  "Размерность ещё пока не поддерживается"
    End Select
 
    On Error GoTo 0
 
    If IsArray(arr_2d_New) Then _
       Массив_Копировать = arr_2d_New
 
End Function
 
Public Function Массив_Копировать_Проверка(arr_Xd(), _
                                           Optional ByVal Row_Start As Long, _
                                           Optional ByVal Row_End As Long, _
                                           Optional ByVal Col_Start As Long, _
                                           Optional ByVal Col_End As Long) _
                                           As String
    If IsArray(arr_Xd()) = False Then
        Массив_Копировать_Проверка = "IsArray(arr_Xd()) = False"
    End If
    'Для нулевых значений ничего не делаю
    If Row_Start <> 0 Then
        If Row_Start < LBound(arr_Xd) And Row_Start > UBound(arr_Xd) Then
            Массив_Копировать_Проверка = "Row_Start < LBound(arr_Xd) And Row_Start > UBound(arr_Xd) "
        End If
    End If
 
    If Row_End <> 0 Then
        If Row_End < LBound(arr_Xd) And Row_End > UBound(arr_Xd) Then
            Массив_Копировать_Проверка = "Row_End < LBound(arr_Xd) And Row_End > UBound(arr_Xd) "
            Exit Function
        End If
    End If
 
    If Row_End < Row_Start Then
        Массив_Копировать_Проверка = "Row_End < Row_Start"
    End If
 
    Select Case Массив_Размерность(arr_Xd)
    Case 1
        Массив_Копировать_Проверка = "Для  1d ещё не сделано"
    Case 2
 
        If Col_Start <> 0 Then
            If Col_Start < LBound(arr_Xd, 2) And Col_Start > UBound(arr_Xd, 2) Then
                Массив_Копировать_Проверка = "Col_Start < LBound(arr_Xd,2) And Col_Start > UBound(arr_Xd,2) "
                Exit Function
            End If
        End If
 
        If Col_End <> 0 Then
            If Col_End < LBound(arr_Xd, 2) And Col_End > UBound(arr_Xd, 2) Then
                Массив_Копировать_Проверка = "Col_End < LBound(arr_Xd,2) And Col_End > UBound(arr_Xd,2) "
            End If
        End If
 
        If Col_End < Col_Start Then
            Массив_Копировать_Проверка = "Col_End < Col_Start"
        End If
 
    Case Else
    End Select
 
    If Массив_Копировать_Проверка <> vbNullString Then
        Err.Raise 567, "Массив_Копировать_Проверка", Массив_Копировать_Проверка
    End If
End Function
 
Private Sub Массив_Копировать_test()
 
    Dim arr()
    arr = Selection
    arr = Массив_Копировать(arr, 2, 3, 2, 2)
    Stop
End Sub
 
Public Function f_dic_Uniq_From_arr_2d(arr() As Variant, _
                                       iCol As Long) _
                                       As Dictionary    ' Microsoft Scripying Runtime должен быть включен
' Возвращает словарь из массива
 
    If IsArray(arr) = False Then Exit Function
 
    If iCol < LBound(arr) Or iCol > UBound(arr) Then Exit Function
 
    'позднее связывание
    Dim dic_Temp
    Set dic_Temp = CreateObject("Scripting.Dictionary")
 
    Dim key As Variant, item As Variant
 
    Dim y As Long
    For y = LBound(arr) To UBound(arr)
        key = arr(y, iCol)
        item = key
        If dic_Temp.Exists(key) = False Then _
           dic_Temp.Add key, item
    Next
 
    Set f_dic_Uniq_From_arr_2d = dic_Temp
End Function
 
Private Sub Dic_from_Arr_2d_test()
 
    Dim dic_Temp
    Set dic_Temp = CreateObject("Scripting.Dictionary")
 
    'Дл Матрицы
    dic_Temp = Dic_from_Arr_2d( _
               Диапазон_в_Массив( _
               Range(Cells(1, 1), Cells(47209, 1))), _
               1)
End Sub
 
Public Function Диапазон_в_Массив(rng As Range) As Variant
    Диапазон_в_Массив = rng.Value
End Function
 
Public Function Dic_from_Arr_2d(arr As Variant, _
                                iCol As Long) _
                                As Dictionary    ' Microsoft Scripying Runtime должен быть включен
' Возвращает словарь из массива
 
'позднее связывание
    Dim dic_Temp
    Set dic_Temp = CreateObject("Scripting.Dictionary")
 
 
    Dim y As Long
 
    For y = LBound(arr) To UBound(arr)
        dic_Temp.Add y, arr(y, iCol)
    Next
 
    Set Dic_from_Arr_2d = dic_Temp
End Function
 
 
Sub ShowUniqKeys()
    Dim Element
    Dim dic_Temp As New Dictionary
    With dic_Temp
        For Each Element In Array("Один", "Один", "Один", "Один", "Один")
            ' Используем Count в качестве значения ключа
            ' таким образом ключи будут 0,1,2,3,4
            .item(.Count) = Element
        Next
        MsgBox Join(.Keys, vbLf)
    End With
End Sub
 
Public Function App_Union(rng_Union As Range, _
                          ByVal rng As Range) _
                          As Range    ' InExSu
' Range Union, объединение диапазонов
' Для упрощения чтения кода
' вызов: Set rng_union = App_Union(rng_union, .Rows(x))
 
'    If rng_union.Parent.Name <> rng.Parent.Name Then MsgBox4Debug
 
    If Not rng_Union Is Nothing Then
        ' If rng_Union.Parent.Name <> rng.Parent.Name Then MsgBox4Debug
        Set rng_Union = Application.Union(rng_Union, rng)
    Else
        Set rng_Union = rng
    End If
 
    Set App_Union = rng_Union
End Function
 
 
Public Function массив_из_Столбцов(ByVal ws As Worksheet, _
                                   ByVal Row_Start As Long, ByVal Row_End As Long, _
                                   arr_1d_CoL() As Variant) As Variant
 
    Dim ws_Temp As Worksheet
    ws_Ведомость.Copy After:=ActiveSheet
    Set ws_Temp = ActiveSheet
 
    Dim rng_Union As Range, rng As Range, x As Long
 
    With ws_Temp
 
        .Cells.UnMerge    'копирование боится объединённых ячеек
 
        For x = LBound(arr_1d_CoL) To UBound(arr_1d_CoL)
 
 
            Set rng = .Range(.Cells(Row_Start, arr_1d_CoL(x)), .Cells(Row_End, arr_1d_CoL(x)))
 
 
            Set rng_Union = App_Union(rng_Union, rng)
 
        Next
    End With
 
    массив_из_Столбцов = Диапазон_на_лист_и_в_массив(rng_Union)
 
    Лист_Удалить_Без_Вопросов ws_Temp
End Function
 
Public Sub Лист_Удалить_Без_Вопросов(ws As Worksheet)
    Dim ApPl_Event As Boolean, Appl_Alert As Boolean, ws_Act As Worksheet
 
    With Application
 
        ApPl_Event = .EnableEvents
        Appl_Alert = .DisplayAlerts
 
        .EnableEvents = False
        .DisplayAlerts = False
 
        ws.Delete
 
        .EnableEvents = ApPl_Event
        .DisplayAlerts = Appl_Alert
    End With
End Sub
Public Function Диапазон_на_лист_и_в_массив(ByVal rng As Range) As Variant
' несвязные, несмежные диапазоны коппруются в массив не полнотсью,
' а здесь полнсотью
 
    If rng Is Nothing Then _
       Err.Raise 567, "Диапазон_на_лист_и_в_массив", "rng Is Nothing"
 
    Dim wb As Workbook, Row_End As Long
    Set wb = Workbooks.Add
 
    With wb.ActiveSheet
        rng.Copy .Cells(1, 1)
 
        Диапазон_на_лист_и_в_массив = .UsedRange.Value
    End With
 
    wb.Close False
End Function

Оставить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.