
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:
- Definir um intervalo editável — proteger o documento e marcar a área aberta
- Remover um intervalo editável — retirar os marcadores e suspender a restrição
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.

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 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:
-
Proteger — Chame
doc.ProtectcomAllowOnlyReading(ouAllowOnlyFormFields) e uma senha. Todo o documento agora está bloqueado. -
Marcar — Envolva cada parágrafo editável pelo revisor em um par
PermissionStart/PermissionEndque compartilhe um mesmo id. Essas regiões se tornam os únicos lugares onde o revisor pode digitar. - 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.
-
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");