How and Where to Use Enumerators with JavaScript via C++
An enumerator is an object that provides the ability to traverse a container or a collection. Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection, whereas an array is an interface that defines a single method enumerator which returns an IEnumerator interface; this, in turn, allows read‑only access to a collection.
Aspose.Cells APIs provide a bunch of enumerators; however, this article mainly discusses the three types listed below.
- Cells Enumerator
- Rows Enumerator
- Columns Enumerator
How to use Enumerators
Cells Enumerator
There are various ways to access the Cells Enumerator, and one can use any of these methods based on the application requirements. Here are the methods that return the cells enumerator.
All of the above‑mentioned methods return an enumerator that allows traversing the collection of cells which have been initialized.
The following code example demonstrates the implementation of the IEnumerator interface for a Cells collection.
<!DOCTYPE html>
<html>
<head>
<title>Aspose.Cells Example</title>
</head>
<body>
<h1>Aspose.Cells Example - Read Cell Values</h1>
<input type="file" id="fileInput" accept=".xls,.xlsx,.csv" />
<button id="runExample">Run Example</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook, SaveFormat } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
if (!fileInput.files.length) {
document.getElementById('result').innerHTML = '<p style="color: red;">Please select an Excel file.</p>';
return;
}
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Instantiating a Workbook object by opening the uploaded Excel file
const workbook = new Workbook(new Uint8Array(arrayBuffer));
// Access the first worksheet
const worksheet = workbook.worksheets.get(0);
const resultLines = [];
// Iterate over all cells in the worksheet
const cellsEnumerator = worksheet.cells.getEnumerator();
for (const cell of cellsEnumerator) {
console.log(`${cell.name} ${cell.value}`);
resultLines.push(`${cell.name} ${cell.value}`);
}
// Iterate over the first row's cells
const firstRowEnumerator = worksheet.cells.rows.get(0).getEnumerator();
for (const cell of firstRowEnumerator) {
console.log(`${cell.name} ${cell.value}`);
resultLines.push(`${cell.name} ${cell.value}`);
}
// Iterate over a specific range A1:B10
const rangeEnumerator = worksheet.cells.createRange("A1:B10").getEnumerator();
for (const cell of rangeEnumerator) {
console.log(`${cell.name} ${cell.value}`);
resultLines.push(`${cell.name} ${cell.value}`);
}
document.getElementById('result').innerHTML = `<pre>${resultLines.join('\n')}</pre>`;
});
</script>
</html>
Rows Enumerator
The Rows Enumerator can be accessed while using the RowCollection.enumerator method. The following code example demonstrates the implementation of the IEnumerator interface for RowCollection.
<!DOCTYPE html>
<html>
<head>
<title>Aspose.Cells Example</title>
</head>
<body>
<h1>Aspose.Cells Example - List Row Indexes</h1>
<input type="file" id="fileInput" accept=".xls,.xlsx,.csv" />
<button id="runExample">Run Example</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook, SaveFormat } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
if (!fileInput.files.length) {
document.getElementById('result').innerHTML = '<p style="color: red;">Please select an Excel file.</p>';
return;
}
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Instantiate Workbook from uploaded file
const workbook = new Workbook(new Uint8Array(arrayBuffer));
// Get RowCollection and iterate using index
const rows = workbook.worksheets.get(0).cells.rows;
const rowCount = rows.count;
// Traverse rows in the collection and display indexes
let output = '<p>Row indexes:</p><ul>';
for (let i = 0; i < rowCount; i++) {
const row = rows.get(i);
output += `<li>${row.index}</li>`;
console.log(row.index);
}
output += '</ul>';
document.getElementById('result').innerHTML = output;
});
</script>
</html>
Columns Enumerator
The Columns Enumerator can be accessed while using the ColumnCollection.enumerator method. The following code example demonstrates the implementation of the IEnumerator interface for ColumnCollection.
<!DOCTYPE html>
<html>
<head>
<title>Aspose.Cells Example</title>
</head>
<body>
<h1>Read Columns Indexes Example</h1>
<input type="file" id="fileInput" accept=".xls,.xlsx,.csv" />
<button id="runExample">Run Example</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook, SaveFormat } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
if (!fileInput.files.length) {
document.getElementById('result').innerHTML = '<p style="color: red;">Please select an Excel file.</p>';
return;
}
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Instantiating a Workbook object from uploaded file
const workbook = new Workbook(new Uint8Array(arrayBuffer));
// Get columns collection from first worksheet
const columns = workbook.worksheets.get(0).cells.columns;
// Traverse columns using index
const count = columns.count;
let html = '<p>Columns indexes:</p><ul>';
for (let i = 0; i < count; i++) {
const col = columns.get(i);
html += `<li>${col.index}</li>`;
console.log(col.index);
}
html += '</ul>';
document.getElementById('result').innerHTML = html;
});
</script>
</html>
Where to use Enumerators
To discuss the advantages of using enumerators, let’s take a real‑time example.
Scenario
An application requirement is to traverse all cells in a given Worksheet to read their values. Several approaches can implement this goal; a few are demonstrated below.
Using Display Range
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Aspose.Cells Example</title>
</head>
<body>
<h1>Read Max Display Range Example</h1>
<input type="file" id="fileInput" accept=".xls,.xlsx,.csv" />
<button id="runExample">Run Example</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook, SaveFormat } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
const resultDiv = document.getElementById('result');
resultDiv.innerHTML = '';
if (!fileInput.files.length) {
resultDiv.innerHTML = '<p style="color: red;">Please select an Excel file.</p>';
return;
}
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Instantiating a Workbook object by opening the Excel file from the uploaded file
const workbook = new Workbook(new Uint8Array(arrayBuffer));
// Get Cells collection of first worksheet
const cells = workbook.worksheets.get(0).cells;
// Get the MaxDisplayRange
const displayRange = cells.maxDisplayRange;
// Loop over all cells in the MaxDisplayRange
let outputLines = [];
for (let row = displayRange.firstRow; row < displayRange.rowCount; row++) {
for (let col = displayRange.firstColumn; col < displayRange.columnCount; col++) {
// Read the Cell value (stringValue property)
const cell = displayRange.get(row, col);
outputLines.push(cell.stringValue);
console.log(cell.stringValue);
}
}
resultDiv.innerHTML = '<pre>' + outputLines.join('\n') + '</pre>';
});
</script>
</html>
Using MaxDataRow & MaxDataColumn
<!DOCTYPE html>
<html>
<head>
<title>Aspose.Cells Example</title>
<meta charset="utf-8" />
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
#result { margin-top: 15px; max-height: 400px; overflow: auto; border: 1px solid #ddd; padding: 10px; }
.cell-value { padding: 2px 0; border-bottom: 1px dashed #eee; }
.error { color: red; }
</style>
</head>
<body>
<h1>Read Cells Example</h1>
<input type="file" id="fileInput" accept=".xlsx,.xls,.csv" />
<button id="runExample">Run Example</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
function escapeHtml(text) {
if (text === null || text === undefined) return '';
return String(text)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
const resultDiv = document.getElementById('result');
resultDiv.innerHTML = '';
if (!fileInput.files.length) {
resultDiv.innerHTML = '<p class="error">Please select an Excel file.</p>';
return;
}
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Instantiating a Workbook object by opening the Excel file from the uploaded file
const workbook = new Workbook(new Uint8Array(arrayBuffer));
// Get Cells collection of first worksheet
const cells2 = workbook.worksheets.get(0).cells;
const maxDataRow = cells2.maxDataRow;
const maxDataColumn = cells2.maxDataColumn;
const outputLines = [];
// Loop over all cells
for (let row = 0; row <= maxDataRow; row++) {
for (let col = 0; col <= maxDataColumn; col++) {
// Read the Cell value
const currentCell = cells2.checkCell(row, col);
if (currentCell) {
const cellText = currentCell.stringValue;
outputLines.push('<div class="cell-value">' + escapeHtml(cellText) + '</div>');
console.log(cellText);
}
}
}
if (outputLines.length === 0) {
resultDiv.innerHTML = '<p>No cell values found.</p>';
} else {
resultDiv.innerHTML = outputLines.join('');
}
});
</script>
</html>
As you can observe, both of the above‑mentioned approaches use more or less similar logic, that is, looping over all cells in the collection to read the cell values. This could be problematic for a number of reasons, as discussed below.
- APIs such as maxRow, maxDataRow, maxColumn, maxDataColumn, and maxDisplayRange require extra time to gather the corresponding statistics. When the data matrix (rows × columns) is large, using these APIs can impose a performance penalty.
- In most cases, not all cells in a given range are instantiated. Checking every cell in the matrix is therefore not as efficient as checking only the instantiated cells.
- Accessing a cell in a loop as
Cells[row, column]will cause all cell objects in the range to be instantiated, which may eventually lead to anOutOfMemoryException.
Conclusion
Based on the above‑mentioned facts, the following are scenarios where enumerators should be used.
- Read‑only access to the cell collection is required; i.e., the requirement is only to inspect the cells.
- A large number of cells need to be traversed.
- Only initialized cells/rows/columns should be traversed.