Skip to content

[Feature] - Support excel to markdown #997

Description

@shps951023

Feature Summary

Add one simple streaming operation that converts Excel worksheets to Markdown:

await MiniExcel.ConvertXlsxToMarkdownAsync(
    xlsxStream,
    markdownStream,
    MarkdownFormat.LlmFriendly,
    cancellationToken: cancellationToken);

The same operation may provide path and Stream overloads, consistent with the existing converter APIs. It should support two output formats:

  • MarkdownFormat.Simple: a compact GitHub-Flavored Markdown table for people and general-purpose tools.
  • MarkdownFormat.LlmFriendly: chunked Markdown with worksheet, range, row, and cell-address context so an LLM or RAG pipeline can retrieve and cite the source more reliably.

Document Formats

  • XLSX
  • XLSM
  • CSV
  • Other

CSV is not required in the first version because it can already be processed as tabular text and does not contain workbook or worksheet metadata.

Motivation

Users currently need to query rows and build Markdown themselves. A built-in converter would provide consistent escaping and formatting while preserving MiniExcel's low-memory behavior.

The main use cases are:

  • Previewing or publishing worksheet data as Markdown.
  • Preparing large spreadsheets for LLM and RAG ingestion.
  • Writing directly to a file or response stream without creating a workbook-sized collection or string in memory.

Proposed Solution

Introduce one conversion operation, with path and stream overloads if appropriate:

Task ConvertXlsxToMarkdownAsync(
    Stream xlsxStream,
    Stream markdownStream,
    MarkdownFormat format = MarkdownFormat.Simple,
    bool hasHeader = true,
    string? sheetName = null,
    CancellationToken cancellationToken = default);

Simple Markdown

Produce a normal GFM table with an optional header row:

| Name | Amount |
| --- | ---: |
| Alice | 120 |
| Bob | 95 |

LLM-friendly Markdown

Produce independently understandable chunks. Each chunk should include enough context to identify its source, for example:

# sales.xlsx
## Worksheet: Orders
<!-- miniexcel:chunk range="A1:C100" -->

| Row | A: OrderId | B: Customer | C: Amount |
| ---: | --- | --- | ---: |
| 2 | SO-001 | Alice | 120 |

The exact syntax can be finalized during implementation, but it should be deterministic and include:

  • Source and worksheet identity.
  • One-based row numbers and A1 column/cell context.
  • Explicit chunk/range boundaries.
  • Repeated header context for each chunk.
  • Formula text and cached values when they are available through the reader.

Streaming Requirements

  • Read rows and write UTF-8 Markdown incrementally.
  • Do not materialize the complete worksheet or complete Markdown output.
  • Keep memory bounded by parser state, shared workbook metadata, and one configured chunk or row.
  • Escape pipes, line breaks, Markdown control characters, and raw HTML safely.
  • Preserve worksheet order and Excel's one-based coordinate semantics.
  • Honor cancellation and propagate malformed workbook or output I/O errors.

Acceptance Criteria

  • A single conversion operation supports Simple and LlmFriendly formats.
  • Path and/or Stream input can write incrementally to a destination Stream.
  • XLSX and XLSM are supported.
  • Large worksheets do not require workbook-sized row or Markdown buffers.
  • Pipes, multiline values, empty cells, Unicode, formulas, and multiple worksheets have focused tests.
  • LLM-friendly chunks contain deterministic source, worksheet, range, and row/address context.
  • Cancellation and invalid input produce clear errors.
  • Public API usage and both output formats are documented.

Alternatives Considered

  • Returning one Markdown string: simpler, but duplicates the entire output in memory and does not satisfy streaming requirements.
  • Exposing only row enumeration: already possible, but every caller must implement escaping, chunking, and provenance differently.
  • Providing only one Markdown layout: compact human-readable tables and retrieval-oriented LLM chunks have different requirements.

Additional Context

The Rust implementation provides a useful reference for bounded-memory, chunked Markdown and explicit source provenance: Streaming Markdown and anydoc comparison.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions