Изменения

Строка 715: Строка 715:     
Ошибки как правило сразу видны внутри акта в шапке в "Ответах в тикете"; и можно подробнее посмотреть ниже в "Запросах" что именно целиком прислал ЕГАИС.
 
Ошибки как правило сразу видны внутри акта в шапке в "Ответах в тикете"; и можно подробнее посмотреть ниже в "Запросах" что именно целиком прислал ЕГАИС.
 +
 +
===Схлопнуть марки в выгруженном списке из акта===
 +
 +
Сейчас в "Актах списания" ШК может повторяться в нескольких строках с разным объёмом - для сохранения истории добавлений; если же требуется вычислить общий объём таких ШК в акте, то надо зайти во вкладку "Марки", выгрузить xlsx файл, затем использовать макрос для суммирования.
 +
 +
Макрос:
 +
 +
<pre>
 +
Option Explicit
 +
 +
Sub СхлопнутьМаркиИСуммироватьОбъем()
 +
 +
    Const HEADER_ROW As Long = 1
 +
    Const RESULT_SHEET_NAME As String = "Схлопнутые марки"
 +
 +
    Dim sourceSheet As Worksheet
 +
    Dim resultSheet As Worksheet
 +
 +
    Dim markColumn As Long
 +
    Dim volumeColumn As Long
 +
    Dim lastRow As Long
 +
    Dim lastColumn As Long
 +
 +
    Dim sourceData As Variant
 +
    Dim resultData() As Variant
 +
 +
    Dim dictionary As Object
 +
    Dim rowIndexes As Object
 +
 +
    Dim rowNumber As Long
 +
    Dim columnNumber As Long
 +
    Dim resultRow As Long
 +
 +
    Dim markValue As String
 +
    Dim volumeValue As Double
 +
    Dim dictionaryKey As Variant
 +
 +
    On Error GoTo ErrorHandler
 +
 +
    Application.ScreenUpdating = False
 +
    Application.EnableEvents = False
 +
    Application.DisplayAlerts = False
 +
 +
    Set sourceSheet = ActiveSheet
 +
 +
    ' Определяем границы таблицы
 +
    lastRow = sourceSheet.Cells( _
 +
        sourceSheet.Rows.Count, 1 _
 +
    ).End(xlUp).Row
 +
 +
    lastColumn = sourceSheet.Cells( _
 +
        HEADER_ROW, sourceSheet.Columns.Count _
 +
    ).End(xlToLeft).Column
 +
 +
    ' Ищем нужные столбцы по названиям
 +
    For columnNumber = 1 To lastColumn
 +
 +
        Select Case Trim$(CStr(sourceSheet.Cells( _
 +
            HEADER_ROW, columnNumber _
 +
        ).Value))
 +
 +
            Case "Марка"
 +
                markColumn = columnNumber
 +
 +
            Case "Объем (мл)"
 +
                volumeColumn = columnNumber
 +
 +
        End Select
 +
 +
    Next columnNumber
 +
 +
    If markColumn = 0 Then
 +
        Err.Raise vbObjectError + 1, , _
 +
            "Не найден столбец «Марка»."
 +
    End If
 +
 +
    If volumeColumn = 0 Then
 +
        Err.Raise vbObjectError + 2, , _
 +
            "Не найден столбец «Объем (мл)»."
 +
    End If
 +
 +
    If lastRow <= HEADER_ROW Then
 +
        Err.Raise vbObjectError + 3, , _
 +
            "В таблице отсутствуют строки с данными."
 +
    End If
 +
 +
    ' Загружаем таблицу в память
 +
    sourceData = sourceSheet.Range( _
 +
        sourceSheet.Cells(HEADER_ROW, 1), _
 +
        sourceSheet.Cells(lastRow, lastColumn) _
 +
    ).Value2
 +
 +
    Set dictionary = CreateObject("Scripting.Dictionary")
 +
    Set rowIndexes = CreateObject("Scripting.Dictionary")
 +
 +
    ' Марки сравниваются целиком, с учётом регистра
 +
    dictionary.CompareMode = vbBinaryCompare
 +
    rowIndexes.CompareMode = vbBinaryCompare
 +
 +
    ' Сначала собираем суммы
 +
    For rowNumber = 2 To UBound(sourceData, 1)
 +
 +
        markValue = Trim$(CStr(sourceData( _
 +
            rowNumber, markColumn _
 +
        )))
 +
 +
        If Len(markValue) > 0 Then
 +
 +
            volumeValue = GetNumericVolume( _
 +
                sourceData(rowNumber, volumeColumn) _
 +
            )
 +
 +
            If dictionary.Exists(markValue) Then
 +
 +
                dictionary(markValue) = _
 +
                    CDbl(dictionary(markValue)) + volumeValue
 +
 +
            Else
 +
 +
                dictionary.Add markValue, volumeValue
 +
                rowIndexes.Add markValue, rowNumber
 +
 +
            End If
 +
 +
        End If
 +
 +
    Next rowNumber
 +
 +
    If dictionary.Count = 0 Then
 +
        Err.Raise vbObjectError + 4, , _
 +
            "В столбце «Марка» нет заполненных значений."
 +
    End If
 +
 +
    ' Формируем итоговый массив:
 +
    ' заголовок + одна строка на каждую уникальную марку
 +
    ReDim resultData( _
 +
        1 To dictionary.Count + 1, _
 +
        1 To lastColumn _
 +
    )
 +
 +
    ' Копируем заголовки
 +
    For columnNumber = 1 To lastColumn
 +
        resultData(1, columnNumber) = _
 +
            sourceData(1, columnNumber)
 +
    Next columnNumber
 +
 +
    resultRow = 2
 +
 +
    For Each dictionaryKey In dictionary.Keys
 +
 +
        rowNumber = CLng(rowIndexes(dictionaryKey))
 +
 +
        ' Берём остальные поля из первой строки марки
 +
        For columnNumber = 1 To lastColumn
 +
            resultData(resultRow, columnNumber) = _
 +
                sourceData(rowNumber, columnNumber)
 +
        Next columnNumber
 +
 +
        ' Записываем точную марку и объединённый объём
 +
        resultData(resultRow, markColumn) = _
 +
            CStr(dictionaryKey)
 +
 +
        resultData(resultRow, volumeColumn) = _
 +
            CDbl(dictionary(dictionaryKey))
 +
 +
        resultRow = resultRow + 1
 +
 +
    Next dictionaryKey
 +
 +
    ' Удаляем старый лист с результатом, если он есть
 +
    On Error Resume Next
 +
    ThisWorkbook.Worksheets(RESULT_SHEET_NAME).Delete
 +
    On Error GoTo ErrorHandler
 +
 +
    ' Создаём новый лист
 +
    Set resultSheet = ThisWorkbook.Worksheets.Add( _
 +
        After:=sourceSheet _
 +
    )
 +
 +
    resultSheet.Name = RESULT_SHEET_NAME
 +
 +
    ' Записываем результат
 +
    resultSheet.Range( _
 +
        resultSheet.Cells(1, 1), _
 +
        resultSheet.Cells(UBound(resultData, 1), lastColumn) _
 +
    ).Value = resultData
 +
 +
    ' Переносим ширину и формат столбцов
 +
    For columnNumber = 1 To lastColumn
 +
 +
        resultSheet.Columns(columnNumber).ColumnWidth = _
 +
            sourceSheet.Columns(columnNumber).ColumnWidth
 +
 +
        resultSheet.Columns(columnNumber).NumberFormat = _
 +
            sourceSheet.Columns(columnNumber).NumberFormat
 +
 +
    Next columnNumber
 +
 +
    ' Оформляем заголовок и фильтр
 +
    With resultSheet.Range( _
 +
        resultSheet.Cells(1, 1), _
 +
        resultSheet.Cells(1, lastColumn) _
 +
    )
 +
        .Font.Bold = True
 +
        .AutoFilter
 +
    End With
 +
 +
    resultSheet.Columns(markColumn).NumberFormat = "@"
 +
    resultSheet.Columns(volumeColumn).NumberFormat = "0.##"
 +
    resultSheet.Rows(1).AutoFit
 +
    resultSheet.Activate
 +
 +
    Application.DisplayAlerts = True
 +
    Application.EnableEvents = True
 +
    Application.ScreenUpdating = True
 +
 +
    MsgBox _
 +
        "Готово." & vbCrLf & _
 +
        "Исходных строк: " & Format$(lastRow - 1, "#,##0") & vbCrLf & _
 +
        "Уникальных марок: " & Format$(dictionary.Count, "#,##0") & vbCrLf & _
 +
        "Результат записан на лист «" & _
 +
        RESULT_SHEET_NAME & "».", _
 +
        vbInformation
 +
 +
    Exit Sub
 +
 +
