grate

repository·main·Indexed 41 days ago

https://github.com/pbnjay/grate

A Go-native package for high-speed, stable extraction of tabular data from Excel (.xls, .xlsx) and delimited text (.csv, .tsv) files. It provides a unified interface for accessing data via Source and Collection interfaces, prioritizing performance and low memory allocation. Includes CLI tools like grater for printing data to stdout and grate2tsv for parallel conversion to TSV files.

Tokens
3.2K
Snippets
14
Records
14
Agent score
100%

What's inside grate

  1. Iterate through rows in a sheet using grate

    main

    Once a sheet is opened via wb.Get(name), you can iterate through its rows using a Next() method. For each row, you can retrieve the cell contents as a slice of strings using Strings().

    Always ensure you call wb.Close() when finished to release resources.

    sheet, _ := wb.Get(s)        // open the sheet
    for sheet.Next() {           // enumerate each row of data
        row := sheet.Strings()   // get the row's content as []string
        fmt.Println(row)
    }
    wb.Close()
  2. Use grate to extract tabular data from files

    main

    Grate is a Go-native package for extracting tabular data from .xls, .xlsx, .csv, and .tsv files. It provides a unified interface for accessing data, whether it is a single table in a plaintext file or multiple worksheets in a spreadsheet.

    To use grate, you must import the core package and the specific driver packages for the file formats you intend to support using blank imports (_).

    Supported formats and their drivers:

    • .xls: github.com/pbnjay/grate/xls
    • .xlsx: github.com/pbnjay/grate/xlsx
    • .csv and .tsv: github.com/pbnjay/grate/simple
    package main
    
    import (
        "fmt"
        "os"
        "strings"
    
        "github.com/pbnjay/grate"
        _ "github.com/pbnjay/grate/simple" // tsv and csv support
        _ "github.com/pbnjay/grate/xls"
        _ "github.com/pbnjay/grate/xlsx"
    )
    
    func main() {
        wb, _ := grate.Open(os.Args[1])  // open the file
        sheets, _ := wb.List()           // list available sheets
        for _, s := range sheets {       // enumerate each sheet name
            sheet, _ := wb.Get(s)        // open the sheet
            for sheet.Next() {           // enumerate each row of data
                row := sheet.Strings()   // get the row's content as []string
                fmt.Println(strings.Join(row, "\t"))
            }
        }
        wb.Close()
    }
  3. Use the grate2tsv CLI to convert files to TSV

    main

    The grate2tsv command is a highly parallel tool designed to extract tabular data from various file formats (including Excel and simple formats) and save them as .tsv files.

    Output Behavior:

    • Extracted files are saved into a results/ subdirectory. To maintain filesystem responsiveness, files are organized into a hierarchical structure based on the MD5 hash of the filename (e.g., results/ab/cd/filename.tsv).
    • A summary log of the process (stats, errors, and row/column counts) is written to a file, which defaults to results.txt.
    # Example usage (assuming the binary is compiled)
    ./grate2tsv file1.xlsx file2.xls data/my_spreadsheet.xlsx
  4. Enable debug logging via build flags

    main

    Detailed logging is controlled by the grate.Debug boolean. This is determined at build time based on the loglevel variable. To enable debug logging, include the following flag in your go build command:

    -ldflags="-X github.com/pbnjay/grate.loglevel=debug"

    go build -ldflags="-X github.com/pbnjay/grate.loglevel=debug"
  5. Wrap multiple errors with WrapErr

    main

    Use WrapErr to group multiple errors into a single error value. If only one error is provided, it returns that error directly. If multiple errors are provided, it returns an errx type that implements the standard error interface, allowing for error unwrapping.

    err := grate.WrapErr(err1, err2, err3)
  6. Use the Source interface to access data

    main

    The Source interface is the entry point for interacting with a data file. It allows you to discover and retrieve specific data tables within the file.

    Methods:

    • List() ([]string, error): Returns a list of names for the individual data tables available in the source.
    • Get(name string) (Collection, error): Retrieves a Collection for the specified table name.
    • Close() error: Closes the source and releases associated memory.
    tables, err := source.List()
    // ...
    collection, err := source.Get(tables[0])
    // ...
    defer source.Close()
  7. Unwrap errors from WrapErr

    main

    Errors created via WrapErr can be unwrapped using the standard errors.Unwrap function. The Unwrap implementation for errx returns the second error in the original slice if multiple errors were provided, or nil if only one error was present. This allows for sequential unwrapping of a chain of errors.

    err := grate.WrapErr(err1, err2)
    
    // errors.Unwrap(err) will return err2
    nextErr := errors.Unwrap(err)
    
    // errors.Unwrap(nextErr) will return nil
  8. Iterate through records using the Collection interface

    main

    A Collection represents an iterable set of records from a specific table. To access data, you must first call Next() to advance to the first record, then loop through the collection.

    Iteration Pattern:

    1. Call Next() to advance to the first record.
    2. Use Scan() or other extraction methods to read the current record.
    3. Call Next() again to move to the subsequent record.

    Extraction Methods:

    • Next() bool: Advances to the next record. Returns false when no more records are available.
    • Scan(args ...interface{}) error: Extracts values into provided pointers. Supported types are bool, int64, float64, string, and time.Time. Returns ErrInvalidScanType if an unsupported type is passed.
    • Strings() []string: Returns the current record's values as a slice of strings.
    • Types() []string: Returns the data types of the current record. Supported types include boolean, integer, float, string, date, blank, and hyperlink.
    • Formats() []string: Returns the format codes for the current record.
    • IsEmpty() bool: Returns true if the current record contains no data values.
    • Err() error: Returns the last error encountered during processing.
    collection, err := source.Get("Sheet1")
    if err != nil {
    	// handle error
    }
    
    for collection.Next() {
    	var val string
    	var num float64
    	if err := collection.Scan(&val, &num); err != nil {
    		// handle error
    	}
    	fmt.Println(val, num)
    }
    
    if err := collection.Err(); err != nil {
    	// handle error from collection
    }
  9. Open a tabular data file with Open()

    main

    Use Open(filename string) to open a tabular data file (like a spreadsheet or delimited text file). It returns a Source interface that provides access to the file's contents. The function iterates through registered format handlers and returns the first one that successfully opens the file. If no handler recognizes the file format, it returns ErrUnknownFormat.

    source, err := grate.Open("data.csv")
    if err != nil {
    	// handle error
    }
    defer source.Close()
  10. Register a new data format with Register()

    main

    You can extend grate by registering new format handlers. Use Register(name string, priority int, opener OpenFunc) to add a new implementation.

    • name: A string identifier for the format.
    • priority: An integer determining the order in which Open() attempts to use this handler. Lower numbers have higher priority.
    • opener: An OpenFunc which is a function with the signature func(filename string) (Source, error).

    Note: The opener function should return ErrNotInFormat immediately if the filename does not match the expected file type. This allows Open() to gracefully skip to the next registered handler.

    err := grate.Register("myformat", 10, func(filename string) (grate.Source, error) {
    	// implementation logic
    	// return ErrNotInFormat if not the right file type
    	return mySource, nil
    })
  11. Reference: grate error variables

    main

    The following sentinel errors are exported by the grate package for error checking and comparison:

    var (
    	// ErrInvalidScanType is returned by Scan for invalid arguments.
    	ErrInvalidScanType = errors.New("grate: Scan only supports *bool, *int, *float64, *string, *time.Time arguments")
    
    	// ErrNotInFormat is used to auto-detect file types using the defined OpenFunc.
    	// It is returned by OpenFunc when the code does not detect correct file formats.
    	ErrNotInFormat = errors.New("grate: file is not in this format")
    
    	// ErrUnknownFormat is used when grate does not know how to open a file format.
    	ErrUnknownFormat = errors.New("grate: file format is not known/supported")
    )
  12. Reference the grate2tsv CLI flags

    main

    The following flags are available to control the behavior of the grate2tsv extraction process:

    # Available flags:
    -l filename.txt    save processing logs to `filename.txt`
    -p                 pretend to output .tsv (dry run)
    -i results.txt     `filename` to record stats about the process (default: results.txt)
    -r                 remove embedded tabs, newlines, and condense spaces in cell contents (default: true)
    -w                 trim whitespace from cell contents (default: true)
    -b                 discard blank rows from the output (default: true)
    --cpuprofile file  write cpu profile to file
    --memprofile file  write memory profile to file