Command-line tool die oude Microsoft Excel .xls bestanden omzet naar nette,
semantische HTML5. Gebouwd voor batchverwerking op Linux (Ubuntu, Debian,
Linux Mint en andere gangbare distributies).
- Zet elk werkblad om naar een toegankelijke, semantische HTML-tabel
- Ondersteunt tekst, getallen, datums, valuta, percentages, booleans, formules (berekende waarde) en samengevoegde cellen
- Verwerkt één bestand, meerdere bestanden of hele mappen (recursief)
- Genereert een modern, responsive stylesheet met licht/donker thema
- Faalt nooit hard: elke fout wordt netjes gemeld, nooit een Python-traceback
- Rijke terminal-uitvoer via Rich, met voortgangsbalk via tqdm
Vereist Python 3.12 of nieuwer.
git clone <repository-url> xls2html
cd xls2html
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtAls python3 -m venv mislukt met een foutmelding over ensurepip, installeer
dan eerst het venv-pakket voor jouw distributie:
sudo apt install python3-venv # Ubuntu, Debian, Linux MintGeen virtuele omgeving beschikbaar of gewenst? Installeer dan direct voor de huidige gebruiker:
pip install --user -r requirements.txt| Package | Doel |
|---|---|
xlrd |
Lezen van .xls bestanden (binair BIFF-formaat) |
beautifulsoup4 |
Well-formedness controle van gegenereerde HTML |
rich |
Gekleurde, leesbare terminal-uitvoer |
tqdm |
Voortgangsbalk bij batchverwerking |
jinja2 |
HTML-templates |
argparse, pathlib, logging en dataclasses komen uit de Python
standaardbibliotheek en hoeven niet apart geïnstalleerd te worden.
De tool wordt uitgevoerd met:
python main.py <bestand.xls> [opties]Wie het pakket geïnstalleerd heeft met pip install -e . (zie
Optioneel: het xls2html commando
hieronder) kan in plaats daarvan ook gewoon xls2html typen.
# Eén bestand, output naast het bronbestand (verkoop.html)
python main.py verkoop.xls
# Eigen bestandsnaam of locatie
python main.py verkoop.xls -o rapport.html
python main.py verkoop.xls --output rapport.html
# Meerdere bestanden via shell-glob
python main.py *.xls
# Hele map (niet-recursief: alleen .xls direct in de map)
python main.py documenten/
# Map recursief doorzoeken, inclusief submappen
python main.py --recursive documenten/
# Bestaande output overschrijven zonder te vragen
python main.py verkoop.xls --overwrite
# Uitgebreide logging (geopende bestanden, werkbladen, rijen/kolommen)
python main.py verkoop.xls --verbose
# Alleen foutmeldingen tonen
python main.py verkoop.xls --quiet
# Thema forceren
python main.py verkoop.xls --theme light
python main.py verkoop.xls --theme dark
# Eigen stylesheet gebruiken
python main.py verkoop.xls --css eigen.css
# CSS direct in de HTML embedden (geen los .css bestand)
python main.py verkoop.xls --embed-css
# Elk werkblad naar een eigen HTML-bestand
python main.py verkoop.xls --split-sheets
# Alle werkbladen op één pagina (standaardgedrag, expliciet gemaakt)
python main.py verkoop.xls --single-page
# Verborgen werkbladen overslaan in plaats van meeconverteren
python main.py verkoop.xls --skip-hidden-sheets
# Volledige hulp
python main.py --help--output/-o gedraagt zich afhankelijk van het aantal invoerbestanden:
bij één bestand is het een bestandsnaam (eindigend op .html) of een map;
bij meerdere bestanden wordt het altijd als uitvoermap behandeld.
Eén bestand:
✔ Bestand gevonden
✔ Januari
✔ HTML opgeslagen
Done.
Batchverwerking, met één corrupt bestand ertussen:
Converteren: 100%|██████████████████████████| 4/4 [00:00<00:00, 270bestand/s]
ERROR
Kan bestand niet openen: kapot.xls
Oorzaak: Bestand is corrupt of geen geldig .xls-bestand
3 bestanden verwerkt
1 fout
Groen (✔) is succes, geel is een waarschuwing (bijv. overgeslagen bestand), rood is een fout, blauw is het aantal succesvol verwerkte bestanden in de samenvatting.
Elke pagina is geldige, semantische HTML5: <thead>/<tbody>,
<th scope="col">, een <caption> met bestands- en werkbladnaam, geen
inline styles, geen tabellen voor layout, geen JavaScript. Cel-inhoud wordt
altijd HTML-geëscaped (bescherming tegen HTML-injectie/XSS vanuit
spreadsheet-inhoud).
Standaard krijgt elk uitvoerbestand een style.css ernaast: responsive,
zebra-gestreepte rijen, sticky header, licht/donker thema (volgt
prefers-color-scheme, of forceer met --theme), en een printvriendelijke
variant. Geen frameworks (geen Bootstrap/Tailwind/Bulma/Foundation) — puur
handgeschreven CSS.
- Bestandsnamen afgeleid van werkbladnamen worden gesaneerd tegen directory-traversal en ongeldige tekens
- Bestaande uitvoerbestanden worden nooit overschreven zonder
--overwrite(of, in een interactieve terminal, expliciete bevestiging) - Alle celwaarden worden HTML-geëscaped door Jinja2's autoescaping
Er wordt nooit een Python-traceback aan de eindgebruiker getoond. Elke fout (corrupt bestand, leeg bestand, ontbrekende toegangsrechten, ongeldig pad) resulteert in een duidelijke melding met oorzaak, en de verwerking van de overige bestanden in een batch gaat gewoon door.
Het legacy .xls-formaat (BIFF8) is intrinsiek beperkt tot 65.536 rijen bij
256 kolommen per werkblad — de tool leest en verwerkt elk werkblad rij voor
rij binnen die grens, wat het geheugengebruik ook bij honderden of duizenden
bestanden in een batch laag en voorspelbaar houdt.
pip install -r requirements-dev.txt
pytestDit voert de volledige testsuite uit inclusief dekkingsrapport
(pytest-cov, geconfigureerd in pyproject.toml). De suite dekt: een enkel
bestand, een map met bestanden, meerdere werkbladen, lege cellen, corrupte
bestanden, ontbrekende toegangsrechten en de inhoud van de gegenereerde
HTML-output.
Codekwaliteit controleren met Ruff:
ruff check .De officiële, geteste manier om de tool te draaien is python main.py. Wie
liever het xls2html commando direct typt, kan een editable install doen:
pip install -e .
xls2html verkoop.xlsDit werkt omdat een editable install de broncode (inclusief de templates/
map) op zijn originele plek laat staan. Een niet-editable install
(pip install .) wordt niet ondersteund, omdat het project bewust een platte
modulestructuur heeft (geen Python-package) zoals gespecificeerd.
xls2html/
├── main.py Entry point voor `python main.py`
├── converter.py .xls inlezen naar een datamodel (xlrd)
├── html_writer.py Datamodel renderen naar HTML (Jinja2)
├── cli.py argparse, Rich/tqdm-uitvoer, batchverwerking
├── utils.py Logging, bestandsdetectie, sanering
├── templates/
│ ├── page.html Jinja2-template voor de HTML-pagina
│ └── style.css Standaard stylesheet
├── tests/ pytest-testsuite
├── requirements.txt
├── requirements-dev.txt
├── pyproject.toml
├── README.md
└── LICENSE
ModuleNotFoundError: No module named 'xlrd'
Dependencies zijn niet geïnstalleerd in de Python-omgeving die je gebruikt.
Voer pip install -r requirements.txt opnieuw uit, en controleer met
which python3 / which pip dat je dezelfde omgeving (virtualenv of
systeem-Python) gebruikt voor installeren én draaien.
error: externally-managed-environment bij pip install
Recente Debian/Ubuntu-versies blokkeren systeembrede pip-installaties. Gebruik
een virtuele omgeving (zie Installatie) of voeg --break-system-packages toe
als je bewust buiten een virtualenv wilt installeren.
"Bestand is corrupt of geen geldig .xls-bestand"
Het bestand is geen echt .xls-bestand (BIFF-formaat), is beschadigd, of is
eigenlijk een modern .xlsx-bestand met een verkeerde extensie. xls2html
ondersteunt bewust alleen het legacy .xls-formaat. Open en sla het bestand
opnieuw op als .xls in een spreadsheetprogramma om te controleren of het
leesbaar is.
Uitvoerbestand wordt overgeslagen in plaats van overschreven
Zonder --overwrite vraagt de tool om bevestiging in een interactieve
terminal, en slaat bestaande bestanden over in een niet-interactieve
omgeving (bijv. een cron-job of CI-pijplijn). Voeg --overwrite toe om dit
te voorkomen.
Kolombreedtes uit het originele Excel-bestand zijn niet zichtbaar
De HTML-tabellen gebruiken bewust geen inline style-attributen (zie
Veiligheid/HTML-kwaliteit hierboven), dus originele kolombreedtes worden niet
1-op-1 overgenomen. De browser bepaalt de kolombreedte op basis van de
inhoud; de meegeleverde stylesheet zorgt voor leesbare, responsive tabellen.
Ondersteunt xls2html ook .xlsx-bestanden?
Nee, bewust niet. De opdracht was specifiek gericht op het legacy
.xls-formaat via xlrd (dat sinds versie 2.0 alleen nog .xls
ondersteunt). Voor .xlsx is een ander pakket (zoals openpyxl) nodig.
Wat gebeurt er met formules?
.xls-bestanden bevatten naast de formule ook de laatst berekende waarde.
xls2html toont die berekende waarde — er wordt niet opnieuw gerekend.
Kan ik verborgen werkbladen altijd overslaan?
Ja, met --skip-hidden-sheets. Standaard worden ze wél meegenomen, zodat er
nooit stilzwijgend gegevens verdwijnen.
Waarom geen pandas?
De opdracht vroeg om pandas te vermijden tenzij strikt noodzakelijk. Omdat
xlrd rechtstreeks en met een lage geheugenvoetafdruk gelezen kan worden,
was pandas niet nodig.
Werkt dit op een headless server zonder terminal-kleuren? Ja. Rich en tqdm detecteren automatisch of de uitvoer naar een echte terminal gaat en vallen terug op platte tekst wanneer dat niet zo is (bijv. bij omleiding naar een logbestand).
MIT — zie LICENSE.