The document after a solid color background is set via Background.Color

Chaque contrat, lettre officielle et support de marque porte une identité visuelle implicite. Une page blanche ordinaire fait l'affaire, mais elle ne dit rien de l'organisation qui se trouve derrière. Dès que vous ajoutez une teinte douce, un subtil dégradé à deux tons ou une image d'arrière-plan répétée, l'ensemble du document passe d'un fichier générique à un artefact de marque reconnaissable — et vos lecteurs le remarquent, même s'ils ne savent pas l'exprimer.

Spire.Doc pour JavaScript apporte ce style visuel directement dans le navigateur via WebAssembly. Aucun aller-retour serveur, aucune dépendance à l'automatisation Office et aucune installation de bureau requise. Vous chargez un fichier Word dans le système de fichiers virtuel (VFS) WASM, choisissez l'un des trois modes d'arrière-plan et exportez le document stylisé — le tout côté client dans une application React.

Ce guide présente chacune des trois options d'arrière-plan non pas comme un catalogue d'API, mais comme un ensemble de décisions de conception. Nous commençons par une comparaison rapide afin que vous puissiez associer la bonne technique à votre cas d'usage, puis nous examinons en détail l'implémentation de chacune.


Trois approches d'arrière-plan en un coup d'œil

Avant d'écrire du code, il est utile de comprendre ce que chaque type d'arrière-plan apporte d'un point de vue de conception. Le tableau ci-dessous résume le résultat visuel, la quantité de configuration nécessaire et les scénarios dans lesquels chaque approche se distingue.

Approche Effet visuel Effort de configuration Idéal pour
Couleur unie Une couleur unique et uniforme remplit chaque page Faible — définissez BackgroundType.Color et attribuez une couleur Contrats, notes internes, lettres officielles nécessitant une teinte de base propre et professionnelle
Dégradé Un mélange directionnel de deux couleurs sur toute la page Moyen — définissez Color1, Color2, ainsi que ShadingStyle et ShadingVariant Pages de couverture, certificats, modèles marketing qui bénéficient d'une profondeur subtile
Image Une image d'arrière-plan répétée sur toute la page Moyen — chargez l'image dans le VFS, puis appelez SetPicture Papeterie de marque, en-têtes avec éléments décoratifs, modèles de documents à thème

Les trois partagent le même flux de travail global : chargez le document source dans le VFS, configurez la propriété Background sur une instance Document, enregistrez le résultat et déclenchez un téléchargement dans le navigateur. Les différences résident entièrement dans la manière dont vous configurez cette propriété Background — c'est là que les choix de conception entrent en jeu.

Pour la configuration du projet et les instructions d'installation, consultez Intégration de Spire.Doc pour JavaScript dans un projet React. Les exemples de code ci-dessous supposent que le module WASM est déjà initialisé et disponible sur window.wasmModule.


Arrière-plan de couleur unie

Une couleur unie est le choix d'arrière-plan le plus sobre — et souvent le plus efficace. Un crème chaud ou un gris pâle derrière un texte noir réduit la fatigue oculaire sans attirer l'attention. Pour les documents formels comme les contrats et les documents de politique, une teinte subtile signale « ce document appartient à une organisation spécifique » sans tomber dans la décoration.

L'implémentation suit trois étapes claires. Premièrement, utilisez FetchFileToVFS pour charger le fichier Word cible (et les fichiers de police) dans le système de fichiers virtuel WASM. Deuxièmement, créez un Document, chargez le fichier, définissez Background.Type sur BackgroundType.Color et attribuez une couleur intégrée à Background.Color. Troisièmement, enregistrez le document dans le VFS avec SaveToFile, lisez le fichier résultant sous forme de tableau d'octets, encapsulez-le dans un Blob et lancez un téléchargement.

function App() {
  const SetSolidColorBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Color
    doc.Background.Type = docModule.BackgroundType.Color;

    // Set the background color
    doc.Background.Color = docModule.Color.get_LightYellow();

    // Define the output file name
    const outputFileName = "SetSolidColorBackground_out.docx";

    // Save the document to the specified path
    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 a Solid Color Background for a Word Document</h1>
      <button onClick={SetSolidColorBackground}>Generate</button>
    </div>
  );
}
export default App;

Une fois Background.Color appliqué, chaque page du document est remplie avec la couleur intégrée choisie — dans ce cas, LightYellow.

The document after a solid color background is set via Background.Color


Arrière-plan dégradé

Les dégradés introduisent une sensation de dimension que les couleurs unies ne peuvent pas offrir. Une transition de haut en bas du blanc au bleu pâle, par exemple, évoque le ciel et l'ouverture — utile pour les certificats, les lettres de distinction ou tout document où une touche de solennité est appropriée. La clé est la retenue : choisissez deux couleurs proches et laissez le dégradé faire son travail discrètement.

Le code reprend le flux de travail de la couleur unie, mais l'étape intermédiaire s'étoffe. Après avoir défini Background.Type sur BackgroundType.Gradient, vous récupérez l'objet dégradé via Background.Gradient et configurez quatre propriétés : Color1 (couleur de début), Color2 (couleur de fin), ShadingVariant (direction de transition) et ShadingStyle (axe du dégradé).

function App() {
  const SetGradientBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Gradient
    doc.Background.Type = docModule.BackgroundType.Gradient;
    let gradient = doc.Background.Gradient;

    // Set the start color and the end color of the gradient
    gradient.Color1 = docModule.Color.get_White();
    gradient.Color2 = docModule.Color.get_LightBlue();

    // Set the shading style and variant of the gradient
    gradient.ShadingVariant = docModule.GradientShadingVariant.ShadingDown;
    gradient.ShadingStyle = docModule.GradientShadingStyle.Horizontal;

    // Define the output file name
    const outputFileName = "SetGradientBackground_out.docx";

    // Save the document to the specified path
    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 a Gradient Background for a Word Document</h1>
      <button onClick={SetGradientBackground}>Generate</button>
    </div>
  );
}
export default App;

Après avoir appliqué Background.Gradient, la page est remplie d'une transition horizontale fluide du blanc au bleu clair, s'écoulant vers le bas.

The document after a gradient background is set via Background.Gradient


Arrière-plan avec image

Un arrière-plan avec image est l'option la plus expressive. Qu'il s'agisse d'un motif de filigrane subtil, d'une texture d'entreprise ou d'un motif décoratif pour des programmes d'événements, une image répétée peut porter des éléments de marque que la couleur et le dégradé ne peuvent tout simplement pas transmettre. Le compromis est le poids du fichier — l'image doit être chargée dans le VFS en même temps que le document — alors réservez cette approche aux modèles où le rendu visuel justifie la ressource supplémentaire.

La configuration diffère des deux méthodes précédentes d'une manière importante : l'image d'arrière-plan doit également être chargée dans le VFS à l'aide de FetchFileToVFS avant de pouvoir être référencée. Une fois le document et l'image dans le VFS, définissez Background.Type sur BackgroundType.Picture et appelez Background.SetPicture avec le chemin VFS de l'image. L'image est alors répétée sur chaque page en tant qu'arrière-plan.

function App() {
  const SetImageBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName1 = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName1, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load the background image into the virtual file system (VFS)
    let inputFileName2 = "Background.png";
    await window.spire.FetchFileToVFS(inputFileName2, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load a Word document
    let doc = new docModule.Document();
    doc.LoadFromFile(inputFileName1);

    // Set the background type as Picture
    doc.Background.Type = docModule.BackgroundType.Picture;

    // Set the background picture
    doc.Background.SetPicture(inputFileName2);

    // Define the output file name
    const outputFileName = "SetImageBackground_out.docx";

    // Save the document to the specified path
    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 a Picture Background in a Word Document</h1>
      <button onClick={SetImageBackground}>Generate</button>
    </div>
  );
}
export default App;

Après avoir appelé Background.SetPicture, l'image spécifiée est répétée sur toute la surface de la page comme arrière-plan du document.

The document after a picture background is set via Background.SetPicture


Considérations d'impression

Il existe une mise en garde pratique qui prend de nombreux développeurs au dépourvu : Microsoft Word n'imprime pas les arrière-plans de page par défaut. Ce n'est pas un bug dans votre code ni une limitation de Spire.Doc — l'arrière-plan est correctement stocké dans le document et s'affiche normalement à l'écran. Word l'omet simplement de la sortie imprimée, sauf si vous lui indiquez explicitement le contraire.

Pour que les arrière-plans apparaissent sur les copies imprimées, l'utilisateur final doit activer un paramètre spécifique dans son client Word :

  1. Ouvrez le document dans Microsoft Word.
  2. Accédez à Fichier > Options > Affichage.
  3. Cochez Imprimer les couleurs et les images d'arrière-plan.
  4. Imprimez comme d'habitude.

Si vous avez besoin que l'arrière-plan s'affiche dans tous les environnements de sortie, quels que soient les paramètres Word du lecteur, envisagez une approche alternative : placez une forme pleine page dans l'en-tête du document ou utilisez un filigrane pour simuler l'effet d'arrière-plan. Ces techniques sont traitées comme du contenu plutôt que comme une mise en forme de page, de sorte qu'elles s'impriment de manière fiable dans toutes les configurations.


FAQ

Pourquoi l'arrière-plan n'apparaît-il pas lorsque j'imprime le document ?

Il s'agit d'un comportement attendu. Word supprime les arrière-plans de page dans la sortie imprimée par défaut — le paramètre est correctement stocké et s'affiche à l'écran, mais les options d'impression du client Word le filtrent. L'arrière-plan n'a pas été perdu ; il n'est simplement pas inclus dans le flux d'impression.

