
JavaScript pode gerar pastas de trabalho do Excel diretamente no navegador. Com o Spire.XLS para JavaScript, você pode criar uma pasta de trabalho, adicionar planilhas, escrever valores e fórmulas, aplicar formatação e salvar o resultado como um arquivo XLSX ou XLS — tudo no lado do cliente, sem necessidade de instalação do Microsoft Excel.
Este tutorial começa com uma pasta de trabalho XLSX básica e depois adiciona valores de célula tipados, fórmulas, formatação, várias planilhas, suporte a download no navegador, conversão de CSV e saída XLS para compatibilidade com sistemas legados.
Instalar e Inicializar o Spire.XLS para JavaScript
O Spire.XLS para JavaScript vem dentro do pacote spire.office, junto com Spire.PDF, Spire.Doc e Spire.Presentation:
npm i spire.office
Iniciar o runtime exige duas importações. A primeira inicia o host WebAssembly .NET compartilhado; a segunda registra a API de planilhas:
// 1. Boot the shared runtime once per page.
const common = await import('/node_modules/spire.office/spire.common.js');
await common.initializeWasm();
// 2. Load the spreadsheet engine — this is what creates window.spirexls.
await import('/node_modules/spire.office/spire.xls.js');
Os arquivos Spire.*.Wasm.zip e a pasta _framework precisam estar acessíveis a partir da raiz do site. O runtime os resolve em relação à URL do documento, e não em relação ao módulo que fez a importação, então em um projeto Vite ou Create React App eles precisam ficar em public/. O prefixo process.env.PUBLIC_URL mostrado em configurações baseadas em React é uma convenção do Create React App, não um padrão do navegador — ajuste o caminho base para corresponder à sua ferramenta de build se você não estiver usando CRA. Se os arquivos estiverem ausentes, o navegador registra WebAssembly.compile(): expected magic word — o servidor de desenvolvimento respondeu à solicitação do arquivo com index.html.
Depois, tudo depende de um único global:
const xls = window.spirexls;
Na configuração atual do pacote usada por este tutorial, a API de planilhas é exposta por meio de window.spirexls. Use esse global após o runtime ter sido inicializado. Versões mais antigas a expunham como window.wasmModule.spirexls; se você estiver trabalhando com uma versão diferente do pacote, verifique qual global está disponível.
Agora você está pronto para gerar arquivos Excel.
Criar um Arquivo Excel Básico em JavaScript
Vamos criar um relatório de vendas. Criaremos uma pasta de trabalho, adicionaremos uma planilha, escreveremos dados de produtos nas células e salvaremos o resultado como um arquivo XLSX que é baixado automaticamente.
async function createExcelFile() {
const xls = window.spirexls;
if (!xls) {
console.error('Spire.XLS is not initialized.');
return;
}
// A fresh Workbook() already contains three blank worksheets, so clear them
// and add the single sheet this report needs.
const workbook = new xls.Workbook();
workbook.Worksheets.Clear();
const sheet = workbook.Worksheets.Add("Sales Report");
// Sample data: product sales
const data = [
["Product", "Quantity", "Price"],
["Laptop", 10, 999.99],
["Mouse", 50, 24.99],
["Keyboard", 30, 59.99],
["Monitor", 15, 329.99]
];
// Write data to cells
for (let row = 0; row < data.length; row++) {
for (let col = 0; col < data[row].length; col++) {
const cell = sheet.Range.get({ row: row + 1, column: col + 1 });
if (typeof data[row][col] === "string") {
cell.Text = data[row][col];
} else {
cell.NumberValue = data[row][col];
}
}
}
// Save to the virtual file system, read the bytes, download, then dispose
const fileName = "SalesReport.xlsx";
workbook.SaveToFile({
fileName: fileName,
version: xls.ExcelVersion.Version2016
});
const fileData = window.dotnetRuntime.Module.FS.readFile(fileName);
const blob = new Blob([fileData], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);
workbook.Dispose();
}
Chame createExcelFile() e você obterá um SalesReport.xlsx com quatro linhas de produtos mais um cabeçalho. O fluxo de trabalho é simples: criar pasta de trabalho → escrever dados → salvar → baixar.
As seções a seguir ampliam este exemplo. Cada trecho de código pressupõe que seja adicionado dentro de createExcelFile() depois que a pasta de trabalho e a planilha tiverem sido criadas.

