Skip to content

Macro Generator

Turn a data table into grandMA macros using your own templates, so repetitive command typing becomes a single export.

Macro Generator - Screenshot

  • Builds macros from a template
    Import a table, apply a template, and get either one macro that holds every row or a separate macro per row.
  • Calculates while it writes
    Put expressions in the template to do maths, pick values with conditions and reformat text, so the table stays simple and the template does the work.
  • Keeps your templates
    Save templates and load them again, so the same job always produces the same result.
  • Covers everything from presets to show setup
    Build rehearsal macros that switch pages and executors per song. Build XYZ preset macros from position data, patch fixtures to DMX addresses, or write cuelists with commands inside them.
  1. Prepare your data:
    • Build your table in Excel or any other program, with one column per field you need.
  2. Import the data:
    • Set the import options first.
      Set the delimiter and the column names on the Settings page. To check the format of your file, open it in a text editor and read the first line.
    • Import File reads a CSV file. Import Clipboard pastes from Excel and similar programs.
      You can also drag a .csv file straight onto the window.
  3. Write the macro template:
    • Create, load and save the template you need.
    • Use placeholders to pull in your data.
      {0} is the current row number.
      {1}, {2}, {3} and so on are the columns.
    • For anything beyond a plain value, write an expression in double braces, such as {{Col3|pad(3)}}.
    • Lines that start with “#” are ignored.
  4. Set the export options:
    • Give the macros a name. For individual macros, put a placeholder in the name to pull in table data.
    • Choose the export mode: one macro with every row, or one macro per row.
  5. Export the macros:
    • Manual import: save the macros to a grandMA2 or grandMA3 folder, then import them on the console.
    • Direct import: send the macros straight to the console. The console asks you to pick the first macro ID. Needs the console's remote interface — see Console Connection.
  • First Row is Header: treats the first row as the column titles, and leaves it out of the macros.
  • Set Name from Filename on Import: fills the export Name field from the name of the imported file.
  • Name: the macro name. Add a placeholder to pull in table data when you export individual macros.
  • Export Mode: one macro holding every row, or one macro per row.
  • Macro Line Wait: the wait time of every macro line, in seconds. The default is 0.01. Leave it empty for Follow.
  • Treat Text after // as Info/Note: everything after // on a template line becomes the info of that macro line instead of part of the command. Write \/\/ if you need a literal //. Inside an expression, // is still the division operator.
  • Columns: the column title. Click it to drop its placeholder into the template at the cursor.
  • Rows: one row per data entry.
  • Eye icon: shows a preview of the macro built from that row.

Placeholders insert a value as it is. An expression can calculate with it, choose between values, and reformat it — so your table can stay simple.

Write an expression in double braces:

Store Cue {{RowIndex + 1}} "{{Col1|upper}}"

Four rules cover most of it:

  • Names are not case-sensitive. {{Col1}}, {{col1}} and {{COL1}} are the same.
  • Spaces inside the braces are fine: {{ Col1 | upper }}.
  • A line can hold as many expressions as you like.
  • An expression that fails, or uses a name the tool does not know, is left in the output untouched.

The app carries the full reference: click the help icon next to the template editor to open Template Syntax, which lists every operator and filter with a worked example.

Write thisMeaning
Col1…ColNthe columns of the current row
RowIndexthe row number, starting at 0 — add 1 to count from 1
Col0the same as RowIndex
a header namethe column with that header, for example {{CueName}}

Header names become identifiers by keeping only letters, digits and underscores, so “Cue Name” becomes CueName and “X-Pos” becomes XPos. A header starting with a digit gets an underscore, so “1st” becomes _1st. Headers are skipped when they clash with Col1…ColN or RowIndex, or when an earlier header already used the name.

Hover a column button above the table to see the exact names for that column.

Cells that look like numbers — 5, -3, 1.25 — are treated as numbers, so maths and comparisons work on them.

Cells like 001 or 1.10 keep their text and are inserted exactly as typed. Maths and comparisons still read them as numbers.

Write text in double or single quotes: "Cue" or 'Cue'. The case is kept as written.

The following examples assume a first row with the headers “Cue Name”, “Value”, “Number” and “Note”, holding intro song, 12.345, 007 and an empty cell.

OperatorWhat it doesExampleResult
+ - * /add, subtract, multiply, divide{{Col3 + 1}}8
+joins text when one side is not a number{{Col1 + "!"}}intro song!
//division rounded down{{7 // 2}}3
%remainder{{7 % 3}}1
^power{{2 ^ 10}}1024
== != < > <= >=comparison{{Col3 == 7}}true
&& || !and, or, not{{Col2 > 10 && !(Col3 > 10)}}true
intext contains, or list contains{{"song" in Col1}}true
( )grouping{{(Col3 + 1) * 2}}16
Write thisWhat it doesExampleResult
cond ? a : ba when the condition is true, otherwise b{{Col2 > 100 ? "High" : "Low"}}Low
value ? value : ba fallback for an empty cell{{Col4 ? Col4 : "Unnamed"}}Unnamed
value ?: bthe short form of that fallback{{Col4 ?: "Unnamed"}}Unnamed

Conditions can be combined (cond1 || cond2 ? a : b) and nested (cond ? a : cond ? b : c).

Apply a transformation with a pipe: value|name, or value|name(arguments). Chain as many as you need — {{Col1|trim|upper}} — and the names are not case-sensitive.

TransformationWhat it does
upperupper case
lowerlower case
capitalizeupper-cases the first character
trimremoves spaces at both ends
pad(length, char = "0")pads on the left to that length
padEnd(length, char = " ")pads on the right to that length
round(decimals = 0)rounds to that many decimals
fixed(decimals = 0)rounds and keeps trailing zeros
intcuts off the decimals
floorrounds down
ceilrounds up
absremoves the sign
replace(search, replacement)replaces every occurrence
default(fallback)a fallback for an empty value
prefix(text)puts text in front
suffix(text)appends text
lenthe number of characters

{0} is the row number starting at 0, {1} the first column, {2} the second, and so on. Nothing about them changed, and you can mix both styles in one template.

They are replaced after the expressions. A single-brace name such as {Col1} is not recognised — use double braces for names.

  • Save a template: click the save icon in the template editor.
  • Load a template: pick it from the Template dropdown.
  • Delete a template: click the delete icon next to the dropdown.

Three settings can live in the template itself:

Write this at the start of a lineWhat it does
# followed by a name (first line)names the template
# Name = ...sets the export name
# Mode = singleexports one macro holding every row
# Mode = individualexports one macro per row

Sometimes you only need a run of numbers instead of imported data.

  1. Click Generate Table.
  2. Enter the First Item and Last Item numbers. Reverse the order if you need to.
  3. Enter the Item Text. Use {0} for the current row number.