File size: 2,731 Bytes
0017280
 
 
 
f95cdb7
 
 
 
 
 
 
 
 
0017280
 
 
 
9093d8f
 
 
 
 
 
 
 
 
 
 
0017280
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9093d8f
 
0017280
 
 
 
fbd18c8
 
 
0017280
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""Reader for Excel files: .xlsx and .xls"""
MAX_CHUNK_CHARS = 6000

def read_excel(file_path: str) -> list[dict]:
    try:
        from pathlib import Path
        ext = Path(file_path).suffix.lower()
        if ext == ".xls":
            return _read_xls(file_path)
        return _read_xlsx(file_path)
    except Exception as e:
        print(f"Warning: Could not read {file_path}: {e}")
        return []

def _read_xlsx(file_path: str) -> list[dict]:
    import openpyxl
    wb = openpyxl.load_workbook(file_path, read_only=True, data_only=True)
    try:
        pages = []
        for sheet_name in wb.sheetnames:
            ws = wb[sheet_name]
            rows = list(ws.iter_rows(values_only=True))
            if not rows:
                continue
            pages.extend(_rows_to_pages(rows, sheet_name))
        return pages
    finally:
        wb.close()

def _read_xls(file_path: str) -> list[dict]:
    import xlrd
    wb = xlrd.open_workbook(file_path)
    pages = []
    for sheet_idx in range(wb.nsheets):
        ws = wb.sheet_by_index(sheet_idx)
        if ws.nrows == 0:
            continue
        rows = []
        for r in range(ws.nrows):
            rows.append(tuple(ws.cell_value(r, c) for c in range(ws.ncols)))
        pages.extend(_rows_to_pages(rows, ws.name))
    return pages

def _rows_to_pages(rows: list[tuple], sheet_name: str) -> list[dict]:
    if not rows:
        return []
    headers = [str(h) if h is not None else "" for h in rows[0]]
    row_texts = []
    for row in rows[1:]:
        parts = []
        padded_row = list(row) + [None] * max(0, len(headers) - len(row))
        for header, val in zip(headers, padded_row[:len(headers)]):
            if val is not None and str(val).strip() and str(val).lower() not in ("nan", "nat", "<na>", "inf", "-inf"):
                parts.append(f"{header}: {val}")
        if parts:
            row_texts.append("; ".join(parts))

    header_line = f"Sheet: {sheet_name} | Columns: {', '.join(headers)}\n"
    pages = []
    block = []
    block_chars = len(header_line)
    block_start = 1

    for idx, row_text in enumerate(row_texts):
        if block and block_chars + len(row_text) + 1 > MAX_CHUNK_CHARS:
            text = header_line + "\n".join(block)
            pages.append({"page": f"{sheet_name}_rows_{block_start}-{block_start + len(block) - 1}", "text": text})
            block = []
            block_chars = len(header_line)
            block_start = idx + 1
        block.append(row_text)
        block_chars += len(row_text) + 1

    if block:
        text = header_line + "\n".join(block)
        pages.append({"page": f"{sheet_name}_rows_{block_start}-{block_start + len(block) - 1}", "text": text})
    return pages