Pour corriger cela, activez Imprimer les couleurs et les images d'arrière-plan sous Fichier > Options > Affichage dans Word avant d'imprimer. Pour les environnements où vous ne pouvez pas contrôler les paramètres d'impression du lecteur, utilisez une forme pleine page dans l'en-tête ou un filigrane pour reproduire l'effet visuel, car ces éléments sont traités comme du contenu imprimable.

Pourquoi l'arrière-plan avec image n'a-t-il aucun effet ?

Cela se produit généralement pour l'une des deux raisons suivantes : soit Background.Type n'a pas été défini sur BackgroundType.Picture avant d'appeler SetPicture, soit le fichier image n'a jamais été chargé dans le VFS via FetchFileToVFS, de sorte que SetPicture ne peut pas le localiser.

Assurez-vous de définir d'abord le type d'arrière-plan et de transmettre le nom de fichier exact d'une image déjà chargée dans le système de fichiers virtuel :

document.Background.Type = wasmModule.BackgroundType.Picture;
document.Background.SetPicture("Background.png");

Voir aussi

The document after a solid color background is set via Background.Color

Cada contrato, carta oficial y pieza de material de marca conlleva una identidad visual implícita. Una página blanca simple cumple su función, pero no dice nada sobre la organización que la respalda. En el momento en que añades un tinte suave, un sutil degradado de dos tonos o una imagen de fondo en mosaico, todo el documento pasa de ser un archivo genérico a un artefacto de marca reconocible, y tus lectores lo notan, aunque no sepan explicar por qué.

Spire.Doc for JavaScript lleva este estilo visual directamente al navegador a través de WebAssembly. No hay ida y vuelta al servidor, ni dependencia de automatización de Office, ni requisito de instalación en el escritorio. Cargas un archivo de Word en el sistema de archivos virtual (VFS) de WASM, eliges uno de los tres modos de fondo y exportas el documento con estilo, todo del lado del cliente en una aplicación React.

Esta guía recorre cada una de las tres opciones de fondo no como un catálogo de API, sino como un conjunto de decisiones de diseño. Comenzamos con una comparación rápida para que puedas relacionar la técnica adecuada con tu caso de uso, y luego profundizamos en los detalles de implementación de cada una.


Tres enfoques de fondo de un vistazo

Antes de escribir cualquier código, ayuda entender qué aporta cada tipo de fondo desde una perspectiva de diseño. La siguiente tabla resume el resultado visual, la cantidad de configuración necesaria y los escenarios en los que destaca cada enfoque.

Enfoque Efecto visual Esfuerzo de configuración Ideal para
Color sólido Un único color uniforme rellena cada página Bajo: establece BackgroundType.Color y asigna un color Contratos, memorandos internos, cartas oficiales que necesitan un tono base limpio y profesional
Degradado Una mezcla direccional de dos colores a través de la página Medio: define Color1, Color2, además de ShadingStyle y ShadingVariant Portadas, certificados, plantillas de marketing que se benefician de una profundidad sutil
Imagen Una imagen de fondo en mosaico por toda la página Medio: carga la imagen en el VFS y luego llama a SetPicture Papelería de marca, membretes con elementos decorativos, plantillas de documentos temáticas

Los tres comparten el mismo flujo de trabajo general: carga el documento de origen en el VFS, configura la propiedad Background en una instancia de Document, guarda el resultado y activa una descarga en el navegador. Las diferencias residen enteramente en cómo configuras esa propiedad Background, que es donde entran las decisiones de diseño.

Para obtener instrucciones de configuración e instalación del proyecto, consulta Integración de Spire.Doc for JavaScript en un proyecto de React. Los ejemplos de código a continuación asumen que el módulo WASM ya está inicializado y disponible en window.wasmModule.


Fondo de color sólido

Un color sólido es la opción de fondo más sobria, y a menudo la más eficaz. Un tono crema cálido o gris pálido detrás de texto negro reduce la fatiga visual sin competir por la atención. Para documentos formales como contratos y documentos de políticas, un tinte sutil indica "este documento pertenece a una organización específica" sin llegar a ser decorativo.

La implementación sigue tres pasos claros. Primero, usa FetchFileToVFS para cargar el archivo de Word objetivo (y los archivos de fuentes) en el sistema de archivos virtual de WASM. Segundo, crea un Document, carga el archivo, establece Background.Type en BackgroundType.Color y asigna un color integrado a Background.Color. Tercero, guarda el documento de nuevo en el VFS con SaveToFile, lee el archivo resultante como una matriz de bytes, envuélvelo en un Blob e inicia una descarga.

function App() {
  const SetSolidColorBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Color
    doc.Background.Type = docModule.BackgroundType.Color;

    // Set the background color
    doc.Background.Color = docModule.Color.get_LightYellow();

    // Define the output file name
    const outputFileName = "SetSolidColorBackground_out.docx";

    // Save the document to the specified path
    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 a Solid Color Background for a Word Document</h1>
      <button onClick={SetSolidColorBackground}>Generate</button>
    </div>
  );
}
export default App;

Una vez aplicado Background.Color, cada página del documento se rellena con el color integrado elegido; en este caso, LightYellow.

The document after a solid color background is set via Background.Color


Fondo degradado

Los degradados introducen una sensación de dimensión que los colores planos no pueden lograr. Una transición de arriba a abajo de blanco a azul pálido, por ejemplo, evoca el cielo y la apertura; es útil para certificados, cartas de reconocimiento o cualquier documento donde sea apropiado un toque de ceremonia. La clave está en la moderación: elige dos colores estrechamente relacionados y deja que el degradado haga su trabajo discretamente.

El código refleja el flujo de trabajo del color sólido, pero el paso intermedio se amplía. Después de establecer Background.Type en BackgroundType.Gradient, recuperas el objeto de degradado mediante Background.Gradient y configuras cuatro propiedades: Color1 (color inicial), Color2 (color final), ShadingVariant (dirección de la transición) y ShadingStyle (eje del degradado).

function App() {
  const SetGradientBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Gradient
    doc.Background.Type = docModule.BackgroundType.Gradient;
    let gradient = doc.Background.Gradient;

    // Set the start color and the end color of the gradient
    gradient.Color1 = docModule.Color.get_White();
    gradient.Color2 = docModule.Color.get_LightBlue();

    // Set the shading style and variant of the gradient
    gradient.ShadingVariant = docModule.GradientShadingVariant.ShadingDown;
    gradient.ShadingStyle = docModule.GradientShadingStyle.Horizontal;

    // Define the output file name
    const outputFileName = "SetGradientBackground_out.docx";

    // Save the document to the specified path
    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 a Gradient Background for a Word Document</h1>
      <button onClick={SetGradientBackground}>Generate</button>
    </div>
  );
}
export default App;

Después de aplicar Background.Gradient, la página se rellena con una transición horizontal suave de blanco a azul claro, que fluye hacia abajo.

The document after a gradient background is set via Background.Gradient


Fondo de imagen

Un fondo de imagen es la opción más expresiva. Ya sea un sutil patrón de marca de agua, una textura corporativa o un motivo decorativo para programas de eventos, una imagen en mosaico puede llevar elementos de marca que el color y el degradado simplemente no pueden. La contrapartida es el peso del archivo: la imagen debe cargarse en el VFS junto con el documento, así que reserva este enfoque para plantillas donde la recompensa visual justifique el recurso adicional.

La configuración difiere de los dos métodos anteriores en un aspecto importante: la imagen de fondo también debe cargarse en el VFS mediante FetchFileToVFS antes de poder referenciarla. Una vez que tanto el documento como la imagen están en el VFS, establece Background.Type en BackgroundType.Picture y llama a Background.SetPicture con la ruta de la imagen en el VFS. La imagen se coloca entonces en mosaico en todas las páginas como fondo.

function App() {
  const SetImageBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName1 = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName1, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load the background image into the virtual file system (VFS)
    let inputFileName2 = "Background.png";
    await window.spire.FetchFileToVFS(inputFileName2, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load a Word document
    let doc = new docModule.Document();
    doc.LoadFromFile(inputFileName1);

    // Set the background type as Picture
    doc.Background.Type = docModule.BackgroundType.Picture;

    // Set the background picture
    doc.Background.SetPicture(inputFileName2);

    // Define the output file name
    const outputFileName = "SetImageBackground_out.docx";

    // Save the document to the specified path
    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 a Picture Background in a Word Document</h1>
      <button onClick={SetImageBackground}>Generate</button>
    </div>
  );
}
export default App;

Después de llamar a Background.SetPicture, la imagen especificada se coloca en mosaico por toda la superficie de la página como fondo del documento.

The document after a picture background is set via Background.SetPicture


Consideraciones de impresión

Hay una advertencia práctica que toma por sorpresa a muchos desarrolladores: Microsoft Word no imprime los fondos de página de forma predeterminada. Esto no es un error en tu código ni una limitación de Spire.Doc; el fondo se almacena correctamente en el documento y se muestra normalmente en pantalla. Word simplemente lo omite en la salida impresa a menos que le indiques explícitamente lo contrario.

Para garantizar que los fondos aparezcan en las copias impresas, el usuario final debe habilitar una configuración específica en su cliente de Word:

  1. Abre el documento en Microsoft Word.
  2. Ve a Archivo > Opciones > Mostrar.
  3. Marca Imprimir colores e imágenes de fondo.
  4. Imprime como de costumbre.

Si necesitas que el fondo se represente en todos los entornos de salida, independientemente de la configuración de Word del lector, considera un enfoque alternativo: coloca una forma de página completa en el encabezado del documento o usa una marca de agua para simular el efecto de fondo. Estas técnicas se tratan como contenido en lugar de formato de página, por lo que se imprimen de forma fiable en todas las configuraciones.


