
Линия между двумя блоками на блок-схеме говорит «они связаны». Стрелка от одного к другому говорит «этот идёт первым». Именно это различие — направление — отличает соединитель от декоративного элемента, и это единственное, что базовый 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-образная форма, а не залитый треугольник — на любом из концов. Смешивание стилей на двух концах допустимо: залитая стрелка на одном конце и открытая на другом сообщает, что одно направление определённое, а другое — предположительное.
Вставка линий со стрелками
В примере в новый рабочий лист вставляются шесть линий со стрелками, охватывающих распространённые комбинации: линия с двойной стрелкой, линия с одной стрелкой, угловой соединитель со стрелкой, угловой соединитель с двойной стрелкой, изогнутый соединитель со стрелкой и изогнутый соединитель с двойной стрелкой. Шаги следующие:
- Создайте объект
Workbookи получите первый рабочий лист. - Вызовите
Worksheet.TypedLines.AddLine()для создания каждой линии. - Задайте положение линии через
Top,Left,WidthиHeight(в пикселях). - Задайте стили стрелок на обоих концах через
BeginArrowHeadStyleиEndArrowHeadStyle. - Укажите тип линии через
LineShapeType(прямая, угловая, изогнутая и т. д.). - Сохраните книгу с помощью
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;
Шесть линий со стрелками: двойная стрелка, одинарная стрелка, угловая стрелка, угловая двойная стрелка, изогнутая стрелка и изогнутая двойная стрелка

Обратите внимание на повторное использование переменных 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 отображает их нативно при открытии файла.