AI-generated Word report, Excel dashboard, PowerPoint slides, and PDF summary produced from a single Excel data source

KI-Dokumentengenerierung verwendet natürlichsprachliche Anweisungen, Quelldaten und Vorlagen, um strukturierte Word-, Excel-, PowerPoint- und PDF-Dateien zu erstellen — nicht nur Text, sondern formatierte Dokumente mit Abschnitten, Tabellen, Diagrammen und Styling. Im Gegensatz zur einfachen KI-Textgenerierung erzeugt sie vollständige, sofort einsatzbereite Dateien, die den Office-Formatierungsstandards entsprechen. Dieser Artikel behandelt, was KI-Dokumentengenerierung ist, wie sie funktioniert, Online-Tools, die Sie sofort ausprobieren können, und eine C#-Implementierung mit Spire.Agent.Office.

Schnellnavigation


1. Was ist KI-Dokumentengenerierung?

KI-Dokumentengenerierung ist der Prozess, künstliche Intelligenz zu verwenden, um formatierte Geschäftsdokumente — Word-, Excel-, PowerPoint- und PDF-Dateien — aus Eingaben wie natürlichsprachlichen Beschreibungen, strukturierten Daten, Vorlagen oder vorhandenen Dokumenten zu erstellen. Die KI liest die Eingabe, bestimmt die Dokumentstruktur, füllt Inhalte ein, wendet Formatierung an und erzeugt eine fertige Datei.

Wie sie sich von KI-Textgenerierung unterscheidet

KI-Textgenerierung (ChatGPT, Claude, Gemini) erzeugt Text — Absätze, Antworten, Codeausschnitte. KI-Dokumentengenerierung geht weiter: Sie erzeugt strukturierte, formatierte Dateien mit Überschriften, Tabellen, Diagrammen, Seitenlayouts und Styling, die den Office-Standards entsprechen. Der Unterschied ist wichtig:

Dimension KI-Textgenerierung KI-Dokumentengenerierung
Ausgabe Reiner Text oder Markdown Formatierte .docx-, .xlsx-, .pptx-, .pdf-Dateien
Struktur Linearer Text Abschnitte, Tabellen, Diagramme, Kopfzeilen, Seitenumbrüche
Formatierung Keine Schriftarten, Stile, Ränder, Zellenformate, Folienlayouts
Anwendungsfall Inhalte entwerfen Lieferfähige Geschäftsdokumente erstellen

Vier Eingabemuster

KI-Dokumentengenerierung arbeitet typischerweise mit einem oder mehreren dieser Eingabemuster:

  1. Prompt → Dokument: Beschreiben Sie, was Sie möchten; die KI erstellt das gesamte Dokument von Grund auf.
  2. Daten → Dokument: Stellen Sie eine Tabelle, einen Datenbankexport oder JSON bereit; die KI strukturiert ein Dokument um die Daten herum.
  3. Vorlage + Daten → Dokument: Laden Sie eine Vorlage mit Platzhalterfeldern; die KI füllt sie aus und passt sie mit Daten an.
  4. Vorhandenes Dokument → neu generiertes Dokument: Laden Sie eine vorhandene Datei; die KI schreibt sie um, formatiert sie neu oder konvertiert sie.

Die meisten realen Workflows kombinieren diese — zum Beispiel das Bereitstellen einer Datendatei und einer natürlichsprachlichen Anweisung, die darauf verweist.


2. Was können KI-Dokumentengeneratoren erstellen?

KI-Dokumentengenerierung umfasst häufig Workflows für Word, Excel, PowerPoint und PDF. Die folgende Tabelle ordnet jedes Format den Dokumenttypen zu, die es erzeugt, sowie einer repräsentativen Anweisung.

Format Dokumenttypen Beispielanweisung
Word (.docx) Managementberichte, Geschäftsbriefe, Memos, Verträge, Angebote, Richtlinien "Erstellen Sie einen Quartalsgeschäftsbericht mit Abschnitten zu Umsatzentwicklung, Top-Produkten, regionalem Vergleich und Risikoindikatoren."
Excel (.xlsx) Finanz-Dashboards, Datenzusammenfassungen, Budget-Arbeitsblätter, Analyseberichte "Erstellen Sie ein Vertriebs-Dashboard mit Pivot-Tabellen, die Umsatz nach Region und Produkt anzeigen, Diagrammen zum Vergleich Q3 vs. Q2 und bedingter Formatierung für Ziele."
PowerPoint (.pptx) Vorstandspräsentationen, Pitch-Decks, Schulungsfolien, All-Hands-Decks, Projekt-Updates "Erstellen Sie eine 10-Folien-Präsentation für das All-Hands-Meeting mit Q3-Highlights, Umsatzwachstum, Top-Performern, Herausforderungen und Q4-Prioritäten."
PDF (.pdf) Einseitige Zusammenfassungen, formelle Berichte, ausfüllbare Formulare, Compliance-Dokumente "Generieren Sie eine einseitige PDF-Zusammenfassung der Q3-Ergebnisse für Regionalleiter, einschließlich Gesamtumsatz, Wachstumsprozentsatz, Top-3-Regionen und Aktionspunkte."

Häufige Anwendungsfälle über alle Formate hinweg

Anwendungsfall Typisches Format Wer es braucht
Vierteljährliche Business-Reviews Word + PPT + PDF Führungskräfte, Vorstandsmitglieder
Vertriebsangebote und Kostenvoranschläge Word + PDF Vertriebsteams
Finanzberichte und Dashboards Excel + PDF Finanzteams
Schulungsmaterialien und Onboarding PPT + Word Personalwesen, Schulungsteams
Rechnungs- und Vertragsgenerierung Word + PDF Betrieb, Recht
Projektstatus-Updates PPT + Word Projektmanager
Marketingmaterial PPT + PDF Marketingteams

3. Wie KI-Dokumentengenerierung funktioniert

AI document generation pipeline: prompt and source data flow through an AI agent to produce formatted Word, Excel, PowerPoint, and PDF files

Unabhängig vom jeweiligen Tool oder SDK folgt KI-Dokumentengenerierung einer gemeinsamen Pipeline: Anweisung + Daten/Vorlage → KI-Agent → Dokumentstruktur → Formatierung → Ausgabedatei. Eine Anweisung plus eine Datendatei oder eine Vorlage gehen hinein; der Agent plant die Struktur, generiert Inhalte und wendet Formatierung an; ein formatiertes Dokument kommt heraus.

Der KI-Agent schreibt nicht einfach „Text in eine Datei“. Er führt mehrere Schritte aus:

  1. Die Anweisung verstehen — die natürlichsprachliche Anfrage analysieren, um Dokumenttyp, Zielgruppe und erforderliche Abschnitte zu bestimmen.
  2. Die Quelldaten analysieren — die angehängten Datendatei(en) lesen und relevante Informationen extrahieren.
  3. Die Struktur planen — entscheiden, wie die Inhalte organisiert werden: welche Abschnitte, Tabellen, Diagramme und Seiten das Dokument benötigt.
  4. Inhalte generieren — den Text für jedes strukturelle Element schreiben oder ausfüllen.
  5. Formatierung anwenden — Schriftarten, Stile, Farben, Ränder, Tabellenlayouts und Diagrammkonfigurationen festlegen.
  6. Die Datei erzeugen — das Ergebnis als .docx-, .xlsx-, .pptx- oder .pdf-Datei rendern.

Drei Architekturmuster

Verschiedene Tools implementieren KI-Dokumentengenerierung auf unterschiedliche Weise:

Muster Funktionsweise Am besten für
Vorlage + KI-Ausfüllung Eine feste Vorlage definiert das Layout; die KI füllt Inhaltsfelder aus. Dokumente mit hohem Volumen und konsistenter Struktur (Rechnungen, Verträge)
KI-Inhaltsgenerierung + SDK-Rendering Die KI generiert strukturierte Inhalte (JSON/Markdown); ein Dokument-SDK rendert sie in eine formatierte Datei. Entwickler-Workflows, bei denen Sie sowohl KI als auch Rendering kontrollieren
Vollständig agentisch Ein KI-Agent übernimmt die gesamte Pipeline — Daten lesen, Struktur planen, Inhalte generieren und die Datei erzeugen — in einem Aufruf. Flexible, datengetriebene Dokumente, bei denen die Struktur variiert

Spire.Agent.Office verwendet einen agentischen Dokumentengenerierungs-Workflow, bei dem ein ExecuteInstruction-Aufruf die gesamte Pipeline übernimmt. Online-Tools wie CloudXDocs bieten einen browserbasierten Agenten-Workflow für denselben allgemeinen Anwendungsfall.


4. KI-Dokumentengenerierung online ausprobieren

Nicht jeder, der KI-Dokumentengenerierung benötigt, ist Entwickler. Wenn Sie Dokumente ohne Programmierung generieren möchten, können browserbasierte KI-Dokumentagenten Prompts, Notizen und Quelldateien in formatierte Word-, Excel-, PowerPoint- oder PDF-Dateien umwandeln.

CloudXDocs ist ein Online-KI-Agent, der Dokumentverarbeitung und -generierung über alle vier Office-Formate hinweg übernimmt. Er richtet sich an Geschäftsanwender in Marketing, Vertrieb, Finanzen, Beratung und Betrieb — kein technischer Hintergrund erforderlich.

So funktioniert es

  1. Laden Sie eine Quelldatei hoch — oder starten Sie mit einem Prompt ohne Quelle
  2. Beschreiben Sie das gewünschte Dokument — in natürlicher Sprache
  3. Prüfen und laden Sie das Ergebnis herunter — als .docx, .xlsx, .pptx oder .pdf

Beispiel

Ein Finanzmanager lädt eine monatliche Vertriebstabelle hoch und gibt ein:

"Erstellen Sie einen monatlichen Finanzleistungsbericht. Fügen Sie eine Zusammenfassung für die Geschäftsleitung, eine Tabelle mit finanziellen Highlights mit Monats- und Jahresvergleichen, eine Umsatzaufschlüsselung nach Geschäftssegment und eine Ausgabenanalyse hinzu. Formatieren Sie ihn als professionelles PDF."

Das Ergebnis kann ein mehrseitiges PDF mit formatierten Tabellen, Diagrammen und gestalteten Abschnitten sein. Wie bei jedem KI-generierten Geschäftsdokument sollten Sie die Ausgabe vor der formalen Verteilung prüfen.

Für die Automatisierung auf Anwendungsseite — das programmatische Generieren von Dokumenten in Ihrer eigenen Software — behandelt der nächste Abschnitt den Entwickleransatz mit Spire.Agent.Office.


5. KI-Dokumentengenerierung für Entwickler

Wenn Sie KI-Dokumentengenerierung in eine .NET-Anwendung integrieren müssen, bietet Spire.Agent.Office ein Dokument-KI-SDK, das die vollständige Generierungspipeline im Prozess übernimmt. Fügen Sie es über NuGet hinzu:

dotnet add package Spire.Agent.Office

Das Kernmuster

Jede Dokumentengenerierungsaufgabe folgt demselben dreistufigen Muster:

using Spire.Doc;
using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;

AIOptions options = new AIOptions
{
    SpireToken = "sk-YourSpireToken",
    TimeoutMs = 600000
};

using (Document doc = new Document())
{
    AIResult result = doc.AI(options).ExecuteInstruction(
        doc,
        "Generate an executive summary report from the attached sales data. "
        + "Include sections for revenue, top products, and risk indicators.",
        @"C:\output\q3-report.docx",
        new[] { @"C:\data\q3-sales-data.xlsx" },  // source files via attachmentPaths
        autonomousOutput: true, maxTurns: null);

    Console.WriteLine(result.Success ? "Done" : result.ErrorMessage);
}

Wichtige API-Aufrufe

Schritt Methode Zweck
Konfigurieren new AIOptions { SpireToken, WorkDir, TimeoutMs } API-Schlüssel und Arbeitsverzeichnis festlegen
Anweisen doc.AI(options).ExecuteInstruction(doc, instruction, savePath, attachmentPaths) Anweisung mit Quelldateien senden
Prüfen result.Success / result.ErrorMessage Abschluss überprüfen

Der Parameter attachmentPaths (IEnumerable<string> von Dateipfaden) ist der Weg, über den formatübergreifende Daten einfließen — Sie übergeben eine Excel-Datei, ein PDF oder eine Markdown-Datei als Quelle, und der Agent liest sie automatisch. Das Ausgabeformat wird durch die Erweiterung von savePath bestimmt (.docx, .xlsx, .pptx, .pdf). Ein praktisches Detail: Der Agent schreibt die fertige Datei als output_<fileName> in sein Arbeitsverzeichnis, nicht direkt nach savePath. Kopieren Sie sie daher, sobald der Aufruf zurückkehrt.


6. Aus einer Datenquelle vier Dokumenttypen

One Excel data source generates four AI-produced documents: Word executive report, Excel dashboard, PowerPoint deck, and PDF one-page summary

Ein praktischer Anwendungsfall für KI-Dokumentengenerierung ist Multi-Format-Ausgabe aus einer einzigen Datenquelle. Statt vier separate Codepfade zu schreiben, schreiben Sie vier Anweisungen und lassen den Agenten den Rest erledigen.

Das Szenario

Ein Vertriebsleiter hat Q3-2026-Daten in einer Excel-Arbeitsmappe (q3-sales-data.xlsx) und benötigt vier Ergebnisse für verschiedene Zielgruppen.

Der Code

using Spire.Doc;
using Spire.Xls;
using Spire.Presentation;
using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;

string[] sources = new[] { @"C:\data\q3-sales-data.xlsx" };
AIOptions options = new AIOptions { SpireToken = "sk-YourToken", TimeoutMs = 600000 };

// 1. Word executive report (for the board)
using (Document doc = new Document())
{
    doc.AI(options).ExecuteInstruction(doc,
        "Generate an executive summary report with sections for revenue, top products, "
        + "regional comparison, and risk indicators.",
        @"C:\output\q3-report.docx", sources, autonomousOutput: true, maxTurns: null);
}

// 2. Excel dashboard (for finance)
using (Workbook wb = new Workbook())
{
    wb.AI(options).ExecuteInstruction(wb,
        "Create a sales dashboard with KPI summary, pivot tables, charts comparing "
        + "Q3 vs Q2, and conditional formatting for targets.",
        @"C:\output\q3-dashboard.xlsx", sources, autonomousOutput: true, maxTurns: null);
}

// 3. PowerPoint deck (for all-hands)
using (Presentation ppt = new Presentation())
{
    ppt.AI(options).ExecuteInstruction(ppt,
        "Build a 10-slide all-hands presentation covering Q3 highlights, revenue growth, "
        + "top performers, challenges, and Q4 priorities.",
        @"C:\output\q3-deck.pptx", sources, autonomousOutput: true, maxTurns: null);
}

// 4. PDF one-pager (for regional managers)
using (Document pdfDoc = new Document())
{
    pdfDoc.AI(options).ExecuteInstruction(pdfDoc,
        "Generate a one-page PDF summary with total revenue, growth rate, "
        + "top 3 regions, and Q4 action items.",
        @"C:\output\q3-summary.pdf", sources, autonomousOutput: true, maxTurns: null);
}

Vier Dokumente, vier Formate, vier Zielgruppen — eine Datenquelle. Alle vier Aufrufe folgen demselben Muster: Quelldaten anhängen, die gewünschte Ausgabe in einer Anweisung beschreiben und den Agenten die Datei erstellen lassen; die Erweiterung von savePath bestimmt das Ausgabeformat.

Ein Parameter trägt die Hauptlast: autonomousOutput: true. Lassen Sie ihn weg (Standard ist false), sucht die Engine nach einer output_*-Datei, die der Agent nie geschrieben hat, kehrt ohne gespeicherte Datei zurück und meldet einen Fehler, der mit „The AI did not produce any output file“ beginnt. maxTurns wird hier nur ausgeschrieben, weil dieselbe Aufrufform eine Obergrenze für Durchläufe akzeptiert; null — keine Obergrenze — ist bereits der Standard.

Da jeder Aufruf eine lang laufende Generierung und keine schnelle Transformation ist, benötigt auch TimeoutMs Spielraum: Bei 300 Sekunden wurden sowohl das Deck als auch das PDF mitten im Aufbau abgeschnitten, bevor der Agent mit dem Schreiben fertig war. Das fertige Dokument landet im Arbeitsverzeichnis als output_<fileName> und spiegelt den Namen wider, den Sie in savePath übergeben haben — kopieren Sie es an den Pfad, den Sie behalten möchten. Lesen Sie diesen Namen statt AIResult.OutputFiles: Der Agent konvertiert eine binäre Quelle vor dem Parsen in Markdown und schreibt diese Zwischendatei in dasselbe Verzeichnis, sodass eine Liste von output_*-Dateien sowohl das angeforderte Dokument als auch die Daten, aus denen es erstellt wurde, enthalten kann — und das generierte Dokument kann diesen intermediären .md-Namen als Quelle angeben.

