This is my latest version, any room for efficiency?

/\*\*
 \* @OnlyCurrentDoc
 \*/

// Configuration function
function getConfig() {
 return {
 // Source sheet properties
 sourceSheetName: 'Sheet3',
 sourceRange: 'A2:E',
 rowsToCheck: 10,
 columnsToCompare: [1, 2, 3],

 // Target sheet properties
 targetSheetName: 'Sheet4',
 targetRangeStart: 'A2',
 };
}

// Main function to copy the range to another sheet
function copyRangeToAnotherSheet() {
 // Get the configuration object
 var config = getConfig();

 // Get the source sheet and target sheet using the configuration
 var sourceSheet = getSourceSheet(config);
 var targetSheet = getTargetSheet(config);

 // Get the source data from the source sheet using the defined range and number of rows to check
 var sourceData = getSourceData(sourceSheet, config);

 // Trim any whitespace from the source data
 sourceData = trimData(sourceData);

 // Get the target start column from the target range start in the configuration
 var targetStartCol = config.targetRangeStart.match(/[A-Z]+/)[0];

 // Process the rows in the source data by checking for duplicates and empty rows
 var results = processRows(config, sourceData, targetSheet, targetStartCol);

 // Generate an alert message based on the results and display it
 showAlert(results);
}

// Get source sheet
function getSourceSheet(config) {
 var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 return spreadsheet.getSheetByName(config.sourceSheetName);
}

// Get target sheet
function getTargetSheet(config) {
 var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 return spreadsheet.getSheetByName(config.targetSheetName);
}

// Get source data
function getSourceData(sourceSheet, config) {
 var sourceRange = sourceSheet.getRange(config.sourceRange + config.rowsToCheck);
 return sourceRange.getValues();
}

function letterToColumn(letter) {
 let column = 0;
 let length = letter.length;
 for (let i = 0; i < length; i++) {
 column += (letter.charCodeAt(i) - 64) \* Math.pow(26, length - i - 1);
 }
 return column;
}

function columnToLetter(column) {
 let temp;
 let letter = '';
 while (column > 0) {
 temp = (column - 1) % 26;
 letter = String.fromCharCode(temp + 65) + letter;
 column = (column - temp - 1) / 26;
 }
 return letter;
}

// Get target data
function getTargetData(targetSheet, config) {
 var lastRow = targetSheet.getLastRow();
 var targetStartRow = parseInt(config.targetRangeStart.match(/\d+/)[0]);
 var targetStartCol = columnToLetter(config.targetRangeStart.match(/[A-Z]+/)[0]);

 if (lastRow < targetStartRow) {
 return [];
 }

 var targetRange = targetSheet.getRange(targetStartCol + targetStartRow + ':' + targetStartCol + lastRow);
 return targetRange.getValues();
}

// Function to check if a row is empty in all specified columns
function isRowEmpty(row, columnsToCheck) {
 return columnsToCheck.every(function (column) {
 return row[column - 1] === '' || row[column - 1] === null;
 });
}

// Function to trim whitespace from the data
function trimData(data) {
 return data.map(function (row) {
 return row.map(function (cell) {
 return typeof cell === 'string' ? cell.trim() : cell;
 });
 });
}

