Категория

Добавление стрелочных соединителей в Excel на JavaScript (React)

2026-09-23 07:40:47 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

Inserting arrow-tipped lines and directional connectors in an Excel worksheet in the browser with Spire.XLS for JavaScript

Линия между двумя блоками на блок-схеме говорит «они связаны». Стрелка от одного к другому говорит «этот идёт первым». Именно это различие — направление — отличает соединитель от декоративного элемента, и это единственное, что базовый API Lines.AddLine() не может сделать на обоих концах. Схема процесса требует стрелки, выходящей из каждого шага; диаграмма причинно-следственных связей требует стрелок, указывающих внутрь; сравнение иногда требует двунаправленных стрелок, чтобы показать двустороннюю связь. Ничего из этого невозможно с одним EndArrowHeadStyle.

Spire.XLS for JavaScript предоставляет sheet.TypedLines.AddLine() именно для такого случая. Он позиционирует линии по пиксельным координатам вместо строк и столбцов и принимает BeginArrowHeadStyle и EndArrowHeadStyle независимо — так что линия может нести стрелку на одном конце, на обоих концах или ни на одном. Движок работает в браузере на WebAssembly, файлы перемещаются через виртуальную файловую систему (VFS), и никакого бэкенда не задействовано.

О настройке проекта см. Интеграция Spire.XLS for JavaScript в проект React. Приведённые ниже примеры предполагают, что пакет установлен и модуль WebAssembly инициализирован.


Направление меняет всё

Три диаграммы, три разных требования к направлению, и один и тот же API линий справляется со всеми:

Тип диаграммы Конфигурация стрелок Что она сообщает
Схема процесса Стрелка только на конце Последовательное выполнение — шаг A ведёт к шагу B
Причинная цепочка Стрелка только на конце, несколько линий последовательно Причина порождает следствие, которое порождает следующее следствие
Двунаправленная связь Стрелка на обоих концах Взаимная связь — A влияет на B, а B влияет на A
Указатель-аннотация Стрелка на конце, нет стрелки на начале Метка указывает на ячейку, которую она описывает

Сам стиль наконечника стрелки также несёт смысл. Залитая сплошная стрелка (LineArrow) воспринимается как определённая, устойчивая связь. Открытая стрелка (LineArrowOpen) воспринимается как более свободная, менее определённая — что часто встречается в диаграммах потоков данных, где направление известно, но механизм не указан.


Предварительные требования

Вам нужен проект React с установленным Spire.XLS for JavaScript и инициализированным модулем WebAssembly, доступным по адресу window.wasmModule.spirexls. Пример загружает шрифт в VFS и сохраняет с флагом версии Excel 2010.


TypedLines против Lines: в чём разница

sheet.Lines.AddLine() и sheet.TypedLines.AddLine() — это два отдельных API для двух разных задач. Различия структурные, а не косметические:

Lines.AddLine() TypedLines.AddLine()
Позиционирование Координаты строк и столбцов Пиксельные координаты (Top, Left)
Размер width и height в конструкторе Width и Height как свойства
Стрелка на конце EndArrowHeadStyle EndArrowHeadStyle
Стрелка на начале Не поддерживается BeginArrowHeadStyle
Тип линии Задаётся через lineShapeType в конструкторе Задаётся через свойство LineShapeType
Лучше всего подходит для Простые фигуры линий, выровненные по ячейкам Направленные соединители с точным размещением

Поддержка стрелки на начале — самое значимое различие. С Lines.AddLine() линия может иметь наконечник на конце, но не в начале — этого достаточно для одностороннего потока, но не для двунаправленной связи. TypedLines.AddLine() снимает это ограничение.

Для базовых фигур линий без стрелок см. Вставка фигур линий в Excel на JavaScript (React), где рассматривается API Lines.AddLine().


Позиционирование с точностью до пикселя

TypedLines.AddLine() размещает линии с помощью Top и Left в пикселях, а Width и Height управляют их протяжённостью:

let line = sheet.TypedLines.AddLine();
line.Top = 10;     // 10 pixels from the top of the sheet
line.Left = 20;    // 20 pixels from the left
line.Width = 100;  // 100 pixels wide
line.Height = 0;   // 0 height — a horizontal line

