Comment créer des fichiers Excel en JavaScript (XLSX/XLS)

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

Créer des fichiers Excel en JavaScript avec Spire.XLS — du navigateur vers XLSX et XLS

JavaScript peut générer des classeurs Excel directement dans le navigateur. Avec Spire.XLS pour JavaScript, vous pouvez créer un classeur, ajouter des feuilles de calcul, écrire des valeurs et des formules, appliquer une mise en forme et enregistrer le résultat au format XLSX ou XLS — entièrement côté client, sans nécessiter l'installation de Microsoft Excel.

Ce tutoriel commence par un classeur XLSX de base, puis ajoute des valeurs de cellules typées, des formules, une mise en forme, plusieurs feuilles de calcul, la prise en charge du téléchargement dans le navigateur, la conversion CSV et l'export XLS pour la compatibilité avec les formats hérités.

Installer et initialiser Spire.XLS pour JavaScript

Spire.XLS pour JavaScript est fourni dans le package spire.office, avec Spire.PDF, Spire.Doc et Spire.Presentation :

npm i spire.office

Le démarrage du runtime nécessite deux imports. Le premier lance l'hôte .NET WebAssembly partagé ; le second enregistre l'API de feuille de calcul :

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

Les archives Spire.*.Wasm.zip et le dossier _framework doivent être accessibles depuis la racine du site. Le runtime les résout par rapport à l'URL du document plutôt qu'au module qui a effectué l'import ; dans un projet Vite ou Create React App, ils doivent donc se trouver dans public/. Le préfixe process.env.PUBLIC_URL présenté dans les configurations basées sur React est une convention de Create React App, et non un standard du navigateur — ajustez le chemin de base en fonction de votre outil de build si vous n'utilisez pas CRA. Si les archives sont manquantes, le navigateur consigne WebAssembly.compile(): expected magic word — le serveur de développement a répondu à la requête d'archive avec index.html.

Tout repose ensuite sur un seul global :

const xls = window.spirexls;

Dans la configuration de package actuelle utilisée par ce tutoriel, l'API de feuille de calcul est exposée via window.spirexls. Utilisez ce global après l'initialisation du runtime. Les versions plus anciennes l'exposaient sous window.wasmModule.spirexls ; si vous travaillez avec une version de package différente, vérifiez quel global est disponible.

Vous êtes maintenant prêt à générer des fichiers Excel.

Créer un fichier Excel de base en JavaScript

Construisons un rapport de ventes. Nous allons créer un classeur, ajouter une feuille de calcul, écrire les données produits dans les cellules et enregistrer le résultat sous la forme d'un fichier XLSX qui se télécharge automatiquement.

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();
}

Appelez createExcelFile() et vous obtiendrez un SalesReport.xlsx contenant quatre lignes de produits plus un en-tête. Le flux de travail est simple : créer le classeur → écrire les données → enregistrer → télécharger.

Les sections suivantes étendent cet exemple. Chaque extrait de code suppose qu'il est ajouté à l'intérieur de createExcelFile() après la création du classeur et de la feuille de calcul.

SalesReport.xlsx généré par la fonction createExcelFile() de base

Écrire différents types de données dans les cellules Excel

Excel distingue le texte, les nombres, les dates et les booléens. Se tromper à ce sujet produit des fichiers où le tri ne fonctionne plus, où les formules renvoient des erreurs et où les nombres s'affichent sous forme de texte.

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;

L'erreur la plus courante ? Écrire cell.Text = "999.99" au lieu de cell.NumberValue = 999.99. La valeur semble identique à l'ouverture du fichier, mais Excel la traite comme du texte — vous ne pouvez ni l'additionner, ni en faire la moyenne, ni la trier numériquement. Utilisez toujours NumberValue pour les nombres, DateTimeValue pour les dates et BooleanValue pour les booléens.

Les dates nécessitent une précaution supplémentaire. DateTimeValue conserve l'instant UTC représenté par l'objet Date JavaScript. Créer une date avec minuit en heure locale peut donc décaler le jour affiché dans certains fuseaux horaires ; utilisez Date.UTC() lorsque vous souhaitez préserver une date calendaire précise.

Ajouter des formules à la feuille de calcul Excel

Les formules font de votre fichier généré une véritable feuille de calcul, et non un simple export de données. Ajoutons une colonne Total qui calcule Quantity × Price pour chaque ligne, ainsi qu'un total général en bas :

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

Appelez workbook.CalculateAllValue() avant d'enregistrer lorsque vous avez besoin que le classeur généré contienne les résultats calculés des formules. Cela est utile pour les visionneuses ou les applications qui s'appuient sur des valeurs mises en cache au lieu de recalculer les formules à l'ouverture.