// Check for duplicates and copy rows
function processRows(config, sourceData, targetSheet, targetStartCol) {
 // Retrieve the target sheet data once
 const targetData = getTargetData(targetSheet, config, targetStartCol);

 const targetStartRow = parseInt(config.targetRangeStart.match(/\d+/)[0]);

 // Process each source row and determine if it is a duplicate or empty
 const processedRows = sourceData.map((sourceRow, rowIndex) => {
 const isDuplicateOrEmpty = isRowEmpty(sourceRow, config.columnsToCompare) || isDuplicate(sourceRow, targetData, config.columnsToCompare, targetStartCol);
 return { sourceRow, rowIndex, isDuplicateOrEmpty };
 });

 // Filter out non-duplicate rows and extract the source row data
 const nonDuplicateRows = processedRows
 .filter(({ isDuplicateOrEmpty }) => !isDuplicateOrEmpty)
 .map(({ sourceRow }) => sourceRow);

 // Store the row indices of duplicate and pasted rows for the results
 const results = {
 duplicates: processedRows.filter(({ isDuplicateOrEmpty }) => isDuplicateOrEmpty).map(({ rowIndex }) => rowIndex + 1),
 pasted: processedRows.filter(({ isDuplicateOrEmpty }) => !isDuplicateOrEmpty).map(({ rowIndex }) => rowIndex + 1),
 };

 // If there are any non-duplicate rows, insert and copy them to the target sheet
 if (nonDuplicateRows.length > 0) {
 // Insert new rows at the targetStartRow in the target sheet
 targetSheet.insertRows(targetStartRow, nonDuplicateRows.length);

 // Get the target range starting at the targetStartRow and having the same dimensions as the nonDuplicateRows
 const targetRange = targetSheet.getRange(targetStartRow, letterToColumn(targetStartCol), nonDuplicateRows.length, nonDuplicateRows[0].length);

 // Copy the non-duplicate rows to the target range
 targetRange.setValues(nonDuplicateRows);
 }

 return results;
}

// Function to check if the source data is a duplicate in the target sheet based on the columns to compare
function isDuplicate(sourceRow, targetData, columnsToCompare, targetStartCol) {
 const targetStartColIndex = letterToColumn(targetStartCol) - 1;

 // Iterate through the targetData instead of retrieving it in every call
 for (const targetRow of targetData) {
 let isMatch = true;

 for (const colIndex of columnsToCompare) {
 if (sourceRow[colIndex - 1] !== targetRow[targetStartColIndex + colIndex - 1]) {
 isMatch = false;
 break;
 }
 }

 if (isMatch) {
 return true;
 }
 }

 return false;
}

// Show alert with the result
function showAlert(results) {
 // Declare the message variable
 let message;

 // Construct the alert message based on the results
 if (results.duplicates.length === 0 && results.pasted.length === 0) {
 message = 'Todos los valores están vacíos';
 } else if (results.duplicates.length === 0) {
 message = 'Todos los valores se han pegado';
 } else if (results.pasted.length === 0) {
 message = 'Todos los valores están DUPLICADOS';
 } else {
 message =
 'DUPLICADOS: Fila(s) ' +
 results.duplicates.join(', ') +
 '\n\nPEGADOS: Fila(s) ' +
 results.pasted.join(', ');
 }

 // Try to display the alert message using SpreadsheetApp.getUi().alert()
 try {
 SpreadsheetApp.getUi().alert(message);
 } catch (error) {
 // If there's an error while displaying the alert, log the error message using console.log()
 console.log('Error displaying alert:', error.message);
 }
}
이게 최신 버전인데 효율성이 떨어지나요?/\*\* \* @OnlyCurrentDoc \*/// 구성 함수함수 getConfig() { return { // 소스 시트 속성 sourceSheetName: 'Sheet3', sourceRange: 'A2:E', rowsToCheck: 10, columnsToCompare: [1, 2, 3], // 대상 시트 속성 targetSheetName: 'Sheet4', targetRangeStart: 'A2', };}// 범위를 다른 시트로 복사하는 메인 함수function copyRangeToAnotherSheet() { // 구성 객체 가져오기 var config = getConfig(); // 구성을 사용하여 소스 시트와 대상 시트를 가져옵니다. var sourceSheet = getSourceSheet(config); var targetSheet = getTargetSheet(config); // 정의된 범위와 확인할 행 수를 사용하여 소스 시트에서 소스 데이터를 가져옵니다. var sourceData = getSourceData(sourceSheet, config); // 소스 데이터에서 공백을 다듬습니다. sourceData = trimData(sourceData); // 구성의 대상 범위 시작에서 대상 시작 열을 가져옵니다. var targetStartCol = config.targetRangeStart.match(/[A-Z]+/)[0]; // 중복 및 빈 행을 확인하여 소스 데이터의 행을 처리합니다. var results = processRows(config, sourceData, targetSheet, targetStartCol); // 결과를 기반으로 경고 메시지를 생성하고 표시합니다. showAlert(results);}// 소스 시트 가져오기함수 getSourceSheet(config) { var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); return spreadsheet.getSheetByName(config.sourceSheetName);}// 대상 시트 가져오기함수 getTargetSheet(config) { var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); return spreadsheet.getSheetByName(config.targetSheetName);}// 소스 데이터 가져오기함수 getSourceData(sourceSheet, config) { var sourceRange = sourceSheet.getRange(config.sourceRange + config.rowsToCheck); return sourceRange.getValues();}함수 letterToColumn(letter) { let column = 0; let length = letter.length; for (let i = 0; i < length; i++) { column += (letter.charCodeAt(i) - 64) \* Math.pow(26, length - i - 1); } 반환 열;}function columnToLetter(column) { let temp; let letter = ''; while (column > 0) { temp = (column - 1) % 26; letter = String.fromCharCode(temp + 65) + letter; column = (column - temp - 1) / 26; } 반환 문자;}// 타겟 데이터 가져오기함수 getTargetData(targetSheet, config) { var lastRow = targetSheet.getLastRow(); var targetStartRow = parseInt(config.targetRangeStart.match(/\d+/)[0]); var targetStartCol = columnToLetter(config.targetRangeStart.match(/[A-Z]+/)[0]); if (lastRow < targetStartRow) { return []; } var targetRange = targetSheet.getRange(targetStartCol + targetStartRow + ':' + targetStartCol + lastRow); return targetRange.getValues();}// 지정된 모든 열에 행이 비어있는지 확인하는 함수function isRowEmpty(row, columnsToCheck) { return columnsToCheck.every(function (column) { return row[column - 1] === '' || row[column - 1] === null; });}// 데이터에서 공백을 잘라내는 함수function trimData(data) { return data.map(function (row) { return row.map(function (cell) { return typeof cell === 'string' ? cell.trim() : cell; }); });}// 중복 여부 확인 및 행 복사function processRows(config, sourceData, targetSheet, targetStartCol) { // 대상 시트 데이터를 한 번 검색 const targetData = getTargetData(targetSheet, config, targetStartCol); const targetStartRow = parseInt(config.targetRangeStart.match(/\d+/)[0]); // 각 소스 행을 처리하고 중복 또는 비어 있는지 확인합니다. const processedRows = sourceData.map((sourceRow, rowIndex) => {{ const isDuplicateOrEmpty = isRowEmpty(sourceRow, config.columnsToCompare) || isDuplicate(sourceRow, targetData, config.columnsToCompare, targetStartCol); 반환 { sourceRow, rowIndex, isDuplicateOrEmpty }; }); // 중복되지 않는 행을 필터링하고 소스 행 데이터를 추출합니다. const nonDuplicateRows = processedRows .filter(({ isDuplicateOrEmpty }) => !isDuplicateOrEmpty) .map(({ sourceRow }) => sourceRow); // 결과에 대해 중복 및 붙여넣기된 행의 행 인덱스를 저장합니다. const results = { duplicates: processedRows.filter(({ isDuplicateOrEmpty }) => isDuplicateOrEmpty).map(({ rowIndex }) => rowIndex + 1), 붙여넣기: processedRows.filter(({ isDuplicateOrEmpty }) => !isDuplicateOrEmpty).map(({ rowIndex }) => rowIndex + 1), }; // 중복되지 않는 행이 있으면 대상 시트에 삽입하여 복사합니다. if (nonDuplicateRows.length > 0) { // 대상 시트의 targetStartRow에 새 행을 삽입합니다. targetSheet.insertRows(targetStartRow, nonDuplicateRows.length); 대상 범위 가져오기 // 대상 범위는 targetStartRow에서 시작하고 비중복 행과 동일한 치수를 갖습니다. const targetRange = targetSheet.getRange(targetStartRow, letterToCol(targetStartCol), nonDuplicateRows.length, nonDuplicateRows[0].length); // 중복되지 않는 행을 목표 범위에 복사합니다. targetRange.setValues(nonDuplicateRows); } 결과를 반환합니다;}// 소스 데이터가 중복되는지 확인하는 함수