package main import ( "fmt" "strings" xls "github.com/extrame/xls" ) func safeXlsRow(sheet *xls.WorkSheet, r int) (row *xls.Row) { defer func() { recover() }() return sheet.Row(r) } func main() { wb, err := xls.Open("/Users/wangjia/.claude/jobs/4f07558d/tmp/test_150rows.xls", "utf-8") if err != nil { fmt.Println("open error:", err) return } sheet := wb.GetSheet(0) if sheet == nil { fmt.Println("no sheet") return } fmt.Printf("MaxRow: %d\n", sheet.MaxRow) numCols := 0 headerRow := sheet.Row(0) fmt.Printf("Header LastCol: %d\n", headerRow.LastCol()) for c := 0; c < headerRow.LastCol(); c++ { v := strings.TrimSpace(headerRow.Col(c)) if v != "" { numCols = c + 1 } } if numCols == 0 { numCols = 20 } fmt.Printf("numCols: %d\n", numCols) const maxRows = 100000 const maxEmpty = 5 emptyStreak := 0 rowCount := 0 for r := 0; r < maxRows; r++ { row := safeXlsRow(sheet, r) cells := make([]string, numCols) isEmpty := true if row != nil { for c := 0; c < numCols; c++ { cells[c] = strings.TrimSpace(row.Col(c)) if cells[c] != "" { isEmpty = false } } } if isEmpty { emptyStreak++ if emptyStreak >= maxEmpty { fmt.Printf("Breaking at r=%d after %d empty streak\n", r, emptyStreak) break } rowCount++ continue } emptyStreak = 0 rowCount++ } fmt.Printf("Total rows read: %d\n", rowCount) }