Proc-macro helpers for generating Excel XLL wrappers using xll-rs.
Working WIP. Macros generate wrappers, registration, and optional manifest helpers.
Type mapping spec: see TYPE_MAPPING.md.
use xllgen::{xll_bindgen, xll_auto_open};
use xll_rs::types::{XllError, XLLError};
#[xll_bindgen]
pub fn add(a: f64, b: f64) -> f64 {
a + b
}
#[xll_bindgen(name = "MEAN", args = "a, b", help = "Average of two numbers")]
pub fn mean(a: f64, b: f64) -> f64 {
(a + b) / 2.0
}
#[xll_bindgen(name = "SCI.SCALE", threadsafe, category = "xllgen")]
pub fn scale(x: f64, factor: f64) -> f64 {
x * factor
}
#[xll_bindgen]
pub fn must_be_positive(x: f64) -> Result<f64, XllError> {
if x < 0.0 {
return Err(XllError::msg(XLLError::VALUE, "x must be >= 0"));
}
Ok(x)
}
xll_auto_open!();Add a build.rs in your XLL crate:
fn main() {
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
if target_os != "windows" {
return;
}
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
if target_env != "msvc" {
println!("cargo:warning=Non-MSVC toolchain detected; .xll output rename is not configured.");
return;
}
let manifest_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let profile = std::env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
let target_dir = std::env::var("CARGO_TARGET_DIR")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| manifest_dir.join("target"));
let out = target_dir.join(&profile).join("your_crate_name.xll");
println!("cargo:rustc-cdylib-link-arg=/OUT:{}", out.display());
}This emits target/<profile>/<your_crate_name>.xll on every build.
- Prefix defaults to the crate name (uppercased) and can be overridden:
xll_auto_open!(prefix = "SCI")
- If no
nameis provided, the Excel name defaults to:PREFIX.<RUST_FN_NAME>(uppercased)
- If
name = "FOO"(no dot), it becomesPREFIX.FOO. - If
name = "PREFIX.FOO", it is treated as fully qualified.
Return Result<T, XllError>:
XllError::new(XLLError::VALUE)-> returns#VALUE!XllError::msg(XLLError::VALUE, "bad input")-> returns"bad input"(string)"VALUE: bad input".into()is also supported
Excel cells can display an error or a string message, not both.
xll_auto_open!(manifest = "json") generates:
xllgen_exports()-> slice ofXllExportxllgen_exports_json()-> JSON string
xll_auto_open! always registers XLLGEN.REG_ERRORS:
- Returns
OKor a;-separated list of failed registrations. - Use
strictto failxlAutoOpenif any registration fails:
xll_auto_open!(strict);
// or
xll_auto_open!(strict = true);XLLGEN.REG_ERRORS is a reserved name. You can disable it:
xll_auto_open!(reg_errors = false);