xl-cli-tools

CLI tools for viewing and editing Excel files
Log | Files | Refs | README | LICENSE

mod.rs (10876B)


      1 use rust_xlsxwriter::*;
      2 use std::path::Path;
      3 
      4 /// Single sheet, 5 rows of mixed types: string, float, int, bool
      5 pub fn create_simple(path: &Path) {
      6     let mut wb = Workbook::new();
      7     let ws = wb.add_worksheet().set_name("Data").unwrap();
      8 
      9     // Headers
     10     ws.write_string(0, 0, "name").unwrap();
     11     ws.write_string(0, 1, "amount").unwrap();
     12     ws.write_string(0, 2, "count").unwrap();
     13     ws.write_string(0, 3, "active").unwrap();
     14 
     15     // Row 1
     16     ws.write_string(1, 0, "Alice").unwrap();
     17     ws.write_number(1, 1, 100.50).unwrap();
     18     ws.write_number(1, 2, 10.0).unwrap();
     19     ws.write_boolean(1, 3, true).unwrap();
     20 
     21     // Row 2
     22     ws.write_string(2, 0, "Bob").unwrap();
     23     ws.write_number(2, 1, 200.75).unwrap();
     24     ws.write_number(2, 2, 20.0).unwrap();
     25     ws.write_boolean(2, 3, false).unwrap();
     26 
     27     // Row 3
     28     ws.write_string(3, 0, "Charlie").unwrap();
     29     ws.write_number(3, 1, 300.00).unwrap();
     30     ws.write_number(3, 2, 30.0).unwrap();
     31     ws.write_boolean(3, 3, true).unwrap();
     32 
     33     // Row 4
     34     ws.write_string(4, 0, "Diana").unwrap();
     35     ws.write_number(4, 1, 400.25).unwrap();
     36     ws.write_number(4, 2, 40.0).unwrap();
     37     ws.write_boolean(4, 3, false).unwrap();
     38 
     39     // Row 5
     40     ws.write_string(5, 0, "Eve").unwrap();
     41     ws.write_number(5, 1, 500.00).unwrap();
     42     ws.write_number(5, 2, 50.0).unwrap();
     43     ws.write_boolean(5, 3, true).unwrap();
     44 
     45     wb.save(path).unwrap();
     46 }
     47 
     48 /// 3 sheets: Revenue (4 rows), Expenses (3 rows), Summary (2 rows)
     49 pub fn create_multi_sheet(path: &Path) {
     50     let mut wb = Workbook::new();
     51 
     52     let ws1 = wb.add_worksheet().set_name("Revenue").unwrap();
     53     ws1.write_string(0, 0, "region").unwrap();
     54     ws1.write_string(0, 1, "amount").unwrap();
     55     for i in 1..=4u32 {
     56         ws1.write_string(i, 0, &format!("Region {i}")).unwrap();
     57         ws1.write_number(i, 1, i as f64 * 1000.0).unwrap();
     58     }
     59 
     60     let ws2 = wb.add_worksheet().set_name("Expenses").unwrap();
     61     ws2.write_string(0, 0, "category").unwrap();
     62     ws2.write_string(0, 1, "amount").unwrap();
     63     for i in 1..=3u32 {
     64         ws2.write_string(i, 0, &format!("Category {i}")).unwrap();
     65         ws2.write_number(i, 1, i as f64 * 500.0).unwrap();
     66     }
     67 
     68     let ws3 = wb.add_worksheet().set_name("Summary").unwrap();
     69     ws3.write_string(0, 0, "metric").unwrap();
     70     ws3.write_string(0, 1, "value").unwrap();
     71     ws3.write_string(1, 0, "Total Revenue").unwrap();
     72     ws3.write_number(1, 1, 10000.0).unwrap();
     73     ws3.write_string(2, 0, "Total Expenses").unwrap();
     74     ws3.write_number(2, 1, 3000.0).unwrap();
     75 
     76     wb.save(path).unwrap();
     77 }
     78 
     79 /// Single sheet with 80 rows (to test head/tail adaptive behavior)
     80 pub fn create_many_rows(path: &Path) {
     81     let mut wb = Workbook::new();
     82     let ws = wb.add_worksheet().set_name("Data").unwrap();
     83 
     84     ws.write_string(0, 0, "id").unwrap();
     85     ws.write_string(0, 1, "value").unwrap();
     86 
     87     for i in 1..=80u32 {
     88         ws.write_number(i, 0, i as f64).unwrap();
     89         ws.write_number(i, 1, i as f64 * 1.5).unwrap();
     90     }
     91 
     92     wb.save(path).unwrap();
     93 }
     94 
     95 /// Single sheet with header row but no data rows
     96 pub fn create_empty_data(path: &Path) {
     97     let mut wb = Workbook::new();
     98     let ws = wb.add_worksheet().set_name("Empty").unwrap();
     99     ws.write_string(0, 0, "col_a").unwrap();
    100     ws.write_string(0, 1, "col_b").unwrap();
    101     wb.save(path).unwrap();
    102 }
    103 
    104 /// Completely empty sheet
    105 pub fn create_empty_sheet(path: &Path) {
    106     let mut wb = Workbook::new();
    107     wb.add_worksheet().set_name("Blank").unwrap();
    108     wb.save(path).unwrap();
    109 }
    110 
    111 /// Create a test file with metadata rows above the real header.
    112 pub fn create_with_metadata(path: &Path) {
    113     use rust_xlsxwriter::*;
    114     let mut workbook = Workbook::new();
    115     let sheet = workbook.add_worksheet().set_name("Data").unwrap();
    116 
    117     // Metadata rows
    118     sheet.write_string(0, 0, "Quarterly Report").unwrap();
    119     sheet.write_string(1, 0, "Generated 2024-01-01").unwrap();
    120 
    121     // Real header at row 2
    122     sheet.write_string(2, 0, "Name").unwrap();
    123     sheet.write_string(2, 1, "Value").unwrap();
    124 
    125     // Data
    126     sheet.write_string(3, 0, "Alice").unwrap();
    127     sheet.write_number(3, 1, 100.0).unwrap();
    128     sheet.write_string(4, 0, "Bob").unwrap();
    129     sheet.write_number(4, 1, 200.0).unwrap();
    130 
    131     workbook.save(path.to_str().unwrap()).unwrap();
    132 }
    133 
    134 /// Create a test file with diverse data for filter testing.
    135 /// Sheet "Data" with 6 rows: State, City, Amount, Year, Status
    136 pub fn create_filterable(path: &Path) {
    137     let mut workbook = Workbook::new();
    138     let sheet = workbook.add_worksheet().set_name("Data").unwrap();
    139 
    140     // Headers
    141     sheet.write_string(0, 0, "State").unwrap();
    142     sheet.write_string(0, 1, "City").unwrap();
    143     sheet.write_string(0, 2, "Amount").unwrap();
    144     sheet.write_string(0, 3, "Year").unwrap();
    145     sheet.write_string(0, 4, "Status").unwrap();
    146 
    147     // Row 1: CA, Los Angeles, 1500, 2023, Active
    148     sheet.write_string(1, 0, "CA").unwrap();
    149     sheet.write_string(1, 1, "Los Angeles").unwrap();
    150     sheet.write_number(1, 2, 1500.0).unwrap();
    151     sheet.write_number(1, 3, 2023.0).unwrap();
    152     sheet.write_string(1, 4, "Active").unwrap();
    153 
    154     // Row 2: NY, New York, 2000, 2023, Active
    155     sheet.write_string(2, 0, "NY").unwrap();
    156     sheet.write_string(2, 1, "New York").unwrap();
    157     sheet.write_number(2, 2, 2000.0).unwrap();
    158     sheet.write_number(2, 3, 2023.0).unwrap();
    159     sheet.write_string(2, 4, "Active").unwrap();
    160 
    161     // Row 3: CA, San Francisco, 800, 2024, Draft
    162     sheet.write_string(3, 0, "CA").unwrap();
    163     sheet.write_string(3, 1, "San Francisco").unwrap();
    164     sheet.write_number(3, 2, 800.0).unwrap();
    165     sheet.write_number(3, 3, 2024.0).unwrap();
    166     sheet.write_string(3, 4, "Draft").unwrap();
    167 
    168     // Row 4: TX, Houston, 1200, 2024, Active
    169     sheet.write_string(4, 0, "TX").unwrap();
    170     sheet.write_string(4, 1, "Houston").unwrap();
    171     sheet.write_number(4, 2, 1200.0).unwrap();
    172     sheet.write_number(4, 3, 2024.0).unwrap();
    173     sheet.write_string(4, 4, "Active").unwrap();
    174 
    175     // Row 5: NY, Albany, 500, 2023, Draft
    176     sheet.write_string(5, 0, "NY").unwrap();
    177     sheet.write_string(5, 1, "Albany").unwrap();
    178     sheet.write_number(5, 2, 500.0).unwrap();
    179     sheet.write_number(5, 3, 2023.0).unwrap();
    180     sheet.write_string(5, 4, "Draft").unwrap();
    181 
    182     // Row 6: FL, Miami, 3000, 2024, Active
    183     sheet.write_string(6, 0, "FL").unwrap();
    184     sheet.write_string(6, 1, "Miami").unwrap();
    185     sheet.write_number(6, 2, 3000.0).unwrap();
    186     sheet.write_number(6, 3, 2024.0).unwrap();
    187     sheet.write_string(6, 4, "Active").unwrap();
    188 
    189     workbook.save(path).unwrap();
    190 }
    191 
    192 /// Create a pair of files for positional diff testing.
    193 /// File A: Name/Score — Alice/90, Bob/80, Charlie/70
    194 /// File B: Name/Score — Alice/90, Charlie/70, Dana/85
    195 /// Expected: Bob removed, Dana added
    196 pub fn create_diff_pair(path_a: &Path, path_b: &Path) {
    197     // File A
    198     {
    199         let mut wb = Workbook::new();
    200         let ws = wb.add_worksheet().set_name("Data").unwrap();
    201         ws.write_string(0, 0, "Name").unwrap();
    202         ws.write_string(0, 1, "Score").unwrap();
    203         ws.write_string(1, 0, "Alice").unwrap();
    204         ws.write_number(1, 1, 90.0).unwrap();
    205         ws.write_string(2, 0, "Bob").unwrap();
    206         ws.write_number(2, 1, 80.0).unwrap();
    207         ws.write_string(3, 0, "Charlie").unwrap();
    208         ws.write_number(3, 1, 70.0).unwrap();
    209         wb.save(path_a).unwrap();
    210     }
    211 
    212     // File B
    213     {
    214         let mut wb = Workbook::new();
    215         let ws = wb.add_worksheet().set_name("Data").unwrap();
    216         ws.write_string(0, 0, "Name").unwrap();
    217         ws.write_string(0, 1, "Score").unwrap();
    218         ws.write_string(1, 0, "Alice").unwrap();
    219         ws.write_number(1, 1, 90.0).unwrap();
    220         ws.write_string(2, 0, "Charlie").unwrap();
    221         ws.write_number(2, 1, 70.0).unwrap();
    222         ws.write_string(3, 0, "Dana").unwrap();
    223         ws.write_number(3, 1, 85.0).unwrap();
    224         wb.save(path_b).unwrap();
    225     }
    226 }
    227 
    228 /// Create a pair of files for key-based diff testing.
    229 /// File A: ID/Name/Score — "1"/Alice/90, "2"/Bob/80, "3"/Charlie/70
    230 /// File B: ID/Name/Score — "1"/Alice/95, "2"/Bob/80, "4"/Dana/85
    231 /// Expected: ID=1 modified (Score 90→95), ID=3 removed, ID=4 added
    232 pub fn create_diff_pair_with_keys(path_a: &Path, path_b: &Path) {
    233     // File A
    234     {
    235         let mut wb = Workbook::new();
    236         let ws = wb.add_worksheet().set_name("Data").unwrap();
    237         ws.write_string(0, 0, "ID").unwrap();
    238         ws.write_string(0, 1, "Name").unwrap();
    239         ws.write_string(0, 2, "Score").unwrap();
    240         ws.write_string(1, 0, "1").unwrap();
    241         ws.write_string(1, 1, "Alice").unwrap();
    242         ws.write_number(1, 2, 90.0).unwrap();
    243         ws.write_string(2, 0, "2").unwrap();
    244         ws.write_string(2, 1, "Bob").unwrap();
    245         ws.write_number(2, 2, 80.0).unwrap();
    246         ws.write_string(3, 0, "3").unwrap();
    247         ws.write_string(3, 1, "Charlie").unwrap();
    248         ws.write_number(3, 2, 70.0).unwrap();
    249         wb.save(path_a).unwrap();
    250     }
    251 
    252     // File B
    253     {
    254         let mut wb = Workbook::new();
    255         let ws = wb.add_worksheet().set_name("Data").unwrap();
    256         ws.write_string(0, 0, "ID").unwrap();
    257         ws.write_string(0, 1, "Name").unwrap();
    258         ws.write_string(0, 2, "Score").unwrap();
    259         ws.write_string(1, 0, "1").unwrap();
    260         ws.write_string(1, 1, "Alice").unwrap();
    261         ws.write_number(1, 2, 95.0).unwrap();
    262         ws.write_string(2, 0, "2").unwrap();
    263         ws.write_string(2, 1, "Bob").unwrap();
    264         ws.write_number(2, 2, 80.0).unwrap();
    265         ws.write_string(3, 0, "4").unwrap();
    266         ws.write_string(3, 1, "Dana").unwrap();
    267         ws.write_number(3, 2, 85.0).unwrap();
    268         wb.save(path_b).unwrap();
    269     }
    270 }
    271 
    272 /// Create a pair of files for tolerance testing.
    273 /// File A: ID/Price — "1"/100.001, "2"/200.5
    274 /// File B: ID/Price — "1"/100.002, "2"/200.6
    275 /// Expected with tolerance 0.01: only ID=2 modified (diff=0.1 > 0.01)
    276 pub fn create_diff_pair_with_floats(path_a: &Path, path_b: &Path) {
    277     // File A
    278     {
    279         let mut wb = Workbook::new();
    280         let ws = wb.add_worksheet().set_name("Data").unwrap();
    281         ws.write_string(0, 0, "ID").unwrap();
    282         ws.write_string(0, 1, "Price").unwrap();
    283         ws.write_string(1, 0, "1").unwrap();
    284         ws.write_number(1, 1, 100.001).unwrap();
    285         ws.write_string(2, 0, "2").unwrap();
    286         ws.write_number(2, 1, 200.5).unwrap();
    287         wb.save(path_a).unwrap();
    288     }
    289 
    290     // File B
    291     {
    292         let mut wb = Workbook::new();
    293         let ws = wb.add_worksheet().set_name("Data").unwrap();
    294         ws.write_string(0, 0, "ID").unwrap();
    295         ws.write_string(0, 1, "Price").unwrap();
    296         ws.write_string(1, 0, "1").unwrap();
    297         ws.write_number(1, 1, 100.002).unwrap();
    298         ws.write_string(2, 0, "2").unwrap();
    299         ws.write_number(2, 1, 200.6).unwrap();
    300         wb.save(path_b).unwrap();
    301     }
    302 }