Автоподбор высоты объединенных ячеек в excel vba

Автоподбор высоты объединенной ячейки с помощью кода VBA Excel, когда метод AutoFit не работает. Обработка ячеек по списку адресов из массива.

Автоподбор высоты ячейки

К сожалению, в объединенных ячейках метод VBA Excel AutoFit не работает. Но есть возможность подогнать ширину или высоту такой ячейки под длину текста с помощью макроса.

Здесь мы рассмотрим макрос для автоподбора высоты ячейки, объединенной с другими по горизонтали в одной строке, которые обычно используются в заголовках электронных таблиц Excel. Для объединенной ячейки должен быть задан перенос текста по словам: Формат ячеек >> Выравнивание >> переносить текст.

Высота ячейки будет такой, чтобы уместились все строки, на которые будет разбит контент в зависимости от ширины объединенной ячейки.

Для решения задачи по автоподбору высоты необходимо с помощью кода VBA определить:

  1. Длину текста (количество символов) в объединенной ячейке.
  2. Ширину объединенной ячейки. Длина одного символа текста со шрифтом и его размером по умолчанию приблизительно соответствует длине символа, в котором измеряется ширина ячейки.
  3. Размер шрифта, чтобы рассчитать коэффициент, увеличивающий или уменьшающий высоту ячейки в зависимости от его (шрифта) размера.

Макрос VBA Excel для автоподбора высоты ячейки с учетом размера используемого шрифта:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Sub PodborVysoty()

Dim myCell As Range, myLen As Integer, _

myWidth As Single, k As Single, n As Single

    With Selection

        ‘Задаем объединенной ячейке перенос текста

        .WrapText = True

        ‘Задаем объединенной ячейке такую высоту строки,

        ‘чтобы умещалась одна строка текста

        .RowHeight = ActiveCell.Font.Size * 1.3

    End With

myLen = Len(CStr(ActiveCell))

    For Each myCell In Selection

        myWidth = myWidth + myCell.ColumnWidth

    Next

n = 10

k = ActiveCell.Font.Size / n

Selection.RowHeight = Selection.RowHeight * _

WorksheetFunction.RoundUp(myLen * k / myWidth, 0)

End Sub

Переменные:

  • myCell — отдельная ячейка в объединенной;
  • myLen — длина текста в активной ячейке;
  • myWidth — ширина объединенной ячейки;
  • k — коэффициент, вносящий поправку в зависимости от размера шрифта;
  • n — размер шрифта по умолчанию.*

* Это не точное значение: у меня по умолчанию установлен шрифт Calibri размером 11, но точнее код работает с n = 10. Значение переменной n подбирается опытным путем, так как длина текста зависит от процентного соотношения широких и узких символов, если шрифт не моноширинный. Переменной n можно присваивать и дробные значения для более точного автоподбора высоты.

Максимальная высота строки — 409,5. Если расчетная высота объединенной ячейки окажется больше, будет сгенерирована ошибка.

Данный код VBA Excel работает с выделенной ячейкой. Вы можете задать список адресов объединенных ячеек и пройтись макросом по каждой из них.

Обработка списка ячеек

Укажите список объединенных ячеек в качестве аргументов функции Array. Для списка используйте адреса только первых ячеек из состава объединенных.

Sub ObkhodYacheyek1()

Sub ObkhodYacheyek()

Dim myCell() As Variant, myElem As Variant

myCell = Array(«A1», «A3», «A5»)

    For Each myElem In myCell

        Range(myElem).Select

        Call PodborVysoty

    Next

End Sub

Переменные:

  • myCell — массив со списком адресов объединенных ячеек;
  • myElem — используется как элемент массива myCell.

Макрос ObkhodYacheyek по адресам из списка обращается к каждой ячейке по очереди, выделяет ее и запускает код автоподбора высоты PodborVysoty.

Если выделить диапазон объединенных ячеек по одной, удерживая клавишу Ctrl, то запустить код автоподбора высоты можно с помощью следующего макроса:

Sub ObkhodYacheyek2()

Dim myCell() As String, myElem As Variant

myCell = Split(Selection.Address, «,»)

    For Each myElem In myCell

        Range(myElem).Select

        Call PodborVysoty

    Next

End Sub


Хитрости »

10 Август 2016              35691 просмотров


