Загрузка данных
' ===== В САМОМ ВЕРХУ МОДУЛЯ (Personal.xlsb) =====
Private SavedRow As Long
Private SavedCol As Long
Private SavedNumLines As Long
Private SavedOldData As Variant
' =================================================
Sub ВставитьСписокИзWordСНумерацией()
On Error GoTo ErrorHandler
Dim dataObj As Object, clipText As String
Dim ws As Worksheet
Dim rngBefore As Range
Dim multiPart As Boolean
Dim cell2Text As String, cell3Text As String
Dim colLines As Collection
Dim i As Long, numLines As Long
Dim lineText As String, numPart As String, textPart As String
Dim dotPos As Long
' 1. Читаем буфер обмена
Set dataObj = Nothing
On Error Resume Next
Set dataObj = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
If Err.Number <> 0 Then
Err.Clear
Set dataObj = CreateObject("MSForms.DataObject")
End If
On Error GoTo ErrorHandler
If dataObj Is Nothing Then
MsgBox "Не удалось получить доступ к буферу обмена.", vbExclamation
Exit Sub
End If
dataObj.GetFromClipboard
' Принудительно превращаем возможный Null в пустую строку
clipText = dataObj.GetText & ""
' Очищаем от невидимых символов
clipText = CleanString(clipText)
If Len(Trim(clipText)) = 0 Then
MsgBox "Буфер обмена пуст или содержит не текст.", vbInformation
Exit Sub
End If
' 2. Проверяем, есть ли табуляции (несколько ячеек)
multiPart = (InStr(clipText, vbTab) > 0)
cell2Text = ""
cell3Text = ""
If multiPart Then
Dim tableRows As Variant, rowText As String
tableRows = Split(clipText, vbCrLf)
If UBound(tableRows) < 0 Then tableRows = Split(clipText, vbLf)
rowText = ""
For i = 0 To UBound(tableRows)
Dim tmpRow As String
tmpRow = CleanString(CStr(tableRows(i)))
If Len(Trim(tmpRow)) > 0 Then
rowText = tableRows(i) ' берём исходную, но уже очищенную
Exit For
End If
Next i
If rowText <> "" Then
Dim parts As Variant
parts = Split(rowText, vbTab)
If UBound(parts) >= 2 Then
cell2Text = CleanString(parts(1))
If UBound(parts) >= 3 Then
cell3Text = CleanString(parts(2))
End If
' Первая часть будет обрабатываться дальше
clipText = parts(0)
End If
End If
End If
' 3. Собираем непустые строки в коллекцию
Set colLines = New Collection
Dim rawLines As Variant, singleLine As Variant
rawLines = Split(clipText, vbCrLf)
If UBound(rawLines) < 0 Then rawLines = Split(clipText, vbLf)
For Each singleLine In rawLines
lineText = CleanString(CStr(singleLine))
If Len(Trim(lineText)) > 0 Then
colLines.Add lineText
End If
Next singleLine
If colLines.Count = 0 Then
MsgBox "Не найдено ни одной строки текста.", vbInformation
Exit Sub
End If
numLines = colLines.Count
' 4. Сохраняем состояние ячеек
Set ws = ActiveSheet
SavedRow = ActiveCell.Row
SavedCol = ActiveCell.Column
SavedNumLines = numLines
Set rngBefore = ws.Range(ws.Cells(SavedRow, SavedCol), ws.Cells(SavedRow + numLines - 1, SavedCol + 1))
If Not rngBefore Is Nothing Then
SavedOldData = rngBefore.Value
Else
SavedOldData = Empty
End If
' 5. Вставляем строки и заполняем
Application.ScreenUpdating = False
ws.Rows(SavedRow & ":" & SavedRow + numLines - 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
For i = 1 To numLines
lineText = colLines(i)
dotPos = InStr(lineText, ". ")
If dotPos > 0 And IsNumeric(Left(lineText, dotPos - 1)) Then
numPart = Left(lineText, dotPos + 1) ' "1. "
textPart = Trim(Mid(lineText, dotPos + 2))
Else
numPart = ""
textPart = lineText
End If
With ws.Cells(SavedRow + i - 1, SavedCol)
.Value = numPart
.Font.Bold = False
.HorizontalAlignment = xlRight
End With
With ws.Cells(SavedRow + i - 1, SavedCol + 1)
.Value = textPart
.Font.Bold = False
End With
If multiPart Then
ws.Cells(SavedRow + i - 1, 5).Value = cell2Text ' E
ws.Cells(SavedRow + i - 1, 5).Font.Bold = False
ws.Cells(SavedRow + i - 1, 6).Value = cell3Text ' F
ws.Cells(SavedRow + i - 1, 6).Font.Bold = False
End If
Next i
' 6. Автоподбор высоты
ws.Rows(SavedRow & ":" & SavedRow + numLines - 1).EntireRow.AutoFit
' 7. Удаление строк до объединённой ячейки в C/D
Dim lastInsertedRow As Long, nextMergedRow As Long, r As Long
lastInsertedRow = SavedRow + numLines - 1
nextMergedRow = 0
For r = lastInsertedRow + 1 To lastInsertedRow + 1000
If ws.Cells(r, 3).MergeCells Or ws.Cells(r, 4).MergeCells Then
If ws.Cells(r, 3).MergeCells Then
nextMergedRow = ws.Cells(r, 3).MergeArea.Row
Else
nextMergedRow = ws.Cells(r, 4).MergeArea.Row
End If
Exit For
End If
Next r
If nextMergedRow > 0 Then
Dim firstRowToDelete As Long, lastRowToDelete As Long
firstRowToDelete = lastInsertedRow + 1
lastRowToDelete = nextMergedRow - 1
If lastRowToDelete >= firstRowToDelete Then
ws.Rows(firstRowToDelete & ":" & lastRowToDelete).Delete Shift:=xlUp
End If
End If
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "Ошибка " & Err.Number & ": " & Err.Description & vbCrLf & _
"Процедура: ВставитьСписокИзWordСНумерацией", vbCritical, "Ошибка в макросе"
End Sub
' Вспомогательная функция очистки строки
Private Function CleanString(ByVal txt As String) As String
txt = txt & "" ' гарантируем строку
txt = Replace(txt, Chr(160), " ")
Dim i As Long
For i = 1 To 31
If i <> 9 And i <> 10 And i <> 13 Then
txt = Replace(txt, Chr(i), "")
End If
Next i
CleanString = txt
End Function
Sub ОтменитьПоследнююВставкуСписка()
On Error GoTo CancelError
If SavedNumLines <= 0 Then
MsgBox "Нет данных для отмены последней вставки.", vbInformation
Exit Sub
End If
Dim ws As Worksheet
Set ws = ActiveSheet
Application.ScreenUpdating = False
ws.Rows(SavedRow & ":" & SavedRow + SavedNumLines - 1).Delete Shift:=xlUp
If Not IsEmpty(SavedOldData) Then
Dim rngRestore As Range
Set rngRestore = ws.Range(ws.Cells(SavedRow, SavedCol), ws.Cells(SavedRow + SavedNumLines - 1, SavedCol + 1))
rngRestore.Value = SavedOldData
End If
SavedNumLines = 0
SavedOldData = Empty
Application.ScreenUpdating = True
Exit Sub
CancelError:
Application.ScreenUpdating = True
MsgBox "Ошибка при отмене: " & Err.Description, vbExclamation
End Sub