Pour un guide complet des fonctions Excel et des opérations sur les formules, consultez Insérer ou lire des fonctions et des formules dans les feuilles de calcul Excel avec JavaScript dans React.

Mettre en forme le fichier Excel généré

Une feuille de calcul contenant des données brutes fonctionne, mais une feuille de calcul mise en forme communique. Transformons notre rapport de ventes en un document que vous enverriez réellement à une partie prenante :

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

Deux détails méritent d'être connus ici. sheet.Columns.get(i) et sheet.Rows.get(i) sont basés sur 0 et utilisent get, contrairement au get_Item exposé par d'autres collections. Et dans la configuration de navigateur testée, AutoFitColumn nécessite une police qui n'est pas disponible dans le bac à sable WebAssembly, donc définir ColumnWidth explicitement est plus fiable.

Le résultat : un en-tête bleu en gras, des prix au format monétaire, des colonnes correctement dimensionnées et des bordures nettes.

Pour des conseils détaillés sur les dimensions des lignes et des colonnes, consultez Définir la hauteur de ligne et la largeur de colonne dans Excel avec JavaScript dans React.

Créer plusieurs feuilles de calcul dans un classeur Excel

Les vrais rapports tiennent rarement sur une seule feuille. Un rapport de ventes peut comporter un récapitulatif sur le premier onglet, le détail des produits sur le second et des répartitions mensuelles sur le troisième.

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

Chaque Worksheets.Add(name) renvoie la feuille qu'il vient de créer, dans l'ordre des appels, de sorte que l'ordre des onglets correspond à l'ordre du code. Remarquez la formule inter-feuilles : =SUM(Products!D2:D5) dans la feuille Summary fait référence à la colonne Total de la feuille Products. Excel gère cela automatiquement à l'ouverture du fichier — aucun code supplémentaire n'est nécessaire.

Classeur multi-feuilles avec les onglets Summary et Products

Pour en savoir plus sur la gestion des feuilles de calcul — ajout, suppression et réorganisation des feuilles — consultez Ajouter, supprimer et déplacer des feuilles de calcul Excel avec JavaScript dans React.

Enregistrer et télécharger le fichier XLSX dans le navigateur

Une fois votre classeur prêt, Spire.XLS l'enregistre dans un système de fichiers virtuel WebAssembly. Vous lisez ensuite les données du fichier, les convertissez en Blob et déclenchez un téléchargement :

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();

Appelez toujours workbook.Dispose() après le téléchargement pour libérer la mémoire — en particulier dans les applications où les utilisateurs génèrent plusieurs fichiers au cours d'une même session. Le classeur lui-même réside dans le tas WebAssembly jusqu'à ce que vous le fassiez, et ce tas n'est pas récupéré par le ramasse-miettes du navigateur.

Vous cherchez une intégration React ou un export de tableau HTML ? Consultez notre guide pour télécharger et exporter des fichiers Excel en JavaScript et React.

Mise en pratique : un rapport de ventes mis en forme

Les extraits ci-dessus construisent un classeur un aspect à la fois. Les voici réunis dans une seule fonction : une feuille de calcul stylisée avec un fond alterné et des formats monétaires, des colonnes de chiffre d'affaires et de part calculées par formule, un graphique à colonnes et une deuxième feuille de calcul qui consolide les chiffres.