Height, равный 0, создаёт горизонтальную линию; Width, равный 0, создаёт вертикальную. Установка обоих значений в ненулевые значения создаёт диагональный или изогнутый соединитель, в зависимости от LineShapeType.

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


Комбинации стрелок

Когда BeginArrowHeadStyle и EndArrowHeadStyle заданы независимо, четыре комбинации охватывают распространённые случаи:

Начало Конец Визуально Значение
LineNoArrow LineArrow → Одностороннее направление: A ведёт к B
LineArrow LineArrow ↔ Двунаправленное: A и B влияют друг на друга
LineArrow LineNoArrow ← Обратное одностороннее: B ведёт к A (редко, но полезно для макетов справа налево)
LineNoArrow LineNoArrow — Без направления: обычный соединитель (для простоты используйте вместо этого Lines.AddLine())

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


Вставка линий со стрелками

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

  1. Создайте объект Workbook и получите первый рабочий лист.
  2. Вызовите Worksheet.TypedLines.AddLine() для создания каждой линии.
  3. Задайте положение линии через Top, Left, Width и Height (в пикселях).
  4. Задайте стили стрелок на обоих концах через BeginArrowHeadStyle и EndArrowHeadStyle.
  5. Укажите тип линии через LineShapeType (прямая, угловая, изогнутая и т. д.).
  6. Сохраните книгу с помощью Workbook.SaveToFile().
function App() {
  const addArrowLines = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font into the VFS for text measurement and column auto-fit
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);

    // Create a new workbook and get the first worksheet
    const workbook = new xlsModule.Workbook();
    const sheet = workbook.Worksheets.get(0);

    // Add a double-arrow line - solid blue
    let line = sheet.TypedLines.AddLine();
    line.Top = 10;
    line.Left = 20;
    line.Width = 100;
    line.Height = 0;
    line.Color = xlsModule.Color.get_Blue();
    line.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;

    // Add a single-arrow line - solid red
    let line_1 = sheet.TypedLines.AddLine();
    line_1.Top = 50;
    line_1.Left = 30;
    line_1.Width = 100;
    line_1.Height = 100;
    line_1.Color = xlsModule.Color.get_Red();
    line_1.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineNoArrow;
    line_1.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;

    // Add an elbow arrow connector
    let line3 = sheet.TypedLines.AddLine();
    line3.LineShapeType = xlsModule.LineShapeType.ElbowLine;
    line3.Width = 30;
    line3.Height = 50;
    line3.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line3.Top = 100;
    line3.Left = 50;

    // Add an elbow double-arrow connector
    let line2 = sheet.TypedLines.AddLine();
    line2.LineShapeType = xlsModule.LineShapeType.ElbowLine;
    line2.Width = 50;
    line2.Height = 50;
    line2.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line2.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line2.Left = 120;
    line2.Top = 100;

    // Add a curved arrow connector
    line3 = sheet.TypedLines.AddLine();
    line3.LineShapeType = xlsModule.LineShapeType.CurveLine;
    line3.Width = 30;
    line3.Height = 50;
    line3.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrowOpen;
    line3.Top = 100;
    line3.Left = 200;

    // Add a curved double-arrow connector
    line2 = sheet.TypedLines.AddLine();
    line2.LineShapeType = xlsModule.LineShapeType.CurveLine;
    line2.Width = 30;
    line2.Height = 50;
    line2.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrowOpen;
    line2.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrowOpen;
    line2.Left = 250;
    line2.Top = 100;

    // Save the workbook
    const outputFileName = 'AddArrowLines.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the saved file from the VFS and trigger the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Add Arrow Lines</h1>
      <button onClick={addArrowLines}>Start</button>
    </div>
  );
}

export default App;

Шесть линий со стрелками: двойная стрелка, одинарная стрелка, угловая стрелка, угловая двойная стрелка, изогнутая стрелка и изогнутая двойная стрелка

Insert arrow-tipped lines