Escrever Diferentes Tipos de Dados em Células do Excel
O Excel distingue entre texto, números, datas e booleanos. Errar isso leva a arquivos nos quais a classificação quebra, as fórmulas retornam erros e os números são exibidos como texto.
const sheet = workbook.Worksheets.get(0);
// Text — for labels, names, descriptions
sheet.Range.get("A1").Text = "Product Name";
// Number — for anything you'll calculate, sort, or filter
sheet.Range.get("B1").NumberValue = 999.99;
// Date — a real DateTimeValue plus a display format
const dateCell = sheet.Range.get("C1");
dateCell.DateTimeValue = new Date(Date.UTC(2025, 2, 15));
dateCell.NumberFormat = "yyyy-mm-dd";
// Boolean — use BooleanValue, not text
sheet.Range.get("D1").BooleanValue = true;
O erro mais comum? Escrever cell.Text = "999.99" em vez de cell.NumberValue = 999.99. O valor parece idêntico ao abrir o arquivo, mas o Excel o trata como texto — você não pode somá-lo, calcular a média ou classificá-lo numericamente. Sempre use NumberValue para números, DateTimeValue para datas e BooleanValue para booleanos.
Datas exigem uma precaução extra. DateTimeValue preserva o instante UTC representado pelo Date do JavaScript. Criar uma data com meia-noite local pode, portanto, deslocar o dia exibido em alguns fusos horários; use Date.UTC() quando quiser que uma data de calendário específica seja preservada.
Adicionar Fórmulas à Planilha do Excel
As fórmulas fazem do seu arquivo gerado uma planilha de verdade, e não apenas um despejo de dados. Vamos adicionar uma coluna Total que calcula Quantity × Price para cada linha, além de um total geral na parte inferior:
// Add "Total" header
sheet.Range.get({ row: 1, column: 4 }).Text = "Total";
// Per-row formula: Total = Quantity × Price
for (let i = 2; i <= 5; i++) {
sheet.Range.get({ row: i, column: 4 }).Formula = `=B${i}*C${i}`;
}
// Grand total row
sheet.Range.get({ row: 6, column: 1 }).Text = "Total";
sheet.Range.get({ row: 6, column: 2 }).Formula = "=SUM(B2:B5)";
sheet.Range.get({ row: 6, column: 4 }).Formula = "=SUM(D2:D5)";
// Evaluate the formulas once, so their results are written into the file.
workbook.CalculateAllValue();
Chame workbook.CalculateAllValue() antes de salvar quando precisar que a pasta de trabalho gerada contenha resultados de fórmulas calculados. Isso é útil para visualizadores ou aplicativos que dependem de valores em cache em vez de recalcular fórmulas ao abrir.
Para um guia abrangente sobre funções do Excel e operações com fórmulas, consulte Inserir ou Ler Funções e Fórmulas em Planilhas do Excel com JavaScript no React.
Formatar o Arquivo Excel Gerado
Uma planilha com dados brutos funciona, mas uma planilha formatada comunica. Vamos transformar nosso relatório de vendas em algo que você realmente enviaria a uma parte interessada:
// Bold, colored header row
const header = sheet.Range.get("A1:D1");
header.Style.Font.IsBold = true;
header.Style.Font.Size = 12;
header.Style.Color = xls.Color.get_LightSkyBlue();
// Currency format for Price and Total columns
for (let i = 2; i <= 5; i++) {
sheet.Range.get({ row: i, column: 3 }).NumberFormat = "$#,##0.00";
sheet.Range.get({ row: i, column: 4 }).NumberFormat = "$#,##0.00";
}
// Set column widths explicitly
[26, 10, 12, 12].forEach((width, i) => {
sheet.Columns.get(i).ColumnWidth = width;
});
// Clean borders
const usedRange = sheet.Range.get("A1:D6");
usedRange.Borders.LineStyle = xls.LineStyleType.Thin;
usedRange.Borders.Color = xls.Color.get_LightSteelBlue();
Dois detalhes vale a pena conhecer aqui. sheet.Columns.get(i) e sheet.Rows.get(i) são baseados em 0 e usam get, diferentemente do get_Item que outras coleções expõem. E na configuração de navegador testada, AutoFitColumn exige uma fonte que não está disponível no sandbox do WebAssembly, então definir ColumnWidth explicitamente é mais confiável.
O resultado: um cabeçalho azul em negrito, preços formatados como moeda, colunas com tamanho adequado e bordas limpas.
Para orientações detalhadas sobre dimensões de linhas e colunas, consulte Definir Altura da Linha e Largura da Coluna no Excel com JavaScript no React.
Criar Várias Planilhas em uma Pasta de Trabalho do Excel
Relatórios reais raramente cabem em uma única planilha. Um relatório de vendas pode ter um resumo na primeira aba, detalhes de produtos na segunda e detalhamentos mensais na terceira.
workbook.Worksheets.Clear();
const summarySheet = workbook.Worksheets.Add("Summary");
const productsSheet = workbook.Worksheets.Add("Products");
const monthlySheet = workbook.Worksheets.Add("Monthly Data");
// Products sheet — write actual data so cross-sheet formulas work
productsSheet.Range.get("A1").Text = "Product";
productsSheet.Range.get("B1").Text = "Quantity";
productsSheet.Range.get("C1").Text = "Price";
productsSheet.Range.get("D1").Text = "Total";
const products = [
["Laptop", 10, 999.99],
["Mouse", 50, 24.99],
["Keyboard", 30, 59.99],
["Monitor", 15, 329.99]
];
for (let i = 0; i < products.length; i++) {
const row = i + 2;
productsSheet.Range.get({ row: row, column: 1 }).Text = products[i][0];
productsSheet.Range.get({ row: row, column: 2 }).NumberValue = products[i][1];
productsSheet.Range.get({ row: row, column: 3 }).NumberValue = products[i][2];
productsSheet.Range.get({ row: row, column: 4 }).Formula = `=B${row}*C${row}`;
}
// Summary sheet with cross-sheet reference
summarySheet.Range.get("A1").Text = "Sales Summary";
summarySheet.Range.get("A1").Style.Font.IsBold = true;
summarySheet.Range.get("A2").Text = "Total Products";
summarySheet.Range.get("B2").NumberValue = 4;
summarySheet.Range.get("A3").Text = "Total Revenue";
summarySheet.Range.get("B3").Formula = "=SUM(Products!D2:D5)";
Cada Worksheets.Add(name) retorna a planilha que acabou de criar, na ordem em que as chamadas são feitas, então a ordem das abas corresponde à ordem do código. Observe a fórmula entre planilhas: =SUM(Products!D2:D5) na planilha Summary faz referência à coluna Total na planilha Products. O Excel lida com isso automaticamente quando o arquivo é aberto — nenhum código extra é necessário.

