diff --git a/pyproject.toml b/pyproject.toml index 9c113ad..bbb1141 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,8 +31,7 @@ dependencies = [ "numpy", "python-pptx", "pandas", - "openpyxl", - "xlrd", + "python-calamine", "pdfminer.six", "puremagic", "pydub", diff --git a/src/markitdown/_markitdown.py b/src/markitdown/_markitdown.py index 50c83b4..ec4f63f 100644 --- a/src/markitdown/_markitdown.py +++ b/src/markitdown/_markitdown.py @@ -715,42 +715,18 @@ def convert(self, local_path, **kwargs) -> Union[None, DocumentConverterResult]: return result -class XlsxConverter(HtmlConverter): +class ExcelConverter(HtmlConverter): """ - Converts XLSX files to Markdown, with each sheet presented as a separate Markdown table. + Converts Excel (XLSX, XLS, XLSM or XLSB) files to Markdown, with each sheet presented as a separate Markdown table. """ def convert(self, local_path, **kwargs) -> Union[None, DocumentConverterResult]: - # Bail if not a XLSX + # Bail if not a XLSX, XLS, XLSM or XLSB extension = kwargs.get("file_extension", "") - if extension.lower() != ".xlsx": + if extension.lower() not in [".xlsx", ".xls", ".xlsb", ".xlsm"]: return None - sheets = pd.read_excel(local_path, sheet_name=None, engine="openpyxl") - md_content = "" - for s in sheets: - md_content += f"## {s}\n" - html_content = sheets[s].to_html(index=False) - md_content += self._convert(html_content).text_content.strip() + "\n\n" - - return DocumentConverterResult( - title=None, - text_content=md_content.strip(), - ) - - -class XlsConverter(HtmlConverter): - """ - Converts XLS files to Markdown, with each sheet presented as a separate Markdown table. - """ - - def convert(self, local_path, **kwargs) -> Union[None, DocumentConverterResult]: - # Bail if not a XLS - extension = kwargs.get("file_extension", "") - if extension.lower() != ".xls": - return None - - sheets = pd.read_excel(local_path, sheet_name=None, engine="xlrd") + sheets = pd.read_excel(local_path, sheet_name=None, engine="calamine") md_content = "" for s in sheets: md_content += f"## {s}\n" @@ -1376,8 +1352,7 @@ def __init__( self.register_page_converter(YouTubeConverter()) self.register_page_converter(BingSerpConverter()) self.register_page_converter(DocxConverter()) - self.register_page_converter(XlsxConverter()) - self.register_page_converter(XlsConverter()) + self.register_page_converter(ExcelConverter()) self.register_page_converter(PptxConverter()) self.register_page_converter(WavConverter()) self.register_page_converter(Mp3Converter()) diff --git a/tests/test_files/test.xlsb b/tests/test_files/test.xlsb new file mode 100644 index 0000000..c002872 Binary files /dev/null and b/tests/test_files/test.xlsb differ diff --git a/tests/test_files/test.xlsm b/tests/test_files/test.xlsm new file mode 100644 index 0000000..01fff3d Binary files /dev/null and b/tests/test_files/test.xlsm differ diff --git a/tests/test_markitdown.py b/tests/test_markitdown.py index 9dc7374..682617a 100644 --- a/tests/test_markitdown.py +++ b/tests/test_markitdown.py @@ -191,11 +191,17 @@ def test_markitdown_local() -> None: result = markitdown.convert(os.path.join(TEST_FILES_DIR, "test.xlsx")) validate_strings(result, XLSX_TEST_STRINGS) + # Test XLSB processing + result = markitdown.convert(os.path.join(TEST_FILES_DIR, "test.xlsb")) + validate_strings(result, XLSX_TEST_STRINGS) + + # Test XLSM processing + result = markitdown.convert(os.path.join(TEST_FILES_DIR, "test.xlsm")) + validate_strings(result, XLSX_TEST_STRINGS) + # Test XLS processing result = markitdown.convert(os.path.join(TEST_FILES_DIR, "test.xls")) - for test_string in XLS_TEST_STRINGS: - text_content = result.text_content.replace("\\", "") - assert test_string in text_content + validate_strings(result, XLSX_TEST_STRINGS) # Test DOCX processing result = markitdown.convert(os.path.join(TEST_FILES_DIR, "test.docx"))