Skip to main content

printing/
printing.rs

1//! Canonical printing creation, streamed source export and original-package editing.
2use crabxl::{
3    Cell, CellValue, PageBreak, PageMargins, PageOrder, PageOrientation, PaperDimension,
4    PrintSettings, PrintedComments, PrintedErrors, Result, Row, RowIndex, SaveOptions, StyleId,
5    WorkbookEditor, WorkbookReader, WorkbookWriter, WriteOptions,
6};
7use std::{fs::File, io::BufWriter};
8fn settings() -> Result<PrintSettings> {
9    let mut value = PrintSettings {
10        auto_page_breaks: Some(false),
11        fit_to_page: Some(true),
12        margins: Some(PageMargins {
13            left: -1.5,
14            right: 0.25,
15            top: 0.5,
16            bottom: 0.75,
17            header: 0.2,
18            footer: 0.3,
19        }),
20        ..PrintSettings::default()
21    };
22    value.options.horizontal_centered = Some(true);
23    value.options.vertical_centered = Some(false);
24    value.options.headings = Some(true);
25    value.options.grid_lines = Some(false);
26    value.options.grid_lines_set = Some(true);
27    value.setup.orientation = Some(PageOrientation::Landscape);
28    value.setup.paper_size = Some(9);
29    value.setup.scale = Some(85);
30    value.setup.fit_to_height = Some(0);
31    value.setup.fit_to_width = Some(1);
32    value.setup.first_page_number = Some(7);
33    value.setup.use_first_page_number = Some(true);
34    value.setup.paper_height = Some(PaperDimension::parse("11.5in tail")?);
35    value.setup.paper_width = Some(PaperDimension::parse("8.25in")?);
36    value.setup.page_order = Some(PageOrder::OverThenDown);
37    value.setup.use_printer_defaults = Some(false);
38    value.setup.black_and_white = Some(true);
39    value.setup.draft = Some(false);
40    value.setup.cell_comments = Some(PrintedComments::AtEnd);
41    value.setup.errors = Some(PrintedErrors::NotAvailable);
42    value.setup.horizontal_dpi = Some(300);
43    value.setup.vertical_dpi = Some(600);
44    value.setup.copies = Some(2);
45    value.row_breaks = vec![
46        PageBreak {
47            id: Some(10),
48            minimum: Some(2),
49            maximum: Some(7),
50            manual: Some(false),
51            pivot: Some(true),
52        },
53        PageBreak {
54            id: Some(25),
55            ..PageBreak::default()
56        },
57    ];
58    value.row_breaks.push(PageBreak {
59        id: None,
60        minimum: None,
61        maximum: None,
62        manual: Some(false),
63        pivot: Some(false),
64    });
65    value.column_breaks = vec![PageBreak {
66        id: Some(3),
67        minimum: Some(1),
68        maximum: Some(1048575),
69        manual: None,
70        pivot: Some(false),
71    }];
72    Ok(value)
73}
74fn output(path: &str) -> Result<BufWriter<File>> {
75    File::create(path).map(BufWriter::new).map_err(|error| {
76        crabxl::Error::caused_by(
77            crabxl::ErrorKind::Io,
78            "Cannot create printing fixture",
79            error,
80        )
81    })
82}
83fn run() -> Result<()> {
84    let args: Vec<_> = std::env::args().collect();
85    if args.len() != 5 {
86        return Err(crabxl::Error::new(
87            crabxl::ErrorKind::InvalidData,
88            "Usage: printing create|copy|edit SOURCE OUTPUT ROWS",
89        ));
90    }
91    if args[1] == "edit" {
92        let mut editor = WorkbookEditor::open(&args[2])?;
93        editor.set_print_settings("Sheet", settings()?)?;
94        println!("PRINT_BYTES={}", editor.patch_bytes());
95        editor.save(output(&args[3])?, SaveOptions::default())?;
96        println!("TEMP_BYTES=0");
97        return Ok(());
98    }
99    if !matches!(args[1].as_str(), "create" | "copy") {
100        return Err(crabxl::Error::new(
101            crabxl::ErrorKind::InvalidData,
102            "Unknown printing operation",
103        ));
104    }
105    let mut reader = if args[1] == "copy" {
106        Some(WorkbookReader::open(&args[2])?)
107    } else {
108        None
109    };
110    let value = match &mut reader {
111        Some(reader) => reader.print_settings("Sheet")?,
112        None => settings()?,
113    };
114    println!("PRINT_BYTES={}", value.memory_bytes());
115    let mut writer = WorkbookWriter::new(WriteOptions::default())?;
116    writer.start_sheet_with_settings("Sheet", None, Some(&value))?;
117    if let Some(reader) = &mut reader {
118        let mut rows = reader.rows("Sheet")?;
119        while let Some(row) = rows.next_row()? {
120            writer.write_row(&row)?;
121        }
122    } else {
123        let count: u32 = args[4].parse().map_err(|error| {
124            crabxl::Error::caused_by(
125                crabxl::ErrorKind::InvalidData,
126                "Invalid printing row count",
127                error,
128            )
129        })?;
130        let mut row = Row::new(RowIndex::new(0)?);
131        for index in 0..count {
132            row.index = RowIndex::new(index)?;
133            row.cells.clear();
134            row.cells.push(Cell {
135                address: crabxl::CellAddress::new(index, 0)?,
136                value: CellValue::Integer(i64::from(index)),
137                style: StyleId::new(0),
138            });
139            writer.write_row(&row)?;
140        }
141    }
142    writer.close_sheet()?;
143    println!("TEMP_BYTES={}", writer.stats().peak_temp_bytes);
144    writer.finish(output(&args[3])?)?;
145    Ok(())
146}
147fn main() {
148    if let Err(error) = run() {
149        eprintln!("{error}");
150        std::process::exit(1);
151    }
152}