calamine-styles 0.1.0

Fork of calamine with Font, Fill, Border, Alignment, and NumberFormat style parsing for xlsx
Documentation
# Style Reading Support in Calamine

This document describes the style extraction functionality in calamine for reading style information from Excel files.

## Overview

Calamine supports extracting style information from Excel files, including:
- Font properties (name, size, weight, color, etc.)
- Fill properties (background colors, patterns)
- Border properties (style, color, position)
- Alignment properties (horizontal, vertical, text rotation, etc.)
- Protection properties (locked, hidden)

## Data Structures

When reading styles from Excel files, you'll work with these data structures:

### Color
```rust
// Colors are returned when reading style information
// You can check color properties like:
if let Some(color) = font.color {
    let (r, g, b, a) = color.rgba();
    println!("Color RGBA: {}, {}, {}, {}", r, g, b, a);
}
```

### Font
```rust
// Font information extracted from Excel files
if let Some(font) = style.get_font() {
    // Access font properties
    if let Some(name) = &font.name {
        println!("Font name: {}", name);
    }
    if let Some(size) = font.size {
        println!("Font size: {}", size);
    }
    println!("Bold: {}", font.is_bold());
    println!("Italic: {}", font.is_italic());
    if let Some(color) = font.color {
        println!("Font color: {}", color);
    }
}
```

### Fill
```rust
// Fill information extracted from Excel files
if let Some(fill) = style.get_fill() {
    if fill.is_visible() {
        println!("Cell has background fill");
        if let Some(color) = fill.get_color() {
            println!("Fill color: {}", color);
        }
        if let Some(pattern) = fill.pattern {
            println!("Fill pattern: {:?}", pattern);
        }
    }
}
```

### Borders
```rust
// Border information extracted from Excel files
if let Some(borders) = style.get_borders() {
    if borders.has_visible_borders() {
        println!("Cell has borders");
        if borders.left.is_visible() {
            println!("Left border style: {:?}", borders.left.style);
            if let Some(color) = borders.left.color {
                println!("Left border color: {}", color);
            }
        }
        // Similar for right, top, bottom borders
    }
}
```

### Alignment
```rust
// Alignment information extracted from Excel files
if let Some(alignment) = style.get_alignment() {
    if let Some(horizontal) = alignment.horizontal {
        println!("Horizontal alignment: {:?}", horizontal);
    }
    if let Some(vertical) = alignment.vertical {
        println!("Vertical alignment: {:?}", vertical);
    }
    if alignment.wrap_text.unwrap_or(false) {
        println!("Text wrapping enabled");
    }
}
```

## Usage Examples

### Reading Styles from Excel Files

```rust
use calamine::{open_workbook, Reader, Data};

let mut workbook = open_workbook("file.xlsx")?;

if let Ok(range) = workbook.worksheet_range("Sheet1") {
    for (row, col, cell) in range.cells() {
        if let Some(cell_data) = cell {
            if cell_data.has_style() {
                if let Some(style) = cell_data.get_style() {
                    println!("Cell ({}, {}) has style:", row, col);
                    
                    // Access font properties
                    if let Some(font) = style.get_font() {
                        println!("  Font: {}", font.name.as_deref().unwrap_or("Unknown"));
                        println!("  Size: {}", font.size.unwrap_or(0.0));
                        println!("  Bold: {}", font.is_bold());
                        println!("  Italic: {}", font.is_italic());
                        if let Some(color) = font.color {
                            let (r, g, b, _) = color.rgba();
                            println!("  Color: rgb({}, {}, {})", r, g, b);
                        }
                    }
                    
                    // Access fill properties
                    if let Some(fill) = style.get_fill() {
                        if fill.is_visible() {
                            println!("  Has background fill");
                            if let Some(color) = fill.get_color() {
                                let (r, g, b, _) = color.rgba();
                                println!("  Fill color: rgb({}, {}, {})", r, g, b);
                            }
                        }
                    }
                    
                    // Access border properties
                    if let Some(borders) = style.get_borders() {
                        if borders.has_visible_borders() {
                            println!("  Has borders:");
                            if borders.left.is_visible() {
                                println!("    Left: {:?}", borders.left.style);
                            }
                            if borders.right.is_visible() {
                                println!("    Right: {:?}", borders.right.style);
                            }
                            if borders.top.is_visible() {
                                println!("    Top: {:?}", borders.top.style);
                            }
                            if borders.bottom.is_visible() {
                                println!("    Bottom: {:?}", borders.bottom.style);
                            }
                        }
                    }
                    
                    // Access alignment properties
                    if let Some(alignment) = style.get_alignment() {
                        if let Some(horizontal) = alignment.horizontal {
                            println!("  Horizontal alignment: {:?}", horizontal);
                        }
                        if let Some(vertical) = alignment.vertical {
                            println!("  Vertical alignment: {:?}", vertical);
                        }
                        if alignment.wrap_text.unwrap_or(false) {
                            println!("  Text wrapping: enabled");
                        }
                    }
                }
            }
        }
    }
}
```

