In finance and tax scenarios, invoice data entry is one of the most common and time-consuming tasks. The invoice number, date, amount, tax amount and buyer on every invoice must be manually checked and entered into Excel or a financial system one by one. During mid-month reconciliation, month-end tax filing or reimbursement peak periods, the backlog of invoices often numbers in the hundreds, and manual entry speed becomes the bottleneck. The traditional approach is to open each invoice PDF page by page, find the corresponding fields, copy and paste — which is not only inefficient but also highly prone to omissions, misalignments and mistyped amounts. Any single error directly affects the accuracy of reconciliation and tax filing. Invoice layouts also vary widely, with fields in all sorts of positions, further increasing the risk of errors in manual processing. Automating the repetitive work of "reading each invoice and copying its fields" is therefore one of the pain points financial teams most urgently want to solve.

Traditional SDK API vs. Spire.Agent.Office

For "extracting fields from a PDF invoice and exporting to Excel", the traditional SDK and Spire.Agent.Office take two completely different paths. With the traditional approach, you must first figure out the field positions and page structure of every invoice, then write locating and extraction code for each field — change the layout and you must change the code. With the agent approach, you only need to describe in natural language "what to extract and what to export as"; the AI understands and orchestrates the rest:

Traditional Spire.Office for .NET API Spire.Agent.Office
Driving approach Write loops + conditionals + exception-handling code, controlling every step of document processing Describe the goal in natural language; the AI understands and orchestrates the execution path
Code volume Page-by-page parsing usually needs 300-600 lines of C# (page traversal, field locating, data export, etc.) ~10 lines of calling code + 1 natural language instruction
Field recognition Hard-code the page position and format of each field; layout changes require code changes AI automatically understands the invoice layout and locates fields such as invoice number, date, amount
Page handling Manually traverse every page and extract each one AI automatically extracts page by page and aggregates
Data export Manually write Excel writing logic and column layout AI automatically generates a structured Excel with aligned fields
Requirement changes Change extracted fields → change code → compile → redeploy Modify the instruction; takes effect immediately

From the comparison, when invoice layouts, extracted fields or export structures change frequently, the agent only needs a change of one sentence, while the traditional approach requires changing code and redeploying.

This article explains how to use the Spire.Agent.Office PDF AI capability to automatically extract the invoice number, date, amount, tax amount and buyer name from each page of a PDF invoice and export them to Excel, digitalizing your financial documents in one step.

For product installation and SpireToken configuration, please refer to Integrating Spire.Agent.Office in a .NET Project. The examples below assume Spire.Agent.Office is installed and SpireToken is configured.


Automatic Invoice Information Extraction

The core idea of automatic invoice information extraction is: pass multiple invoice PDFs to the AI agent as attachments; the agent reads each invoice, understands the layout page by page, recognizes fields such as invoice number, issue date, amount, tax ID, tax amount, buyer name and title, and aggregates them into a structured Excel. The whole process is roughly divided into three steps — first the agent reads each invoice PDF and locates the invoice fields on every page; second, it aligns the fields recognized on each page by semantics; finally, it aggregates the results into Excel and beautifies them as requested (auto-fitting column widths, adding borders, keeping numeric values with two decimal places and right-aligned). The whole "page-by-page parsing → field recognition → aggregation & beautification" process is completed automatically by the AI from a natural language instruction, without writing a separate parsing routine for each invoice or worrying about layout differences between suppliers.

For invoice PDFs with dozens or hundreds of pages, the traditional approach requires a set of locating rules for each layout, whereas with the agent approach you always maintain just one natural language instruction no matter how the invoice source or layout changes. Requirements such as the amount basis (tax-inclusive vs. tax-exclusive), column order, or whether to flag anomalies can also be written directly into the instruction and take effect immediately.

The following example uses the Spire.Agent.Office agent to automatically extract invoice information from each page of PDFs and export it to Excel through a natural language instruction:

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

// PDF processing configuration
string key = "**************************";  // Apply for a SpireToken Key on the official website

string inputDir = @"E:\invoices";  // Directory containing invoice PDFs (multiple allowed)
string[] pdfFiles = Directory.GetFiles(inputDir, "*.pdf", SearchOption.TopDirectoryOnly);
string savePath = @"E:\output\merged.xlsx";  // Output file path (null -> auto-generated to the output directory)

string instruction =
    "Read the attachment files and identify the information of each invoice, extracting the invoice number, issue date, amount, tax ID, tax amount, buyer name and title.\n" +
    "Put each invoice as one row and summarize them into a single Excel table.\n" +
    "When exporting to Excel, please beautify the table appropriately:\n" +
    "auto-fit the column widths so that text is fully displayed; add borders to the whole data area to make rows and columns clear and readable;\n" +
    "keep numeric columns such as amount and tax amount with two decimal places and right-aligned. Finally save as a well-formatted, easy-to-read Excel file.";