Preguntas frecuentes

¿Por qué no aparece el fondo cuando imprimo el documento?

Este es el comportamiento esperado. Word suprime los fondos de página en la salida impresa de forma predeterminada; la configuración se almacena correctamente y se representa en pantalla, pero las opciones de impresión del cliente de Word la filtran. El fondo no se ha perdido; simplemente no se incluye en el flujo de impresión.

Para solucionarlo, habilita Imprimir colores e imágenes de fondo en Archivo > Opciones > Mostrar en Word antes de imprimir. En entornos donde no puedas controlar la configuración de impresión del lector, usa una forma de página completa en el encabezado o una marca de agua para replicar el efecto visual, ya que esos elementos se tratan como contenido imprimible.

¿Por qué el fondo de imagen no tiene efecto?

Esto suele ocurrir por una de dos razones: o bien Background.Type no se estableció en BackgroundType.Picture antes de llamar a SetPicture, o el archivo de imagen nunca se cargó en el VFS mediante FetchFileToVFS, por lo que SetPicture no puede localizarlo.

Asegúrate de establecer primero el tipo de fondo y pasar el nombre de archivo exacto de una imagen que ya se haya cargado en el sistema de archivos virtual:

document.Background.Type = wasmModule.BackgroundType.Picture;
document.Background.SetPicture("Background.png");

Véase también

Das Dokument, nachdem ein einfarbiger Hintergrund über Background.Color festgelegt wurde

Jeder Vertrag, jedes offizielle Schreiben und jedes Stück Markenkommunikation trägt eine implizite visuelle Identität. Eine schlichte weiße Seite erfüllt ihren Zweck, sagt aber nichts über die dahinterstehende Organisation aus. In dem Moment, in dem Sie eine sanfte Tönung, einen dezenten zweifarbigen Verlauf oder ein gekacheltes Hintergrundbild hinzufügen, verwandelt sich das gesamte Dokument von einer generischen Datei in ein wiedererkennbares Markenartefakt – und Ihre Leser bemerken es, auch wenn sie nicht in Worte fassen können, warum.

Spire.Doc for JavaScript bringt diese visuelle Gestaltung über WebAssembly direkt in den Browser. Es gibt keinen Server-Roundtrip, keine Abhängigkeit von Office-Automatisierung und keine Notwendigkeit einer Desktop-Installation. Sie laden eine Word-Datei in das virtuelle Dateisystem (VFS) von WASM, wählen einen von drei Hintergrundmodi und exportieren das gestaltete Dokument – alles clientseitig in einer React-Anwendung.

Dieser Leitfaden behandelt jede der drei Hintergrundoptionen nicht als API-Katalog, sondern als eine Reihe von Designentscheidungen. Wir beginnen mit einem kurzen Vergleich, damit Sie die richtige Technik für Ihren Anwendungsfall auswählen können, und tauchen dann in die Implementierungsdetails für jede einzelne ein.


Drei Hintergrundansätze auf einen Blick

Bevor Sie Code schreiben, ist es hilfreich zu verstehen, was jeder Hintergrundtyp aus Designperspektive bietet. Die folgende Tabelle fasst das visuelle Ergebnis, den Konfigurationsaufwand und die Szenarien zusammen, in denen jeder Ansatz seine Stärken ausspielt.

Ansatz Visueller Effekt Konfigurationsaufwand Am besten geeignet für
Einfarbig Eine einzige gleichmäßige Farbe füllt jede Seite Gering – BackgroundType.Color festlegen und eine Farbe zuweisen Verträge, interne Memos, offizielle Schreiben, die einen klaren, professionellen Grundton benötigen
Verlauf Eine gerichtete Mischung aus zwei Farben über die Seite Mittel – Color1, Color2 sowie ShadingStyle und ShadingVariant definieren Titelseiten, Zertifikate, Marketingvorlagen, die von subtiler Tiefe profitieren
Bild Ein Hintergrundbild, das über die gesamte Seite gekachelt wird Mittel – Bild in VFS laden, dann SetPicture aufrufen Markenbriefpapier, Briefköpfe mit dekorativen Elementen, thematische Dokumentvorlagen

Alle drei teilen denselben Gesamtworkflow: Laden Sie das Quelldokument in das VFS, konfigurieren Sie die Eigenschaft Background einer Document-Instanz, speichern Sie das Ergebnis und lösen Sie einen Browser-Download aus. Die Unterschiede liegen ausschließlich darin, wie Sie diese Eigenschaft Background konfigurieren – und genau hier kommen die Designentscheidungen ins Spiel.

Informationen zur Projekteinrichtung und Installation finden Sie unter Integrating Spire.Doc for JavaScript in a React Project. Die folgenden Codebeispiele setzen voraus, dass das WASM-Modul bereits initialisiert und unter window.wasmModule verfügbar ist.


Einfarbiger Hintergrund

Eine einfarbige Hintergrundfarbe ist die zurückhaltendste Wahl – und oft die wirkungsvollste. Ein warmes Creme oder ein helles Grau hinter schwarzem Text reduziert die Augenbelastung, ohne um Aufmerksamkeit zu konkurrieren. Bei formellen Dokumenten wie Verträgen und Richtlinienpapieren signalisiert eine dezente Tönung: „Dieses Dokument gehört zu einer bestimmten Organisation“, ohne in Dekoration abzudriften.

Die Implementierung folgt drei klaren Schritten. Zunächst laden Sie mit FetchFileToVFS die Ziel-Word-Datei (und Schriftdateien) in das virtuelle Dateisystem von WASM. Zweitens erstellen Sie ein Document, laden die Datei, setzen Background.Type auf BackgroundType.Color und weisen Background.Color eine integrierte Farbe zu. Drittens speichern Sie das Dokument mit SaveToFile zurück in das VFS, lesen die resultierende Datei als Byte-Array ein, verpacken sie in einen Blob und starten einen Download.

function App() {
  const SetSolidColorBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Color
    doc.Background.Type = docModule.BackgroundType.Color;

    // Set the background color
    doc.Background.Color = docModule.Color.get_LightYellow();

    // Define the output file name
    const outputFileName = "SetSolidColorBackground_out.docx";

    // Save the document to the specified path
    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 a Solid Color Background for a Word Document</h1>
      <button onClick={SetSolidColorBackground}>Generate</button>
    </div>
  );
}
export default App;

Sobald Background.Color angewendet wurde, wird jede Seite des Dokuments mit der gewählten integrierten Farbe gefüllt – in diesem Fall LightYellow.

Das Dokument, nachdem ein einfarbiger Hintergrund über Background.Color festgelegt wurde


Verlaufshintergrund

Verläufe vermitteln ein Gefühl von Räumlichkeit, das flache Farben nicht bieten können. Ein Übergang von Weiß zu Hellblau von oben nach unten beispielsweise weckt Assoziationen an Himmel und Offenheit – nützlich für Zertifikate, Auszeichnungsschreiben oder jedes Dokument, bei dem ein Hauch von Feierlichkeit angebracht ist. Der Schlüssel ist Zurückhaltung: Wählen Sie zwei eng verwandte Farben und lassen Sie den Verlauf die Arbeit leise erledigen.

Der Code entspricht dem Workflow für einfarbige Hintergründe, doch der mittlere Schritt wird umfangreicher. Nachdem Sie Background.Type auf BackgroundType.Gradient gesetzt haben, rufen Sie das Verlaufsobjekt über Background.Gradient ab und konfigurieren vier Eigenschaften: Color1 (Startfarbe), Color2 (Endfarbe), ShadingVariant (Übergangsrichtung) und ShadingStyle (Achse des Verlaufs).

function App() {
  const SetGradientBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Gradient
    doc.Background.Type = docModule.BackgroundType.Gradient;
    let gradient = doc.Background.Gradient;

    // Set the start color and the end color of the gradient
    gradient.Color1 = docModule.Color.get_White();
    gradient.Color2 = docModule.Color.get_LightBlue();

    // Set the shading style and variant of the gradient
    gradient.ShadingVariant = docModule.GradientShadingVariant.ShadingDown;
    gradient.ShadingStyle = docModule.GradientShadingStyle.Horizontal;

    // Define the output file name
    const outputFileName = "SetGradientBackground_out.docx";

    // Save the document to the specified path
    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 a Gradient Background for a Word Document</h1>
      <button onClick={SetGradientBackground}>Generate</button>
    </div>
  );
}
export default App;

Nach dem Anwenden von Background.Gradient wird die Seite mit einem sanften horizontalen Übergang von Weiß zu Hellblau gefüllt, der nach unten fließt.

Das Dokument, nachdem ein Verlaufshintergrund über Background.Gradient festgelegt wurde


Bildhintergrund

Ein Bildhintergrund ist die ausdrucksstärkste Option. Ob es sich um ein dezentes Wasserzeichenmuster, eine Unternehmensstruktur oder ein dekoratives Motiv für Veranstaltungsprogramme handelt – ein gekacheltes Bild kann Branding-Elemente transportieren, die Farbe und Verlauf einfach nicht leisten können. Der Kompromiss ist das Dateigewicht – das Bild muss zusammen mit dem Dokument in das VFS geladen werden –, daher sollten Sie diesen Ansatz für Vorlagen reservieren, bei denen der visuelle Nutzen den zusätzlichen Ressourceneinsatz rechtfertigt.