Was jede Anweisung erzeugt

Ausgabe Zielgruppe Wichtige Inhalte
q3-report.docx Vorstand Titelseite, Umsatztabelle, Produktranking, Risikohinweise, Empfehlungen
q3-dashboard.xlsx Finanzen KPI-Übersichtsblatt, Pivot-Tabellen, Q3-vs-Q2-Diagramme, bedingte Formatierung
q3-deck.pptx All-Hands 10 Folien: Highlights, Wachstumsdiagramm, Top-Performer, Herausforderungen, Q4-Prioritäten
q3-summary.pdf Regionalleiter Eine Seite: Umsatzzahl, Wachstums-%, Top-3-Regionen, Aktionspunkte

Drei der vier Ausgaben, genau wie der Agent sie geschrieben hat — das Excel-Dashboard, das Deck und das einseitige PDF:

Excel sales dashboard generated by the AI agent: KPI summary sheet, pivot tables, and Q3-vs-Q2 charts with conditional formatting

The generated 10-slide Q3 all-hands deck, shown in PowerPoint slide sorter view

The generated one-page PDF summary: total revenue, growth rate, top 3 regions, and Q4 action items


7. KI-Generierung vs. traditionelle Dokumentenautomatisierung

Warum KI-Dokumentengenerierung anstelle von Vorlagen, Serienbriefen oder Dokument-SDK-Code verwenden? Betrachten Sie eine Aufgabe: Erstellen Sie einen Word-Bericht aus Excel-Daten mit einer Zusammenfassungstabelle, einem Diagramm und formatierten Überschriften.

Traditioneller Ansatz

Dies mit einem Dokument-SDK zu schreiben erfordert: die Excel-Daten laden, ein Word-Dokument erstellen, einen Titelabsatz mit Schriftart und Ausrichtung hinzufügen, eine Abschnittsüberschrift erstellen, eine Tabelle mit den richtigen Abmessungen aufbauen, durch die Daten schleifen, um Zellen zu füllen, Kopfzeilenstil und abwechselnde Zeilenschattierung anwenden, Spaltenbreiten festlegen, eine Diagrammform hinzufügen und ihre Datenquelle konfigurieren, verbleibende Abschnitte hinzufügen, Seitenränder festlegen und speichern. Die Codemenge wächst mit der Komplexität des Layouts — und dies gilt nur für ein Format.

Ansatz mit KI-Agent

using (Document doc = new Document())
{
    doc.AI(options).ExecuteInstruction(doc,
        "Generate an executive summary report with a revenue summary table, "
        + "a growth chart, and formatted section headings.",
        @"C:\output\report.docx", new[] { @"C:\data\sales.xlsx" },
        autonomousOutput: true, maxTurns: null);
}

Die Anweisung beschreibt die Ausgabe; der Agent übernimmt alle Layoutschritte intern. Die Implementierung bleibt über alle vier Formate hinweg kompakt.

Der Kompromiss

Dimension Traditionelles SDK / Vorlagen KI-Dokumentengenerierung
Codestruktur Formatspezifische API-Aufrufe und Layoutlogik Natürlichsprachliche Anweisung plus Agenten-Orchestrierung
Lernkurve Die API jedes Formats erlernen Ein gemeinsames übergeordnetes Muster über alle Formate hinweg
Kontrolle Feingranular, Element für Element Anweisungsbasiert, durch Spezifität
Vorhersagbarkeit Typischerweise deterministischer und wiederholbarer Hoch, kann aber zwischen Durchläufen variieren
Am besten für Feste Vorlagen, Compliance-Dokumente, exakte Layouts Datengetriebene Berichte, Multi-Format-Ausgabe, Prototyping

8. Wann KI-Dokumentengenerierung verwendet werden sollte

Szenario KI-Generierung Traditionelles SDK
Prototyping eines neuen Dokumenttyps ✅ Durch Anweisungsänderungen iterieren Langsam — jede Layoutänderung bedeutet Codeänderungen
Berichte aus sich entwickelnden Datenschemata ✅ Agent passt Struktur an Daten an Vorlagenbasierte Workflows können Vorlagenänderungen erfordern, wenn sich das Datenschema ändert
Multi-Format-Ausgabe aus einer Quelle ✅ Dasselbe Muster für jedes Format Separater Codepfad pro Format
Einmalige oder Ad-hoc-Dokumente ✅ Beschreiben Sie, was Sie benötigen Overkill, Layoutcode für eine einmalige Verwendung zu schreiben
Nicht technische Benutzer, die Dokumente erstellen ✅ Online-Tools (CloudXDocs) Nicht zutreffend
Pixelgenaues Layout mit exakter Positionierung ✅ Volle Kontrolle über Koordinaten und Größen
Batch mit hohem Volumen und fester Vorlage ✅ Deterministisch, keine KI-Latenz pro Dokument
Compliance-Dokumente mit strenger Formatierung ✅ Typischerweise deterministischer und wiederholbarer

Online-Tool vs. Entwickler-SDK

Wenn Sie... Verwenden Sie
Dokumente ohne Code generieren möchten CloudXDocs — browserbasierter KI-Agent
Die Generierung in eine Anwendung integrieren müssen Spire.Agent.Office — .NET SDK
Beides möchten — Benutzer online generieren lassen und im Code automatisieren Beide lassen sich natürlich kombinieren: CloudXDocs für Ad-hoc, SDK für die Pipeline

9. Häufig gestellte Fragen

Was ist der Unterschied zwischen KI-Dokumentengenerierung und KI-Textgenerierung?

KI-Textgenerierung erzeugt reinen Text oder Markdown — Absätze, Antworten, Codeausschnitte. KI-Dokumentengenerierung erzeugt formatierte Dateien (.docx, .xlsx, .pptx, .pdf) mit Struktur: Abschnitte, Tabellen, Diagramme, Styling und Seitenlayout. Die Ausgabe ist ein lieferfähiges Dokument, nicht nur Text.

Kann ich mehrere Dokumente aus einer einzigen Anweisung generieren?

Nicht mit einem Aufruf: Im SDK erfordert jedes Ausgabeformat seinen eigenen ExecuteInstruction-Aufruf, aber diese Aufrufe können eine Quelldatei gemeinsam nutzen — das ist das Muster in Abschnitt 6. Um stattdessen mehrere Anweisungen auf ein einzelnes Dokument anzuwenden, akzeptiert ExecuteInstructionsAsync ein string[] von Anweisungen und führt sie der Reihe nach aus.

Wie steuere ich bestimmte Formatierungen wie Ränder, Schriftarten oder Tabellenstile?

Geben Sie Formatierungsdetails in der Anweisung an: „Verwenden Sie 1-Zoll-Ränder, 12-pt-Calibri-Fließtext und eine gebänderte Tabelle mit dunkelblauer Kopfzeile.“ Der Agent wendet diese Vorgaben an. Bei Anforderungen, die exakt sein müssen (z. B. ein regulatorischer Rand), generieren Sie zuerst mit KI und passen Sie dann bestimmte Eigenschaften mit SDK-Aufrufen an.

Kann ich meine eigenen Vorlagen als Ausgangspunkt verwenden?

Ja. Laden Sie eine Vorlagendatei mit LoadFromFile und senden Sie dann eine Anweisung wie „Füllen Sie die Platzhalterabschnitte mit Daten aus der angehängten Excel-Datei.“ Der Agent behandelt die geladene Vorlage als Ausgangsdokument und ändert sie. Sie können Vorlagendateien auch als Anhänge zusammen mit Datendateien übergeben.

Welche Dateiformate werden für Eingabe und Ausgabe unterstützt?

Eingabe: .docx, .xlsx, .pptx, .pdf und Markdown (.md) — die zugrunde liegenden Spire-Engines lesen auch die Legacy-Formate .doc, .xls und .ppt. Das Ausgabeformat wird durch die Erweiterung des Speicherpfads bestimmt — ändern Sie .docx in .pdf im Speicherpfad, und dieselbe Anweisung erzeugt stattdessen ein PDF.

Erfordert das Online-Tool ein Abonnement?

CloudXDocs bietet kostenlosen Zugang zum Ausprobieren der Dokumentengenerierung. Für den Produktionseinsatz prüfen Sie deren Preisseite. Das Spire.Agent.Office SDK erfordert einen SpireToken, erhältlich auf der e-iceblue-Website.


Bereit, KI-Dokumentengenerierung auszuprobieren?

  • Ohne Code: Probieren Sie CloudXDocs aus — laden Sie eine Datei hoch, beschreiben Sie, was Sie möchten, laden Sie das Ergebnis herunter.
  • In Ihrer App: Installieren Sie das Spire.Agent.Office NuGet-Paket, konfigurieren Sie Ihren SpireToken und führen Sie die obigen Beispiele aus.

Weiterführende Literatur

AI-generated Word report, Excel dashboard, PowerPoint slides, and PDF summary produced from a single Excel data source

Генерация документов с помощью ИИ использует инструкции на естественном языке, исходные данные и шаблоны для создания структурированных файлов Word, Excel, PowerPoint и PDF — не просто текста, а форматированных документов с разделами, таблицами, диаграммами и стилями. В отличие от простой генерации текста с помощью ИИ, она создаёт полные, готовые к использованию файлы, соответствующие стандартам форматирования Office. В этой статье рассматривается, что такое генерация документов с помощью ИИ, как она работает, онлайн-инструменты, которые можно попробовать прямо сейчас, и реализация на C# с Spire.Agent.Office.

Быстрая навигация


1. Что такое генерация документов с помощью ИИ?

Генерация документов с помощью ИИ — это процесс использования искусственного интеллекта для создания форматированных деловых документов — файлов Word, Excel, PowerPoint и PDF — из таких входных данных, как описания на естественном языке, структурированные данные, шаблоны или существующие документы. ИИ читает входные данные, определяет структуру документа, заполняет содержимое, применяет форматирование и создаёт готовый файл.

Чем это отличается от генерации текста с помощью ИИ

Генерация текста с помощью ИИ (ChatGPT, Claude, Gemini) создаёт текст — абзацы, ответы, фрагменты кода. Генерация документов с помощью ИИ идёт дальше: она создаёт структурированные, форматированные файлы с заголовками, таблицами, диаграммами, макетами страниц и стилями, соответствующими стандартам Office. Это различие важно:

Аспект Генерация текста с помощью ИИ Генерация документов с помощью ИИ
Вывод Обычный текст или Markdown Форматированные файлы .docx, .xlsx, .pptx, .pdf
Структура Линейный текст Разделы, таблицы, диаграммы, колонтитулы, разрывы страниц
Форматирование Отсутствует Шрифты, стили, поля, форматы ячеек, макеты слайдов
Вариант использования Создание черновиков контента Создание готовых деловых документов

Четыре шаблона входных данных

Генерация документов с помощью ИИ обычно работает с одним или несколькими из следующих шаблонов входных данных:

  1. Запрос → документ: Опишите, что вы хотите; ИИ создаёт весь документ с нуля.
  2. Данные → документ: Предоставьте электронную таблицу, экспорт базы данных или JSON; ИИ структурирует документ на основе данных.
  3. Шаблон + данные → документ: Загрузите шаблон с полями-заполнителями; ИИ заполняет и адаптирует его с помощью данных.
  4. Существующий документ → пересозданный документ: Загрузите существующий файл; ИИ переписывает, переформатирует или конвертирует его.

Большинство реальных рабочих процессов комбинируют их — например, предоставление файла данных и инструкции на естественном языке, которая ссылается на него.


2. Что могут создавать генераторы документов с ИИ?

Генерация документов с помощью ИИ обычно включает рабочие процессы Word, Excel, PowerPoint и PDF. В таблице ниже сопоставлен каждый формат с типами создаваемых документов и примером инструкции.

Формат Типы документов Пример инструкции
Word (.docx) Деловые отчёты, деловые письма, служебные записки, контракты, предложения, политики «Создайте отчёт о квартальном бизнес-обзоре с разделами для показателей выручки, основных продуктов, регионального сравнения и индикаторов риска.»
Excel (.xlsx) Финансовые дашборды, сводки данных, бюджеты, аналитические отчёты «Создайте дашборд продаж со сводными таблицами, показывающими выручку по регионам и продуктам, диаграммами, сравнивающими Q3 и Q2, и условным форматированием для целей.»
PowerPoint (.pptx) Презентации для совета директоров, питч-деки, обучающие слайды, презентации для общих собраний, обновления по проектам «Создайте презентацию из 10 слайдов для общего собрания, охватывающую основные моменты Q3, рост выручки, лучших сотрудников, проблемы и приоритеты Q4.»
PDF (.pdf) Одностраничные сводки, официальные отчёты, заполняемые формы, документы о соответствии «Создайте одностраничную PDF-сводку результатов Q3 для региональных менеджеров, включая общую выручку, процент роста, топ-3 региона и задачи к выполнению.»

Типичные варианты использования по форматам

Вариант использования Типичный формат Кому это нужно
Квартальные бизнес-обзоры Word + PPT + PDF Руководители, члены совета директоров
Коммерческие предложения и сметы Word + PDF Отделы продаж
Финансовые отчёты и дашборды Excel + PDF Финансовые отделы
Обучающие материалы и адаптация PPT + Word HR, отделы обучения
Генерация счетов и контрактов Word + PDF Операционные и юридические отделы
Обновления статуса проекта PPT + Word Руководители проектов
Маркетинговые материалы PPT + PDF Маркетинговые отделы

3. Как работает генерация документов с помощью ИИ

AI document generation pipeline: prompt and source data flow through an AI agent to produce formatted Word, Excel, PowerPoint, and PDF files

Независимо от конкретного инструмента или SDK, генерация документов с помощью ИИ следует одному общему конвейеру: Инструкция + Данные/Шаблон → ИИ-агент → Структура документа → Форматирование → Выходной файл. На вход подаётся инструкция плюс файл данных или шаблон; агент планирует структуру, генерирует содержимое и применяет форматирование; на выходе получается форматированный документ.

ИИ-агент не просто «записывает текст в файл». Он выполняет несколько шагов:

  1. Понимает инструкцию — разбирает запрос на естественном языке, чтобы определить тип документа, аудиторию и необходимые разделы.
  2. Анализирует исходные данные — читает прикреплённые файлы данных и извлекает соответствующую информацию.
  3. Планирует структуру — решает, как организовать содержимое: какие разделы, таблицы, диаграммы и страницы нужны документу.
  4. Генерирует содержимое — пишет или заполняет текст для каждого структурного элемента.
  5. Применяет форматирование — задаёт шрифты, стили, цвета, поля, макеты таблиц и конфигурации диаграмм.
  6. Создаёт файл — преобразует результат в файл .docx, .xlsx, .pptx или .pdf.

Три архитектурных шаблона

Разные инструменты реализуют генерацию документов с помощью ИИ по-разному:

Шаблон Как это работает Лучше всего подходит для
Шаблон + заполнение ИИ Фиксированный шаблон определяет макет; ИИ заполняет поля содержимого Документы с большим объёмом и согласованной структурой (счета, контракты)
Генерация содержимого ИИ + рендеринг SDK ИИ генерирует структурированное содержимое (JSON/Markdown); SDK для документов преобразует его в форматированный файл Рабочие процессы разработчиков, где вы контролируете и ИИ, и рендеринг
Полностью агентный ИИ-агент обрабатывает весь конвейер — чтение данных, планирование структуры, генерацию содержимого и создание файла — за один вызов Гибкие, управляемые данными документы, где структура варьируется

Spire.Agent.Office использует агентный рабочий процесс генерации документов, где один вызов ExecuteInstruction обрабатывает весь конвейер. Онлайн-инструменты, такие как CloudXDocs, предоставляют браузерный рабочий процесс агента для того же общего варианта использования.


4. Попробуйте генерацию документов с помощью ИИ онлайн

Не все, кому нужна генерация документов с помощью ИИ, являются разработчиками. Если вы хотите создавать документы без написания кода, браузерные ИИ-агенты для документов могут превратить запросы, заметки и исходные файлы в форматированные файлы Word, Excel, PowerPoint или PDF.

CloudXDocs — это онлайн-ИИ-агент, который обрабатывает и создаёт документы во всех четырёх форматах Office. Он ориентирован на бизнес-пользователей в маркетинге, продажах, финансах, консалтинге и операционной деятельности — техническая подготовка не требуется.

Как это работает

  1. Загрузите исходный файл — или начните с запроса без источника
  2. Опишите нужный документ — на естественном языке
  3. Просмотрите и скачайте результат — в формате .docx, .xlsx, .pptx или .pdf

