Checksum of a saved file
A common issue that occurs with rust_xlsxwriter
, but also with Excel, is that
running the same program twice doesn't generate the same file, byte for byte.
This can cause issues with applications that do checksumming for testing
purposes.
For example consider the following simple rust_xlsxwriter
program:
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright 2022-2024, John McNamara, jmcnamara@cpan.org
//! Create a simple workbook to demonstrate the changing checksum due to the
//! changing creation date.
use rust_xlsxwriter::{Workbook, XlsxError};
fn main() -> Result<(), XlsxError> {
let mut workbook = Workbook::new();
let worksheet = workbook.add_worksheet();
worksheet.write_string(0, 0, "Hello")?;
workbook.save("properties.xlsx")?;
Ok(())
}
If we run this several times, with a small delay, we will get different checksums as shown below:
$ cargo run --example doc_properties_checksum1
$ sum properties.xlsx
62457 6 properties.xlsx
$ sleep 2
$ cargo run --example doc_properties_checksum1
$ sum properties.xlsx
56692 6 properties.xlsx # Different to previous.
This is due to a file creation datetime that is included in the file and which changes each time a new file is created.
The relevant section of the docProps/core.xml
sub-file in the xlsx format
looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cp:coreProperties>
<dc:creator/>
<cp:lastModifiedBy/>
<dcterms:created xsi:type="dcterms:W3CDTF">2023-01-08T00:23:58Z</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">2023-01-08T00:23:58Z</dcterms:modified>
</cp:coreProperties>
If required this can be avoided by setting a constant creation date in the document properties metadata:
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright 2022-2024, John McNamara, jmcnamara@cpan.org
//! Create a simple workbook to demonstrate a constant checksum due to the a
//! constant creation date.
use rust_xlsxwriter::{DocProperties, ExcelDateTime, Workbook, XlsxError};
fn main() -> Result<(), XlsxError> {
let mut workbook = Workbook::new();
// Create a file creation date for the file.
let date = ExcelDateTime::from_ymd(2023, 1, 1)?;
// Add it to the document metadata.
let properties = DocProperties::new().set_creation_datetime(&date);
workbook.set_properties(&properties);
let worksheet = workbook.add_worksheet();
worksheet.write_string(0, 0, "Hello")?;
workbook.save("properties.xlsx")?;
Ok(())
}
Then we will get the same checksum for the same output every time:
$ cargo run --example doc_properties_checksum2
$ sum properties.xlsx
8914 6 properties.xlsx
$ sleep 2
$ cargo run --example doc_properties_checksum2
$ sum properties.xlsx
8914 6 properties.xlsx # Same as previous
For more details see DocProperties
and workbook::set_properties()
.