Подбор высоты строки/ширины столбца объединенной ячейки

Для начала немного теории. Если в ячейках листа Excel записан некий длинный текст, то обычно устанавливают перенос на строки(вкладка Главная -группа ВыравниваниеПеренос текста), чтобы текст не растягивался на весь экран, а умещался в ячейке. При этом высота ячейки тоже должна измениться, чтобы отобразить все содержимое. Если речь идет всего об одной простой ячейке — проблем не возникает. Обычно, чтобы установить высоту строки на основании содержимого ячейки, достаточно навести курсор мыши в заголовке строк на границу строки(курсор приобретет вид направленных в разные стороны стрелок — Стрелки) и дважды быстро щелкнуть левой кнопкой мыши. Тоже самое можно сделать и для ширины столбцов.
Но с объединенными ячейками такой фокус не прокатывает — ширина и высота для этих ячеек так не подбирается, сколько ни щелкай и приходится вручную подгонять каждую, чтобы текст ячейки отображался полностью:
Текст в объединенных ячейках
Стандартными средствами такой автоподбор не сделать, но вот при помощи VBA — без проблем. Ниже приведена функция, которая поможет подобрать высоту и ширину объединенных ячеек на основании их содержимого.

'---------------------------------------------------------------------------------------
' Procedure : RowHeightForContent
' Author    : The_Prist(Щербаков Дмитрий)
'             http://www.excel-vba.ru
' Purpose   : Функция подбирает высоту строки/ширину столбца объединенных ячеек по содержимому
'---------------------------------------------------------------------------------------
Function RowColHeightForContent(rc As Range, Optional bRowHeight As Boolean = True)
'rc -         ячейка, высоту строки или ширину столбца которой необходимо подобрать
'bRowHeight - True - если необходимо подобрать высоту строки
'             False - если необходимо подобрать ширину столбца
    Dim OldR_Height As Single, OldC_Widht As Single
    Dim MergedR_Height As Single, MergedC_Widht As Single
    Dim CurrCell As Range
    Dim ih As Integer
    Dim iw As Integer
    Dim NewR_Height As Single, NewC_Widht As Single
    Dim ActiveCellHeight As Single
 
    If rc.MergeCells Then
        With rc.MergeArea 'если ячейка объединена
            'запоминаем кол-во столбцов
            iw = .Columns(.Columns.Count).Column - rc.Column + 1
            'запоминаем кол-во строк.
            ih = .Rows(.Rows.Count).Row - rc.Row + 1
            'Определяем высоту и ширину объединения ячеек
            MergedR_Height = 0
            For Each CurrCell In .Rows
                MergedR_Height = CurrCell.RowHeight + MergedR_Height
            Next
            MergedC_Widht = 0
            For Each CurrCell In .Columns
                MergedC_Widht = CurrCell.ColumnWidth + MergedC_Widht
            Next
            'запоминаем высоту и ширину первой ячейки из объединенных
            OldR_Height = .Cells(1, 1).RowHeight
            OldC_Widht = .Cells(1, 1).ColumnWidth
            'отменяем объединение ячеек
            .MergeCells = False
            'назначаем новую высоту и ширину для первой ячейки
            .Cells(1).RowHeight = MergedR_Height
            .Cells(1, 1).EntireColumn.ColumnWidth = MergedC_Widht
            'если необходимо изменить высоту строк
            If bRowHeight Then
                '.WrapText = True 'раскомментировать, если необходимо принудительно выставлять перенос текста
                .EntireRow.AutoFit
                NewR_Height = .Cells(1).RowHeight    'запоминаем высоту строки
                .MergeCells = True
                If OldR_Height < (NewR_Height / ih) Then
                    .RowHeight = NewR_Height / ih
                Else
                    .RowHeight = OldR_Height
                End If
                'возвращаем ширину столбца первой ячейки
                .Cells(1, 1).EntireColumn.ColumnWidth = OldC_Widht
            Else 'если необходимо изменить ширину столбца
                .EntireColumn.AutoFit
                NewC_Widht = .Cells(1).EntireColumn.ColumnWidth    'запоминаем ширину столбца
                .MergeCells = True
                If OldC_Widht < (NewC_Widht / iw) Then
                    .ColumnWidth = NewC_Widht / iw
                Else
                    .ColumnWidth = OldC_Widht
                End If
                'возвращаем высоту строки первой ячейки
                .Cells(1, 1).RowHeight = OldR_Height
            End If
        End With
    End If
