Test files › Office documents › legacy-workbook.xls

Sample XLS file (legacy workbook)

A real legacy Excel 97-2003 workbook: BIFF8 records inside an OLE2 compound file, with two sheets, numbers, and text held in a shared string table.

↓ Download legacy-workbook.xls
Filenamelegacy-workbook.xls
FormatXLS
Size3.5 KB (3,584 bytes)
MIME typeapplication/vnd.ms-excel
SHA-256e4ddabb0ba6f10493b909d5f3be09e70c94f622d6b97c9d12664c6527f33294e
What this file catchesCode that treats .xls and .xlsx as the same thing. They share nothing structurally - .xlsx is a ZIP of XML starting with PK, .xls is an OLE2 compound document starting with D0 CF 11 E0, and a reader for one cannot open the other. Also catches importers that only accept the modern format, and signature checks that map the OLE2 magic to Word. Opens in Excel, LibreOffice, xlrd and pandas.

Handle it in code

Each snippet below was run against this exact file with Python 3.14.4 and Node 24.15.0 when this page was built, and the output shown is what it printed.

Python

Check for macros before accepting or opening an Office upload. Modern files are ZIPs: VBA lives in vbaProject.bin (Microsoft) or a Basic folder (OpenDocument). Legacy .xls/.doc files are OLE2 containers that need a dedicated parser, such as oletools, to see inside.

import zipfile

OLE2 = bytes.fromhex("d0cf11e0a1b11ae1")

with open("legacy-workbook.xls", "rb") as f:
    magic = f.read(8)
if magic == OLE2:
    print("legacy OLE2 file (.xls, .doc, .ppt, .msg): may carry VBA; inspect it with an OLE parser")
elif not zipfile.is_zipfile("legacy-workbook.xls"):
    print("not an Office file")
else:
    with zipfile.ZipFile("legacy-workbook.xls") as z:
        names = z.namelist()
        types = z.read("[Content_Types].xml").decode() if "[Content_Types].xml" in names else ""
    macros = [n for n in names if n.lower().endswith("vbaproject.bin") or n.startswith(("Basic/", "Scripts/"))]
    if macros or "macroEnabled" in types:
        print("contains macros:", ", ".join(macros) or "declared in [Content_Types].xml")
    else:
        print(f"no macro parts among {len(names)} entries")

Run against this file, it prints: legacy OLE2 file (.xls, .doc, .ppt, .msg): may carry VBA; inspect it with an OLE parser

Related guides and tools

Sample XLS and XLSX (Excel) filesFile signaturesMIME typesCheck a file's real typeVerify its SHA-256

Download & verify

curl -fsSL -o "legacy-workbook.xls" "https://files.hexaqa.com/office/legacy-workbook.xls"
curl -fsSL "https://files.hexaqa.com/office/legacy-workbook.xls" | sha256sum # expect: e4ddabb0ba6f10493b909d5f3be09e70c94f622d6b97c9d12664c6527f33294e

More office documents test files

corrupt-missing-content-types.docxdocument.docxdocument.odtformula-injection.xlsxmacro-enabled.xlsmpresentation.odppresentation.pptxspreadsheet.ods

← All Office documents files