Para mais informações sobre gerenciamento de planilhas — adicionar, remover e reordenar planilhas — consulte Adicionar, Remover e Mover Planilhas do Excel com JavaScript no React.
Salvar e Baixar o Arquivo XLSX no Navegador
Depois que sua pasta de trabalho estiver pronta, o Spire.XLS a salva em um sistema de arquivos virtual do WebAssembly. Em seguida, você lê os dados do arquivo, converte-os em um Blob e dispara o download:
workbook.SaveToFile({
fileName: "Report.xlsx",
version: xls.ExcelVersion.Version2016
});
const fileData = window.dotnetRuntime.Module.FS.readFile("Report.xlsx");
const blob = new Blob([fileData], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "Report.xlsx";
a.click();
URL.revokeObjectURL(url);
workbook.Dispose();
Sempre chame workbook.Dispose() após o download para liberar memória — especialmente em aplicativos nos quais os usuários geram vários arquivos em uma sessão. A pasta de trabalho em si permanece no heap do WebAssembly até você fazer isso, e esse heap não é recuperado pelo coletor de lixo do navegador.
Procurando integração com React ou exportação de tabela HTML? Confira nosso guia para baixar e exportar arquivos Excel em JavaScript e React.
Juntando Tudo: Um Relatório de Vendas Formatado
Os trechos acima constroem uma pasta de trabalho um aspecto de cada vez. Aqui eles estão em uma única função: uma planilha estilizada com faixas zebradas e formatos de moeda, colunas de receita e participação orientadas por fórmulas, um gráfico de colunas e uma segunda planilha que consolida os números.
/**
* Build a formatted sales report workbook in the browser and download it as
* SalesReport.xlsx.
*
* The layout is driven by `products` below — swap it for form input, an API
* response or component state and nothing else needs to change.
*/
async function createExcelReport() {
// spire.office 11.7.0 exposes Spire.XLS as `window.spirexls`. Older builds
// hung it off `window.wasmModule.spirexls`; that global no longer exists.
const xls = window.spirexls;
if (!xls) throw new Error('Spire.XLS is not ready yet');
// [product, units sold, unit price] — revenue and share are derived by formula
const products = [
['Atlas 14 Ultrabook', 42, 1249.0],
['Orbit Wireless Mouse', 380, 24.99],
['Vertex Mechanical Keyboard', 165, 89.5],
['Lumen 27 4K Monitor', 74, 429.0],
['Halo USB-C Dock', 210, 139.0],
['Pulse ANC Headset', 128, 199.0],
];
const FIRST = 5; // first data row
const TOTAL = FIRST + products.length; // total row
const wb = new xls.Workbook();
wb.Worksheets.Clear();
const sheet = wb.Worksheets.Add('Sales Report');
const at = (a) => sheet.Range.get(a);
const cell = (row, col) => sheet.Range.get({ row: row, column: col });
const paint = (a, colour) => {
at(a).Style.Color = colour;
};
// ── Sizing ── explicit widths (AutoFitColumn is unreliable in the WASM sandbox)
[34, 9, 13, 14, 9].forEach((w, i) => {
sheet.Columns.get(i).ColumnWidth = w;
});
sheet.Rows.get(0).RowHeight = 34; // title
sheet.Rows.get(1).RowHeight = 20; // subtitle
sheet.Rows.get(2).RowHeight = 8; // spacer
sheet.Rows.get(3).RowHeight = 24; // header
// ── Title band ── merge first, then style the whole merged area
at('A1:E1').Merge();
cell(1, 1).Text = 'Sales Report — Q3 2026';
paint('A1:E1', xls.Color.get_DarkBlue());
at('A1:E1').Style.Font.Color = xls.Color.get_White();
at('A1:E1').Style.Font.IsBold = true;
at('A1:E1').Style.Font.Size = 15;
at('A1:E1').Style.VerticalAlignment = xls.VerticalAlignType.Center;
at('A2:E2').Merge();
cell(2, 1).Text = 'Region: West · Period: 1 Jul – 30 Sep 2026 · Amounts in USD';
paint('A2:E2', xls.Color.get_DarkBlue());
at('A2:E2').Style.Font.Color = xls.Color.get_LightSteelBlue();
at('A2:E2').Style.Font.Size = 9.5;
at('A2:E2').Style.VerticalAlignment = xls.VerticalAlignType.Center;
// ── Header row ───────────────────────────────────────────────────────────
['Product', 'Units', 'Unit Price', 'Revenue', 'Share'].forEach((label, i) => {
cell(4, i + 1).Text = label;
});
paint('A4:E4', xls.Color.get_LightSteelBlue());
at('A4:E4').Style.Font.Color = xls.Color.get_DarkBlue();
at('A4:E4').Style.Font.IsBold = true;
at('A4:E4').Style.Font.Size = 10.5;
at('A4:E4').Style.HorizontalAlignment = xls.HorizontalAlignType.Center;
at('A4:E4').Style.VerticalAlignment = xls.VerticalAlignType.Center;
// ── Data rows ── numbers go in as NumberValue, never as text
products.forEach(([name, units, price], i) => {
const r = FIRST + i;
cell(r, 1).Text = name;
cell(r, 2).NumberValue = units;
cell(r, 3).NumberValue = price;
cell(r, 4).Formula = `=B${r}*C${r}`;
cell(r, 5).Formula = `=D${r}/$D${TOTAL}`; // share of the grand total
sheet.Rows.get(r - 1).RowHeight = 20;
if (i % 2) paint(`A${r}:E${r}`, xls.Color.get_WhiteSmoke()); // zebra banding
});
// ── Total row ────────────────────────────────────────────────────────────
cell(TOTAL, 1).Text = 'Total';
[2, 4, 5].forEach((col) => {
const letter = String.fromCharCode(64 + col);
cell(TOTAL, col).Formula = `=SUM(${letter}${FIRST}:${letter}${TOTAL - 1})`;
});
paint(`A${TOTAL}:E${TOTAL}`, xls.Color.get_LightSkyBlue());
at(`A${TOTAL}:E${TOTAL}`).Style.Font.IsBold = true;
sheet.Rows.get(TOTAL - 1).RowHeight = 22;
// ── Number formats and borders ───────────────────────────────────────────
at(`B${FIRST}:B${TOTAL}`).NumberFormat = '#,##0';
at(`C${FIRST}:D${TOTAL}`).NumberFormat = '$#,##0.00';
at(`E${FIRST}:E${TOTAL}`).NumberFormat = '0.0%';
const table = at(`A4:E${TOTAL}`);
table.Borders.LineStyle = xls.LineStyleType.Thin;
table.Borders.Color = xls.Color.get_LightSteelBlue();
at(`A${TOTAL}:E${TOTAL}`).Borders.get_Item(xls.BordersLineType.EdgeTop).LineStyle =
xls.LineStyleType.Medium;
// ── Chart ── build the series by hand (DataRange would mix units)
const chart = sheet.Charts.Add();
chart.ChartType = xls.ExcelChartType.ColumnClustered;
chart.LeftColumn = 6;
chart.TopRow = 3;
chart.RightColumn = 13;
chart.BottomRow = 21;
const serie = chart.Series.Add();
serie.CategoryLabels = at(`A${FIRST}:A${TOTAL - 1}`);
serie.Values = at(`D${FIRST}:D${TOTAL - 1}`);
serie.Name = 'Revenue';
chart.ChartTitleArea.Text = 'Revenue by product';
chart.HasLegend = false;
chart.PrimaryValueAxis.NumberFormat = '$#,##0';
// ── Sheet chrome ──
sheet.FreezePanes(FIRST, 1);
sheet.GridLinesVisible = false;
sheet.TabColor = xls.Color.get_DarkBlue();
// ── Second worksheet: cross-sheet roll-up ──
const summary = wb.Worksheets.Add('Summary');
summary.Columns.get(0).ColumnWidth = 26;
summary.Columns.get(1).ColumnWidth = 18;
summary.Rows.get(0).RowHeight = 30;
summary.Rows.get(1).RowHeight = 18;
summary.Rows.get(3).RowHeight = 22;
const band = (a, text, size) => {
summary.Range.get(a).Merge();
summary.Range.get(a.split(':')[0]).Text = text;
summary.Range.get(a).Style.Color = xls.Color.get_DarkBlue();
summary.Range.get(a).Style.Font.Color = xls.Color.get_White();
summary.Range.get(a).Style.Font.IsBold = true;
summary.Range.get(a).Style.Font.Size = size;
summary.Range.get(a).Style.VerticalAlignment = xls.VerticalAlignType.Center;
};
band('A1:B1', 'Executive Summary', 14);
band('A2:B2', 'Sales Report · Q3 2026', 9.5);
['Metric', 'Value'].forEach((label, i) => {
summary.Range.get({ row: 4, column: i + 1 }).Text = label;
});
summary.Range.get('A4:B4').Style.Color = xls.Color.get_LightSteelBlue();
summary.Range.get('A4:B4').Style.Font.Color = xls.Color.get_DarkBlue();
summary.Range.get('A4:B4').Style.Font.IsBold = true;
[
['Total revenue', "='Sales Report'!D" + TOTAL, '$#,##0.00'],
['Units shipped', "='Sales Report'!B" + TOTAL, '#,##0'],
['Average unit price', `='Sales Report'!D${TOTAL}/'Sales Report'!B${TOTAL}`, '$#,##0.00'],
].forEach(([label, formula, format], i) => {
summary.Range.get({ row: 5 + i, column: 1 }).Text = label;
const value = summary.Range.get({ row: 5 + i, column: 2 });
value.Formula = formula;
value.NumberFormat = format;
value.Style.HorizontalAlignment = xls.HorizontalAlignType.Right;
if (i % 2) summary.Range.get(`A${5 + i}:B${5 + i}`).Style.Color = xls.Color.get_WhiteSmoke();
});
// Date — use Date.UTC to avoid timezone shift
summary.Range.get('A8').Text = 'Report date';
const reportDate = summary.Range.get('B8');
reportDate.DateTimeValue = new Date(Date.UTC(2026, 8, 28));
reportDate.NumberFormat = 'yyyy-mm-dd';
reportDate.Style.HorizontalAlignment = xls.HorizontalAlignType.Right;
const kpis = summary.Range.get('A4:B8');
kpis.Borders.LineStyle = xls.LineStyleType.Thin;
kpis.Borders.Color = xls.Color.get_LightSteelBlue();
summary.GridLinesVisible = false;
summary.TabColor = xls.Color.get_LightSteelBlue();
// ── Save, then release ──
wb.CalculateAllValue();
const fileName = 'SalesReport.xlsx';
wb.SaveToFile({ fileName: fileName, version: xls.ExcelVersion.Version2016 });
const fileData = window.dotnetRuntime.Module.FS.readFile(fileName);
const blob = new Blob([fileData], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
const url = URL.createObjectURL(blob);
Object.assign(document.createElement('a'), { href: url, download: fileName }).click();
URL.revokeObjectURL(url);
wb.Dispose(); // free the WASM heap — one workbook per generation cycle
}
O layout segue os dados. Substitua o array products por uma resposta da sua própria API e todo o resto — totais, percentuais de participação, o intervalo do gráfico, a consolidação do resumo — continua funcionando, porque tudo é expresso como fórmulas ou intervalos derivados, e não como valores codificados fixamente.

Para mais tipos de gráfico e opções de configuração, consulte Criar Gráficos do Excel com JavaScript no React.
Criar um Arquivo Excel a Partir de Dados CSV
Você pode carregar dados tabulares de um arquivo CSV em uma planilha e salvar o resultado como XLSX. A pasta de trabalho resultante pode então ser formatada ou ampliada com fórmulas e planilhas adicionais:
// The library reads from its own virtual file system, so the CSV has to be
// there before you can load it — written from a string here, from the bytes of
// a File object in a real application.
const csv = "Product,Quantity,Price\nLaptop,10,999.99\nMouse,50,24.99\nKeyboard,30,59.99";
window.dotnetRuntime.Module.FS.writeFile("data.csv", new TextEncoder().encode(csv));
workbook.LoadFromFile("data.csv", ",");
workbook.SaveToFile({
fileName: "ConvertedFromCSV.xlsx",
version: xls.ExcelVersion.Version2016
});
A planilha importada recebe o nome do arquivo (data), então Worksheets.get(0) a seleciona.
O separador é um segundo argumento obrigatório. LoadFromFile("data.csv") sozinho é rejeitado com This is not a structured storage file, porque a sobrecarga de argumento único espera um formato estruturado como .xlsx ou .xls e não detecta CSV.
Há um segundo problema: o importador de CSV grava todos os campos como texto. Uma coluna de quantidade chega como "10" em vez de 10, o que significa que não pode ser somada ou classificada numericamente — exatamente o problema descrito anteriormente neste tutorial. Converta as colunas necessárias antes de salvar:
const csvSheet = workbook.Worksheets.get(0);
// The importer leaves every field as text — coerce each numeric column.
// Columns 2 and 3 hold Quantity and Price; both arrive as "10" and "999.99".
for (let row = 2; row <= 4; row++) {
[2, 3].forEach((column) => {
const cell = csvSheet.Range.get({ row: row, column: column });
if (cell.Text !== "") {
cell.NumberValue = Number(cell.Text);
}
});
}
Para um guia completo sobre conversão entre os formatos CSV e Excel, consulte nosso tutorial de conversão de CSV para Excel.
Criar um Arquivo XLS em Vez de XLSX
Se seu aplicativo precisar gerar o formato legado .xls em vez de .xlsx, altere o parâmetro version:
workbook.SaveToFile({
fileName: "Report.xls",
version: xls.ExcelVersion.Version97to2003
});
O membro de enum é Version97to2003 — não existe Version97. Mantenha gráficos em XLSX; o gravador XLS testado falha quando métricas de fonte de gráfico são necessárias.
XLSX (Excel 2007+) é o formato recomendado para novos aplicativos. XLS (Excel 97–2003) só é necessário quando a compatibilidade com versões anteriores é exigida.
Problemas Comuns
window.wasmModule é indefinido. Exemplos mais antigos liam a API de planilhas de window.wasmModule.spirexls. Versões atuais a instalam diretamente em window.spirexls e deixam wasmModule indefinido, então o primeiro acesso já lança erro. Verifique window.spirexls em vez disso.
Módulo WASM não inicializado. Se window.spirexls estiver indefinido, o runtime ainda não terminou de carregar. Mostre um indicador de carregamento e espere a inicialização terminar antes de tentar qualquer operação do Excel.
Auto-fit lança um erro de fonte. AutoFitColumn e AutoFitRow precisam de uma fonte do sistema para medir o texto, e o sandbox do WebAssembly não tem nenhuma. Eles falham com Cannot found font(Arial) installed on the system. Calcule ou codifique fixamente as larguras das colunas com sheet.Columns.get(i).ColumnWidth.
Números armazenados como texto. Usar cell.Text = "100" em vez de cell.NumberValue = 100 quebra a classificação e os cálculos. Este é o problema mais comum que os desenvolvedores encontram ao escrever arquivos Excel em JavaScript, e a importação de CSV o aciona automaticamente — sempre use NumberValue para dados numéricos.
Uma planilha "Evaluation Warning" aparece. Ao usar a versão de avaliação sem uma licença válida, o Spire.XLS adiciona uma planilha de avaliação à pasta de trabalho salva. Essa planilha é recriada ao salvar, então removê-la programaticamente não é uma solução confiável. Aplique uma chave de licença para evitá-la.
Vazamentos de memória em aplicativos de longa duração. Chame workbook.Dispose() após cada ciclo de geração. Em aplicativos de página única, pastas de trabalho não descartadas acumulam memória e degradam o desempenho com o tempo.
Perguntas Frequentes
O JavaScript pode criar arquivos Excel sem o Microsoft Excel?
Sim. O Spire.XLS para JavaScript é executado inteiramente no navegador via WebAssembly. Nenhuma instalação do Microsoft Excel ou do Office no lado do servidor é necessária para gerar arquivos XLSX.
O JavaScript pode criar arquivos XLSX diretamente no navegador?
Sim. Todas as operações de planilha acontecem no lado do cliente. O arquivo é salvo em um sistema de arquivos virtual e depois baixado como um Blob — nenhum servidor de backend é necessário.
Qual é a diferença entre XLS e XLSX?
XLSX (Excel 2007 e posteriores) é o formato moderno baseado em XML, recomendado para novos aplicativos. XLS (Excel 97–2003) é o formato binário legado, útil para compatibilidade com sistemas mais antigos.
Conclusão
Criar arquivos Excel em JavaScript não exige um servidor de backend ou o Microsoft Excel. Com o Spire.XLS para JavaScript, você pode construir pastas de trabalho do zero, escrever dados tipados, adicionar fórmulas, aplicar formatação e organizar dados em várias planilhas — tudo no navegador.
Comece com o exemplo básico acima e depois adicione fórmulas e formatação conforme suas necessidades crescerem. Para integração específica com React e exportação de tabela HTML, consulte nosso tutorial dedicado de exportação.