ErrorHandler:
 +
 +
    Application.DisplayAlerts = True
 +
    Application.EnableEvents = True
 +
    Application.ScreenUpdating = True
 +
 +
    MsgBox _
 +
        "Не удалось обработать таблицу:" & vbCrLf & _
 +
        Err.Description, _
 +
        vbCritical
 +
 +
End Sub
 +
 +
 +
Private Function GetNumericVolume(ByVal cellValue As Variant) As Double
 +
 +
    Dim textValue As String
 +
 +
    If IsError(cellValue) Or IsEmpty(cellValue) Then
 +
        GetNumericVolume = 0
 +
        Exit Function
 +
    End If
 +
 +
    If IsNumeric(cellValue) Then
 +
        GetNumericVolume = CDbl(cellValue)
 +
        Exit Function
 +
    End If
 +
 +
    textValue = Trim$(CStr(cellValue))
 +
    textValue = Replace(textValue, Chr(160), "")
 +
    textValue = Replace(textValue, " ", "")
 +
    textValue = Replace(textValue, ".", _
 +
        Application.DecimalSeparator)
 +
    textValue = Replace(textValue, ",", _
 +
        Application.DecimalSeparator)
 +
 +
    If IsNumeric(textValue) Then
 +
        GetNumericVolume = CDbl(textValue)
 +
    Else
 +
        GetNumericVolume = 0
 +
    End If
 +
 +
End Function
 +
</pre>
 +
 +
Выгружаете список "Марки", затем:
 +
 +
1 - Сохраните файл как «Книга Excel с поддержкой макросов (*.xlsm)».
 +
 +
2 - Нажмите Alt + F11.
 +
 +
3 - Выберите Вставка → Модуль.
 +
 +
4 - Вставьте код макроса (выше).
 +
 +
5 - Вернитесь в Excel.
 +
 +
6 - Откройте исходный лист и нажмите Alt + F8.
 +
 +
7 - Запустите «СхлопнутьМаркиИСуммироватьОбъем».
 +
 +
Будет создан новый лист со "схлопнутыми" марками, где будут суммированные объёмы.
    
===Ошибка в актах списания из-за марок с низким регистром===
 
===Ошибка в актах списания из-за марок с низким регистром===