Die Einrichtung unterscheidet sich in einem wichtigen Punkt von den beiden vorherigen Methoden: Das Hintergrundbild muss ebenfalls mit FetchFileToVFS in das VFS geladen werden, bevor es referenziert werden kann. Sobald sowohl das Dokument als auch das Bild im VFS liegen, setzen Sie Background.Type auf BackgroundType.Picture und rufen Background.SetPicture mit dem VFS-Pfad des Bildes auf. Das Bild wird dann als Hintergrund über jede Seite gekachelt.

function App() {
  const SetImageBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName1 = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName1, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load the background image into the virtual file system (VFS)
    let inputFileName2 = "Background.png";
    await window.spire.FetchFileToVFS(inputFileName2, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load a Word document
    let doc = new docModule.Document();
    doc.LoadFromFile(inputFileName1);

    // Set the background type as Picture
    doc.Background.Type = docModule.BackgroundType.Picture;

    // Set the background picture
    doc.Background.SetPicture(inputFileName2);

    // Define the output file name
    const outputFileName = "SetImageBackground_out.docx";

    // Save the document to the specified path
    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 a Picture Background in a Word Document</h1>
      <button onClick={SetImageBackground}>Generate</button>
    </div>
  );
}
export default App;

Nach dem Aufruf von Background.SetPicture wird das angegebene Bild als Dokumenthintergrund über die gesamte Seitenfläche gekachelt.

Das Dokument, nachdem ein Bildhintergrund über Background.SetPicture festgelegt wurde


Hinweise zum Drucken

Es gibt einen praktischen Vorbehalt, der viele Entwickler überrascht: Microsoft Word druckt Seitenhintergründe standardmäßig nicht. Das ist kein Fehler in Ihrem Code und keine Einschränkung von Spire.Doc – der Hintergrund wird korrekt im Dokument gespeichert und normal auf dem Bildschirm angezeigt. Word lässt ihn lediglich aus der Druckausgabe weg, es sei denn, Sie weisen es ausdrücklich anders an.

Damit Hintergründe in gedruckten Exemplaren erscheinen, muss der Endbenutzer eine bestimmte Einstellung in seinem Word-Client aktivieren:

  1. Öffnen Sie das Dokument in Microsoft Word.
  2. Gehen Sie zu Datei > Optionen > Anzeige.
  3. Aktivieren Sie Hintergrundfarben und -bilder drucken.
  4. Drucken Sie wie gewohnt.

Wenn der Hintergrund in jeder Ausgabeumgebung gerendert werden soll, unabhängig von den Word-Einstellungen des Lesers, sollten Sie einen alternativen Ansatz in Betracht ziehen: Platzieren Sie eine ganzseitige Form in der Kopfzeile des Dokuments oder verwenden Sie ein Wasserzeichen, um den Hintergrundeffekt zu simulieren. Diese Techniken werden als Inhalt und nicht als Seitenformatierung behandelt, sodass sie in allen Konfigurationen zuverlässig gedruckt werden.


FAQ

Warum wird der Hintergrund beim Drucken des Dokuments nicht angezeigt?

Dies ist das erwartete Verhalten. Word unterdrückt Seitenhintergründe standardmäßig in der Druckausgabe – die Einstellung wird korrekt gespeichert und auf dem Bildschirm gerendert, aber die Druckoptionen des Word-Clients filtern sie heraus. Der Hintergrund ist nicht verloren gegangen; er wird einfach nicht in den Druckdatenstrom aufgenommen.

Um dies zu beheben, aktivieren Sie in Word vor dem Drucken Hintergrundfarben und -bilder drucken unter Datei > Optionen > Anzeige. In Umgebungen, in denen Sie die Druckeinstellungen des Lesers nicht kontrollieren können, verwenden Sie eine ganzseitige Form in der Kopfzeile oder ein Wasserzeichen, um den visuellen Effekt nachzubilden, da diese Elemente als druckbarer Inhalt behandelt werden.

Warum hat der Bildhintergrund keine Wirkung?

Dies geschieht typischerweise aus einem von zwei Gründen: Entweder wurde Background.Type nicht auf BackgroundType.Picture gesetzt, bevor SetPicture aufgerufen wurde, oder die Bilddatei wurde nie über FetchFileToVFS in das VFS geladen, sodass SetPicture sie nicht finden kann.

Stellen Sie sicher, dass Sie zuerst den Hintergrundtyp festlegen und den exakten Dateinamen eines Bildes übergeben, das bereits in das virtuelle Dateisystem geladen wurde:

document.Background.Type = wasmModule.BackgroundType.Picture;
document.Background.SetPicture("Background.png");

Siehe auch

The document after a solid color background is set via Background.Color

Каждый договор, официальное письмо и элемент фирменного стиля несёт неявную визуальную идентичность. Обычная белая страница выполняет свою задачу, но ничего не говорит об организации, стоящей за ней. Как только вы добавляете мягкий оттенок, тонкий двухцветный градиент или мозаичное фоновое изображение, весь документ превращается из безликого файла в узнаваемый брендированный артефакт — и читатели это замечают, даже если не могут объяснить почему.

Spire.Doc for JavaScript привносит это визуальное оформление прямо в браузер через WebAssembly. Здесь нет обращения к серверу, зависимости от автоматизации Office или необходимости устанавливать настольную программу. Вы загружаете файл Word в виртуальную файловую систему WASM (VFS), выбираете один из трёх режимов фона и экспортируете оформленный документ — всё на стороне клиента в приложении React.

Это руководство рассматривает каждый из трёх вариантов фона не как каталог API, а как набор дизайнерских решений. Мы начнём с краткого сравнения, чтобы вы могли подобрать подходящую технику для своего сценария, а затем перейдём к деталям реализации каждого варианта.


Три подхода к фону: краткий обзор

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

Подход Визуальный эффект Трудоёмкость настройки Лучше всего подходит для
Сплошной цвет Один однородный цвет заполняет каждую страницу Низкая — установите BackgroundType.Color и назначьте один цвет Договоры, внутренние служебные записки, официальные письма, которым нужен чистый профессиональный базовый тон
Градиент Двухцветное направленное смешение по всей странице Средняя — задайте Color1, Color2, а также ShadingStyle и ShadingVariant Титульные страницы, сертификаты, маркетинговые шаблоны, которым нужна тонкая глубина
Изображение Фоновое изображение, мозаично заполняющее всю страницу Средняя — загрузите изображение в VFS, затем вызовите SetPicture Брендированные фирменные бланки, бланки с декоративными элементами, тематические шаблоны документов

Все три подхода используют один и тот же общий рабочий процесс: загрузите исходный документ в VFS, настройте свойство Background у экземпляра Document, сохраните результат и запустите скачивание в браузере. Различия заключаются исключительно в том, как вы настраиваете это свойство Background — именно здесь и появляются дизайнерские решения.

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


Фон сплошного цвета

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

Реализация состоит из трёх чётких шагов. Сначала используйте FetchFileToVFS, чтобы загрузить целевой файл Word (и файлы шрифтов) в виртуальную файловую систему WASM. Затем создайте Document, загрузите файл, установите Background.Type в BackgroundType.Color и назначьте встроенный цвет свойству Background.Color. В-третьих, сохраните документ обратно в VFS с помощью SaveToFile, прочитайте полученный файл как массив байтов, оберните его в Blob и инициируйте скачивание.

function App() {
  const SetSolidColorBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Color
    doc.Background.Type = docModule.BackgroundType.Color;

    // Set the background color
    doc.Background.Color = docModule.Color.get_LightYellow();

    // Define the output file name
    const outputFileName = "SetSolidColorBackground_out.docx";

    // Save the document to the specified path
    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 a Solid Color Background for a Word Document</h1>
      <button onClick={SetSolidColorBackground}>Generate</button>
    </div>
  );
}
export default App;

После применения Background.Color каждая страница документа заполняется выбранным встроенным цветом — в данном случае LightYellow.

The document after a solid color background is set via Background.Color


Градиентный фон

Градиенты придают ощущение объёма, которого не дают плоские цвета. Например, переход сверху вниз от белого к бледно-голубому вызывает ассоциации с небом и открытостью — это полезно для сертификатов, наградных писем или любого документа, где уместна толика торжественности. Главное — сдержанность: выберите два близких цвета и позвольте градиенту делать свою работу незаметно.

Код повторяет рабочий процесс для сплошного цвета, но средний шаг расширяется. После установки Background.Type в BackgroundType.Gradient вы получаете объект градиента через Background.Gradient и настраиваете четыре свойства: Color1 (начальный цвет), Color2 (конечный цвет), ShadingVariant (направление перехода) и ShadingStyle (ось градиента).

function App() {
  const SetGradientBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);

    // Create Word document
    let doc = new docModule.Document();

    // Load the file
    doc.LoadFromFile(inputFileName);

    // Set the background type as Gradient
    doc.Background.Type = docModule.BackgroundType.Gradient;
    let gradient = doc.Background.Gradient;

    // Set the start color and the end color of the gradient
    gradient.Color1 = docModule.Color.get_White();
    gradient.Color2 = docModule.Color.get_LightBlue();

    // Set the shading style and variant of the gradient
    gradient.ShadingVariant = docModule.GradientShadingVariant.ShadingDown;
    gradient.ShadingStyle = docModule.GradientShadingStyle.Horizontal;

    // Define the output file name
    const outputFileName = "SetGradientBackground_out.docx";

    // Save the document to the specified path
    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 a Gradient Background for a Word Document</h1>
      <button onClick={SetGradientBackground}>Generate</button>
    </div>
  );
}
export default App;

После применения Background.Gradient страница заполняется плавным горизонтальным переходом от белого к светло-синему, стекающим вниз.

The document after a gradient background is set via Background.Gradient


Фоновое изображение