/**
 * 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
}

La mise en page suit les données. Remplacez le tableau products par une réponse de votre propre API et tout le reste — totaux, pourcentages de part, plage du graphique, consolidation du récapitulatif — continue de fonctionner, car tout est exprimé sous forme de formules ou de plages dérivées plutôt que de valeurs codées en dur.

Rapport de ventes complet et mis en forme avec graphique, fond alterné et feuille de calcul de synthèse

Pour plus de types de graphiques et d'options de configuration, consultez Créer des graphiques Excel avec JavaScript dans React.

Créer un fichier Excel à partir de données CSV

Vous pouvez charger des données tabulaires à partir d'un fichier CSV dans une feuille de calcul et enregistrer le résultat au format XLSX. Le classeur obtenu peut ensuite être mis en forme ou enrichi avec des formules et des feuilles de calcul supplémentaires :

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

La feuille importée porte le nom du fichier (data), donc Worksheets.get(0) la récupère.

Le séparateur est un deuxième argument obligatoire. LoadFromFile("data.csv") seul est rejeté avec This is not a structured storage file, car la surcharge à un seul argument attend un format structuré tel que .xlsx ou .xls et ne détecte pas le CSV.

Il y a un second piège : l'importateur CSV écrit chaque champ sous forme de texte. Une colonne de quantités arrive sous la forme "10" plutôt que 10, ce qui signifie qu'elle ne peut pas être additionnée ni triée numériquement — exactement le problème décrit plus haut dans ce tutoriel. Convertissez les colonnes dont vous avez besoin avant d'enregistrer :

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

Pour un guide complet sur la conversion entre les formats CSV et Excel, consultez notre tutoriel de conversion CSV vers Excel.

Créer un fichier XLS au lieu de XLSX

Si votre application doit générer l'ancien format .xls au lieu de .xlsx, modifiez le paramètre de version :

workbook.SaveToFile({
    fileName: "Report.xls",
    version: xls.ExcelVersion.Version97to2003
});

Le membre d'énumération est Version97to2003 — il n'existe pas de Version97. Gardez les graphiques au format XLSX ; l'écrivain XLS testé échoue lorsque les métriques de police des graphiques sont requises.

XLSX (Excel 2007 et versions ultérieures) est le format recommandé pour les nouvelles applications. XLS (Excel 97–2003) n'est nécessaire que lorsqu'une compatibilité ascendante est requise.

Problèmes courants

window.wasmModule est undefined. Les anciens exemples lisaient l'API de feuille de calcul depuis window.wasmModule.spirexls. Les versions actuelles l'installent directement sur window.spirexls et laissent wasmModule undefined, de sorte que le tout premier accès lève une erreur. Vérifiez plutôt window.spirexls.

Module WASM non initialisé. Si window.spirexls est undefined, le runtime n'a pas terminé son chargement. Affichez un indicateur de chargement et attendez la fin de l'initialisation avant de tenter toute opération Excel.

L'ajustement automatique lève une erreur de police. AutoFitColumn et AutoFitRow ont besoin d'une police système pour mesurer le texte, et le bac à sable WebAssembly n'en a aucune. Ils échouent avec Cannot found font(Arial) installed on the system. Calculez ou codez en dur vos largeurs de colonne avec sheet.Columns.get(i).ColumnWidth.

Nombres stockés sous forme de texte. Utiliser cell.Text = "100" au lieu de cell.NumberValue = 100 casse le tri et les calculs. C'est le problème le plus courant rencontré par les développeurs lorsqu'ils écrivent des fichiers Excel en JavaScript, et l'import CSV le déclenche automatiquement — utilisez toujours NumberValue pour les données numériques.

Une feuille « Evaluation Warning » apparaît. Lorsque vous utilisez la version d'évaluation sans licence valide, Spire.XLS ajoute une feuille d'évaluation au classeur enregistré. Cette feuille est recréée à chaque enregistrement, donc la supprimer par programmation n'est pas une solution fiable. Appliquez une clé de licence pour l'éviter.

Fuites de mémoire dans les applications de longue durée. Appelez workbook.Dispose() après chaque cycle de génération. Dans les applications monopage, les classeurs non libérés accumulent de la mémoire et dégradent les performances au fil du temps.

FAQ

JavaScript peut-il créer des fichiers Excel sans Microsoft Excel ?

Oui. Spire.XLS pour JavaScript s'exécute entièrement dans le navigateur via WebAssembly. Aucune installation de Microsoft Excel ou d'Office côté serveur n'est nécessaire pour générer des fichiers XLSX.

JavaScript peut-il créer des fichiers XLSX directement dans le navigateur ?

Oui. Toutes les opérations sur la feuille de calcul se déroulent côté client. Le fichier est enregistré dans un système de fichiers virtuel, puis téléchargé en tant que Blob — aucun serveur backend n'est nécessaire.

Quelle est la différence entre XLS et XLSX ?

XLSX (Excel 2007 et versions ultérieures) est le format moderne basé sur XML, recommandé pour les nouvelles applications. XLS (Excel 97–2003) est l'ancien format binaire, utile pour la compatibilité avec les systèmes plus anciens.

Conclusion

Créer des fichiers Excel en JavaScript ne nécessite ni serveur backend ni Microsoft Excel. Avec Spire.XLS pour JavaScript, vous pouvez construire des classeurs à partir de zéro, écrire des données typées, ajouter des formules, appliquer une mise en forme et organiser les données sur plusieurs feuilles — le tout dans le navigateur.

Commencez par l'exemple de base ci-dessus, puis ajoutez des formules et de la mise en forme selon vos besoins. Pour une intégration spécifique à React et l'export de tableaux HTML, consultez notre tutoriel dédié à l'export.

Voir aussi