CLua Documentation

📊 Working with XLSX Spreadsheets

CLua provides a set of functions for loading, reading, creating and editing .xlsx files. These functions use a C# backend via the ClosedXML library and are accessible through a simple Lua API.


📁 File Structure

  • Excel spreadsheets are located in the following folder:
    Tables/
  • They are loaded on demand by individual macros.

📥 Loading and Creating a Workbook

Loading an existing workbook

local wb = Workbook("FileName.xlsx");
  • Workbook(path) creates a workbook object (wb).
  • The path must be relative to the Tables/ folder.

Creating a new workbook

local wb = NewWorkbook("NewWorkbook.xlsx");
  • Creates a new empty workbook.
  • If the file already exists, it returns an error.

Creating or loading a workbook

local wb = NewWorkbook("Workbook.xlsx", true);
  • The second parameter true means: if the file exists, load it; otherwise create a new one.
  • Useful for scripts that need to work with a workbook regardless of whether it exists.

📄 Accessing Sheets

local sheet = wb:Sheet("SheetName");
  • Returns a sheet object you can read from or write to.

Sheet management

-- Add a new sheet
wb:AddSheet("NewSheet");

-- Rename a sheet
wb:RenameSheet("OldName", "NewName");

-- Delete a sheet
wb:DeleteSheet("UnneededSheet");

-- Get a list of all sheets
local sheetNames = wb:GetSheetNames();
for i, name in ipairs(sheetNames) do
    print(i, name);
end

🔎 Checking Existence

local isWb = WorkbookExists("workbookName.xlsx");
local isSheet = wb:ContainSheet("SheetName");
  • Returns a boolean indicating whether the given workbook exists.
  • Returns a boolean indicating whether the workbook contains the given sheet.

📋 Cell Objects

A Cell object represents a single cell in the spreadsheet and allows elegant manipulation of its content and formatting.

Creating a Cell object

local cell = sheet:Cell(5, 3);  -- row 5, column 3

Method chaining

Cell objects support chaining — multiple operations in sequence:

sheet:Cell(1, 1)
    :SetValue("Header")
    :SetBold(true)
    :SetFontSize(14)
    :SetBackgroundColor("#4472C4")
    :SetFontColor("#FFFFFF")
    :SetAlignment("Center", "Center");

🔍 Reading Values

Basic reading

-- String value
local value = sheet:GetCell(3, 2);  -- backward compatibility
local value = sheet:Cell(3, 2):GetS();

-- Typed value (number, string, boolean, etc.)
local value = sheet:Cell(3, 2):Get();

-- Via Cell object
local cell = sheet:Cell(3, 2);
local value = cell:Get();   -- typed
local text = cell:GetS();   -- string
  • Note: Row and column indices start at 1 (as in Excel), not 0.

Reading formatting

local cell = sheet:Cell(5, 3);

-- Font
local isBold = cell:GetBold();
local isItalic = cell:GetItalic();
local isUnderline = cell:GetUnderline();
local isStrikethrough = cell:GetStrikethrough();
local fontSize = cell:GetFontSize();
local fontName = cell:GetFontName();

-- Colors (returns hex string, e.g. "#FF0000")
local bgColor = cell:GetBackgroundColor();
local fontColor = cell:GetFontColor();

-- Alignment
local hAlign = cell:GetHorizontalAlignment();  -- "Left", "Center", "Right", "Justify"
local vAlign = cell:GetVerticalAlignment();    -- "Top", "Center", "Bottom", "Justify"
local isWrapped = cell:GetWrapText();

-- Borders
local topBorder = cell:GetBorderTop();      -- "None", "Thin", "Medium", "Thick", etc.
local bottomBorder = cell:GetBorderBottom();
local leftBorder = cell:GetBorderLeft();
local rightBorder = cell:GetBorderRight();

-- Number format
local format = cell:GetNumberFormat();  -- e.g. "#,##0.00"

-- Formula
local formula = cell:GetFormula();  -- e.g. "=SUM(A1:A10)" or nil
local hasFormula = cell:HasFormula();

-- Merged cells
local isMerged = cell:IsMerged();
local mergedRange = cell:GetMergedRange();  -- e.g. "A1:C1" or nil

-- Cell address
local address = cell:GetAddress();  -- e.g. "C5"

Detailed cell information

local cellInfo = sheet:CellEx(5, 3);

-- cellInfo contains all possible properties:
-- value, format, formula, dataType, isBold, isItalic,
-- fontColor, bgColor, hAlign, vAlign, borders,
-- richText, comment, etc.

print(cellInfo.value);
print(cellInfo.fontName);
if cellInfo.isBold then
    print("Cell is bold");
