Коннектор Python openpyxl с якорем

Мне очень хотелось бы нарисовать изогнутую стрелку с привязкой к ячейке с помощью библиотеки openpyxl, как показано на рисунке ниже;

После того, как я просмотрел официальную документацию, я не могу найти способ сделать это (хотя я нашел подходящее ключевое слово в классе openpyxl.drawing.shapes.PresetGeometry2D)

Как я могу нарисовать такой закрепленный соединитель с помощью Python? Я открыт для других пакетов, если OpenPyxl не поддерживает эту функцию.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Openpyxl обычно не очень хорошо работает с Shapes, поэтому лучшим вариантом обычно будет использование альтернативного модуля, такого как Xlwings или Win32com;

Ниже приведен базовый пример того, как это сделать в Xlwings;

  1. Создает новую книгу и лист.
  2. Добавляет два прямоугольника
  3. Добавьте изогнутый соединитель
  4. Соединяет начало изогнутого соединителя с прямоугольником 1 в позиции 1.
  5. Соединяет конец изогнутого соединителя с прямоугольником 2 в позиции 1.
  6. Перенаправляет соединение на кратчайший путь между двумя фигурами.

Пример кода
Числовые значения, используемые не для позиционирования, являются значениями перечисления Excel для параметра. Чтобы получить эти значения, используйте необходимый метод Excel Enumerations.
(Обратите внимание, что команды для win32com будут аналогичны этому)

import xlwings as xw
from xlwings.utils import rgb_to_int


with xw.App(visible=True) as app:
    wb = xw.Book()
    ws = wb.sheets.active

    # Add two rectangle shapes
    ### Excel AddShape command, Values are Type, Left, Top, Width & Height

    shape1 = ws.api.Shapes.AddShape(1, 50, 44, 95, 27)  # 1 is a rectangle
    print(f"Shape1 name '{shape1.Name}'")
    shape1.Fill.ForeColor.RGB = rgb_to_int((255, 233, 00))  # Set Fill colour

    shape2 = ws.api.Shapes.AddShape(1, 290, 115, 94, 28)
    print(f"Shape2 name '{shape2.Name}'")
    shape2.Fill.ForeColor.RGB = '&HFF0000'  # Alternate method to set fill colour

    ### AddConnector (line) has same params; Type, Left, Top, Width & Height
    connector1 = ws.api.Shapes.AddConnector(3, 1, 1, 1, 1)  # 3 is a msoConnectorCurve (Curved connector)
    # connector1.Line.ForeColor.RGB = '&H000000'  # Set Line colour method 1
    # connector1.Line.ForeColor.RGB = rgb_to_int((0, 0, 0))  # Set Line colour method 2
    connector1.Line.ForeColor.ObjectThemeColor = 13  # Set line colour method 3
    connector1.Line.EndArrowheadStyle = 2  # Set Arrow head style as desired
    connector1.Line.EndArrowheadLength = 3  # Set Arrow head length as desired
    connector1.Line.EndArrowheadWidth = 3  # Set Arrow head width as desired

    ### Connecting the curved connector between the two rectangles
    connector1.ConnectorFormat.BeginConnect(ConnectedShape=shape1, ConnectionSite=1)
    connector1.ConnectorFormat.EndConnect(ConnectedShape=shape2, ConnectionSite=1)
    ### Re-route the connectors to the shortest route between the two shapes
    connector1.RerouteConnections()

    wb.save('Shapes.xlsx')

Результирующий лист

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

Дополнительные подробности
Для первого параметра команды AddShape «Тип» — это тип добавляемой фигуры. Это типы перечислений Excel, поэтому может быть либо имя, либо число,
Т.е. Перечисление msoShapeRectangle (Rectangle) равно 1, поэтому в качестве типа можно использовать либо «msoShapeRectangle», либо 1.
Остальные параметры — это положение и размер фигуры, как указано в коде.
Для размещения прямоугольников я использовал произвольные значения.

Размер и расположение разъема также можно изменять. Однако, поскольку мы соединяем его между двумя фигурами, мы можем использовать для них произвольные значения и предоставить Excel объединить начальную и конечную точки, поэтому в этом примере я просто установил для них все значения 1.
При соединении изогнутого соединителя между двумя фигурами вам необходимо указать начальную форму и точку (место соединения) на начальной фигуре для соединения, а также конечную форму и место соединения на конечной форме для соединения.
Место соединения, обозначенное цифрой, будет варьироваться в зависимости от формы. Если вы знаете, какое значение требуется для сайта подключения, его можно указать.
Пример в примере, который я использовал, сайт подключения Rectangle 1 — 4, а сайт подключения Rectangle 2 — 2, поэтому команда могла быть такой;

connector1.ConnectorFormat.BeginConnect(ConnectedShape=shape1, ConnectionSite=4)
connector1.ConnectorFormat.EndConnect(ConnectedShape=shape2, ConnectionSite=2)

Однако, если номера мест соединителя неизвестны, вы можете подключиться к двум произвольным точкам, как я сделал здесь, а затем заставить Excel перенаправить соединитель на кратчайший маршрут, используя RerouteConnections()