End Function

Пара замечаний:

  • т.к. нельзя выставить и автоширину и автовысоту — то функция подбирает либо высоту, либо ширину, что логично
  • чтобы подбор по высоте ячеек сработал, для ячейки должен быть выставлен перенос строк(вкладка Главная -группа ВыравниваниеПеренос текста). Если ячеек много и выставлять вручную лень — можно просто убрать апостроф перед точкой в строке:’.WrapText = True ‘раскомментировать, если необходимо принудительно выставлять перенос текстатогда код сам проставит переносы. Но тут следует учитывать, что в данном случае перенос будет выставлен для всех ячеек, что не всегда отвечает условиям
  • функция подбирает высоту и ширину исключительно для объединенных ячеек. Если ячейка не объединена — код оставит её без изменений

Теперь о том, как это работает и как применять. Для начала необходимо приведенный выше код функции вставить в стандартный модуль. Сама по себе функция работать не будет — её надо вызывать из другого кода, который определяет какие ячейки обрабатывать. В качестве такого кода я предлагаю следующий:

Sub ChangeRowColHeight()
    Dim rc As Range
    Dim bRow As Boolean
    bRow = (MsgBox("Изменять высоту строк?", vbQuestion + vbYesNo, "www.excel-vba.ru") = vbYes)
    'bRow = True:  для изменения высоты строк
    'bRow = False: для изменения ширины столбцов
    Application.ScreenUpdating = False
    For Each rc In Selection
        RowColHeightForContent rc, bRow
    Next
    Application.ScreenUpdating = True
End Sub

Этот код также необходимо вставить в стандартный модуль. Теперь его можно будет вызвать из этой книги, нажатием клавиш Alt+F8 и выбрав ChangeRowColHeight, или создав на листе кнопку и назначив ей макрос. После этого достаточно будет выделить диапазон ячеек, среди которых есть объединенные и вызвать макрос ChangeRowColHeight. Для всех объединенных ячеек в выделенном диапазоне будет подобрана высота или ширина.
Чтобы было нагляднее — я приложил пример, в котором помимо самих кодов есть вырезка из стандартной накладной. Именно в таких документах наиболее часто встречаются подобные казусы и необходимость подбирать высоту и ширину объединенных ячеек.
Скачать пример:

  Tips_Macro_HeightWidthInMergeCell.xls (64,0 KiB, 3 476 скачиваний)

Если подобную операцию приходится производить постоянно — советую коды записать в надстройку: Как создать свою надстройку?. Так же можно воспользоваться уже готовым решением в составе MulTEx — Высота/Ширина объединенной ячейки.


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Цитата
cuprum написал:
Если же высота строки заведомо больше чем нужно,

можно просто в этом блоке:

Код
If OldR_Height < (NewR_Height / ih) Then
    .RowHeight = NewR_Height / ih
Else
    .RowHeight = OldR_Height
End If

оставить только одну строку:

Код
.RowHeight = NewR_Height / ih

т.е. убрать условие на проверку высоты строки ДО, подбирая таким образом подо все строки без исключения. Не очень правильный подход, на мой взгляд, особенно если собрались для нескольких столбцов сразу применять. Если объединенные ячейки будут в разных столбцах, то высота будет подобрана на основании объединенных ячеек в последних столбцах.
Правильнее всего делать иначе: если это возможно, то перед выполнением цикла по ячейкам добавить строку установки стандартной высоты:

Код
Sub ChangeRowColHeight()
    Dim rc As Range
    Dim bRow As Boolean
    bRow = (MsgBox("Изменять высоту строк?", vbQuestion + vbYesNo, "www.excel-vba.ru") = vbYes)
    'bRow = True:  для изменения высоты строк
    'bRow = False: для изменения ширины столбцов
    Application.ScreenUpdating = False
    Selection.EntireRow.RowHeight = 12.75
    For Each rc In Selection
        RowColHeightForContent rc, bRow
    Next
    Application.ScreenUpdating = True
End Sub

еще правильнее делать это только в случае, если в строке есть хоть одна объединенная ячейка. Лень сейчас писать такой код, если честно. Но не сложный — можно просто выдернуть части из предложенных кодов и все.