Пример

Финансовый менеджер загружает ежемесячную таблицу продаж и вводит:

«Создайте ежемесячный отчёт о финансовых результатах. Включите краткое резюме для руководства, таблицу ключевых финансовых показателей с изменениями месяц к месяцу и год к году, разбивку выручки по бизнес-сегментам и анализ расходов. Оформите в виде профессионального PDF.»

Результатом может быть многостраничный PDF с форматированными таблицами, диаграммами и стилизованными разделами. Как и с любым деловым документом, созданным ИИ, проверьте результат перед официальной рассылкой.

Для автоматизации на стороне приложения — программной генерации документов в вашем собственном программном обеспечении — следующий раздел описывает подход для разработчиков с Spire.Agent.Office.


5. Генерация документов с помощью ИИ для разработчиков

Если вам нужно интегрировать генерацию документов с помощью ИИ в приложение .NET, Spire.Agent.Office предоставляет SDK для работы с документами с ИИ, который обрабатывает весь конвейер генерации в процессе. Добавьте его через NuGet:

dotnet add package Spire.Agent.Office

Основной шаблон

Каждая задача генерации документа следует одному и тому же трёхшаговому шаблону:

using Spire.Doc;
using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;

AIOptions options = new AIOptions
{
    SpireToken = "sk-YourSpireToken",
    TimeoutMs = 600000
};

using (Document doc = new Document())
{
    AIResult result = doc.AI(options).ExecuteInstruction(
        doc,
        "Generate an executive summary report from the attached sales data. "
        + "Include sections for revenue, top products, and risk indicators.",
        @"C:\output\q3-report.docx",
        new[] { @"C:\data\q3-sales-data.xlsx" },  // source files via attachmentPaths
        autonomousOutput: true, maxTurns: null);

    Console.WriteLine(result.Success ? "Done" : result.ErrorMessage);
}

Ключевые вызовы API

Шаг Метод Назначение
Настройка new AIOptions { SpireToken, WorkDir, TimeoutMs } Задать ключ API и рабочий каталог
Инструкция doc.AI(options).ExecuteInstruction(doc, instruction, savePath, attachmentPaths) Отправить инструкцию с исходными файлами
Проверка result.Success / result.ErrorMessage Проверить завершение

Параметр attachmentPaths (IEnumerable<string> путей к файлам) — это способ передачи данных между форматами: вы передаёте файл Excel, PDF или Markdown в качестве источника, и агент автоматически его читает. Формат вывода определяется расширением savePath (.docx, .xlsx, .pptx, .pdf). Одна практическая деталь: агент записывает готовый файл в свой рабочий каталог как output_<fileName>, а не напрямую в savePath, поэтому скопируйте его после возврата вызова.


6. Из одного источника данных — четыре типа документов

One Excel data source generates four AI-produced documents: Word executive report, Excel dashboard, PowerPoint deck, and PDF one-page summary

Один практический вариант использования генерации документов с помощью ИИ — вывод в нескольких форматах из одного источника данных. Вместо написания четырёх отдельных путей кода вы пишете четыре инструкции и позволяете агенту сделать всё остальное.

Сценарий

У вице-президента по продажам есть данные за Q3 2026 в книге Excel (q3-sales-data.xlsx), и ему нужны четыре результата для разных аудиторий.

Код

using Spire.Doc;
using Spire.Xls;
using Spire.Presentation;
using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;

string[] sources = new[] { @"C:\data\q3-sales-data.xlsx" };
AIOptions options = new AIOptions { SpireToken = "sk-YourToken", TimeoutMs = 600000 };

// 1. Word executive report (for the board)
using (Document doc = new Document())
{
    doc.AI(options).ExecuteInstruction(doc,
        "Generate an executive summary report with sections for revenue, top products, "
        + "regional comparison, and risk indicators.",
        @"C:\output\q3-report.docx", sources, autonomousOutput: true, maxTurns: null);
}

// 2. Excel dashboard (for finance)
using (Workbook wb = new Workbook())
{
    wb.AI(options).ExecuteInstruction(wb,
        "Create a sales dashboard with KPI summary, pivot tables, charts comparing "
        + "Q3 vs Q2, and conditional formatting for targets.",
        @"C:\output\q3-dashboard.xlsx", sources, autonomousOutput: true, maxTurns: null);
}

// 3. PowerPoint deck (for all-hands)
using (Presentation ppt = new Presentation())
{
    ppt.AI(options).ExecuteInstruction(ppt,
        "Build a 10-slide all-hands presentation covering Q3 highlights, revenue growth, "
        + "top performers, challenges, and Q4 priorities.",
        @"C:\output\q3-deck.pptx", sources, autonomousOutput: true, maxTurns: null);
}

// 4. PDF one-pager (for regional managers)
using (Document pdfDoc = new Document())
{
    pdfDoc.AI(options).ExecuteInstruction(pdfDoc,
        "Generate a one-page PDF summary with total revenue, growth rate, "
        + "top 3 regions, and Q4 action items.",
        @"C:\output\q3-summary.pdf", sources, autonomousOutput: true, maxTurns: null);
}

Четыре документа, четыре формата, четыре аудитории — один источник данных. Все четыре вызова следуют одному шаблону: прикрепите исходные данные, опишите желаемый вывод в инструкции и позвольте агенту создать файл; расширение savePath определяет формат вывода.

Один параметр несёт нагрузку: autonomousOutput: true. Не указывайте его (по умолчанию false), и движок будет искать файл output_*, который агент никогда не записывал, вернётся без сохранения и сообщит об ошибке, начинающейся с «The AI did not produce any output file». maxTurns указан здесь только потому, что та же форма вызова принимает ограничение на количество ходов; null — без ограничения — уже является значением по умолчанию.

Поскольку каждый вызов — это длительная генерация, а не быстрое преобразование, TimeoutMs тоже требует запаса: при 300 секундах и презентация, и PDF были прерваны в середине сборки, прежде чем агент закончил их запись. Готовый документ попадает в рабочий каталог как output_<fileName>, повторяя имя, переданное в savePath — скопируйте его в путь, который хотите сохранить. Читайте это имя, а не AIResult.OutputFiles: агент преобразует бинарный источник в Markdown перед его разбором и записывает этот промежуточный файл в тот же каталог, поэтому список файлов output_* может содержать как запрошенный вами документ, так и данные, на основе которых он был создан — и сгенерированный документ может ссылаться на это промежуточное имя .md как на свой источник.

Что создаёт каждая инструкция

Вывод Аудитория Ключевое содержимое
q3-report.docx Совет директоров Титульная страница, таблица выручки, рейтинг продуктов, флаги рисков, рекомендации
q3-dashboard.xlsx Финансы Лист сводки KPI, сводные таблицы, диаграммы Q3 против Q2, условное форматирование
q3-deck.pptx Общее собрание 10 слайдов: основные моменты, график роста, лучшие сотрудники, проблемы, приоритеты Q4
q3-summary.pdf Региональные менеджеры Одна страница: показатель выручки, % роста, топ-3 региона, задачи к выполнению

Три из четырёх выходных файлов, именно так, как их записал агент — дашборд Excel, презентация и одностраничный PDF:

Excel sales dashboard generated by the AI agent: KPI summary sheet, pivot tables, and Q3-vs-Q2 charts with conditional formatting

The generated 10-slide Q3 all-hands deck, shown in PowerPoint slide sorter view

The generated one-page PDF summary: total revenue, growth rate, top 3 regions, and Q4 action items


7. Генерация с помощью ИИ против традиционной автоматизации документов

Почему стоит использовать генерацию документов с помощью ИИ вместо шаблонов, слияния почты или кода SDK для документов? Рассмотрим одну задачу: создать отчёт Word из данных Excel со сводной таблицей, диаграммой и форматированными заголовками.

Традиционный подход

Написание этого с помощью SDK для документов требует: загрузки данных Excel, создания документа Word, добавления абзаца заголовка со шрифтом и выравниванием, создания заголовка раздела, построения таблицы с нужными размерами, перебора данных для заполнения ячеек, применения стиля заголовка и чередующейся заливки строк, установки ширины столбцов, добавления фигуры диаграммы и настройки её источника данных, добавления оставшихся разделов, установки полей страницы и сохранения. Объём кода растёт со сложностью макета — и это только для одного формата.

Подход с ИИ-агентом

using (Document doc = new Document())
{
    doc.AI(options).ExecuteInstruction(doc,
        "Generate an executive summary report with a revenue summary table, "
        + "a growth chart, and formatted section headings.",
        @"C:\output\report.docx", new[] { @"C:\data\sales.xlsx" },
        autonomousOutput: true, maxTurns: null);
}

Инструкция описывает вывод; агент внутренне выполняет все шаги макета. Реализация остаётся компактной для всех четырёх форматов.

Компромисс

Аспект Традиционный SDK / Шаблоны Генерация документов с помощью ИИ
Структура кода Вызовы API для конкретного формата и логика макета Инструкция на естественном языке плюс оркестрация агента
Кривая обучения Нужно изучить API каждого формата Один общий высокоуровневый шаблон для всех форматов
Контроль Детальный, поэлементный На основе инструкций, через конкретику
Предсказуемость Обычно более детерминированная и воспроизводимая Высокая, но может варьироваться между запусками
Лучше всего подходит для Фиксированные шаблоны, документы о соответствии, точные макеты Отчёты на основе данных, вывод в нескольких форматах, прототипирование

8. Когда использовать генерацию документов с помощью ИИ

Сценарий Генерация с помощью ИИ Традиционный SDK
Прототипирование нового типа документа ✅ Итерации через изменения инструкций Медленно — каждое изменение макета означает изменение кода
Отчёты на основе развивающихся схем данных ✅ Агент адаптирует структуру к данным Рабочие процессы на основе шаблонов могут потребовать изменения шаблона при изменении схемы данных
Вывод в нескольких форматах из одного источника ✅ Один и тот же шаблон для каждого формата Отдельный путь кода для каждого формата
Разовые или специальные документы ✅ Опишите, что вам нужно Излишне писать код макета для одного использования
Нетехнические пользователи, создающие документы ✅ Онлайн-инструменты (CloudXDocs) Не применимо
Пиксельно точный макет с точным позиционированием ✅ Полный контроль над координатами и размерами
Массовый пакет с фиксированным шаблоном ✅ Детерминированный, без задержки ИИ на документ
Документы о соответствии со строгим форматированием ✅ Обычно более детерминированный и воспроизводимый

Онлайн-инструмент против SDK для разработчиков

Если вы... Используйте
Хотите создавать документы без кода CloudXDocs — браузерный ИИ-агент
Нужно интегрировать генерацию в приложение Spire.Agent.Office — .NET SDK
Хотите и то, и другое — позволить пользователям генерировать онлайн и автоматизировать в коде Оба естественно сочетаются: CloudXDocs для специальных задач, SDK для конвейера

9. Часто задаваемые вопросы

В чём разница между генерацией документов с помощью ИИ и генерацией текста с помощью ИИ?

Генерация текста с помощью ИИ создаёт обычный текст или Markdown — абзацы, ответы, фрагменты кода. Генерация документов с помощью ИИ создаёт форматированные файлы (.docx, .xlsx, .pptx, .pdf) со структурой: разделами, таблицами, диаграммами, стилями и макетом страницы. Результат — готовый документ, а не просто текст.

Могу ли я создать несколько документов из одной инструкции?

Не одним вызовом: в SDK каждый формат вывода требует своего вызова ExecuteInstruction, но эти вызовы могут использовать один исходный файл — это шаблон из раздела 6. Чтобы вместо этого применить несколько инструкций к одному документу, ExecuteInstructionsAsync принимает string[] инструкций и выполняет их по порядку.

Как управлять конкретным форматированием, например полями, шрифтами или стилями таблиц?

Включите детали форматирования в инструкцию: «используйте поля 1 дюйм, основной текст Calibri 12 пт и таблицу с чередующимися строками и тёмно-синей строкой заголовка». Агент применяет эти спецификации. Для требований, которые должны быть точными (например, нормативное поле), сначала сгенерируйте с помощью ИИ, затем скорректируйте конкретные свойства вызовами SDK.

Могу ли я использовать свои собственные шаблоны в качестве отправной точки?

Да. Загрузите файл шаблона с помощью LoadFromFile, затем отправьте инструкцию вроде «заполните разделы-заполнители данными из прикреплённого файла Excel». Агент рассматривает загруженный шаблон как исходный документ и изменяет его. Вы также можете передавать файлы шаблонов как вложения вместе с файлами данных.

Какие форматы файлов поддерживаются для ввода и вывода?

Ввод: .docx, .xlsx, .pptx, .pdf и Markdown (.md) — базовые движки Spire также читают устаревшие .doc, .xls и .ppt. Формат вывода определяется расширением пути сохранения — измените .docx на .pdf в пути сохранения, и та же инструкция создаст PDF.

Требует ли онлайн-инструмент подписки?

CloudXDocs предлагает бесплатный доступ для пробной генерации документов. Для производственного использования ознакомьтесь с их страницей цен. SDK Spire.Agent.Office требует SpireToken, доступный на веб-сайте e-iceblue.


Готовы попробовать генерацию документов с помощью ИИ?

  • Без кода: Попробуйте CloudXDocs — загрузите файл, опишите, что хотите, скачайте результат.
  • В вашем приложении: Установите пакет NuGet Spire.Agent.Office, настройте ваш SpireToken и запустите примеры выше.

Дополнительное чтение

Lendo todas as fórmulas de uma planilha do Excel no navegador com Spire.XLS for JavaScript

Alguém construiu esta pasta de trabalho anos atrás. Ela recalcula quando os dados mudam, os totais se movem de maneiras que ninguém mais prevê, e não há documentação — porque as fórmulas são a documentação. Ler os números não lhe dirá como eles foram produzidos. Ler as regras, sim.

Spire.XLS for JavaScript compila um mecanismo de planilha para WebAssembly, de modo que um aplicativo React pode abrir um .xlsx existente no navegador, percorrer suas células e extrair a regra por trás de cada uma. A pasta de trabalho trafega por um sistema de arquivos virtual (VFS), então nada é enviado e nenhum backend está envolvido.

Duas perguntas são feitas para cada célula: ela contém uma fórmula e, em caso afirmativo, o que essa fórmula diz? A primeira é uma verificação de propriedade. A segunda é uma leitura. Quase tudo neste artigo decorre de manter essas duas coisas separadas.

Para a configuração do projeto, consulte Integrando o Spire.XLS for JavaScript em um Projeto React. Os exemplos abaixo pressupõem que o pacote esteja instalado e que o módulo WebAssembly tenha sido inicializado.


Quando você precisa das fórmulas, não dos números

A razão para ler regras em vez de valores é quase sempre uma destas:

  • Assumir um modelo que ninguém documentou. As regras são a única descrição sobrevivente do que a pasta de trabalho faz.
  • Mover cálculos para fora da planilha. Reimplementar um cálculo no código do aplicativo exige conhecer a expressão exata, não apenas seu último resultado.
  • Verificar consistência. Uma linha que silenciosamente usa uma regra diferente das linhas ao redor é invisível nos valores e óbvia nas fórmulas.
  • Produzir uma solicitação de mudança. Uma lista de células e as regras que elas contêm é algo que um usuário de negócios pode revisar e corrigir.
  • Verificar uma pasta de trabalho gerada pelo seu próprio código. Confirmar que o que foi escrito é o que foi armazenado — consulte Como Inserir Fórmulas e Funções do Excel em JavaScript (React) para o lado da escrita desse par.

Pré-requisitos

Você precisa de um projeto React com o Spire.XLS for JavaScript instalado e o módulo WebAssembly inicializado, acessível em window.wasmModule.spirexls. A pasta de trabalho que você deseja inspecionar já deve estar no VFS — carregada da pasta pública do seu aplicativo com FetchFileToVFS, ou gravada ali como bytes, caso tenha vindo de outro lugar.

Se o resultado for formatado — larguras de coluna e afins —, carregue também uma fonte no VFS, como o exemplo faz.


As duas perguntas a fazer para cada célula

Comece pedindo à planilha a região que ela realmente usa:

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange é a metade desse trecho que protege você. Percorrer A1:Z1000 em uma planilha com doze linhas usadas gasta a maior parte do tempo em células vazias e deixa você filtrando-as depois. Pedir à planilha sua região alocada mantém o loop proporcional ao conteúdo, o que importa assim que a pasta de trabalho é real.

Então HasFormula decide o que vale a pena ler. É um booleano simples e responde exatamente a uma pergunta — se a célula contém uma fórmula —, que acaba sendo uma pergunta mais restrita do que parece.


Um exemplo completo

