
Stellen Sie sich eine Vertragsvorlage vor, die an Dutzende von Kunden versendet wird. Das Rechtsteam hat jede Klausel sorgfältig ausgearbeitet, und die einzigen Dinge, die jeder Empfänger anfassen sollte, sind der Unterschriftsblock, der Projektname und das Annahmedatum. Geben Sie ihnen eine vollständig bearbeitbare Word-Datei, und irgendjemand wird unweigerlich eine Vertragsstrafenklausel umformulieren oder einen Haftungsabschnitt löschen. Sperren Sie das gesamte Dokument, und niemand kann die Felder überhaupt ausfüllen. Was Sie wirklich brauchen, ist selektives Bearbeiten — eine Möglichkeit zu sagen: „Diese bestimmten Absätze sind freigegeben, alles andere ist eingefroren.“
Genau das ermöglichen Ihnen bearbeitbare Bereiche. Sie schützen das gesamte Dokument als schreibgeschützt und setzen dann ein Paar Berechtigungsmarkierungen um die Absätze, die Sie offen halten möchten. Jeder, der die Datei in Word öffnet, kann innerhalb des markierten Bereichs tippen, aber außerhalb davon kein einziges Zeichen ändern. Spire.Doc for JavaScript bringt diese Funktion über WebAssembly in den Browser, sodass Sie geschützte Dokumente aus einer React-App ohne Server-Roundtrip erzeugen können — Schriftarten und Eingabedateien werden über ein virtuelles In-Memory-Dateisystem (VFS) verwaltet.
Dieser Leitfaden behandelt beide Hälften des Workflows:
- Einen bearbeitbaren Bereich festlegen — das Dokument schützen und den offenen Bereich markieren
- Einen bearbeitbaren Bereich entfernen — die Markierungen entfernen und die Einschränkung aufheben
Wenn Sie Spire.Doc noch nicht in Ihr Projekt eingebunden haben, beginnen Sie mit Integrating Spire.Doc for JavaScript in a React Project. Die folgenden Snippets gehen davon aus, dass das WebAssembly-Modul geladen und bereit ist.
Einen bearbeitbaren Bereich festlegen
Der Prozess hat drei Phasen. Zuerst laden Sie die Schriftartdateien und das Ziel-Word-Dokument mit FetchFileToVFS in das virtuelle WASM-Dateisystem. Als Nächstes instanziieren Sie ein Document, laden die Datei, rufen Protect auf, um das gesamte Dokument als schreibgeschützt zu sperren, und erstellen dann ein Paar aus PermissionStart / PermissionEnd, das dieselbe id teilt — diese beiden Markierungen umschließen den Absatz, den Sie bearbeitbar lassen möchten. Abschließend speichern Sie die Datei, lesen sie aus dem VFS zurück, verpacken sie in einen Blob und lösen einen Download aus.
function App() {
const SetEditableRange = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the input document into VFS
const inputFileName = "SetEditableRange.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);
// Create a document object and load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Protect the whole document: everything outside the editable range is read-only
doc.Protect({ type: docModule.ProtectionType.AllowOnlyReading, password: "password" });
// Create the permission markers: a start and an end with the same id form one editable range
const start = new docModule.PermissionStart(doc, "testID");
const end = new docModule.PermissionEnd(doc, "testID");
// Insert the markers into the first paragraph: the start at the beginning, the end appended at the end
doc.Sections.get_Item(0).Paragraphs.get_Item(0).ChildObjects.Insert(0, start);
doc.Sections.get_Item(0).Paragraphs.get_Item(0).ChildObjects.Add(end);
// Save the document
const outputFileName = "Set Editable Range.docx";
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>Set Editable Range in a Word Document</h1>
<button onClick={SetEditableRange}>
Generate
</button>
</div>
);
}
export default App;
In der Beispieldatei tragen die Felder, die ein Prüfer ausfüllen darf, eine leichte Schattierung — das ist lediglich ein visueller Hinweis für den Leser und hat keinen Einfluss darauf, wie der bearbeitbare Bereich im Code definiert wird. Sobald die Markierungen platziert sind, behandelt Word den schattierten Absatz als bearbeitbar und jeden anderen Absatz als gesperrt.

Einen bearbeitbaren Bereich entfernen
Das Entfernen des bearbeitbaren Bereichs ist eine einzige Durchquerung: Sie durchlaufen jeden Abschnitt und jeden Absatz, prüfen jedes Objekt in der ChildObjects-Sammlung des Absatzes und ziehen alles heraus, was ein PermissionStart oder PermissionEnd ist.
Eine Feinheit überrascht viele: ChildObjects.Remove verkleinert die Sammlung sofort, sodass jedes Element nach dem entfernten um einen Index nach vorne rutscht. Wenn Sie Ihren Schleifenzähler beim Löschen erhöhen, wird bei jeder Entfernung genau die nächste Markierung übersprungen — und je mehr Markierungen Sie haben, desto mehr Überbleibsel bleiben zurück.
function App() {
const RemoveEditableRange = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the input document into VFS
const inputFileName = "RemoveEditableRange.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);
// Create a document object and load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Iterate over every section and paragraph and delete the permission markers
for (let i = 0; i < doc.Sections.Count; i++) {
const section = doc.Sections.get_Item(i);
for (let j = 0; j < section.Body.Paragraphs.Count; j++) {
const paragraph = section.Body.Paragraphs.get_Item(j);
// Remove on a match; the collection shrinks, so the index is not incremented
for (let k = 0; k < paragraph.ChildObjects.Count;) {
const obj = paragraph.ChildObjects.get_Item(k);
if (obj instanceof docModule.PermissionStart || obj instanceof docModule.PermissionEnd) {
paragraph.ChildObjects.Remove(obj);
} else {
k++;
}
}
}
}
// Save the document
const outputFileName = "Remove Editable Range.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
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 Editable Ranges from a Word Document</h1>
<button onClick={RemoveEditableRange}>
Generate
</button>
</div>
);
}
export default App;
Das Löschen der Markierungen verschiebt nur die Grenze dessen, was bearbeitbar ist — der Text selbst und die gesamte Formatierung bleiben unberührt.