Автоподбор высоты объединённых ячеек

Предлагаю 2 варианта автоподбора высоты объединённых ячеек в Excel
(оба работаю не идеально, — но, тем не менее, в большинстве случаев и этого будет достаточно)

1 вариант: (разъединение, автоподбор, объединение)

Sub AutoFitMergeAreaSize(ByRef cell As Range)
    Dim ra As Range: Set ra = cell.MergeArea
    cell.UnMerge
    cell.EntireRow.AutoFit
    ra.Merge
End Sub
 
Sub ПримерИспользования_АвтоподборВысотыОбъединённойЯчейки()
    AutoFitMergeAreaSize ActiveCell
    AutoFitMergeAreaSize [d3]
End Sub

2 вариант:(то же самое, по сути, только кода побольше)

Sub AutoFitMergedCellRowHeight(ByRef ra As Range)
    Dim CurrCell As Range, cell As Range, ma As Range: Dim col As Range, ro As Range
    For Each ro In ra.Rows
        maxRH = 0
        For Each cell In ro.Cells
            If cell.MergeCells And cell.Address = cell.MergeArea.Cells(1).Address Then
                Debug.Print cell.Address
                Set ma = cell.MergeArea: newCW = 0
                With ma
                    cw = .Columns(1).ColumnWidth: .UnMerge
                    For Each col In .EntireColumn: newCW = newCW + col.ColumnWidth: Next
                    .Columns(1).ColumnWidth = newCW: .EntireRow.AutoFit
                    rh = .EntireRow.RowHeight: If rh > maxRH Then maxRH = rh
                    .Merge: .Columns(1).ColumnWidth = cw
                End With
            End If
        Next cell
        If maxRH > 0 Then ro.EntireRow.RowHeight = maxRH
    Next ro
End Sub
 
Sub ПримерИспользования()
    Application.ScreenUpdating = False
    AutoFitMergedCellRowHeight [a2:z8]
End Sub
  • 28246 просмотров

Не получается применить макрос? Не удаётся изменить код под свои нужды?

Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.

Xiaohny

1 / 1 / 0

Регистрация: 12.02.2017

Сообщений: 52

15.11.2018, 16:55

 [ТС]

2

Наткунлся на схожую тему AutoFit объединённой ячейки. ColumnWidth и Columns(n).Width созданнуюtolikt
Предложенный вариант решения немного адаптировал под свою задачу, однако не получается реализовать одну из задумок.

Предполагаю, что макрос будет сравнивать высоту объединенных ячеек и выбирать такую, что содержимое ячеек будет читабельным, ширина строк останется прежней.

Предположительный алгоритм таков

If HeighN>HeighG And HeighN>HeighF And HeighN/CountRows>HeighRow Then
newHeighRow = HeighN/CountRows
ElseIf HeighG >HeighN And HeighG >HeighF And HeighG/CountRows>HeighRow Then
newHeighRow = HeighG/CountRows
ElseIf HeighF>HeighN And HeighF>HeighG And HeighF/CountRows>HeighRow Then
newHeighRow = HeighF/CountRows

HeighN — Высота объединенной ячейки столбца N
HeighG — Высота объединенной ячейки столбца G
HeighF — Высота объединенной ячейки столбца F
HeighRow — Высота строки
newHeighRow — Новая высота строки
CountRows — Количество строк в объединенной ячейки

Попытка реализации описанного алгоритма не увенчалась успехом, поэтому прошу помощи умов сего ресурса.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Sub RowHeightFiting2_Naim()
iLastRow = Cells(Rows.Count, 1).End(xlUp).Row
Range(Cells(1, 1), Cells(iLastRow, 1)).EntireRow.AutoFit
 
For Counter = 0 To iLastRow
Range("N3:N4").Offset(Counter, 0).Activate
 
' Объединённая ячейка должна быть активной!!! <FONT color=#dd33dd>' Если неактивна, то нужно переменной MyRanAdr присвоить ПОЛНЫЙ АДРЕС ОБЛАСТИ объединённой ячейки
Application.ScreenUpdating = False
Dim MyRanAdr As String
Dim MergeAreaTotalHeight, NewRH As Long
Dim MergeAreaFirstCellColWidth, MergeAreaFirstCellColHeight
 