O componente abaixo carrega uma pasta de trabalho existente, percorre seu intervalo usado e escreve cada fórmula encontrada em uma nova planilha como uma linha legível — o endereço da célula e a regra nela armazenada:

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Leia fórmulas e resultados de funções de planilhas do Excel

Ler Fórmulas e Funções de uma Planilha do Excel

Observe o que o código faz com a pasta de trabalho de origem: ele a lê e nada mais. Uma segunda Workbook é criada para a saída, de modo que o arquivo inspecionado nunca é modificado. Isso importa quando você está examinando o documento de outra pessoa — a inspeção deve ser não destrutiva por construção, e não por lembrar de não salvar.


Fórmula ou valor

É aqui que a leitura restrita de HasFormula compensa, porque as propriedades que você pode ler de uma célula não retornam todas a mesma coisa:

Propriedade O que você obtém Recorra a ela quando
HasFormula Se a célula contém uma fórmula Triar um intervalo antes de ler qualquer coisa
Formula A string da fórmula conforme armazenada — =SUM(B1:F1) Você precisa da regra
FormulaNumberValue O resultado numérico da avaliação dessa fórmula Você precisa do número que a regra produziu
NumberValue O número contido em uma célula de dados A célula é um dado, e não uma regra
Text O texto conforme escrito na célula Você quer a string de exibição

O par que causa mais confusão é Formula versus FormulaNumberValue: a mesma célula, duas respostas completamente diferentes. Uma é a regra; a outra é o que a regra produziu. Peça a errada e você obterá um valor tecnicamente válido que não é aquilo que você procurava — uma auditoria de fórmulas que retorna números ou uma extração de valores que retorna fórmulas.


Montando um inventário de fórmulas

O exemplo grava cada ocorrência em uma segunda pasta de trabalho e a baixa. Essa é a forma correta quando o inventário é ele próprio um documento — algo para entregar a um revisor ou anexar a um ticket.

Quando o inventário é para a tela, em vez disso, colete os mesmos dados primeiro e decida como apresentá-los depois:

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

RangeAddressLocal é o que torna o resultado utilizável. Ele retorna o endereço na notação da própria planilha — o nome que uma pessoa usaria ao discutir a célula — em vez de um par linha-e-coluna, que é tecnicamente equivalente e praticamente ilegível. Uma entrada que diz B7 pode ser usada; uma entrada que diz linha 7, coluna 2 precisa ser traduzida primeiro.


Mais de uma planilha

O loop acima cobre uma planilha. Um inventário no nível da pasta de trabalho significa repeti-lo para cada planilha, por vez, obtendo cada uma da mesma forma que a primeira, com Workbook.Worksheets.get(i) recebendo o índice.

Dois detalhes valem a pena acertar antes de ampliar a escala. Registre de qual planilha veio cada entrada, porque B7 em duas planilhas são duas células diferentes e uma lista que não as distingue é ambígua exatamente no momento em que isso importa. E mantenha a coluna de saída larga o suficiente — os endereços e as strings de regras são longos, e um inventário truncado é pior que um estreito.


Por que uma célula de fórmula pode passar despercebida

Uma célula que exibe =SUM(B1:F1) não contém necessariamente uma fórmula. Se ela foi escrita por meio de Text ou Value em vez de Formula, ou digitada em uma célula que já estava formatada como texto, então os caracteres são armazenados como uma string. A planilha mostra uma fórmula; a célula contém um rótulo.

HasFormula relata isso corretamente como false, e uma varredura que espera encontrar essa célula fica vazia. Esta é a armadilha neste fluxo de trabalho porque não parece uma falha: a pasta de trabalho contém visivelmente fórmulas, o código roda sem erro e o inventário fica faltando exatamente a quantidade de células que foram digitadas como texto.

Quando uma fórmula parece estar faltando em um inventário, verifique como ela foi escrita antes de verificar o código de leitura. Se a pasta de trabalho é gerada pelo seu próprio aplicativo, essa é a mesma distinção de propriedade que inserir fórmulas aborda do lado da escrita.


Problemas comuns

A varredura não encontra nada, mas a planilha está cheia de fórmulas. Elas estão armazenadas como texto. Consulte a seção acima — HasFormula relata apenas fórmulas reais.

O resultado é um número quando eu queria a fórmula, ou o contrário. Você leu a propriedade errada. Formula fornece a regra, FormulaNumberValue fornece o número calculado.

O loop é lento ou produz centenas de entradas vazias. Ele está percorrendo um intervalo retangular fixo em vez da região alocada da planilha. Use AllocatedRange como fonte da iteração.

Faltam células de uma segunda planilha. O loop é executado em uma única planilha. Repita-o para cada planilha e mantenha a planilha junto de cada entrada.

A pasta de trabalho de origem mudou após a execução. Não deveria ter mudado — o exemplo lê uma pasta de trabalho e grava em outra. Verifique se a saída está sendo salva em um objeto Workbook diferente, como no código acima.


Perguntas frequentes

Preciso ter o Excel instalado para ler fórmulas de uma pasta de trabalho?

Não. O mecanismo vem incluído no pacote e é executado como WebAssembly dentro do navegador. O aplicativo de planilha original não está envolvido em momento algum.

Posso ler o valor calculado em vez da fórmula?

Sim. Leia FormulaNumberValue em vez de Formula da mesma célula. Use HasFormula primeiro para só fazer essa pergunta a células onde ela faz sentido.

Ler uma pasta de trabalho a modifica?

A leitura não modifica. O exemplo abre a entrada, cria uma pasta de trabalho de saída separada para os resultados e salva apenas essa — de modo que o arquivo inspecionado é deixado como estava.

Quais formatos do Excel posso ler?

Tanto o formato legado .xls quanto os arquivos modernos .xlsx são suportados pela mesma API, então uma pasta de trabalho não precisa ser convertida antes de poder ser inspecionada.

Isso funciona para pastas de trabalho armazenadas em um servidor?

Sim, se você conseguir levar os bytes para o navegador. Grave-os no VFS e carregue a partir de lá — a leitura em si é totalmente do lado do cliente, e a pasta de trabalho só é enviada se o seu próprio aplicativo optar por enviá-la.


Veja também

Spire.XLS for JavaScript를 사용해 브라우저에서 Excel 워크시트의 모든 수식 읽기

누군가 이 통합 문서를 몇 년 전에 만들었습니다. 데이터가 바뀌면 다시 계산되고, 합계는 이제 아무도 예측하지 못하는 방식으로 움직이며, 문서는 없습니다. 수식이 곧 문서이기 때문입니다. 숫자를 읽는 것만으로는 그 숫자가 어떻게 만들어졌는지 알 수 없습니다. 규칙을 읽어야 알 수 있습니다.

Spire.XLS for JavaScript는 스프레드시트 엔진을 WebAssembly로 컴파일하므로, React 앱에서 브라우저에서 기존 .xlsx 파일을 열고 셀을 순회하며 각 셀에 담긴 규칙을 추출할 수 있습니다. 통합 문서는 가상 파일 시스템(VFS)을 통해 이동하므로 아무것도 업로드되지 않고 백엔드도 관여하지 않습니다.

모든 셀에 두 가지 질문을 던집니다. 수식을 포함하고 있는가, 그리고 그렇다면 그 수식은 무엇을 말하는가? 첫 번째는 속성 확인이고, 두 번째는 읽기입니다. 이 글의 거의 모든 내용은 이 둘을 구분하는 데서 나옵니다.

프로젝트 설정은 React 프로젝트에서 Spire.XLS for JavaScript 통합하기를 참고하세요. 아래 예제는 패키지가 설치되어 있고 WebAssembly 모듈이 초기화되었다고 가정합니다.


숫자가 아니라 수식이 필요할 때

값이 아니라 규칙을 읽어야 하는 이유는 거의 항상 다음 중 하나입니다.

  • 아무도 문서화하지 않은 모델을 인수할 때. 규칙은 그 통합 문서가 하는 일에 대해 유일하게 남은 설명입니다.
  • 스프레드시트 밖으로 계산을 옮길 때. 애플리케이션 코드에서 계산을 다시 구현하려면 마지막 결과가 아니라 정확한 식을 알아야 합니다.
  • 일관성을 확인할 때. 주변 행과 다른 규칙을 조용히 사용하는 한 행은 값에서는 보이지 않지만 수식에서는 분명히 드러납니다.
  • 변경 요청을 작성할 때. 셀 목록과 그 안에 담긴 규칙은 비즈니스 사용자가 검토하고 수정할 수 있는 자료입니다.
  • 직접 작성한 코드가 생성한 통합 문서를 검증할 때. 기록한 내용이 실제로 저장되었는지 확인하는 작업입니다. 이 짝의 쓰기 쪽은 JavaScript(React)에서 Excel 수식과 함수를 삽입하는 방법을 참고하세요.

사전 요구 사항

Spire.XLS for JavaScript가 설치되어 있고 WebAssembly 모듈이 초기화된 React 프로젝트가 필요하며, 모듈은 window.wasmModule.spirexls에서 접근할 수 있어야 합니다. 검사하려는 통합 문서는 이미 VFS에 있어야 합니다. 애플리케이션의 public 폴더에서 FetchFileToVFS로 로드하거나, 다른 곳에서 전달된 경우 바이트로 기록해 두면 됩니다.

결과에 서식(열 너비 등)을 적용할 예정이라면, 예제에서처럼 폰트도 VFS에 로드하세요.


모든 셀에 던져야 할 두 가지 질문

먼저 워크시트에 실제로 사용하는 영역을 물어보는 것부터 시작합니다.

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange는 이 코드 조각에서 여러분을 보호해 주는 부분입니다. 사용 중인 행이 열두 개뿐인 시트에서 A1:Z1000을 순회하면 대부분의 시간을 빈 셀에 낭비하고, 나중에 그것들을 걸러내야 합니다. 시트에 할당된 영역을 물어보면 반복 횟수가 내용에 비례하게 유지되며, 이는 통합 문서가 실제로 쓰이는 순간부터 중요해집니다.

그다음 HasFormula가 무엇을 읽을 가치가 있는지 결정합니다. 이는 단순한 불리언 값으로, 셀이 수식을 포함하는지라는 단 하나의 질문에만 답합니다. 이 질문은 들리는 것보다 훨씬 좁은 범위입니다.


완전한 예제

아래 컴포넌트는 기존 통합 문서를 로드하고 사용 영역을 순회하며, 찾은 모든 수식을 새 시트에 읽기 쉬운 한 줄로 기록합니다. 즉 셀 주소와 그 안에 저장된 규칙입니다.

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Excel 워크시트에서 수식과 함수 결과 읽기

Excel 워크시트에서 수식과 함수 읽기

코드가 원본 통합 문서에 대해 하는 일에 주목하세요. 읽기만 하고 그 외에는 아무것도 하지 않습니다. 출력을 위해 두 번째 Workbook이 생성되므로 검사 대상 파일은 절대 수정되지 않습니다. 이는 다른 사람의 문서를 검사할 때 중요한데, 검사는 저장하지 않기로 기억하는 것이 아니라 구조적으로 비파괴적이어야 합니다.


수식 또는 값

여기서 HasFormula를 좁게 해석하는 것이 이득을 봅니다. 셀에서 읽을 수 있는 속성들이 모두 같은 것을 반환하지는 않기 때문입니다.

속성 반환되는 값 사용 시기
HasFormula 셀이 수식을 포함하는지 여부 아무것도 읽기 전에 범위를 선별할 때
Formula 저장된 그대로의 수식 문자열 — =SUM(B1:F1) 규칙이 필요할 때
FormulaNumberValue 해당 수식을 평가한 숫자 결과 규칙이 만들어낸 숫자가 필요할 때
NumberValue 데이터 셀에 담긴 숫자 셀이 규칙이 아니라 데이터일 때
Text 셀에 입력된 그대로의 텍스트 표시 문자열이 필요할 때

가장 많은 혼란을 일으키는 짝은 Formula와 FormulaNumberValue입니다. 같은 셀이지만 완전히 다른 두 가지 답입니다. 하나는 규칙이고, 다른 하나는 그 규칙이 만들어낸 결과입니다. 잘못된 것을 요청하면 기술적으로는 유효하지만 찾고 있던 것이 아닌 값을 얻게 됩니다. 숫자를 반환하는 수식 감사, 또는 수식을 반환하는 값 추출처럼요.


수식 목록 구성하기

예제는 찾은 항목을 각각 두 번째 통합 문서에 기록한 뒤 다운로드합니다. 목록 자체가 문서일 때 — 검토자에게 건네주거나 티켓에 첨부할 때 — 알맞은 형태입니다.

목록을 화면에 표시하려는 경우에는 같은 데이터를 먼저 수집한 뒤 표시 방법을 나중에 결정하세요.

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

RangeAddressLocal이 결과를 쓸모 있게 만듭니다. 행과 열의 쌍(기술적으로는 동일하지만 실제로는 읽기 어려운) 대신 시트 자체 표기법으로 주소를 반환합니다. 즉 사람이 그 셀을 이야기할 때 쓰는 이름입니다. B7이라고 적힌 항목은 바로 활용할 수 있지만, 7행 2열이라고 적힌 항목은 먼저 변환해야 합니다.


워크시트가 둘 이상일 때

위의 반복문은 시트 하나만 다룹니다. 통합 문서 전체 목록을 만들려면 각 워크시트에 대해 차례대로 반복해야 하며, 첫 번째 시트를 가져온 것과 같은 방식으로 각 시트를 가져오고 Workbook.Worksheets.get(i)에 인덱스를 전달합니다.

규모를 키우기 전에 제대로 해 두어야 할 두 가지 세부 사항이 있습니다. 각 항목이 어느 워크시트에서 왔는지 기록하세요. 두 시트의 B7은 서로 다른 셀이며, 이를 구분하지 않는 목록은 정확히 중요한 순간에 모호해집니다. 또한 출력 열 너비를 충분히 넓게 유지하세요. 주소와 규칙 문자열은 길고, 잘린 목록은 좁은 목록보다 더 나쁩니다.


수식 셀이 감지되지 않을 수 있는 이유

=SUM(B1:F1)을 표시하는 셀이 반드시 수식을 담고 있는 것은 아닙니다. Formula 대신 Text나 Value를 통해 기록되었거나, 이미 텍스트로 서식이 지정된 셀에 입력되었다면 그 문자들은 문자열로 저장됩니다. 시트에는 수식이 표시되지만 셀에는 레이블이 들어 있는 것입니다.

HasFormula는 이를 false로 정확히 보고하므로, 해당 셀을 찾으리라 기대한 스캔 결과는 비어 있게 됩니다. 이것이 이 워크플로의 함정인데, 실패처럼 보이지 않기 때문입니다. 통합 문서에는 분명히 수식이 보이고, 코드는 오류 없이 실행되며, 목록은 텍스트로 입력된 셀 수만큼 부족할 뿐입니다.

목록에서 수식이 빠진 것처럼 보이면, 읽기 코드를 확인하기 전에 그 수식이 어떻게 기록되었는지 확인하세요. 통합 문서가 여러분의 애플리케이션에서 생성된 것이라면, 이는 수식 삽입에서 쓰기 관점으로 다루는 것과 동일한 속성 구분입니다.


일반적인 문제

스캔 결과가 아무것도 없는데 시트는 수식으로 가득 차 있습니다. 수식이 텍스트로 저장되어 있습니다. 위 섹션을 참고하세요. HasFormula는 실제 수식만 보고합니다.

수식을 원했는데 숫자가 나오거나 그 반대입니다. 잘못된 속성을 읽었습니다. Formula는 규칙을, FormulaNumberValue는 계산된 숫자를 반환합니다.

반복문이 느리거나 빈 항목이 수백 개 생깁니다. 시트의 할당된 영역 대신 고정된 사각형 범위를 순회하고 있습니다. 반복 대상으로 AllocatedRange를 사용하세요.

두 번째 시트의 셀이 누락되었습니다. 반복문이 워크시트 하나에서만 실행됩니다. 각 워크시트마다 반복하고, 각 항목에 시트 정보를 함께 기록하세요.

실행 후 원본 통합 문서가 변경되었습니다. 변경되지 않아야 합니다. 예제는 한 통합 문서를 읽고 다른 통합 문서에 씁니다. 위 코드처럼 출력이 다른 Workbook 객체에 저장되는지 확인하세요.


자주 묻는 질문

통합 문서에서 수식을 읽으려면 Excel이 설치되어 있어야 하나요?

아니요. 엔진은 패키지에 포함되어 있으며 브라우저 내에서 WebAssembly로 실행됩니다. 원래의 스프레드시트 애플리케이션은 어느 시점에도 관여하지 않습니다.

수식 대신 계산된 값을 읽을 수 있나요?

