Загрузка данных


Sub ВставитьСписокИДопДанные()
    ' Единая запись отмены
    Dim undoRec As UndoRecord
    Set undoRec = Application.UndoRecord
    undoRec.StartCustomRecord "Вставить список и доп. данные"
    
    Dim startPos As Long
    Dim i As Long
    Dim para As Paragraph
    Dim colParasMain As Collection    ' для основных строк (из D)
    Dim arrB As Variant               ' массив доп. данных (из B)
    Dim rngFirst As Range
    
    ' Запоминаем позицию курсора до вставки
    startPos = Selection.Start

    ' 1. Вставка текста из буфера
    On Error Resume Next
    Selection.PasteSpecial Link:=False, _
                           DataType:=wdPasteText, _
                           Placement:=wdInLine, _
                           DisplayAsIcon:=False
    If Err.Number <> 0 Then
        MsgBox "Не удалось вставить текст. Проверьте, скопированы ли данные.", vbExclamation
        undoRec.EndCustomRecord
        Exit Sub
    End If
    On Error GoTo 0

    ' 2. Выделяем весь вставленный текст
    Selection.SetRange Start:=startPos, End:=Selection.End

    ' 3. Очистка форматирования
    Selection.ClearFormatting
    Selection.ParagraphFormat.Reset
    With Selection.ParagraphFormat
        .SpaceBefore = 0
        .SpaceAfter = 0
        .LineSpacingRule = wdLineSpaceSingle
        .FirstLineIndent = 0
        .LeftIndent = 0
        .RightIndent = 0
    End With

    ' 4. Шрифт Times New Roman 11
    With Selection.Font
        .Name = "Times New Roman"
        .Size = 11
    End With

    ' 5. Первая буква каждого слова — заглавная
    Selection.Range.Case = wdTitleWord

    ' 6. Сбор непустых абзацев и разделение на основной и доп. данные
    Set colParasMain = New Collection
    ReDim arrB(1 To Selection.Range.Paragraphs.Count) ' максимум
    Dim countB As Long
    countB = 0
    
    For Each para In Selection.Range.Paragraphs
        If Len(para.Range.Text) > 1 Then ' непустой абзац (содержит не только маркер)
            Dim fullText As String
            fullText = para.Range.Text
            ' Убираем конечный маркер абзаца (символ возврата каретки)
            If Right(fullText, 1) = vbCr Then
                fullText = Left(fullText, Len(fullText) - 1)
            End If
            
            ' Разделяем по табуляции
            Dim parts As Variant
            parts = Split(fullText, vbTab)
            
            Dim mainText As String
            Dim extraText As String
            mainText = parts(0)
            If UBound(parts) >= 1 Then
                extraText = Trim(parts(1))
            Else
                extraText = ""
            End If
            
            ' Добавляем основной текст в коллекцию
            colParasMain.Add mainText & vbCr ' добавляем маркер обратно для InsertBefore
            
            ' Сохраняем доп. данные (если не пусто)
            If Len(extraText) > 0 Then
                countB = countB + 1
                arrB(countB) = extraText
            End If
        End If
    Next para

    If colParasMain.Count = 0 Then
        MsgBox "Не найдено ни одной строки основного текста.", vbInformation
        Selection.Collapse Direction:=wdCollapseEnd
        undoRec.EndCustomRecord
        Exit Sub
    End If

    ' 7. Нумерация основных строк (поверх существующего текста)
    i = 1
    Dim paraMain As Variant
    For Each paraMain In colParasMain
        ' paraMain — это строка, вставленная в абзац. Мы будем вставлять номер перед ней
        ' Но у нас сейчас выделен весь текст, нам нужно работать с абзацами
        ' Лучше заново перебрать абзацы выделенного текста, сохранив ссылки
    Next paraMain
    
    ' Альтернативный способ: т.к. мы уже имеем коллекцию colParasMain строк,
    ' мы можем просто заменить текст в каждом непустом абзаце нумерованным.
    ' Очистим выделенный текст и вставим заново с номерами.
    Selection.Delete ' удаляем вставленный текст, будем вставлять оформленный список
    
    ' Вставляем оформленный список из colParasMain
    Dim numberedLines As String
    numberedLines = ""
    i = 1
    Dim lineText As Variant
    For Each lineText In colParasMain
        ' убираем маркер vbCr, который мы добавляли, чтобы вставить номер
        Dim cleanLine As String
        cleanLine = Left(lineText, Len(lineText) - 1)
        numberedLines = numberedLines & i & ". " & cleanLine & vbCrLf
        i = i + 1
    Next lineText
    
    ' Убираем последний лишний перенос строки
    If Len(numberedLines) > 0 Then
        numberedLines = Left(numberedLines, Len(numberedLines) - 1)
    End If
    
    Selection.TypeText Text:=numberedLines
    
    ' Теперь выделяем вставленный нумерованный список
    Selection.SetRange Start:=startPos, End:=Selection.End
    
    ' Применяем заглавные буквы ко всему тексту (уже было, но после новой вставки нужно заново)
    Selection.Range.Case = wdTitleWord
    
    ' Шрифт и абзац уже были применены, но после удаления/вставки сбросились, применим снова
    Selection.ClearFormatting
    Selection.ParagraphFormat.Reset
    With Selection.ParagraphFormat
        .SpaceBefore = 0
        .SpaceAfter = 0
        .LineSpacingRule = wdLineSpaceSingle
    End With
    With Selection.Font
        .Name = "Times New Roman"
        .Size = 11
    End With
    
    ' 8. Добавляем пустые строки сверху и снизу
    ' Сначала сверху
    Selection.HomeKey Unit:=wdLine
    Selection.InsertParagraphBefore
    ' Снизу
    Selection.EndKey Unit:=wdLine
    Selection.TypeParagraph
    
    ' Очищаем форматирование пустых строк
    Selection.ClearFormatting
    Selection.ParagraphFormat.Reset
    With Selection.ParagraphFormat
        .SpaceBefore = 0
        .SpaceAfter = 0
        .LineSpacingRule = wdLineSpaceSingle
    End With
    
    ' 9. Обработка доп. данных из столбца B
    If countB > 0 Then
        Dim firstB As String, lastB As String
        firstB = arrB(1)
        lastB = arrB(countB)
        
        Dim digits1 As String, digits2 As String
        digits1 = ExtractLast8Digits(firstB)
        digits2 = ExtractLast8Digits(lastB)
        
        Dim resultB As String
        resultB = digits1 & "-" & digits2
        
        ' Определяем, находимся ли мы в таблице
        If Selection.Information(wdWithInTable) Then
            ' Переходим в соседнюю ячейку справа
            Selection.MoveRight Unit:=wdCell
            ' Вставляем результат
            Selection.TypeText Text:=resultB
            ' Форматируем
            With Selection.Font
                .Name = "Times New Roman"
                .Size = 11
                .Bold = False
            End With
        Else
            ' Не в таблице – вставляем через табуляцию на той же строке
            Selection.TypeParagraph
            Selection.TypeText Text:=resultB
            With Selection.Font
                .Name = "Times New Roman"
                .Size = 11
                .Bold = False
            End With
        End If
    End If
    
    ' 10. Завершаем отмену
    undoRec.EndCustomRecord
End Sub

' Функция извлечения последних 8 цифр из строки
Private Function ExtractLast8Digits(txt As String) As String
    Dim digits As String
    digits = ""
    Dim i As Long
    For i = Len(txt) To 1 Step -1
        If Mid(txt, i, 1) Like "#" Then
            digits = Mid(txt, i, 1) & digits
            If Len(digits) >= 8 Then Exit For
        End If
    Next i
    ExtractLast8Digits = digits
End Function