end

✍️ Writing Values

Basic writing

-- String
sheet:SetCell(3, 2, "Text"); -- backward compatibility
sheet:Cell(3, 2):SetS("Text");

-- Typed value
sheet:Cell(3, 2):Set(123);      -- number
sheet:Cell(3, 2):Set(45.67);    -- float
sheet:Cell(3, 2):Set(true);     -- boolean
sheet:Cell(3, 2):Set("Text");   -- string

-- Via Cell object
local cell = sheet:Cell(3, 2);
cell:SetValue(123);
cell:SetS("Text");  -- string variant

Text formatting

local cell = sheet:Cell(1, 1);

-- Font
cell:SetBold(true);
cell:SetItalic(true);
cell:SetUnderline(true);
cell:SetStrikethrough(true);
cell:SetFontSize(14);
cell:SetFontName("Arial");

Colors

local cell = sheet:Cell(1, 1);

-- Hex format
cell:SetBackgroundColor("#FFFF00");
cell:SetFontColor("#FF0000");

-- RGB format
cell:SetBackgroundColor(RGB(255, 255, 0));
cell:SetFontColor(RGB(255, 0, 0));

-- Theme colors
cell:SetBackgroundColorTheme("Accent1");
cell:SetBackgroundColorTheme("Accent2", 0.5);  -- with tint

-- Indexed colors
cell:SetBackgroundColorIndexed(10);

Available theme colors:

  • "Dark1", "Light1", "Dark2", "Light2"
  • "Accent1", "Accent2", "Accent3", "Accent4", "Accent5", "Accent6"
  • "Hyperlink", "FollowedHyperlink"
  • "Text1", "Text2", "Background1", "Background2"

Alignment

local cell = sheet:Cell(1, 1);

-- Horizontal and vertical alignment
cell:SetAlignment("Center", "Center");

-- Options:
-- Horizontal: "Left", "Center", "Right", "Justify", "General"
-- Vertical: "Top", "Center", "Bottom", "Justify"

-- Text wrapping
cell:SetWrapText(true);  -- text wraps to multiple lines

Borders

local cell = sheet:Cell(1, 1);

-- All sides at once
cell:SetBorder("Thin");

-- Outside border only
cell:SetBorderOutside("Medium");

-- Individual sides
cell:SetBorderTop("Thick");
cell:SetBorderBottom("Thin");
cell:SetBorderLeft("Dashed");
cell:SetBorderRight("Dotted");

-- Styles: "None", "Thin", "Medium", "Thick", "Double", "Dotted", "Dashed"

Number format

local cell = sheet:Cell(1, 1);

cell:SetNumberFormat("#,##0.00");      -- thousands with comma, 2 decimal places
cell:SetNumberFormat("0.00%");         -- percentage
cell:SetNumberFormat("dd.mm.yyyy");    -- date
cell:SetNumberFormat("hh:mm:ss");      -- time

Formula

local cell = sheet:Cell(1, 1);

cell:SetFormula("=SUM(A1:A10)");
cell:SetFormula("=IF(B1>100, \"High\", \"Low\")");

-- Check
if cell:HasFormula() then
    print("Formula:", cell:GetFormula());
end

Clearing content

local cell = sheet:Cell(1, 1);

cell:Clear();           -- clears everything (value + formatting)
cell:ClearContents();   -- clears value only, formatting remains
cell:ClearFormats();    -- clears formatting only, value remains

📐 Working with Ranges

Note: ERange is a shorthand alias for Excel.Range — both can be used interchangeably.

ERange (alias Excel.Range) can be created in several ways:

ERange(2, 1, 10, 5)       -- row1, col1, row2, col2
ERange("A1:E10")           -- string notation
ERange("A1", "E10")        -- two addresses
ERange(cell1, cell2)       -- two Cell objects
-- Set background color for a range
sheet:SetRangeBackgroundColor(ERange(2, 1, 10, 5), "#E0E0E0");

-- RGB variant
sheet:SetRangeBackgroundColor(ERange(2, 1, 10, 5), RGB(224, 224, 224));

-- Bold text for a range
sheet:SetRangeBold(ERange(1, 1, 1, 5), true);

-- Range border
sheet:SetRangeBorder(ERange(1, 1, 10, 5), "Thin");

-- Merge cells
sheet:MergeRange(ERange(1, 1, 1, 3));  -- merges row 1, columns 1-3

📏 Column Width and Row Height

-- Set column width
sheet:SetColumnWidth(1, 25);

-- Auto-fit column width
sheet:AutoFitColumn(1);

-- Get column width
local width = sheet:GetColumnWidth(1);