네. 같은 셀에서 Formula 대신 FormulaNumberValue를 읽으세요. 먼저 HasFormula를 사용해 의미가 있는 셀에만 그 질문을 던지세요.

통합 문서를 읽으면 파일이 수정되나요?

읽기는 수정하지 않습니다. 예제는 입력 파일을 열고 결과를 위한 별도의 출력 통합 문서를 만든 뒤 그것만 저장하므로, 검사 대상 파일은 원래대로 남습니다.

어떤 Excel 형식을 읽을 수 있나요?

레거시 .xls 형식과 최신 .xlsx 파일 모두 같은 API에서 지원되므로, 통합 문서를 검사하기 전에 변환할 필요가 없습니다.

서버에 저장된 통합 문서에도 사용할 수 있나요?

네, 바이트를 브라우저로 가져올 수 있다면 가능합니다. VFS에 기록하고 그곳에서 로드하세요. 읽기 자체는 전적으로 클라이언트 측에서 이루어지며, 통합 문서는 여러분의 애플리케이션이 업로드하기로 선택한 경우에만 업로드됩니다.


함께 보기

Leggere ogni formula da un foglio di lavoro Excel nel browser con Spire.XLS per JavaScript

Qualcuno ha creato questa cartella di lavoro anni fa. Ricalcola quando i dati cambiano, i totali si spostano in modi che nessuno prevede più e non esiste documentazione — perché le formule sono la documentazione. Leggere i numeri non ti dirà come sono stati prodotti. Leggere le regole sì.

Spire.XLS per JavaScript compila un motore per fogli di calcolo in WebAssembly, così un'app React può aprire un .xlsx esistente nel browser, scorrerne le celle ed estrarre la regola dietro ognuna di esse. La cartella di lavoro passa attraverso un file system virtuale (VFS), quindi nulla viene caricato e nessun backend è coinvolto.

A ogni cella vengono poste due domande: contiene una formula e, se sì, cosa dice quella formula? La prima è una verifica di proprietà. La seconda è una lettura. Quasi tutto in questo articolo deriva dal tenere separate queste due cose.

Per la configurazione del progetto, vedi Integrare Spire.XLS per JavaScript in un progetto React. Gli esempi seguenti presuppongono che il pacchetto sia installato e che il modulo WebAssembly sia stato inizializzato.


Quando servono le formule, non i numeri

Il motivo per leggere le regole anziché i valori è quasi sempre uno di questi:

  • Subentrare in un modello che nessuno ha documentato. Le regole sono l'unica descrizione sopravvissuta di ciò che fa la cartella di lavoro.
  • Spostare i calcoli fuori dal foglio di calcolo. Reimplementare un calcolo nel codice dell'applicazione richiede di conoscere l'espressione esatta, non solo il suo ultimo risultato.
  • Verificare la coerenza. Una riga che usa silenziosamente una regola diversa da quelle intorno a sé è invisibile nei valori e ovvia nelle formule.
  • Produrre una richiesta di modifica. Un elenco di celle e delle regole che contengono è qualcosa che un utente business può esaminare e correggere.
  • Verificare una cartella di lavoro generata dal tuo stesso codice. Confermare che ciò che è stato scritto è ciò che è stato memorizzato — vedi Come inserire formule e funzioni di Excel in JavaScript (React) per il lato di scrittura di questa coppia.

Prerequisiti

Ti serve un progetto React con Spire.XLS per JavaScript installato e il modulo WebAssembly inizializzato, raggiungibile all'indirizzo window.wasmModule.spirexls. La cartella di lavoro che vuoi ispezionare dovrebbe già trovarsi nel VFS — caricata dalla cartella public della tua applicazione con FetchFileToVFS, oppure scritta lì come byte se è arrivata da altrove.

Se il risultato dovrà essere formattato — larghezze di colonna e simili — carica nel VFS anche un font, come fa l'esempio.


Le due domande da porre a ogni cella

Inizia chiedendo al foglio di lavoro la regione che effettivamente utilizza:

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange è la metà di quel frammento che ti protegge. Ciclare su A1:Z1000 in un foglio con dodici righe utilizzate passa la maggior parte del tempo su celle vuote e ti lascia a filtrarle in seguito. Chiedere al foglio la sua regione allocata mantiene il ciclo proporzionato al contenuto, cosa che conta non appena la cartella di lavoro è reale.

Poi HasFormula decide cosa vale la pena leggere. È un semplice booleano e risponde esattamente a una domanda — se la cella contiene una formula — che si rivela una domanda più ristretta di quanto sembri.


Un esempio completo

Il componente seguente carica una cartella di lavoro esistente, scorre il suo intervallo utilizzato e scrive ogni formula trovata in un nuovo foglio come riga leggibile — l'indirizzo della cella e la regola in essa memorizzata:

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Leggi formule e risultati delle funzioni dai fogli di lavoro Excel

Leggere formule e funzioni da un foglio di lavoro Excel

Nota cosa fa il codice con la cartella di lavoro di origine: la legge e nulla più. Per l'output viene creato un secondo Workbook, quindi il file ispezionato non viene mai modificato. Questo conta quando stai esaminando il documento di qualcun altro — l'ispezione dovrebbe essere non distruttiva per costruzione, non perché ti ricordi di non salvare.


Formula o valore

Qui è dove la lettura ristretta di HasFormula ripaga, perché le proprietà che puoi leggere da una cella non restituiscono tutte la stessa cosa:

Proprietà Cosa ottieni Usala quando
HasFormula Se la cella contiene una formula Vuoi selezionare un intervallo prima di leggere qualsiasi cosa
Formula La stringa della formula così com'è memorizzata — =SUM(B1:F1) Ti serve la regola
FormulaNumberValue Il risultato numerico della valutazione di quella formula Ti serve il numero prodotto dalla regola
NumberValue Il numero contenuto in una cella di dati La cella è un dato anziché una regola
Text Il testo così come è stato scritto nella cella Vuoi la stringa visualizzata

La coppia che causa più confusione è Formula rispetto a FormulaNumberValue: la stessa cella, due risposte completamente diverse. Una è la regola; l'altra è ciò che la regola ha prodotto. Chiedi quella sbagliata e otterrai un valore tecnicamente valido che non è ciò che stavi cercando — un audit delle formule che restituisce numeri, o un'estrazione di valori che restituisce formule.


Comporre un inventario delle formule

L'esempio scrive ogni occorrenza in una seconda cartella di lavoro e la scarica. Questa è la forma giusta quando l'inventario è esso stesso un documento — qualcosa da consegnare a un revisore o da allegare a un ticket.

Quando invece l'inventario è destinato allo schermo, raccogli prima gli stessi dati e decidi dopo come presentarli:

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

RangeAddressLocal è ciò che rende utilizzabile il risultato. Restituisce l'indirizzo nella notazione propria del foglio — il nome che una persona userebbe parlando della cella — anziché una coppia riga-colonna, che è tecnicamente equivalente e praticamente illeggibile. Una voce che dice B7 può essere gestita; una voce che dice riga 7, colonna 2 deve prima essere tradotta.


Più di un foglio di lavoro

Il ciclo sopra copre un solo foglio. Un inventario a livello di cartella di lavoro significa ripeterlo per ogni foglio di lavoro, recuperando ciascuno nello stesso modo in cui viene recuperato il primo, con Workbook.Worksheets.get(i) che prende l'indice.

Due dettagli valgono la pena di essere gestiti correttamente prima di scalare il tutto. Registra da quale foglio di lavoro proviene ogni voce, perché B7 su due fogli sono due celle diverse e un elenco che non le distingue è ambiguo esattamente nel momento in cui conta. E mantieni la colonna di output abbastanza larga — gli indirizzi e le stringhe delle regole sono lunghi, e un inventario troncato è peggio di uno stretto.


Perché una cella con formula può non essere rilevata

Una cella che visualizza =SUM(B1:F1) non necessariamente contiene una formula. Se è stata scritta tramite Text o Value invece che tramite Formula, oppure digitata in una cella già formattata come testo, allora i caratteri sono memorizzati come stringa. Il foglio mostra una formula; la cella contiene un'etichetta.

HasFormula lo segnala correttamente come false, e una scansione che si aspetta di trovare quella cella risulta vuota. Questa è la trappola in questo flusso di lavoro perché non sembra un errore: la cartella di lavoro contiene visibilmente delle formule, il codice viene eseguito senza errori e l'inventario è più corto di tutte le celle che sono state digitate come testo.

Quando una formula sembra mancare da un inventario, controlla come è stata scritta prima di controllare il codice di lettura. Se la cartella di lavoro è generata dalla tua stessa applicazione, questa è la stessa distinzione di proprietà che l'inserimento di formule copre dal lato della scrittura.


Problemi comuni

La scansione non trova nulla, ma il foglio è pieno di formule. Sono memorizzate come testo. Vedi la sezione precedente — HasFormula segnala solo le formule reali.

Il risultato è un numero quando volevo la formula, o viceversa. Hai letto la proprietà sbagliata. Formula fornisce la regola, FormulaNumberValue fornisce il numero calcolato.

Il ciclo è lento o produce centinaia di voci vuote. Sta scorrendo un intervallo rettangolare fisso invece della regione allocata del foglio. Usa AllocatedRange come origine dell'iterazione.

Mancano le celle di un secondo foglio. Il ciclo viene eseguito su un solo foglio di lavoro. Ripetilo per ogni foglio e mantieni il nome del foglio accanto a ogni voce.

La cartella di lavoro di origine è cambiata dopo l'esecuzione. Non dovrebbe esserlo — l'esempio legge una cartella di lavoro e ne scrive un'altra. Verifica che l'output venga salvato in un oggetto Workbook diverso, come nel codice sopra.


Domande frequenti

Devo avere Excel installato per leggere le formule da una cartella di lavoro?

No. Il motore è incluso nel pacchetto e funziona come WebAssembly all'interno del browser. L'applicazione originale per fogli di calcolo non è coinvolta in nessun momento.

Posso leggere il valore calcolato invece della formula?

Sì. Leggi FormulaNumberValue anziché Formula dalla stessa cella. Usa prima HasFormula in modo da porre quella domanda solo alle celle in cui ha senso.

Leggere una cartella di lavoro la modifica?

La lettura no. L'esempio apre l'input, crea una cartella di lavoro di output separata per i risultati e salva solo quella — così il file ispezionato resta com'era.

Quali formati Excel posso leggere?

Sia il formato legacy .xls sia i file moderni .xlsx sono supportati dalla stessa API, quindi una cartella di lavoro non deve essere convertita prima di poter essere ispezionata.

Funziona per cartelle di lavoro archiviate su un server?

Sì, se riesci a portare i byte nel browser. Scrivili nel VFS e carica da lì — la lettura stessa è interamente lato client, e la cartella di lavoro viene caricata solo se la tua applicazione sceglie di caricarla.


Vedi anche

Lire chaque formule d'une feuille de calcul Excel dans le navigateur avec Spire.XLS for JavaScript

Quelqu'un a créé ce classeur il y a des années. Il se recalcule lorsque les données changent, les totaux évoluent d'une manière que plus personne ne prévoit, et il n'existe aucune documentation — parce que les formules sont la documentation. Lire les chiffres ne vous dira pas comment ils ont été produits. Lire les règles, si.

Spire.XLS for JavaScript compile un moteur de tableur en WebAssembly, ce qui permet à une application React d'ouvrir un fichier .xlsx existant dans le navigateur, de parcourir ses cellules et d'extraire la règle qui se cache derrière chacune d'elles. Le classeur transite par un système de fichiers virtuel (VFS), donc rien n'est téléversé et aucun backend n'intervient.

Deux questions sont posées à chaque cellule : contient-elle une formule et, si oui, que dit cette formule ? La première est une vérification de propriété. La seconde est une lecture. Presque tout dans cet article découle du fait de garder ces deux aspects distincts.

Pour la configuration du projet, consultez Intégrer Spire.XLS for JavaScript dans un projet React. Les exemples ci-dessous supposent que le package est installé et que le module WebAssembly a été initialisé.


Quand vous avez besoin des formules, pas des chiffres

La raison de lire les règles plutôt que les valeurs est presque toujours l'une des suivantes :

  • Reprendre un modèle que personne n'a documenté. Les règles sont la seule description subsistante de ce que fait le classeur.
  • Sortir les calculs du tableur. Réimplémenter un calcul dans le code de l'application exige de connaître l'expression exacte, et pas seulement son dernier résultat.
  • Vérifier la cohérence. Une ligne qui utilise discrètement une règle différente de celle des lignes voisines est invisible dans les valeurs et évidente dans les formules.
  • Produire une demande de modification. Une liste de cellules et des règles qu'elles contiennent est quelque chose qu'un utilisateur métier peut examiner et corriger.
  • Vérifier un classeur généré par votre propre code. Confirmer que ce qui a été écrit est bien ce qui a été enregistré — voir Comment insérer des formules et fonctions Excel en JavaScript (React) pour le volet écriture de cette paire.

Prérequis

Vous avez besoin d'un projet React avec Spire.XLS for JavaScript installé et le module WebAssembly initialisé, accessible à l'adresse window.wasmModule.spirexls. Le classeur que vous souhaitez inspecter doit déjà se trouver dans le VFS — chargé depuis le dossier public de votre application avec FetchFileToVFS, ou écrit à cet endroit sous forme d'octets s'il provient d'ailleurs.

Si le résultat doit être mis en forme — largeurs de colonnes et autres — chargez également une police dans le VFS, comme le fait l'exemple.


Les deux questions à poser à chaque cellule

Commencez par demander à la feuille de calcul la région qu'elle utilise réellement :

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange est la moitié de cet extrait qui vous protège. Parcourir A1:Z1000 sur une feuille comptant douze lignes utilisées passe l'essentiel de son temps sur des cellules vides, et vous laisse les filtrer ensuite. Demander à la feuille sa région allouée maintient la boucle proportionnelle au contenu, ce qui compte dès que le classeur est réel.

Ensuite, HasFormula détermine ce qui vaut la peine d'être lu. C'est un simple booléen, et il répond exactement à une question — si la cellule contient une formule — ce qui s'avère être une question plus étroite qu'il n'y paraît.


Un exemple complet

Le composant ci-dessous charge un classeur existant, parcourt sa plage utilisée et écrit chaque formule qu'il trouve dans une nouvelle feuille sous forme d'une ligne lisible — l'adresse de la cellule et la règle qu'elle contient :

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Lire les formules et les résultats de fonctions depuis des feuilles de calcul Excel

Lire les formules et les fonctions depuis une feuille de calcul Excel

Notez ce que le code fait avec le classeur source : il le lit et rien d'autre. Un second Workbook est créé pour la sortie, de sorte que le fichier inspecté n'est jamais modifié. Cela compte lorsque vous examinez le document de quelqu'un d'autre — l'inspection doit être non destructive par construction, et non parce que l'on se souvient de ne pas enregistrer.


Formule ou valeur

C'est ici que la lecture étroite de HasFormula porte ses fruits, car les propriétés que vous pouvez lire depuis une cellule ne renvoient pas toutes la même chose :

Propriété Ce que vous obtenez Utilisez-la quand
HasFormula Si la cellule contient une formule Vous filtrez une plage avant toute lecture
Formula La chaîne de formule telle qu'elle est stockée — =SUM(B1:F1) Vous avez besoin de la règle
FormulaNumberValue Le résultat numérique de l'évaluation de cette formule Vous avez besoin du nombre produit par la règle
NumberValue Le nombre contenu dans une cellule de données La cellule est une donnée plutôt qu'une règle
Text Le texte tel qu'il a été écrit dans la cellule Vous voulez la chaîne affichée

La paire qui prête le plus à confusion est Formula face à FormulaNumberValue : la même cellule, deux réponses complètement différentes. L'une est la règle ; l'autre est ce que la règle a produit. Demandez la mauvaise et vous obtiendrez une valeur techniquement valide qui n'est pas ce que vous cherchiez — un audit de formules qui renvoie des nombres, ou une extraction de valeurs qui renvoie des formules.


Constituer un inventaire de formules

L'exemple écrit chaque correspondance dans un second classeur et le télécharge. C'est la bonne forme lorsque l'inventaire est lui-même un document — quelque chose à remettre à un réviseur ou à joindre à un ticket.

Lorsque l'inventaire est destiné à l'écran, en revanche, collectez d'abord les mêmes données et décidez ensuite comment les présenter :

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

RangeAddressLocal est ce qui rend le résultat exploitable. Il renvoie l'adresse dans la notation propre à la feuille — le nom qu'une personne utiliserait en parlant de la cellule — plutôt qu'une paire ligne-colonne, qui est techniquement équivalente et pratiquement illisible. Une entrée qui indique B7 peut être traitée ; une entrée qui indique ligne 7, colonne 2 doit d'abord être traduite.