// Call the PDF processing function (attachments are the invoice PDFs)
AIResult result = ExecuteDemoPDF(instruction, savePath, key, pdfFiles);

// Execute PDF document AI processing
static AIResult ExecuteDemoPDF(string instruction, string savePath, string key, string[] attachments)
{
    // Create an AIOptions configuration object
    AIOptions options = new AIOptions();
    options.SpireToken = key;  // Set SpireToken Key

    // Process the PDF document with a PdfDocument object
    using (PdfDocument pdf = new PdfDocument())
    {
        // Create the AI document processor; attachments are the invoice PDFs
        AIDocumentProcessor processor = pdf.AI(options);
        return processor.ExecuteInstruction(pdf, instruction, savePath, attachments);
    }
}

Original invoice PDF Original invoice PDF Extracted and exported Excel Extracted and exported Excel


FAQ

The extracted amount or tax amount is incorrect

Reason: The invoice amount has both uppercase and lowercase forms, or the tax-inclusive/tax-exclusive basis is inconsistent.

Solution: Specify the extraction basis clearly in the instruction (e.g., "extract the total amount including tax", "extract the amount excluding tax"); the AI agent will extract according to the specified basis. If the invoice has two forms of amount, it is also recommended to state which one takes precedence to avoid ambiguity.

How are invoices with different layouts recognized?

Reason: Invoices from different suppliers have different layouts and field positions.

Solution: The AI agent can automatically understand the invoice layout and locate fields; for unusual layouts, you can add field hints in the instruction (e.g., "the invoice number is located in the upper-right corner") to help the agent locate more accurately.

The column order / field names of the result don't match expectations

Reason: By default the AI outputs fields in the order it recognizes them.

Solution: Specify the field names and order clearly in the instruction (e.g., "export in the order: invoice number, date, amount, tax amount, buyer"), and the agent will arrange the output columns as requested.


Getting a SpireToken Key

Configure it in code:

AIOptions options = new AIOptions();
options.SpireToken = key;

In daily office work, data often needs to be exchanged between Excel spreadsheets and OpenDocument spreadsheets (ODS). ODS is an open-standard spreadsheet format widely used in open-source office software such as LibreOffice and OpenOffice. Spire.XLS for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server is required. It provides simple, easy-to-use APIs that make format conversion more convenient.

With Spire.XLS for JavaScript, you can save an Excel workbook as ODS format to work seamlessly with open-source office software, or import an ODS file to create a fully formatted Excel workbook. This makes data migration between different applications more convenient and efficient.

This article covers two core features:

For installation and project setup, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.


Convert Excel Workbook to ODS File

Exporting Excel data as ODS format makes it easy to open and edit directly in open-source office software such as LibreOffice and OpenOffice. With Spire.XLS for JavaScript, you can save an entire workbook as an ODS file, preserving table structure, styles, and data while enabling cross-platform data sharing. The steps are as follows:

  • Create a Workbook object and load an existing Excel file.
  • Call the workbook's SaveToFile() method, specifying the output filename and the FileFormat.ODS file format.
  • Dispose of the workbook resources, read the result file from VFS, and trigger the download.

Below is a complete code example demonstrating how to convert Excel to ODS in React:

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

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

    // Load the font file to ensure proper text rendering
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}font/`);

    // Load the sample Excel file into VFS
    await window.spire.FetchFileToVFS('Sample.xlsx', '', `${process.env.PUBLIC_URL}data/`);

    // Create a workbook object and load the Excel file
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: 'Sample.xlsx' });

    // Save the workbook as an ODS file
    const outputFileName = 'ExcelToODS.ods';
    workbook.SaveToFile({ fileName: outputFileName, fileFormat: xlsModule.FileFormat.ODS });
    workbook.Dispose();

    // Read the file from VFS and trigger download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.oasis.opendocument.spreadsheet' });
    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>Convert Excel to ODS</h1>
      <button onClick={convertToODS}>
        Generate
      </button>
    </div>
  );
}

export default App;

Excel converted to ODS with Spire.XLS for JavaScript

Excel converted to ODS with Spire.XLS for JavaScript


Convert ODS File to Excel Workbook

Importing an ODS file into an Excel spreadsheet allows you to take full advantage of Excel's powerful formatting, calculation, and charting capabilities. Spire.XLS for JavaScript supports loading an ODS file directly via the LoadFromFile() method, which automatically detects its file format, and then you can save the workbook as an Excel file. The steps are as follows:

  • Load the font file and ODS sample file into the VFS.
  • Create a Workbook object and load the ODS file via the LoadFromFile() method.
  • Save the workbook as an Excel file and trigger the download.

Below is a complete code example demonstrating how to convert ODS to Excel in React:

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

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

    // Load the font file to ensure proper text rendering
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}font/`);

    // Load the ODS sample file into VFS
    await window.spire.FetchFileToVFS('Sample.ods', '', `${process.env.PUBLIC_URL}data/`);

    // Create a workbook object and load the ODS file
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: 'Sample.ods' });

    // Save the workbook and release resources
    const outputFileName = 'ODSToExcel.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
    workbook.Dispose();

    // Read the file from VFS and trigger 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>Convert ODS to Excel</h1>
      <button onClick={convertToExcel}>
        Generate
      </button>
    </div>
  );
}

