The Compare/SpreadSheets extension compares two Excel files from inside a Virtuoso journey.
This is useful when your test needs to compare a master spreadsheet with another spreadsheet and identify differences in cell count or cell content.
Parameters:
-
masterUrlrequired, the URL of the master Excel file; -
otherUrlrequired, the URL of the Excel file to compare against the master file; -
masterSheetNameoptional, the sheet name to compare in the master file. The current source defaults toData; -
otherSheetNameoptional, the sheet name to compare in the other file. The current source defaults toData.
Note: The current source uses the sheet name Data when reading both files. Make sure both workbooks contain a sheet named Data.
NLP usage
Use the extension in a journey by calling Compare/SpreadSheets with the execute command. Pass each value to the matching extension input using as inputName.
Note: The extension returns an array of difference messages. If no differences are found, it returns an empty array.
To compare two Excel files:
execute "Compare/SpreadSheets" using "https://example.com/master.xlsx" as masterUrl, "https://example.com/other.xlsx" as otherUrl, "Data" as masterSheetName, "Data" as otherSheetName returning $differencesYou can also use Virtuoso variables to make the same step reusable across different spreadsheet URLs:
execute "Compare/SpreadSheets" using "$masterUrl" as masterUrl, "$otherUrl" as otherUrl, "$masterSheetName" as masterSheetName, "$otherSheetName" as otherSheetName returning $differencesExample setup using variables before calling the extension:
store value "https://example.com/master.xlsx" in $masterUrl
store value "https://example.com/other.xlsx" in $otherUrl
store value "Data" in $masterSheetName
store value "Data" in $otherSheetName
execute "Compare/SpreadSheets" using "$masterUrl" as masterUrl, "$otherUrl" as otherUrl, "$masterSheetName" as masterSheetName, "$otherSheetName" as otherSheetName returning $differencesExample response when differences are found:
["OtherFile cell A1 with value: Updated differs from Master with value: Original"]This extension requires the following resource:
The extension should be configured as:
- Run asynchronously: Yes
- Scope: Global
Limitation: This extension compares cell values from the selected sheets. It does not compare formulas, styles, merged cells, charts, hidden rows, workbook metadata, or formatting differences.
Add the extension to your Virtuoso instance
Select the domain that matches your Virtuoso account.
View source
Last updated: 22/05/2026
Resources:
const errors = [];
async function getFile(fileUrl) {
const data = await (await fetch(fileUrl)).arrayBuffer();
return data;
}
function checkCellCount(masterData, fileData) {
if (!masterData || !fileData) {
throw new Error('Master or file data is undefined/null');
}
const masterKeys = Object.keys(masterData);
const fileKeys = Object.keys(fileData);
for (const key of masterKeys) {
if (!masterData[key]) {
throw new Error('Missing data for key: ' + key);
}
if (key.startsWith("!")) continue;
if (!fileKeys.find((element) => key == element)) {
console.log("Master " + key);
console.log(masterData[key]["v"]);
errors.push(`Master as more cells than otherFile => cell ${key} with value: ${masterData[key]["v"]}`);
}
}
for (const key of fileKeys) {
if (!fileData[key]) {
throw new Error('Missing data for key: ' + key);
}
if (key.startsWith("!")) continue;
if (!masterKeys.find((element) => key == element)) {
errors.push(`OtherFile as more cells than master => cell ${key} with value: ${fileData[key]["v"]}`);
}
}
}
function checkCellContent(masterData, fileData) {
if (!masterData || !fileData) {
throw new Error('Master or file data is undefined/null');
}
const masterKeys = Object.keys(masterData);
for (const key of masterKeys) {
if (!masterData[key]) {
throw new Error('Missing data for key: ' + key);
}
if (!fileData[key]) {
throw new Error('Missing data for key: ' + key);
}
if (key.startsWith("!")) continue;
if (fileData[key]["v"] != masterData[key]["v"]) {
errors.push(`OtherFile cell ${key} with value: ${fileData[key]["v"]} differs from Master with value: ${masterData[key]["v"]}`);
}
}
}
async function main() {
//const masterUrl = masterUrl;
//const otherUrl = otherUrl;
const masterFile = await getFile(masterUrl);
const master = XLSX.read(masterFile, { type: 'buffer' });
if (!master) {
throw new Error('Failed to parse master file');
}
const masterSheetName = 'Data' || otherSheetName;
const masterSheet = master.Sheets[masterSheetName];
if (!masterSheet) {
throw new Error('Master missing ' + masterSheetName + ' sheet');
}
const masterData = masterSheet;
const otherFile = await getFile(otherUrl);
const other = XLSX.read(otherFile, { type: 'buffer' });
if (!other) {
throw new Error('Failed to parse other file');
}
const otherSheetName = 'Data' || masterSheetName;
const fileData = other.Sheets[otherSheetName];
if (!fileData) {
throw new Error('File missing Data sheet');
}
checkCellCount(masterData, fileData);
checkCellContent(masterData, fileData);
return errors;
}
main().then(done).catch(doneError);
Comments
0 comments
Please sign in to leave a comment.