Фоновое изображение — самый выразительный вариант. Будь то тонкий узор-водяной знак, корпоративная текстура или декоративный мотив для программ мероприятий, мозаичное изображение может нести элементы брендинга, которые цвет и градиент просто не способны передать. Компромисс — вес файла: изображение необходимо загрузить в VFS вместе с документом, поэтому оставьте этот подход для шаблонов, где визуальный эффект оправдывает дополнительные ресурсы.

Настройка отличается от двух предыдущих методов в одном важном моменте: фоновое изображение также необходимо загрузить в VFS с помощью FetchFileToVFS, прежде чем на него можно будет ссылаться. Когда и документ, и изображение окажутся в VFS, установите Background.Type в BackgroundType.Picture и вызовите Background.SetPicture, указав путь к изображению в VFS. После этого изображение мозаично заполнит каждую страницу в качестве фона.

function App() {
  const SetImageBackground = async () => {
    const docModule = window.wasmModule?.spiredoc;
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }
    // Load the sample file into the virtual file system (VFS)
    let inputFileName1 = "ScienceTemplate.docx";
    await window.spire.FetchFileToVFS(inputFileName1, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load the background image into the virtual file system (VFS)
    let inputFileName2 = "Background.png";
    await window.spire.FetchFileToVFS(inputFileName2, "", `${process.env.PUBLIC_URL}static/data/`);

    // Load a Word document
    let doc = new docModule.Document();
    doc.LoadFromFile(inputFileName1);

    // Set the background type as Picture
    doc.Background.Type = docModule.BackgroundType.Picture;

    // Set the background picture
    doc.Background.SetPicture(inputFileName2);

    // Define the output file name
    const outputFileName = "SetImageBackground_out.docx";

    // Save the document to the specified path
    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 a Picture Background in a Word Document</h1>
      <button onClick={SetImageBackground}>Generate</button>
    </div>
  );
}
export default App;

После вызова Background.SetPicture указанное изображение мозаично заполняет всю поверхность страницы в качестве фона документа.

The document after a picture background is set via Background.SetPicture


Особенности печати

Есть одна практическая оговорка, которая часто застаёт разработчиков врасплох: Microsoft Word по умолчанию не печатает фон страницы. Это не ошибка в вашем коде и не ограничение Spire.Doc — фон корректно сохраняется в документе и нормально отображается на экране. Word просто опускает его при печати, если явно не указать обратное.

Чтобы фон появлялся на печатных копиях, конечному пользователю нужно включить определённую настройку в клиенте Word:

  1. Откройте документ в Microsoft Word.
  2. Перейдите в Файл > Параметры > Экран.
  3. Установите флажок Печатать цвета и изображения фона.
  4. Печатайте как обычно.

Если вам нужно, чтобы фон отображался в любой среде вывода независимо от настроек Word у читателя, рассмотрите альтернативный подход: разместите фигуру на всю страницу в колонтитуле документа или используйте водяной знак для имитации фонового эффекта. Эти приёмы считаются содержимым, а не форматированием страницы, поэтому они надёжно печатаются при любых конфигурациях.


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

Почему фон не отображается при печати документа?

Это ожидаемое поведение. Word по умолчанию подавляет фон страницы при печати — настройка корректно сохраняется и отображается на экране, но параметры печати клиента Word отфильтровывают её. Фон не потерян; он просто не включается в поток печати.

Чтобы исправить это, включите Печатать цвета и изображения фона в разделе Файл > Параметры > Экран в Word перед печатью. В средах, где вы не можете управлять настройками печати читателя, используйте фигуру на всю страницу в колонтитуле или водяной знак для воспроизведения визуального эффекта, поскольку эти элементы считаются печатаемым содержимым.

Почему фоновое изображение не даёт эффекта?

Обычно это происходит по одной из двух причин: либо Background.Type не был установлен в BackgroundType.Picture перед вызовом SetPicture, либо файл изображения не был загружен в VFS через FetchFileToVFS, поэтому SetPicture не может его найти.

Убедитесь, что сначала задан тип фона, и передайте точное имя файла изображения, которое уже загружено в виртуальную файловую систему:

document.Background.Type = wasmModule.BackgroundType.Picture;
document.Background.SetPicture("Background.png");

См. также

O documento após a definição de um intervalo editável; o parágrafo levemente sombreado é o intervalo editável

Imagine um modelo de contrato enviado para dezenas de clientes. A equipe jurídica redigiu cada cláusula com cuidado, e as únicas coisas que cada destinatário deve alterar são o bloco de assinatura, o nome do projeto e a data de aceite. Entregue a eles um arquivo Word totalmente editável e inevitavelmente alguém vai reformular uma cláusula de multa ou excluir uma seção de responsabilidade. Bloqueie o documento inteiro e ninguém conseguirá preencher os campos. O que você realmente precisa é de edição seletiva — uma forma de dizer "estes parágrafos específicos podem ser alterados, todo o resto está congelado."

É exatamente isso que os intervalos editáveis oferecem. Você protege todo o documento como somente leitura e depois insere um par de marcadores de permissão ao redor dos parágrafos que deseja manter abertos. Qualquer pessoa que abrir o arquivo no Word pode digitar dentro da região marcada, mas não pode alterar um único caractere fora dela. O Spire.Doc for JavaScript traz essa capacidade para o navegador por meio do WebAssembly, para que você possa gerar documentos protegidos a partir de um aplicativo React sem ida e volta ao servidor — as fontes e os arquivos de entrada são gerenciados por meio de um sistema de arquivos virtual (VFS) em memória.

Este guia aborda as duas metades do fluxo de trabalho:

Caso você ainda não tenha integrado o Spire.Doc ao seu projeto, comece por Integrating Spire.Doc for JavaScript in a React Project. Os trechos abaixo pressupõem que o módulo WebAssembly esteja carregado e pronto.


Definir um Intervalo Editável

O processo tem três etapas. Primeiro, traga os arquivos de fonte e o documento Word de destino para o sistema de arquivos virtual do WASM com FetchFileToVFS. Em seguida, instancie um Document, carregue o arquivo, chame Protect para bloquear todo o documento como somente leitura e, depois, crie um par PermissionStart / PermissionEnd que compartilhe o mesmo id — esses dois marcadores delimitam o parágrafo que você deseja deixar editável. Por fim, salve o arquivo, leia-o de volta do VFS, envolva-o em um Blob e dispare o download.

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;

No arquivo de exemplo, os campos que o revisor tem permissão para preencher possuem um sombreamento claro — isso é apenas uma indicação visual para o leitor e não tem relação com a forma como o intervalo editável é definido no código. Depois que os marcadores estão posicionados, o Word trata o parágrafo sombreado como editável e todos os outros parágrafos como bloqueados.

O documento após a definição de um intervalo editável; o parágrafo levemente sombreado é o intervalo editável


Remover um Intervalo Editável

Remover o intervalo editável é uma única travessia: percorra cada seção e cada parágrafo, inspecione cada objeto na coleção ChildObjects do parágrafo e extraia qualquer coisa que seja um PermissionStart ou PermissionEnd.

Uma sutileza pega as pessoas de surpresa: ChildObjects.Remove reduz a coleção na hora, então cada elemento após o removido avança um índice. Se você incrementar o contador do laço ao mesmo tempo em que exclui, cada remoção faz com que o marcador imediatamente seguinte seja ignorado — e quanto mais marcadores você tiver, mais sobreviventes ficarão para trás.

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;

Excluir os marcadores apenas redesenha o limite do que é editável — o texto em si e toda a formatação permanecem intactos.

O documento após a remoção dos marcadores de intervalo editável; o conteúdo e a formatação permanecem inalterados


O Ciclo de Vida Completo da Proteção

Em um fluxo de aprovação real, você raramente faz apenas uma coisa. Um ciclo típico é assim:

  1. Proteger — Chame doc.Protect com AllowOnlyReading (ou AllowOnlyFormFields) e uma senha. Todo o documento agora está bloqueado.
  2. Marcar — Envolva cada parágrafo editável pelo revisor em um par PermissionStart / PermissionEnd que compartilhe um mesmo id. Essas regiões se tornam os únicos lugares onde o revisor pode digitar.
  3. Desmarcar — Quando a rodada de revisão terminar, percorra o documento e remova todos os marcadores de permissão. As regiões voltam a fazer parte do corpo somente leitura.
  4. Desproteger — Chame doc.Unprotect("password") para liberar o documento por completo, devolvendo-o a um estado totalmente editável para a próxima etapa do processamento.

O ponto principal é que a proteção e os intervalos editáveis são duas camadas independentes. A proteção decide se o documento está bloqueado; o par de marcadores decide quais trechos ficam isentos desse bloqueio. Você pode adicionar e remover marcadores quantas vezes quiser sem tocar no estado de proteção, e pode ativar ou desativar a proteção sem mexer nos marcadores — mas os marcadores só têm efeito enquanto a proteção estiver ativa.


Perguntas Frequentes

O intervalo editável está definido, mas o conteúdo dentro dele ainda não pode ser editado

Por que acontece: Os marcadores de permissão são inertes por si só. Eles apenas abrem exceções a uma restrição que abrange todo o documento, então, se Protect nunca foi chamado, não há restrição da qual isentar e os marcadores não fazem nada. Um segundo requisito é que PermissionStart e PermissionEnd devem carregar a mesma string de id — o Word só os trata como um par quando os ids coincidem.

Correção: Ative primeiro a restrição de edição e depois crie os dois marcadores com um id idêntico:

// 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");

Alguns marcadores são ignorados ao remover intervalos editáveis

