Okay, let's break down the issues with the script and how to fix it to meet your requirements.
Understanding the Problems
Corrected Script
Here's the modified script that addresses the core problem of syncing only columns A-D while preserving the row order from the source sort:
/**
* Sorts the Source sheet (rows 5+) by Column B then C,
* and updates columns A-D in the Destination sheet(s) to match the sorted order,
* leaving columns E onwards in the destination sheets untouched.
*
* Designed to be run manually from a menu or potentially via a trigger.
*/
function menuTriggeredSortAndSyncSpecificColumns() {
var sourceSheetId = "sssssssssssssssssssssss"; // <--- Replace with your ACTUAL Source spreadsheet ID
var sourceSheetName = "Source"; // Source sheet name
var destSheetIds = [
"ddddddddddddddddddddddddddddddd", // <--- Replace with your ACTUAL Destination spreadsheet ID(s)
// Add more destination sheet IDs here if needed
];
var destSheetName = "Sheet1"; // Destination sheet name (must be the same in all destination spreadsheets)
var startRow = 5; // Start row for sorting and syncing
var numColsToSync = 4; // Sync columns A, B, C, D (1 to 4)
try {
var sourceSpreadsheet = SpreadsheetApp.openById(sourceSheetId);
var sourceSheet = sourceSpreadsheet.getSheetByName(sourceSheetName);
if (!sourceSheet) {
SpreadsheetApp.getUi().alert("Source sheet '" + sourceSheetName + "' not found in spreadsheet ID: " + sourceSheetId);
return;
}
// Get the full data range starting from startRow in the source sheet
var sourceLastRow = sourceSheet.getLastRow();
if (sourceLastRow < startRow) {
Logger.log("No data to sort or sync starting from row " + startRow + " in the source sheet.");
// Optional: You might want to clear A:D in destination sheets if source is empty
// clearDestinationColumns(destSheetIds, destSheetName, startRow, numColsToSync);
SpreadsheetApp.getUi().alert("No data found in the source sheet starting from row " + startRow + ".");
return;
}
var sortRange = sourceSheet.getRange(startRow, 1, sourceLastRow - startRow + 1, sourceSheet.getLastColumn());
// --- Optional Protection ---
// If column C contains formulas or requires strict protection during the sort, keep this.
// Otherwise, you can remove the protection block for simplicity.
var rangeToProtect = sourceSheet.getRange("C:C"); // Protect Column C
var protection = rangeToProtect.protect();
protection.setWarningOnly(false); // Prevent editing during script execution
Logger.log("Applied temporary protection to Column C.");
// --- End Optional Protection ---
try {
// Sort the source sheet by column B (2) then by column C (3)
Logger.log("Sorting source sheet range: " + sortRange.getA1Notation());
sortRange.sort([{ column: 2, ascending: true }, { column: 3, ascending: true }]);
SpreadsheetApp.flush(); // Ensure the sort is applied before proceeding
Logger.log("Source sheet sorted.");
// Get the newly sorted data from Columns A-D only
var sourceDataColsAD = sourceSheet.getRange(startRow, 1, sourceLastRow - startRow + 1, numColsToSync).getValues();
Logger.log("Fetched sorted data for columns A-D from source.");
// Apply the sorting effect (sync Columns A-D) to destination sheets
destSheetIds.forEach(function (destSheetId) {
try {
var destSpreadsheet = SpreadsheetApp.openById(destSheetId);
var destSheet = destSpreadsheet.getSheetByName(destSheetName);
if (destSheet) {
Logger.log("Syncing columns A-D to destination: " + destSheetId + " - " + destSheetName);
syncSpecificColumns(sourceDataColsAD, destSheet, startRow, numColsToSync);
} else {
Logger.log("Destination sheet '" + destSheetName + "' not found in spreadsheet ID: " + destSheetId);
}
} catch (error) {
Logger.log("Error accessing or syncing destination spreadsheet " + destSheetId + ": " + error.message);
}
});
SpreadsheetApp.getUi().alert("Sorting and syncing of columns A-D complete!");
} catch (error) {
Logger.log("Error during sorting or data retrieval: " + error.message);
SpreadsheetApp.getUi().alert("An error occurred during sorting: " + error.message);
} finally {
// --- Optional Protection Removal ---
// Ensure column C protection is removed even if errors occur
try {
protection.remove();
Logger.log("Removed temporary protection from Column C.");
} catch (unlockError) {
// Log error if protection was already removed or another issue happened
Logger.log("Info: Could not remove protection (may have already been removed or error occurred): " + unlockError.message);
}
// --- End Optional Protection Removal ---
}
} catch (error) {
Logger.log("Error opening source spreadsheet " + sourceSheetId + ": " + error.message);
SpreadsheetApp.getUi().alert("An error occurred accessing the source spreadsheet: " + error.message);
}
}
/**
* Clears and updates specific columns (A-D) in the destination sheet
* based on the provided sorted data, matching row for row.
*/
function syncSpecificColumns(sourceDataColsAD, destSheet, startRow, numColsToSync) {
var numRows = sourceDataColsAD.length;
var destLastRow = destSheet.getLastRow();
// Define the range in the destination sheet to update (Columns A-D)
var destRangeColsAD = destSheet.getRange(startRow, 1, numRows, numColsToSync);
// Clear existing content only in Columns A-D for the affected rows
Logger.log("Clearing destination range: " + destRangeColsAD.getA1Notation());
destRangeColsAD.clearContent(); // Use clearContent to preserve formatting
// Write the new sorted data (A-D) from the source to the destination
Logger.log("Setting values in destination range: " + destRangeColsAD.getA1Notation());
destRangeColsAD.setValues(sourceDataColsAD);
// Optional: Clear columns A-D in destination rows that *no longer exist* in the source
// This happens if rows were deleted from the source before sorting.
var sourceEndOfDataRow = startRow + numRows - 1;
if (destLastRow > sourceEndOfDataRow && destLastRow >= startRow) {
var clearRange = destSheet.getRange(sourceEndOfDataRow + 1, 1, destLastRow - sourceEndOfDataRow, numColsToSync);
Logger.log("Clearing orphaned rows A-D in destination: " + clearRange.getA1Notation());
clearRange.clearContent();
}
SpreadsheetApp.flush(); // Ensure changes are written to the destination sheet
}
// --- Helper function if needed for the case where source becomes empty ---
/*
function clearDestinationColumns(destSheetIds, destSheetName, startRow, numColsToSync) {
destSheetIds.forEach(function(destSheetId) {
try {
var destSpreadsheet = SpreadsheetApp.openById(destSheetId);
var destSheet = destSpreadsheet.getSheetByName(destSheetName);
if (destSheet) {
var destLastRow = destSheet.getLastRow();
if (destLastRow >= startRow) {
destSheet.getRange(startRow, 1, destLastRow - startRow + 1, numColsToSync).clearContent();
Logger.log(`Cleared columns A-D in destination ${destSheetId} - ${destSheetName} from row ${startRow}`);
}
}
} catch(e) {
Logger.log(`Error clearing columns A-D in destination ${destSheetId}: ${e}`);
}
});
}
*/
Explanation of Changes:
How to Use:
Regarding Automatic Trigger ("when new data added"):
This corrected script directly addresses the requirement to only sync columns A-D while maintaining the row order determined by the source sheet sort. Remember to replace the placeholder IDs!