Обратите внимание на повторное использование переменных line3 и line2 во второй половине функции. Каждый вызов TypedLines.AddLine() возвращает новый объект линии, который уже добавлен на рабочий лист — переменная является дескриптором для задания свойств, а не контейнером, который нужно сохранять. Повторное использование имени переменной для следующей линии безопасно, потому что предыдущая линия уже добавлена в коллекцию фигур листа.


Управление существующими линиями

Рабочий лист, который уже содержит линии — добавленные вашим кодом, импортированные из файла или нарисованные пользователем — предоставляет к ним доступ через коллекцию sheet.Shapes. Каждую фигуру можно получить по индексу и изменить через её свойства:

// Get the first shape in the worksheet
let shape = sheet.Shapes.get(0);
// Modify its properties — color, dash style, etc.
shape.Color = xlsModule.Color.get_Red();

Для удаления sheet.Shapes.Remove(index) удаляет фигуру по указанному индексу. Чтобы удалять линии выборочно — по имени, по типу или по положению — переберите коллекцию и удалите подходящие фигуры. При удалении в цикле удаляйте с последнего индекса вниз, поскольку удаление элемента сдвигает индексы всех элементов после него.


Типичные проблемы

Наконечник стрелки не отображается. BeginArrowHeadStyle или EndArrowHeadStyle не был задан или был установлен в LineNoArrow. Проверьте, на каком конце вы ожидаете стрелку, и присвойте соответствующее свойство. Линия, у которой не задано ни одно из свойств, не имеет стрелок ни на одном конце.

Линия отображается в неправильном положении. Top и Left задаются в пикселях, а не в строках и столбцах. Значение Top = 10 размещает линию на расстоянии 10 пикселей от верхнего края листа, а не в строке 10. Если вы привыкли к API Lines.AddLine(), это наиболее частая причина неправильного размещения.

Угловой соединитель изгибается не в ту сторону. Направление изгиба зависит от знаков и относительных величин Width и Height. Положительные Width и Height дают изгиб вправо-вниз. Измените знак или поменяйте два значения местами, чтобы изменить изгиб. Сначала протестируйте с небольшими значениями.

Изогнутая линия изгибается не так, как я ожидал. CurveLine через TypedLines рисует плавную дугу между начальной и конечной точками, и на форму дуги влияют Width и Height. В отличие от углового соединителя, у которого один изгиб под прямым углом, кривая непрерывна — но её точный путь зависит от размеров, поэтому проверьте результат, прежде чем полагаться на него для точной разметки.


Часто задаваемые вопросы

В чём разница между LineArrow и LineArrowOpen?

LineArrow рисует залитый треугольный наконечник стрелки. LineArrowOpen рисует открытый V-образный наконечник стрелки — два штриха без заливки. Открытый стиль часто встречается в диаграммах потоков данных и диаграммах «сущность-связь», где стрелка указывает направление, не подразумевая конкретного механизма.

Могу ли я задать разные стили стрелок на двух концах?

Да. BeginArrowHeadStyle и EndArrowHeadStyle — независимые свойства. Линия с LineArrow на одном конце и LineArrowOpen на другом допустима и сообщает, что одно направление определённое, а другое — предположительное.

Как пиксельные координаты соотносятся с разметкой рабочего листа?

Пиксельные координаты отсчитываются от верхнего левого угла рабочего листа. Высота строк и ширина столбцов в Excel измеряются в пунктах и символах соответственно, поэтому для преобразования между позициями ячеек и пиксельными координатами необходимо учитывать текущую высоту строк и ширину столбцов. Для линий, которые должны выравниваться по границам ячеек, Lines.AddLine() с параметрами строк и столбцов может оказаться проще.

Могу ли я смешивать Lines.AddLine() и TypedLines.AddLine() в одном рабочем листе?

Да. Оба API добавляют фигуры в коллекцию фигур одного и того же рабочего листа. Рабочий лист может одновременно содержать базовые фигуры линий и линии со стрелками.

Требуется ли для этого установленный Excel?

Нет. Движок работает как WebAssembly в браузере. Линии и стрелки записываются как стандартные объекты фигур в XML рабочего листа, и Excel отображает их нативно при открытии файла.


См. также