Перейти к содержимому
Наше приложение «Дешевые авиабилеты» в AppGallery >>

VBA Excel. Работа с фигурами (Shapes)

    Работа с фигурами в VBA Excel: создание фигур методом Shapes.AddShape, типы фигур (MsoAutoShapeType), обращение к фигурам и изменение их свойств. Примеры.

    Объекты для работы с фигурами

    Фигуры в VBA Excel представлены тремя объектами:

    Объект Описание
    Shapes Коллекция всех фигур на рабочем листе. Используется для создания новых фигур, для обращения к одной фигуре по имени и для перебора фигур циклом.
    ShapeRange Коллекция нескольких фигур, аргументом которой является массив имен выбранных объектов. Используется для редактирования сразу всех фигур, входящих в эту коллекцию.
    Shape Объект, представляющий одну фигуру. Используется для редактирования одной этой фигуры.

    Создание фигур в VBA Excel

    Фигуры в VBA Excel создаются методом Shapes.AddShape.

    Синтаксис метода AddShape

    Shapes — выражение, возвращающее коллекцию фигур на рабочем листе, например: ActiveSheet.Shapes.

    Параметры метода AddShape

    Параметр Описание
    Type Константа из коллекции MsoAutoShapeType, определяющая тип создаваемой фигуры.
    Left Расстояние от левой границы фигуры до левой границы табличной части рабочего листа в пунктах.. Тип данных — Single.
    Top Расстояние от верхней границы фигуры до верхней границы табличной части рабочего листа в пунктах.. Тип данных — Single.
    Width Ширина фигуры по внешним границам в пунктах.
    Height Высота фигуры по внешним границам в пунктах.

    Все параметры метода Shapes.AddShape являются обязательными.

    Константы MsoAutoShapeType

    Константы коллекции MsoAutoShapeType, определяющие основные типы создаваемых фигур:

    Константа Значение Тип фигуры
    msoShapeRectangle 1 Прямоугольник
    msoShapeParallelogram 2 Параллелограмм
    msoShapeTrapezoid 3 Трапеция
    msoShapeDiamond 4 Ромб
    msoShapeRoundedRectangle 5 Прямоугольник: скругленные углы
    msoShapeOctagon 6 Восьмиугольник (октаэдр)
    msoShapeIsoscelesTriangle 7 Равнобедренный треугольник
    msoShapeRightTriangle 8 Прямоугольный треугольник
    msoShapeOval 9 Овал
    msoShapeHexagon 10 Шестиугольник (гексаэдр)
    msoShapeCross 11 Крест
    msoShapeRegularPentagon 12 Пятиугольник (пентаэдр)
    msoShapeCan 13 Цилиндр
    msoShapeCube 14 Куб
    msoShapeDonut 18 Круг: прозрачная заливка (кольцо)
    msoShapeLightningBolt 22 Молния
    msoShapeSun 23 Солнце
    msoShapeMoon 24 Месяц (луна)
    msoShape5pointStar 92 Звезда: 5 точек (пятиконечная)
    msoShapeCloud 179 Облако

    Все доступные константы из коллекции MsoAutoShapeType смотрите на сайте разработчиков.

    Создание объекта ShapeRange

    Создание коллекции ShapeRange из выбранных фигур:

    Объектная переменная myShapeRange не обязательна, можно обратиться непосредственно к возвращенной коллекции, например, присвоив всем ее элементам синий цвет:

    Примеры работы с фигурами

    Пример 1

    Создание пяти разных фигур из кода VBA Excel методом Shapes.AddShape:

    Результат работы кода:

    Фигуры на листе Excel

    Пример 2

    Работа с одной фигурой:

    Пример 3

    Редактирование одновременно нескольких фигур с помощью коллекции ShapeRange:

    Пример 4

    Редактирование одновременно всех фигур на рабочем листе с помощью коллекции ShapeRange:

    Пример 5

    Добавление надписи (текста) на фигуру:

    Результат работы кода:

    Фигура Облако с надписью

    Изменить цвет текста, например на черный, можно двумя способами:

    С константами из коллекции MsoThemeColorIndex вы можете ознакомиться на сайте разработчиков.

    Пример 6

    Удаление фигур с рабочего листа из кода VBA Excel с помощью метода Delete.

    Удаление одной фигуры:

    Удаление нескольких фигур:

    Удаление всех фигур с рабочего листа с помощью цикла:

    В 7 примере рассмотрено удаление всех фигур без цикла.

    Пример 7

    Выделение всех фигур на рабочем листе:

    Выбор всех фигур и удаление выбранного (всех фигур):


    Продолжение темы в статье VBA Excel. Копирование, перемещение и поворот фигур.


    Содержание рубрики VBA Excel по тематическим разделам со ссылками на все статьи.

    98 комментариев для “VBA Excel. Работа с фигурами (Shapes)”

    1. Сбитый Лётчик Небосводов

      Здравствуйте!
      Можно ли константы MsoAutoShapeType задавать переменными?
      Что-то у меня не получается. Как ни пробую, всё Run-time error ’13’: Type mismatch.

      1. Евгений

        Добрый вечер!
        У меня работает:

        То же самое при использовании текстовых значений констант MsoAutoShapeType:

    2. Сбитый Лётчик Небосводов

      Спасибо, лучший друг VBAшника Евгений!
      У меня не работает при str = «msoShapeOctagon» и .AddShape str,…
      Ваше решение меня выручает.

    3. Сбитый Лётчик Небосводов

      Можно ли наносить на Shapes надписи? И как, если да?
      Не могу найти, а нужно срочно. Можно, разумеется ответить ссылкой.

      1. Сбитый Лётчик Небосводов

        Можно.

          1. Сбитый Лётчик Небосводов

            Добавил бы

    4. здравствуйте
      Если вопрос не по теме — просьба перенести в соответствующий раздел.
      На рабочем Листе есть фигуры/картинки/фотографии…
      которым присвоены свои имена («Прямоугольник 1», «Рисунок 2″…)
      при копировании (внутри листа) они получают новые имена (фигура 12; рисунок 4 …)
      У меня 2-а вопроса:
      1) как макросом определить наименование картинки которая расположена в диапазоне D3:F5 ?
      2) при изменении размера, встроенный компилятор показывает код:

      какой написать код , чтобы машина выполняла действия ( изменение размера) без Selection ?

      1. Евгений

        Добрый день, 0mega!
        1) Как макросом определить наименование картинки, которая расположена в диапазоне D3:F5?
        Так можно найти фигуру, левая верхняя точка которой находится в диапазоне D3:F5:

        2) Какой написать код , чтобы машина выполняла действия (изменение размера) без Selection?

        1. спасибо,
          а как можно изменить имя напр. «Прямоугольник 1» — «figure12» ?

          1. можно ли скопировать и сразу переименовать фигуру ?

          2. Евгений

            ActiveSheet.Shapes(«Прямоугольник 1»).Name = «figure12»

          3. Евгений

    5. Добрый день!
      Как соединить кодом VBA две фигуры соединительной линией так, чтобы при перемещении одной из фигур соединитель не отрывался от нее?

    6. Есть два объекта shapes. В одном стоит цифра. надо читать эту цифру и на основе цифры написать на другой объект shapes определенный текст. Заранее спасибо.

      1. Евгений

        Привет, Надир!
        Примерный код может быть таким:

    7. Добрый день. Подскажите, пожалуйста, как для автофигуры назначить нажатие? Задача такая, что если по нажатию на автофигуру срабатывал бы код Application.CommandBars.FindControl(ID:=1605).Execute, а при втором нажатии срабатывал бы код Application.CommandBars.FindControl(ID:=1605).Reset
      Буду очень благодарен.

      1. Евгений

        Здравствуйте, Юрий!
        Объявите переменную уровня модуля типа Boolean. При открытии файла, она будет иметь значение False. Пример кода:

    8. Григорий

      Добрый день!
      Вот так на Активном листе создаются прямоугольники (один запуск — один прямоугольник) один под другим:

      а вот так я их удаляю:

      Вопрос: нужно чтобы прямоугольник, сначала выделялся, затем шел диалог запроса: Удалять-Оставить-Завершить.
      Удаляет и оставляет и завершает, но … с выделением уже голову сломал. Может кто подскажет: что не так?

      1. Евгений

        Здравствуйте, Григорий!
        Попробуйте после With shp вместо .Select вставить следующую строку:

    9. А есть возможность перемещать фигуры? То есть менять их координаты?

      1. Евгений

        Добрый вечер, Антон!
        Перемещать фигуры можно:

    10. Добрый день.
      Как можно фигуру (в моём случае это картинка на листе) назначить как картинку или фон для пользовательской формы?

      1. Евгений

        Здравствуйте, Артём!
        По-моему, это невозможно.

    11. Александр

      Здравствуйте. А можно как-нибудь удалить строку, если в ячейке нет объекта Shape&

    12. Александр

      Здравствуйте, есть ли возможность присвоить имя в ячейке для объекта SHAPE?

      1. Евгений

        Добрый день, Александр!
        Вы хотите слово, записанное в ячейку, присвоить в качестве имени объекту Shape?

        1. Александр

          Добрый день. Нужно, чтоб в ячейке, куда вставляется объект Shape вставлялось еще наименование данного объекта

          1. Евгений

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

            Для любого случая:

    13. ЕвгенияУ

      Добрый день! У вас в статье приведены примеры с внесением текста в фигуру. Я вижу что текст не в одну строку в фигуре, а переносится по словам на следующие строки. Объясните, пожалуйста, как это сделано? Только, пожалуйста, простыми словами (. Я макросами никогда не занималась, и разбираю чужой макрос.

      1. Евгений

        Здравствуйте, Евгения!
        В моем примере текст переносится по словам по умолчанию.
        Отмена переноса текста по словам:

        где Shape — выражение, возвращающее фигуру, например, Shapes(1), Shapes(«Ромб 1»), или, как в моем примере, это может быть переменная (myShape).
        Поищите в своем макросе строку с текстом .WordWrap = msoFalse и закомментируйте ее.
        А так можно задать перенос текста по словам из кода макроса:

        1. ЕвгенияУ

          Фразы такой в макросе не нашла. Видите-ли в чем дело, ранее перенос не требовался, т.к. текст был коротким. Теперь текст увеличился и выходит далеко за границы страницы вообще. Этот текст макрос переносит с первой страницы во все остальные(своего рода заполнение штампа). И так понимаю что функция переноса просто не вписана вообще. Я вписалась то что вы мне прислали
          Shape.TextFrame2.WordWrap=msoTrue.
          В ответ он пишет «Ошибка компиляции. Переменная не определена». Фразу я эту вписала последней строкой после строк заполнения штампа(заполнения граф).

          1. Евгений

            Вам надо заменить слово Shape на то имя фигуры, которое используется в вашем макросе.

            1. ЕвгенияУ

              Добрый день, Евгений! К сожалению у меня все равно ничего не получается. Либо я не туда вписываю программную строку, либо не вписываю вместо Shape. Я сделал отдельный макрос (просто отредактировал текст в фигуре через «формат фигуры»), но при выводе на печать он сбрасывает все(.

    14. Дмитрий

      Добрый день!

      Как задать ширину и длину объекта в см на основании значения определенных ячеек?

      1. Евгений

        Здравствуйте, Дмитрий!
        Высота и ширина фигур задаются в пунктах. В 1 см содержится приблизительно 28.35 пунктов:

    15. здравствуйте
      на рабочем листе имеется картинка "Sred"
      Верхний левый угол этой картинки надо припарковать в D5
      ActiveSheet.Shapes.Range(Array("Sred")).Copy Range("d5")
      Такую команду машина игнорирует и картинка остается на своем месте
      Range("D5") = Shapes("Sred")
      здесь тоже.
      Как переместить картинку в нужную ячейку ?
      P.S.
      IncrementLeft/Top не подходят потому что адрес назначения имеет RND
      Вставлять надо именно в адресную ячейку

      1. Евгений

        Привет!

    16. Евгений, с наступающим

      Имеется книга "E_N".В ней несколько листов. Нас интересуют два листа "Sv" и последний лист.
      На Листе "Sv" есть фигура "Sun".
      Макрос должен скопировать "Sun" и вставить на последний лист в ячейку F7
      Ничего сложного.
      Такой макрос обычный макрорекордер запишет, но есть одно условие
      Копировать/вставлять надо без Selection

      1. Евгений

        Добрый день!

    17. спасибо.
      всё работает как надо

      Евгений , мысли вслух… (можно и не публиковать )
      почему бы вам не организовать свой Excel-форум.
      Подобрать пару-тройку грамотных модераторов и я думаю что вы не долго будете «в тени»

    18. ЕвгенияУ

      Евгений, здравствуйте! Я все перепробовала-у меня ничего не получилось. Могу ли я Вам как-то показать макрос, который строит штамп и вносит туда данные?

      1. Евгений

        Здравствуйте, Евгения!
        Вставьте ваш макрос в комментарий. Если в нем есть конфиденциальная информация, замените ее незначащим текстом.

        1. ЕвгенияУ

          Здравствуйте, Евгений!
          Я Вам написала в комментариях макрос, пока правда он еще что-то не отобразился(

          1. Евгений

            Здравствуйте, Евгения!
            Макрос пришел, я посмотрю его.

          2. Евгений

            Евгения, попробуйте заменить строку

            на

            1. ЕвгенияУ

              Спасибо большое! Как выйду с выходных попробую.

            2. ЕвгенияУ

              Евгений, доброе утро! К сожалению то что вы предложили не сработало. Текст не переносится на следующую строчку.

              1. Евгений

                Здравствуйте, Евгения!
                Тогда попробуйте заменить ту же строку

                на

                Если получится, установите нужные значения ширины и высоты надписи.

                1. ЕвгенияУ

                  Спасибо большое, Евгений! Заработало! Но работает во всех строках кроме "один", там почему-то не переносит.

                  1. Евгений

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

                    1. ЕвгенияУ

                      В коде относящемся к «один» почему-то выпадает строка
                      .name=name ‘имя ячейки.

                      1. Евгений

                        Закомментируйте строки с If в этом блоке:

                    2. ЕвгенияУ

                      Евгений, здравствуйте! Все просмотрела через F8, везде все операции одинаковы и последовательность их выполнения одинакова, но в поле «один» текст так и не переносится(.

                      1. Евгений

                        Здравствуйте, Евгения! А вы закомментировали строки с If?

                    3. ЕвгенияУ

                      Здравствуйте, Евгений!
                      Да, закомментировала ( ну если все правильно сделала)
                      If name""Then '...
                      .name=name 'имя ячейки
                      End If '...

                      Отличие в выполнении команд по полю «один» и остальных заключается в:
                      name="один"
                      addUnitLabel ws,10*0,10*0,500,10,True,name,getCellValue(name)

                      в слове True. Все остальные False. Я несколько раз все пересмотрела и сравнила. Только в этом отличие.

                      1. Евгений

                        Евгения, вы неправильно закомментировали строки с If — апострофы должны стоять перед If и End:

                        True задает полужирное начертание, если оно вам не нужно, замените на False.

                      2. ЕвгенияУ

                        Здравствуйте, Евгений! Извините, я просто никогда vba не занималась(.
                        Я закомментировала как вы сказали, и теперь строка
                        .name=name ‘имя ячейки
                        высвечивается как ошибка (выделена жёлтым).

                      3. Евгений

                        Евгения, отмените комментирование строк с If. Откройте «Диспетчер имен» на вкладке «Формулы» и посмотрите, есть ли там имена «один», «два», «три» и т.д. Возможно, среди всех имен, у вас нет имени «один», поэтому строка .name = name на имени «один» пропускается.

                      4. Евгений

                        Если в «Диспетчере имен» есть имя «один», значит ячейка с этим именем пустая, посмотрите адреса именованных ячеек и что в них записано. Возможно, вам просто нужно вписать нужный текст в ячейку с именем «один».

                      5. ЕвгенияУ

                        Добрый день, Евгений!
                        Фразы с if раскомментировала.
                        В «диспетчере имен» есть все поля. У них у всех есть, имя, значение, диапазон и область. Данные в саму ячейку внесены, иначе я не смогла бы заметить что там не переносится информация.
                        Теперь при использовании F8 все поля выполняются одинаковыми функциями, нет ни одного отличия. Строчка с name присутствует в выполнении программы в каждом поле. Но проблема с переносом текста в поле «один» так и осталась.

                        1. Евгений

                          Здравствуйте, Евгения!
                          Текст в поле «один» не вставляется или вставляется, но не переносится по словам?

                        2. ЕвгенияУ

                          Евгений, здравствуйте! Текст в поле «один» вставляется, но перенос на другую строку не происходит и он наползает на поле «пять». В поле «один» и «два» цифровые значения, в остальных буквенные.

                          1. Евгений

                            А между цифрами в поле «один» встречаются пробелы? Цифры печатаются в поле «один» полужирным шрифтом?

                          2. ЕвгенияУ

                            В поле «один» идёт некоторый набор цифр, перечисление, через запятые. Так же как и в поле «два». Полужирное написание в поле «один» есть.

                            1. Евгений

                              Закомментируйте строки

                              вставьте под ними

                              И посмотрите что получится.

                            2. ЕвгенияУ

                              Евгений, здравствуйте! Спасибо Вам огромное! Вы просто гений и супер знаток. Все заработало как надо!!!

          3. Александр

            А как выделить все фигуры на активном листе через vba?

          4. АндрейК

            Добрый день. Подскажите, как создать фигуру без фона. В примере 2 ".Fill.ForeColor.RGB = vbYellow" вместо vbYellow какое значение нужно поставить? И можно ли создать фигуру с помощью макроса, которая не будет перемещаться и изменять свой размер вместе с ячейками.

            1. АндрейК

              С фигурой без фона разобрался.
              Записал и фон стал прозрачным.
              .Fill.ForeColor.RGB = RGB (255,255,255)
              .Fill.Transparency = 1

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

              1. Евгений

                Здравствуйте, Андрей!
                Фигура перемещается с ячейкой, но размеры не изменяет:

                А чтобы фигура вообще оставалась на месте:

                1. АндрейК

                  Еще подскажите. Как это свойствам применить не нескольким созданным объектам? Как у вас идет обращение к «Блок-схема 2» (на сколько я понимаю это группа объектов). Как нескольким объектам присвоить одну группу

                  1. Евгений

                    «Блок-схема 2» — это одна фигура. Как изменить свойства одновременно у нескольких фигур показано в примерах 3 и 4.

                    1. АндрейК

                      Спасибо разобрался. И надеюсь последний вопрос: можно ли задать поля для надписи внутри фигуры. Когда смотрю свойства созданной фигуры, в параметрах «Надпись» установлены значения по умолчанию: 0,25/0,25/0,13/0,13см (левое/правое/верхнее/нижнее поле). Возможно ли в макросе задать эти значения (необходимо везде 0см установить). Либо если текст не помещается в фигуре, автоматически подогнать размер шрифта.

                      1. Евгений

                2. АндрейК

                  Прошу прощения, что возвращаюсь к закрытому вопросу, но хотел бы все таки у Вас узнать. Возможно ли полностью удалить заливку у фигуры с помощью макроса? Создав фигуру с заливкой и убрав ее с помощью добавления прозрачности решается только часть проблемы. Когда фон у фиругы убран с помощью прозрачности, ячейки под фигурой становятся видимы, но выделить ячейку все равно проблематично, потому что нажав на ячейку внутри фигуры выделяться фигуру, а не ячейка. Когда в ручную полностью отключается фон (в свойствах выбираю «нет заливки»), то перемещение по ячейкам внутри фигуры производится в обычном режиме (как будто фигуры и нету на листе).
                  Подытожив, задача заключается в том, чтобы на листе была рамка, но работа с ячейками внутри рамки осуществлялась в обычном режиме.
                  Прошу прощения за много текста, но надеюсь удалось объяснить суть моего вопроса. За ранее благодарен

                  1. Евгений

                    Это не сложно:

          Обсуждение закрыто.