export default App;

ODS converted to Excel with Spire.XLS for JavaScript

ODS converted to Excel with Spire.XLS for JavaScript


FAQ

Why can't the generated ODS file be opened properly?

Cause: When saving the workbook with the SaveToFile() method, if the correct output file format is not specified via the fileFormat parameter, the generated file format may not match the extension, causing it to fail to open.

Solution: Specify the specific file format enum value xlsModule.FileFormat.ODS when saving as ODS:

const outputFileName = 'ExcelToODS.ods';
workbook.SaveToFile({ fileName: outputFileName, fileFormat: xlsModule.FileFormat.ODS });

How to handle the downloaded ODS file being opened as another type or unrecognized?

Cause: The MIME type is not set correctly when creating the Blob, so the browser cannot recognize the downloaded file as an ODS document, which may cause it to open as another type or display garbled text.

Solution: Specify the correct MIME type when downloading and make sure the download filename ends with .ods:

const blob = new Blob([fileArray], { type: 'application/vnd.oasis.opendocument.spreadsheet' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'ExcelToODS.ods';
a.click();

Get a Free License

Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.

In corporate legal and compliance management scenarios, contract review is one of the most time-consuming and error-prone tasks. Every contract involves a large number of rights and obligations clauses — liquidated damages, payment terms, disclaimer clauses, breach liability, dispute resolution, and more. Any clause that is unfavorable to your side or ambiguously worded may lead to legal disputes or financial losses in the future. Traditional approaches rely on legal professionals reading and annotating each clause manually; a single contract of dozens of pages often takes hours, and review standards vary from person to person.

Comparison with Traditional SDK API Processing

Traditional Spire.Office for .NET API Spire.Agent.Office
Driving approach Write code to parse clauses one by one: load document → iterate paragraphs → regex match keywords → judge risk → highlight and annotate; every step requires code control Describe the review goal in natural language, and AI automatically identifies and annotates risk clauses
Code volume Requires a large amount of code to maintain the clause risk rule library, keyword matching, and annotation logic Only configuration code + 1 natural language instruction
Risk rules Risk judgment relies on hard-coded keywords; new risk types require code changes AI understands clauses semantically and can identify new risks not covered by the rules
Review stance Review logic for each contract type must be developed separately A single phrase like "review from our side" in the instruction switches the review stance
Maintainability The risk rule library requires continuous manual maintenance Review scope and rules can be adjusted at any time in natural language

This article explains how to use the Word AI capability of Spire.Agent.Office to review contract clauses and annotate risks. You can choose to highlight risk clauses on the original contract and add comments, or batch review and output a structured risk review report, meeting contract review needs of different scales and scenarios.

For product installation and SpireToken configuration, refer to Integrating Spire.Agent.Office in a .NET Project. The examples below assume Spire.Agent.Office is installed and SpireToken is configured.


Risk Clause Highlighting and Annotation

Risk clause highlighting and annotation suits in-depth review of important contracts. The core idea is: let AI review contract clauses one by one, identify clauses that are unfavorable to your side or carry legal risks, highlight them in yellow in place and add comments, so legal professionals can view the risk points directly on the contract.

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

// Path of the contract file to be reviewed
string inputPath = "E:\\Input\\Software_Contract.docx";
// Save path
string savePath = "E:\\Output\\Review.docx";
// Output directory
string OutDir = "E:\\Output";
// SpireToken Key
string key = "xxxxx";
// Natural language instruction
string instruction =
    "Review all clauses in the current contract document and identify clauses that are unfavorable to the purchaser or carry legal risks, including but not limited to: " +
    "excessively high liquidated damages, stringent payment terms, overly broad disclaimer clauses, missing breach liability provisions, unfavorable court jurisdiction agreements, unclear intellectual property ownership, etc. " +
    "For each risk clause, perform the following operations: 1. Highlight the risk clause text in yellow; 2. Add a comment in place, noting the risk point, risk level (high/medium/low), and modification suggestions. " +
    "After processing, keep the same layout, styles, and fonts as the original document, and finally save and output in DOCX format";

// Call the Word document processing function
AIResult result = ExecuteDemoWord(instruction, inputPath, savePath, key, OutDir, null);

// Execute Word document AI processing
static AIResult ExecuteDemoWord(string instruction, string inputPath, string savePath, string key, string output, string[] attachmentPaths)
{
    // Create an AIOptions configuration object
    AIOptions options = new AIOptions();
    // Set the working directory to the output directory
    options.WorkDir = output;
    // Set the SpireToken Key
    options.SpireToken = key;

    // Use the Document object to process the Word document
    using (Document doc = new Document())
    {
        // Load the contract document from file
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            doc.LoadFromFile(inputPath);
        }
        // Create the AI document processor
        AIDocumentProcessor processor = doc.AI(options);

        // Execute the AI instruction
        return processor.ExecuteInstruction(doc, instruction, savePath, attachmentPaths);
    }
}

Contract after AI highlighting and annotation Contract with highlighted annotations

In the reviewed contract, risk clauses are highlighted in yellow, and the comments clearly state the risk points and modification suggestions. Legal professionals can quickly locate the highlighted positions without reading the original text line by line, and can directly discuss modification plans with the business side based on the comments.


Batch Review and Review Report

For quick screening of large batches of contracts (such as contract renewal or supplier qualification review), batch review with a structured review report is more suitable. The core idea is: let AI review multiple contracts one by one, consolidate the risk clauses of each contract into a risk list, and output it as an MD report for statistics, tracking, and tiered processing.

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

// Paths of multiple contract files to be reviewed
string[] attachments = new string[] {
    "E:\\Input\\Purchase_Contract_EN.docx",   // Purchase contract
    "E:\\Input\\Sales_Contract_EN.docx",   // Sales contract
    "E:\\Input\\Labor_Contract_EN.docx"    // Labor contract
};
// Save path (null here; the output folder path set below will be used)
string savePath = "E:\\Output\\Structural_Review_Output.md";
// Output directory
string OutDir = "E:\\Output";
// SpireToken Key
string key = "xxxxx";
// Natural language instruction
string instruction =
    "Review the contract documents in the attachments one by one, extract risk clauses, and output a Markdown review report: " +
    "The report contains a table with fixed columns: Contract Name | Clause Number | Clause Original Text | Risk Level (High/Medium/Low) | Risk Type | Risk Description | Modification Suggestion. " +
    "Sort by risk level from high to low; the clause original text must be quoted from the contract, truncated with … after 20 characters, and must not be fabricated.";

// Call the Word document processing function
AIResult result = ExecuteDemoWord(instruction, savePath, key, OutDir, attachments);

// Execute Word document AI processing
static AIResult ExecuteDemoWord(string instruction, string savePath, string key, string output, string[] attachments)
{
    // Create an AIOptions configuration object
    AIOptions options = new AIOptions();
    // Set the working directory to the output directory
    options.WorkDir = output;
    // Set the SpireToken Key
    options.SpireToken = key;

    // Use the Document object to process the Word document
    using (Document doc = new Document())
    {
        // Create the AI document processor
        AIDocumentProcessor processor = doc.AI(options);

        // Execute the AI instruction
        return processor.ExecuteInstruction(doc, instruction, savePath, attachments);
    }
}

Contract risk review report output by AI Contract risk review report

Each row in the review report corresponds to a risk clause and contains the clause original text, risk level, risk type, and modification suggestion. Legal professionals can sort by risk level to prioritize high-risk clauses, or export the report for risk ledger tracking in a contract management system.


FAQ

Risk clauses identified inaccurately

Reason: AI's judgment of "unfavorable clauses" depends on the review stance. From your side's perspective versus the counterparty's perspective, the risk judgment for the same clause may be completely opposite.

Solution: Specify the review stance clearly in the instruction, such as "review from the purchaser's perspective", and add a list of risk types to focus on. AI will strictly follow this stance and scope.

Document style changes after highlighting

Reason: The AI model automatically modified or added content during processing.

Solution: Add a description such as "keep the same layout, styles, and fonts as the original document" to the instruction.

Review report does not accurately correspond to contract clauses

Reason: Clause numbers are inconsistent, or the same clause is scattered across multiple places in the contract, causing the clause original text in the report to not match the contract.

Solution: In the instruction, require AI to quote the clause original text and note the source of the clause number, for easy manual verification and location.


Get the SpireToken Key

Configure it in your code:

AIOptions options = new AIOptions();
options.SpireToken = key;
Page 6 of 348
page 6