1

Тема: Макрорекодер vs руки

Товарищи, помогите пожалуйста с такой проблемой: Имеется таблица, в ней могу быть объединённые ячейки (по вертикали и\или по горизонтали). При установке курсора в начале таблицы (т.е. Tables(1).Select + Selection.Collapse Direction:=wdCollapseStart) и записи действий макрорекодером получается один результат, а при воспроизведении этого кода в дальнейшем - другой. При записи использую диалоговое окно "свойства таблицы" и перемещаюсь на столбец вправо-влево, но при использовании "свойств" и кнопки "предыдущий столбец" или кнопки "следующий столбец" - выделение происходит адекватно (выделяется ровно столбец), а при проигрывании кода - выделяется вся таблица.

Sub Макрос1()
    Selection.Move Unit:=wdColumn, Count:=1
    Selection.SelectColumn 'Второй столбец выделяется нормально, а дальше начинается ересь
    Selection.Collapse Direction:=wdCollapseStart
    Selection.Move Unit:=wdColumn, Count:=-1
    Selection.SelectColumn 'данная команда выделяет вместо столбца - таблицу целиком
    Selection.Move Unit:=wdColumn, Count:=1
    Selection.SelectColumn
    Selection.Move Unit:=wdColumn, Count:=1
    Selection.SelectColumn
End Sub

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

2

Re: Макрорекодер vs руки

Сбрасываю таблицу для примера. Надо определить ширину самой узкой ячейки каждого столбца. Обращаться к ячейкам по номеру строки-столбца не выйдет т.к. объединённые ячейки будут давать ошибку 5941

Post's attachments

Пример таблицы.doc 64.5 Кб, файл не был скачан. 

You don't have the permssions to download the attachments of this post.

3

Re: Макрорекодер vs руки

Fck_This пишет:

Надо определить ширину самой узкой ячейки каждого столбца. Обращаться к ячейкам по номеру строки-столбца не выйдет т.к. объединённые ячейки будут давать ошибку 5941

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

Sub processTableCells()
Dim tbl As Table
Dim iCol As Long
Dim iRow As Long
Dim trc As Long
Dim trr As Long
Dim mincolsz As Variant
Dim curcolsz As Variant
Dim cl As Cell
Set tbl = Nothing
On Error Resume Next
Set tbl = Selection.Tables(1)
On Error GoTo 0
If Not (tbl Is Nothing) Then
    trr = tbl.Rows.count
    trc = tbl.Columns.count
    For iCol = 1 To trc
        mincolsz = 999999
        For iRow = 1 To trr
            Set crg = Nothing
            On Error Resume Next
            Set cl = tbl.Rows(iRow).Cells(iCol)
            On Error GoTo 0
            If Not (cl Is Nothing) Then
                curcolsz = PointsToCentimeters(cl.Width)
                If curcolsz < mincolsz Then
                    mincolsz = curcolsz
                End If
            End If
        Next iRow
        'Here use mincolsz
        '. . .
    Next iCol
End If
End Sub

4

Re: Макрорекодер vs руки

yshindin пишет:

Поправка (Set cl = Nothing)

...
        For iRow = 1 To trr
            Set cl = Nothing
            On Error Resume Next
...

5

Re: Макрорекодер vs руки

yshindin пишет:
yshindin пишет:

Поправка (Set cl = Nothing)

...
        For iRow = 1 To trr
            Set cl = Nothing
            On Error Resume Next
...

Крутая идея сделать изначаль объект как Nothing, а потом (при возможности) назначить его как существующий объект. Проблема только в том, что из-за объединения и, как следствие, ошибки -  они все Nothing по пути Tables.Rows.Cells и Tables.Columns.Cells

6

Re: Макрорекодер vs руки

Fck_This пишет:

Проблема только в том, что из-за объединения и, как следствие, ошибки -  они все Nothing по пути Tables.Rows.Cells и Tables.Columns.Cells

Я на своем примере смотрел - у меня в цикл попадали все ячейки, кроме объединенных (я, видимо, так неправильно понял, что объединенные заведомо шире, а нам надо найти ячейку с минимальной шириной).
Попробуйте еще использовать свойства Range.Iformation (внешняя ссылка) - там есть такие свойства определения номеров строки и столбца, как wdEndOfRangeColumnNumber и wdEndOfRangeRowNumber. А цикл делайте одноуровневым по всем ячейкам таблицы, для ячейки определяйте Range, а затем номер строки и столбца. Соответственно, для каждого столбца накапиливайте минимальное значение ширины. Но что-то мне подсказывает, что результат может быть некорректным ввиду того, что N-я ячейка в 1-й и скажем, в 5-й строке визуально относятся к разным столбцам таблицы.

7

Re: Макрорекодер vs руки

yshindin пишет:
Fck_This пишет:

Проблема только в том, что из-за объединения и, как следствие, ошибки -  они все Nothing по пути Tables.Rows.Cells и Tables.Columns.Cells

Я на своем примере смотрел - у меня в цикл попадали все ячейки, кроме объединенных (я, видимо, так неправильно понял, что объединенные заведомо шире, а нам надо найти ячейку с минимальной шириной).
Попробуйте еще использовать свойства Range.Iformation (внешняя ссылка) - там есть такие свойства определения номеров строки и столбца, как wdEndOfRangeColumnNumber и wdEndOfRangeRowNumber. А цикл делайте одноуровневым по всем ячейкам таблицы, для ячейки определяйте Range, а затем номер строки и столбца. Соответственно, для каждого столбца накапиливайте минимальное значение ширины. Но что-то мне подсказывает, что результат может быть некорректным ввиду того, что N-я ячейка в 1-й и скажем, в 5-й строке визуально относятся к разным столбцам таблицы.

Визуально может быть вообще бардак невесть какой, а фактически они относятся к тому столбцу, к которому примыкают левой границей. В таблице, в которой есть и вертикальное и горизонтальное объединение ячеек, невозможно обращение к ячейке посредством указания номеров столбца или колонки - ваш код на моей таблице просто отказывается работать (например: ячейка(1) в rows(2) существует и не является объединённой, но по ошибке '5991' она не может определяться через строки-колонки) + при обращении по Columns будет выдаваться ошибка '5992'.
Я таки на 4-ый день нарыл кое-какой код, позволяющий разобраться с этой проблемой. Перебрать ячейки можно в том случае, если они будут являться элементами коллекции, а отнесённость их к колонке-строке можно через ColumnIndex-RowIndex. В дальнейшем можно использовать эти индексы и обращаться по точному адресу ячейки oTable.Cell(sName, ABC). С индексом определённого столбца можно выбрать самую узкую ячейку:

Sub Макрос1()
Dim oTable As Table
Dim oCell As Cell
For i = 1 To activeDocument.tables.count
Set oTable = ActiveDocument.Tables(i)
oTable.Select
For Each oCell In Selection.Range.Cells
    oCell.Select
    ABC = oCell.ColumnIndex
    sName = oCell.RowIndex
Next oCell
Next i
End Sub

Может кому пригодится.

8

Re: Макрорекодер vs руки

Хотя как задать ширину столбцу - так и не выяснил. Написал макросы для определения ширины наименьшей ячейки столбца, перевёл в проценты, а как применить - не понятно. Опять при обращении к столбцу через номер - выдаёт ошибку 5992, а при задании вручную - прекрасно выделяется весь столбец (вручную - через свойства таблицы). Как всё-таки задать ширину столбца в таблице с объединёнными ячейками?