Plusieurs feuilles de calcul

La boucle ci-dessus couvre une seule feuille. Un inventaire au niveau du classeur implique de la répéter pour chaque feuille de calcul à tour de rôle, en récupérant chacune de la même manière que la première, avec Workbook.Worksheets.get(i) qui prend l'index.

Deux détails méritent d'être bien traités avant de passer à l'échelle supérieure. Enregistrez la feuille de calcul d'où provient chaque entrée, car B7 sur deux feuilles correspond à deux cellules différentes et une liste qui ne les distingue pas est ambiguë exactement au moment où cela compte. Et gardez la colonne de sortie suffisamment large — les adresses et les chaînes de règles sont longues, et un inventaire tronqué est pire qu'un inventaire étroit.


Pourquoi une cellule de formule peut passer inaperçue

Une cellule qui affiche =SUM(B1:F1) ne contient pas nécessairement une formule. Si elle a été écrite via Text ou Value au lieu de Formula, ou saisie dans une cellule déjà formatée en texte, alors les caractères sont stockés sous forme de chaîne. La feuille affiche une formule ; la cellule contient une étiquette.

HasFormula le signale correctement comme false, et une analyse qui s'attend à trouver cette cellule revient vide. C'est le piège de ce flux de travail, car cela ne ressemble pas à un échec : le classeur contient visiblement des formules, le code s'exécute sans erreur, et l'inventaire est incomplet du nombre de cellules saisies comme texte.

Lorsqu'une formule semble manquer dans un inventaire, vérifiez comment elle a été écrite avant de vérifier le code de lecture. Si le classeur est généré par votre propre application, il s'agit de la même distinction de propriété que l'insertion de formules aborde du côté de l'écriture.


Problèmes courants

L'analyse ne trouve rien, mais la feuille est pleine de formules. Elles sont stockées sous forme de texte. Voir la section ci-dessus — HasFormula ne signale que les véritables formules.

Le résultat est un nombre alors que je voulais la formule, ou l'inverse. Vous avez lu la mauvaise propriété. Formula donne la règle, FormulaNumberValue donne le nombre calculé.

La boucle est lente ou produit des centaines d'entrées vides. Elle parcourt une plage rectangulaire fixe au lieu de la région allouée de la feuille. Utilisez AllocatedRange comme source de l'itération.

Les cellules d'une seconde feuille sont manquantes. La boucle s'exécute sur une seule feuille de calcul. Répétez-la pour chaque feuille de calcul, et conservez la feuille aux côtés de chaque entrée.

Le classeur source a changé après l'exécution. Il n'aurait pas dû — l'exemple lit un classeur et écrit dans un autre. Vérifiez que la sortie est enregistrée dans un objet Workbook différent, comme dans le code ci-dessus.


FAQ

Ai-je besoin d'Excel installé pour lire les formules d'un classeur ?

Non. Le moteur est fourni avec le package et s'exécute en WebAssembly dans le navigateur. L'application de tableur d'origine n'intervient à aucun moment.

Puis-je lire la valeur calculée au lieu de la formule ?

Oui. Lisez FormulaNumberValue plutôt que Formula depuis la même cellule. Utilisez d'abord HasFormula afin de ne poser cette question qu'aux cellules où elle a un sens.

La lecture d'un classeur le modifie-t-elle ?

Non. L'exemple ouvre l'entrée, crée un classeur de sortie distinct pour les résultats et n'enregistre que celui-ci — le fichier inspecté reste donc tel qu'il était.

Quels formats Excel puis-je lire ?

Aussi bien l'ancien format .xls que les fichiers modernes .xlsx sont pris en charge par la même API, si bien qu'un classeur n'a pas besoin d'être converti avant de pouvoir être inspecté.

Cela fonctionne-t-il pour des classeurs stockés sur un serveur ?

Oui, si vous pouvez amener les octets dans le navigateur. Écrivez-les dans le VFS et chargez-les depuis là — la lecture elle-même est entièrement côté client, et le classeur n'est téléversé que si votre propre application choisit de le faire.


Voir aussi

Reading every formula out of an Excel worksheet in the browser with Spire.XLS for JavaScript

Alguien creó este libro de trabajo hace años. Se recalcula cuando cambian los datos, los totales se mueven de formas que ya nadie predice y no hay documentación, porque las fórmulas son la documentación. Leer los números no le dirá cómo se produjeron. Leer las reglas sí.

Spire.XLS for JavaScript compila un motor de hojas de cálculo a WebAssembly, de modo que una aplicación React puede abrir un .xlsx existente en el navegador, recorrer sus celdas y extraer la regla que hay detrás de cada una. El libro de trabajo viaja a través de un sistema de archivos virtual (VFS), por lo que no se sube nada y no interviene ningún backend.

A cada celda se le hacen dos preguntas: ¿contiene una fórmula? Y, si es así, ¿qué dice esa fórmula? La primera es una comprobación de propiedad. La segunda es una lectura. Casi todo en este artículo se deriva de mantener esas dos cosas separadas.

Para la configuración del proyecto, consulte Integrating Spire.XLS for JavaScript in a React Project. Los ejemplos siguientes asumen que el paquete está instalado y que el módulo WebAssembly se ha inicializado.


Cuando necesita las fórmulas, no los números

La razón para leer reglas en lugar de valores casi siempre es una de estas:

  • Hacerse cargo de un modelo que nadie documentó. Las reglas son la única descripción que queda de lo que hace el libro de trabajo.
  • Sacar los cálculos de la hoja de cálculo. Reimplementar un cálculo en el código de la aplicación requiere conocer la expresión exacta, no solo su último resultado.
  • Comprobar la coherencia. Una fila que usa en silencio una regla distinta de las filas que la rodean es invisible en los valores y obvia en las fórmulas.
  • Producir una solicitud de cambio. Una lista de celdas y las reglas que contienen es algo que un usuario de negocio puede revisar y corregir.
  • Verificar un libro de trabajo generado por su propio código. Confirmar que lo que se escribió es lo que se almacenó; consulte How to Insert Excel Formulas and Functions in JavaScript (React) para la parte de escritura de ese par.

Requisitos previos

Necesita un proyecto React con Spire.XLS for JavaScript instalado y el módulo WebAssembly inicializado, accesible en window.wasmModule.spirexls. El libro de trabajo que desea inspeccionar ya debe estar en el VFS: cargado desde la carpeta pública de su aplicación con FetchFileToVFS, o escrito allí como bytes si llegó desde otro lugar.

Si el resultado se va a formatear —anchos de columna y similares—, cargue también una fuente en el VFS, como hace el ejemplo.


Las dos preguntas que hay que hacer a cada celda

Empiece por pedir a la hoja de cálculo la región que realmente usa:

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange es la mitad de ese fragmento que le protege. Recorrer A1:Z1000 en una hoja con doce filas usadas dedica la mayor parte del tiempo a celdas vacías y luego le obliga a filtrarlas. Pedir a la hoja su región asignada mantiene el bucle proporcional al contenido, lo cual importa en cuanto el libro de trabajo es real.

Después, HasFormula decide qué merece la pena leer. Es un booleano simple y responde exactamente a una pregunta —si la celda contiene una fórmula—, que resulta ser una pregunta más limitada de lo que parece.


Un ejemplo completo

El componente siguiente carga un libro de trabajo existente, recorre su rango usado y escribe cada fórmula que encuentra en una hoja nueva como una línea legible: la dirección de la celda y la regla almacenada en ella:

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Lea fórmulas y resultados de funciones desde hojas de cálculo de Excel

Read Formulas and Functions from an Excel Worksheet

Observe lo que hace el código con el libro de trabajo de origen: lo lee y nada más. Se crea un segundo Workbook para la salida, por lo que el archivo que se inspecciona nunca se modifica. Eso importa cuando examina el documento de otra persona: la inspección debe ser no destructiva por construcción, no porque recuerde no guardar.


Fórmula o valor

Aquí es donde compensa la lectura limitada de HasFormula, porque las propiedades que puede leer de una celda no todas devuelven lo mismo:

Propiedad Qué obtiene Úsela cuando
HasFormula Si la celda contiene una fórmula Filtre un rango antes de leer cualquier cosa
Formula La cadena de fórmula tal como se almacena: =SUM(B1:F1) Necesita la regla
FormulaNumberValue El resultado numérico de evaluar esa fórmula Necesita el número que produjo la regla
NumberValue El número contenido en una celda de datos La celda es un dato en lugar de una regla
Text El texto tal como se escribió en la celda Quiere la cadena de visualización

El par que causa más confusión es Formula frente a FormulaNumberValue: la misma celda, dos respuestas completamente diferentes. Una es la regla; la otra es lo que produjo la regla. Pida la equivocada y obtendrá un valor técnicamente válido que no es lo que estaba buscando: una auditoría de fórmulas que devuelve números, o una extracción de valores que devuelve fórmulas.


Cómo elaborar un inventario de fórmulas

El ejemplo escribe cada coincidencia en un segundo libro de trabajo y lo descarga. Esa es la forma correcta cuando el inventario es en sí mismo un documento: algo que entregar a un revisor o adjuntar a un ticket.

Cuando el inventario es para la pantalla, recopile primero los mismos datos y decida después cómo presentarlos:

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

RangeAddressLocal es lo que hace utilizable el resultado. Devuelve la dirección en la propia notación de la hoja —el nombre que usaría una persona al hablar de la celda— en lugar de un par fila-columna, que es técnicamente equivalente y prácticamente ilegible. Se puede actuar sobre una entrada que dice B7; una entrada que dice fila 7, columna 2 tiene que traducirse primero.


Más de una hoja de cálculo

El bucle anterior cubre una hoja. Un inventario a nivel de libro de trabajo implica repetirlo para cada hoja de cálculo por turno, obteniendo cada una de la misma manera que la primera, con Workbook.Worksheets.get(i) tomando el índice.

Merece la pena acertar con dos detalles antes de ampliarlo. Registre de qué hoja de cálculo proviene cada entrada, porque B7 en dos hojas son dos celdas diferentes y una lista que no las distingue es ambigua justo en el momento en que importa. Y mantenga la columna de salida lo bastante ancha: las direcciones y las cadenas de reglas son largas, y un inventario truncado es peor que uno estrecho.


Por qué una celda con fórmula puede pasar desapercibida

Una celda que muestra =SUM(B1:F1) no necesariamente contiene una fórmula. Si se escribió mediante Text o Value en lugar de Formula, o se escribió en una celda que ya estaba formateada como texto, los caracteres se almacenan como una cadena. La hoja muestra una fórmula; la celda contiene una etiqueta.

HasFormula lo informa correctamente como false, y un escaneo que espera encontrar esa celda no devuelve nada. Esta es la trampa de este flujo de trabajo porque no parece un fallo: el libro de trabajo contiene fórmulas visiblemente, el código se ejecuta sin error y el inventario se queda corto en todas las celdas que se escribieron como texto.

Cuando una fórmula parece faltar en un inventario, compruebe cómo se escribió antes de comprobar el código de lectura. Si el libro de trabajo lo genera su propia aplicación, esta es la misma distinción de propiedades que inserting formulas cubre desde el lado de la escritura.


Problemas comunes

El escaneo no encuentra nada, pero la hoja está llena de fórmulas. Están almacenadas como texto. Consulte la sección anterior: HasFormula solo informa de fórmulas reales.

El resultado es un número cuando quería la fórmula, o al revés. Leyó la propiedad equivocada. Formula da la regla, FormulaNumberValue da el número calculado.

El bucle es lento o produce cientos de entradas vacías. Está recorriendo un rango rectangular fijo en lugar de la región asignada de la hoja. Use AllocatedRange como origen de la iteración.

Faltan celdas de una segunda hoja. El bucle se ejecuta en una sola hoja de cálculo. Repítalo para cada hoja y conserve la hoja junto a cada entrada.

El libro de trabajo de origen cambió después de ejecutarlo. No debería haber cambiado: el ejemplo lee un libro de trabajo y escribe en otro. Compruebe que la salida se guarda en un objeto Workbook distinto, como en el código anterior.


Preguntas frecuentes

¿Necesito tener Excel instalado para leer fórmulas de un libro de trabajo?

No. El motor viene incluido con el paquete y se ejecuta como WebAssembly dentro del navegador. La aplicación original de hojas de cálculo no interviene en ningún momento.

¿Puedo leer el valor calculado en lugar de la fórmula?

Sí. Lea FormulaNumberValue en lugar de Formula de la misma celda. Use HasFormula primero para hacer esa pregunta solo a las celdas donde significa algo.

¿Leer un libro de trabajo lo modifica?

Leerlo no lo modifica. El ejemplo abre la entrada, crea un libro de trabajo de salida separado para los resultados y guarda solo ese, por lo que el archivo que se inspecciona queda como estaba.

¿Qué formatos de Excel puedo leer?

Tanto el formato heredado .xls como los archivos modernos .xlsx son compatibles con la misma API, por lo que un libro de trabajo no necesita convertirse antes de poder inspeccionarlo.

¿Esto funciona para libros de trabajo almacenados en un servidor?

Sí, si puede llevar los bytes al navegador. Escríbalos en el VFS y cargue desde allí: la lectura en sí es completamente del lado del cliente, y el libro de trabajo solo se sube si su propia aplicación decide subirlo.


Véase también

Reading every formula out of an Excel worksheet in the browser with Spire.XLS for JavaScript

Jemand hat diese Arbeitsmappe vor Jahren erstellt. Sie berechnet sich neu, wenn sich die Daten ändern, die Summen verschieben sich auf eine Weise, die niemand mehr vorhersagt, und es gibt keine Dokumentation – denn die Formeln sind die Dokumentation. Die Zahlen zu lesen, verrät Ihnen nicht, wie sie entstanden sind. Die Regeln zu lesen, schon.

Spire.XLS für JavaScript kompiliert eine Tabellenkalkulations-Engine zu WebAssembly, sodass eine React-App eine vorhandene .xlsx im Browser öffnen, ihre Zellen durchlaufen und die Regel hinter jeder einzelnen herausziehen kann. Die Arbeitsmappe wandert durch ein virtuelles Dateisystem (VFS), sodass nichts hochgeladen wird und kein Backend beteiligt ist.

An jede Zelle werden zwei Fragen gestellt: Enthält sie eine Formel, und wenn ja, was besagt diese Formel? Die erste ist eine Eigenschaftsprüfung. Die zweite ist ein Lesevorgang. Fast alles in diesem Artikel folgt daraus, diese beiden auseinanderzuhalten.

Zur Projekteinrichtung siehe Integration von Spire.XLS für JavaScript in ein React-Projekt. Die folgenden Beispiele gehen davon aus, dass das Paket installiert und das WebAssembly-Modul initialisiert wurde.


Wenn Sie die Formeln brauchen, nicht die Zahlen

Der Grund, Regeln statt Werte zu lesen, ist fast immer einer der folgenden:

  • Übernahme eines Modells, das niemand dokumentiert hat. Die Regeln sind die einzige erhaltene Beschreibung dessen, was die Arbeitsmappe tut.
  • Verlagerung von Berechnungen aus der Tabellenkalkulation. Um eine Berechnung im Anwendungscode neu zu implementieren, muss man den genauen Ausdruck kennen, nicht nur sein letztes Ergebnis.
  • Konsistenzprüfung. Eine Zeile, die stillschweigend eine andere Regel verwendet als die Zeilen um sie herum, ist in den Werten unsichtbar und in den Formeln offensichtlich.
  • Erstellung einer Änderungsanforderung. Eine Liste von Zellen und den darin enthaltenen Regeln ist etwas, das ein Fachanwender prüfen und korrigieren kann.
  • Überprüfung einer Arbeitsmappe, die Ihr eigener Code erzeugt hat. Bestätigung, dass das Geschriebene auch das Gespeicherte ist – siehe Wie man Excel-Formeln und -Funktionen in JavaScript (React) einfügt für die schreibende Seite dieses Paares.

Voraussetzungen

Sie brauchen ein React-Projekt mit installiertem Spire.XLS für JavaScript und initialisiertem WebAssembly-Modul, erreichbar unter window.wasmModule.spirexls. Die Arbeitsmappe, die Sie untersuchen möchten, sollte sich bereits im VFS befinden – geladen aus dem public-Ordner Ihrer Anwendung mit FetchFileToVFS oder als Bytes dorthin geschrieben, wenn sie von woanders gekommen ist.

Wenn das Ergebnis formatiert werden soll – Spaltenbreiten und dergleichen –, laden Sie zusätzlich eine Schriftart in das VFS, wie es das Beispiel tut.


Die zwei Fragen, die Sie an jede Zelle stellen sollten

