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


Option Explicit

' Константы Word для позднего связывания
Private Const wdAlignParagraphLeft = 0
Private Const wdAlignParagraphCenter = 1
Private Const wdAlignParagraphRight = 2
Private Const wdAlignParagraphJustify = 3
Private Const wdCellAlignVerticalTop = 0
Private Const wdCellAlignVerticalCenter = 1
Private Const wdCellAlignVerticalBottom = 2
Private Const wdLineStyleSingle = 1
Private Const wdLineStyleDotted = 2
Private Const wdLineStyleDashed = 3
Private Const wdLineStyleDotDash = 4
Private Const wdLineStyleDouble = 5
Private Const wdColorAutomatic = -16777216
Private Const wdUnderlineNone = 0

Sub ImportWordTableToActiveCell()
    ' Импорт выделенной в Word таблицы на текущий лист Excel,
    ' начиная с активной ячейки.
    ' Автоматически добавляет строки, если их недостаточно,
    ' и подгоняет высоту строк под содержимое.

    Dim wdApp As Object, wdDoc As Object
    Dim wdTable As Object
    Dim ws As Worksheet
    Dim startCell As Range
    Dim startRow As Long, startCol As Long
    Dim maxRows As Long, maxCols As Long
    Dim colWidths() As Single, rowHeights() As Single
    Dim cell As Object
    Dim r0 As Long, c0 As Long, rowSpan As Long, colSpan As Long
    Dim cellText As String
    Dim i As Long, j As Long, k As Long
    Dim sumWidth As Single, sumHeight As Single
    Const TOLERANCE As Single = 2

    ' --- Подключаемся к открытому Word ---
    On Error Resume Next
    Set wdApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then
        MsgBox "Word не запущен. Откройте Word с нужным документом и таблицей.", vbExclamation
        Exit Sub
    End If
    On Error GoTo 0

    Set wdDoc = wdApp.ActiveDocument
    If wdDoc Is Nothing Then
        MsgBox "Нет активного документа Word.", vbExclamation
        Exit Sub
    End If

    ' Проверяем, что курсор внутри таблицы
    If Not wdApp.Selection.Information(12) Then ' wdWithInTable
        MsgBox "Выделите таблицу или установите курсор внутрь неё в Word.", vbExclamation
        Exit Sub
    End If
    Set wdTable = wdApp.Selection.Tables(1)

    ' --- Текущий лист и активная ячейка ---
    Set ws = ActiveSheet
    Set startCell = ActiveCell
    If startCell Is Nothing Then
        MsgBox "Выделите ячейку на листе Excel, с которой начнётся вставка.", vbExclamation
        Exit Sub
    End If
    startRow = startCell.Row
    startCol = startCell.Column

    maxRows = wdTable.Rows.Count
    maxCols = wdTable.Columns.Count
    If maxRows = 0 Or maxCols = 0 Then Exit Sub

    ' --- Добавляем строки и столбцы, если не хватает ---
    Dim needRows As Long, needCols As Long
    needRows = startRow + maxRows - 1
    needCols = startCol + maxCols - 1
    If needRows > ws.Rows.Count Then
        ws.Rows(ws.Rows.Count).Resize(needRows - ws.Rows.Count).Insert Shift:=xlDown
    End If
    If needCols > ws.Columns.Count Then
        ' Обычно столбцов хватает, но на всякий случай
        ws.Columns(ws.Columns.Count).Resize(, needCols - ws.Columns.Count).Insert Shift:=xlToRight
    End If

    ' Запоминаем ширины столбцов и высоты строк Word
    ReDim colWidths(1 To maxCols)
    For j = 1 To maxCols
        colWidths(j) = wdTable.Columns(j).Width
    Next j
    ReDim rowHeights(1 To maxRows)
    For i = 1 To maxRows
        rowHeights(i) = wdTable.Rows(i).Height
    Next i

    Application.ScreenUpdating = False

    ' --- Перенос ячеек с учётом смещения startRow, startCol ---
    For Each cell In wdTable.Range.Cells
        r0 = cell.RowIndex
        c0 = cell.ColumnIndex

        ' Горизонтальное объединение
        sumWidth = 0
        colSpan = 0
        For k = c0 To maxCols
            sumWidth = sumWidth + colWidths(k)
            If sumWidth >= cell.Width - TOLERANCE Then
                colSpan = k - c0 + 1
                Exit For
            End If
        Next k
        If colSpan = 0 Then colSpan = 1

        ' Вертикальное объединение
        sumHeight = 0
        rowSpan = 0
        For k = r0 To maxRows
            sumHeight = sumHeight + rowHeights(k)
            If sumHeight >= cell.Height - TOLERANCE Then
                rowSpan = k - r0 + 1
                Exit For
            End If
        Next k
        If rowSpan = 0 Then rowSpan = 1

        ' Чистый текст (убираем символ конца ячейки)
        cellText = cell.Range.Text
        If Len(cellText) >= 2 Then
            cellText = Left(cellText, Len(cellText) - 2)
        End If

        ' Адрес в Excel с учётом смещения
        Dim exRange As Range
        Set exRange = ws.Range( _
            ws.Cells(startRow + r0 - 1, startCol + c0 - 1), _
            ws.Cells(startRow + r0 - 1 + rowSpan - 1, startCol + c0 - 1 + colSpan - 1))

        With exRange
            .Merge
            .Value = cellText

            ' Шрифт
            .Font.Name = cell.Range.Font.Name
            .Font.Size = cell.Range.Font.Size
            .Font.Bold = cell.Range.Font.Bold
            .Font.Italic = cell.Range.Font.Italic
            .Font.Underline = (cell.Range.Font.Underline <> wdUnderlineNone)
            If cell.Range.Font.Color <> wdColorAutomatic Then
                .Font.Color = cell.Range.Font.Color
            End If

            ' Выравнивание
            Select Case cell.Range.ParagraphFormat.Alignment
                Case wdAlignParagraphCenter: .HorizontalAlignment = xlHAlignCenter
                Case wdAlignParagraphRight:  .HorizontalAlignment = xlHAlignRight
                Case wdAlignParagraphJustify: .HorizontalAlignment = xlHAlignJustify
                Case Else: .HorizontalAlignment = xlHAlignLeft
            End Select

            Select Case cell.VerticalAlignment
                Case wdCellAlignVerticalCenter: .VerticalAlignment = xlVAlignCenter
                Case wdCellAlignVerticalBottom: .VerticalAlignment = xlVAlignBottom
                Case Else: .VerticalAlignment = xlVAlignTop
            End Select

            .WrapText = True

            ' Заливка
            On Error Resume Next
            If cell.Shading.BackgroundPatternColor <> wdColorAutomatic And _
               cell.Shading.BackgroundPatternColor <> 16777215 Then
                .Interior.Color = cell.Shading.BackgroundPatternColor
            End If
            On Error GoTo 0

            ' Границы
            ApplyBorders cell, .Cells
        End With
    Next cell

    ' Ширина столбцов (пропорционально Word)
    For j = 1 To maxCols
        ws.Columns(startCol + j - 1).ColumnWidth = colWidths(j) * 0.7
    Next j

    ' АВТОПОДБОР ВЫСОТЫ СТРОК ПОД СОДЕРЖИМОЕ
    ws.Rows(startRow & ":" & startRow + maxRows - 1).AutoFit

    Application.ScreenUpdating = True
    MsgBox "Таблица вставлена, начиная с ячейки " & startCell.Address(False, False) & ".", vbInformation