### Checking for Specific Style Properties

```rust
use calamine::{open_workbook, Reader, FontWeight, HorizontalAlignment};

let mut workbook = open_workbook("file.xlsx")?;

if let Ok(range) = workbook.worksheet_range("Sheet1") {
    for (row, col, cell) in range.cells() {
        if let Some(cell_data) = cell {
            if cell_data.has_style() {
                if let Some(style) = cell_data.get_style() {
                    // Check for bold text
                    if let Some(font) = style.get_font() {
                        if font.is_bold() {
                            println!("Cell ({}, {}) has bold text", row, col);
                        }
                    }
                    
                    // Check for center alignment
                    if let Some(alignment) = style.get_alignment() {
                        if alignment.horizontal == Some(HorizontalAlignment::Center) {
                            println!("Cell ({}, {}) is center-aligned", row, col);
                        }
                    }
                    
                    // Check for background color
                    if let Some(fill) = style.get_fill() {
                        if fill.is_visible() {
                            println!("Cell ({}, {}) has background color", row, col);
                        }
                    }
                }
            }
        }
    }
}
```

### Working with CellData

```rust
use calamine::{CellData, Data};

// When iterating through cells, you get CellData which may contain style information
fn process_cell(cell_data: &CellData) {
    // Check if cell has any style information
    if cell_data.has_style() {
        println!("Cell value: {:?}", cell_data.get_value());
        
        if let Some(style) = cell_data.get_style() {
            if !style.is_empty() {
                println!("Cell has formatting");
                
                // Process style information as shown in previous examples
                if let Some(font) = style.get_font() {
                    if font.is_bold() {
                        println!("Text is bold");
                    }
                }
            }
        }
    }
}
```

## Supported Formats

Style extraction is supported for:
- [x] **XLSX**: Full style support including fonts, fills, borders, and alignment
- [ ] **XLSB**: Basic style support (format-based)
- [ ] **XLS**: Basic style support (format-based)
- [ ] **ODS**: Basic style support (format-based)

## Style Parsing

The style parser extracts information from the Excel styles.xml file, including:

### Font Properties
- Font name
- Font size  
- Font weight (bold/normal)
- Font style (italic/normal)
- Underline style
- Strikethrough
- Font color
- Font family

### Fill Properties
- Fill pattern (solid, patterns, etc.)
- Foreground color
- Background color

### Border Properties
- Border style (thin, medium, thick, etc.)
- Border color
- Border position (left, right, top, bottom, diagonal)

### Alignment Properties
- Horizontal alignment (left, center, right, justify, etc.)
- Vertical alignment (top, center, bottom, justify, etc.)
- Text rotation
- Wrap text
- Indent level
- Shrink to fit

### Protection Properties
- Cell locked
- Cell hidden

## Limitations

1. **Theme Colors**: Theme color support is limited and may not fully match Excel's rendering
2. **Indexed Colors**: Indexed color support is basic
3. **Complex Patterns**: Some complex fill patterns may not be fully supported
4. **Conditional Formatting**: Conditional formatting styles are not extracted

## Future Enhancements

Planned improvements for style reading include:
- Full theme color support
- Conditional formatting style extraction
- Enhanced pattern support
- Better color space handling

## API Reference

### Key Types for Reading Styles

- `Style`: Complete cell style container (read-only)
- `Font`: Font properties (read-only)
- `Fill`: Fill properties (read-only)
- `Borders`: Border properties (read-only)
- `Alignment`: Alignment properties (read-only)
- `Protection`: Protection properties (read-only)
- `Color`: Color representation (read-only)
- `CellData`: Cell value with optional style information

### Key Methods for Reading Styles

- `CellData::get_style()`: Get cell style information
- `CellData::has_style()`: Check if cell has style information
- `Style::get_font()`: Get font properties
- `Style::get_fill()`: Get fill properties
- `Style::get_borders()`: Get border properties
- `Style::get_alignment()`: Get alignment properties
- `Style::is_empty()`: Check if style has any properties
- `Style::has_visible_properties()`: Check if style has visible properties
- `Font::is_bold()`: Check if font is bold
- `Font::is_italic()`: Check if font is italic
- `Fill::is_visible()`: Check if fill is visible
- `Borders::has_visible_borders()`: Check if borders are visible

## Migration Guide

The style reading functionality is backward compatible. Existing code will continue to work without changes. To add style reading support:

1. Update your cell iteration to check for styles using `has_style()`
2. Use `get_style()` to access style information
3. Access specific style properties through the getter methods
4. Check for visibility using methods like `is_visible()` and `has_visible_borders()`

## Examples

See the `examples/style.rs` file for a complete working example of style extraction and usage.