Blocca le aree modificabili nei documenti Word con JavaScript

2026-09-30 09:24:39 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

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