Bloqueie áreas editáveis em documentos do Word com JavaScript

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

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