MyRanAdr = ActiveCell.MergeArea.Address 'адрес области с объединённой ячейкой
MyRanAdrN = Range(MyRanAdr).Offset(, 0).MergeArea.Address 'адрес области с объединённой ячейкой N
MyRanAdrG = Range(MyRanAdr).Offset(, -7).MergeArea.Address 'адрес области с объединённой ячейкой G
MyRanAdrF = Range(MyRanAdr).Offset(, -8).MergeArea.Address 'адрес области с объединённой ячейкой F
 
MergeAreaTotalHeight = Range(MyRanAdr).Height ' высота всей объединённой ячейки в ед. пт
MergeAreaFirstCellColWidth = Range(MyRanAdr).Cells(1, 1).EntireColumn.ColumnWidth ' ширина первого столбца в объединённой ячейке
MergeAreaFirstCellColHeight = Range(MyRanAdr).Cells(1, 1).EntireRow.RowHeight ' высота первой строки в объединённой ячейке
Range(MyRanAdr).Cells(1, 1).ColumnWidth = (Range(MyRanAdr).Width - 3.75) / 4.5 'установка ширины первого столбца объед. ячейки равной общей ширине объед. ячейки  '''БЕЗ ПОДГОНКИ!!!
Range(MyRanAdr).WrapText = True
Range(MyRanAdr).MergeCells = False
Range(MyRanAdr).Cells(1, 1).EntireRow.AutoFit
NewRH = Range(MyRanAdr).Cells(1, 1).EntireRow.RowHeight
 
NewRHN = Range(MyRanAdrN).Cells(1, 1).EntireRow.RowHeight
NewRHG = Range(MyRanAdrG).Cells(1, 1).EntireRow.RowHeight
NewRHF = Range(MyRanAdrF).Cells(1, 1).EntireRow.RowHeight
 
Range(MyRanAdr).MergeCells = True
Range(MyRanAdr).Cells(1, 1).EntireColumn.ColumnWidth = MergeAreaFirstCellColWidth
'Range(MyRanAdr).Cells(1, 1).EntireRow.RowHeight = NewRH - (MergeAreaTotalHeight - MergeAreaFirstCellColHeight) ' для 1-й строки в объед.ячейке
'Range(MyRanAdr).EntireRow.RowHeight = NewRH / Range(MyRanAdr).Rows.Count 'для равной высоты всех строк в объед.ячейке
 
'MsgBox ("Строка№ " & 3 + Counter & vbCrLf & "Новая высота объед строки= " & NewRH & vbCrLf & "Новая высота 1 строки" & NewRH / Range(MyRanAdr).Rows.Count & vbCrLf & "Старая высота 1 строки" & Cells(3 + Counter, 4).EntireRow.RowHeight)
 
 
'If NewRH > NewRHG And NewRH > NewRHF And NewRH > Cells(3 + Counter, 4).EntireRow.RowHeight Then
'Range(MyRanAdr).EntireRow.RowHeight = NewRH / Range(MyRanAdr).Rows.Count 'для равной высоты всех строк в объед.ячейке
If NewRHG > NewRH And NewRHG > NewRHF And NewRHG > Cells(3 + Counter, 4).EntireRow.RowHeight Then
'ElseIf NewRHG > NewRH And NewRHG > NewRHF And NewRHG > Cells(3 + Counter, 4).EntireRow.RowHeight Then
Range(MyRanAdrG).EntireRow.RowHeight = NewRHG / Range(MyRanAdrG).Rows.Count 'для равной высоты всех строк в объед.ячейке
'ElseIf NewRHF > NewRH And NewRHF > NewRHG And NewRHF > Cells(3 + Counter, 4).EntireRow.RowHeight Then
'Range(MyRanAdrF).EntireRow.RowHeight = NewRHF / Range(MyRanAdrF).Rows.Count 'для равной высоты всех строк в объед.ячейке
Else
End If
 
Next Counter
Application.ScreenUpdating = True
End Sub

Пример таблицы с макросом прикладываю во вложение.

Вложения

Тип файла: xls протокол-форум.xls (80.5 Кб, 12 просмотров)



0



Понравилась статья? Поделить с друзьями:
  • Автопереносы в word что это
  • Автопереносы в word где
  • Автопереносы в word в таблице
  • Автопереносы в word 2010
  • Автоперенос ячеек в excel