ZhuLinsen/daily_stock_analysis · error · ValueError
仅支持 .xlsx 格式,请将 .xls 另存为 .xlsx 后重试
Error message
仅支持 .xlsx 格式,请将 .xls 另存为 .xlsx 后重试
What it means
Hard rejection in parse_import_from_bytes for files with .xls extension: the parser supports only .xlsx (openpyxl reads zip-based OOXML), not the legacy binary .xls (OLE2/BIFF) format.
Source
Thrown at src/services/import_parser.py:179
first_row = [str(x).strip().lower() for x in df.iloc[0].tolist()]
if any(c in _CODE_ALIASES or c in _NAME_ALIASES for c in first_row):
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
return _parse_dataframe(df)
except Exception as e:
# If bytes strongly indicate xlsx container, treat as real Excel parse failure.
if looks_like_zip:
hint = (
"请确认:(1) 文件为 .xlsx 格式;(2) 工作表不为空;(3) 文件未损坏。"
"若为 .xls 格式,请另存为 .xlsx 后重试。"
)
raise ValueError(f"Excel 解析失败: {e}。{hint}") from e
# For extension-only mismatch (e.g. csv named .xlsx), fallback to text parsing.
logger.warning(f"扩展名为 .xlsx 但未解析为 Excel,将回退文本解析: {e}")
# .xls not supported
if ext == ".xls":
raise ValueError("仅支持 .xlsx 格式,请将 .xls 另存为 .xlsx 后重试")
# CSV / text
for encoding in ("utf-8", "gbk"):
try:
text = data.decode(encoding)
break
except UnicodeDecodeError:
continue
else:
raise ValueError("无法识别文件编码,请使用 UTF-8 或 GBK")
# Single-column (one value per line): bypass pandas to avoid sep=None inference issues
# e.g. "00700\n600519" or "code\n00700" - pandas with sep=None can produce wrong results
lines = [ln.strip() for ln in text.strip().splitlines() if ln.strip()]
if _should_use_single_column_fast_path(lines):
rows = [[ln] for ln in lines]
df = pd.DataFrame(rows)
first_row = [str(x).strip().lower() for x in df.iloc[0].tolist()]View on GitHub (pinned to 5159bd72e8)
Solutions
- Open the .xls in Excel/WPS and 'Save As' -> .xlsx, then re-upload
- Or copy the data into a CSV and upload that
- If automating, convert with LibreOffice headless: soffice --headless --convert-to xlsx file.xls
Example fix
$ soffice --headless --convert-to xlsx portfolio.xls # then upload portfolio.xlsx
Defensive patterns
Strategy: validation
Validate before calling
if filename and filename.rsplit('.',1)[-1].lower() == 'xls':
prompt_user('检测到 .xls,请另存为 .xlsx 或导出 CSV 后重试') Type guard
def is_xls(filename: str) -> bool:
return (filename or '').rsplit('.', 1)[-1].lower() == 'xls' Prevention
- Filter the file picker to .xlsx and .csv only
- Convert legacy .xls exports at the source (Excel/LibreOffice) before import
When it happens
Trigger: Uploading a file named *.xls (legacy Excel 97-2003 format, or any file given that extension).
Common situations: Old broker exports still shipped as .xls; user renames .xls to .xlsx (which then takes the zip-magic fallback path, not this one); corporate templates in legacy format.
Related errors
- Excel 解析失败: {e}。请确认:(1) 文件为 .xlsx 格式;(2) 工作表不为空;(3) 文件未损坏。若为
- invalid_import_file
- 未安装 Futu OpenAPI SDK;请先执行 `pip install "futu-api==10.8.6808"
- 加载 Futu OpenAPI SDK 失败: {exc}
- 请安装 schedule 库: pip install schedule
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/03e4facb6ddb6459.
Report an issue: GitHub.