Загрузка данных
Private SavedRow As Long
Private SavedCol As Long
Private SavedNumLines As Long
Sub ВставитьСписокИзWordСНумерацией()
Dim dataObj As Object, clipText As String, linesArr As Variant
Dim i As Long, lineText As String, numPart As String, textPart As String
Dim dotPos As Long, numLines As Long, ws As Worksheet, firstField As String
Dim lastE As String, lastF As String
On Error Resume Next
Set dataObj = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
If Err.Number <> 0 Then
On Error GoTo 0
Set dataObj = CreateObject("MSForms.DataObject")
End If
On Error GoTo 0
If dataObj Is Nothing Then
MsgBox "Не удалось получить доступ к буферу обмена.", vbExclamation
Exit Sub
End If
dataObj.GetFromClipboard
clipText = dataObj.GetText
If Len(Trim(clipText)) = 0 Then
MsgBox "Буфер обмена пуст или содержит не текст.", vbInformation
Exit Sub
End If
Dim rawLines As Variant, col As New Collection, rawLine As Variant
rawLines = Split(clipText, vbCrLf)
If UBound(rawLines) < 0 Then rawLines = Split(clipText, vbLf)
For Each rawLine In rawLines
If Len(Trim(CStr(rawLine))) > 0 Then col.Add CStr(rawLine)
Next rawLine
If col.Count = 0 Then
MsgBox "Не найдено ни одной строки текста.", vbInformation
Exit Sub
End If
ReDim linesArr(0 To col.Count - 1)
For i = 0 To col.Count - 1: linesArr(i) = col(i + 1): Next i
numLines = col.Count
Set ws = ActiveSheet
SavedRow = ActiveCell.Row
SavedCol = ActiveCell.Column
SavedNumLines = numLines
Application.ScreenUpdating = False
ws.Rows(SavedRow + 1 & ":" & SavedRow + numLines).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
firstField = "": lastE = "": lastF = ""
For i = 0 To numLines - 1
lineText = linesArr(i)
If Len(lineText) = 0 Then GoTo NextLine
Dim parts As Variant, v0 As Variant, v1 As Variant, v2 As Variant
parts = Split(lineText, vbTab)
v0 = parts(0)
If UBound(parts) >= 1 Then v1 = parts(1) Else v1 = Empty
If UBound(parts) >= 2 Then v2 = parts(2) Else v2 = Empty
Dim field1 As String, field2 As String, field3 As String
field1 = SafeString(v0): field2 = SafeString(v1): field3 = SafeString(v2)
If Len(field2) > 0 Then lastE = field2
If Len(field3) > 0 Then lastF = field3
If i = 0 Then firstField = field1
numPart = "": textPart = ""
If Len(field1) > 0 Then
On Error Resume Next
dotPos = InStr(field1, ". ")
If dotPos > 0 And IsNumeric(Left(field1, dotPos - 1)) Then
numPart = Left(field1, dotPos + 1)
textPart = Trim(Mid(field1, dotPos + 2))
Else
textPart = field1
End If
If Err.Number <> 0 Then numPart = "": textPart = field1: Err.Clear
On Error GoTo 0
End If
With ws.Cells(SavedRow + i, SavedCol): .Value = numPart: .Font.Bold = False: .HorizontalAlignment = xlRight: End With
With ws.Cells(SavedRow + i, SavedCol + 1): .Value = textPart: .Font.Bold = False: End With
With ws.Cells(SavedRow + i, SavedCol + 2): .Value = field2: .Font.Bold = False: End With
With ws.Cells(SavedRow + i, SavedCol + 3): .Value = field3: .Font.Bold = False: End With
NextLine:
Next i
ws.Rows(SavedRow & ":" & SavedRow + numLines - 1).EntireRow.AutoFit
Dim lastRow As Long, j As Long
lastRow = SavedRow + numLines - 1
For j = lastRow To SavedRow + 1 Step -1
If WorksheetFunction.CountA(ws.Rows(j)) = 0 Then
ws.Rows(j).Delete Shift:=xlUp
numLines = numLines - 1
End If
Next j
lastRow = SavedRow + numLines - 1
If numLines > 0 Then
Dim rngFirstCD As Range
Set rngFirstCD = ws.Range(ws.Cells(SavedRow, SavedCol), ws.Cells(SavedRow, SavedCol + 1))
If rngFirstCD.MergeCells Then rngFirstCD.UnMerge
rngFirstCD.Merge
rngFirstCD.Value = firstField
rngFirstCD.Font.Bold = False
rngFirstCD.HorizontalAlignment = xlLeft
rngFirstCD.WrapText = True
If Len(firstField) >= 4 Then
rngFirstCD.Characters(1, 4).Font.Bold = True
ElseIf Len(firstField) > 0 Then
rngFirstCD.Characters(1, Len(firstField)).Font.Bold = True
End If
End If
If numLines > 0 Then
Dim rngE As Range, rngF As Range
Set rngE = ws.Range(ws.Cells(SavedRow, SavedCol + 2), ws.Cells(lastRow, SavedCol + 2))
Set rngF = ws.Range(ws.Cells(SavedRow, SavedCol + 3), ws.Cells(lastRow, SavedCol + 3))
If Not HasAnyFormula(rngE) Then
If rngE.MergeCells Then rngE.UnMerge
rngE.ClearContents: rngE.Merge
If Len(lastE) > 0 Then rngE(1).Value = lastE: rngE(1).Font.Bold = False
End If
If Not HasAnyFormula(rngF) Then
If rngF.MergeCells Then rngF.UnMerge
rngF.ClearContents: rngF.Merge
If Len(lastF) > 0 Then rngF(1).Value = lastF: rngF(1).Font.Bold = False
End If
End If
If numLines > 0 Then
Dim maxCol As Long, colIdx As Long
On Error Resume Next
maxCol = ws.Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
If Err.Number <> 0 Then maxCol = 8
On Error GoTo 0
If maxCol < 8 Then maxCol = 8
For colIdx = 1 To maxCol
If colIdx = 3 Or colIdx = 4 Then GoTo ContinueCol
Dim rngCol As Range
Set rngCol = ws.Range(ws.Cells(SavedRow, colIdx), ws.Cells(lastRow, colIdx))
If Application.CountA(rngCol) = 0 And Not HasAnyFormula(rngCol) Then GoTo ContinueCol
If HasAnyFormula(rngCol) Then
If rngCol.MergeCells Then rngCol.UnMerge
rngCol.Merge
rngCol.HorizontalAlignment = xlLeft: rngCol.VerticalAlignment = xlTop
GoTo ContinueCol
End If
If rngCol.MergeCells Then rngCol.UnMerge
Dim lastVal As String, rSearch As Long, cellVal As Variant
lastVal = ""
For rSearch = lastRow To SavedRow Step -1
cellVal = ws.Cells(rSearch, colIdx).Value
If Not IsEmpty(cellVal) Then
Dim cleanVal As String: cleanVal = Trim(CStr(cellVal))
If Len(cleanVal) > 0 Then lastVal = cleanVal: Exit For
End If
Next rSearch
rngCol.ClearContents: rngCol.Merge
If Len(lastVal) > 0 Then rngCol(1).Value = lastVal: rngCol(1).Font.Bold = False
ContinueCol:
Next colIdx
End If
If numLines > 0 Then
Dim rngH As Range, hValue As Variant
Set rngH = ws.Range(ws.Cells(SavedRow, 8), ws.Cells(lastRow, 8))
If Not rngH.MergeCells And rngH.Count > 1 Then rngH.Merge
hValue = Trim(CStr(ws.Cells(SavedRow, 8).Value))
If hValue = "-" Then rngH.HorizontalAlignment = xlCenter Else rngH.HorizontalAlignment = xlLeft
rngH.VerticalAlignment = xlTop
End If
If numLines > 1 And WorksheetFunction.CountA(ws.Rows(SavedRow + numLines - 1)) = 0 Then
ws.Rows(SavedRow + numLines - 1).Delete Shift:=xlUp
numLines = numLines - 1
lastRow = lastRow - 1
End If
Dim r As Long, maxRow As Long
maxRow = ws.Rows.Count
r = lastRow + 1
Do While r <= maxRow
If RowHasAnyFormula(ws.Rows(r)) Then Exit Do
If ws.Cells(r, 3).MergeCells Or ws.Cells(r, 4).MergeCells Then Exit Do
ws.Rows(r).Delete Shift:=xlUp
maxRow = ws.Rows.Count
Loop
If numLines > 0 Then
Dim tmpSheet As Worksheet, tmpCell As Range
Set tmpSheet = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
Set tmpCell = tmpSheet.Range("A1")
tmpCell.Value = firstField
tmpCell.Font.Name = "Times New Roman": tmpCell.Font.Size = 11
tmpCell.WrapText = True
tmpCell.ColumnWidth = ws.Range("C1").ColumnWidth + ws.Range("D1").ColumnWidth
tmpCell.EntireRow.AutoFit
ws.Rows(SavedRow).RowHeight = tmpCell.RowHeight
Application.DisplayAlerts = False
tmpSheet.Delete
Application.DisplayAlerts = True
End If
Application.ScreenUpdating = True
End Sub
Private Function HasAnyFormula(rng As Range) As Boolean
Dim cell As Range
For Each cell In rng.Cells
If cell.HasFormula Then HasAnyFormula = True: Exit Function
Next cell
HasAnyFormula = False
End Function
Private Function RowHasAnyFormula(rng As Range) As Boolean
Dim cell As Range
For Each cell In rng.Columns
If cell.HasFormula Then RowHasAnyFormula = True: Exit Function
Next cell
RowHasAnyFormula = False
End Function
Private Function SafeString(v As Variant) As String
If IsNull(v) Or IsError(v) Then SafeString = "" Else SafeString = Trim(CStr(v))
End Function