Por que acontece: Cada chamada a ChildObjects.Remove reduz a coleção em um elemento, deslocando o índice de todos os elementos seguintes para baixo. Se o contador do laço avançar na mesma iteração de uma remoção, o elemento que deslizou para a posição atual nunca é examinado — ele é ignorado, e o problema se acumula a cada marcador adicional.

Correção: Mantenha o índice fixo durante a remoção (avance-o apenas quando nenhuma remoção tiver ocorrido) ou reúna primeiro os objetos de destino e exclua-os em ordem inversa:

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++;
  }
}

O documento continua somente leitura após a remoção dos marcadores

Por que acontece: Os marcadores apenas definem quais áreas ficam isentas do bloqueio — eles não são o bloqueio em si. Removê-los simplesmente remove as isenções; a proteção subjacente estabelecida por Protect continua em vigor, então o documento inteiro permanece somente leitura.

Correção: Assim que os marcadores forem removidos e você não precisar mais da restrição, chame Unprotect com a senha original:

document.Unprotect("password");

Veja Também

The document after an editable range is set; the lightly shaded paragraph is the editable range

수십 명의 고객에게 발송되는 계약서 템플릿을 상상해 보세요. 법무팀은 모든 조항을 신중하게 작성했고, 각 수신자가 손대야 하는 것은 서명란, 프로젝트 이름, 승인 날짜뿐입니다. 완전히 편집 가능한 Word 파일을 건네면 누군가는 반드시 위약금 조항을 고쳐 쓰거나 책임 조항을 삭제할 것입니다. 문서 전체를 잠그면 아무도 필드를 채울 수 없습니다. 정말 필요한 것은 선택적 편집, 즉 “이 특정 단락은 편집해도 되고 나머지는 모두 고정된다”라고 말할 수 있는 방법입니다.

바로 이것이 편집 가능 범위가 제공하는 기능입니다. 문서 전체를 읽기 전용으로 보호한 다음, 열어 두려는 단락 주위에 한 쌍의 권한 표식을 배치합니다. Word에서 파일을 연 사람은 표시된 영역 안에서는 입력할 수 있지만 그 밖의 문자는 단 하나도 변경할 수 없습니다. Spire.Doc for JavaScript는 WebAssembly를 통해 이 기능을 브라우저로 가져오므로, 서버 왕복 없이 React 앱에서 보호된 문서를 생성할 수 있습니다. 글꼴과 입력 파일은 인메모리 가상 파일 시스템(VFS)을 통해 관리됩니다.

이 가이드에서는 워크플로의 두 부분을 모두 살펴봅니다:

아직 프로젝트에 Spire.Doc을 연결하지 않았다면 React 프로젝트에서 Spire.Doc for JavaScript 통합하기부터 시작하세요. 아래 코드 조각은 WebAssembly 모듈이 로드되어 준비된 상태를 가정합니다.


편집 가능 범위 설정

이 프로세스는 세 단계로 구성됩니다. 먼저 FetchFileToVFS로 글꼴 파일과 대상 Word 문서를 WASM 가상 파일 시스템으로 가져옵니다. 다음으로 Document를 인스턴스화하고 파일을 로드한 뒤, Protect를 호출해 문서 전체를 읽기 전용으로 잠그고, 동일한 id를 공유하는 PermissionStart / PermissionEnd 쌍을 만듭니다. 이 두 표식이 편집 가능하게 남겨 둘 단락을 감쌉니다. 마지막으로 파일을 저장하고 VFS에서 다시 읽어 Blob으로 감싼 다음 다운로드를 트리거합니다.

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;

샘플 파일에서 검토자가 채울 수 있는 필드는 연한 음영으로 표시되어 있습니다. 이는 순전히 읽는 사람을 위한 시각적 신호일 뿐이며 코드에서 편집 가능 범위가 정의되는 방식과는 무관합니다. 표식이 배치되면 Word는 음영 처리된 단락을 편집 가능으로, 다른 모든 단락을 잠긴 것으로 처리합니다.

The document after an editable range is set; the lightly shaded paragraph is the editable range


편집 가능 범위 제거

편집 가능 범위를 제거하는 것은 단일 순회입니다. 모든 섹션과 모든 단락을 반복하면서 단락의 ChildObjects 컬렉션에 있는 각 개체를 검사하고, PermissionStart 또는 PermissionEnd인 항목을 뽑아냅니다.

사람들이 흔히 놓치는 미묘한 점이 있습니다. ChildObjects.Remove는 컬렉션을 즉시 축소하므로 제거된 요소 뒤의 모든 요소가 인덱스 하나씩 앞으로 이동합니다. 삭제하면서 루프 카운터를 증가시키면 제거할 때마다 바로 다음 표식이 건너뛰어지고, 표식이 많을수록 더 많은 표식이 남게 됩니다.

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;

표식을 삭제하면 편집 가능한 경계만 다시 그려질 뿐, 텍스트 자체와 모든 서식은 그대로 유지됩니다.

The document after the editable range markers are removed; the content and formatting stay unchanged


전체 보호 수명 주기

실제 승인 워크플로에서는 한 가지 작업만 하는 경우가 거의 없습니다. 일반적인 왕복 과정은 다음과 같습니다:

  1. 보호 — AllowOnlyReading(또는 AllowOnlyFormFields)와 암호를 사용해 doc.Protect를 호출합니다. 이제 문서 전체가 잠깁니다.
  2. 표시 — 검토자가 편집할 수 있는 각 단락을 하나의 id를 공유하는 PermissionStart / PermissionEnd 쌍으로 감쌉니다. 해당 영역만 검토자가 입력할 수 있는 곳이 됩니다.
  3. 표시 해제 — 검토 라운드가 끝나면 문서를 순회하며 모든 권한 표식을 제거합니다. 해당 영역은 다시 읽기 전용 본문에 포함됩니다.
  4. 보호 해제 — doc.Unprotect("password")를 호출해 문서를 완전히 해제하고, 다음 처리 단계를 위해 완전히 편집 가능한 상태로 되돌립니다.

핵심은 보호와 편집 가능 범위가 서로 독립적인 두 계층이라는 점입니다. 보호는 문서가 잠기는지 여부를 결정하고, 표식 쌍은 그 잠금에서 어떤 부분이 예외인지를 결정합니다. 보호 상태를 건드리지 않고 표식을 원하는 만큼 추가하거나 제거할 수 있으며, 표식을 어지럽히지 않고 보호를 켜거나 끌 수 있습니다. 다만 표식은 보호가 활성화되어 있을 때만 효력을 발휘합니다.


자주 묻는 질문

편집 가능 범위를 설정했지만 그 안의 내용을 여전히 편집할 수 없습니다

원인: 권한 표식은 그 자체로는 아무 효과가 없습니다. 문서 전체 제한에 대한 예외를 만들어 줄 뿐이므로 Protect를 호출한 적이 없다면 예외를 적용할 제한 자체가 없어 표식은 아무 일도 하지 않습니다. 두 번째 요구 사항은 PermissionStart와 PermissionEnd가 동일한 id 문자열을 가져야 한다는 점입니다. Word는 id가 일치할 때만 이들을 한 쌍으로 취급합니다.

해결 방법: 먼저 편집 제한을 켠 다음, 동일한 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");

편집 가능 범위를 제거할 때 일부 표식이 누락됩니다

원인: ChildObjects.Remove를 호출할 때마다 컬렉션이 하나씩 줄어들어 이후 모든 요소의 인덱스가 앞으로 이동합니다. 제거와 같은 반복에서 루프 카운터가 증가하면 현재 위치로 밀려온 요소를 검사하지 않게 되어 건너뛰게 되고, 표식이 추가될수록 문제가 더 커집니다.

해결 방법: 제거하는 동안 인덱스를 고정하거나(제거가 없을 때만 증가), 대상 개체를 먼저 모은 뒤 역순으로 삭제합니다:

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++;
  }
}

표식을 제거한 후에도 문서가 여전히 읽기 전용입니다

원인: 표식은 잠금에서 어떤 영역이 예외인지만 정의할 뿐, 잠금 자체가 아닙니다. 표식을 제거하면 예외만 사라지고, Protect가 설정한 기본 보호는 여전히 유효하므로 문서 전체가 읽기 전용으로 남습니다.

해결 방법: 표식이 사라지고 더 이상 제한이 필요하지 않으면 원래 암호로 Unprotect를 호출하세요:

document.Unprotect("password");

참고 항목

Il documento dopo l'impostazione di un intervallo modificabile; il paragrafo leggermente ombreggiato è l'intervallo modificabile

Immagina un modello di contratto che viene inviato a decine di clienti. Il team legale ha redatto con cura ogni clausola e le uniche cose che ciascun destinatario dovrebbe toccare sono il blocco della firma, il nome del progetto e la data di accettazione. Consegna loro un file Word completamente modificabile e qualcuno riscriverà inevitabilmente una clausola penale o eliminerà una sezione sulla responsabilità. Blocca l'intero documento e nessuno riuscirà a compilare i campi. Ciò di cui hai davvero bisogno è la modifica selettiva: un modo per dire "questi paragrafi specifici sono liberi, tutto il resto è congelato".

È esattamente questo che ti offrono gli intervalli modificabili. Proteggi l'intero documento in sola lettura, poi inserisci una coppia di marcatori di autorizzazione attorno ai paragrafi che vuoi mantenere aperti. Chiunque apra il file in Word può digitare all'interno dell'area contrassegnata, ma non può modificare un solo carattere al di fuori di essa. Spire.Doc for JavaScript porta questa funzionalità nel browser tramite WebAssembly, così puoi generare documenti protetti da un'app React senza alcun round-trip verso il server: i font e i file di input sono gestiti tramite un file system virtuale in memoria (VFS).

Questa guida illustra entrambe le parti del flusso di lavoro:

Se non hai ancora integrato Spire.Doc nel tuo progetto, inizia con Integrare Spire.Doc for JavaScript in un progetto React. Gli snippet riportati di seguito presuppongono che il modulo WebAssembly sia caricato e pronto.


Impostare un intervallo modificabile

Il processo si articola in tre fasi. Per prima cosa, porta i file dei font e il documento Word di destinazione nel file system virtuale WASM con FetchFileToVFS. Poi istanzia un Document, carica il file, chiama Protect per bloccare l'intero documento in sola lettura e quindi crea una coppia PermissionStart / PermissionEnd che condivida lo stesso id: questi due marcatori delimitano il paragrafo che vuoi lasciare modificabile. Infine salva il file, rileggilo dal VFS, avvolgilo in un Blob e attiva il download.

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;

Nel file di esempio, i campi che il revisore è autorizzato a compilare presentano una leggera ombreggiatura: si tratta puramente di un suggerimento visivo per il lettore e non ha alcuna influenza su come viene definito l'intervallo modificabile nel codice. Una volta inseriti i marcatori, Word considera modificabile il paragrafo ombreggiato e bloccato ogni altro paragrafo.

Il documento dopo l'impostazione di un intervallo modificabile; il paragrafo leggermente ombreggiato è l'intervallo modificabile


Rimuovere un intervallo modificabile

Eliminare l'intervallo modificabile richiede un'unica scansione: scorri ogni sezione e ogni paragrafo, esamina ciascun oggetto nella raccolta ChildObjects del paragrafo ed estrai tutto ciò che è un PermissionStart o un PermissionEnd.

Una sottigliezza coglie molti di sorpresa: ChildObjects.Remove riduce la raccolta sul momento, quindi ogni elemento successivo a quello rimosso scala avanti di un indice. Se incrementi il contatore del ciclo mentre elimini, ogni rimozione fa saltare il marcatore immediatamente successivo — e più marcatori hai, più superstiti lasci indietro.

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;

Eliminare i marcatori ridefinisce soltanto il confine di ciò che è modificabile: il testo stesso e tutta la formattazione restano invariati.

Il documento dopo la rimozione dei marcatori dell'intervallo modificabile; il contenuto e la formattazione restano invariati


Il ciclo di vita completo della protezione

In un flusso di approvazione reale raramente fai una sola cosa. Un ciclo tipico si presenta così:

  1. Proteggi — Chiama doc.Protect con AllowOnlyReading (o AllowOnlyFormFields) e una password. L'intero documento è ora bloccato.
  2. Contrassegna — Racchiudi ogni paragrafo modificabile dal revisore in una coppia PermissionStart / PermissionEnd che condivide un unico id. Quelle regioni diventano gli unici punti in cui il revisore può digitare.
  3. Rimuovi i contrassegni — Al termine del ciclo di revisione, percorri il documento e rimuovi ogni marcatore di autorizzazione. Le regioni si ricongiungono al corpo in sola lettura.
  4. Rimuovi la protezione — Chiama doc.Unprotect("password") per liberare completamente il documento, riportandolo a uno stato pienamente modificabile per la fase successiva di elaborazione.

Il concetto chiave è che la protezione e gli intervalli modificabili sono due livelli indipendenti. La protezione stabilisce se il documento è bloccato o meno; la coppia di marcatori stabilisce quali porzioni sono esenti da tale blocco. Puoi aggiungere e rimuovere marcatori quante volte vuoi senza toccare lo stato di protezione, e puoi attivare o disattivare la protezione senza disturbare i marcatori — ma i marcatori hanno effetto solo finché la protezione è attiva.


Domande frequenti

L'intervallo modificabile è impostato, ma il contenuto al suo interno non è ancora modificabile

Perché accade: i marcatori di autorizzazione sono inerti di per sé. Delimitano soltanto eccezioni a una restrizione valida per l'intero documento; quindi, se Protect non è mai stato chiamato, non esiste alcuna restrizione da cui essere esenti e i marcatori non fanno nulla. Un secondo requisito è che PermissionStart e PermissionEnd devono avere la stessa stringa di id: Word li considera una coppia solo quando gli id corrispondono.

Soluzione: attiva prima la restrizione di modifica, poi crea entrambi i marcatori con un id identico:

// 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");

Alcuni marcatori vengono saltati durante la rimozione degli intervalli modificabili

Perché accade: ogni chiamata a ChildObjects.Remove riduce la raccolta di un elemento, spostando verso il basso l'indice di ogni elemento successivo. Se il contatore del ciclo avanza nella stessa iterazione in cui avviene una rimozione, l'elemento che è scivolato nella posizione corrente non viene mai esaminato: viene saltato, e il problema si aggrava con ogni marcatore aggiuntivo.

Soluzione: mantieni fisso l'indice durante la rimozione (avanzi solo quando non avviene alcuna rimozione), oppure raccogli prima gli oggetti di destinazione ed eliminali in ordine inverso:

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++;
  }
}

Il documento è ancora in sola lettura dopo la rimozione dei marcatori

Perché accade: i marcatori definiscono solo quali aree sono esenti dal blocco: non sono il blocco stesso. Rimuoverli elimina semplicemente le esenzioni; la protezione sottostante stabilita da Protect è ancora in vigore, quindi l'intero documento resta in sola lettura.

Soluzione: una volta rimossi i marcatori e quando la restrizione non serve più, chiama Unprotect con la password originale:

document.Unprotect("password");

Vedi anche

Le document après la définition d'une plage modifiable ; le paragraphe légèrement grisé correspond à la plage modifiable

Imaginez un modèle de contrat envoyé à des dizaines de clients. L'équipe juridique a soigneusement rédigé chaque clause, et les seuls éléments que chaque destinataire doit toucher sont le bloc de signature, le nom du projet et la date d'acceptation. Remettez-leur un fichier Word entièrement modifiable et quelqu'un reformulera inévitablement une clause pénale ou supprimera une section de responsabilité. Verrouillez l'intégralité du document et personne ne pourra remplir les champs. Ce dont vous avez réellement besoin, c'est d'une édition sélective — un moyen de dire « ces paragraphes précis sont modifiables, tout le reste est figé ».

C'est exactement ce que vous offrent les plages modifiables. Vous protégez l'ensemble du document en lecture seule, puis vous placez une paire de marqueurs d'autorisation autour des paragraphes que vous souhaitez laisser ouverts. Toute personne ouvrant le fichier dans Word peut saisir du texte à l'intérieur de la zone balisée, mais ne peut modifier le moindre caractère en dehors. Spire.Doc for JavaScript met cette fonctionnalité à la disposition du navigateur via WebAssembly, ce qui vous permet de générer des documents protégés depuis une application React sans aller-retour vers le serveur — les polices et les fichiers d'entrée sont gérés par un système de fichiers virtuel en mémoire (VFS).

Ce guide parcourt les deux volets du processus :

Si vous n'avez pas encore intégré Spire.Doc à votre projet, commencez par Intégrer Spire.Doc for JavaScript dans un projet React. Les extraits de code ci-dessous supposent que le module WebAssembly est chargé et prêt.


Définir une plage modifiable

Le processus comporte trois étapes. Tout d'abord, chargez les fichiers de polices et le document Word cible dans le système de fichiers virtuel WASM avec FetchFileToVFS. Ensuite, instanciez un Document, chargez le fichier, appelez Protect pour verrouiller l'intégralité du document en lecture seule, puis créez une paire PermissionStart / PermissionEnd partageant le même id — ces deux marqueurs encadrent le paragraphe que vous souhaitez laisser modifiable. Enfin, enregistrez le fichier, relisez-le depuis le VFS, encapsulez-le dans un Blob et déclenchez un téléchargement.

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;

Dans le fichier d'exemple, les champs qu'un relecteur est autorisé à remplir portent un léger grisé — il s'agit uniquement d'un repère visuel pour le lecteur, sans aucune incidence sur la façon dont la plage modifiable est définie dans le code. Une fois les marqueurs en place, Word considère le paragraphe grisé comme modifiable et tous les autres paragraphes comme verrouillés.

Le document après la définition d'une plage modifiable ; le paragraphe légèrement grisé correspond à la plage modifiable


Supprimer une plage modifiable

Supprimer la plage modifiable ne demande qu'un seul parcours : bouclez sur chaque section et chaque paragraphe, inspectez chaque objet de la collection ChildObjects du paragraphe et extrayez tout ce qui est un PermissionStart ou un PermissionEnd.

Une subtilité prend souvent les gens au dépourvu : ChildObjects.Remove réduit la collection immédiatement, de sorte que chaque élément suivant celui qui a été supprimé remonte d'un index. Si vous incrémentez votre compteur de boucle pendant la suppression, chaque suppression fait sauter le marqueur suivant — et plus vous avez de marqueurs, plus vous en laissez derrière vous.

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;

La suppression des marqueurs ne fait que redéfinir la limite de ce qui est modifiable — le texte lui-même et toute la mise en forme restent intacts.

Le document après la suppression des marqueurs de plage modifiable ; le contenu et la mise en forme restent inchangés


Le cycle de vie complet de la protection

Dans un véritable processus de validation, il est rare de ne faire qu'une seule chose. Un aller-retour type se déroule ainsi :

  1. Protéger — Appelez doc.Protect avec AllowOnlyReading (ou AllowOnlyFormFields) et un mot de passe. L'intégralité du document est désormais verrouillée.
  2. Baliser — Encadrez chaque paragraphe modifiable par le relecteur dans une paire PermissionStart / PermissionEnd partageant un même id. Ces zones deviennent les seuls endroits où un relecteur peut saisir du texte.
  3. Débaliser — Une fois la campagne de révision terminée, parcourez le document et supprimez tous les marqueurs d'autorisation. Les zones rejoignent le corps en lecture seule.
  4. Déprotéger — Appelez doc.Unprotect("password") pour libérer entièrement le document et le rétablir dans un état totalement modifiable pour l'étape suivante du traitement.