Fragen Sie zunächst das Arbeitsblatt nach dem Bereich, den es tatsächlich verwendet:

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange ist die Hälfte dieses Snippets, die Sie schützt. Eine Schleife über A1:Z1000 in einem Blatt mit zwölf verwendeten Zeilen verbringt die meiste Zeit mit leeren Zellen und lässt Sie diese anschließend herausfiltern. Das Arbeitsblatt nach seinem zugewiesenen Bereich zu fragen, hält die Schleife proportional zum Inhalt – was zählt, sobald die Arbeitsmappe echt ist.

Dann entscheidet HasFormula, was es wert ist, gelesen zu werden. Es ist ein einfacher boolescher Wert und beantwortet genau eine Frage – ob die Zelle eine Formel enthält –, was sich als eine engere Frage entpuppt, als es klingt.


Ein vollständiges Beispiel

Die folgende Komponente lädt eine vorhandene Arbeitsmappe, durchläuft ihren verwendeten Bereich und schreibt jede gefundene Formel als lesbare Zeile in ein neues Blatt – die Zelladresse und die darin gespeicherte Regel:

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Formeln und Funktionsergebnisse aus Excel-Arbeitsblättern lesen

Read Formulas and Functions from an Excel Worksheet

Beachten Sie, was der Code mit der Quellarbeitsmappe macht: Er liest sie und sonst nichts. Für die Ausgabe wird eine zweite Workbook erstellt, sodass die untersuchte Datei nie verändert wird. Das ist wichtig, wenn Sie das Dokument einer anderen Person prüfen – die Untersuchung sollte konstruktionsbedingt nicht destruktiv sein und nicht davon abhängen, dass man daran denkt, nicht zu speichern.


Formel oder Wert

Hier zahlt sich die enge Auslegung von HasFormula aus, denn die Eigenschaften, die Sie aus einer Zelle lesen können, liefern nicht alle dasselbe:

Eigenschaft Was Sie erhalten Greifen Sie darauf zurück, wenn
HasFormula Ob die Zelle eine Formel enthält Sie einen Bereich prüfen, bevor Sie irgendetwas lesen
Formula Die gespeicherte Formelzeichenkette – =SUM(B1:F1) Sie die Regel brauchen
FormulaNumberValue Das numerische Ergebnis der Auswertung dieser Formel Sie die Zahl brauchen, die die Regel erzeugt hat
NumberValue Die in einer Datenzelle enthaltene Zahl Die Zelle Daten und keine Regel enthält
Text Der in die Zelle geschriebene Text Sie die Anzeigezeichenkette möchten

Das Paar, das die meiste Verwirrung stiftet, ist Formula versus FormulaNumberValue: dieselbe Zelle, zwei völlig unterschiedliche Antworten. Die eine ist die Regel; die andere ist das, was die Regel erzeugt hat. Fragen Sie nach der falschen, erhalten Sie einen technisch gültigen Wert, der nicht das ist, wonach Sie gesucht haben – ein Formel-Audit, das Zahlen zurückgibt, oder eine Wertextraktion, die Formeln zurückgibt.


Ein Formelverzeichnis zusammenstellen

Das Beispiel schreibt jeden Treffer in eine zweite Arbeitsmappe und lädt sie herunter. Das ist die richtige Form, wenn das Verzeichnis selbst ein Dokument ist – etwas, das man einem Prüfer aushändigt oder an ein Ticket anhängt.

Wenn das Verzeichnis stattdessen für den Bildschirm bestimmt ist, sammeln Sie zuerst dieselben Daten und entscheiden Sie danach, wie Sie sie präsentieren:

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

RangeAddressLocal ist es, was das Ergebnis brauchbar macht. Es gibt die Adresse in der eigenen Notation des Blatts zurück – den Namen, den eine Person verwenden würde, wenn sie über die Zelle spricht – statt eines Zeilen-und-Spalten-Paares, das technisch äquivalent und praktisch unlesbar ist. Ein Eintrag, der B7 sagt, kann umgesetzt werden; ein Eintrag, der Zeile 7, Spalte 2 sagt, muss zuerst übersetzt werden.


Mehr als ein Arbeitsblatt

Die obige Schleife deckt ein Blatt ab. Ein Verzeichnis auf Arbeitsmappenebene bedeutet, sie der Reihe nach für jedes Arbeitsblatt zu wiederholen und jedes davon genauso abzurufen, wie das erste abgerufen wird, wobei Workbook.Worksheets.get(i) den Index annimmt.

Zwei Details sollten Sie richtig hinbekommen, bevor Sie es skalieren. Halten Sie fest, von welchem Arbeitsblatt jeder Eintrag stammt, denn B7 auf zwei Blättern sind zwei verschiedene Zellen, und eine Liste, die sie nicht unterscheidet, ist genau in dem Moment mehrdeutig, in dem es darauf ankommt. Und halten Sie die Ausgabespalte breit genug – die Adressen und Regelzeichenketten sind lang, und ein abgeschnittenes Verzeichnis ist schlimmer als ein schmales.


Warum eine Formelzelle unentdeckt bleiben kann

Eine Zelle, die =SUM(B1:F1) anzeigt, enthält nicht unbedingt eine Formel. Wenn sie über Text oder Value statt über Formula geschrieben oder in eine bereits als Text formatierte Zelle eingegeben wurde, dann werden die Zeichen als Zeichenkette gespeichert. Das Blatt zeigt eine Formel; die Zelle enthält ein Label.

HasFormula meldet dies korrekt als false, und ein Scan, der diese Zelle zu finden erwartet, liefert nichts. Das ist die Falle in diesem Workflow, weil es nicht wie ein Fehler aussieht: Die Arbeitsmappe enthält sichtbar Formeln, der Code läuft fehlerfrei, und dem Verzeichnis fehlen so viele Zellen, wie als Text eingegeben wurden.

Wenn in einem Verzeichnis eine Formel zu fehlen scheint, prüfen Sie, wie sie geschrieben wurde, bevor Sie den Lesecode prüfen. Wenn die Arbeitsmappe von Ihrer eigenen Anwendung erzeugt wird, ist dies dieselbe Eigenschaftsunterscheidung, die das Einfügen von Formeln von der schreibenden Seite her behandelt.


Häufige Probleme

Der Scan findet nichts, aber das Blatt ist voller Formeln. Sie sind als Text gespeichert. Siehe den Abschnitt oben – HasFormula meldet nur echte Formeln.

Das Ergebnis ist eine Zahl, obwohl ich die Formel wollte, oder umgekehrt. Sie haben die falsche Eigenschaft gelesen. Formula liefert die Regel, FormulaNumberValue liefert die berechnete Zahl.

Die Schleife ist langsam oder erzeugt Hunderte leerer Einträge. Sie durchläuft einen festen rechteckigen Bereich statt des zugewiesenen Bereichs des Blatts. Verwenden Sie AllocatedRange als Quelle der Iteration.

Zellen aus einem zweiten Blatt fehlen. Die Schleife läuft auf einem Arbeitsblatt. Wiederholen Sie sie für jedes Arbeitsblatt und behalten Sie das Blatt neben jedem Eintrag bei.

Die Quellarbeitsmappe hat sich nach dem Ausführen geändert. Das sollte sie nicht – das Beispiel liest eine Arbeitsmappe und schreibt in eine andere. Prüfen Sie, dass die Ausgabe in ein anderes Workbook-Objekt gespeichert wird, wie im Code oben.


FAQ

Muss Excel installiert sein, um Formeln aus einer Arbeitsmappe zu lesen?

Nein. Die Engine ist im Paket enthalten und läuft als WebAssembly im Browser. Die ursprüngliche Tabellenkalkulationsanwendung ist an keiner Stelle beteiligt.

Kann ich statt der Formel den berechneten Wert lesen?

Ja. Lesen Sie FormulaNumberValue statt Formula aus derselben Zelle. Verwenden Sie zuerst HasFormula, damit Sie diese Frage nur bei Zellen stellen, bei denen sie etwas bedeutet.

Verändert das Lesen einer Arbeitsmappe diese?

Das Lesen nicht. Das Beispiel öffnet die Eingabe, erstellt eine separate Ausgabearbeitsmappe für die Ergebnisse und speichert nur diese – die untersuchte Datei bleibt also so, wie sie war.

Welche Excel-Formate kann ich lesen?

Sowohl das ältere .xls-Format als auch moderne .xlsx-Dateien werden von derselben API unterstützt, sodass eine Arbeitsmappe nicht konvertiert werden muss, bevor sie untersucht werden kann.

Funktioniert das auch für Arbeitsmappen, die auf einem Server gespeichert sind?

Ja, wenn Sie die Bytes in den Browser bekommen. Schreiben Sie sie in das VFS und laden Sie von dort – das Lesen selbst findet vollständig clientseitig statt, und die Arbeitsmappe wird nur hochgeladen, wenn Ihre eigene Anwendung sich dafür entscheidet.


Siehe auch

Reading every formula out of an Excel worksheet in the browser with Spire.XLS for JavaScript

Кто-то создал эту книгу много лет назад. Она пересчитывается при изменении данных, итоги меняются так, как уже никто не предскажет, и никакой документации нет — потому что формулы и есть документация. Чтение чисел не расскажет, как они были получены. Чтение правил — расскажет.

Spire.XLS for JavaScript компилирует движок электронных таблиц в WebAssembly, поэтому приложение на React может открыть существующий .xlsx в браузере, обойти его ячейки и извлечь правило, стоящее за каждой из них. Книга перемещается через виртуальную файловую систему (VFS), поэтому ничего не загружается на сервер и бэкенд не задействован.

К каждой ячейке задаются два вопроса: содержит ли она формулу и, если да, что эта формула говорит? Первый — это проверка свойства. Второй — это чтение. Практически всё в этой статье вытекает из того, чтобы не смешивать эти два действия.

О настройке проекта см. Интеграция Spire.XLS for JavaScript в проект на React. Примеры ниже предполагают, что пакет установлен и модуль WebAssembly инициализирован.


Когда нужны формулы, а не числа

Причина читать правила, а не значения, почти всегда одна из следующих:

  • Принять на себя модель, которую никто не документировал. Правила — единственное сохранившееся описание того, что делает книга.
  • Перенос вычислений из электронной таблицы. Чтобы реализовать вычисление в коде приложения заново, нужно знать точное выражение, а не только его последний результат.
  • Проверка согласованности. Одна строка, тихо использующая иное правило, чем окружающие её строки, незаметна в значениях и очевидна в формулах.
  • Подготовка запроса на изменение. Список ячеек и содержащихся в них правил — это то, что бизнес-пользователь может просмотреть и исправить.
  • Проверка книги, созданной вашим собственным кодом. Подтверждение того, что записано именно то, что сохранилось — о стороне записи этой пары см. Как вставлять формулы и функции Excel в JavaScript (React).

Предварительные требования

Вам нужен проект на React с установленным Spire.XLS for JavaScript и инициализированным модулем WebAssembly, доступным по адресу window.wasmModule.spirexls. Книга, которую вы хотите проверить, уже должна находиться в VFS — загружена из общей папки вашего приложения с помощью FetchFileToVFS или записана туда в виде байтов, если она пришла откуда-то ещё.

Если результат будет форматироваться — ширины столбцов и тому подобное — загрузите в VFS также шрифт, как это делает пример.


Два вопроса к каждой ячейке

Начните с того, что запросите у листа область, которую он действительно использует:

// The region the sheet actually uses — not the whole grid
const usedRange = sheet.AllocatedRange;

for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    // this cell holds a rule
  }
}

AllocatedRange — это та половина фрагмента, которая вас защищает. Перебор A1:Z1000 на листе с двенадцатью используемыми строками тратит большую часть времени на пустые ячейки и оставляет вам их фильтрацию после. Запрос у листа его выделенной области делает цикл пропорциональным содержимому, что важно, как только книга становится реальной.

Затем HasFormula решает, что стоит читать. Это обычное логическое значение, и оно отвечает ровно на один вопрос — содержит ли ячейка формулу — который, как выясняется, является более узким вопросом, чем кажется.


Полный пример

Компонент ниже загружает существующую книгу, обходит её используемый диапазон и записывает каждую найденную формулу в новый лист в виде удобочитаемой строки — адрес ячейки и хранящееся в ней правило:

