Navigation: ← Chapter 08 · Manual index · Chapter 10 →
All failure cases used by XLKit conform to XLKitError. Prefer pattern matching on the enum so you preserve associated messages.
import XLKit
@MainActor
func exportWorkbook(_ workbook: Workbook, to url: URL) async {
do {
try await workbook.save(to: url)
} catch let error as XLKitError {
switch error {
case .securityError(let message):
print("Path not allowed: \(message)")
case .rateLimitExceeded(let message):
print("Slow down: \(message)")
case .fileWriteError(let message), .zipCreationError(let message), .xmlGenerationError(let message):
print("Export failed: \(message)")
default:
print("Other XLKit error: \(error.localizedDescription)")
}
} catch {
print("System error: \(error)")
}
}Image loading can throw fileSizeLimitExceeded, suspiciousFileDetected, or securityError (paths) depending on SecurityManager / CoreUtils settings:
do {
if let img = try ImageUtils.createExcelImage(from: data, format: .png) {
_ = img.id // place with `sheet.addImage(_:at:)` / `workbook.addImage` as needed
}
} catch let error as XLKitError {
if case .suspiciousFileDetected(let msg) = error {
print(msg)
}
} catch {
print(error)
}XLKitError conforms to LocalizedError; you can show error.localizedDescription in UI.
Full case list: Chapter 12 — API reference (XLKitError).
let letters = CoreUtils.columnLetter(from: 28) // "AB"
let n = CoreUtils.columnNumber(from: "AB") // 28
let coord = CellCoordinate(row: 5, column: 3) // C5
print(coord.excelAddress)Cells store dates as numbers in the worksheet XML; XLKit converts using an Excel 1900-era epoch:
let someDate = Date() // or your fixed test date from Calendar
let excelSerial = CoreUtils.excelNumberFromDate(someDate)
let roundTrip = CoreUtils.dateFromExcelNumber(excelSerial)
let label = CoreUtils.formatDate(roundTrip) // yyyy-mm-dd style string for stringValue pathsIf you generate XML beside XLKit, reuse:
let safe = CoreUtils.escapeXML("A & B < C")if let sha = try? CoreUtils.generateFileChecksum(fileURL) {
print(sha)
}
let dataChecksum = CoreUtils.generateChecksum(Data("hello".utf8))do {
try CoreUtils.validateImageFileSize(imageData)
try CoreUtils.validateExcelFileSize(xlsxData)
} catch let error as XLKitError {
if case .fileSizeLimitExceeded(let msg) = error { print(msg) }
}When SecurityManager.enableFilePathRestrictions is true, CoreUtils.validateFilePath runs on save paths. On iOS, validation is relaxed when restrictions are on (sandbox enforces access); on macOS, paths must sit under allowed roots — see Chapter 08.
do {
try CoreUtils.validateFilePath(url.path)
} catch let error as XLKitError {
if case .securityError(let msg) = error { print(msg) }
}Use a URL under the app’s Documents, Caches, or temporary directory — not arbitrary POSIX paths.
CoreUtils.safeFileURL(for:) returns a file URL under Documents on iOS (and a sensible location on macOS for the helper’s contract — see source if you rely on macOS behaviour).
import XLKit
@MainActor
func saveForIOS(_ workbook: Workbook) async throws {
let url = CoreUtils.safeFileURL(for: "report.xlsx")
try await workbook.save(to: url)
}if let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let url = documents.appendingPathComponent("report.xlsx")
try await workbook.save(to: url)
}To expose exports in Files or document browser workflows, enable the usual keys (exact keys vary by app requirements):
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>Workbook.save, SecurityManager, and image helpers are @MainActor. Declare your export UI or service as @MainActor, or hop to the main actor before calling XLKit:
await MainActor.run {
try? await workbook.save(to: url)
}| Need | API |
|---|---|
| User-visible error text | XLKitError.localizedDescription |
| Column index ↔ letters | CoreUtils.columnLetter, columnNumber |
| Date ↔ Excel serial | excelNumberFromDate, dateFromExcelNumber |
| Safe output URL on iOS | CoreUtils.safeFileURL(for:) |
| SHA-256 | generateChecksum, generateFileChecksum |