How to Create a Multi-Column Menu in Batch Script
Standard Batch menus are usually a single vertical list of options. While functional, this wastes screen space and can force a user to scroll up to see all the choices. A Multi-Column Menu presents options in side-by-side columns, creating a more compact and professional "dashboard" feel for your admin tools.
In this guide, we will demonstrate how to align your menu choices into columns using arithmetic and string padding.
The Strategy: Tabular Alignment
To create a two-column menu, we treat each row as a pair of options. We print the first option, pad it with spaces to a fixed width, and then print the second option on the same line.
Method 1: The Hardcoded Grid (Fastest)
If your menu options rarely change, you can manually build the columns using a fixed layout.
Implementation Script
@echo off
setlocal enabledelayedexpansion
:menu
cls
echo ======================================================
echo SYSTEM MANAGEMENT CONSOLE
echo ======================================================
echo.
echo [1] Start Service [5] View Log
echo [2] Stop Service [6] Export Data
echo [3] Update Patch [7] Backup Files
echo [4] System Audit [8] Exit
echo.
echo ======================================================
set "choice="
set /p "choice=Select an option (1-8): "
if "!choice!"=="1" (
echo Starting Service...
pause
goto :menu
)
if "!choice!"=="2" (
echo Stopping Service...
pause
goto :menu
)
if "!choice!"=="3" (
echo Updating Patch...
pause
goto :menu
)
if "!choice!"=="4" (
echo Running System Audit...
pause
goto :menu
)
if "!choice!"=="5" (
echo Viewing Log...
pause
goto :menu
)
if "!choice!"=="6" (
echo Exporting Data...
pause
goto :menu
)
if "!choice!"=="7" (
echo Backing up Files...
pause
goto :menu
)
if "!choice!"=="8" (
echo Exiting...
endlocal
exit /b
)
:: Handle invalid input
echo.
echo [ERROR] Invalid option: "!choice!". Please enter a number from 1 to 8.
pause
goto :menu
Method 2: Dynamic Multi-Column List
If you are generating a list of options from a set of files or dynamic data, you need a way to wrap the output every N columns.
The Wrapping Logic Script
@echo off
setlocal enabledelayedexpansion
set "pad= "
set "colWidth=20"
set "numCols=2"
set "colCount=0"
echo AVAILABLE PROJECTS (!numCols! Columns)
echo ------------------------------------------
:: Loop through files and display in columns
for %%F in (*.txt) do (
set /a "colCount+=1"
:: Format: pad the filename to a fixed width
set "name=%%~nF!pad!"
set "entry=[!colCount!] !name:~0,%colWidth%!"
:: Print without a newline
<nul set /p "=!entry!"
:: Every numCols items, start a new line
set /a "mod=colCount %% numCols"
if !mod! equ 0 echo.
)
:: If the last row was incomplete, add a final newline
set /a "mod=colCount %% numCols"
if !mod! neq 0 echo.
echo ------------------------------------------
if !colCount! equ 0 (
echo No .txt files found in the current directory.
) else (
echo Total: !colCount! items.
)
endlocal
pause
Key Logic:
set "entry=[!colCount!] !name:~0,%colWidth%!": Each entry is padded to exactlycolWidthcharacters so that the second column always starts at the same position regardless of filename length.set /a "mod=colCount %% numCols": The modulo operator determines when a row is full. When the count is evenly divisible by the number of columns, we print a newline to start the next row.<nul set /p "=!entry!": Prints the entry without advancing to a new line, allowing multiple columns to appear on the same row.
Method 3: Configurable N-Column Menu
For maximum flexibility, you can make both the data and the column count configurable. This approach works well for scripts that present varying numbers of options.
@echo off
setlocal enabledelayedexpansion
:: Configuration
set "numCols=3"
set "colWidth=18"
set "pad= "
:: Define menu items
set "item1=Users"
set "item2=Groups"
set "item3=Policies"
set "item4=Services"
set "item5=Firewall"
set "item6=Updates"
set "item7=Backup"
set "item8=Restore"
set "item9=Logs"
set "itemCount=9"
echo ======================================================
echo ADMIN DASHBOARD (%numCols% Columns)
echo ======================================================
echo.
for /L %%i in (1,1,%itemCount%) do (
set "label=!item%%i!!pad!"
set "entry=[%%i] !label:~0,%colWidth%!"
<nul set /p "=!entry!"
set /a "mod=%%i %% numCols"
if !mod! equ 0 echo.
)
:: Handle trailing incomplete row
set /a "mod=itemCount %% numCols"
if !mod! neq 0 echo.
echo.
echo ======================================================
set "choice="
set /p "choice=Select an option (1-%itemCount%): "
:: Validate input is a number in range
set "valid="
for /L %%i in (1,1,%itemCount%) do (
if "!choice!"=="%%i" set "valid=1"
)
if not defined valid (
echo [ERROR] Invalid option.
) else (
echo You selected: !item%choice%!
)
endlocal
pause
Best Practices for Multi-Column Menus
- Logical Grouping: Place related tasks in the same column (e.g., Column 1 for "File Operations," Column 2 for "System Status").
- Consistent Width: Use the padding technique (
!var:~0,N!) to ensure the start of each column is perfectly aligned. Jagged columns look amateurish. - Keyboard Shortcuts: Use numbers (1, 2, 3...) or distinct single letters (S, B, X...) that correspond to the items. Don't force the user to type out full words.
- Handle Invalid Input: Always validate the user's choice and display a clear error message for unrecognized input, rather than silently doing nothing or crashing.
- Handle Trailing Rows: When the total number of items is not evenly divisible by the column count, the last row will be incomplete. Always check and print a final newline after the loop so subsequent output is not appended to the last partial row.
Conclusion
Multi-column menus transform a basic "script" into a polished "application." They efficiently use the available terminal real estate and provide a cleaner, dashboard-like overview of all available commands. By using simple arithmetic for row-wrapping and string padding for alignment, you can create professional interfaces that are both aesthetically pleasing and highly functional.