-- Set row height
sheet:SetRowHeight(1, 30);

-- Get row height
local height = sheet:GetRowHeight(1);

➕➖ Inserting and Deleting Rows/Columns

-- Insert a row above row 5
sheet:InsertRowAbove(5);

-- Delete row 10
sheet:DeleteRow(10);

-- Insert a column before column 3
sheet:InsertColumnBefore(3);

-- Delete column 5
sheet:DeleteColumn(5);

🔍 Searching

All search functions return Cell objects or tables of Cell objects.

Searching the entire sheet

-- Find the first occurrence
local cell = sheet:Find("Total");
if cell then
    print("Found at:", cell:GetAddress());
    cell:SetBold(true);
end

-- Find all occurrences
local cells = sheet:FindAll("Error");
for _, cell in ipairs(cells) do
    cell:SetFontColor("#FF0000");
    print("Error at:", cell:GetAddress());
end

Searching in a range

-- Numeric range
local cell = sheet:FindInRange("Sum", ERange(1, 1, 10, 5));

-- String range
local cell = sheet:FindInRange("Total", ERange("A1:E10"));
local cell = sheet:FindInRange("Total", ERange("A1", "E10"));

-- Two Cell objects forming opposite corners
local cell = sheet:FindInRange("Sum", ERange(cell1, cell2));

-- All occurrences in range
local cells = sheet:FindAllInRange("Error", ERange("A1:Z100"));

Searching in a row or column

-- Find in column 1
local cell = sheet:FindInColumn("Total", 1);
local cell = sheet:FindInColumn("Control", 1, 5);  -- start from row 5

-- Find in row 1
local cell = sheet:FindInRow("Name", 1);
local cell = sheet:FindInRow("Price", 1, 3);  -- start from column 3

-- All occurrences
local cells = sheet:FindAllInColumn("X", 1);
local cells = sheet:FindAllInRow("Header", 1);

📊 Sheet Range

local rows, cols = sheet:GetSheetRange();
print("Sheet has", rows, "rows and", cols, "columns");

-- Iterate all cells
for row = 1, rows do
    for col = 1, cols do
        local value = sheet:Cell(row, col):Get();
        print(row, col, value);
    end;
end;

💾 Saving and Closing

wb:Save();
wb:SaveAs("path/newName.xlsx");
wb:Close();
  • wb:Save() saves all changes in the given Workbook object. (Changes are not reflected until you save.)
  • Overwrites the original .xlsx file.
  • wb:SaveAs() saves all changes to a new file.
  • New workbooks must be saved using SaveAs.
  • wb:Close() closes the open workbook and its sheets and frees memory.

🧰 Excel Module Helper Functions

-- Convert address to row, col
local row, col = Excel.AddressToRowCol("C5");  -- 5, 3

-- Convert row, col to address
local address = Excel.RowColToAddress(5, 3);  -- "C5"

-- Parse a range
local row1, row2, col1, col2 = Excel.ParseStringRange("A1:C10");

-- Column index to letter
local letter = Excel.ColumnIndexToLetter(3);  -- "C"

-- Letter to column index
local index = Excel.LetterToColumnIndex("C");  -- 3

-- Checks
local isCell = Excel.IsCellAddress("C5");     -- true
local isRange = Excel.IsRange("A1:C10");  -- true

-- Expand range to individual addresses
local cells = Excel.ExpandRange("A1:B2");  -- {"A1", "A2", "B1", "B2"}

-- Normalize range (top-left to bottom-right)
local r1, r2, c1, c2 = Excel.NormalizeRange(10, 1, 5, 3);  -- 1, 10, 3, 5

-- Heuristic type from format
local type = Excel.FormatToType("#,##0.00");  -- "number"

-- Create string range from row/col
local range = Excel.RangeToString(1, 10, 1, 5);  -- "A1:E10"

Example 1: Processing data with search

local wb = Workbook("Units.xlsx");
local sheet = wb:Sheet("EngCon");

-- Find the cell with "Control"
local controlCell = sheet:FindInColumn("Control", 1);
if controlCell then
    -- Write a value to the row below it
    local dataCell = sheet:Cell(controlCell.row + 1, 5);
    dataCell:SetValue("Workshop");
    dataCell:SetBackgroundColor("#90EE90");

    print("Unit written:", dataCell:GetValue());
else
    wb:Close();
    error("Control not found.");
end

-- Find all cells with "Error" and highlight them
local errorCells = sheet:FindAll("Error");
for _, cell in ipairs(errorCells) do
    cell:SetFontColor("#FF0000")
        :SetBold(true)
        :SetBackgroundColor("#FFE0E0");
    print("Error at:", cell:GetAddress());