Der vollständige Schutz-Lebenszyklus
In einem realen Genehmigungsworkflow tun Sie selten nur eine einzige Sache. Ein typischer Durchlauf sieht so aus:
-
Schützen — Rufen Sie
doc.ProtectmitAllowOnlyReading(oderAllowOnlyFormFields) und einem Kennwort auf. Das gesamte Dokument ist nun gesperrt. -
Markieren — Umschließen Sie jeden für Prüfer bearbeitbaren Absatz mit einem Paar aus
PermissionStart/PermissionEnd, das eine id teilt. Diese Bereiche werden zu den einzigen Stellen, an denen ein Prüfer tippen kann. - Markierung entfernen — Wenn die Prüfungsrunde vorbei ist, durchlaufen Sie das Dokument und entfernen jede Berechtigungsmarkierung. Die Bereiche fügen sich wieder in den schreibgeschützten Hauptteil ein.
-
Schutz aufheben — Rufen Sie
doc.Unprotect("password")auf, um das Dokument vollständig freizugeben und es für die nächste Verarbeitungsphase wieder in einen vollständig bearbeitbaren Zustand zu versetzen.
Die entscheidende Erkenntnis ist, dass Schutz und bearbeitbare Bereiche zwei unabhängige Ebenen sind. Der Schutz entscheidet, ob das Dokument überhaupt gesperrt ist; das Markierungspaar entscheidet, welche kleinen Bereiche von dieser Sperre ausgenommen sind. Sie können Markierungen beliebig oft hinzufügen und entfernen, ohne den Schutzstatus zu berühren, und Sie können den Schutz ein- oder ausschalten, ohne die Markierungen zu stören — aber die Markierungen haben nur dann Wirkung, wenn der Schutz aktiv ist.
FAQ
Der bearbeitbare Bereich ist festgelegt, aber der Inhalt darin kann trotzdem nicht bearbeitet werden
Warum das passiert: Berechtigungsmarkierungen sind für sich genommen wirkungslos. Sie schaffen lediglich Ausnahmen von einer dokumentweiten Einschränkung. Wenn Protect also nie aufgerufen wurde, gibt es keine Einschränkung, von der ausgenommen werden könnte, und die Markierungen bewirken nichts. Eine zweite Voraussetzung ist, dass PermissionStart und PermissionEnd dieselbe id-Zeichenfolge tragen müssen — Word behandelt sie nur dann als Paar, wenn die ids übereinstimmen.
Lösung: Aktivieren Sie zuerst die Bearbeitungseinschränkung und erstellen Sie dann beide Markierungen mit einer identischen id:
// Enable protection first so that the markers mean something
document.Protect({ type: wasmModule.ProtectionType.AllowOnlyReading, password: "password" });
// The start and the end must use the same id
const start = new wasmModule.PermissionStart(document, "testID");
const end = new wasmModule.PermissionEnd(document, "testID");
Beim Entfernen bearbeitbarer Bereiche werden einige Markierungen übersehen
Warum das passiert: Jeder Aufruf von ChildObjects.Remove verkleinert die Sammlung um eins und verschiebt den Index jedes nachfolgenden Elements nach unten. Wenn der Schleifenzähler im selben Durchlauf wie eine Entfernung erhöht wird, wird das Element, das an die aktuelle Position gerutscht ist, nie geprüft — es wird übersprungen, und das Problem verstärkt sich mit jeder weiteren Markierung.
Lösung: Halten Sie den Index beim Entfernen entweder stabil (erhöhen Sie ihn nur, wenn keine Entfernung stattgefunden hat) oder sammeln Sie die Zielobjekte zuerst und löschen Sie sie in umgekehrter Reihenfolge:
for (let k = 0; k < paragraph.ChildObjects.Count;) {
const obj = paragraph.ChildObjects.get_Item(k);
if (obj instanceof wasmModule.PermissionStart || obj instanceof wasmModule.PermissionEnd) {
paragraph.ChildObjects.Remove(obj);
// Do not increment k here: check the new object at the current index
} else {
k++;
}
}
Das Dokument ist nach dem Entfernen der Markierungen weiterhin schreibgeschützt
Warum das passiert: Die Markierungen definieren nur, welche Bereiche von der Sperre ausgenommen sind — sie sind nicht die Sperre selbst. Ihr Entfernen hebt lediglich die Ausnahmen auf; der zugrunde liegende Schutz, den Protect eingerichtet hat, ist weiterhin in Kraft, sodass das gesamte Dokument schreibgeschützt bleibt.
Lösung: Sobald die Markierungen entfernt sind und Sie die Einschränkung nicht mehr benötigen, rufen Sie Unprotect mit dem ursprünglichen Kennwort auf:
document.Unprotect("password");