Fastest Way to Populate an Excel File in IronXL
When you build large spreadsheets in IronXL, the data-loading method you pick has a big effect on how long generation takes. The benchmark below compares three common approaches against the same 20,000-row by 55-column dataset.
Benchmark
Every test populates identical data and writes the result to disk as an .xlsx file. Both duration (in seconds) and the resulting file size were recorded.
- Adding data cell by cell: ~13 sec, 3094 KB
- Loading from
DataTable: ~3.4 sec, 3094 KB - Loading from CSV: ~4.1 sec, 3094 KB
All three produce the same file size. What changes dramatically is the time to generate it.
The Methods
Option 1: Adding Data Cell by Cell
This approach assigns a value to each individual cell through nested loops. It is the slowest of the three.
string[] fruits = { "Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe",
"Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit",
"Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango",
"Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew",
"Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak",
"Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit",
"Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon",
"cherry", "nectarine", "Butternut squash"};
var workbook = WorkBook.Create(ExcelFileFormat.XLSX);
var worksheet = workbook.CreateWorkSheet("Fruits");
var columnsTitles = GetExcelCellLetters(fruits.Length);
for (int col = 0; col < columnsTitles.Count; col++)
{
string columnLetter = columnsTitles[col]; // To avoid interpolation that can cause performance issues in large loops because it build string objects in every loop
for (int row = 1; row <= 20000; row++)
{
worksheet[columnLetter + row].Value = fruits[col];
//worksheet.Rows[row].Columns[columnLetter].Value.ToString();
}
}
workbook.SaveAs("C:\\Temp\\ManualCell-by-CellAssignment.xlsx");
private static List<string> GetExcelCellLetters(int iMaxNum)
{
string[] alphabet = { string.Empty, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
IEnumerable<string> lst = (from c1 in alphabet
from c2 in alphabet
from c3 in alphabet.Skip(1)
where c1 == string.Empty || c2 != string.Empty
select c1 + c2 + c3).Take(iMaxNum);
return lst.ToList();
}Dim fruits() As String = {"Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe", "Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit", "Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango", "Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew", "Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak", "Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit", "Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon", "cherry", "nectarine", "Butternut squash"}
Dim workbook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim worksheet = workbook.CreateWorkSheet("Fruits")
Dim columnsTitles = GetExcelCellLetters(fruits.Length)
For col As Integer = 0 To columnsTitles.Count - 1
Dim columnLetter As String = columnsTitles(col)
For row As Integer = 1 To 20000
worksheet(columnLetter & row).Value = fruits(col)
Next
Next
workbook.SaveAs("C:\Temp\ManualCell-by-CellAssignment.xlsx")
Private Shared Function GetExcelCellLetters(ByVal iMaxNum As Integer) As List(Of String)
Dim alphabet() As String = {String.Empty, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
Dim lst As IEnumerable(Of String) = (From c1 In alphabet From c2 In alphabet From c3 In alphabet.Skip(1) Where c1 = String.Empty OrElse c2 <> String.Empty Select c1 & c2 & c3).Take(iMaxNum)
Return lst.ToList()
End FunctionDim fruits() As String = {"Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe", "Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit", "Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango", "Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew", "Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak", "Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit", "Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon", "cherry", "nectarine", "Butternut squash"}
Dim workbook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim worksheet = workbook.CreateWorkSheet("Fruits")
Dim columnsTitles = GetExcelCellLetters(fruits.Length)
For col As Integer = 0 To columnsTitles.Count - 1
Dim columnLetter As String = columnsTitles(col)
For row As Integer = 1 To 20000
worksheet(columnLetter & row).Value = fruits(col)
Next
Next
workbook.SaveAs("C:\Temp\ManualCell-by-CellAssignment.xlsx")
Private Shared Function GetExcelCellLetters(ByVal iMaxNum As Integer) As List(Of String)
Dim alphabet() As String = {String.Empty, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
Dim lst As IEnumerable(Of String) = (From c1 In alphabet From c2 In alphabet From c3 In alphabet.Skip(1) Where c1 = String.Empty OrElse c2 <> String.Empty Select c1 & c2 & c3).Take(iMaxNum)
Return lst.ToList()
End FunctionPrecomputing columnLetter outside the inner loop avoids string interpolation on every iteration, which otherwise allocates new strings millions of times over.

Option 2: Loading from a DataTable
Build a DataTable in memory, then hand it to IronXL in one call with LoadWorkSheet. This is one of the two fastest options, and from v2026.10.1 it is as fast as CSV or faster, and far quicker than manual cell insertion.
string[] fruits = { "Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe",
"Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit",
"Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango",
"Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew",
"Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak",
"Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit",
"Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon",
"cherry", "nectarine", "Butternut squash"};
var workbook = WorkBook.Create(ExcelFileFormat.XLSX);
DataTable table = new DataTable("Fruits");
foreach (string fruitName in fruits)
{
table.Columns.Add(fruitName);
}
int rowCount = 20000;
for (int i = 0; i < rowCount; i++)
{
table.Rows.Add(fruits);
}
workbook.LoadWorkSheet(table);
workbook.SaveAs("C:\\Temp\\LoadDataTableDirectly.xlsx");string[] fruits = { "Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe",
"Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit",
"Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango",
"Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew",
"Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak",
"Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit",
"Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon",
"cherry", "nectarine", "Butternut squash"};
var workbook = WorkBook.Create(ExcelFileFormat.XLSX);
DataTable table = new DataTable("Fruits");
foreach (string fruitName in fruits)
{
table.Columns.Add(fruitName);
}
int rowCount = 20000;
for (int i = 0; i < rowCount; i++)
{
table.Rows.Add(fruits);
}
workbook.LoadWorkSheet(table);
workbook.SaveAs("C:\\Temp\\LoadDataTableDirectly.xlsx");Dim fruits As String() = {"Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe", "Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit", "Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango", "Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew", "Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak", "Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit", "Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon", "cherry", "nectarine", "Butternut squash"}
Dim workbook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim table As New DataTable("Fruits")
For Each fruitName As String In fruits
table.Columns.Add(fruitName)
Next
Dim rowCount As Integer = 20000
For i As Integer = 0 To rowCount - 1
table.Rows.Add(fruits)
Next
workbook.LoadWorkSheet(table)
workbook.SaveAs("C:\Temp\LoadDataTableDirectly.xlsx")Dim fruits As String() = {"Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe", "Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit", "Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango", "Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew", "Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak", "Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit", "Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon", "cherry", "nectarine", "Butternut squash"}
Dim workbook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim table As New DataTable("Fruits")
For Each fruitName As String In fruits
table.Columns.Add(fruitName)
Next
Dim rowCount As Integer = 20000
For i As Integer = 0 To rowCount - 1
table.Rows.Add(fruits)
Next
workbook.LoadWorkSheet(table)
workbook.SaveAs("C:\Temp\LoadDataTableDirectly.xlsx")LoadWorkSheet(table) writes the entire table at once instead of touching cells individually, which is where the speedup comes from.

Option 3: Loading from CSV
Write the data to a delimited .csv file, then read it back with LoadCSV. This is one of the two fastest options and the natural choice when your data is already flat and delimited.
string[] fruits = { "Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe",
"Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit",
"Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango",
"Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew",
"Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak",
"Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit",
"Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon",
"cherry", "nectarine", "Butternut squash"};
var sb = new StringBuilder();
// Step 1: Add header row
sb.AppendLine(string.Join(",", fruits));
// Step 2: Add 20,000 identical rows
string rowData = string.Join(",", fruits); // same as headers
for (int i = 1; i < 20000; i++)
{
sb.AppendLine(rowData);
}
File.WriteAllText("C:\\Temp\\csvfile.csv", sb.ToString(), Encoding.UTF8);
var workbook = WorkBook.LoadCSV("C:\\Temp\\csvfile.csv");
workbook.SaveAs("C:\\Temp\\LoadFromCSV.xlsx");string[] fruits = { "Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe",
"Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit",
"Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango",
"Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew",
"Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak",
"Cherimoya", "Buddha's Hand", "Citron", "Finger Lime", "Kumquat", "Pomelo", "Tangelo", "Ugli Fruit",
"Galia Melon", "Kiwano (Horned Melon)", "Mouse Melon", "Muskmelon",
"cherry", "nectarine", "Butternut squash"};
var sb = new StringBuilder();
// Step 1: Add header row
sb.AppendLine(string.Join(",", fruits));
// Step 2: Add 20,000 identical rows
string rowData = string.Join(",", fruits); // same as headers
for (int i = 1; i < 20000; i++)
{
sb.AppendLine(rowData);
}
File.WriteAllText("C:\\Temp\\csvfile.csv", sb.ToString(), Encoding.UTF8);
var workbook = WorkBook.LoadCSV("C:\\Temp\\csvfile.csv");
workbook.SaveAs("C:\\Temp\\LoadFromCSV.xlsx");Dim fruits As String() = {"Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe", "Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit", "Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango", "Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew", "Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak", "Cher...
Dim sb = New StringBuilder()
' Step 1: Add header row
sb.AppendLine(String.Join(",", fruits))
' Step 2: Add 20,000 identical rows
Dim rowData As String = String.Join(",", fruits) ' same as headers
For i As Integer = 1 To 19999
sb.AppendLine(rowData)
Next
File.WriteAllText("C:\Temp\csvfile.csv", sb.ToString(), Encoding.UTF8)
Dim workbook = WorkBook.LoadCSV("C:\Temp\csvfile.csv")
workbook.SaveAs("C:\Temp\LoadFromCSV.xlsx")Dim fruits As String() = {"Apples", "Apricot", "Banana", "Blackberry", "Blueberry", "Boysenberry", "Canary Melon", "Cantaloupe", "Currants", "Dates (tree dried only) Dragon Fruit", "Durian (purchase cut) Figs", "Gooseberry", "Grapes", "Grapefruit", "Lemon", "Lime", "Loganberry", "Longan", "Loquat", "Lychee", "Mandarin", "Mango", "Blood Orange", "Papaya", "Passion Fruit", "Peach", "Pear", "Persimmon", "Pineapple", "Plum", "Honeydew", "Rambutan", "Starfruit", "Tamarind", "Yuzu", "Açaí", "Abiu", "Ackee", "Breadfruit", "Cempedak", "Cher...
Dim sb = New StringBuilder()
' Step 1: Add header row
sb.AppendLine(String.Join(",", fruits))
' Step 2: Add 20,000 identical rows
Dim rowData As String = String.Join(",", fruits) ' same as headers
For i As Integer = 1 To 19999
sb.AppendLine(rowData)
Next
File.WriteAllText("C:\Temp\csvfile.csv", sb.ToString(), Encoding.UTF8)
Dim workbook = WorkBook.LoadCSV("C:\Temp\csvfile.csv")
workbook.SaveAs("C:\Temp\LoadFromCSV.xlsx")LoadCSV parses the delimited file in bulk, so the cost is in writing and reading the intermediate .csv rather than per-cell assignment.

Which to Choose
- For data already on disk: read it with CSV when the source is a flat, delimited file.
- For data already in memory: load a
DataTable; fromv2026.10.1it is the fastest or joint-fastest option. - For per-cell logic or styling: reach for cell-by-cell writing only then, since it is the slowest path.
Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.