karo 0.1.2

Spreadsheet export
Documentation
use chrono::{NaiveTime, TimeZone, Utc};
use indexmap::indexset;
use karo::{
    cell, col_range, row_range, Border, BorderStyle, Criterion, Format,
    Pattern, Result, Validation, ValidationErrorType, ValidationType,
    VerticalAlignment, Workbook, Worksheet,
};
use rgb::RGB8;

fn write_data(w: &mut Worksheet, format: Option<&Format>) -> Result<()> {
    w.write_string(
        cell("A1")?,
        "Some examples of data validation in karo",
        format,
    )?;
    w.write_string(cell("B1")?, "Enter values in this column", format)?;
    w.write_string(cell("D1")?, "Sample data", format)?;

    w.write_string(cell("D3")?, "Integers", None)?;
    w.write_number(cell("E3")?, 1f64, None)?;
    w.write_number(cell("F3")?, 10f64, None)?;

    w.write_string(cell("D4")?, "List data", None)?;
    w.write_string(cell("E4")?, "open", None)?;
    w.write_string(cell("F4")?, "high", None)?;
    w.write_string(cell("G4")?, "close", None)?;

    w.write_string(cell("D5")?, "Formula", None)?;
    w.write_formula(cell("E5")?, "=AND(F5=50,G5=60)", None)?;
    w.write_number(cell("F5")?, 50f64, None)?;
    w.write_number(cell("G5")?, 60f64, None)?;

    Ok(())
}