function App() {
  const readFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font and Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'FormulasAndFunctions.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Load the Excel workbook
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Get the used cell range of the worksheet
    const usedRange = sheet.AllocatedRange;

    // Create an output workbook
    const output = new xlsModule.Workbook();
    const outSheet = output.Worksheets.get(0);
    let outRow = 1;

    // Loop through the used cells
    for (const cell of usedRange.Cells) {
      // Check whether the cell contains a formula or function
      if (cell.HasFormula) {
        // Get the cell name
        const cellname = cell.RangeAddressLocal;

        // Get the formula or function in the cell
        const formula = cell.Formula;

        // Write the cell name and formula that were read
        outSheet.Range.get({ row: outRow, column: 1 }).Value = "Cell " + cellname + " contains: " + formula;
        outRow += 1;
      }
    }

    // Set the output column width so the text displays completely
    outSheet.SetColumnWidth(1, 45);

    // Save the output workbook
    const outputFileName = 'ReadFormulasAndFunctions_output.xlsx';
    output.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    output.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Read Formulas and Functions</h1>
      <button onClick={readFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Чтение формул и результатов функций из листов Excel

Read Formulas and Functions from an Excel Worksheet

Обратите внимание, что код делает с исходной книгой: он только читает её, и ничего больше. Для вывода создаётся второй Workbook, поэтому проверяемый файл никогда не изменяется. Это важно, когда вы изучаете чужой документ — проверка должна быть неразрушающей по своей конструкции, а не за счёт того, что вы помните о необходимости не сохранять.


Формула или значение

Именно здесь узкое понимание HasFormula окупается, потому что свойства, которые можно прочитать из ячейки, возвращают не одно и то же:

Свойство Что вы получаете Когда к нему прибегать
HasFormula Содержит ли ячейка формулу При отборе диапазона перед чтением чего-либо
Formula Строка формулы в том виде, в каком она хранится — =SUM(B1:F1) Вам нужно правило
FormulaNumberValue Числовой результат вычисления этой формулы Вам нужно число, которое произвело правило
NumberValue Число, содержащееся в ячейке данных Ячейка содержит данные, а не правило
Text Текст в том виде, в каком он записан в ячейку Вам нужна отображаемая строка

Наибольшую путаницу вызывает пара Formula и FormulaNumberValue: одна и та же ячейка, два совершенно разных ответа. Один — это правило; другой — то, что правило произвело. Запросите не тот — и получите технически корректное значение, которое не является тем, что вы искали: аудит формул, возвращающий числа, или извлечение значений, возвращающее формулы.


Составление описи формул

В примере каждое найденное совпадение записывается во вторую книгу и скачивается. Это правильная форма, когда сама опись является документом — тем, что можно передать проверяющему или приложить к заявке.

Когда же опись предназначена для отображения на экране, сначала соберите те же данные, а затем решите, как их представить:

// Collect first, then decide how to present it
const inventory = [];
for (const cell of usedRange.Cells) {
  if (cell.HasFormula) {
    inventory.push({ cell: cell.RangeAddressLocal, formula: cell.Formula });
  }
}

Именно RangeAddressLocal делает результат пригодным для использования. Он возвращает адрес в собственной нотации листа — имя, которое человек использовал бы при обсуждении ячейки, — а не пару «строка и столбец», которая технически эквивалентна и практически нечитаема. С записью, которая говорит B7, можно работать; запись, которая говорит «строка 7, столбец 2», нужно сначала перевести.


Более одного листа

Приведённый выше цикл охватывает один лист. Опись на уровне всей книги означает повторение его по очереди для каждого листа, при этом каждый лист извлекается так же, как первый, с помощью Workbook.Worksheets.get(i), принимающего индекс.

Прежде чем масштабировать это, стоит правильно сделать две вещи. Записывайте, с какого листа пришла каждая запись, потому что B7 на двух листах — это две разные ячейки, а список, который их не различает, становится неоднозначным именно в тот момент, когда это важно. И держите столбец вывода достаточно широким — адреса и строки правил длинные, а обрезанная опись хуже узкой.


Почему ячейка с формулой может остаться незамеченной

Ячейка, отображающая =SUM(B1:F1), не обязательно содержит формулу. Если она была записана через Text или Value вместо Formula, или введена в ячейку, уже отформатированную как текст, то символы хранятся как строка. Лист показывает формулу; ячейка содержит метку.

HasFormula корректно сообщает об этом как false, и сканирование, ожидающее найти эту ячейку, ничего не находит. В этом и заключается ловушка данного рабочего процесса: это не выглядит как сбой — книга наглядно содержит формулы, код выполняется без ошибок, а в описи не хватает ровно столько ячеек, сколько было введено как текст.

Когда формула, по-видимому, отсутствует в описи, проверьте, как она была записана, прежде чем проверять код чтения. Если книга создаётся вашим собственным приложением, это то же самое различие свойств, которое вставка формул рассматривает со стороны записи.


Типичные проблемы

Сканирование ничего не находит, но лист полон формул. Они хранятся как текст. См. раздел выше — HasFormula сообщает только о настоящих формулах.

Результат — число, хотя мне нужна была формула, или наоборот. Вы прочитали не то свойство. Formula даёт правило, FormulaNumberValue даёт вычисленное число.

Цикл работает медленно или создаёт сотни пустых записей. Он обходит фиксированный прямоугольный диапазон вместо выделенной области листа. Используйте AllocatedRange в качестве источника перебора.

Отсутствуют ячейки со второго листа. Цикл выполняется на одном листе. Повторите его для каждого листа и сохраняйте имя листа рядом с каждой записью.

Исходная книга изменилась после выполнения. Этого не должно было произойти — пример читает одну книгу, а записывает в другую. Убедитесь, что вывод сохраняется в другой объект Workbook, как в приведённом выше коде.


Часто задаваемые вопросы

Нужен ли установленный Excel, чтобы читать формулы из книги?

Нет. Движок входит в состав пакета и работает как WebAssembly внутри браузера. Исходное приложение для работы с электронными таблицами нигде не задействовано.

Можно ли прочитать вычисленное значение вместо формулы?

Да. Читайте FormulaNumberValue вместо Formula из той же ячейки. Сначала используйте HasFormula, чтобы задавать этот вопрос только тем ячейкам, где он имеет смысл.

Изменяет ли чтение книгу?

Чтение — нет. Пример открывает входной файл, создаёт отдельную выходную книгу для результатов и сохраняет только её, поэтому проверяемый файл остаётся таким, каким был.

Какие форматы Excel я могу читать?

Как устаревший формат .xls, так и современные файлы .xlsx поддерживаются одним и тем же API, поэтому книгу не нужно преобразовывать перед проверкой.

Работает ли это с книгами, хранящимися на сервере?

Да, если вы можете доставить байты в браузер. Запишите их в VFS и загружайте оттуда — само чтение полностью выполняется на стороне клиента, и книга загружается на сервер только если ваше приложение решит это сделать.


См. также

Writing formulas and functions into an Excel worksheet in the browser with Spire.XLS for JavaScript

Uma planilha gerada cheia de números pré-calculados é um instantâneo. Ela parece correta no momento em que é produzida e começa a envelhecer imediatamente: os dados por trás dela avançam, os números dentro dela não, e depois que o arquivo saiu da sua aplicação ninguém consegue dizer quais células podem ser alteradas. Uma pasta de trabalho que carrega suas fórmulas, por outro lado, permanece um documento vivo — edite uma entrada e os totais acompanham.

O Spire.XLS for JavaScript é um mecanismo de planilha compilado para WebAssembly, de modo que um aplicativo React pode criar pastas de trabalho no navegador sem um servidor. Os arquivos são lidos e gravados por meio de um sistema de arquivos virtual (VFS), e as fórmulas são escritas da mesma forma que os valores: através do objeto Range de uma célula. Só o nome da propriedade muda.

Esse último ponto é todo o truque. A pergunta interessante não é como escrever uma fórmula, mas com qual das quatro propriedades disponíveis escrevê-la, porque três delas armazenarão silenciosamente sua fórmula como texto simples.

Para a configuração do projeto, consulte Integrating Spire.XLS for JavaScript in a React Project. Os exemplos abaixo pressupõem que o pacote está instalado e que o módulo WebAssembly foi inicializado.


Por que pastas de trabalho geradas devem conter fórmulas

Gerar um arquivo com as respostas já preenchidas é mais fácil de escrever e pior de receber. Os casos em que isso realmente quebra:

  • Modelos com espaços reservados. Espera-se que o destinatário substitua as entradas. Se os totais estiverem codificados diretamente, substituir uma entrada deixa os totais errados e nada o avisa.
  • Modelos entregues a um analista. Ele vai querer testar uma premissa diferente. Uma planilha que não pode ser recalculada é uma planilha que ele terá de reconstruir.
  • Relatórios que precisam ser rastreáveis. Um número sem uma regra visível por trás dele não pode ser verificado. Uma fórmula pode.
  • Planilhas que alimentam outras planilhas. Outras células fazem referência a estas; se o valor nunca for recalculado, tudo o que está a jusante herda a desatualização.

Em todos os quatro casos, a fórmula é o ponto central do arquivo. Os valores são um subproduto.


Pré-requisitos

Você precisa de um projeto React com o Spire.XLS for JavaScript instalado e o módulo WebAssembly inicializado, acessível em window.wasmModule.spirexls. O exemplo abaixo também carrega uma fonte no VFS antes de formatar qualquer texto e salva com o sinalizador da versão Excel 2010 para que a saída abra sem problemas tanto no Excel atual quanto em versões mais antigas.


Escolhendo a propriedade que escreve uma fórmula

Cada célula em que você escreve é um objeto Range, e ele expõe quatro propriedades que aceitam algo. Elas não são intercambiáveis:

Propriedade O que você fornece a ela O que a célula acaba armazenando
Value Texto ou um valor, com o tipo inferido O valor, como dado
NumberValue Um número Um número — dado, não uma regra
Text Uma string de exibição Uma string literal, nunca avaliada
Formula Uma string de fórmula começando com = A própria regra, que o mecanismo avalia

Text é a propriedade com que se deve ter cuidado, e vale a pena entender por quê antes do código abaixo. Atribua =SUM(B1:F1) a Text e a célula armazenará esses caracteres — ela exibirá a fórmula para sempre, porque nada jamais a avaliará.

Esse comportamento não é um defeito. É exatamente o que o exemplo usa deliberadamente, para que cada linha possa mostrar a fórmula à esquerda e seu resultado à direita: a célula da esquerda usa Text porque sua finalidade é exibir a regra, e a célula da direita usa Formula porque sua finalidade é aplicá-la.


Escrevendo fórmulas nas células

O fluxo é curto:

  1. Crie um objeto Workbook.
  2. Obtenha uma planilha com o método Workbook.Worksheets.get().
  3. Escreva os dados de entrada nas células e defina a formatação das células.
  4. Atribua fórmulas às células que devem calcular, por meio da propriedade Range.Formula.
  5. Salve a pasta de trabalho com Workbook.SaveToFile().

O exemplo cria uma pequena planilha com uma linha de números de entrada e, em seguida, escreve cinco fórmulas abaixo dela — uma expressão aritmética, uma função de data, uma função trigonométrica, uma média e uma soma:

function App() {
  const insertFormulasAndFunctions = async () => {
    // Get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // Check whether the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // Load the font into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);

    // Create a Workbook object
    const workbook = new xlsModule.Workbook();

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Declare two variables: currentRow and currentFormula
    let currentRow = 1;
    let currentFormula = "";

    // Set the column width
    sheet.SetColumnWidth(1, 32);
    sheet.SetColumnWidth(2, 16);

    // Write data into cells
    sheet.Range.get({ row: currentRow, column: 1 }).Value = "Test Data";
    sheet.Range.get({ row: currentRow, column: 2 }).NumberValue = 1;
    sheet.Range.get({ row: currentRow, column: 3 }).NumberValue = 2;
    sheet.Range.get({ row: currentRow, column: 4 }).NumberValue = 3;
    sheet.Range.get({ row: currentRow, column: 5 }).NumberValue = 4;
    sheet.Range.get({ row: currentRow, column: 6 }).NumberValue = 5;
    currentRow += 2;
    sheet.Range.get({ row: currentRow, column: 1 }).Value = "Formula or Function";
    sheet.Range.get({ row: currentRow, column: 2 }).Value = "Result";

    // Set the cell formatting
    let range = sheet.Range.get({ row: currentRow, column: 1, lastRow: currentRow, lastColumn: 2 });
    range.Style.Font.FontName = "Arial";
    range.Style.KnownColor = xlsModule.ExcelColors.LightGreen;
    range.Style.FillPattern = xlsModule.ExcelPatternType.Solid;
    range.Style.Borders.get(xlsModule.BordersLineType.EdgeBottom).LineStyle = xlsModule.LineStyleType.Medium;
    range.Style.Font.IsBold = true;

    // Mathematical operation
    currentFormula = "=1/2+3*4";
    currentRow += 1;
    sheet.Range.get({ row: currentRow, column: 1 }).NumberFormat = "@";
    sheet.Range.get({ row: currentRow, column: 1 }).Text = currentFormula;
    sheet.Range.get({ row: currentRow, column: 2 }).Formula = currentFormula;

    // Date function
    currentFormula = "=TODAY()";
    currentRow += 1;
    sheet.Range.get({ row: currentRow, column: 1 }).NumberFormat = "@";
    sheet.Range.get({ row: currentRow, column: 1 }).Text = currentFormula;
    sheet.Range.get({ row: currentRow, column: 2 }).Formula = currentFormula;
    sheet.Range.get({ row: currentRow, column: 2 }).Style.NumberFormat = "YYYY/MM/DD";

    // Trigonometric function
    currentFormula = "=SIN(PI()/6)";
    currentRow += 1;
    sheet.Range.get({ row: currentRow, column: 1 }).NumberFormat = "@";
    sheet.Range.get({ row: currentRow, column: 1 }).Text = currentFormula;
    sheet.Range.get({ row: currentRow, column: 2 }).Formula = currentFormula;

    // Average function
    currentFormula = "=AVERAGE(B1:F1)";
    currentRow += 1;
    sheet.Range.get({ row: currentRow, column: 1 }).NumberFormat = "@";
    sheet.Range.get({ row: currentRow, column: 1 }).Text = currentFormula;
    sheet.Range.get({ row: currentRow, column: 2 }).Formula = currentFormula;

    // Sum function
    currentFormula = "=SUM(B1:F1)";
    currentRow += 1;
    sheet.Range.get({ row: currentRow, column: 1 }).NumberFormat = "@";
    sheet.Range.get({ row: currentRow, column: 1 }).Text = currentFormula;
    sheet.Range.get({ row: currentRow, column: 2 }).Formula = currentFormula;

    // Save the workbook
    const outputFileName = 'InsertFormulasAndFunctions_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    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>Insert Formulas and Functions</h1>
      <button onClick={insertFormulasAndFunctions}>
        Start
      </button>
    </div>
  );
}

export default App;

Insira fórmulas e resultados de funções em planilhas do Excel

Insert Formulas and Functions into an Excel Worksheet

Observe a chamada de formatação antes das fórmulas. Range.get() aceita lastRow e lastColumn, então um bloco de cabeçalho pode ser estilizado em uma única chamada em vez de célula por célula — o mesmo objeto que você usa para escrever uma fórmula também carrega o estilo.


Funções por categoria

As cinco fórmulas do exemplo não são cinco técnicas diferentes. São uma única técnica aplicada a cinco tipos de expressão:

Fórmula Tipo Vale saber
=1/2+3*4 Expressão aritmética A precedência de operadores se aplica exatamente como no Excel
=TODAY() Função de data Volátil — muda a cada recálculo e precisa de um formato de data para ser exibida como data
=SIN(PI()/6) Trigonométrica Os ângulos estão em radianos; escreva PI()/6 em vez de um decimal arredondado
=AVERAGE(B1:F1) Estatística em um intervalo A sintaxe do intervalo é idêntica à que você digitaria no Excel
=SUM(B1:F1) Agregação Mesma sintaxe de intervalo, função diferente

Não existe uma API separada para "funções". Uma função é uma fórmula — Range.Formula recebe a string, e o mecanismo decide o que fazer com ela. É por isso que o catálogo de coisas que você pode escrever é tão grande quanto a lista de funções do mecanismo de planilha, sem nenhum wrapper a manter por função.


Exibindo o texto da fórmula ao lado do seu resultado

Um dos hábitos mais úteis em uma planilha gerada é manter a regra visível ao lado da sua saída. O exemplo faz isso colocando a string da fórmula na coluna A como texto literal e o valor avaliado na coluna B:

// Column A displays the rule; column B applies it
sheet.Range.get({ row: currentRow, column: 1 }).NumberFormat = "@";
sheet.Range.get({ row: currentRow, column: 1 }).Text = currentFormula;
sheet.Range.get({ row: currentRow, column: 2 }).Formula = currentFormula;

Atribuir "@" como formato de número primeiro é o que impede a coluna de rótulos de tentar interpretar a string — a célula é declarada como texto antes que qualquer coisa seja escrita nela. A coluna de resultados não precisa desse cuidado, mas pode precisar de um formato de exibição próprio: a linha da data define .Style.NumberFormat = "YYYY/MM/DD", sem o qual o valor é renderizado como um número de série em vez de uma data.

Uma planilha que carrega suas próprias regras assim sobrevive a cada ida e volta, porque os rótulos são texto simples que nenhum mecanismo vai tocar.


Uma fórmula em todo um intervalo

Planilhas reais raramente precisam de uma única fórmula; elas precisam da mesma regra ao longo de uma coluna. Como você é quem monta a string, você controla as referências explicitamente:

// One rule, many rows: the row number in the reference shifts with each cell
for (let row = 2; row <= 11; row += 1) {
  sheet.Range.get({ row: row, column: 3 }).Formula = `=A${row}*B${row}`;
}

Esse é o mesmo comportamento de referência relativa que você obteria arrastando uma fórmula para baixo no Excel, escrito por extenso. Se a regra deve sempre apontar para uma entrada fixa, fixe-a — $A$1 não muda quando a fórmula se move, enquanto A1 muda.


Sintaxe de fórmulas que costuma causar problemas

  • O sinal de igual no início. Uma string de fórmula sem = não é uma fórmula. Ela será armazenada como texto e nunca avaliada.
  • Referências relativas versus absolutas. A1 muda; $A$1 não. Escolha deliberadamente ao gerar fórmulas em um laço.
  • Referências entre planilhas. Nomeie a planilha dentro da string — Sheet2!A1. Se o nome da planilha contiver espaços, coloque-o entre aspas: 'Q1 Sales'!A1.
  • Separadores de argumentos entre localidades. A string é armazenada como você a escreve. Mantenha a forma separada por vírgulas usada acima se o arquivo for aberto em uma combinação de localidades, nas quais algumas exibem ponto e vírgula.
  • Funções voláteis. TODAY() e NOW() mudam sempre que a pasta de trabalho é recalculada, então um valor lido depois não corresponderá ao que você viu. Essa lacuna entre uma regra e seu último valor calculado merece ser conhecida por si só — é disso que trata Reading and Extracting Excel Formulas in JavaScript (React).

Problemas comuns

A célula exibe a fórmula em vez do resultado. Ela foi escrita por meio de Text em vez de Formula. Reatribua-a com Formula — a célula precisa da regra, não dos caracteres.

Uma data aparece como um número de cinco dígitos. Esse é o valor de série sem nenhum formato de data aplicado. Defina .Style.NumberFormat na célula, como o exemplo faz para a linha de TODAY().

A formatação recai sobre células que eu não pretendia tocar. Verifique o intervalo que você passou para Range.get(). Informar lastRow e lastColumn aplica a alteração a um bloco, o que é conveniente para um cabeçalho e fácil de delimitar incorretamente.

A fórmula é armazenada, mas a célula parece vazia quando lida de volta. Os resultados aparecem depois que a pasta de trabalho é calculada. Salve após escrever as fórmulas para que os valores calculados viajem junto com o arquivo.


Perguntas frequentes

Preciso do Excel ou do Office instalado para escrever fórmulas?

Não. O mecanismo de planilha é fornecido com o pacote e é executado como WebAssembly no navegador. Nada é automatizado e nada é necessário na máquina do usuário.

Uma fórmula pode fazer referência a uma planilha diferente na mesma pasta de trabalho?

Sim, e você a escreve exatamente como faria no Excel — inclua o nome da planilha na string da fórmula.

Posso misturar fórmulas e valores simples em uma mesma planilha?

Sim, e normalmente você fará isso. As propriedades são independentes: algumas células recebem dados por meio de NumberValue ou Value, outras recebem regras por meio de Formula.

O que acontece com os resultados quando o destinatário abre o arquivo?

As fórmulas são armazenadas, e o Excel recalcula quando a pasta de trabalho é aberta. Esse é o objetivo de escrever regras em vez de resultados — o arquivo permanece correto mesmo que as entradas sejam editadas depois.

Escrever fórmulas exige um backend?

Não. A pasta de trabalho é criada no navegador e retornada como bytes que você transforma em um Blob para download. Nada é enviado.


Veja também