L'idée clé est que la protection et les plages modifiables sont deux couches indépendantes. La protection détermine si le document est verrouillé ou non ; la paire de marqueurs détermine quelles portions échappent à ce verrou. Vous pouvez ajouter et supprimer des marqueurs autant de fois que vous le souhaitez sans toucher à l'état de protection, et activer ou désactiver la protection sans perturber les marqueurs — mais les marqueurs n'ont de portée réelle que tant que la protection est active.


FAQ

La plage modifiable est définie, mais le contenu qu'elle renferme reste non modifiable

Pourquoi cela se produit : les marqueurs d'autorisation sont inactifs en eux-mêmes. Ils ne font que créer des exceptions à une restriction appliquée à l'ensemble du document ; donc si Protect n'a jamais été appelé, il n'existe aucune restriction dont ils pourraient exempter quoi que ce soit et les marqueurs ne font rien. Une seconde condition est que PermissionStart et PermissionEnd doivent porter la même chaîne d'id — Word ne les traite comme une paire que si les id correspondent.

Solution : activez d'abord la restriction de modification, puis créez les deux marqueurs avec un id identique :

// 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");

Certains marqueurs sont oubliés lors de la suppression des plages modifiables

Pourquoi cela se produit : chaque appel à ChildObjects.Remove réduit la collection d'un élément, ce qui décale vers le bas l'index de tous les éléments suivants. Si le compteur de boucle progresse lors de la même itération qu'une suppression, l'élément qui a glissé à la position courante n'est jamais examiné — il est ignoré, et le problème s'aggrave à chaque marqueur supplémentaire.

Solution : soit maintenez l'index fixe pendant la suppression (ne l'incrémentez que lorsqu'aucune suppression n'a eu lieu), soit collectez d'abord les objets cibles et supprimez-les dans l'ordre inverse :

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++;
  }
}

Le document reste en lecture seule après la suppression des marqueurs

Pourquoi cela se produit : les marqueurs définissent uniquement les zones exemptées du verrou — ils ne constituent pas le verrou lui-même. Les supprimer ne fait que supprimer les exemptions ; la protection sous-jacente établie par Protect est toujours en vigueur, de sorte que tout le document reste en lecture seule.

Solution : une fois les marqueurs supprimés et la restriction devenue inutile, appelez Unprotect avec le mot de passe d'origine :

document.Unprotect("password");

Voir aussi

El documento después de establecer un rango editable; el párrafo ligeramente sombreado es el rango editable

Imagina una plantilla de contrato que se envía a decenas de clientes. El equipo legal ha redactado con cuidado cada cláusula, y lo único que cada destinatario debería tocar son el bloque de firma, el nombre del proyecto y la fecha de aceptación. Entrega un archivo de Word totalmente editable y alguien acabará reformulando una cláusula de penalización o eliminando una sección de responsabilidad. Bloquea todo el documento y nadie podrá rellenar los campos. Lo que realmente necesitas es edición selectiva: una forma de decir "estos párrafos concretos son editables, todo lo demás está congelado".

Eso es exactamente lo que te ofrecen los rangos editables. Proteges todo el documento como solo lectura y luego colocas un par de marcadores de permiso alrededor de los párrafos que quieres mantener abiertos. Cualquiera que abra el archivo en Word puede escribir dentro de la región marcada, pero no puede alterar ni un solo carácter fuera de ella. Spire.Doc for JavaScript lleva esta capacidad al navegador mediante WebAssembly, de modo que puedes generar documentos protegidos desde una aplicación React sin idas y vueltas al servidor: las fuentes y los archivos de entrada se gestionan a través de un sistema de archivos virtual (VFS) en memoria.

Esta guía recorre ambas partes del flujo de trabajo:

Si aún no has integrado Spire.Doc en tu proyecto, empieza por Integrar Spire.Doc for JavaScript en un proyecto de React. Los fragmentos siguientes suponen que el módulo WebAssembly está cargado y listo.


Establecer un rango editable

El proceso tiene tres etapas. Primero, carga los archivos de fuentes y el documento de Word de destino en el sistema de archivos virtual de WASM con FetchFileToVFS. A continuación, crea una instancia de Document, carga el archivo, llama a Protect para bloquear todo el documento como solo lectura y luego crea un par PermissionStart / PermissionEnd que comparta el mismo id: estos dos marcadores delimitan el párrafo que quieres dejar editable. Por último, guarda el archivo, vuelve a leerlo desde el VFS, envuélvelo en un Blob y activa la descarga.

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;

En el archivo de ejemplo, los campos que el revisor puede rellenar llevan un sombreado claro: es solo una pista visual para el lector y no influye en cómo se define el rango editable en el código. Una vez colocados los marcadores, Word trata el párrafo sombreado como editable y todos los demás como bloqueados.

El documento después de establecer un rango editable; el párrafo ligeramente sombreado es el rango editable


Eliminar un rango editable

Quitar el rango editable es un único recorrido: itera por cada sección y cada párrafo, inspecciona cada objeto de la colección ChildObjects del párrafo y extrae cualquier cosa que sea un PermissionStart o un PermissionEnd.

Un detalle sutil suele pillar desprevenidos a muchos: ChildObjects.Remove reduce la colección en el acto, por lo que cada elemento posterior al eliminado se desplaza un índice hacia delante. Si incrementas el contador del bucle mientras eliminas, cada eliminación provoca que se omita el marcador inmediatamente siguiente, y cuantos más marcadores tengas, más supervivientes dejarás atrás.

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;

Eliminar los marcadores solo redibuja el límite de lo que es editable: el texto en sí y todo el formato permanecen intactos.

El documento después de eliminar los marcadores de rango editable; el contenido y el formato permanecen sin cambios


El ciclo de vida completo de la protección

En un flujo de trabajo de aprobación real, rara vez haces solo una cosa. Un ciclo típico de ida y vuelta es así:

  1. Proteger: llama a doc.Protect con AllowOnlyReading (o AllowOnlyFormFields) y una contraseña. Todo el documento queda bloqueado.
  2. Marcar: envuelve cada párrafo editable por el revisor en un par PermissionStart / PermissionEnd que comparta un mismo id. Esas regiones pasan a ser los únicos lugares donde el revisor puede escribir.
  3. Desmarcar: cuando termina la ronda de revisión, recorre el documento y elimina todos los marcadores de permiso. Las regiones vuelven a formar parte del cuerpo de solo lectura.
  4. Desproteger: llama a doc.Unprotect("password") para liberar el documento por completo, devolviéndolo a un estado totalmente editable para la siguiente etapa del procesamiento.

La clave está en que la protección y los rangos editables son dos capas independientes. La protección decide si el documento está bloqueado; el par de marcadores decide qué pequeñas porciones quedan exentas de ese bloqueo. Puedes añadir y eliminar marcadores tantas veces como quieras sin tocar el estado de protección, y puedes activar o desactivar la protección sin alterar los marcadores, pero los marcadores solo tienen efecto mientras la protección está activa.


Preguntas frecuentes

El rango editable está establecido, pero el contenido dentro de él aún no se puede editar

Por qué ocurre: los marcadores de permiso son inertes por sí solos. Solo establecen excepciones a una restricción que abarca todo el documento, así que si nunca se llamó a Protect, no hay ninguna restricción de la que eximirse y los marcadores no hacen nada. Un segundo requisito es que PermissionStart y PermissionEnd lleven la misma cadena de id: Word solo los trata como un par cuando los ids coinciden.

Solución: activa primero la restricción de edición y luego crea ambos marcadores con un id idéntico:

// 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");

Algunos marcadores se omiten al eliminar rangos editables

Por qué ocurre: cada llamada a ChildObjects.Remove reduce la colección en uno, desplazando hacia abajo el índice de todos los elementos siguientes. Si el contador del bucle avanza en la misma iteración que una eliminación, el elemento que se deslizó a la posición actual nunca se examina: se omite, y el problema se agrava con cada marcador adicional.

Solución: mantén el índice fijo mientras eliminas (avánzalo solo cuando no se haya producido ninguna eliminación) o reúne primero los objetos objetivo y elimínalos en orden inverso:

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++;
  }
}

El documento sigue siendo de solo lectura después de eliminar los marcadores

Por qué ocurre: los marcadores solo definen qué áreas quedan exentas del bloqueo; no son el bloqueo en sí. Eliminarlos simplemente quita las exenciones; la protección subyacente que estableció Protect sigue vigente, por lo que todo el documento permanece de solo lectura.

Solución: una vez que los marcadores han desaparecido y ya no necesitas la restricción, llama a Unprotect con la contraseña original:

document.Unprotect("password");

Véase también

The document after an editable range is set; the lightly shaded paragraph is the editable range

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:

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.

The document after an editable range is set; the lightly shaded paragraph is the editable range


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.

The document after the editable range markers are removed; the content and formatting stay unchanged


Der vollständige Schutz-Lebenszyklus

In einem realen Genehmigungsworkflow tun Sie selten nur eine einzige Sache. Ein typischer Durchlauf sieht so aus:

  1. Schützen — Rufen Sie doc.Protect mit AllowOnlyReading (oder AllowOnlyFormFields) und einem Kennwort auf. Das gesamte Dokument ist nun gesperrt.
  2. 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.
  3. 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.
  4. 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");

Siehe auch

Page 2 of 28