fn main() -> karo::Result<()> {
    let mut workbook = Workbook::new();

    let mut format = Format::default();
    format.borders.set_around(Some(Border {
        style: BorderStyle::Thin,
        color: None,
    }));
    format.fill.fg_color = Some(RGB8 {
        r: 0xc6,
        g: 0xef,
        b: 0xce,
    });
    format.fill.pattern = Some(Pattern::Solid);
    format.font.bold = true;
    format.text_wrap = true;
    format.vertical_alignment = Some(VerticalAlignment::Center);
    format.indent = 1;

    {
        let worksheet = workbook.add_worksheet(None)?;
        write_data(worksheet, Some(&format))?;

        // Set up layout of the worksheet.
        worksheet.set_column(col_range(0, 0)?, 55f64, None)?;
        worksheet.set_column(col_range(1, 1)?, 15f64, None)?;
        worksheet.set_column(col_range(3, 3)?, 15f64, None)?;
        worksheet.set_row(row_range(0, 0)?, 36f64, None)?;

        // Example 1. Limiting input to an integer in a fixed range.
        worksheet.write_string(
            cell("A3")?,
            "Enter an integer between 1 and 10",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::Integer(Criterion::Between(1, 10)),
            cell("B3")?,
        );
        worksheet.data_validation(validation)?;

        // Example 2. Limiting input to an integer outside a fixed range.
        worksheet.write_string(
            cell("A5")?,
            "Enter an integer not between 1 and 10 \
             (using cell references)",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::IntegerFormula(Criterion::NotBetween(
                "=E3".to_string(),
                "=F3".to_string(),
            )),
            cell("B5")?,
        );
        worksheet.data_validation(validation)?;

        // Example 3. Limiting input to an integer greater than a fixed value.
        worksheet.write_string(
            cell("A7")?,
            "Enter an integer greater than 0",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::Integer(Criterion::GreaterThan(0)),
            cell("B7")?,
        );
        worksheet.data_validation(validation)?;

        // Example 4. Limiting input to an integer less than a fixed value.
        worksheet.write_string(
            cell("A9")?,
            "Enter an integer less than 10",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::Integer(Criterion::LessThan(10)),
            cell("B9")?,
        );
        worksheet.data_validation(validation)?;

        // Example 5. Limiting input to a decimal in a fixed range.
        worksheet.write_string(
            cell("A11")?,
            "Enter a decimal between 0.1 and 0.5",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::Decimal(Criterion::Between(0.1, 0.5)),
            cell("B11")?,
        );
        worksheet.data_validation(validation)?;

        // Example 6. Limiting input to a value in dropdown list.
        worksheet.write_string(
            cell("A13")?,
            "Select a value from a drop down list",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::List {
                values: indexset! {
                    "open".to_string(),
                    "high".to_string(),
                    "close".to_string(),
                },
                show_dropdown: true,
            },
            cell("B13")?,
        );
        worksheet.data_validation(validation)?;

        // Example 7. Limiting input to a value in a dropdown list.
        worksheet.write_string(
            cell("A15")?,
            "Select a value from a drop down list (using a cell range)",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::ListFormula {
                formula: "=$E$4:$G$4".to_string(),
                show_dropdown: true,
            },
            cell("B15")?,
        );
        worksheet.data_validation(validation)?;

        // Example 8. Limiting input to date in a fixed range.
        worksheet.write_string(
            cell("A17")?,
            "Enter a date between 1/1/2008 and 12/12/2008",
            None,
        )?;
        let date1 = Utc.ymd(2008, 1, 1).and_hms(0, 0, 0);
        let date2 = Utc.ymd(2008, 12, 12).and_hms(0, 0, 0);
        let validation = Validation::new(
            ValidationType::Date(Criterion::Between(date1, date2)),
            cell("B17")?,
        );
        worksheet.data_validation(validation)?;

        // Example 9. Limiting input to time in a fixed range.
        worksheet.write_string(
            cell("A19")?,
            "Enter a time between 6:00 and 12:00",
            None,
        )?;
        let time1 = NaiveTime::from_hms(6, 0, 0);
        let time2 = NaiveTime::from_hms(12, 0, 0);
        let validation = Validation::new(
            ValidationType::Time(Criterion::Between(time1, time2)),
            cell("B19")?,
        );
        worksheet.data_validation(validation)?;

        // Example 10. Limiting input to a string greater than a fixed length.
        worksheet.write_string(
            cell("A21")?,
            "Enter a string longer than 3 characters",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::Length(Criterion::GreaterThan(3)),
            cell("B21")?,
        );
        worksheet.data_validation(validation)?;

        // Example 11. Limiting input based on a formula.
        worksheet.write_string(
            cell("A23")?,
            "Enter a value if the folowing is true \"=AND(F5=50,G5=60)\"",
            None,
        )?;
        let validation = Validation::new(
            ValidationType::CustomFormula("=AND(F5=50,G5=60)".to_string()),
            cell("B23")?,
        );
        worksheet.data_validation(validation)?;

        // Example 12. Displaying and modifying data validation messages.
        worksheet.write_string(
            cell("A25")?,
            "Displays a message when you select the cell",
            None,
        )?;
        let mut validation = Validation::new(
            ValidationType::Integer(Criterion::Between(1, 100)),
            cell("B25")?,
        );
        validation.input_title = Some("Enter an integer:".to_string());
        validation.input_message = Some("between 1 and 100".to_string());
        worksheet.data_validation(validation)?;

        // Example 13. Displaying and modifying data validation messages.
        worksheet.write_string(
            cell("A27")?,
            "Displays a custom error message when integer isn't \
             between 1 and 100",
            None,
        )?;
        let mut validation = Validation::new(
            ValidationType::Integer(Criterion::Between(1, 100)),
            cell("B27")?,
        );
        validation.input_title = Some("Enter an integer:".to_string());
        validation.input_message = Some("between 1 and 100".to_string());
        validation.error_title =
            Some("Input value is not valid!".to_string());
        validation.error_message = Some(
            "It should be an integer \
             between 1 and 100"
                .to_string(),
        );
        worksheet.data_validation(validation)?;

        // Example 14. Displaying and modifying data validation messages.
        worksheet.write_string(
            cell("A29")?,
            "Displays a custom info message when integer isn't \
             between 1 and 100",
            None,
        )?;
        let mut validation = Validation::new(
            ValidationType::Integer(Criterion::Between(1, 100)),
            cell("B29")?,
        );
        validation.input_title = Some("Enter an integer:".to_string());
        validation.input_message = Some("between 1 and 100".to_string());
        validation.error_title =
            Some("Input value is not valid!".to_string());
        validation.error_message = Some(
            "It should be an integer \
             between 1 and 100"
                .to_string(),
        );
        validation.error_type = ValidationErrorType::Information;
        worksheet.data_validation(validation)?;
    }

    workbook.write_file("data_validate.xlsx")?;

    Ok(())
}