Следуйте дальше
Можно отказаться от фигур [прямоугольника] и просто нарисовать изогнутый соединитель так, чтобы он проходил между двумя ячейками. Тогда соединитель будет перемещаться вместе с ячейками.
Как уже отмечалось, ячейки не имеют точек соединения, однако мы можем получить данные о левом, верхнем, ширине и высоте ячейки и на их основе выполнить расчеты. Рекомендуется получать сведения о ячейке из листа, для которого установлено масштабирование 100 %, чтобы обеспечить точность. Я включил эту настройку в пример кода ниже.
В приведенном ниже примере вводятся координаты начальной и конечной ячейки, получаются данные слева, сверху, ширины и высоты и используются они для расчета деталей начала и конца соединителя. В коде параметры соединителя:
Тип, BeginX, BeginY, EndX, EndY

BeginX — начало позиции соединителя в строке
BeginY — начало позиции соединителя в столбце
EndX, EndY одинаковы для конечного положения соединителя.

При расчете позиций X я вошел в ячейку на 1/4 ее ширины, чтобы было понятно, где находится разъем.

Пример кода
Добавьте соединитель из ячейки «B3» в «E6».

import xlwings as xw
from xlwings.utils import rgb_to_int


def add_connector(begin_cell, end_cell):
    with xw.App(visible=True) as app:
        wb = xw.Book()
        ws = wb.sheets.active
        app.api.ActiveWindow.Zoom = 100  # Ensure the zoom on the sheet is 100%

        ### Start cell postion values
        ws[begin_cell].color = (255, 192, 0)
        cell_start = ws[begin_cell]
        sleft = cell_start.left
        stop = cell_start.top
        sheight = cell_start.height
        swidth = cell_start.width
        print(f"Cell A3 details: Left:{sleft}, Top:{stop}, Height{sheight}, Width{swidth}")

        ### End cell postion values
        ws[end_cell].color = (47, 117, 181)
        cell_dest = ws[end_cell]
        dleft = cell_dest.left
        dtop = cell_dest.top
        dheight = cell_dest.height
        dwidth = cell_dest.width
        print(f"Cell F10 details: Left:{dleft}, Top:{dtop}, Height{dheight}, Width{dwidth}")

        ### Obtain the connector start and end points from the cells postion
        ### Add 1/4 of the cell width intrusion in to the cell
        ### Start cell
        begin_x = (sleft + swidth) - swidth/4
        begin_y = stop + sheight/2
        ### End cell
        end_x = dleft + swidth/4
        end_y = dtop + dheight/2

        ### AddConnector (line) has params; Type, BeginX, BeginY, EndX, EndY
        connector1 = ws.api.Shapes.AddConnector(3, begin_x, begin_y, end_x, end_y)
        # connector1.Line.ForeColor.RGB = '&H000000'  # Set Line colour method 1
        # connector1.Line.ForeColor.RGB = rgb_to_int((0, 0, 0))  # Set Line colour method 2
        connector1.Line.ForeColor.ObjectThemeColor = 13  # Set line colour method 3
        connector1.Line.EndArrowheadStyle = 2  # Set Arrow head style as desired
        connector1.Line.EndArrowheadLength = 3  # Set Arrow head length as desired
        connector1.Line.EndArrowheadWidth = 3  # Set Arrow head width as desired

        wb.save('connector.xlsx')

add_connector('B3', 'E6')

Пример листа

Ой, спасибо за добрый ответ! Это примерно то, что я хочу, за исключением того, что мне хотелось бы соединять ячейки, а не фигуры. Я проверил документацию, Learn.microsoft.com/en-us/office/vba/api/…, но она принимает форму только в качестве аргумента ConnectedShape. Могу ли я как-нибудь привязать его к определенной точке определенной ячейки???

lighthouse 19.06.2024 05:05

Кроме того, код, похоже, не работает на моем Mac. Файл "/Users/name/Documents/dev/python/notebooks/venv/lib/python3‌​.12/site-packages/ae‌​osa/appscript/refere‌​nce.py", строка 596, в типе выбора getattr, код = self.AS_appdata.referencebyname()[имя] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ KeyError : «Формы»

lighthouse 19.06.2024 05:17

Я добавил к ответу относительно ваших комментариев, см. раздел «Примечания» внизу.

moken 19.06.2024 05:55

Это была линия shape1 = ws.api.Shapes.AddShape(1, 50, 44, 95, 27). Действительно, похоже, что Xlwings используют другую операционную систему. Возможно, мне придется попробовать это в Windows или перейти к прямым манипуляциям с XML. Что вы думаете о манипуляциях с XML? Будет ли это осуществимой идеей?

lighthouse 19.06.2024 07:59

Использование Windows, безусловно, является лучшим вариантом, если она у вас есть. Непосредственное изменение XML является более сложным, поскольку вам необходимо убедиться, что необходимые файлы обновлены правильно, чтобы понимание их взаимодействия и необходимых тегов было абсолютным. Я не нашел сообщений людей, использующих XLwings и AddShape для MAC, поэтому нет подробностей, сталкивались ли другие с той же проблемой.

moken 19.06.2024 08:30

Я обновил ответ, добавив соединитель между двумя ячейками. Обновление и пример кода см. в следующем разделе. В этом примере кода требуется только AddConnector, поэтому добавить фигуру все равно необходимо.

moken 20.06.2024 08:54

Чтобы помочь заставить код работать на MACOS, вы можете посмотреть, что возвращается для Shapes, используя пример кода здесь. Итак, создайте лист с требуемыми фигурами и посмотрите, что представляет собой возвращаемый объект.

moken 20.06.2024 09:03

Другие вопросы по теме