End Sub

' Перенос границ
Private Sub ApplyBorders(wdCell As Object, exRange As Range)
    Dim wdBorder As Object
    Dim wdStyle As Long
    Dim exLineStyle As XlLineStyle
    Dim exWeight As XlBorderWeight
    Dim exColor As Long

    On Error Resume Next
    Set wdBorder = wdCell.Borders(2) ' wdBorderLeft
    If Not wdBorder Is Nothing Then
        wdStyle = wdBorder.LineStyle
        If wdStyle = 0 Then
            exRange.Borders.LineStyle = xlNone
        Else
            exLineStyle = ConvertLineStyle(wdStyle)
            exWeight = ConvertWeight(wdBorder.LineWidth)
            exColor = wdBorder.Color
            With exRange.Borders
                .LineStyle = exLineStyle
                .Weight = exWeight
                .Color = exColor
            End With
        End If
    End If
    On Error GoTo 0
End Sub

Private Function ConvertLineStyle(wdStyle As Long) As XlLineStyle
    Select Case wdStyle
        Case wdLineStyleSingle: ConvertLineStyle = xlContinuous
        Case wdLineStyleDotted: ConvertLineStyle = xlDot
        Case wdLineStyleDashed, wdLineStyleDotDash: ConvertLineStyle = xlDash
        Case wdLineStyleDouble: ConvertLineStyle = xlDouble
        Case Else: ConvertLineStyle = xlNone
    End Select
End Function

Private Function ConvertWeight(widthPt As Single) As XlBorderWeight
    If widthPt <= 1 Then
        ConvertWeight = xlThin
    ElseIf widthPt <= 2 Then
        ConvertWeight = xlMedium
    Else
        ConvertWeight = xlThick
    End If
End Function