end

wb:Save();
wb:Close();

Example 2: Formatting a table header

local wb = Workbook("Report.xlsx");
local sheet = wb:Sheet("Data");

-- Find the header row
local headerCells = sheet:FindAllInRow("Name", 1);

-- Format the entire header row
for _, cell in ipairs(headerCells) do
    local row = cell.row;

    for col = 1, 10 do
        sheet:Cell(row, col)
            :SetBold(true)
            :SetBackgroundColor("#4472C4")
            :SetFontColor("#FFFFFF")
            :SetAlignment("Center", "Center")
            :SetBorder("Thin");
    end;

    break;  -- Only the first match needed
end;

-- AutoFit all columns
for col = 1, 10 do
    sheet:AutoFitColumn(col);
end;

wb:Save();
wb:Close();

Example 3: Working with Formulas

local cell = sheet:Cell(1, 1);

cell:SetFormula("=SUM(A1:A10)");
cell:SetFormula("=IF(B1>100, \"High\", \"Low\")");

-- Check
if cell:HasFormula() then
    print("Formula:", cell:GetFormula());
end

⚠️ Important note about formulas:

CLua uses ClosedXML, which does not recalculate formulas automatically. Formulas are written to the file, but their results will be calculated when a value is requested (via cell:Get()) or when the file is opened in Excel, LibreOffice, or another program.

sheet:Cell(1, 1):SetValue(10);
sheet:Cell(1, 2):SetValue(20);
sheet:Cell(1, 3):SetFormula("=A1+B1");

local result = sheet:Cell(1, 3):Get();

🧪 Full Function Reference

Workbook functions

Function Description
Workbook(path) Load an existing workbook
NewWorkbook(name) Create a new workbook in memory (optional working name)
WorkbookExists(path) Check if a workbook exists
CloseAllWorkbooks() Close all open workbooks
wb:Sheet(name) Return a sheet object
wb:AddSheet(name) Add a new sheet
wb:DeleteSheet(name) Delete a sheet
wb:RenameSheet(oldName, newName) Rename a sheet
wb:ContainSheet(name) Check if a sheet exists
wb:GetSheetNames() Return a list of all sheets
wb:Save() Save changes (workbook must have a path)
wb:SaveAs(path) Save workbook to a new path
wb:Recalculate() Recalculate all formulas in the workbook
wb:Close() Close the workbook

Sheet functions - Basic operations

Function Description
sheet:Cell(row, col) Create a Cell object
sheet:GetCell(row, col) Read string value (backward compatibility)
sheet:SetCell(row, col, value) Set string value (backward compatibility)
sheet:GetSheetRange() Return row and column count (2 values)
sheet:Recalculate() Recalculate all formulas in the sheet

Sheet functions - Search

All return a Cell object or a table of Cell objects.

Function Description
sheet:Find(text) Find first occurrence in sheet
sheet:FindAll(text) Find all occurrences in sheet
sheet:FindInRange(text, range) Find in range (ERange object)
sheet:FindAllInRange(text, range) Find all in range
sheet:FindInRow(text, row, startCol) Find in row
sheet:FindAllInRow(text, row, startCol) Find all in row
sheet:FindInColumn(text, col, startRow) Find in column
sheet:FindAllInColumn(text, col, startRow) Find all in column

Sheet functions - Columns and rows

Function Description
sheet:SetColumnWidth(col, width) Set column width (Excel units)
sheet:AutoFitColumn(col) Auto-fit column width to content
sheet:GetColumnWidth(col) Get column width
sheet:SetRowHeight(row, height) Set row height (points)
sheet:GetRowHeight(row) Get row height
sheet:DeleteRow(row) Delete a row
sheet:DeleteColumn(col) Delete a column
sheet:InsertRowAbove(row) Insert row above
sheet:InsertColumnBefore(col) Insert column before

Sheet functions - Row formatting

Function Description
sheet:SetRowBackgroundColor(row, hex) Row background color (hex or RGB table)
sheet:SetRowFontColor(row, hex) Row font color (hex or RGB table)
sheet:SetRowBold(row, bool) Row bold

Sheet functions - Column formatting

Function Description
sheet:SetColumnBackgroundColor(col, hex) Column background color (hex or RGB table)
sheet:SetColumnFontColor(col, hex) Column font color (hex or RGB table)
sheet:SetColumnBold(col, bool) Column bold

Sheet functions - Ranges

Function Description
sheet:SetRangeBackgroundColor(range, hex) Range background color (hex or RGB table)
sheet:SetRangeBold(range, bool) Range bold
sheet:SetRangeBorder(range, style) Range border
sheet:MergeRange(range) Merge cells

