{"record":{"id":"5ade62ec14d5dcf5","repo":"PaddlePaddle/PaddleOCR","slug":"xlsx-conversion-requires-openpyxl-pip-install-pad","errorCode":null,"errorMessage":"XLSX conversion requires openpyxl: pip install paddleocr[doc2md]","messagePattern":"XLSX conversion requires openpyxl: pip install paddleocr\\[doc2md\\]","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"paddleocr/_doc2md/converters/xlsx.py","lineNumber":170,"sourceCode":"    return (int(min_r), int(max_r), int(min_c), int(max_c))\n\n\n@default_registry.register\nclass XlsxConverter(BaseConverter):\n    supported_extensions = [\"xlsx\"]\n    supported_mimetypes = [\n        \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n    ]\n\n    def convert_file(self, file_path: Path, **kwargs) -> ConvertResult:\n        try:\n            import openpyxl\n            from openpyxl.drawing.spreadsheet_drawing import (\n                OneCellAnchor,\n                TwoCellAnchor,\n            )\n        except ImportError:\n            raise RuntimeError(\n                \"XLSX conversion requires openpyxl: pip install paddleocr[doc2md]\"\n            )\n\n        sheet_name: Optional[str] = kwargs.get(\"sheet_name\", None)\n        max_rows: Optional[int] = kwargs.get(\"max_rows\", None)\n        extract_drawings: bool = kwargs.get(\"extract_drawings\", True)\n\n        import zipfile\n\n        # read_only=False is required to access merged_cells\n        wb = openpyxl.load_workbook(str(file_path), read_only=False, data_only=True)\n        sheets_md = []\n        images: dict = {}\n        image_counter = 0\n\n        target_sheets = [sheet_name] if sheet_name else wb.sheetnames\n\n        with zipfile.ZipFile(str(file_path), \"r\") as _zf:","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_doc2md/converters/xlsx.py#L152-L188","documentation":"RuntimeError raised by XlsxConverter.convert_file when the lazy import of openpyxl (including its spreadsheet_drawing anchors) fails. XLSX-to-Markdown conversion requires openpyxl, provided by the doc2md extra.","triggerScenarios":"doc2md_convert('data.xlsx', sheet_name='Sheet1') without openpyxl installed; headless servers where openpyxl was never added.","commonSituations":"Spreadsheet ingestion pipelines deployed from minimal images; local dev worked because openpyxl came from another package (e.g. pandas exports) but CI lacks it.","solutions":["pip install 'paddleocr[doc2md]'","Or: pip install openpyxl","If openpyxl is installed but too old to expose drawing anchors, upgrade it"],"exampleFix":"# before (shell)\npip install paddleocr\n# after\npip install 'paddleocr[doc2md]'","handlingStrategy":"validation","validationCode":"import importlib.util\n\nif importlib.util.find_spec('openpyxl') is None:\n    raise RuntimeError('openpyxl missing: pip install paddleocr[doc2md]')","typeGuard":null,"tryCatchPattern":"try:\n    result = doc2md_convert(path)\nexcept RuntimeError as e:\n    if 'openpyxl' in str(e):\n        fail_with_install_hint(e)\n    raise","preventionTips":["Include paddleocr[doc2md] in deployments handling spreadsheets","Beware: pandas may mask a missing openpyxl locally but not in CI"],"tags":["optional-dependency","doc2md","xlsx","installation"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}