
Каждый, кому доводилось форматировать длинный документ Word в браузере, знает эту боль: заголовок раздела остаётся одиноко висеть внизу страницы, а его основной текст начинается на следующей, или же вставленное из другого файла содержимое тянет за собой целую цепочку нежелательных пустых страниц. Обе проблемы почти всегда связаны с разрывами страниц — либо их нет там, где они должны быть, либо они остались там, где их быть не должно.
Spire.Doc for JavaScript полностью работает в браузере через WebAssembly, используя виртуальную файловую систему (VFS) для операций ввода-вывода файлов. Это значит, что вы можете вставлять и удалять разрывы страниц без каких-либо обращений к серверу. В этом руководстве рассматриваются обе операции и два особых случая, которые часто возникают при работе с реальными документами:
- Вставить разрыв страницы в определённом абзаце
- Удалить все разрывы страниц за один проход
- Исправить лишнюю пустую строку, появляющуюся после вставки разрыва
- Исправить документ, который всё ещё разбивается на страницы после удаления разрывов
По вопросам установки и настройки проекта обратитесь к разделу Интеграция Spire.Doc for JavaScript в проект React. Примеры ниже предполагают, что модуль WASM уже инициализирован.
Вставка разрыва страницы в определённом абзаце
Процесс состоит из трёх шагов: загрузите целевой документ в виртуальную файловую систему WASM с помощью FetchFileToVFS, откройте его как объект Document, затем найдите абзац, в котором нужно сделать разрыв, и вызовите AppendBreak с BreakType.PageBreak. Разрыв добавляется как дочерний объект в конец этого абзаца, поэтому всё после него переносится на следующую страницу. Наконец, прочитайте сохранённый файл из VFS, оберните его в Blob и инициируйте скачивание в браузере.
function App() {
const InsertPageBreak = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the target Word document into VFS
const inputFileName = "Template_Docx_1.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);
// Create a Document instance and load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Locate the fourth paragraph of the first section and append a page break to its end
doc.Sections.get_Item(0).Paragraphs.get_Item(3).AppendBreak(docModule.BreakType.PageBreak);
// Define the output file name
const outputFileName = "InsertPageBreak_out.docx";
// Save the document to VFS
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
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>Insert a Page Break into a Word Document</h1>
<button onClick={InsertPageBreak}>Generate</button>
</div>
);
}
export default App;
Документ после добавления разрыва страницы в конец четвёртого абзаца

Удаление всех разрывов страниц за один проход
Когда в документе накапливаются разрывы страниц из-за многократного редактирования или операций копирования и вставки, часто требуется удалить их все и позволить содержимому перестроиться естественным образом. Подход таков: переберите все абзацы в целевом разделе и проверьте каждый дочерний объект. Если дочерний объект определён как Break с BreakType.PageBreak, удалите его с помощью ChildObjects.Remove.
Важная деталь во внутреннем цикле — дочерние объекты перебираются в обратном порядке, от последнего индекса до нуля. Удаление элемента из коллекции, обходимой в прямом порядке, сдвигает индексы всех последующих элементов, что может привести к пропуску элементов или выходу за границы. Обратный обход полностью устраняет эту проблему, поскольку каждое удаление затрагивает только уже обработанные индексы.
function App() {
const RemovePageBreaks = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the target Word document into VFS
const inputFileName = "Template_Docx_4.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);
// Create a Document instance and load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section
const section = doc.Sections.get_Item(0);
// Walk through every paragraph in the section
for (let j = 0; j < section.Paragraphs.Count; j++) {
const p = section.Paragraphs.get_Item(j);
// Walk the paragraph's child objects backwards, so that removing an element does not shift the indices still to come
for (let i = p.ChildObjects.Count - 1; i >= 0; i--) {
const obj = p.ChildObjects.get_Item(i);
// Test whether the object is a page break
if (obj.DocumentObjectType == docModule.DocumentObjectType.Break
&& obj.BreakType == docModule.BreakType.PageBreak) {
// Remove the page break from the paragraph
p.ChildObjects.Remove(obj);
}
}
}
// Define the output file name
const outputFileName = "RemovePageBreaks_out.docx";
// Save the document to VFS
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
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>Remove Page Breaks from a Word Document</h1>
<button onClick={RemovePageBreaks}>Generate</button>
</div>
);
}
export default App;
Документ после удаления всех разрывов страниц

Лишняя пустая строка после вставки разрыва страницы
После вызова AppendBreak вы можете заметить нежелательную пустую полосу в верхней части новой страницы. Это происходит потому, что AppendBreak прикрепляет разрыв к концу целевого абзаца, и настройка «интервал после» этого абзаца переносится на начало следующей страницы. Когда включён автоматический интервал, промежуток даже масштабируется вместе с размером шрифта — это особенно заметно после крупных заголовков.
Решение — обнулить конечный интервал абзаца перед добавлением разрыва:
const para = document.Sections.get_Item(0).Paragraphs.get_Item(3);
// Turn off automatic spacing after the paragraph and set the space after it to 0
para.Format.AfterAutoSpacing = false;
para.Format.AfterSpacing = 0;
// Then insert the page break
para.AppendBreak(wasmModule.BreakType.PageBreak);
Установка AfterAutoSpacing в false и AfterSpacing в 0 гарантирует, что абзац не добавит вертикального промежутка после разрыва, поэтому новая страница начнётся ровно от верхнего поля.
Документ всё ещё разбивается на страницы после удаления разрывов
Даже после успешного удаления всех объектов разрывов страниц документ может по-прежнему разбиваться в тех же местах. Причина: разбиение на страницы также может возникать из-за свойства уровня абзаца под названием «разрыв страницы перед». Когда этот флаг установлен для абзаца, этот абзац всегда начинается с новой страницы — независимо от того, существует ли объект Break. Приведённый выше цикл удаления нацелен только на объекты разрывов, поэтому абзацы с этим флагом остаются нетронутыми.
Чтобы полностью устранить принудительное разбиение на страницы, сбросьте флаг PageBreakBefore для каждого абзаца вместе с очисткой объектов разрывов:
const section = document.Sections.get_Item(0);
for (let j = 0; j < section.Paragraphs.Count; j++) {
const p = section.Paragraphs.get_Item(j);
// Clear the page-break-before property set on the paragraph
if (p.Format.PageBreakBefore) {
p.Format.PageBreakBefore = false;
}
}
Вы можете выполнить этот цикл в том же проходе, что и удаление объектов разрывов, или отдельным этапом после него — порядок не важен, поскольку эти две операции воздействуют на независимые свойства.
Часто задаваемые вопросы
Как получить бесплатную лицензию для Spire.Doc for JavaScript?
Spire.Doc for JavaScript предлагает 30-дневную полнофункциональную бесплатную пробную лицензию без ограничений по функциональности. Вы можете оставить заявку здесь, чтобы оценить продукт перед покупкой.