Sheet functions - Freeze panes

Function Description
sheet:FreezeRows(count) Freeze top rows (header)
sheet:FreezeColumns(count) Freeze left columns
sheet:FreezePanes(row, col) Freeze rows above and columns before
sheet:UnfreezePanes() Unfreeze panes

Cell functions - Values

Function Description
cell:SetValue(value) Set typed value (number/string/bool)
cell:GetValue() Get typed value
cell:SetS(text) Set string value
cell:GetS() Get string value
cell:Set(value) Alias for SetValue
cell:Get() Alias for GetValue
cell:SetFormula(formula) Set formula
cell:GetFormula() Get formula (or nil)
cell:HasFormula() Check for formula
cell:Calculate() Recalculate formula in cell
cell:Clear() Clear everything (value + formatting)
cell:ClearContents() Clear value only
cell:ClearFormats() Clear formatting only

Cell functions - Font formatting

Function Description
cell:SetBold(bool) Bold
cell:SetItalic(bool) Italic
cell:SetUnderline(bool) Underline
cell:SetStrikethrough(bool) Strikethrough
cell:SetFontSize(size) Font size (points)
cell:SetFontName(name) Font name (e.g. "Arial")

Cell functions - Colors

Function Description
cell:SetBackgroundColor(hex) Background color (hex or RGB table)
cell:SetBackgroundColorTheme(name, tint) Theme background color
cell:SetFontColor(hex) Font color (hex or RGB table)
cell:SetFontColorTheme(name, tint) Theme font color

Cell functions - Alignment

Function Description
cell:SetAlignment(h, v) Alignment (h: "Left"/"Center"/"Right", v: "Top"/"Center"/"Bottom")
cell:SetWrapText(bool) Text wrapping

Cell functions - Borders

Function Description
cell:SetBorder(style) All sides (styles: "Thin", "Medium", "Thick", "Double", etc.)
cell:SetBorderOutside(style) Outside border only
cell:SetBorderTop(style) Top border
cell:SetBorderBottom(style) Bottom border
cell:SetBorderLeft(style) Left border
cell:SetBorderRight(style) Right border

Cell functions - Number format

Function Description
cell:SetNumberFormat(format) Format (e.g. "#,##0.00", "dd.mm.yyyy")

Cell functions - Reading formatting

Function Description
cell:GetBold() Check bold
cell:GetItalic() Check italic
cell:GetUnderline() Check underline
cell:GetStrikethrough() Check strikethrough
cell:GetFontSize() Get font size
cell:GetFontName() Get font name
cell:GetBackgroundColor() Get background color (hex)
cell:GetFontColor() Get font color (hex)
cell:GetHorizontalAlignment() Get horizontal alignment
cell:GetVerticalAlignment() Get vertical alignment
cell:GetWrapText() Check text wrapping
cell:GetBorderTop() Get top border
cell:GetBorderBottom() Get bottom border
cell:GetBorderLeft() Get left border
cell:GetBorderRight() Get right border
cell:GetNumberFormat() Get number format
cell:IsMerged() Check if merged
cell:GetMergedRange() Get merged range (e.g. "A1:C1")
cell:GetAddress() Get cell address (e.g. "C5")
cell:GetEx() Get all details (CellEx)

Excel helper functions

Function Description
Excel.AddressToRowCol("C5") Convert address to row, col (returns 2 values)
Excel.RowColToAddress(row, col) Convert row, col to address (e.g. "C5")
Excel.ParseStringRange("A1:C10") Parse range (returns r1, r2, c1, c2)
Excel.ColumnIndexToLetter(col) Column index to letter (3 → "C")
Excel.LetterToColumnIndex("C") Letter to column index ("C" → 3)
Excel.IsCellAddress(str) Check cell address
Excel.IsRange(str) Check range string
Excel.ExpandRange("A1:B2") Expand range to addresses
Excel.NormalizeRange(r1,r2,c1,c2) Normalize range
Excel.RangeToString(r1,r2,c1,c2) Create string range
Excel.FormatToType(format) Heuristic type from format
ERange(...) / Excel.Range(...) Create ExcelRange object

RGB color helpers

local color = RGB(255, 200, 100)  -- {red=255, green=200, blue=100}
local black = BLACK()
local white = WHITE()
local gray  = GRAY(192)

Note: Although it's not strictly necessary to manually close the workbook, it is recommended when working in larger or repeated macros. CLua keeps the workbook in memory, and if you call Workbook("filename.xlsx") again, it will return the existing reference unless it was previously closed. Using Program → Reset CLua will also unload all open workbooks from memory.